Merge pull request #164 from TerraForged/master
update branch to latest
This commit is contained in:
commit
bfb726d2d5
@ -1 +1 @@
|
|||||||
Subproject commit 5af4aff86ab3e3a362346bb91076d2bdb0206ca7
|
Subproject commit 0da0d13c3dc8426b18a55107b42986e9d66387f1
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.terraforged.core.region.gen;
|
||||||
|
|
||||||
|
import com.terraforged.core.region.Region;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class FutureRegion implements Future<Region>, Callable<Region> {
|
||||||
|
|
||||||
|
private final int rx;
|
||||||
|
private final int rz;
|
||||||
|
private final RegionGenerator generator;
|
||||||
|
|
||||||
|
private volatile Region result;
|
||||||
|
|
||||||
|
public FutureRegion(int rx, int rz, RegionGenerator generator) {
|
||||||
|
this.rx = rx;
|
||||||
|
this.rz = rz;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Region call() {
|
||||||
|
Region region = result;
|
||||||
|
if (region == null) {
|
||||||
|
region = generator.generateRegion(rx, rz);
|
||||||
|
result = region;
|
||||||
|
}
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDone() {
|
||||||
|
return result != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Region get() {
|
||||||
|
return call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Region get(long timeout, TimeUnit unit) {
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.terraforged.core.region.gen;
|
||||||
|
|
||||||
|
import com.terraforged.core.region.Region;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class FutureRegionZoom implements Future<Region>, Callable<Region> {
|
||||||
|
|
||||||
|
private final float cx;
|
||||||
|
private final float cz;
|
||||||
|
private final float zoom;
|
||||||
|
private final boolean filters;
|
||||||
|
private final RegionGenerator generator;
|
||||||
|
|
||||||
|
private volatile Region result;
|
||||||
|
|
||||||
|
public FutureRegionZoom(float cx, float cz, float zoom, boolean filters, RegionGenerator generator) {
|
||||||
|
this.cx = cx;
|
||||||
|
this.cz = cz;
|
||||||
|
this.zoom = zoom;
|
||||||
|
this.filters = filters;
|
||||||
|
this.generator = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Region call() {
|
||||||
|
Region region = result;
|
||||||
|
if (region == null) {
|
||||||
|
region = generator.generateRegion(cx, cz, zoom, filters);
|
||||||
|
result = region;
|
||||||
|
}
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDone() {
|
||||||
|
return result != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Region get() {
|
||||||
|
return call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Region get(long timeout, TimeUnit unit) {
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
}
|
@ -73,7 +73,7 @@ public class RegionCache implements RegionExtent, Disposable.Listener<Region> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Region getRegion(int regionX, int regionZ) {
|
public Region getRegion(int regionX, int regionZ) {
|
||||||
Region region = queueRegion(regionX, regionZ).get();
|
Region region = computeRegion(regionX, regionZ).get();
|
||||||
|
|
||||||
if (queuing) {
|
if (queuing) {
|
||||||
queueNeighbours(regionX, regionZ);
|
queueNeighbours(regionX, regionZ);
|
||||||
@ -82,9 +82,14 @@ public class RegionCache implements RegionExtent, Disposable.Listener<Region> {
|
|||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CacheEntry<Region> computeRegion(int regionX, int regionZ) {
|
||||||
|
long id = NoiseUtil.seed(regionX, regionZ);
|
||||||
|
return cache.computeIfAbsent(id, l -> generator.compute(regionX, regionZ));
|
||||||
|
}
|
||||||
|
|
||||||
public CacheEntry<Region> queueRegion(int regionX, int regionZ) {
|
public CacheEntry<Region> queueRegion(int regionX, int regionZ) {
|
||||||
long id = NoiseUtil.seed(regionX, regionZ);
|
long id = NoiseUtil.seed(regionX, regionZ);
|
||||||
return cache.computeIfAbsent(id, l -> generator.generateCached(regionX, regionZ));
|
return cache.computeIfAbsent(id, l -> generator.queue(regionX, regionZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void queueNeighbours(int regionX, int regionZ) {
|
private void queueNeighbours(int regionX, int regionZ) {
|
||||||
|
@ -97,8 +97,20 @@ public class RegionGenerator implements RegionExtent {
|
|||||||
return CompletableFuture.supplyAsync(() -> generateRegion(centerX, centerZ, zoom, filter), threadPool);
|
return CompletableFuture.supplyAsync(() -> generateRegion(centerX, centerZ, zoom, filter), threadPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CacheEntry<Region> generateCached(int regionX, int regionZ) {
|
public CacheEntry<Region> compute(int regionX, int regionZ) {
|
||||||
return CacheEntry.supplyAsync(() -> generateRegion(regionX, regionZ), threadPool);
|
return CacheEntry.supply(new FutureRegion(regionX, regionZ, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheEntry<Region> compute(float centerX, float centerZ, float zoom, boolean filter) {
|
||||||
|
return CacheEntry.supply(new FutureRegionZoom(centerX, centerZ, zoom, filter, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheEntry<Region> queue(int regionX, int regionZ) {
|
||||||
|
return CacheEntry.supplyAsync(new FutureRegion(regionX, regionZ, this), threadPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheEntry<Region> queue(float centerX, float centerZ, float zoom, boolean filter) {
|
||||||
|
return CacheEntry.supplyAsync(new FutureRegionZoom(centerX, centerZ, zoom, filter, this), threadPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Region generateRegion(int regionX, int regionZ) {
|
public Region generateRegion(int regionX, int regionZ) {
|
||||||
|
@ -3,14 +3,16 @@ package com.terraforged.core.util.concurrent.cache;
|
|||||||
import com.terraforged.core.util.concurrent.ThreadPool;
|
import com.terraforged.core.util.concurrent.ThreadPool;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ForkJoinTask;
|
import java.util.concurrent.ForkJoinTask;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
public class CacheEntry<T> implements ExpiringEntry {
|
public class CacheEntry<T> implements ExpiringEntry {
|
||||||
|
|
||||||
private volatile long timestamp;
|
private volatile long timestamp;
|
||||||
private final ForkJoinTask<T> task;
|
private final Future<T> task;
|
||||||
|
|
||||||
public CacheEntry(ForkJoinTask<T> task) {
|
public CacheEntry(Future<T> task) {
|
||||||
this.task = task;
|
this.task = task;
|
||||||
this.timestamp = System.currentTimeMillis();
|
this.timestamp = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
@ -25,7 +27,19 @@ public class CacheEntry<T> implements ExpiringEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public T get() {
|
public T get() {
|
||||||
return task.join();
|
if (task instanceof ForkJoinTask) {
|
||||||
|
return ((ForkJoinTask<T>) task).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return task.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> CacheEntry<T> supply(Future<T> future) {
|
||||||
|
return new CacheEntry<>(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CacheEntry<T> supplyAsync(Callable<T> callable, ThreadPool executor) {
|
public static <T> CacheEntry<T> supplyAsync(Callable<T> callable, ThreadPool executor) {
|
||||||
|
@ -163,9 +163,8 @@ public class River extends TerrainPopulator {
|
|||||||
// lerp the position's height to the riverbank height
|
// lerp the position's height to the riverbank height
|
||||||
if (cell.value > bankHeight) {
|
if (cell.value > bankHeight) {
|
||||||
cell.value = NoiseUtil.lerp(cell.value, bankHeight, valleyAlpha);
|
cell.value = NoiseUtil.lerp(cell.value, bankHeight, valleyAlpha);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean carveBanks(Cell<Terrain> cell, float banksAlpha, float bedHeight) {
|
private boolean carveBanks(Cell<Terrain> cell, float banksAlpha, float bedHeight) {
|
||||||
|
@ -63,10 +63,22 @@ public class BiomeProvider extends AbstractBiomeProvider {
|
|||||||
this.modifierManager = SetupHooks.setup(new BiomeModifierManager(context, biomeMap), context.copy());
|
this.modifierManager = SetupHooks.setup(new BiomeModifierManager(context, biomeMap), context.copy());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TerraContext getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lookupPos(int x, int z, Cell<Terrain> cell) {
|
||||||
|
worldLookup.applyCell(cell, x, z);
|
||||||
|
}
|
||||||
|
|
||||||
public Cell<Terrain> lookupPos(int x, int z) {
|
public Cell<Terrain> lookupPos(int x, int z) {
|
||||||
return worldLookup.getCell(x, z);
|
return worldLookup.getCell(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canSpawnAt(Cell<Terrain> cell) {
|
||||||
|
return cell.tag != context.terrain.ocean && cell.tag != context.terrain.deepOcean && cell.value > context.levels.ground;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getNoiseBiome(int x, int y, int z) {
|
public Biome getNoiseBiome(int x, int y, int z) {
|
||||||
x = (x << 2);
|
x = (x << 2);
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.terraforged.mod.biome.spawn;
|
||||||
|
|
||||||
|
import com.terraforged.mod.Log;
|
||||||
|
import com.terraforged.mod.biome.provider.BiomeProvider;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||||
|
import net.minecraft.world.gen.feature.Feature;
|
||||||
|
import net.minecraft.world.gen.feature.IFeatureConfig;
|
||||||
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
|
||||||
|
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||||
|
public class SpawnHandler {
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void createSpawn(WorldEvent.CreateSpawnPosition event) {
|
||||||
|
if (event.getWorld() instanceof ServerWorld) {
|
||||||
|
ServerWorld world =(ServerWorld) event.getWorld();
|
||||||
|
if (world.getChunkProvider().getChunkGenerator().getBiomeProvider() instanceof BiomeProvider) {
|
||||||
|
Log.info("Searching for world spawn position");
|
||||||
|
BiomeProvider provider = (BiomeProvider) world.getChunkProvider().getChunkGenerator().getBiomeProvider();
|
||||||
|
SpawnSearch search = new SpawnSearch(BlockPos.ZERO, provider);
|
||||||
|
BlockPos spawn = search.get();
|
||||||
|
|
||||||
|
Log.info("Setting world spawn: {}", spawn);
|
||||||
|
event.setCanceled(true);
|
||||||
|
event.getWorld().getWorldInfo().setSpawn(spawn);
|
||||||
|
|
||||||
|
if (event.getSettings().isBonusChestEnabled()) {
|
||||||
|
Log.info("Generating bonus chest");
|
||||||
|
createBonusChest(world, spawn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createBonusChest(ServerWorld world, BlockPos pos) {
|
||||||
|
ConfiguredFeature<?, ?> chest = Feature.BONUS_CHEST.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG);
|
||||||
|
chest.place(world, world.getChunkProvider().getChunkGenerator(), world.rand, pos);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.terraforged.mod.biome.spawn;
|
||||||
|
|
||||||
|
import com.terraforged.core.cell.Cell;
|
||||||
|
import com.terraforged.core.world.terrain.Terrain;
|
||||||
|
import com.terraforged.mod.Log;
|
||||||
|
import com.terraforged.mod.biome.provider.BiomeProvider;
|
||||||
|
import com.terraforged.mod.command.search.Search;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
public class SpawnSearch extends Search {
|
||||||
|
|
||||||
|
private final BiomeProvider biomeProvider;
|
||||||
|
private final Cell<Terrain> cell = new Cell<>();
|
||||||
|
|
||||||
|
public SpawnSearch(BlockPos center, BiomeProvider biomeProvider) {
|
||||||
|
super(center, 0, 2048);
|
||||||
|
this.biomeProvider = biomeProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpacing() {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(BlockPos pos) {
|
||||||
|
biomeProvider.lookupPos(pos.getX(), pos.getZ(), cell);
|
||||||
|
return biomeProvider.canSpawnAt(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BlockPos success(BlockPos.Mutable pos) {
|
||||||
|
pos.setY(biomeProvider.getContext().levels.scale(cell.value));
|
||||||
|
Log.info("Found valid spawn position: {}", pos);
|
||||||
|
return super.success(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BlockPos fail(BlockPos pos) {
|
||||||
|
Log.info("Unable to find valid spawn position, defaulting x=0, z=0");
|
||||||
|
return new BlockPos(0, biomeProvider.getContext().levels.groundLevel, 0);
|
||||||
|
}
|
||||||
|
}
|
@ -395,7 +395,7 @@ public class TerraChunkGenerator extends ObfHelperChunkGenerator<GenerationSetti
|
|||||||
.legacy(context.terraSettings.version == 0)
|
.legacy(context.terraSettings.version == 0)
|
||||||
.pool(ThreadPool.getPool())
|
.pool(ThreadPool.getPool())
|
||||||
.factory(context.factory)
|
.factory(context.factory)
|
||||||
.size(4, 2)
|
.size(3, 2)
|
||||||
.build()
|
.build()
|
||||||
.toCache(false);
|
.toCache(false);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.terraforged.mod.command;
|
||||||
|
|
||||||
|
public class Permissions {
|
||||||
|
|
||||||
|
public static final String QUERY = "terraforged.command.terra.query";
|
||||||
|
public static final String DEBUG = "terraforged.command.terra.debug";
|
||||||
|
public static final String DATA = "terraforged.command.terra.data";
|
||||||
|
public static final String DEFAULTS = "terraforged.command.terra.defaults";
|
||||||
|
public static final String LOCATE = "terraforged.command.terra.locate";
|
||||||
|
}
|
@ -27,7 +27,6 @@ package com.terraforged.mod.command;
|
|||||||
|
|
||||||
import com.mojang.brigadier.Command;
|
import com.mojang.brigadier.Command;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
@ -49,7 +48,6 @@ import com.terraforged.mod.data.DataGen;
|
|||||||
import com.terraforged.mod.settings.SettingsHelper;
|
import com.terraforged.mod.settings.SettingsHelper;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.command.CommandSource;
|
||||||
import net.minecraft.command.Commands;
|
import net.minecraft.command.Commands;
|
||||||
import net.minecraft.command.arguments.ArgumentSerializer;
|
|
||||||
import net.minecraft.command.arguments.ArgumentTypes;
|
import net.minecraft.command.arguments.ArgumentTypes;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
@ -70,18 +68,21 @@ import net.minecraft.world.gen.ChunkGenerator;
|
|||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||||
|
import net.minecraftforge.server.permission.DefaultPermissionLevel;
|
||||||
|
import net.minecraftforge.server.permission.PermissionAPI;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
|
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||||
public class TerraCommand {
|
public class TerraCommand {
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
ArgumentTypes.register("terraforged:biome", BiomeArgType.class, new ArgumentSerializer<>(BiomeArgType::new));
|
ArgumentTypes.register("terraforged:biome", BiomeArgType.class, new BiomeArgType.Serializer());
|
||||||
ArgumentTypes.register("terraforged:terrain", TerrainArgType.class, new ArgumentSerializer<>(TerrainArgType::new));
|
ArgumentTypes.register("terraforged:terrain", TerrainArgType.class, new TerrainArgType.Serializer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
@ -91,31 +92,59 @@ public class TerraCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void register(CommandDispatcher<CommandSource> dispatcher) {
|
public static void register(CommandDispatcher<CommandSource> dispatcher) {
|
||||||
dispatcher.register(command());
|
registerSimple(dispatcher);
|
||||||
|
registerLocate(dispatcher);
|
||||||
|
PermissionAPI.registerNode(Permissions.QUERY, DefaultPermissionLevel.OP, "Allows use of the query command");
|
||||||
|
PermissionAPI.registerNode(Permissions.DATA, DefaultPermissionLevel.OP, "Allows use of the data command");
|
||||||
|
PermissionAPI.registerNode(Permissions.DEFAULTS, DefaultPermissionLevel.OP, "Allows use of the defaults command");
|
||||||
|
PermissionAPI.registerNode(Permissions.DEBUG, DefaultPermissionLevel.OP, "Allows use of the debug command");
|
||||||
|
PermissionAPI.registerNode(Permissions.LOCATE, DefaultPermissionLevel.OP, "Allows use of the locate command");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LiteralArgumentBuilder<CommandSource> command() {
|
private static void registerSimple(CommandDispatcher<CommandSource> dispatcher) {
|
||||||
return Commands.literal("terra")
|
dispatcher.register(Commands.literal("terra")
|
||||||
.requires(source -> source.hasPermissionLevel(2))
|
|
||||||
.then(Commands.literal("query")
|
.then(Commands.literal("query")
|
||||||
|
.requires(perm(Permissions.QUERY))
|
||||||
.executes(TerraCommand::query))
|
.executes(TerraCommand::query))
|
||||||
.then(Commands.literal("data")
|
.then(Commands.literal("data")
|
||||||
|
.requires(perm(Permissions.DATA))
|
||||||
.then(Commands.literal("dump")
|
.then(Commands.literal("dump")
|
||||||
.executes(TerraCommand::dump)))
|
.executes(TerraCommand::dump)))
|
||||||
.then(Commands.literal("defaults")
|
.then(Commands.literal("defaults")
|
||||||
|
.requires(perm(Permissions.DEFAULTS))
|
||||||
.then(Commands.literal("set")
|
.then(Commands.literal("set")
|
||||||
.executes(TerraCommand::setDefaults)))
|
.executes(TerraCommand::setDefaults)))
|
||||||
.then(Commands.literal("debug")
|
.then(Commands.literal("debug")
|
||||||
.executes(TerraCommand::debugBiome))
|
.requires(perm(Permissions.DEBUG))
|
||||||
|
.executes(TerraCommand::debugBiome)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerLocate(CommandDispatcher<CommandSource> dispatcher) {
|
||||||
|
dispatcher.register(Commands.literal("terra")
|
||||||
.then(Commands.literal("locate")
|
.then(Commands.literal("locate")
|
||||||
|
.requires(perm(Permissions.LOCATE))
|
||||||
.then(Commands.argument("biome", BiomeArgType.biome())
|
.then(Commands.argument("biome", BiomeArgType.biome())
|
||||||
.executes(TerraCommand::findBiome)
|
.executes(TerraCommand::findBiome))));
|
||||||
.then(Commands.argument("terrain", TerrainArgType.terrain())
|
|
||||||
.executes(TerraCommand::findTerrainAndBiome)))
|
dispatcher.register(Commands.literal("terra")
|
||||||
|
.then(Commands.literal("locate")
|
||||||
|
.requires(perm(Permissions.LOCATE))
|
||||||
|
.then(Commands.argument("terrain", TerrainArgType.terrain())
|
||||||
|
.executes(TerraCommand::findTerrain))));
|
||||||
|
|
||||||
|
dispatcher.register(Commands.literal("terra")
|
||||||
|
.then(Commands.literal("locate")
|
||||||
|
.requires(perm(Permissions.LOCATE))
|
||||||
|
.then(Commands.argument("biome", BiomeArgType.biome())
|
||||||
|
.then(Commands.argument("terrain", TerrainArgType.terrain())
|
||||||
|
.executes(TerraCommand::findTerrainAndBiome)))));
|
||||||
|
|
||||||
|
dispatcher.register(Commands.literal("terra")
|
||||||
|
.then(Commands.literal("locate")
|
||||||
|
.requires(perm(Permissions.LOCATE))
|
||||||
.then(Commands.argument("terrain", TerrainArgType.terrain())
|
.then(Commands.argument("terrain", TerrainArgType.terrain())
|
||||||
.executes(TerraCommand::findTerrain)
|
|
||||||
.then(Commands.argument("biome", BiomeArgType.biome())
|
.then(Commands.argument("biome", BiomeArgType.biome())
|
||||||
.executes(TerraCommand::findTerrainAndBiome))));
|
.executes(TerraCommand::findTerrainAndBiome)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int query(CommandContext<CommandSource> context) throws CommandSyntaxException {
|
private static int query(CommandContext<CommandSource> context) throws CommandSyntaxException {
|
||||||
@ -194,7 +223,7 @@ public class TerraCommand {
|
|||||||
WorldGenerator worldGenerator = terraContext.factory.get();
|
WorldGenerator worldGenerator = terraContext.factory.get();
|
||||||
Search search = new TerrainSearchTask(pos, worldGenerator, target);
|
Search search = new TerrainSearchTask(pos, worldGenerator, target);
|
||||||
doSearch(server, playerID, search);
|
doSearch(server, playerID, search);
|
||||||
context.getSource().sendFeedback(new StringTextComponent("Searching..."), false);
|
context.getSource().sendFeedback(new StringTextComponent("Locating terrain..."), false);
|
||||||
|
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -213,7 +242,7 @@ public class TerraCommand {
|
|||||||
IWorldReader reader = context.getSource().asPlayer().getServerWorld();
|
IWorldReader reader = context.getSource().asPlayer().getServerWorld();
|
||||||
Search search = new BiomeSearchTask(pos, reader, biome);
|
Search search = new BiomeSearchTask(pos, reader, biome);
|
||||||
doSearch(server, playerID, search);
|
doSearch(server, playerID, search);
|
||||||
context.getSource().sendFeedback(new StringTextComponent("Searching..."), false);
|
context.getSource().sendFeedback(new StringTextComponent("Locating biome..."), false);
|
||||||
|
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -237,7 +266,7 @@ public class TerraCommand {
|
|||||||
Search terrainSearch = new TerrainSearchTask(pos, worldGenerator, target);
|
Search terrainSearch = new TerrainSearchTask(pos, worldGenerator, target);
|
||||||
Search search = new BothSearchTask(pos, biomeSearch, terrainSearch);
|
Search search = new BothSearchTask(pos, biomeSearch, terrainSearch);
|
||||||
doSearch(server, playerID, search);
|
doSearch(server, playerID, search);
|
||||||
context.getSource().sendFeedback(new StringTextComponent("Searching..."), false);
|
context.getSource().sendFeedback(new StringTextComponent("Locating biome & terrain..."), false);
|
||||||
|
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -275,14 +304,31 @@ public class TerraCommand {
|
|||||||
// the terrain parsed from the command will not be the same instance as used in the
|
// the terrain parsed from the command will not be the same instance as used in the
|
||||||
// world generator, so find the matching instance by name
|
// world generator, so find the matching instance by name
|
||||||
private static Terrain getTerrainInstance(Terrain find, Terrains terrains) {
|
private static Terrain getTerrainInstance(Terrain find, Terrains terrains) {
|
||||||
|
// search for exact match first
|
||||||
for (Terrain t : terrains.index) {
|
for (Terrain t : terrains.index) {
|
||||||
if (t.getName().equals(find.getName())) {
|
if (t.getName().equals(find.getName())) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// find a mixed terrain as a fallback
|
||||||
|
for (Terrain t : terrains.index) {
|
||||||
|
if (t.getName().contains("-") && t.getName().contains(find.getName())) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
return find;
|
return find;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Predicate<CommandSource> perm(String node) {
|
||||||
|
return source -> {
|
||||||
|
try {
|
||||||
|
return PermissionAPI.hasPermission(source.asPlayer(), node);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return source.hasPermissionLevel(2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static BiomeProvider getBiomeProvider(CommandContext<CommandSource> context) {
|
private static BiomeProvider getBiomeProvider(CommandContext<CommandSource> context) {
|
||||||
return (BiomeProvider) context.getSource().getWorld().getChunkProvider().getChunkGenerator().getBiomeProvider();
|
return (BiomeProvider) context.getSource().getWorld().getChunkProvider().getChunkGenerator().getBiomeProvider();
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
package com.terraforged.mod.command.arg;
|
package com.terraforged.mod.command.arg;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
@ -33,8 +34,9 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
|||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
import net.minecraft.command.ISuggestionProvider;
|
import net.minecraft.command.ISuggestionProvider;
|
||||||
|
import net.minecraft.command.arguments.IArgumentSerializer;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.registry.Registry;
|
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
@ -45,9 +47,28 @@ public class BiomeArgType implements ArgumentType<Biome> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome parse(StringReader reader) throws CommandSyntaxException {
|
public Biome parse(StringReader reader) throws CommandSyntaxException {
|
||||||
ResourceLocation resourcelocation = ResourceLocation.read(reader);
|
int cursor = reader.getCursor();
|
||||||
return Registry.BIOME.getValue(resourcelocation)
|
String raw = reader.getString().substring(cursor);
|
||||||
.orElseThrow(() -> createException("Invalid biome", "%s is not a valid biome", resourcelocation));
|
|
||||||
|
if (raw.indexOf(':') == -1) {
|
||||||
|
reader.setCursor(cursor);
|
||||||
|
throw createException("Invalid biome", "%s is not a valid biome", raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLocation resourcelocation = ResourceLocation.tryCreate(raw);
|
||||||
|
if (resourcelocation == null) {
|
||||||
|
reader.setCursor(cursor);
|
||||||
|
throw createException("Invalid biome", "%s is not a valid biome", raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ForgeRegistries.BIOMES.containsKey(resourcelocation)) {
|
||||||
|
reader.setCursor(cursor);
|
||||||
|
throw createException("Invalid biome", "%s is not a valid biome", resourcelocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.setCursor(reader.getString().length());
|
||||||
|
|
||||||
|
return ForgeRegistries.BIOMES.getValue(resourcelocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,4 +90,22 @@ public class BiomeArgType implements ArgumentType<Biome> {
|
|||||||
public static <S> Biome getBiome(CommandContext<S> context, String name) {
|
public static <S> Biome getBiome(CommandContext<S> context, String name) {
|
||||||
return context.getArgument(name, Biome.class);
|
return context.getArgument(name, Biome.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Serializer implements IArgumentSerializer<BiomeArgType> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(BiomeArgType type, PacketBuffer buffer) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeArgType read(PacketBuffer buffer) {
|
||||||
|
return new BiomeArgType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(BiomeArgType type, JsonObject json) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
package com.terraforged.mod.command.arg;
|
package com.terraforged.mod.command.arg;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
@ -32,8 +33,12 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
import com.terraforged.core.settings.Settings;
|
||||||
import com.terraforged.core.world.terrain.Terrain;
|
import com.terraforged.core.world.terrain.Terrain;
|
||||||
|
import com.terraforged.core.world.terrain.Terrains;
|
||||||
import net.minecraft.command.ISuggestionProvider;
|
import net.minecraft.command.ISuggestionProvider;
|
||||||
|
import net.minecraft.command.arguments.IArgumentSerializer;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -42,7 +47,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
public class TerrainArgType implements ArgumentType<Terrain> {
|
public class TerrainArgType implements ArgumentType<Terrain> {
|
||||||
|
|
||||||
private final List<Terrain> terrains = Terrain.getRegistered();
|
private final List<Terrain> terrains = createTerrainList();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terrain parse(StringReader reader) throws CommandSyntaxException {
|
public Terrain parse(StringReader reader) throws CommandSyntaxException {
|
||||||
@ -76,4 +81,26 @@ public class TerrainArgType implements ArgumentType<Terrain> {
|
|||||||
new StringTextComponent(String.format(message, args))
|
new StringTextComponent(String.format(message, args))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<Terrain> createTerrainList() {
|
||||||
|
return Terrains.create(new Settings()).index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Serializer implements IArgumentSerializer<TerrainArgType> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(TerrainArgType type, PacketBuffer buffer) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerrainArgType read(PacketBuffer buffer) {
|
||||||
|
return new TerrainArgType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(TerrainArgType type, JsonObject json) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,14 @@ public abstract class Search implements Supplier<BlockPos> {
|
|||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected BlockPos success(BlockPos.Mutable pos) {
|
||||||
|
return pos.toImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockPos fail(BlockPos pos) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockPos get() {
|
public BlockPos get() {
|
||||||
int radius = maxRadius;
|
int radius = maxRadius;
|
||||||
@ -60,7 +68,7 @@ public abstract class Search implements Supplier<BlockPos> {
|
|||||||
pos.setPos(center.getX() + (x * getSpacing()), center.getY(), center.getZ() + (z * getSpacing()));
|
pos.setPos(center.getX() + (x * getSpacing()), center.getY(), center.getZ() + (z * getSpacing()));
|
||||||
if (center.distanceSq(pos) >= minRadius2) {
|
if (center.distanceSq(pos) >= minRadius2) {
|
||||||
if (test(pos)) {
|
if (test(pos)) {
|
||||||
return pos.toImmutable();
|
return success(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +83,7 @@ public abstract class Search implements Supplier<BlockPos> {
|
|||||||
z += dz;
|
z += dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BlockPos.ZERO;
|
return fail(BlockPos.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean test(BlockPos pos);
|
public abstract boolean test(BlockPos pos);
|
||||||
|
@ -30,12 +30,24 @@ import com.google.gson.JsonElement;
|
|||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.mojang.datafixers.Dynamic;
|
import com.mojang.datafixers.Dynamic;
|
||||||
import com.mojang.datafixers.types.JsonOps;
|
import com.mojang.datafixers.types.JsonOps;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
import net.minecraft.world.gen.GenerationStage;
|
import net.minecraft.world.gen.GenerationStage;
|
||||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||||
|
import net.minecraft.world.gen.feature.IFeatureConfig;
|
||||||
|
import net.minecraft.world.gen.feature.jigsaw.JigsawManager;
|
||||||
|
import net.minecraft.world.gen.feature.jigsaw.JigsawPattern;
|
||||||
|
import net.minecraft.world.gen.feature.jigsaw.JigsawPatternRegistry;
|
||||||
|
import net.minecraft.world.gen.feature.jigsaw.JigsawPiece;
|
||||||
|
import net.minecraft.world.gen.feature.structure.Structure;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
public class WorldGenFeatures extends DataGen {
|
public class WorldGenFeatures extends DataGen {
|
||||||
|
|
||||||
@ -43,7 +55,9 @@ public class WorldGenFeatures extends DataGen {
|
|||||||
if (dataDir.exists() || dataDir.mkdirs()) {
|
if (dataDir.exists() || dataDir.mkdirs()) {
|
||||||
for (Biome biome : ForgeRegistries.BIOMES) {
|
for (Biome biome : ForgeRegistries.BIOMES) {
|
||||||
genBiomeFeatures(dataDir, biome);
|
genBiomeFeatures(dataDir, biome);
|
||||||
|
genBiomeStructures(dataDir, biome);
|
||||||
}
|
}
|
||||||
|
genBiomeJigsaws(dataDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,4 +79,55 @@ public class WorldGenFeatures extends DataGen {
|
|||||||
write(root, writer);
|
write(root, writer);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void genBiomeStructures(File dir, Biome biome) {
|
||||||
|
write(new File(dir, getJsonPath("structures", biome.getRegistryName())), writer -> {
|
||||||
|
JsonObject root = new JsonObject();
|
||||||
|
for (Map.Entry<String, Structure<?>> e : Structure.STRUCTURES.entrySet()) {
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
IFeatureConfig config = biome.getStructureConfig(e.getValue());
|
||||||
|
if (config == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
JsonElement element = config.serialize(JsonOps.INSTANCE).getValue();
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.addProperty("structure", e.getValue().getRegistryName() + "");
|
||||||
|
object.add("config", element);
|
||||||
|
array.add(object);
|
||||||
|
}
|
||||||
|
write(root, writer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void genBiomeJigsaws(File dir) {
|
||||||
|
Random random = new Random();
|
||||||
|
write(new File(dir, "jigsaws.json"), writer -> {
|
||||||
|
JsonObject root = new JsonObject();
|
||||||
|
for (Map.Entry<ResourceLocation, JigsawPattern> e : getJigsawRegistry().entrySet()) {
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
List<JigsawPiece> pieces = e.getValue().getShuffledPieces(random);
|
||||||
|
for (JigsawPiece piece : pieces) {
|
||||||
|
JsonElement element = piece.serialize(JsonOps.INSTANCE).getValue();
|
||||||
|
array.add(element);
|
||||||
|
}
|
||||||
|
root.add(e.getKey().toString(), array);
|
||||||
|
}
|
||||||
|
write(root, writer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<ResourceLocation, JigsawPattern> getJigsawRegistry() {
|
||||||
|
try {
|
||||||
|
for (Field field : JigsawPatternRegistry.class.getDeclaredFields()) {
|
||||||
|
if (field.getType() == Map.class) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object value = field.get(JigsawManager.REGISTRY);
|
||||||
|
return (Map<ResourceLocation, JigsawPattern>) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import net.minecraft.world.gen.feature.Feature;
|
|||||||
import net.minecraft.world.gen.feature.NoFeatureConfig;
|
import net.minecraft.world.gen.feature.NoFeatureConfig;
|
||||||
import net.minecraft.world.server.ServerWorld;
|
import net.minecraft.world.server.ServerWorld;
|
||||||
import net.minecraftforge.event.world.SaplingGrowTreeEvent;
|
import net.minecraftforge.event.world.SaplingGrowTreeEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.EventPriority;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ public class SaplingListener {
|
|||||||
{new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1), new Vec3i(0, 0, 1)},
|
{new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1), new Vec3i(0, 0, 1)},
|
||||||
};
|
};
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||||
public static void onTreeGrow(SaplingGrowTreeEvent event) {
|
public static void onTreeGrow(SaplingGrowTreeEvent event) {
|
||||||
// ignore if client
|
// ignore if client
|
||||||
if (event.getWorld().isRemote()) {
|
if (event.getWorld().isRemote()) {
|
||||||
|
@ -53,6 +53,6 @@ public class StructurePage extends BasePage {
|
|||||||
@Override
|
@Override
|
||||||
public void init(OverlayScreen parent) {
|
public void init(OverlayScreen parent) {
|
||||||
Column left = getColumn(0);
|
Column left = getColumn(0);
|
||||||
addElements(left.left, left.top, left, structureSettings, false, left.scrollPane::addButton, this::update);
|
addElements(left.left, left.top, left, structureSettings, true, left.scrollPane::addButton, this::update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import com.terraforged.core.region.Region;
|
|||||||
import com.terraforged.core.region.gen.RegionGenerator;
|
import com.terraforged.core.region.gen.RegionGenerator;
|
||||||
import com.terraforged.core.settings.Settings;
|
import com.terraforged.core.settings.Settings;
|
||||||
import com.terraforged.core.util.concurrent.ThreadPool;
|
import com.terraforged.core.util.concurrent.ThreadPool;
|
||||||
|
import com.terraforged.core.util.concurrent.cache.CacheEntry;
|
||||||
import com.terraforged.core.world.GeneratorContext;
|
import com.terraforged.core.world.GeneratorContext;
|
||||||
import com.terraforged.core.world.WorldGeneratorFactory;
|
import com.terraforged.core.world.WorldGeneratorFactory;
|
||||||
import com.terraforged.core.world.terrain.Terrain;
|
import com.terraforged.core.world.terrain.Terrain;
|
||||||
@ -48,8 +49,6 @@ import net.minecraft.nbt.CompoundNBT;
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
public class Preview extends Button {
|
public class Preview extends Button {
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ public class Preview extends Button {
|
|||||||
private int seed;
|
private int seed;
|
||||||
private long lastUpdate = 0L;
|
private long lastUpdate = 0L;
|
||||||
private Settings settings = new Settings();
|
private Settings settings = new Settings();
|
||||||
private Future<Region> task = null;
|
private CacheEntry<Region> task = null;
|
||||||
private Region region = null;
|
private Region region = null;
|
||||||
|
|
||||||
private String[] labels = {"Area: ", "Terrain: ", "Biome: "};
|
private String[] labels = {"Area: ", "Terrain: ", "Biome: "};
|
||||||
@ -131,10 +130,6 @@ public class Preview extends Button {
|
|||||||
try {
|
try {
|
||||||
region = task.get();
|
region = task.get();
|
||||||
render(region);
|
render(region);
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
e.getCause().printStackTrace();
|
|
||||||
} finally {
|
} finally {
|
||||||
task = null;
|
task = null;
|
||||||
}
|
}
|
||||||
@ -195,7 +190,7 @@ public class Preview extends Button {
|
|||||||
texture.updateDynamicTexture();
|
texture.updateDynamicTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Future<Region> generate(Settings settings, CompoundNBT prevSettings) {
|
private CacheEntry<Region> generate(Settings settings, CompoundNBT prevSettings) {
|
||||||
NBTHelper.deserialize(prevSettings, previewSettings);
|
NBTHelper.deserialize(prevSettings, previewSettings);
|
||||||
settings.generator.seed = seed;
|
settings.generator.seed = seed;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
@ -208,7 +203,7 @@ public class Preview extends Button {
|
|||||||
.size(FACTOR, 0)
|
.size(FACTOR, 0)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return renderer.generate(offsetX, offsetZ, 101 - previewSettings.zoom, true);
|
return renderer.queue(offsetX, offsetZ, 101 - previewSettings.zoom, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLegend(int mx ,int my) {
|
private void updateLegend(int mx ,int my) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"biomes": [
|
"biomes": [
|
||||||
"minecraft:jungle",
|
"minecraft:jungle",
|
||||||
|
"minecraft:modified_jungle",
|
||||||
"minecraft:bamboo_jungle"
|
"minecraft:bamboo_jungle"
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"biomes": [
|
"biomes": [
|
||||||
"minecraft:jungle_edge"
|
"minecraft:jungle_edge",
|
||||||
|
"minecraft:modified_jungle_edge"
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
[
|
[
|
||||||
|
@ -1,7 +1,19 @@
|
|||||||
{
|
{
|
||||||
"biomes": [
|
"biomes": [
|
||||||
"minecraft:plains",
|
"minecraft:plains",
|
||||||
"minecraft:river"
|
"minecraft:sunflower_plains",
|
||||||
|
"minecraft:river",
|
||||||
|
"minecraft:frozen_river",
|
||||||
|
"minecraft:ocean",
|
||||||
|
"minecraft:deep_ocean",
|
||||||
|
"minecraft:warm_ocean",
|
||||||
|
"minecraft:deep_warm_ocean",
|
||||||
|
"minecraft:lukewarm_ocean",
|
||||||
|
"minecraft:deep_lukewarm_ocean",
|
||||||
|
"minecraft:cold_ocean",
|
||||||
|
"minecraft:deep_cold_ocean",
|
||||||
|
"minecraft:frozen_ocean",
|
||||||
|
"minecraft:deep_frozen_ocean"
|
||||||
],
|
],
|
||||||
"match": [
|
"match": [
|
||||||
[
|
[
|
||||||
|
Loading…
Reference in New Issue
Block a user