Meteorite Worldgen
This commit is contained in:
@@ -46,11 +46,14 @@ public final class AECommand {
|
||||
|
||||
private void add(LiteralArgumentBuilder<net.minecraft.command.CommandSource> builder, Commands subCommand) {
|
||||
|
||||
builder.then(literal(subCommand.name().toLowerCase()).requires(src -> src.hasPermissionLevel(subCommand.level))
|
||||
.executes(ctx -> {
|
||||
subCommand.command.call(ServerLifecycleHooks.getCurrentServer(), new String[0], ctx.getSource());
|
||||
return 1;
|
||||
}));
|
||||
LiteralArgumentBuilder<CommandSource> subCommandBuilder = literal(subCommand.name().toLowerCase())
|
||||
.requires(src -> src.hasPermissionLevel(subCommand.level));
|
||||
subCommand.command.addArguments(subCommandBuilder);
|
||||
subCommandBuilder.executes(ctx -> {
|
||||
subCommand.command.call(ServerLifecycleHooks.getCurrentServer(), ctx, ctx.getSource());
|
||||
return 1;
|
||||
});
|
||||
builder.then(subCommandBuilder);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,12 @@ package appeng.server;
|
||||
|
||||
import appeng.server.subcommands.ChunkLogger;
|
||||
import appeng.server.subcommands.Supporters;
|
||||
import appeng.server.subcommands.TestMeteoritesCommand;
|
||||
import appeng.server.subcommands.TestOreGenCommand;
|
||||
|
||||
public enum Commands {
|
||||
Chunklogger(4, new ChunkLogger(), false), Supporters(0, new Supporters(), false),
|
||||
TestOreGen(4, new TestOreGenCommand(), true);
|
||||
TestOreGen(4, new TestOreGenCommand(), true), TestMeteorites(4, new TestMeteoritesCommand(), true);
|
||||
|
||||
public final int level;
|
||||
public final ISubCommand command;
|
||||
|
||||
@@ -18,10 +18,16 @@
|
||||
|
||||
package appeng.server;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public interface ISubCommand {
|
||||
|
||||
void call(MinecraftServer srv, String[] args, CommandSource sender);
|
||||
default void addArguments(LiteralArgumentBuilder<CommandSource> builder) {
|
||||
}
|
||||
|
||||
void call(MinecraftServer srv, CommandContext<CommandSource> ctx, CommandSource sender);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
package appeng.server.subcommands;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
@@ -65,7 +67,7 @@ public class ChunkLogger implements ISubCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(final MinecraftServer srv, final String[] data, final CommandSource sender) {
|
||||
public void call(final MinecraftServer srv, final CommandContext<CommandSource> data, final CommandSource sender) {
|
||||
this.enabled = !this.enabled;
|
||||
|
||||
if (this.enabled) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package appeng.server.subcommands;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -29,7 +30,7 @@ import appeng.server.ISubCommand;
|
||||
public class Supporters implements ISubCommand {
|
||||
|
||||
@Override
|
||||
public void call(final MinecraftServer srv, final String[] data, final CommandSource sender) {
|
||||
public void call(final MinecraftServer srv, final CommandContext<CommandSource> data, final CommandSource sender) {
|
||||
final String[] who = { "Stig Halvorsen", "Josh Ricker", "Jenny \"Othlon\" Sutherland", "Hristo Bogdanov",
|
||||
"BevoLJ" };
|
||||
sender.sendFeedback(new StringTextComponent("Special thanks to " + Joiner.on(", ").join(who)), true);
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* This file is part of Applied Energistics 2.
|
||||
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
|
||||
*
|
||||
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
|
||||
package appeng.server.subcommands;
|
||||
|
||||
import static net.minecraft.command.Commands.literal;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.google.common.math.StatsAccumulator;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
import net.minecraft.world.gen.feature.structure.StructureStart;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||
|
||||
import appeng.server.ISubCommand;
|
||||
import appeng.worldgen.MeteoriteStructure;
|
||||
import appeng.worldgen.MeteoriteStructurePiece;
|
||||
import appeng.worldgen.PlacedMeteoriteSettings;
|
||||
|
||||
/**
|
||||
* This is a testing command to validate quartz ore generation.
|
||||
*/
|
||||
public class TestMeteoritesCommand implements ISubCommand {
|
||||
|
||||
@Override
|
||||
public void addArguments(LiteralArgumentBuilder<CommandSource> builder) {
|
||||
builder.then(literal("force").executes(ctx -> {
|
||||
test(ServerLifecycleHooks.getCurrentServer(), ctx.getSource(), true);
|
||||
return 1;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(final MinecraftServer srv, final CommandContext<CommandSource> ctx, final CommandSource sender) {
|
||||
test(srv, sender, false);
|
||||
}
|
||||
|
||||
private static void test(MinecraftServer srv, final CommandSource sender, boolean force) {
|
||||
int radius = 100;
|
||||
|
||||
ServerPlayerEntity player = null;
|
||||
try {
|
||||
player = sender.asPlayer();
|
||||
} catch (CommandSyntaxException ignored) {
|
||||
}
|
||||
ServerWorld world;
|
||||
BlockPos centerBlock;
|
||||
if (player != null) {
|
||||
world = player.getServerWorld();
|
||||
centerBlock = new BlockPos(player.getPosX(), 0, player.getPosZ());
|
||||
} else {
|
||||
world = srv.getWorld(DimensionType.OVERWORLD);
|
||||
centerBlock = world.getSpawnPoint();
|
||||
}
|
||||
|
||||
ChunkPos center = new ChunkPos(centerBlock);
|
||||
|
||||
ChunkGenerator<?> generator = world.getChunkProvider().getChunkGenerator();
|
||||
|
||||
// Find all meteorites in the given rectangle
|
||||
List<PlacedMeteoriteSettings> found = new ArrayList<>();
|
||||
int chunksChecked = 0;
|
||||
for (int cx = center.x - radius; cx <= center.x + radius; cx++) {
|
||||
for (int cz = center.z - radius; cz <= center.z + radius; cz++) {
|
||||
chunksChecked++;
|
||||
ChunkPos cp = new ChunkPos(cx, cz);
|
||||
BlockPos p = new BlockPos(cp.getXStart(), 0, cp.getZStart());
|
||||
BlockPos nearest = MeteoriteStructure.INSTANCE.findNearest(world, generator, p, 0, false);
|
||||
if (nearest != null) {
|
||||
IChunk chunk = world.getChunk(cx, cz, ChunkStatus.STRUCTURE_STARTS);
|
||||
// The actual relevant information is in the structure piece
|
||||
MeteoriteStructurePiece piece = getMeteoritePieceFromChunk(chunk);
|
||||
if (piece != null) {
|
||||
found.add(piece.getSettings());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create stats on how far apart the meteorites are
|
||||
StatsAccumulator stats = new StatsAccumulator();
|
||||
for (PlacedMeteoriteSettings settings : found) {
|
||||
double closestOther = Double.NaN;
|
||||
for (PlacedMeteoriteSettings otherSettings : found) {
|
||||
if (otherSettings != settings) {
|
||||
double d = settings.getPos().distanceSq(otherSettings.getPos());
|
||||
if (Double.isNaN(closestOther) || d < closestOther) {
|
||||
closestOther = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Double.isNaN(closestOther)) {
|
||||
stats.add(Math.sqrt(closestOther));
|
||||
}
|
||||
}
|
||||
|
||||
found.sort(Comparator.comparingDouble(settings -> settings.getPos().distanceSq(centerBlock)));
|
||||
|
||||
sendLine(sender, "Chunks checked: %d", chunksChecked);
|
||||
sendLine(sender, "Meteorites found: %d", found.size());
|
||||
sendLine(sender, "Closest: min=%.2f max=%.2f mean=%.2f stddev=%.2f", stats.min(), stats.max(), stats.mean(),
|
||||
stats.populationStandardDeviation());
|
||||
|
||||
int closestCount = Math.min(5, found.size());
|
||||
for (int i = 0; i < closestCount; i++) {
|
||||
PlacedMeteoriteSettings settings = found.get(i);
|
||||
BlockPos pos = settings.getPos();
|
||||
|
||||
String state = "not final";
|
||||
|
||||
if (force && settings.getFallout() == null) {
|
||||
IChunk chunk = world.getChunk(pos);
|
||||
MeteoriteStructurePiece piece = getMeteoritePieceFromChunk(chunk);
|
||||
if (piece == null) {
|
||||
state = "removed";
|
||||
} else {
|
||||
settings = piece.getSettings();
|
||||
pos = settings.getPos();
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.getFallout() == null) {
|
||||
sendLine(sender, " #%d: pos=%d,%d,%d, radius=%.2f [%s]", i + 1, pos.getX(), pos.getY(), pos.getZ(),
|
||||
settings.getMeteoriteRadius(), state);
|
||||
} else {
|
||||
sendLine(sender, " #%d: pos=%d,%d,%d, radius=%.2f, crater=%s, lava=%s, fallout=%s", i + 1, pos.getX(),
|
||||
pos.getY(), pos.getZ(), settings.getMeteoriteRadius(), settings.isPlaceCrater(),
|
||||
settings.isLava(), settings.getFallout().name().toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static MeteoriteStructurePiece getMeteoritePieceFromChunk(IChunk chunk) {
|
||||
StructureStart start = chunk.getStructureStart(MeteoriteStructure.INSTANCE.getStructureName());
|
||||
|
||||
if (start != null && start.getComponents().size() > 0
|
||||
&& start.getComponents().get(0) instanceof MeteoriteStructurePiece) {
|
||||
return (MeteoriteStructurePiece) start.getComponents().get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void sendLine(CommandSource sender, String text, Object... args) {
|
||||
sender.sendFeedback(new StringTextComponent(String.format(Locale.ROOT, text, args)), true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.util.function.ToDoubleFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.math.StatsAccumulator;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
@@ -56,7 +57,7 @@ public class TestOreGenCommand implements ISubCommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(final MinecraftServer srv, final String[] data, final CommandSource sender) {
|
||||
public void call(final MinecraftServer srv, final CommandContext<CommandSource> data, final CommandSource sender) {
|
||||
|
||||
int radius = 1000;
|
||||
|
||||
@@ -67,7 +68,7 @@ public class TestOreGenCommand implements ISubCommand {
|
||||
world = player.getServerWorld();
|
||||
center = new BlockPos(player.getPosX(), 0, player.getPosZ());
|
||||
} catch (CommandSyntaxException e) {
|
||||
world = srv.getWorld(DimensionType.OVERWORLD);
|
||||
world = srv.getWorld(DimensionType.OVERWORLD);
|
||||
center = world.getSpawnPoint();
|
||||
}
|
||||
|
||||
@@ -83,7 +84,8 @@ public class TestOreGenCommand implements ISubCommand {
|
||||
}
|
||||
|
||||
AggregatedStats oreCount = AggregatedStats.create(stats.chunks, cs -> (double) cs.quartzOreCount);
|
||||
List<ChunkStats> chunksWithOre = stats.chunks.stream().filter(c -> c.quartzOreCount > 0).collect(Collectors.toList());
|
||||
List<ChunkStats> chunksWithOre = stats.chunks.stream().filter(c -> c.quartzOreCount > 0)
|
||||
.collect(Collectors.toList());
|
||||
AggregatedStats minHeight = AggregatedStats.create(chunksWithOre, cs -> (double) cs.minHeight);
|
||||
AggregatedStats maxHeight = AggregatedStats.create(chunksWithOre, cs -> (double) cs.maxHeight);
|
||||
AggregatedStats chargedCount = AggregatedStats.create(chunksWithOre, cs -> (double) cs.chargedOreCount);
|
||||
@@ -165,12 +167,8 @@ public class TestOreGenCommand implements ISubCommand {
|
||||
accumulator.add(getter.applyAsDouble(value));
|
||||
}
|
||||
|
||||
return new AggregatedStats(
|
||||
accumulator.min(),
|
||||
accumulator.max(),
|
||||
accumulator.mean(),
|
||||
accumulator.populationStandardDeviation()
|
||||
);
|
||||
return new AggregatedStats(accumulator.min(), accumulator.max(), accumulator.mean(),
|
||||
accumulator.populationStandardDeviation());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,8 +176,7 @@ public class TestOreGenCommand implements ISubCommand {
|
||||
if (Double.isNaN(min)) {
|
||||
return "Invalid";
|
||||
}
|
||||
return String.format(Locale.ROOT, "min=%.2f, max=%.2f, mean=%.2f, stdDev=%.2f",
|
||||
min, max, mean, stdDev);
|
||||
return String.format(Locale.ROOT, "min=%.2f, max=%.2f, mean=%.2f, stdDev=%.2f", min, max, mean, stdDev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user