Update search task

This commit is contained in:
dags- 2020-03-08 21:50:10 +00:00
parent 8eca5b6974
commit 7ac2eb773b
10 changed files with 190 additions and 332 deletions

View File

@ -29,7 +29,6 @@ import com.google.common.collect.ImmutableSet;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes; import net.minecraft.world.biome.Biomes;
import net.minecraft.world.biome.ColumnFuzzedBiomeMagnifier;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;

View File

@ -41,12 +41,11 @@ import com.terraforged.mod.chunk.TerraChunkGenerator;
import com.terraforged.mod.chunk.TerraContext; import com.terraforged.mod.chunk.TerraContext;
import com.terraforged.mod.command.arg.BiomeArgType; import com.terraforged.mod.command.arg.BiomeArgType;
import com.terraforged.mod.command.arg.TerrainArgType; import com.terraforged.mod.command.arg.TerrainArgType;
import com.terraforged.mod.command.task.FindBiomeTask; import com.terraforged.mod.command.search.BiomeSearchTask;
import com.terraforged.mod.command.task.FindBothTask; import com.terraforged.mod.command.search.BothSearchTask;
import com.terraforged.mod.command.task.FindTask; import com.terraforged.mod.command.search.Search;
import com.terraforged.mod.command.task.FindTerrainTask; import com.terraforged.mod.command.search.TerrainSearchTask;
import com.terraforged.mod.data.DataGen; import com.terraforged.mod.data.DataGen;
import me.dags.noise.util.Vec2i;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -59,6 +58,7 @@ import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent; import net.minecraft.util.text.event.HoverEvent;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.ChunkGenerator;
@ -69,6 +69,7 @@ import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
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.Supplier;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
public class TerraCommand { public class TerraCommand {
@ -144,8 +145,8 @@ public class TerraCommand {
UUID playerID = context.getSource().asPlayer().getUniqueID(); UUID playerID = context.getSource().asPlayer().getUniqueID();
MinecraftServer server = context.getSource().getServer(); MinecraftServer server = context.getSource().getServer();
WorldGenerator worldGenerator = terraContext.factory.get(); WorldGenerator worldGenerator = terraContext.factory.get();
FindTask task = new FindTerrainTask(pos, target, worldGenerator); Search search = new TerrainSearchTask(pos, worldGenerator, target);
doSearch(server, playerID, task); doSearch(server, playerID, search);
context.getSource().sendFeedback(new StringTextComponent("Searching..."), false); context.getSource().sendFeedback(new StringTextComponent("Searching..."), false);
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
@ -162,10 +163,9 @@ public class TerraCommand {
BlockPos pos = context.getSource().asPlayer().getPosition(); BlockPos pos = context.getSource().asPlayer().getPosition();
UUID playerID = context.getSource().asPlayer().getUniqueID(); UUID playerID = context.getSource().asPlayer().getUniqueID();
MinecraftServer server = context.getSource().getServer(); MinecraftServer server = context.getSource().getServer();
WorldGenerator worldGenerator = terraContext.factory.get(); IWorldReader reader = context.getSource().asPlayer().getServerWorld();
BiomeProvider biomeProvider = getBiomeProvider(context); Search search = new BiomeSearchTask(pos, reader, biome);
FindTask task = new FindBiomeTask(pos, biome, worldGenerator, biomeProvider); doSearch(server, playerID, search);
doSearch(server, playerID, task);
context.getSource().sendFeedback(new StringTextComponent("Searching..."), false); context.getSource().sendFeedback(new StringTextComponent("Searching..."), false);
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
@ -182,25 +182,27 @@ public class TerraCommand {
Terrain target = getTerrainInstance(terrain, terraContext.terrain); Terrain target = getTerrainInstance(terrain, terraContext.terrain);
Biome biome = BiomeArgType.getBiome(context, "biome"); Biome biome = BiomeArgType.getBiome(context, "biome");
BlockPos pos = context.getSource().asPlayer().getPosition(); BlockPos pos = context.getSource().asPlayer().getPosition();
IWorldReader world = context.getSource().asPlayer().getServerWorld();
UUID playerID = context.getSource().asPlayer().getUniqueID(); UUID playerID = context.getSource().asPlayer().getUniqueID();
MinecraftServer server = context.getSource().getServer(); MinecraftServer server = context.getSource().getServer();
WorldGenerator worldGenerator = terraContext.factory.get(); WorldGenerator worldGenerator = terraContext.factory.get();
BiomeProvider biomeProvider = getBiomeProvider(context); Search biomeSearch = new BiomeSearchTask(pos, world, biome);
FindTask task = new FindBothTask(pos, target, biome, worldGenerator, biomeProvider); Search terrainSearch = new TerrainSearchTask(pos, worldGenerator, target);
doSearch(server, playerID, task); Search search = new BothSearchTask(pos, biomeSearch, terrainSearch);
doSearch(server, playerID, search);
context.getSource().sendFeedback(new StringTextComponent("Searching..."), false); context.getSource().sendFeedback(new StringTextComponent("Searching..."), false);
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
private static void doSearch(MinecraftServer server, UUID userId, FindTask task) { private static void doSearch(MinecraftServer server, UUID userId, Supplier<BlockPos> supplier) {
CompletableFuture.supplyAsync(task).thenAccept(pos -> server.deferTask(() -> { CompletableFuture.supplyAsync(supplier).thenAccept(pos -> server.deferTask(() -> {
PlayerEntity player = server.getPlayerList().getPlayerByUUID(userId); PlayerEntity player = server.getPlayerList().getPlayerByUUID(userId);
if (player == null) { if (player == null) {
return; return;
} }
if (pos.x == 0 && pos.y == 0) { if (pos.getX() == 0 && pos.getZ() == 0) {
player.sendMessage(new StringTextComponent("Location not found :[")); player.sendMessage(new StringTextComponent("Location not found :["));
return; return;
} }
@ -245,11 +247,11 @@ public class TerraCommand {
); );
} }
private static ITextComponent createTeleportMessage(Vec2i pos) { private static ITextComponent createTeleportMessage(BlockPos pos) {
return TextComponentUtils.wrapInSquareBrackets(new TranslationTextComponent( return TextComponentUtils.wrapInSquareBrackets(new TranslationTextComponent(
"chat.coordinates", pos.x, "~", pos.y "chat.coordinates", pos.getX(), "~", pos.getZ()
)).applyTextStyle((style) -> style.setColor(TextFormatting.GREEN) )).applyTextStyle((style) -> style.setColor(TextFormatting.GREEN)
.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tp @s " + pos.x + " ~ " + pos.y)) .setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tp @s " + pos.getX() + " ~ " + pos.getZ()))
.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslationTextComponent("chat.coordinates.tooltip"))) .setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TranslationTextComponent("chat.coordinates.tooltip")))
); );
} }

View File

@ -0,0 +1,27 @@
package com.terraforged.mod.command.search;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.biome.Biome;
public class BiomeSearchTask extends Search {
private final Biome biome;
private final IWorldReader reader;
public BiomeSearchTask(BlockPos center, IWorldReader reader, Biome biome) {
super(center, 128);
this.reader = reader;
this.biome = biome;
}
@Override
public int getSpacing() {
return 10;
}
@Override
public boolean test(BlockPos pos) {
return reader.getNoiseBiomeRaw(pos.getX() >> 2, pos.getY(), pos.getZ() >> 2) == biome;
}
}

View File

@ -0,0 +1,27 @@
package com.terraforged.mod.command.search;
import net.minecraft.util.math.BlockPos;
public class BothSearchTask extends Search {
private final int spacing;
private final Search a;
private final Search b;
public BothSearchTask(BlockPos center, Search a, Search b) {
super(center, Math.min(a.getMinRadius(), b.getMinRadius()));
this.spacing = Math.min(a.getSpacing(), b.getSpacing());
this.a = a;
this.b = b;
}
@Override
public int getSpacing() {
return spacing;
}
@Override
public boolean test(BlockPos pos) {
return a.test(pos) && b.test(pos);
}
}

View File

@ -0,0 +1,84 @@
package com.terraforged.mod.command.search;
import net.minecraft.util.math.BlockPos;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public abstract class Search implements Supplier<BlockPos> {
protected static final int MIN_RADIUS = 128;
protected static final int MAX_RADIUS = 24000;
private final BlockPos center;
private final int minRadius;
private final int maxRadius;
private final double minRadius2;
public Search(BlockPos center) {
this(center, MIN_RADIUS);
}
public Search(BlockPos center, int minRadius) {
this(center, minRadius, MAX_RADIUS);
}
public Search(BlockPos center, int minRadius, int maxRadius) {
this.center = center;
this.minRadius = minRadius;
this.minRadius2 = minRadius * minRadius;
this.maxRadius = Math.min(maxRadius, MAX_RADIUS);
}
public int getMinRadius() {
return minRadius;
}
public int getSpacing() {
return 16;
}
@Override
public BlockPos get() {
int radius = maxRadius;
int x = 0;
int z = 0;
int dx = 0;
int dz = -1;
int size = radius + 1 + radius;
long max = (long) size * (long) size;
long timeOut = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(30);
BlockPos.Mutable pos = new BlockPos.Mutable();
for (long i = 0; i < max; i++) {
if (System.currentTimeMillis() > timeOut) {
break;
}
if ((-radius <= x) && (x <= radius) && (-radius <= z) && (z <= radius)) {
pos.setPos(center.getX() + (x * getSpacing()), center.getY(), center.getZ() + (z * getSpacing()));
if (center.distanceSq(pos) >= minRadius2) {
if (test(pos)) {
return pos.toImmutable();
}
}
}
if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z))) {
size = dx;
dx = -dz;
dz = size;
}
x += dx;
z += dz;
}
System.out.println("LAST POS: " + pos);
return BlockPos.ZERO;
}
public abstract boolean test(BlockPos pos);
}

View File

@ -0,0 +1,30 @@
package com.terraforged.mod.command.search;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.WorldGenerator;
import com.terraforged.core.world.terrain.Terrain;
import net.minecraft.util.math.BlockPos;
public class TerrainSearchTask extends Search {
private final Terrain type;
private final WorldGenerator generator;
private final Cell<Terrain> cell = new Cell<>();
public TerrainSearchTask(BlockPos center, WorldGenerator generator, Terrain type) {
super(center, 256);
this.type = type;
this.generator = generator;
}
@Override
public int getSpacing() {
return 20;
}
@Override
public boolean test(BlockPos pos) {
generator.getHeightmap().apply(cell, pos.getX(), pos.getZ());
return cell.tag == type;
}
}

View File

@ -1,86 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.mod.command.task;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.WorldGenerator;
import com.terraforged.core.world.decorator.Decorator;
import com.terraforged.core.world.terrain.Terrain;
import com.terraforged.mod.biome.provider.BiomeProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;
public class FindBiomeTask extends FindTask {
private final Biome biome;
private final WorldGenerator generator;
private final BiomeProvider biomeProvider;
private final Cell<Terrain> cell = new Cell<>();
public FindBiomeTask(BlockPos center, Biome biome, WorldGenerator generator, BiomeProvider biomeProvider) {
this(center, biome, generator, biomeProvider, 100);
}
public FindBiomeTask(BlockPos center, Biome biome, WorldGenerator generator, BiomeProvider biomeProvider, int minRadius) {
super(center, minRadius);
this.biome = biome;
this.generator = generator;
this.biomeProvider = biomeProvider;
}
@Override
protected int transformCoord(int coord) {
return coord * 8;
}
@Override
protected boolean search(int x, int z) {
generator.getHeightmap().apply(cell, x, z);
for (Decorator decorator : generator.getDecorators().getDecorators()) {
if (decorator.apply(cell, x, z)) {
break;
}
}
if (biome.getCategory() != Biome.Category.BEACH && biome.getCategory() != Biome.Category.OCEAN) {
if (cell.continentEdge > 0.4 && cell.continentEdge < 0.45) {
return false;
}
}
return biomeProvider.getBiome(cell, x, z) == biome;
}
protected boolean test(Cell<Terrain> cell, int x, int z) {
if (biome.getCategory() != Biome.Category.BEACH && biome.getCategory() != Biome.Category.OCEAN) {
if (cell.continentEdge > 0.4 && cell.continentEdge < 0.5) {
return false;
}
}
return biomeProvider.getBiome(cell, x, z) == biome;
}
}

View File

@ -1,57 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.mod.command.task;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.WorldGenerator;
import com.terraforged.core.world.terrain.Terrain;
import com.terraforged.mod.biome.provider.BiomeProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;
public class FindBothTask extends FindBiomeTask {
private final Terrain type;
private final WorldGenerator generator;
private final Cell<Terrain> cell = new Cell<>();
public FindBothTask(BlockPos center, Terrain terrain, Biome biome, WorldGenerator generator, BiomeProvider biomeProvider) {
super(center, biome, generator, biomeProvider, 300);
this.type = terrain;
this.generator = generator;
}
@Override
protected boolean search(int x, int z) {
generator.getHeightmap().apply(cell, x, z);
return test(cell, x , z) && super.test(cell, x, z);
}
@Override
protected boolean test(Cell<Terrain> cell, int x, int z) {
return cell.continentEdge > 0.5 && cell.regionEdge > 0.8F && cell.tag == type;
}
}

View File

@ -1,109 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.mod.command.task;
import me.dags.noise.util.Vec2i;
import net.minecraft.util.math.BlockPos;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public abstract class FindTask implements Supplier<Vec2i> {
private static final int RADIUS = 5000;
private final BlockPos center;
private final int minRadius;
private final long timeout;
protected FindTask(BlockPos center, int minRadius) {
this.center = center;
this.minRadius = minRadius;
this.timeout = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(20);
}
@Override
public Vec2i get() {
try {
int x = 0;
int y = 0;
int dx = 0;
int dy = -1;
int radius = RADIUS;
int size = radius + 1 + radius;
int max = size * size;
int minSize = minRadius + 1 + minRadius;
int min = minSize * minSize;
for (int i = 0; i < max; i++) {
if (i % 100 == 0) {
if (System.currentTimeMillis() > timeout) {
break;
}
}
if ((-radius <= x) && (x <= radius) && (-radius <= y) && (y <= radius)) {
int distX = transformCoord(x);
int distY = transformCoord(y);
int dist2 = distX * distX + distY * distY;
if (dist2 > min) {
int posX = center.getX() + distX;
int posZ = center.getZ() + distY;
if (search(posX, posZ)) {
return new Vec2i(posX, posZ);
}
}
}
if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y))) {
size = dx;
dx = -dy;
dy = size;
}
x += dx;
y += dy;
}
return new Vec2i(0, 0);
} catch (Throwable t) {
t.printStackTrace();
return new Vec2i(0, 0);
}
}
protected abstract int transformCoord(int coord);
/**
* Performs the search at the given x,z coordinates and returns true if a result is found
*
* @param x the x block coordinate
* @param z the z block coordinate
* @return the search result
*/
protected abstract boolean search(int x, int z);
}

View File

@ -1,59 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.mod.command.task;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.WorldGenerator;
import com.terraforged.core.world.terrain.Terrain;
import net.minecraft.util.math.BlockPos;
public class FindTerrainTask extends FindTask {
private final Terrain type;
private final WorldGenerator generator;
private final Cell<Terrain> cell = new Cell<>();
public FindTerrainTask(BlockPos center, Terrain type, WorldGenerator generator) {
super(center, 300);
this.type = type;
this.generator = generator;
}
@Override
protected int transformCoord(int coord) {
return coord * 64;
}
@Override
protected boolean search(int x, int z) {
generator.getHeightmap().apply(cell, x, z);
return test(cell);
}
protected boolean test(Cell<Terrain> cell) {
return cell.continentEdge > 0.5 && cell.regionEdge > 0.8F && cell.tag == type;
}
}