mirror of
https://github.com/array-in-a-matrix/brainwine.git
synced 2025-04-02 11:11:58 -04:00
Improved zone generator & resource file management
This commit is contained in:
parent
e9975a38c6
commit
993e22b15b
99 changed files with 2339 additions and 507 deletions
|
@ -13,7 +13,7 @@ import brainwine.gameserver.prefab.PrefabManager;
|
|||
import brainwine.gameserver.server.NetworkRegistry;
|
||||
import brainwine.gameserver.server.Server;
|
||||
import brainwine.gameserver.zone.ZoneManager;
|
||||
import brainwine.gameserver.zone.gen.StaticZoneGenerator;
|
||||
import brainwine.gameserver.zone.gen.ZoneGenerator;
|
||||
|
||||
public class GameServer {
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class GameServer {
|
|||
GameConfiguration.init();
|
||||
lootManager = new LootManager();
|
||||
prefabManager = new PrefabManager();
|
||||
StaticZoneGenerator.init();
|
||||
ZoneGenerator.init();
|
||||
zoneManager = new ZoneManager();
|
||||
playerManager = new PlayerManager();
|
||||
NetworkRegistry.init();
|
||||
|
|
|
@ -7,6 +7,7 @@ import brainwine.gameserver.command.Command;
|
|||
import brainwine.gameserver.command.CommandExecutor;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
import brainwine.gameserver.zone.gen.ZoneGenerator;
|
||||
|
||||
public class GenerateZoneCommand extends Command {
|
||||
|
||||
|
@ -49,19 +50,39 @@ public class GenerateZoneCommand extends Command {
|
|||
biome = Biome.fromName(args[2]);
|
||||
}
|
||||
|
||||
ZoneGenerator generator = null;
|
||||
|
||||
if(args.length >= 4) {
|
||||
String name = args[3];
|
||||
generator = ZoneGenerator.getZoneGenerator(name);
|
||||
|
||||
if(generator == null) {
|
||||
executor.notify(String.format("The zone generator '%s' does not exist.", name), ALERT);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
generator = ZoneGenerator.getZoneGenerator(biome);
|
||||
|
||||
// If no custom generator was specified, use the default one.
|
||||
if(generator == null){
|
||||
generator = ZoneGenerator.getDefaultZoneGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
if(args.length >= 5) {
|
||||
try {
|
||||
seed = Integer.parseInt(args[3]);
|
||||
seed = Integer.parseInt(args[4]);
|
||||
} catch(NumberFormatException e) {
|
||||
seed = args[3].hashCode();
|
||||
seed = args[4].hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
executor.notify("Your zone is being generated. It should be ready soon!", ALERT);
|
||||
GameServer.getInstance().getZoneManager().generateZoneAsync(biome, width, height, seed, zone -> {
|
||||
generator.generateZoneAsync(biome, width, height, seed, zone -> {
|
||||
if(zone == null) {
|
||||
executor.notify("An unexpected error occured while generating your zone.", ALERT);
|
||||
} else {
|
||||
GameServer.getInstance().getZoneManager().addZone(zone);
|
||||
executor.notify(String.format("Your zone '%s' is ready for exploration!", zone.getName()), ALERT);
|
||||
}
|
||||
});
|
||||
|
@ -84,7 +105,7 @@ public class GenerateZoneCommand extends Command {
|
|||
|
||||
@Override
|
||||
public String getUsage(CommandExecutor executor) {
|
||||
return "/genzone [<width> <height>] [biome] [seed]";
|
||||
return "/genzone [<width> <height>] [biome] [generator] [seed]";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,7 +2,6 @@ package brainwine.gameserver.loot;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -14,6 +13,7 @@ import org.apache.logging.log4j.Logger;
|
|||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import brainwine.gameserver.util.ResourceUtils;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
import brainwine.shared.JsonHelper;
|
||||
|
@ -30,18 +30,17 @@ public class LootManager {
|
|||
private void loadLootTables() {
|
||||
logger.info("Loading loot tables ...");
|
||||
File file = new File("loottables.json");
|
||||
ResourceUtils.copyDefaults("loottables.json");
|
||||
|
||||
if(file.isFile()) {
|
||||
try {
|
||||
if(!file.exists()) {
|
||||
Files.copy(LootManager.class.getResourceAsStream("/loottables.json"), file.toPath());
|
||||
}
|
||||
|
||||
Map<String, List<Loot>> loot = JsonHelper.readValue(file, new TypeReference<Map<String, List<Loot>>>(){});
|
||||
lootTables.putAll(loot);
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load loot tables", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Loot> getLootTable(String category) {
|
||||
return lootTables.getOrDefault(category, Collections.emptyList());
|
||||
|
|
|
@ -1,25 +1,22 @@
|
|||
package brainwine.gameserver.prefab;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.msgpack.core.MessagePack;
|
||||
import org.msgpack.core.MessageUnpacker;
|
||||
import org.msgpack.jackson.dataformat.MessagePackFactory;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.ResourcesScanner;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
|
||||
import brainwine.gameserver.serialization.BlockDeserializer;
|
||||
import brainwine.gameserver.serialization.BlockSerializer;
|
||||
import brainwine.gameserver.util.ResourceUtils;
|
||||
import brainwine.gameserver.util.ZipUtils;
|
||||
import brainwine.gameserver.zone.Block;
|
||||
import brainwine.shared.JsonHelper;
|
||||
|
@ -36,32 +33,15 @@ public class PrefabManager {
|
|||
|
||||
public PrefabManager() {
|
||||
logger.info("Loading prefabs ...");
|
||||
ResourceUtils.copyDefaults("prefabs");
|
||||
|
||||
if(!dataDir.exists()) {
|
||||
logger.info("Copying default prefabs ...");
|
||||
dataDir.mkdirs();
|
||||
Reflections reflections = new Reflections("prefabs", new ResourcesScanner());
|
||||
Set<String> fileNames = reflections.getResources(x -> true);
|
||||
|
||||
for(String fileName : fileNames) {
|
||||
File outputFile = new File(fileName);
|
||||
outputFile.getParentFile().mkdirs();
|
||||
|
||||
try {
|
||||
Files.copy(PrefabManager.class.getResourceAsStream(String.format("/%s", fileName)), outputFile.toPath());
|
||||
} catch (IOException e) {
|
||||
logger.error("Could not copy default prefabs", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File[] files = dataDir.listFiles();
|
||||
|
||||
for(File file : files) {
|
||||
if(dataDir.isDirectory()) {
|
||||
for(File file : dataDir.listFiles()) {
|
||||
if(file.isDirectory()) {
|
||||
loadPrefab(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Successfully loaded {} prefab(s)", prefabs.size());
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package brainwine.gameserver.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Set;
|
||||
|
||||
import org.reflections.Reflections;
|
||||
|
||||
/**
|
||||
* Simple helper class for the Reflections library.
|
||||
*/
|
||||
public class ReflectionsHelper {
|
||||
|
||||
private static final Reflections reflections = new Reflections("brainwine.gameserver");
|
||||
|
||||
public static Set<Class<?>> getTypesAnnotatedWith(Class<? extends Annotation> annotation) {
|
||||
return reflections.getTypesAnnotatedWith(annotation);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package brainwine.gameserver.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.ResourcesScanner;
|
||||
|
||||
public class ResourceUtils {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
|
||||
public static void copyDefaults(String path) {
|
||||
copyDefaults(path, false);
|
||||
}
|
||||
|
||||
public static void copyDefaults(String path, boolean force) {
|
||||
try {
|
||||
File file = new File(path);
|
||||
|
||||
if(!file.exists() || force) {
|
||||
Reflections reflections = new Reflections(String.format("defaults/%s", path), new ResourcesScanner());
|
||||
Set<String> fileNames = reflections.getResources(x -> true);
|
||||
|
||||
for(String fileName : fileNames) {
|
||||
File output = new File(fileName.substring(9));
|
||||
File parent = output.getAbsoluteFile().getParentFile();
|
||||
|
||||
if(parent != null) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
|
||||
try {
|
||||
Files.copy(ResourceUtils.class.getResourceAsStream(String.format("/%s", fileName)), output.toPath());
|
||||
} catch (Exception e) {
|
||||
logger.error("Couldn't copy resource '{}'", fileName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.error("Couldn't copy defaults '{}'", path, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String removeFileSuffix(String string) {
|
||||
if(!string.contains(".")) {
|
||||
return string;
|
||||
}
|
||||
|
||||
return string.substring(0, string.lastIndexOf('.'));
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
@ -21,14 +20,12 @@ import org.msgpack.jackson.dataformat.MessagePackFactory;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import brainwine.gameserver.util.ZipUtils;
|
||||
import brainwine.gameserver.zone.gen.AsyncZoneGenerator;
|
||||
import brainwine.gameserver.zone.gen.StaticZoneGenerator;
|
||||
import brainwine.gameserver.zone.gen.ZoneGenerator;
|
||||
import brainwine.shared.JsonHelper;
|
||||
|
||||
public class ZoneManager {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private final AsyncZoneGenerator asyncGenerator = new AsyncZoneGenerator(this);
|
||||
private final ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
|
||||
private final File dataDir = new File("zones");
|
||||
private Map<String, Zone> zones = new HashMap<>();
|
||||
|
@ -46,16 +43,18 @@ public class ZoneManager {
|
|||
|
||||
if(zones.isEmpty()) {
|
||||
logger.info("No zones were loaded. Generating default zone ...");
|
||||
Zone zone = StaticZoneGenerator.generateZone(Biome.PLAIN, 2000, 600);
|
||||
saveZone(zone);
|
||||
putZone(zone);
|
||||
ZoneGenerator generator = ZoneGenerator.getZoneGenerator(Biome.PLAIN);
|
||||
|
||||
if(generator == null) {
|
||||
logger.warn("No generator for plain biomes was found! The default generator will be used.");
|
||||
generator = ZoneGenerator.getDefaultZoneGenerator();
|
||||
}
|
||||
|
||||
Zone zone = generator.generateZone(Biome.PLAIN, 2000, 600);
|
||||
addZone(zone);
|
||||
} else {
|
||||
logger.info("Successfully loaded {} zone(s)", zonesByName.size());
|
||||
}
|
||||
|
||||
logger.info("Starting zone generator thread ...");
|
||||
asyncGenerator.setDaemon(true);
|
||||
asyncGenerator.start();
|
||||
}
|
||||
|
||||
public void tick(float deltaTime) {
|
||||
|
@ -108,7 +107,7 @@ public class ZoneManager {
|
|||
ZoneConfig config = JsonHelper.readValue(new File(file, "config.json"), ZoneConfig.class);
|
||||
Zone zone = new Zone(id, config, data);
|
||||
zone.setMetaBlocks(JsonHelper.readList(new File(file, "metablocks.json"), MetaBlock.class));
|
||||
putZone(zone);
|
||||
addZone(zone);
|
||||
} catch (Exception e) {
|
||||
logger.error("Zone load failure. id: {}", id, e);
|
||||
}
|
||||
|
@ -136,7 +135,7 @@ public class ZoneManager {
|
|||
}
|
||||
}
|
||||
|
||||
private void putZone(Zone zone) {
|
||||
public void addZone(Zone zone) {
|
||||
String id = zone.getDocumentId();
|
||||
String name = zone.getName();
|
||||
|
||||
|
@ -149,16 +148,6 @@ public class ZoneManager {
|
|||
zonesByName.put(name.toLowerCase(), zone);
|
||||
}
|
||||
|
||||
public void generateZoneAsync(Biome biome, int width, int height, int seed, Consumer<Zone> callback) {
|
||||
asyncGenerator.generateZone(biome, width, height, seed, zone -> {
|
||||
if(zone != null) {
|
||||
putZone(zone);
|
||||
}
|
||||
|
||||
callback.accept(zone);
|
||||
});
|
||||
}
|
||||
|
||||
public Zone getZone(String id) {
|
||||
return zones.get(id);
|
||||
}
|
||||
|
|
|
@ -11,18 +11,15 @@ import brainwine.gameserver.GameServer;
|
|||
import brainwine.gameserver.TickLoop;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
import brainwine.gameserver.zone.ZoneManager;
|
||||
|
||||
public class AsyncZoneGenerator extends Thread {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private final Queue<AsyncZoneGeneratorTask> tasks = new ConcurrentLinkedQueue<>();
|
||||
private final ZoneManager zoneManager;
|
||||
private boolean running;
|
||||
|
||||
public AsyncZoneGenerator(ZoneManager zoneManager) {
|
||||
super("zone-generator");
|
||||
this.zoneManager = zoneManager;
|
||||
public AsyncZoneGenerator() {
|
||||
super("zonegen");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,6 +27,7 @@ public class AsyncZoneGenerator extends Thread {
|
|||
TickLoop loop = new TickLoop(1, () -> {
|
||||
while(!tasks.isEmpty()) {
|
||||
AsyncZoneGeneratorTask task = tasks.poll();
|
||||
ZoneGenerator generator = task.getGenerator();
|
||||
Biome biome = task.getBiome();
|
||||
int width = task.getWidth();
|
||||
int height = task.getHeight();
|
||||
|
@ -37,10 +35,9 @@ public class AsyncZoneGenerator extends Thread {
|
|||
Zone zone = null;
|
||||
|
||||
try {
|
||||
zone = StaticZoneGenerator.generateZone(biome, width, height, seed);
|
||||
zoneManager.saveZone(zone);
|
||||
zone = generator.generateZone(biome, width, height, seed);
|
||||
} catch(Exception e) {
|
||||
logger.error("An unexpected error occured while generating zone [biome:{}, width:{}, height:{}, seed:{}]", biome, width, height, seed, e);
|
||||
logger.error("An unexpected error occured while generating zone [biome:{}, width:{}, height:{}, seed:{}]", biome, width, height, generator, seed, e);
|
||||
}
|
||||
|
||||
Zone generated = zone;
|
||||
|
@ -59,7 +56,11 @@ public class AsyncZoneGenerator extends Thread {
|
|||
}
|
||||
}
|
||||
|
||||
public void generateZone(Biome biome, int width, int height, int seed, Consumer<Zone> callback) {
|
||||
tasks.add(new AsyncZoneGeneratorTask(biome, width, height, seed, callback));
|
||||
public void addTask(AsyncZoneGeneratorTask task) {
|
||||
tasks.add(task);
|
||||
}
|
||||
|
||||
public void addTask(ZoneGenerator generator, Biome biome, int width, int height, int seed, Consumer<Zone> callback) {
|
||||
addTask(new AsyncZoneGeneratorTask(generator, biome, width, height, seed, callback));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,15 @@ import brainwine.gameserver.zone.Zone;
|
|||
|
||||
public class AsyncZoneGeneratorTask {
|
||||
|
||||
private final ZoneGenerator generator;
|
||||
private final Biome biome;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int seed;
|
||||
private final Consumer<Zone> callback;
|
||||
|
||||
public AsyncZoneGeneratorTask(Biome biome, int width, int height, int seed, Consumer<Zone> callback) {
|
||||
public AsyncZoneGeneratorTask(ZoneGenerator generator, Biome biome, int width, int height, int seed, Consumer<Zone> callback) {
|
||||
this.generator = generator;
|
||||
this.biome = biome;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
@ -21,6 +23,10 @@ public class AsyncZoneGeneratorTask {
|
|||
this.callback = callback;
|
||||
}
|
||||
|
||||
public ZoneGenerator getGenerator() {
|
||||
return generator;
|
||||
}
|
||||
|
||||
public Biome getBiome() {
|
||||
return biome;
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import brainwine.gameserver.zone.gen.models.CaveType;
|
||||
import brainwine.shared.JsonHelper;
|
||||
|
||||
/**
|
||||
* It's a bit hack-ish, but it works.
|
||||
*/
|
||||
public class CaveDecoratorListDeserializer extends JsonDeserializer<List<CaveDecorator>> {
|
||||
|
||||
@Override
|
||||
public List<CaveDecorator> deserialize(JsonParser parser, DeserializationContext ctx) throws IOException, JsonProcessingException {
|
||||
List<CaveDecorator> list = new ArrayList<>();
|
||||
JsonNode node = parser.readValueAsTree();
|
||||
Iterator<Entry<String, JsonNode>> it = node.fields();
|
||||
|
||||
while(it.hasNext()) {
|
||||
Entry<String, JsonNode> entry = it.next();
|
||||
CaveType type = JsonHelper.readValue(String.format("\"%s\"", entry.getKey()), CaveType.class);
|
||||
CaveDecorator decorator = JsonHelper.readValue(entry.getValue().toString(), type.getDecoratorType());
|
||||
list.add(decorator);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,30 +2,73 @@ package brainwine.gameserver.zone.gen;
|
|||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.util.MathUtils;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.caves.Cave;
|
||||
import brainwine.gameserver.zone.gen.caves.CaveType;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
import brainwine.gameserver.zone.gen.models.StoneVariant;
|
||||
|
||||
public class CaveGenerator implements GeneratorTask {
|
||||
|
||||
private final WeightedMap<StoneVariant> stoneVariants;
|
||||
private final List<CaveDecorator> decorators;
|
||||
private final Collection<CaveType> caveTypes;
|
||||
|
||||
public CaveGenerator(GeneratorConfig config) {
|
||||
stoneVariants = config.getStoneVariants();
|
||||
decorators = config.getCaveDecorators();
|
||||
caveTypes = config.getCaveTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext ctx) {
|
||||
boolean[][] cells = generateCells(ctx, 0.4625, 9);
|
||||
List<Cave> caves = indexCaves(ctx, cells);
|
||||
int width = ctx.getWidth();
|
||||
int height = ctx.getHeight();
|
||||
boolean[][] cells = new boolean[width][height];
|
||||
List<Cave> caves = new ArrayList<>();
|
||||
|
||||
// Multiple layers to increase cave density.
|
||||
// I'm not sure if there are better ways to do this, but eh whatever.
|
||||
for(int i = 0; i < 10; i++) {
|
||||
boolean[][] currentCells = generateCells(ctx, 0.4625, 5);
|
||||
List<Cave> currentCaves = indexCaves(ctx, currentCells);
|
||||
|
||||
// Remove caves that overlap with existing ones
|
||||
for(Cave cave : currentCaves) {
|
||||
boolean overlaps = false;
|
||||
|
||||
if(!caves.isEmpty()) {
|
||||
for(BlockPosition block : cave.getBlocks()) {
|
||||
int x = block.getX();
|
||||
int y = block.getY();
|
||||
|
||||
for(int j = x - 3; j < x + 3; j++) {
|
||||
for(int k = y - 3; k < y + 3; k++) {
|
||||
if(ctx.inBounds(j, k) && cells[j][k]) {
|
||||
overlaps = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(overlaps) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!overlaps) {
|
||||
caves.add(cave);
|
||||
|
||||
for(BlockPosition block : cave.getBlocks()) {
|
||||
cells[block.getX()][block.getY()] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(Cave cave : caves) {
|
||||
ctx.addCave(cave);
|
||||
|
@ -63,14 +106,15 @@ public class CaveGenerator implements GeneratorTask {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean[][] generateCells(GeneratorContext ctx, double cellRate, int smoothCount) {
|
||||
public boolean[][] generateCells(GeneratorContext ctx, double cellRate, int smoothCount) {
|
||||
int width = ctx.getWidth();
|
||||
int height = ctx.getHeight();
|
||||
boolean[][] cells = new boolean[width][height];
|
||||
boolean[][] result = new boolean[width][height];
|
||||
|
||||
for(int x = 0; x < width; x++) {
|
||||
for(int y = 0; y < height; y++) {
|
||||
if(ctx.isUnderground(x, y) && ctx.nextDouble() <= cellRate) {
|
||||
if((y >= ctx.getZone().getSurface()[x] + ctx.nextInt(3)) && ctx.nextDouble() <= cellRate) {
|
||||
cells[x][y] = true;
|
||||
}
|
||||
}
|
||||
|
@ -79,12 +123,19 @@ public class CaveGenerator implements GeneratorTask {
|
|||
for(int i = 0; i < smoothCount; i++) {
|
||||
for(int x = 0; x < width; x++) {
|
||||
for(int y = 0; y < height; y++) {
|
||||
int count = getAdjacentCells(ctx, cells, x, y);
|
||||
cells[x][y] = count > 4 ? true : count < 4 ? false : cells[x][y];
|
||||
int neighbours = getAdjacentCells(ctx, cells, x, y);
|
||||
|
||||
if(neighbours > 4) {
|
||||
result[x][y] = true;
|
||||
} else if(neighbours < 4) {
|
||||
result[x][y] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cells = result;
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
|
@ -137,23 +188,30 @@ public class CaveGenerator implements GeneratorTask {
|
|||
int bY = caveBlock.getY();
|
||||
|
||||
for(int i = bX - 1; i <= bX + 1; i++) {
|
||||
for(int j = bY - 1; j <= bY + 1; j++) {
|
||||
if(ctx.inBounds(i, j) && !indexed[i][j] && cells[i][j]) {
|
||||
BlockPosition newBlock = new BlockPosition(i, j);
|
||||
if(ctx.inBounds(i, bY) && !indexed[i][bY] && cells[i][bY]) {
|
||||
BlockPosition newBlock = new BlockPosition(i, bY);
|
||||
blocks.add(newBlock);
|
||||
queue.add(newBlock);
|
||||
indexed[i][j] = true;
|
||||
indexed[i][bY] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int j = bY - 1; j <= bY + 1; j++) {
|
||||
if(ctx.inBounds(bX, j) && !indexed[bX][j] && cells[bX][j]) {
|
||||
BlockPosition newBlock = new BlockPosition(bX, j);
|
||||
blocks.add(newBlock);
|
||||
queue.add(newBlock);
|
||||
indexed[bX][j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size = blocks.size();
|
||||
|
||||
if(size >= 20) {
|
||||
if(size > 20 && size < 800) {
|
||||
int surface = ctx.getZone().getSurface()[x];
|
||||
double depth = (double)(y - surface) / (ctx.getHeight() - surface);
|
||||
Cave cave = new Cave(getRandomEligibleDecorator(ctx, size, depth), stoneVariants.next(ctx.getRandom(), StoneVariant.DEFAULT));
|
||||
Cave cave = new Cave(getRandomEligibleType(ctx, size, depth), stoneVariants.next(ctx.getRandom(), StoneVariant.DEFAULT));
|
||||
cave.addBlock(first);
|
||||
|
||||
for(BlockPosition block : blocks) {
|
||||
|
@ -181,12 +239,12 @@ public class CaveGenerator implements GeneratorTask {
|
|||
return null;
|
||||
}
|
||||
|
||||
private CaveDecorator getRandomEligibleDecorator(GeneratorContext ctx, int size, double depth) {
|
||||
WeightedMap<CaveDecorator> list = new WeightedMap<>();
|
||||
private CaveType getRandomEligibleType(GeneratorContext ctx, int size, double depth) {
|
||||
WeightedMap<CaveType> list = new WeightedMap<>();
|
||||
|
||||
for(CaveDecorator decorator : decorators) {
|
||||
if(size >= decorator.getMinSize() && size <= decorator.getMaxSize() && depth >= decorator.getMinDepth() && depth <= decorator.getMaxDepth()) {
|
||||
list.addEntry(decorator, decorator.getFrequency());
|
||||
for(CaveType type : caveTypes) {
|
||||
if(size >= type.getMinSize() && size <= type.getMaxSize() && depth >= type.getMinDepth() && depth <= type.getMaxDepth()) {
|
||||
list.addEntry(type, type.getFrequency());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,11 @@ import java.util.Map;
|
|||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.zone.gen.caves.Cave;
|
||||
import brainwine.gameserver.zone.gen.caves.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.CaveType;
|
||||
import brainwine.gameserver.zone.gen.models.BaseResourceType;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
import brainwine.gameserver.zone.gen.models.Deposit;
|
||||
import brainwine.gameserver.zone.gen.models.ModTileBlock;
|
||||
import brainwine.gameserver.zone.gen.models.OreDeposit;
|
||||
|
@ -57,12 +59,18 @@ public class DecorGenerator implements GeneratorTask {
|
|||
}
|
||||
}
|
||||
|
||||
CaveDecorator decorator = cave.getDecorator();
|
||||
CaveType type = cave.getType();
|
||||
|
||||
if(decorator != null) {
|
||||
if(type != null) {
|
||||
// TODO structure caves should probably be moved to StructureGenerators, or they
|
||||
// will take up dungeon space.
|
||||
for(CaveDecorator decorator : type.getDecorators()) {
|
||||
if(ctx.nextDouble() <= decorator.getChance()) {
|
||||
decorator.decorate(ctx, cave);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baseResources.forEach((k, v) -> {
|
||||
generateBaseResources(ctx, k, v);
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
package brainwine.gameserver.zone.gen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.prefab.Prefab;
|
||||
import brainwine.gameserver.util.Vector2i;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.caves.CaveType;
|
||||
import brainwine.gameserver.zone.gen.models.BaseResourceType;
|
||||
import brainwine.gameserver.zone.gen.models.Deposit;
|
||||
import brainwine.gameserver.zone.gen.models.OreDeposit;
|
||||
|
@ -49,8 +48,7 @@ public class GeneratorConfig {
|
|||
private WeightedMap<StoneVariant> stoneVariants = new WeightedMap<>();
|
||||
|
||||
@JsonProperty("cave_types")
|
||||
@JsonDeserialize(using = CaveDecoratorListDeserializer.class)
|
||||
private List<CaveDecorator> decorators = new ArrayList<>();
|
||||
private Map<String, CaveType> caveTypes = new HashMap<>();
|
||||
|
||||
@JsonProperty("base_resources")
|
||||
private Map<BaseResourceType, Deposit> baseResources = new HashMap<>();
|
||||
|
@ -94,8 +92,8 @@ public class GeneratorConfig {
|
|||
return stoneVariants;
|
||||
}
|
||||
|
||||
public List<CaveDecorator> getCaveDecorators() {
|
||||
return decorators;
|
||||
public Collection<CaveType> getCaveTypes() {
|
||||
return caveTypes.values();
|
||||
}
|
||||
|
||||
public Map<BaseResourceType, Deposit> getBaseResources() {
|
||||
|
|
|
@ -12,8 +12,8 @@ import brainwine.gameserver.item.Layer;
|
|||
import brainwine.gameserver.prefab.Prefab;
|
||||
import brainwine.gameserver.zone.Chunk;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
import brainwine.gameserver.zone.gen.caves.Cave;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
public class GeneratorContext {
|
||||
|
||||
|
@ -27,9 +27,7 @@ public class GeneratorContext {
|
|||
this.zone = zone;
|
||||
this.seed = seed;
|
||||
random = new Random(seed);
|
||||
}
|
||||
|
||||
public void createChunks() {
|
||||
for(int i = 0; i < zone.getChunkCount(); i++) {
|
||||
int x = i % zone.getNumChunksWidth() * zone.getChunkWidth();
|
||||
int y = i / zone.getNumChunksWidth() * zone.getChunkHeight();
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
import brainwine.shared.JsonHelper;
|
||||
|
||||
public class StaticZoneGenerator {
|
||||
|
||||
// TODO Collect more names and create a name generator that's actually proper lmao
|
||||
private static final String[] FIRST_NAMES = {
|
||||
"Malvern", "Tralee", "Horncastle", "Old", "Westwood",
|
||||
"Citta", "Tadley", "Mossley", "West", "East",
|
||||
"North", "South", "Wadpen", "Githam", "Soatnust",
|
||||
"Highworth", "Creakynip", "Upper", "Lower", "Cannock",
|
||||
"Dovercourt", "Limerick", "Pickering", "Glumshed", "Crusthack",
|
||||
"Osyltyr", "Aberstaple", "New", "Stroud", "Crumclum",
|
||||
"Crumsidle", "Bankswund", "Fiddletrast", "Bournpan", "St.",
|
||||
"Funderbost", "Bexwoddly", "Pilkingheld", "Wittlepen", "Rabbitbleaker",
|
||||
"Griffingumby", "Guilthead", "Bigglelund", "Bunnymold", "Rosesidle",
|
||||
"Crushthorn", "Tanlyward", "Ahncrace", "Pilkingking", "Dingstrath",
|
||||
"Axebury", "Ginglingtap", "Ballybibby", "Shadehoven"
|
||||
};
|
||||
|
||||
private static final String[] LAST_NAMES = {
|
||||
"Falls", "Alloa", "Glen", "Way", "Dolente",
|
||||
"Peak", "Heights", "Creek", "Banffshire", "Chagford",
|
||||
"Gorge", "Valley", "Catacombs", "Depths", "Mines",
|
||||
"Crickbridge", "Guildbost", "Pits", "Vaults", "Ruins",
|
||||
"Dell", "Keep", "Chatterdin", "Scrimmance", "Gitwick",
|
||||
"Ridge", "Alresford", "Place", "Bridge", "Glade",
|
||||
"Mill", "Court", "Dooftory", "Hills", "Specklewint",
|
||||
"Grove", "Aylesbury", "Wagwouth", "Russetcumby", "Point",
|
||||
"Canyon", "Cranwarry", "Bluff", "Passage", "Crantippy",
|
||||
"Kerbodome", "Dale", "Cemetery"
|
||||
};
|
||||
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private static final ZoneGenerator fallback = new ZoneGenerator();
|
||||
private static final Map<Biome, ZoneGenerator> generators = new HashMap<>();
|
||||
|
||||
public static void init() {
|
||||
logger.info("Loading zone generator configurations ...");
|
||||
File file = new File("generators.json");
|
||||
|
||||
try {
|
||||
if(!file.exists()) {
|
||||
Files.copy(StaticZoneGenerator.class.getResourceAsStream("/generators.json"), file.toPath());
|
||||
}
|
||||
|
||||
Map<Biome, GeneratorConfig> configs = JsonHelper.readValue(new File("generators.json"), new TypeReference<Map<Biome, GeneratorConfig>>(){});
|
||||
|
||||
for(Entry<Biome, GeneratorConfig> entry : configs.entrySet()) {
|
||||
generators.put(entry.getKey(), new ZoneGenerator(entry.getValue()));
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.error("Could not load generator configurations", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Zone generateZone(Biome biome, int width, int height) {
|
||||
return generateZone(biome, width, height, (int)(Math.random() * Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
public static Zone generateZone(Biome biome, int width, int height, int seed) {
|
||||
String firstName = FIRST_NAMES[(int)(Math.random() * FIRST_NAMES.length)];
|
||||
String lastName = LAST_NAMES[(int)(Math.random() * LAST_NAMES.length)];
|
||||
String name = firstName + " " + lastName;
|
||||
Zone zone = new Zone(generateDocumentId(seed), name, biome, width, height);
|
||||
GeneratorContext ctx = new GeneratorContext(zone, seed);
|
||||
ZoneGenerator generator = generators.getOrDefault(biome, fallback);
|
||||
generator.generate(ctx);
|
||||
return zone;
|
||||
}
|
||||
|
||||
private static String generateDocumentId(int seed) {
|
||||
Random random = new Random();
|
||||
long mostSigBits = (((long)seed) << 32) | (random.nextInt() & 0xFFFFFFFFL);
|
||||
long leastSigBits = random.nextLong();
|
||||
return new UUID(mostSigBits, leastSigBits).toString();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,56 @@
|
|||
package brainwine.gameserver.zone.gen;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.util.ResourceUtils;
|
||||
import brainwine.gameserver.zone.Biome;
|
||||
import brainwine.gameserver.zone.Zone;
|
||||
import brainwine.shared.JsonHelper;
|
||||
|
||||
public class ZoneGenerator {
|
||||
|
||||
// TODO Collect more names and create a name generator that's actually proper lmao
|
||||
private static final String[] FIRST_NAMES = {
|
||||
"Malvern", "Tralee", "Horncastle", "Old", "Westwood",
|
||||
"Citta", "Tadley", "Mossley", "West", "East",
|
||||
"North", "South", "Wadpen", "Githam", "Soatnust",
|
||||
"Highworth", "Creakynip", "Upper", "Lower", "Cannock",
|
||||
"Dovercourt", "Limerick", "Pickering", "Glumshed", "Crusthack",
|
||||
"Osyltyr", "Aberstaple", "New", "Stroud", "Crumclum",
|
||||
"Crumsidle", "Bankswund", "Fiddletrast", "Bournpan", "St.",
|
||||
"Funderbost", "Bexwoddly", "Pilkingheld", "Wittlepen", "Rabbitbleaker",
|
||||
"Griffingumby", "Guilthead", "Bigglelund", "Bunnymold", "Rosesidle",
|
||||
"Crushthorn", "Tanlyward", "Ahncrace", "Pilkingking", "Dingstrath",
|
||||
"Axebury", "Ginglingtap", "Ballybibby", "Shadehoven"
|
||||
};
|
||||
|
||||
private static final String[] LAST_NAMES = {
|
||||
"Falls", "Alloa", "Glen", "Way", "Dolente",
|
||||
"Peak", "Heights", "Creek", "Banffshire", "Chagford",
|
||||
"Gorge", "Valley", "Catacombs", "Depths", "Mines",
|
||||
"Crickbridge", "Guildbost", "Pits", "Vaults", "Ruins",
|
||||
"Dell", "Keep", "Chatterdin", "Scrimmance", "Gitwick",
|
||||
"Ridge", "Alresford", "Place", "Bridge", "Glade",
|
||||
"Mill", "Court", "Dooftory", "Hills", "Specklewint",
|
||||
"Grove", "Aylesbury", "Wagwouth", "Russetcumby", "Point",
|
||||
"Canyon", "Cranwarry", "Bluff", "Passage", "Crantippy",
|
||||
"Kerbodome", "Dale", "Cemetery"
|
||||
};
|
||||
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private static final Map<String, ZoneGenerator> generators = new HashMap<>();
|
||||
private static final ZoneGenerator defaultGenerator = new ZoneGenerator();
|
||||
private static final AsyncZoneGenerator asyncGenerator = new AsyncZoneGenerator();
|
||||
private static boolean initialized;
|
||||
private final GeneratorTask terrainGenerator;
|
||||
private final GeneratorTask caveGenerator;
|
||||
private final GeneratorTask decorGenerator;
|
||||
|
@ -20,17 +67,107 @@ public class ZoneGenerator {
|
|||
structureGenerator = new StructureGenerator(config);
|
||||
}
|
||||
|
||||
public void generate(GeneratorContext ctx) {
|
||||
int width = ctx.getWidth();
|
||||
int height = ctx.getHeight();
|
||||
ctx.createChunks();
|
||||
public static void init() {
|
||||
if(initialized) {
|
||||
logger.warn("ZoneGenerator is already initialized!");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Loading zone generator configurations ...");
|
||||
ResourceUtils.copyDefaults("generators");
|
||||
File dataDir = new File("generators");
|
||||
|
||||
if(dataDir.isDirectory()) {
|
||||
for(File file : dataDir.listFiles()) {
|
||||
try {
|
||||
String name = ResourceUtils.removeFileSuffix(file.getName()).toLowerCase();
|
||||
|
||||
if(generators.containsKey(name)) {
|
||||
logger.warn("Duplicate generator config name '{}'", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
GeneratorConfig config = JsonHelper.readValue(file, GeneratorConfig.class);
|
||||
generators.put(name, new ZoneGenerator(config));
|
||||
} catch(Exception e) {
|
||||
logger.error("Failed to load generator config '{}'", file.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Starting async zone generator thread ...");
|
||||
asyncGenerator.setDaemon(true);
|
||||
asyncGenerator.start();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public static ZoneGenerator getZoneGenerator(String name) {
|
||||
return generators.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
public static ZoneGenerator getZoneGenerator(Biome biome) {
|
||||
return getZoneGenerator(biome.toString());
|
||||
}
|
||||
|
||||
public static ZoneGenerator getDefaultZoneGenerator() {
|
||||
return defaultGenerator;
|
||||
}
|
||||
|
||||
public Zone generateZone() {
|
||||
return generateZone(Biome.getRandomBiome());
|
||||
}
|
||||
|
||||
public Zone generateZone(Biome biome) {
|
||||
return generateZone(biome, 2000, 600);
|
||||
}
|
||||
|
||||
public Zone generateZone(Biome biome, int width, int height) {
|
||||
return generateZone(biome, width, height, getRandomSeed());
|
||||
}
|
||||
|
||||
public Zone generateZone(Biome biome, int width, int height, int seed) {
|
||||
String firstName = FIRST_NAMES[(int)(Math.random() * FIRST_NAMES.length)];
|
||||
String lastName = LAST_NAMES[(int)(Math.random() * LAST_NAMES.length)];
|
||||
String name = firstName + " " + lastName;
|
||||
Zone zone = new Zone(generateDocumentId(seed), name, biome, width, height);
|
||||
GeneratorContext ctx = new GeneratorContext(zone, seed);
|
||||
terrainGenerator.generate(ctx);
|
||||
caveGenerator.generate(ctx);
|
||||
decorGenerator.generate(ctx);
|
||||
structureGenerator.generate(ctx);
|
||||
|
||||
// Bedrock
|
||||
for(int x = 0; x < width; x++) {
|
||||
ctx.updateBlock(x, height - 1, Layer.FRONT, 666, 0);
|
||||
}
|
||||
|
||||
return zone;
|
||||
}
|
||||
|
||||
public void generateZoneAsync(Consumer<Zone> callback) {
|
||||
generateZoneAsync(Biome.getRandomBiome(), callback);
|
||||
}
|
||||
|
||||
public void generateZoneAsync(Biome biome, Consumer<Zone> callback) {
|
||||
generateZoneAsync(biome, 2000, 600, callback);
|
||||
}
|
||||
|
||||
public void generateZoneAsync(Biome biome, int width, int height, Consumer<Zone> callback) {
|
||||
generateZoneAsync(biome, width, height, getRandomSeed(), callback);
|
||||
}
|
||||
|
||||
public void generateZoneAsync(Biome biome, int width, int height, int seed, Consumer<Zone> callback) {
|
||||
asyncGenerator.addTask(this, biome, width, height, seed, callback);
|
||||
}
|
||||
|
||||
private static String generateDocumentId(int seed) {
|
||||
Random random = new Random();
|
||||
long mostSigBits = (((long)seed) << 32) | (random.nextInt() & 0xFFFFFFFFL);
|
||||
long leastSigBits = random.nextLong();
|
||||
return new UUID(mostSigBits, leastSigBits).toString();
|
||||
}
|
||||
|
||||
private static int getRandomSeed() {
|
||||
return (int)(Math.random() * Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class BatCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("guano_chance")
|
||||
private double rate = 0.175;
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
for(BlockPosition block : cave.getFloorBlocks()) {
|
||||
if(ctx.nextDouble() <= rate) {
|
||||
ctx.updateBlock(block.getX(), block.getY(), Layer.FRONT, 590);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class CandyCaneCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("candy_canes")
|
||||
private final WeightedMap<Item> candyCanes = new WeightedMap<Item>()
|
||||
.addEntry(ItemRegistry.getItem("holiday/candy-cane-small"), 6)
|
||||
.addEntry(ItemRegistry.getItem("holiday/candy-cane-large"), 1);
|
||||
|
||||
@JsonProperty("candy_cane_chance")
|
||||
private double rate = 0.15;
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
for(BlockPosition block : cave.getFloorBlocks()) {
|
||||
if(ctx.nextDouble() <= rate) {
|
||||
ctx.updateBlock(block.getX(), block.getY(), Layer.FRONT, candyCanes.next(ctx.getRandom()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +1,21 @@
|
|||
package brainwine.gameserver.zone.gen.models;
|
||||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.StoneVariant;
|
||||
|
||||
public class Cave {
|
||||
|
||||
private final List<BlockPosition> blocks = new ArrayList<>();
|
||||
private final List<BlockPosition> ceilingBlocks = new ArrayList<>();
|
||||
private final List<BlockPosition> floorBlocks = new ArrayList<>();
|
||||
private final CaveDecorator decorator;
|
||||
private final CaveType type;
|
||||
private final StoneVariant variant;
|
||||
|
||||
public Cave(CaveDecorator decorator, StoneVariant variant) {
|
||||
this.decorator = decorator;
|
||||
public Cave(CaveType type, StoneVariant variant) {
|
||||
this.type = type;
|
||||
this.variant = variant;
|
||||
}
|
||||
|
||||
|
@ -62,8 +63,8 @@ public class Cave {
|
|||
return floorBlocks;
|
||||
}
|
||||
|
||||
public CaveDecorator getDecorator() {
|
||||
return decorator;
|
||||
public CaveType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public StoneVariant getVariant() {
|
|
@ -0,0 +1,31 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
|
||||
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
|
||||
@JsonSubTypes({
|
||||
@Type(name = "floor", value = FloorCaveDecorator.class),
|
||||
@Type(name = "mushroom", value = MushroomCaveDecorator.class),
|
||||
@Type(name = "fill", value = FillCaveDecorator.class),
|
||||
@Type(name = "structure", value = StructureCaveDecorator.class),
|
||||
})
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public abstract class CaveDecorator {
|
||||
|
||||
@JsonProperty("chance")
|
||||
private double chance = 1.0;
|
||||
|
||||
public abstract void decorate(GeneratorContext ctx, Cave cave);
|
||||
|
||||
public double getChance() {
|
||||
return chance;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
package brainwine.gameserver.zone.gen;
|
||||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public abstract class CaveDecorator {
|
||||
public class CaveType {
|
||||
|
||||
@JsonProperty("min_size")
|
||||
private int minSize = 20;
|
||||
|
@ -23,7 +24,8 @@ public abstract class CaveDecorator {
|
|||
@JsonProperty("frequency")
|
||||
private int frequency = 1;
|
||||
|
||||
public abstract void decorate(GeneratorContext ctx, Cave cave);
|
||||
@JsonProperty("decorators")
|
||||
private List<CaveDecorator> decorators = new ArrayList<>();
|
||||
|
||||
public int getMinSize() {
|
||||
return minSize;
|
||||
|
@ -44,4 +46,8 @@ public abstract class CaveDecorator {
|
|||
public int getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public List<CaveDecorator> getDecorators() {
|
||||
return decorators;
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class CrystalCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("crystals")
|
||||
private final WeightedMap<Item> crystals = new WeightedMap<Item>()
|
||||
.addEntry(ItemRegistry.getItem("ground/crystal-blue-1"), 16)
|
||||
.addEntry(ItemRegistry.getItem("ground/crystal-blue-3"), 16)
|
||||
.addEntry(ItemRegistry.getItem("ground/crystal-blue-2"), 4)
|
||||
.addEntry(ItemRegistry.getItem("ground/crystal-blue-4"), 1);
|
||||
|
||||
@JsonProperty("crystal_chance")
|
||||
private double rate = 0.07;
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
for(BlockPosition block : cave.getFloorBlocks()) {
|
||||
if(ctx.nextDouble() <= rate) {
|
||||
ctx.updateBlock(block.getX(), block.getY(), Layer.FRONT, crystals.next(ctx.getRandom()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class EmptyCaveDecorator extends CaveDecorator {
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
|
||||
public class FillCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("item")
|
||||
private Item item = Item.AIR;
|
||||
|
||||
@JsonProperty("liquid")
|
||||
private boolean liquid = false;
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
int minY = -1;
|
||||
int maxY = -1;
|
||||
|
||||
for(BlockPosition block : cave.getBlocks()) {
|
||||
int y = block.getY();
|
||||
|
||||
if(y < minY || minY == -1) {
|
||||
minY = y;
|
||||
}
|
||||
|
||||
if(y > maxY || maxY == -1) {
|
||||
maxY = y;
|
||||
}
|
||||
}
|
||||
|
||||
int maxDifference = (maxY - minY + 1) / 5;
|
||||
int center = (minY + maxY) / 2;
|
||||
int volume = ctx.nextInt(maxDifference + 1) - maxDifference + center;
|
||||
int surfaceLevel = ctx.nextInt(4) + 1;
|
||||
|
||||
for(BlockPosition block : cave.getBlocks()) {
|
||||
if(block.getY() >= volume) {
|
||||
int mod = liquid ? block.getY() == volume ? surfaceLevel : 5 : 0;
|
||||
ctx.updateBlock(block.getX(), block.getY(), item.getLayer(), item, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
|
||||
public class FloorCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("single_type")
|
||||
private boolean singleType = false;
|
||||
|
||||
@JsonProperty("item_spawn_chance")
|
||||
private double spawnChance = 0.1;
|
||||
|
||||
@JsonProperty("items")
|
||||
private WeightedMap<Item> items = new WeightedMap<>();
|
||||
|
||||
@JsonProperty("mods")
|
||||
private Map<Item, WeightedMap<Integer>> mods = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
if(!items.isEmpty()) {
|
||||
Item item = singleType ? items.next(ctx.getRandom()) : null;
|
||||
|
||||
for(BlockPosition block : cave.getFloorBlocks()) {
|
||||
if(ctx.nextDouble() <= spawnChance) {
|
||||
if(!singleType) {
|
||||
item = items.next(ctx.getRandom());
|
||||
}
|
||||
|
||||
int mod = 0;
|
||||
|
||||
if(mods.containsKey(item)) {
|
||||
mod = mods.get(item).next(ctx.getRandom());
|
||||
}
|
||||
|
||||
ctx.updateBlock(block.getX(), block.getY(), item.getLayer(), item, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +1,22 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
import brainwine.gameserver.zone.gen.models.MushroomType;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MushroomCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("mushrooms")
|
||||
private final WeightedMap<MushroomType> mushrooms = new WeightedMap<>();
|
||||
|
||||
@JsonProperty("mushroom_chance")
|
||||
private double rate = 0.2;
|
||||
@JsonProperty("mushroom_spawn_chance")
|
||||
private double spawnChance = 0.2;
|
||||
|
||||
@JsonProperty("elder_chance")
|
||||
private double elderRate = 0.05;
|
||||
@JsonProperty("elder_spawn_chance")
|
||||
private double elderSpawnChance = 0.05;
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
|
@ -29,14 +24,14 @@ public class MushroomCaveDecorator extends CaveDecorator {
|
|||
MushroomType mushroom = mushrooms.next(ctx.getRandom());
|
||||
|
||||
for(BlockPosition block : cave.getFloorBlocks()) {
|
||||
if(ctx.nextDouble() <= rate) {
|
||||
if(ctx.nextDouble() <= spawnChance) {
|
||||
int x = block.getX();
|
||||
int y = block.getY();
|
||||
int item = mushroom.getItem();
|
||||
|
||||
if(mushroom.hasStalk()) {
|
||||
growMushroom(ctx, x, y, item, mushroom.getStalk(), mushroom.getMaxHeight());
|
||||
} else if(mushroom.hasElder() && ctx.nextDouble() <= elderRate){
|
||||
} else if(mushroom.hasElder() && ctx.nextDouble() <= elderSpawnChance){
|
||||
ctx.updateBlock(x, y, Layer.FRONT, mushroom.getElder());
|
||||
} else {
|
||||
ctx.updateBlock(x, y, Layer.FRONT, item);
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
public enum MushroomType {
|
||||
|
||||
PORTABELLA(746),
|
||||
OYSTER(745),
|
||||
PORCINI(747),
|
||||
WILLOW(735, 736, 3),
|
||||
AMANITA(730, 731, 3),
|
||||
CHANTERELLE(748),
|
||||
MOREL(744, 449),
|
||||
ANBARIC(743, 487),
|
||||
ACID(741, 742),
|
||||
LAVA(750, 447),
|
||||
ARCTIC(751, 446),
|
||||
HELL(749, 448),
|
||||
SHADE(1169),
|
||||
APOSTATE(1167, 445),
|
||||
DEVILS_CIGAR(1168);
|
||||
|
||||
private final int item;
|
||||
private int elder;
|
||||
private int stalk;
|
||||
private int maxHeight;
|
||||
|
||||
private MushroomType(int item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
private MushroomType(int item, int stalk, int maxHeight) {
|
||||
this.item = item;
|
||||
this.stalk = stalk;
|
||||
this.maxHeight = maxHeight;
|
||||
}
|
||||
|
||||
private MushroomType(int item, int elder) {
|
||||
this.item = item;
|
||||
this.elder = elder;
|
||||
}
|
||||
|
||||
public int getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public boolean hasElder() {
|
||||
return elder != 0;
|
||||
}
|
||||
|
||||
public int getElder() {
|
||||
return elder;
|
||||
}
|
||||
|
||||
public boolean hasStalk() {
|
||||
return stalk != 0;
|
||||
}
|
||||
|
||||
public int getStalk() {
|
||||
return stalk;
|
||||
}
|
||||
|
||||
public int getMaxHeight() {
|
||||
return maxHeight;
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class RareCrystalCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("crystals")
|
||||
private final WeightedMap<Item> crystals = new WeightedMap<>();
|
||||
|
||||
@JsonProperty("crystal_chance")
|
||||
private double rate = 0.05;
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
if(!crystals.isEmpty()) {
|
||||
Item crystal = crystals.next(ctx.getRandom());
|
||||
|
||||
for(BlockPosition block : cave.getFloorBlocks()) {
|
||||
if(ctx.nextDouble() <= rate) {
|
||||
ctx.updateBlock(block.getX(), block.getY(), Layer.FRONT, crystal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.item.Item;
|
||||
import brainwine.gameserver.item.ItemRegistry;
|
||||
import brainwine.gameserver.item.Layer;
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
import brainwine.gameserver.zone.gen.models.Cave;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class SaltCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("salt")
|
||||
private Item salt = ItemRegistry.getItem(586);
|
||||
|
||||
@JsonProperty("salt_chance")
|
||||
private double rate = 0.175;
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
for(BlockPosition block : cave.getFloorBlocks()) {
|
||||
if(ctx.nextDouble() <= rate) {
|
||||
ctx.updateBlock(block.getX(), block.getY(), Layer.FRONT, salt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package brainwine.gameserver.zone.gen.caves;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import brainwine.gameserver.prefab.Prefab;
|
||||
import brainwine.gameserver.util.WeightedMap;
|
||||
import brainwine.gameserver.zone.gen.GeneratorContext;
|
||||
import brainwine.gameserver.zone.gen.models.BlockPosition;
|
||||
|
||||
public class StructureCaveDecorator extends CaveDecorator {
|
||||
|
||||
@JsonProperty("prefabs")
|
||||
private WeightedMap<Prefab> prefabs = new WeightedMap<>();
|
||||
|
||||
@Override
|
||||
public void decorate(GeneratorContext ctx, Cave cave) {
|
||||
if(!prefabs.isEmpty()) {
|
||||
// TODO maybe randomly offset by prefab size
|
||||
BlockPosition position = cave.getBlocks().get(ctx.nextInt(cave.getSize() - 1));
|
||||
ctx.placePrefab(prefabs.next(), position.getX(), position.getY());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package brainwine.gameserver.zone.gen.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
|
||||
|
||||
import brainwine.gameserver.zone.gen.CaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.BatCaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.CandyCaneCaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.CrystalCaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.EmptyCaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.MushroomCaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.RareCrystalCaveDecorator;
|
||||
import brainwine.gameserver.zone.gen.caves.SaltCaveDecorator;
|
||||
|
||||
public enum CaveType {
|
||||
|
||||
@JsonEnumDefaultValue
|
||||
EMPTY,
|
||||
MUSHROOM_GROVE(MushroomCaveDecorator.class),
|
||||
CRYSTAL(CrystalCaveDecorator.class),
|
||||
RARE_CRYSTAL(RareCrystalCaveDecorator.class),
|
||||
SALT(SaltCaveDecorator.class),
|
||||
BAT_CAVE(BatCaveDecorator.class),
|
||||
CANDY_CANE(CandyCaneCaveDecorator.class);
|
||||
|
||||
private final Class<? extends CaveDecorator> decoratorType;
|
||||
|
||||
private CaveType() {
|
||||
this(EmptyCaveDecorator.class);
|
||||
}
|
||||
|
||||
private CaveType(Class<? extends CaveDecorator> decoratorType) {
|
||||
this.decoratorType = decoratorType;
|
||||
}
|
||||
|
||||
public Class<? extends CaveDecorator> getDecoratorType() {
|
||||
return decoratorType;
|
||||
}
|
||||
}
|
285
gameserver/src/main/resources/defaults/generators/arctic.json
Normal file
285
gameserver/src/main/resources/defaults/generators/arctic.json
Normal file
|
@ -0,0 +1,285 @@
|
|||
{
|
||||
"surface_fillers": [
|
||||
"rubble/stone-pile-1",
|
||||
"rubble/stone-pile-2",
|
||||
"rubble/stone-pile-3",
|
||||
"rubble/stone-pile-4",
|
||||
"rubble/stone-pile-5",
|
||||
"rubble/stone-pile-6",
|
||||
"rubble/stone-pile-7",
|
||||
"rubble/stone-pile-8",
|
||||
"rubble/scrap-metal-1",
|
||||
"rubble/scrap-metal-2",
|
||||
"rubble/scrap-metal-3",
|
||||
"rubble/scrap-metal-4",
|
||||
"rubble/scrap-metal-5",
|
||||
"rubble/scrap-metal-6",
|
||||
"rubble/scrap-metal-7",
|
||||
"rubble/scrap-metal-8",
|
||||
"rubble/scrap-metal-9",
|
||||
"rubble/scrap-metal-10"
|
||||
],
|
||||
"speleothems": [
|
||||
"arctic/icicle-1",
|
||||
"arctic/icicle-2",
|
||||
"arctic/icicle-3",
|
||||
"arctic/icicle-4",
|
||||
"arctic/icicle-5"
|
||||
],
|
||||
"stone_variants": {
|
||||
"default": 6,
|
||||
"limestone": 1
|
||||
},
|
||||
"unique_structures": [
|
||||
"paint_bunker",
|
||||
"head_bunker"
|
||||
],
|
||||
"dungeons": [
|
||||
"dungeon_large_1",
|
||||
"dungeon_large_2",
|
||||
"dungeon_medium_1",
|
||||
"dungeon_medium_2",
|
||||
"dungeon_medium_3",
|
||||
"dungeon_medium_4",
|
||||
"dungeon_medium_5",
|
||||
"dungeon_medium_6",
|
||||
"dungeon_medium_7",
|
||||
"dungeon_medium_8",
|
||||
"dungeon_medium_9",
|
||||
"dungeon_medium_10",
|
||||
"dungeon_small_1",
|
||||
"dungeon_small_2",
|
||||
"dungeon_small_3",
|
||||
"dungeon_small_4"
|
||||
],
|
||||
"spawn_towers": [
|
||||
"spawn_building_arctic_1",
|
||||
"spawn_building_arctic_2"
|
||||
],
|
||||
"dungeon_chance": 0.333,
|
||||
"base_resources": {
|
||||
"clay": {
|
||||
"per": 1200
|
||||
},
|
||||
"logs": {
|
||||
"per": 1600,
|
||||
"min_depth": 0.05,
|
||||
"max_depth": 0.2
|
||||
},
|
||||
"roots": {
|
||||
"per": 1600,
|
||||
"max_depth": 0.2
|
||||
},
|
||||
"rocks": {
|
||||
"per": 300,
|
||||
"min_depth": 0.1
|
||||
}
|
||||
},
|
||||
"ore_deposits": {
|
||||
"ground/iron": {
|
||||
"per": 3500,
|
||||
"min_size": 5,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.35
|
||||
},
|
||||
"ground/copper": {
|
||||
"per": 4100,
|
||||
"min_size": 4,
|
||||
"max_size": 12,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.5
|
||||
},
|
||||
"ground/zinc": {
|
||||
"per": 2500,
|
||||
"min_size": 7,
|
||||
"max_size": 14,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.8
|
||||
},
|
||||
"ground/quartz": {
|
||||
"per": 3000,
|
||||
"min_size": 5,
|
||||
"max_size": 10,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.5
|
||||
},
|
||||
"ground/lead": {
|
||||
"per": 8000,
|
||||
"min_size": 3,
|
||||
"max_size": 6,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/diamond": {
|
||||
"per": 100000,
|
||||
"min_size": 1,
|
||||
"max_size": 4,
|
||||
"min_depth": 0.2
|
||||
}
|
||||
},
|
||||
"cave_types": {
|
||||
"candy_cane": {
|
||||
"min_size": 30,
|
||||
"max_size": 70,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.1,
|
||||
"items": {
|
||||
"holiday/candy-cane-small": 16,
|
||||
"holiday/candy-cane-large": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"empty": {
|
||||
"min_size": 150,
|
||||
"min_depth": 0.25,
|
||||
"frequency": 10
|
||||
},
|
||||
"mushroom_grove": {
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "mushroom",
|
||||
"mushrooms": {
|
||||
"portabella": 55,
|
||||
"oyster": 50,
|
||||
"arctic": 20,
|
||||
"anbaric": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ice": {
|
||||
"max_size": 300,
|
||||
"frequency": 9,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "arctic/ice"
|
||||
}
|
||||
]
|
||||
},
|
||||
"snow": {
|
||||
"max_size": 300,
|
||||
"max_depth": 0.6,
|
||||
"frequency": 9,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "arctic/snow"
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 100,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-blue-1": 16,
|
||||
"ground/crystal-blue-3": 16,
|
||||
"ground/crystal-blue-2": 4,
|
||||
"ground/crystal-blue-4": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"rare_crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"single_type": true,
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-rainbow": 1,
|
||||
"ground/onyx": 8,
|
||||
"ground/crystal-red-1": 50,
|
||||
"ground/crystal-purple-1": 45
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ruins": {
|
||||
"max_size": 170,
|
||||
"min_depth": 0.2,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 7,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "structure",
|
||||
"prefabs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"bat_cave": {
|
||||
"max_depth": 0.5,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/guano"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"hatchery": {
|
||||
"max_size": 300,
|
||||
"frequency": 3,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/terrapus-egg"],
|
||||
"mods": {
|
||||
"ground/terrapus-egg": {
|
||||
"0": 1,
|
||||
"1": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"salt": {
|
||||
"min_depth": 0.2,
|
||||
"frequency": 3,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/salt-crystal"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"graveyard":{
|
||||
"min_size": 15,
|
||||
"max_size": 75,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.4,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": {
|
||||
"rubble/gravestone": 4,
|
||||
"rubble/bone-pile": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
220
gameserver/src/main/resources/defaults/generators/brain.json
Normal file
220
gameserver/src/main/resources/defaults/generators/brain.json
Normal file
|
@ -0,0 +1,220 @@
|
|||
{
|
||||
"surface_fillers": [
|
||||
"rubble/stone-pile-1",
|
||||
"rubble/stone-pile-2",
|
||||
"rubble/stone-pile-3",
|
||||
"rubble/stone-pile-4",
|
||||
"rubble/stone-pile-5",
|
||||
"rubble/stone-pile-6",
|
||||
"rubble/stone-pile-7",
|
||||
"rubble/stone-pile-8",
|
||||
"rubble/scrap-metal-1",
|
||||
"rubble/scrap-metal-2",
|
||||
"rubble/scrap-metal-3",
|
||||
"rubble/scrap-metal-4",
|
||||
"rubble/scrap-metal-5",
|
||||
"rubble/scrap-metal-6",
|
||||
"rubble/scrap-metal-7",
|
||||
"rubble/scrap-metal-8",
|
||||
"rubble/scrap-metal-9",
|
||||
"rubble/scrap-metal-10"
|
||||
],
|
||||
"speleothems": [
|
||||
"mechanical/spikes-brain",
|
||||
"mechanical/spikes-brain-small"
|
||||
],
|
||||
"stone_variants": {
|
||||
"default": 6,
|
||||
"limestone": 1
|
||||
},
|
||||
"unique_structures": [
|
||||
"paint_bunker",
|
||||
"head_bunker"
|
||||
],
|
||||
"dungeons": [
|
||||
"dungeon_large_1",
|
||||
"dungeon_large_2",
|
||||
"dungeon_medium_1",
|
||||
"dungeon_medium_2",
|
||||
"dungeon_medium_3",
|
||||
"dungeon_medium_4",
|
||||
"dungeon_medium_5",
|
||||
"dungeon_medium_6",
|
||||
"dungeon_medium_7",
|
||||
"dungeon_medium_8",
|
||||
"dungeon_medium_9",
|
||||
"dungeon_medium_10",
|
||||
"dungeon_small_1",
|
||||
"dungeon_small_2",
|
||||
"dungeon_small_3",
|
||||
"dungeon_small_4"
|
||||
],
|
||||
"spawn_towers": ["spawn_building_brain_1"],
|
||||
"dungeon_chance": 0.4,
|
||||
"base_resources": {
|
||||
"rocks": {
|
||||
"per": 200
|
||||
}
|
||||
},
|
||||
"ore_deposits": {
|
||||
"ground/iron": {
|
||||
"per": 6000,
|
||||
"min_size": 5,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.35
|
||||
},
|
||||
"ground/lead": {
|
||||
"per": 3000,
|
||||
"min_size": 4,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/sulfur": {
|
||||
"per": 9000,
|
||||
"min_size": 8,
|
||||
"max_size": 12,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/zinc": {
|
||||
"per": 2400,
|
||||
"min_size": 5,
|
||||
"max_size": 11,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.8
|
||||
},
|
||||
"ground/quartz": {
|
||||
"per": 2200,
|
||||
"min_size": 3,
|
||||
"max_size": 8,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.7
|
||||
}
|
||||
},
|
||||
"cave_types": {
|
||||
"empty": {
|
||||
"min_size": 150,
|
||||
"min_depth": 0.25,
|
||||
"frequency": 12
|
||||
},
|
||||
"mushroom_grove": {
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 3,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "mushroom",
|
||||
"mushrooms": {
|
||||
"portabella": 65,
|
||||
"oyster": 50,
|
||||
"porcini": 25,
|
||||
"willow": 20,
|
||||
"amanita": 11,
|
||||
"chanterelle": 7,
|
||||
"anbaric": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"acid": {
|
||||
"max_size": 300,
|
||||
"frequency": 14,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/acid",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.05,
|
||||
"items": {
|
||||
"vegetation/mushroom-acid": 16,
|
||||
"vegetation/mushroom-acid-tall": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 100,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-blue-1": 16,
|
||||
"ground/crystal-blue-3": 16,
|
||||
"ground/crystal-blue-2": 4,
|
||||
"ground/crystal-blue-4": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"rare_crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"single_type": true,
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-rainbow": 1,
|
||||
"ground/onyx": 8,
|
||||
"ground/crystal-purple-1": 30,
|
||||
"ground/crystal-purple-large": 5,
|
||||
"ground/crystal-green-small": 50,
|
||||
"ground/crystal-green-large": 12
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ruins": {
|
||||
"max_size": 170,
|
||||
"min_depth": 0.2,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 11,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "structure",
|
||||
"prefabs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"hatchery": {
|
||||
"max_size": 300,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/terrapus-egg"],
|
||||
"mods": {
|
||||
"ground/terrapus-egg": {
|
||||
"0": 1,
|
||||
"1": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"salt": {
|
||||
"min_depth": 0.2,
|
||||
"frequency": 4,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/salt-crystal"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
215
gameserver/src/main/resources/defaults/generators/deep.json
Normal file
215
gameserver/src/main/resources/defaults/generators/deep.json
Normal file
|
@ -0,0 +1,215 @@
|
|||
{
|
||||
"surface": false,
|
||||
"speleothems": [
|
||||
"ground/stalagmite-1",
|
||||
"ground/stalagmite-2",
|
||||
"ground/stalagmite-3",
|
||||
"ground/stalagmite-4",
|
||||
"ground/stalagmite-5"
|
||||
],
|
||||
"stone_variants": {
|
||||
"default": 17,
|
||||
"limestone": 4
|
||||
},
|
||||
"unique_structures": [
|
||||
"paint_bunker",
|
||||
"head_bunker"
|
||||
],
|
||||
"dungeons": [
|
||||
"dungeon_large_1",
|
||||
"dungeon_large_2",
|
||||
"dungeon_medium_1",
|
||||
"dungeon_medium_2",
|
||||
"dungeon_medium_3",
|
||||
"dungeon_medium_4",
|
||||
"dungeon_medium_5",
|
||||
"dungeon_medium_6",
|
||||
"dungeon_medium_7",
|
||||
"dungeon_medium_8",
|
||||
"dungeon_medium_9",
|
||||
"dungeon_medium_10",
|
||||
"dungeon_small_1",
|
||||
"dungeon_small_2",
|
||||
"dungeon_small_3",
|
||||
"dungeon_small_4"
|
||||
],
|
||||
"spawn_towers": ["spawn_building_deep_1"],
|
||||
"dungeon_region": [81, 85],
|
||||
"dungeon_chance": 0.4,
|
||||
"base_resources": {
|
||||
"clay": {
|
||||
"per": 1200
|
||||
},
|
||||
"rocks": {
|
||||
"per": 300
|
||||
}
|
||||
},
|
||||
"ore_deposits": {
|
||||
"ground/iron": {
|
||||
"per": 2200,
|
||||
"min_size": 6,
|
||||
"max_size": 13
|
||||
},
|
||||
"ground/quartz": {
|
||||
"per": 6000,
|
||||
"min_size": 3,
|
||||
"max_size": 9
|
||||
},
|
||||
"ground/lead": {
|
||||
"per": 4000,
|
||||
"min_size": 4,
|
||||
"max_size": 9
|
||||
},
|
||||
"ground/marble": {
|
||||
"per": 20000,
|
||||
"min_size": 3,
|
||||
"max_size": 8,
|
||||
"max_depth": 0.5
|
||||
}
|
||||
},
|
||||
"cave_types": {
|
||||
"empty": {
|
||||
"min_size": 150,
|
||||
"frequency": 24
|
||||
},
|
||||
"mushroom_grove": {
|
||||
"frequency": 23,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "mushroom",
|
||||
"mushrooms": {
|
||||
"portabella": 80,
|
||||
"shade": 75,
|
||||
"oyster": 45,
|
||||
"porcini": 35,
|
||||
"apostate": 15,
|
||||
"chanterelle": 9,
|
||||
"devils_cigar": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"acid": {
|
||||
"max_size": 300,
|
||||
"frequency": 18,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/acid",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.05,
|
||||
"items": {
|
||||
"vegetation/mushroom-acid": 16,
|
||||
"vegetation/mushroom-acid-tall": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"magma": {
|
||||
"max_size": 300,
|
||||
"frequency": 12,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/magma",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.1,
|
||||
"items": {
|
||||
"vegetation/mushroom-lava": 16,
|
||||
"vegetation/mushroom-lava-elder": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"hatchery": {
|
||||
"max_size": 400,
|
||||
"frequency": 25,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/terrapus-egg"],
|
||||
"mods": {
|
||||
"ground/terrapus-egg": {
|
||||
"0": 1,
|
||||
"1": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 100,
|
||||
"frequency": 3,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-blue-1": 16,
|
||||
"ground/crystal-blue-3": 16,
|
||||
"ground/crystal-blue-2": 4,
|
||||
"ground/crystal-blue-4": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"rare_crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 80,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"single_type": true,
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-rainbow": 1,
|
||||
"ground/crystal-red-large": 5,
|
||||
"ground/crystal-purple-large": 5,
|
||||
"ground/crystal-orange": 8,
|
||||
"ground/crystal-purple-1": 45,
|
||||
"ground/crystal-red-1": 50
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ruins": {
|
||||
"max_size": 170,
|
||||
"frequency": 22,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "structure",
|
||||
"prefabs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"bat_cave": {
|
||||
"frequency": 12,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/guano"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"salt": {
|
||||
"frequency": 10,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/salt-crystal"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
258
gameserver/src/main/resources/defaults/generators/desert.json
Normal file
258
gameserver/src/main/resources/defaults/generators/desert.json
Normal file
|
@ -0,0 +1,258 @@
|
|||
{
|
||||
"surface_fillers": [
|
||||
"vegetation/shrub-dead",
|
||||
"vegetation/cactus-small",
|
||||
"vegetation/tumbleweed"
|
||||
],
|
||||
"speleothems": [
|
||||
"ground/stalagmite-1",
|
||||
"ground/stalagmite-2",
|
||||
"ground/stalagmite-3",
|
||||
"ground/stalagmite-4",
|
||||
"ground/stalagmite-5"
|
||||
],
|
||||
"stone_variants": {
|
||||
"default": 3,
|
||||
"sandstone": 1
|
||||
},
|
||||
"unique_structures": [
|
||||
"paint_bunker",
|
||||
"head_bunker"
|
||||
],
|
||||
"dungeons": [
|
||||
"dungeon_large_1",
|
||||
"dungeon_large_2",
|
||||
"dungeon_medium_1",
|
||||
"dungeon_medium_2",
|
||||
"dungeon_medium_3",
|
||||
"dungeon_medium_4",
|
||||
"dungeon_medium_5",
|
||||
"dungeon_medium_6",
|
||||
"dungeon_medium_7",
|
||||
"dungeon_medium_8",
|
||||
"dungeon_medium_9",
|
||||
"dungeon_medium_10",
|
||||
"dungeon_small_1",
|
||||
"dungeon_small_2",
|
||||
"dungeon_small_3",
|
||||
"dungeon_small_4"
|
||||
],
|
||||
"spawn_towers": [
|
||||
"spawn_building_desert_1",
|
||||
"spawn_building_desert_2"
|
||||
],
|
||||
"dungeon_chance": 0.333,
|
||||
"base_resources": {
|
||||
"clay": {
|
||||
"per": 800
|
||||
},
|
||||
"rocks": {
|
||||
"per": 250
|
||||
}
|
||||
},
|
||||
"ore_deposits": {
|
||||
"ground/iron": {
|
||||
"per": 3800,
|
||||
"min_size": 6,
|
||||
"max_size": 13,
|
||||
"min_depth": 0.35
|
||||
},
|
||||
"ground/copper": {
|
||||
"per": 2200,
|
||||
"min_size": 6,
|
||||
"max_size": 13,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.5
|
||||
},
|
||||
"ground/zinc": {
|
||||
"per": 4200,
|
||||
"min_size": 5,
|
||||
"max_size": 11,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.8
|
||||
},
|
||||
"ground/lead": {
|
||||
"per": 3000,
|
||||
"min_size": 4,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/sulfur": {
|
||||
"per": 5500,
|
||||
"min_size": 5,
|
||||
"max_size": 10,
|
||||
"min_depth": 0.7
|
||||
},
|
||||
"ground/beryllium": {
|
||||
"per": 27000,
|
||||
"min_size": 5,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.5
|
||||
}
|
||||
},
|
||||
"cave_types": {
|
||||
"empty": {
|
||||
"min_size": 150,
|
||||
"min_depth": 0.25,
|
||||
"frequency": 10
|
||||
},
|
||||
"mushroom_grove": {
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 11,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "mushroom",
|
||||
"mushrooms": {
|
||||
"portabella": 85,
|
||||
"oyster": 70,
|
||||
"porcini": 35,
|
||||
"willow": 20,
|
||||
"amanita": 11,
|
||||
"chanterelle": 7,
|
||||
"morel": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"sand": {
|
||||
"max_size": 100,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "ground/sand"
|
||||
}
|
||||
]
|
||||
},
|
||||
"acid": {
|
||||
"max_size": 100,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/acid",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.1,
|
||||
"items": {
|
||||
"vegetation/mushroom-acid": 16,
|
||||
"vegetation/mushroom-acid-tall": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"hatchery": {
|
||||
"max_size": 300,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/terrapus-egg"],
|
||||
"mods": {
|
||||
"ground/terrapus-egg": {
|
||||
"0": 1,
|
||||
"1": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 100,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-blue-1": 16,
|
||||
"ground/crystal-blue-3": 16,
|
||||
"ground/crystal-blue-2": 4,
|
||||
"ground/crystal-blue-4": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"rare_crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"single_type": true,
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-rainbow": 1,
|
||||
"ground/onyx": 8,
|
||||
"ground/crystal-red-1": 50,
|
||||
"ground/crystal-purple-1": 45
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ruins": {
|
||||
"max_size": 170,
|
||||
"min_depth": 0.2,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 9,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "structure",
|
||||
"prefabs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"bat_cave": {
|
||||
"max_depth": 0.5,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/guano"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"salt": {
|
||||
"min_depth": 0.2,
|
||||
"frequency": 4,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/salt-crystal"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"graveyard": {
|
||||
"min_size": 15,
|
||||
"max_size": 75,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.4,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": {
|
||||
"rubble/gravestone": 4,
|
||||
"rubble/bone-pile": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
227
gameserver/src/main/resources/defaults/generators/hell.json
Normal file
227
gameserver/src/main/resources/defaults/generators/hell.json
Normal file
|
@ -0,0 +1,227 @@
|
|||
{
|
||||
"surface_fillers": [
|
||||
"rubble/stone-pile-1",
|
||||
"rubble/stone-pile-2",
|
||||
"rubble/stone-pile-3",
|
||||
"rubble/stone-pile-4",
|
||||
"rubble/stone-pile-5",
|
||||
"rubble/stone-pile-6",
|
||||
"rubble/stone-pile-7",
|
||||
"rubble/stone-pile-8",
|
||||
"rubble/scrap-metal-1",
|
||||
"rubble/scrap-metal-2",
|
||||
"rubble/scrap-metal-3",
|
||||
"rubble/scrap-metal-4",
|
||||
"rubble/scrap-metal-5",
|
||||
"rubble/scrap-metal-6",
|
||||
"rubble/scrap-metal-7",
|
||||
"rubble/scrap-metal-8",
|
||||
"rubble/scrap-metal-9",
|
||||
"rubble/scrap-metal-10"
|
||||
],
|
||||
"speleothems": [
|
||||
"ground/stalagmite-1",
|
||||
"ground/stalagmite-2",
|
||||
"ground/stalagmite-3",
|
||||
"ground/stalagmite-4",
|
||||
"ground/stalagmite-5"
|
||||
],
|
||||
"unique_structures": [
|
||||
"paint_bunker",
|
||||
"head_bunker"
|
||||
],
|
||||
"dungeons": [
|
||||
"dungeon_large_1",
|
||||
"dungeon_large_2",
|
||||
"dungeon_medium_1",
|
||||
"dungeon_medium_2",
|
||||
"dungeon_medium_3",
|
||||
"dungeon_medium_4",
|
||||
"dungeon_medium_5",
|
||||
"dungeon_medium_6",
|
||||
"dungeon_medium_7",
|
||||
"dungeon_medium_8",
|
||||
"dungeon_medium_9",
|
||||
"dungeon_medium_10",
|
||||
"dungeon_small_1",
|
||||
"dungeon_small_2",
|
||||
"dungeon_small_3",
|
||||
"dungeon_small_4"
|
||||
],
|
||||
"spawn_towers": [
|
||||
"spawn_building_hell_1",
|
||||
"spawn_building_hell_2",
|
||||
"spawn_building_hell_3",
|
||||
"spawn_building_hell_4"
|
||||
],
|
||||
"dungeon_chance": 0.375,
|
||||
"base_resources": {
|
||||
"clay": {
|
||||
"per": 1500
|
||||
},
|
||||
"rocks": {
|
||||
"per": 180
|
||||
}
|
||||
},
|
||||
"ore_deposits": {
|
||||
"ground/iron": {
|
||||
"per": 3100,
|
||||
"min_size": 5,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.35
|
||||
},
|
||||
"ground/lead": {
|
||||
"per": 2600,
|
||||
"min_size": 4,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/sulfur": {
|
||||
"per": 2500,
|
||||
"min_size": 8,
|
||||
"max_size": 12,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/bloodstone": {
|
||||
"per": 5200,
|
||||
"min_size": 5,
|
||||
"max_size": 10,
|
||||
"min_depth": 0.7
|
||||
}
|
||||
},
|
||||
"cave_types": {
|
||||
"empty": {
|
||||
"min_size": 150,
|
||||
"min_depth": 0.25,
|
||||
"frequency": 9
|
||||
},
|
||||
"mushroom_grove": {
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 3,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "mushroom",
|
||||
"mushroom": "hell"
|
||||
}
|
||||
]
|
||||
},
|
||||
"magma": {
|
||||
"max_size": 300,
|
||||
"frequency": 9,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/magma",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.05,
|
||||
"items": {
|
||||
"vegetation/mushroom-lava": 16,
|
||||
"vegetation/mushroom-lava-elder": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 100,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-blue-1": 16,
|
||||
"ground/crystal-blue-3": 16,
|
||||
"ground/crystal-blue-2": 4,
|
||||
"ground/crystal-blue-4": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"rare_crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"single_type": true,
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-rainbow": 1,
|
||||
"ground/crystal-red-large": 5,
|
||||
"ground/onyx": 8,
|
||||
"ground/crystal-red-1": 50,
|
||||
"ground/crystal-purple-1": 45
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ruins": {
|
||||
"max_size": 170,
|
||||
"min_depth": 0.2,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 10,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "structure",
|
||||
"prefabs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"hatchery": {
|
||||
"max_size": 300,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/terrapus-egg"],
|
||||
"mods": {
|
||||
"ground/terrapus-egg": {
|
||||
"0": 1,
|
||||
"1": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"graveyard": {
|
||||
"min_size": 15,
|
||||
"max_size": 75,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.4,
|
||||
"frequency": 20,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": {
|
||||
"rubble/hell-gravestone": 4,
|
||||
"rubble/bone-pile": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"salt": {
|
||||
"min_depth": 0.2,
|
||||
"frequency": 3,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/fire-salt-crystal"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
298
gameserver/src/main/resources/defaults/generators/plain.json
Normal file
298
gameserver/src/main/resources/defaults/generators/plain.json
Normal file
|
@ -0,0 +1,298 @@
|
|||
{
|
||||
"surface_fillers": [
|
||||
"vegetation/shrub-dead"
|
||||
],
|
||||
"speleothems": [
|
||||
"ground/stalagmite-1",
|
||||
"ground/stalagmite-2",
|
||||
"ground/stalagmite-3",
|
||||
"ground/stalagmite-4",
|
||||
"ground/stalagmite-5"
|
||||
],
|
||||
"stone_variants": {
|
||||
"default": 17,
|
||||
"sandstone": 4,
|
||||
"limestone": 2
|
||||
},
|
||||
"unique_structures": [
|
||||
"paint_bunker",
|
||||
"head_bunker"
|
||||
],
|
||||
"dungeons": [
|
||||
"dungeon_large_1",
|
||||
"dungeon_large_2",
|
||||
"dungeon_medium_1",
|
||||
"dungeon_medium_2",
|
||||
"dungeon_medium_3",
|
||||
"dungeon_medium_4",
|
||||
"dungeon_medium_5",
|
||||
"dungeon_medium_6",
|
||||
"dungeon_medium_7",
|
||||
"dungeon_medium_8",
|
||||
"dungeon_medium_9",
|
||||
"dungeon_medium_10",
|
||||
"dungeon_small_1",
|
||||
"dungeon_small_2",
|
||||
"dungeon_small_3",
|
||||
"dungeon_small_4"
|
||||
],
|
||||
"spawn_towers": [
|
||||
"spawn_building_plain_1",
|
||||
"spawn_building_plain_2",
|
||||
"spawn_building_plain_3",
|
||||
"spawn_building_plain_4"
|
||||
],
|
||||
"base_resources": {
|
||||
"clay": {
|
||||
"per": 1200
|
||||
},
|
||||
"logs": {
|
||||
"per": 1600,
|
||||
"min_depth": 0.05,
|
||||
"max_depth": 0.2
|
||||
},
|
||||
"roots": {
|
||||
"per": 1600,
|
||||
"max_depth": 0.2
|
||||
},
|
||||
"rocks": {
|
||||
"per": 300,
|
||||
"min_depth": 0.1
|
||||
}
|
||||
},
|
||||
"ore_deposits": {
|
||||
"ground/iron": {
|
||||
"per": 2400,
|
||||
"min_size": 6,
|
||||
"max_size": 13,
|
||||
"min_depth": 0.35
|
||||
},
|
||||
"ground/copper": {
|
||||
"per": 2700,
|
||||
"min_size": 6,
|
||||
"max_size": 13,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.5
|
||||
},
|
||||
"ground/zinc": {
|
||||
"per": 3600,
|
||||
"min_size": 5,
|
||||
"max_size": 11,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.8
|
||||
},
|
||||
"ground/quartz": {
|
||||
"per": 3200,
|
||||
"min_size": 3,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.5
|
||||
},
|
||||
"ground/lead": {
|
||||
"per": 2700,
|
||||
"min_size": 4,
|
||||
"max_size": 9,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/sulfur": {
|
||||
"per": 3700,
|
||||
"min_size": 5,
|
||||
"max_size": 10,
|
||||
"min_depth": 0.7
|
||||
},
|
||||
"ground/marble": {
|
||||
"per": 13000,
|
||||
"min_size": 3,
|
||||
"max_size": 10,
|
||||
"min_depth": 0.6,
|
||||
"max_depth": 0.8
|
||||
}
|
||||
},
|
||||
"cave_types": {
|
||||
"empty": {
|
||||
"min_size": 150,
|
||||
"min_depth": 0.25,
|
||||
"frequency": 9
|
||||
},
|
||||
"mushroom_grove": {
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 11,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "mushroom",
|
||||
"mushrooms": {
|
||||
"portabella": 85,
|
||||
"oyster": 70,
|
||||
"porcini": 35,
|
||||
"willow": 20,
|
||||
"amanita": 11,
|
||||
"chanterelle": 7,
|
||||
"morel": 4,
|
||||
"anbaric": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"water": {
|
||||
"max_size": 200,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/water",
|
||||
"liquid": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"acid": {
|
||||
"max_size": 200,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 4,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/acid",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.1,
|
||||
"items": {
|
||||
"vegetation/mushroom-acid": 16,
|
||||
"vegetation/mushroom-acid-tall": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"magma": {
|
||||
"max_size": 200,
|
||||
"min_depth": 0.85,
|
||||
"frequency": 4,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/magma",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.1,
|
||||
"items": {
|
||||
"vegetation/mushroom-lava": 16,
|
||||
"vegetation/mushroom-lava-elder": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"hatchery": {
|
||||
"max_size": 300,
|
||||
"frequency": 3,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/terrapus-egg"],
|
||||
"mods": {
|
||||
"ground/terrapus-egg": {
|
||||
"0": 1,
|
||||
"1": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 100,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-blue-1": 16,
|
||||
"ground/crystal-blue-3": 16,
|
||||
"ground/crystal-blue-2": 4,
|
||||
"ground/crystal-blue-4": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"rare_crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"single_type": true,
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-rainbow": 1,
|
||||
"ground/onyx": 8,
|
||||
"ground/crystal-red-1": 50,
|
||||
"ground/crystal-purple-1": 45
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ruins": {
|
||||
"max_size": 170,
|
||||
"min_depth": 0.2,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 9,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "structure",
|
||||
"prefabs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"bat_cave": {
|
||||
"max_depth": 0.5,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/guano"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"salt": {
|
||||
"min_depth": 0.2,
|
||||
"frequency": 4,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/salt-crystal"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"graveyard": {
|
||||
"min_size": 15,
|
||||
"max_size": 75,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.4,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": {
|
||||
"rubble/gravestone": 4,
|
||||
"rubble/bone-pile": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
229
gameserver/src/main/resources/defaults/generators/space.json
Normal file
229
gameserver/src/main/resources/defaults/generators/space.json
Normal file
|
@ -0,0 +1,229 @@
|
|||
{
|
||||
"surface_fillers": [
|
||||
"rubble/stone-pile-1",
|
||||
"rubble/stone-pile-2",
|
||||
"rubble/stone-pile-3",
|
||||
"rubble/stone-pile-4",
|
||||
"rubble/stone-pile-5",
|
||||
"rubble/stone-pile-6",
|
||||
"rubble/stone-pile-7",
|
||||
"rubble/stone-pile-8",
|
||||
"rubble/scrap-metal-1",
|
||||
"rubble/scrap-metal-2",
|
||||
"rubble/scrap-metal-3",
|
||||
"rubble/scrap-metal-4",
|
||||
"rubble/scrap-metal-5",
|
||||
"rubble/scrap-metal-6",
|
||||
"rubble/scrap-metal-7",
|
||||
"rubble/scrap-metal-8",
|
||||
"rubble/scrap-metal-9",
|
||||
"rubble/scrap-metal-10"
|
||||
],
|
||||
"speleothems": [
|
||||
"ground/stalagmite-1",
|
||||
"ground/stalagmite-2",
|
||||
"ground/stalagmite-3",
|
||||
"ground/stalagmite-4",
|
||||
"ground/stalagmite-5"
|
||||
],
|
||||
"unique_structures": [
|
||||
"paint_bunker",
|
||||
"head_bunker"
|
||||
],
|
||||
"dungeons": [
|
||||
"dungeon_large_1",
|
||||
"dungeon_large_2",
|
||||
"dungeon_medium_1",
|
||||
"dungeon_medium_2",
|
||||
"dungeon_medium_3",
|
||||
"dungeon_medium_4",
|
||||
"dungeon_medium_5",
|
||||
"dungeon_medium_6",
|
||||
"dungeon_medium_7",
|
||||
"dungeon_medium_8",
|
||||
"dungeon_medium_9",
|
||||
"dungeon_medium_10",
|
||||
"dungeon_small_1",
|
||||
"dungeon_small_2",
|
||||
"dungeon_small_3",
|
||||
"dungeon_small_4"
|
||||
],
|
||||
"spawn_towers": ["spawn_building_space_1"],
|
||||
"dungeon_region": [81, 81],
|
||||
"dungeon_chance": 0.333,
|
||||
"base_resources": {
|
||||
"rocks": {
|
||||
"per": 100
|
||||
}
|
||||
},
|
||||
"ore_deposits": {
|
||||
"ground/iron": {
|
||||
"per": 1900,
|
||||
"min_size": 6,
|
||||
"max_size": 10,
|
||||
"min_depth": 0.2
|
||||
},
|
||||
"ground/copper": {
|
||||
"per": 2000,
|
||||
"min_size": 6,
|
||||
"max_size": 10,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.7
|
||||
},
|
||||
"ground/zinc": {
|
||||
"per": 2000,
|
||||
"min_size": 5,
|
||||
"max_size": 11,
|
||||
"min_depth": 0.4,
|
||||
"max_depth": 0.9
|
||||
},
|
||||
"ground/quartz": {
|
||||
"per": 3500,
|
||||
"min_size": 5,
|
||||
"max_size": 12,
|
||||
"min_depth": 0.5
|
||||
},
|
||||
"ground/platinum": {
|
||||
"per": 85000,
|
||||
"min_size": 3,
|
||||
"max_size": 5,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.9
|
||||
}
|
||||
},
|
||||
"cave_types": {
|
||||
"empty": {
|
||||
"min_size": 150,
|
||||
"frequency": 10
|
||||
},
|
||||
"hatchery": {
|
||||
"max_size": 300,
|
||||
"frequency": 8,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/terrapus-egg"],
|
||||
"mods": {
|
||||
"ground/terrapus-egg": {
|
||||
"0": 1,
|
||||
"1": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"acid": {
|
||||
"max_size": 200,
|
||||
"min_depth": 0.2,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 6,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "fill",
|
||||
"item": "liquid/acid",
|
||||
"liquid": true
|
||||
},
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.1,
|
||||
"items": {
|
||||
"vegetation/mushroom-acid": 16,
|
||||
"vegetation/mushroom-acid-tall": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 100,
|
||||
"min_depth": 0.3,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-blue-1": 16,
|
||||
"ground/crystal-blue-3": 16,
|
||||
"ground/crystal-blue-2": 4,
|
||||
"ground/crystal-blue-4": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"rare_crystal": {
|
||||
"min_size": 30,
|
||||
"max_size": 80,
|
||||
"min_depth": 0.5,
|
||||
"max_depth": 0.9,
|
||||
"frequency": 1,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"single_type": true,
|
||||
"item_spawn_chance": 0.07,
|
||||
"items": {
|
||||
"ground/crystal-rainbow": 1,
|
||||
"ground/onyx": 8,
|
||||
"ground/crystal-white-large": 18,
|
||||
"ground/crystal-purple-1": 30,
|
||||
"ground/crystal-white-small": 50
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ruins": {
|
||||
"max_size": 170,
|
||||
"min_depth": 0.2,
|
||||
"max_depth": 0.7,
|
||||
"frequency": 9,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "structure",
|
||||
"prefabs": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"bat_cave": {
|
||||
"max_depth": 0.5,
|
||||
"frequency": 5,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/guano"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"salt": {
|
||||
"min_depth": 0.2,
|
||||
"frequency": 6,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": ["ground/salt-crystal"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"graveyard": {
|
||||
"min_size": 15,
|
||||
"max_size": 75,
|
||||
"min_depth": 0.1,
|
||||
"max_depth": 0.4,
|
||||
"frequency": 2,
|
||||
"decorators": [
|
||||
{
|
||||
"type": "floor",
|
||||
"item_spawn_chance": 0.175,
|
||||
"items": {
|
||||
"rubble/gravestone": 4,
|
||||
"rubble/bone-pile": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue