added MeteorDevelopment/meteor-client/pull/1300
This commit is contained in:
@@ -76,7 +76,9 @@ public class MeteorRejectsAddon extends MeteorAddon {
|
||||
commands.add(new GhostCommand());
|
||||
commands.add(new GiveCommand());
|
||||
commands.add(new SaveSkinCommand());
|
||||
commands.add(new SeedCommand());
|
||||
commands.add(new HeadsCommand());
|
||||
// commands.add(new LocateCommand()); I wish it was that simple -_-
|
||||
commands.add(new ServerCommand());
|
||||
commands.add(new SetBlockCommand());
|
||||
commands.add(new TeleportCommand());
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package cloudburst.rejects.arguments;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.text.LiteralText;
|
||||
|
||||
public class EnumArgumentType<T extends Enum<?>> implements ArgumentType<T> {
|
||||
private static final DynamicCommandExceptionType NO_SUCH_TYPE = new DynamicCommandExceptionType(o ->
|
||||
new LiteralText(o + " is not a valid argument."));
|
||||
|
||||
private T[] values;
|
||||
|
||||
public EnumArgumentType(T defaultValue) {
|
||||
super();
|
||||
|
||||
try {
|
||||
values = (T[]) defaultValue.getClass().getMethod("values").invoke(null);
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Enum<?>> EnumArgumentType<T> enumArgument(T defaultValue) {
|
||||
return new EnumArgumentType<T>(defaultValue);
|
||||
}
|
||||
|
||||
public static <T extends Enum<?>> T getEnum(CommandContext<?> context, String name, T defaultValue) {
|
||||
return (T) context.getArgument(name, defaultValue.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public T parse(StringReader reader) throws CommandSyntaxException {
|
||||
String argument = reader.readString();
|
||||
for (T t : values) {
|
||||
if (t.toString().equals(argument)) return t;
|
||||
}
|
||||
throw NO_SUCH_TYPE.create(argument);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||
return CommandSource.suggestMatching(Arrays.stream(values).map(T::toString), builder);
|
||||
}
|
||||
}
|
||||
194
src/main/java/cloudburst/rejects/commands/LocateCommand.java
Normal file
194
src/main/java/cloudburst/rejects/commands/LocateCommand.java
Normal file
@@ -0,0 +1,194 @@
|
||||
package cloudburst.rejects.commands;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||
import meteordevelopment.meteorclient.MeteorClient;
|
||||
import meteordevelopment.meteorclient.events.packets.PacketEvent;
|
||||
import meteordevelopment.meteorclient.systems.commands.Command;
|
||||
import cloudburst.rejects.arguments.EnumArgumentType;
|
||||
import meteordevelopment.meteorclient.utils.Utils;
|
||||
import meteordevelopment.meteorclient.utils.player.ChatUtils;
|
||||
import meteordevelopment.meteorclient.utils.player.FindItemResult;
|
||||
import meteordevelopment.meteorclient.utils.player.InvUtils;
|
||||
import cloudburst.rejects.utils.WorldGenUtils;
|
||||
import meteordevelopment.orbit.EventHandler;
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.text.BaseText;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import static com.mojang.brigadier.Command.SINGLE_SUCCESS;
|
||||
|
||||
public class LocateCommand extends Command {
|
||||
|
||||
private final static DynamicCommandExceptionType NOT_FOUND = new DynamicCommandExceptionType(o -> {
|
||||
if (o instanceof WorldGenUtils.Feature) {
|
||||
return new LiteralText(String.format(
|
||||
"%s not found.",
|
||||
Utils.nameToTitle(o.toString().replaceAll("_", "-")))
|
||||
);
|
||||
}
|
||||
return new LiteralText("Not found.");
|
||||
});
|
||||
|
||||
private Vec3d firstStart;
|
||||
private Vec3d firstEnd;
|
||||
private Vec3d secondStart;
|
||||
private Vec3d secondEnd;
|
||||
|
||||
public LocateCommand() {
|
||||
super("locate", "Locates structures", "loc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
||||
builder.then(literal("lodestone").executes(ctx -> {
|
||||
ItemStack stack = mc.player.getInventory().getMainHandStack();
|
||||
if (stack.getItem() != Items.COMPASS) {
|
||||
error("You need to hold a lodestone compass");
|
||||
return SINGLE_SUCCESS;
|
||||
}
|
||||
NbtCompound tag = stack.getTag();
|
||||
if (tag == null) {
|
||||
error("Couldn't get the NBT data. Are you holding a (highlight)lodestone(default) compass?");
|
||||
return SINGLE_SUCCESS;
|
||||
}
|
||||
NbtCompound nbt1 = tag.getCompound("LodestonePos");
|
||||
if (nbt1 == null) {
|
||||
error("Couldn't get the NBT data. Are you holding a (highlight)lodestone(default) compass?");
|
||||
return SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
Vec3d coords = new Vec3d(nbt1.getDouble("X"),nbt1.getDouble("Y"),nbt1.getDouble("Z"));
|
||||
BaseText text = new LiteralText("Lodestone located at ");
|
||||
text.append(ChatUtils.formatCoords(coords));
|
||||
text.append(".");
|
||||
info(text);
|
||||
return SINGLE_SUCCESS;
|
||||
}));
|
||||
|
||||
builder.then(argument("feature", EnumArgumentType.enumArgument(WorldGenUtils.Feature.stronghold)).executes(ctx -> {
|
||||
WorldGenUtils.Feature feature = EnumArgumentType.getEnum(ctx, "feature", WorldGenUtils.Feature.stronghold);
|
||||
BlockPos pos = WorldGenUtils.locateFeature(feature, mc.player.getBlockPos());
|
||||
if (pos != null) {
|
||||
BaseText text = new LiteralText(String.format(
|
||||
"%s located at ",
|
||||
Utils.nameToTitle(feature.toString().replaceAll("_", "-"))
|
||||
));
|
||||
Vec3d coords = new Vec3d(pos.getX(), pos.getY(), pos.getZ());
|
||||
text.append(ChatUtils.formatCoords(coords));
|
||||
text.append(".");
|
||||
info(text);
|
||||
return SINGLE_SUCCESS;
|
||||
}
|
||||
if (feature == WorldGenUtils.Feature.stronghold) {
|
||||
FindItemResult eye = InvUtils.findInHotbar(Items.ENDER_EYE);
|
||||
if (eye.found()) {
|
||||
BaritoneAPI.getProvider().getPrimaryBaritone().getCommandManager().execute("follow entity minecraft:eye_of_ender");
|
||||
firstStart = null;
|
||||
firstEnd = null;
|
||||
secondStart = null;
|
||||
secondEnd = null;
|
||||
MeteorClient.EVENT_BUS.subscribe(this);
|
||||
info("Please throw the first Eye of Ender");
|
||||
}
|
||||
}
|
||||
throw NOT_FOUND.create(feature);
|
||||
}));
|
||||
|
||||
builder.then(literal("cancel").executes(s -> {
|
||||
cancel();
|
||||
return SINGLE_SUCCESS;
|
||||
}));
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
warning("Locate canceled");
|
||||
MeteorClient.EVENT_BUS.unsubscribe(this);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
private void onReadPacket(PacketEvent.Receive event) {
|
||||
if (event.packet instanceof EntitySpawnS2CPacket) {
|
||||
EntitySpawnS2CPacket packet = (EntitySpawnS2CPacket) event.packet;
|
||||
if (packet.getEntityTypeId() == EntityType.EYE_OF_ENDER) {
|
||||
firstPosition(packet.getX(),packet.getY(),packet.getZ());
|
||||
}
|
||||
}
|
||||
if (event.packet instanceof PlaySoundS2CPacket) {
|
||||
PlaySoundS2CPacket packet = (PlaySoundS2CPacket) event.packet;
|
||||
if (packet.getSound() == SoundEvents.ENTITY_ENDER_EYE_DEATH) {
|
||||
lastPosition(packet.getX(), packet.getY(), packet.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void firstPosition(double x, double y, double z) {
|
||||
Vec3d pos = new Vec3d(x, y, z);
|
||||
if (this.firstStart == null) {
|
||||
this.firstStart = pos;
|
||||
}
|
||||
else {
|
||||
this.secondStart = pos;
|
||||
}
|
||||
}
|
||||
|
||||
private void lastPosition(double x, double y, double z) {
|
||||
info("%s Eye of Ender's trajectory saved.", (this.firstEnd == null) ? "First" : "Second");
|
||||
Vec3d pos = new Vec3d(x, y, z);
|
||||
if (this.firstEnd == null) {
|
||||
this.firstEnd = pos;
|
||||
info("Please throw the second Eye Of Ender from a different location.");
|
||||
}
|
||||
else {
|
||||
this.secondEnd = pos;
|
||||
findStronghold();
|
||||
}
|
||||
}
|
||||
|
||||
private void findStronghold() {
|
||||
if (this.firstStart == null || this.firstEnd == null || this.secondStart == null || this.secondEnd == null) {
|
||||
error("Missing position data");
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
final double[] start = new double[]{this.secondStart.x, this.secondStart.z, this.secondEnd.x, this.secondEnd.z};
|
||||
final double[] end = new double[]{this.firstStart.x, this.firstStart.z, this.firstEnd.x, this.firstEnd.z};
|
||||
final double[] intersection = calcIntersection(start, end);
|
||||
if (Double.isNaN(intersection[0]) || Double.isNaN(intersection[1]) || Double.isInfinite(intersection[0]) || Double.isInfinite(intersection[1])) {
|
||||
error("Lines are parallel");
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
BaritoneAPI.getProvider().getPrimaryBaritone().getCommandManager().execute("stop");
|
||||
MeteorClient.EVENT_BUS.unsubscribe(this);
|
||||
Vec3d coords = new Vec3d(intersection[0],0,intersection[1]);
|
||||
BaseText text = new LiteralText("Stronghold roughly located at ");
|
||||
text.append(ChatUtils.formatCoords(coords));
|
||||
text.append(".");
|
||||
info(text);
|
||||
}
|
||||
|
||||
private double[] calcIntersection(double[] line, double[] line2) {
|
||||
final double a1 = line[3] - line[1];
|
||||
final double b1 = line[0] - line[2];
|
||||
final double c1 = a1 * line[0] + b1 * line[1];
|
||||
|
||||
final double a2 = line2[3] - line2[1];
|
||||
final double b2 = line2[0] - line2[2];
|
||||
final double c2 = a2 * line2[0] + b2 * line2[1];
|
||||
|
||||
final double delta = a1 * b2 - a2 * b1;
|
||||
|
||||
return new double[]{(b2 * c1 - b1 * c2) / delta, (a1 * c2 - a2 * c1) / delta};
|
||||
}
|
||||
}
|
||||
68
src/main/java/cloudburst/rejects/commands/SeedCommand.java
Normal file
68
src/main/java/cloudburst/rejects/commands/SeedCommand.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package cloudburst.rejects.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.text.BaseText;
|
||||
import net.minecraft.text.LiteralText;
|
||||
|
||||
import kaptainwutax.mcutils.version.MCVersion;
|
||||
import meteordevelopment.meteorclient.systems.commands.Command;
|
||||
import cloudburst.rejects.arguments.EnumArgumentType;
|
||||
import cloudburst.rejects.utils.seeds.Seed;
|
||||
import cloudburst.rejects.utils.seeds.Seeds;
|
||||
import meteordevelopment.meteorclient.utils.Utils;
|
||||
|
||||
import static com.mojang.brigadier.Command.SINGLE_SUCCESS;
|
||||
|
||||
import com.mojang.brigadier.arguments.LongArgumentType;
|
||||
|
||||
public class SeedCommand extends Command {
|
||||
private final static SimpleCommandExceptionType NO_SEED = new SimpleCommandExceptionType(new LiteralText("No seed for current world saved."));
|
||||
|
||||
public SeedCommand() {
|
||||
super("seed", "Get or set seed for the current world.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
||||
builder.executes(ctx -> {
|
||||
Seed seed = Seeds.get().getSeed();
|
||||
if (seed == null) throw NO_SEED.create();
|
||||
info(seed.toText());
|
||||
return SINGLE_SUCCESS;
|
||||
});
|
||||
|
||||
builder.then(literal("list").executes(ctx -> {
|
||||
Seeds.get().seeds.forEach((name, seed) -> {
|
||||
BaseText text = new LiteralText(name + " ");
|
||||
text.append(seed.toText());
|
||||
info(text);
|
||||
});
|
||||
return SINGLE_SUCCESS;
|
||||
}));
|
||||
|
||||
builder.then(literal("delete").executes(ctx -> {
|
||||
Seed seed = Seeds.get().getSeed();
|
||||
if (seed != null) {
|
||||
BaseText text = new LiteralText("Deleted ");
|
||||
text.append(seed.toText());
|
||||
info(text);
|
||||
}
|
||||
Seeds.get().seeds.remove(Utils.getWorldName());
|
||||
return SINGLE_SUCCESS;
|
||||
}));
|
||||
|
||||
builder.then(argument("seed", LongArgumentType.longArg()).executes(ctx -> {
|
||||
Seeds.get().setSeed(LongArgumentType.getLong(ctx, "seed"));
|
||||
return SINGLE_SUCCESS;
|
||||
}));
|
||||
|
||||
builder.then(argument("seed", LongArgumentType.longArg()).then(argument("version", EnumArgumentType.enumArgument(MCVersion.v1_17_1)).executes(ctx -> {
|
||||
Seeds.get().setSeed(LongArgumentType.getLong(ctx, "seed"), EnumArgumentType.getEnum(ctx, "version", MCVersion.v1_17_1));
|
||||
return SINGLE_SUCCESS;
|
||||
})));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package cloudburst.rejects.mixin.meteor;
|
||||
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
||||
import meteordevelopment.meteorclient.systems.commands.Command;
|
||||
import meteordevelopment.meteorclient.systems.commands.Commands;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import net.minecraft.command.CommandSource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Mixin(Commands.class)
|
||||
public class CommandsMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private List<Command> commands;
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private Map<Class<? extends Command>, Command> commandInstances;
|
||||
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private CommandDispatcher<CommandSource> DISPATCHER = new CommandDispatcher<>();
|
||||
|
||||
@Inject(method = "add", at=@At("HEAD"), remap = false, cancellable = true)
|
||||
private void onAdd(Command cmd, CallbackInfo ci) {
|
||||
if (cmd instanceof meteordevelopment.meteorclient.systems.commands.commands.LocateCommand) {
|
||||
Command command = new cloudburst.rejects.commands.LocateCommand();
|
||||
commands.removeIf(command1 -> command1.getName().equals(command.getName()));
|
||||
commandInstances.values().removeIf(command1 -> command1.getName().equals(command.getName()));
|
||||
|
||||
command.registerTo(DISPATCHER);
|
||||
commands.add(command);
|
||||
commandInstances.put(command.getClass(), command);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,15 @@ import meteordevelopment.meteorclient.MeteorClient;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import cloudburst.rejects.utils.seeds.Seeds;
|
||||
|
||||
public class RejectsUtils {
|
||||
public static int CPS = 0;
|
||||
|
||||
public static void init() {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
RejectsConfig.get().save(MeteorClient.FOLDER);
|
||||
Seeds.get().save(MeteorClient.FOLDER);
|
||||
}));
|
||||
|
||||
new Timer().scheduleAtFixedRate(newTimerTaskFromLambda(() -> CPS = 0), 0, 1000);
|
||||
|
||||
313
src/main/java/cloudburst/rejects/utils/WorldGenUtils.java
Normal file
313
src/main/java/cloudburst/rejects/utils/WorldGenUtils.java
Normal file
@@ -0,0 +1,313 @@
|
||||
package cloudburst.rejects.utils;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import kaptainwutax.biomeutils.source.BiomeSource;
|
||||
import kaptainwutax.featureutils.misc.SlimeChunk;
|
||||
import kaptainwutax.featureutils.structure.*;
|
||||
import kaptainwutax.mcutils.rand.ChunkRand;
|
||||
import kaptainwutax.mcutils.state.Dimension;
|
||||
import kaptainwutax.mcutils.util.data.SpiralIterator;
|
||||
import kaptainwutax.mcutils.util.pos.*;
|
||||
import kaptainwutax.mcutils.version.MCVersion;
|
||||
import kaptainwutax.terrainutils.TerrainGenerator;
|
||||
import cloudburst.rejects.utils.seeds.Seed;
|
||||
import cloudburst.rejects.utils.seeds.Seeds;
|
||||
import meteordevelopment.meteorclient.utils.player.ChatUtils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.mob.*;
|
||||
import net.minecraft.entity.passive.IronGolemEntity;
|
||||
import net.minecraft.entity.passive.VillagerEntity;
|
||||
import net.minecraft.entity.vehicle.ChestMinecartEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static meteordevelopment.meteorclient.utils.Utils.mc;
|
||||
|
||||
public class WorldGenUtils {
|
||||
|
||||
private static final HashMap<Feature, List<Block>> FEATURE_BLOCKS = new HashMap<>(){{
|
||||
put(Feature.nether_fortress, Arrays.asList(
|
||||
Blocks.NETHER_BRICKS,
|
||||
Blocks.NETHER_BRICK_FENCE,
|
||||
Blocks.NETHER_WART
|
||||
));
|
||||
put(Feature.ocean_monument, Arrays.asList(
|
||||
Blocks.PRISMARINE_BRICKS,
|
||||
Blocks.SEA_LANTERN,
|
||||
Blocks.DARK_PRISMARINE
|
||||
));
|
||||
put(Feature.stronghold, Arrays.asList(
|
||||
Blocks.END_PORTAL_FRAME,
|
||||
Blocks.END_PORTAL
|
||||
));
|
||||
put(Feature.end_city, Arrays.asList(
|
||||
Blocks.PURPUR_BLOCK,
|
||||
Blocks.PURPUR_PILLAR,
|
||||
Blocks.PURPUR_STAIRS,
|
||||
Blocks.END_ROD
|
||||
));
|
||||
put(Feature.village, Arrays.asList(
|
||||
Blocks.BELL,
|
||||
Blocks.BREWING_STAND
|
||||
));
|
||||
put(Feature.mineshaft, Collections.singletonList(
|
||||
Blocks.RAIL
|
||||
));
|
||||
}};
|
||||
|
||||
private static final HashMap<Feature, List<Class<? extends Entity>>> FEATURE_ENTITIES = new HashMap<>(){{
|
||||
put(Feature.ocean_monument, Arrays.asList(
|
||||
ElderGuardianEntity.class,
|
||||
GuardianEntity.class
|
||||
));
|
||||
put(Feature.nether_fortress, Arrays.asList(
|
||||
BlazeEntity.class,
|
||||
WitherSkeletonEntity.class
|
||||
));
|
||||
put(Feature.mansion, Collections.singletonList(
|
||||
EvokerEntity.class
|
||||
));
|
||||
put(Feature.slime_chunk, Collections.singletonList(
|
||||
SlimeEntity.class
|
||||
));
|
||||
put(Feature.bastion_remnant, Collections.singletonList(
|
||||
PiglinBruteEntity.class
|
||||
));
|
||||
put(Feature.end_city, Collections.singletonList(
|
||||
ShulkerEntity.class
|
||||
));
|
||||
put(Feature.village, Arrays.asList(
|
||||
VillagerEntity.class,
|
||||
IronGolemEntity.class
|
||||
));
|
||||
put(Feature.mineshaft, Collections.singletonList(
|
||||
ChestMinecartEntity.class
|
||||
));
|
||||
}};
|
||||
|
||||
public enum Feature {
|
||||
buried_treasure,
|
||||
mansion,
|
||||
stronghold,
|
||||
nether_fortress,
|
||||
ocean_monument,
|
||||
bastion_remnant,
|
||||
end_city,
|
||||
village,
|
||||
mineshaft,
|
||||
slime_chunk
|
||||
}
|
||||
|
||||
public static BlockPos locateFeature(Feature feature, BlockPos center) {
|
||||
Seed seed = Seeds.get().getSeed();
|
||||
BlockPos pos = null;
|
||||
if (seed != null) {
|
||||
pos = locateFeature(seed, feature, center);
|
||||
if (pos != null) return pos;
|
||||
}
|
||||
if (mc.player != null) {
|
||||
ItemStack stack = mc.player.getStackInHand(Hand.MAIN_HAND);
|
||||
if (stack.getItem() != Items.FILLED_MAP)
|
||||
stack = mc.player.getStackInHand(Hand.OFF_HAND);
|
||||
if (stack.getItem() == Items.FILLED_MAP) {
|
||||
pos = locateFeatureMap(feature, stack);
|
||||
if (pos != null) return pos;
|
||||
}
|
||||
}
|
||||
pos = locateFeatureEntities(feature);
|
||||
if (pos != null) return pos;
|
||||
pos = locateFeatureBlocks(feature);
|
||||
return pos;
|
||||
}
|
||||
|
||||
private static BlockPos locateFeatureMap(Feature feature, ItemStack stack) {
|
||||
if (!isValidMap(feature, stack)) return null;
|
||||
return getMapMarker(stack);
|
||||
}
|
||||
|
||||
private static BlockPos locateFeatureBlocks(Feature feature) {
|
||||
List<Block> blocks = FEATURE_BLOCKS.get(feature);
|
||||
if (blocks == null) return null;
|
||||
List<BlockPos> posList = BaritoneAPI
|
||||
.getProvider()
|
||||
.getWorldScanner()
|
||||
.scanChunkRadius(
|
||||
BaritoneAPI
|
||||
.getProvider()
|
||||
.getPrimaryBaritone()
|
||||
.getPlayerContext(),
|
||||
blocks,64,10,32);
|
||||
if (posList.isEmpty()) return null;
|
||||
if (posList.size() < 5) {
|
||||
ChatUtils.warning("Locate", "Only %d block(s) found. This search might be a false positive.", posList.size());
|
||||
}
|
||||
return posList.get(0);
|
||||
}
|
||||
|
||||
private static BlockPos locateFeatureEntities(Feature feature) {
|
||||
List<Class<? extends Entity>> entities = FEATURE_ENTITIES.get(feature);
|
||||
if (entities == null) return null;
|
||||
if (mc.world == null) return null;
|
||||
for (Entity e: mc.world.getEntities()) {
|
||||
for (Class<? extends Entity> clazz: entities) {
|
||||
if (clazz.isInstance(e))
|
||||
return e.getBlockPos();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static BlockPos locateFeature(Seed seed, Feature feature, BlockPos center) {
|
||||
if (feature == Feature.slime_chunk) return locateSlimeChunk(seed, center);
|
||||
return locateStructure(seed, feature, center);
|
||||
}
|
||||
|
||||
private static BlockPos locateSlimeChunk(Seed seed, BlockPos center) {
|
||||
Dimension dimension = getDimension(Feature.slime_chunk);
|
||||
MCVersion mcVersion = seed.version;
|
||||
CPos centerChunk = new CPos(center.getX() >> 4, center.getZ() >> 4);
|
||||
CPos slimeChunkPos = locateSlimeChunk(new SlimeChunk(mcVersion), centerChunk, 6400, seed.seed, new ChunkRand(), dimension);
|
||||
if (slimeChunkPos == null) return null;
|
||||
return toBlockPos(slimeChunkPos.toBlockPos());
|
||||
}
|
||||
|
||||
private static CPos locateSlimeChunk(SlimeChunk slimeChunk, CPos centerChunk, int radius, long seed, ChunkRand rand, Dimension dimension) {
|
||||
if (!slimeChunk.isValidDimension(dimension))
|
||||
return null;
|
||||
SpiralIterator<CPos> spiralIterator = new SpiralIterator<>(centerChunk, new CPos(radius, radius), (x, y, z) -> new CPos(x, z));
|
||||
for (CPos next : spiralIterator) {
|
||||
SlimeChunk.Data data = slimeChunk.at(next.getX(), next.getZ(), true);
|
||||
if (data.testStart(seed, rand)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static BlockPos locateStructure(Seed seed, Feature feature, BlockPos center) {
|
||||
Dimension dimension = getDimension(feature);
|
||||
MCVersion mcVersion = seed.version;
|
||||
Structure<?, ?> structure = getStructure(feature, mcVersion);
|
||||
if (structure == null) return null;
|
||||
BiomeSource biomeSource = BiomeSource.of(dimension, mcVersion, seed.seed);
|
||||
if (!structure.isValidDimension(biomeSource.getDimension()))
|
||||
return null;
|
||||
BPos structurePos = locateStructure(structure, new BPos(center.getX(), center.getY(), center.getZ()), 6400, new ChunkRand(), biomeSource, TerrainGenerator.of(biomeSource));
|
||||
if (structurePos == null) return null;
|
||||
return toBlockPos(structurePos);
|
||||
}
|
||||
|
||||
private static BPos locateStructure(Structure<?, ?> structure, BPos center, int radius, ChunkRand chunkRand, BiomeSource source, TerrainGenerator terrainGenerator) {
|
||||
if (structure instanceof RegionStructure<?, ?> regionStructure) {
|
||||
int chunkInRegion = regionStructure.getSpacing();
|
||||
int regionSize = chunkInRegion * 16;
|
||||
|
||||
final int border = 30_000_000;
|
||||
SpiralIterator<RPos> spiralIterator = new SpiralIterator<>(center.toRegionPos(regionSize), new BPos(-border, 0, -border).toRegionPos(regionSize), new BPos(border, 0, border).toRegionPos(regionSize), 1, (x, y, z) -> new RPos(x, z, regionSize));
|
||||
return StreamSupport.stream(spiralIterator.spliterator(), false)
|
||||
.map(rPos -> regionStructure.getInRegion(source.getWorldSeed(), rPos.getX(), rPos.getZ(), chunkRand))
|
||||
.filter(Objects::nonNull)
|
||||
.filter(cPos -> (regionStructure.canSpawn(cPos, source)) && (terrainGenerator == null || regionStructure.canGenerate(cPos, terrainGenerator)))
|
||||
.findAny().map(cPos -> cPos.toBlockPos().add(9, 0, 9)).orElse(null);
|
||||
} else {
|
||||
if (structure instanceof Stronghold strongholdStructure) {
|
||||
CPos currentChunkPos = center.toChunkPos();
|
||||
int squaredDistance = Integer.MAX_VALUE;
|
||||
CPos closest = new CPos(0, 0);
|
||||
for (CPos stronghold : strongholdStructure.getAllStarts(source, chunkRand)) {
|
||||
int newSquaredDistance = (currentChunkPos.getX() - stronghold.getX()) * (currentChunkPos.getX() - stronghold.getX()) + (currentChunkPos.getZ() - stronghold.getZ()) * (currentChunkPos.getZ() - stronghold.getZ());
|
||||
if (newSquaredDistance < squaredDistance) {
|
||||
squaredDistance = newSquaredDistance;
|
||||
closest = stronghold;
|
||||
}
|
||||
}
|
||||
BPos dimPos = closest.toBlockPos().add(9, 0, 9);
|
||||
return new BPos(dimPos.getX(), 0, dimPos.getZ());
|
||||
} else if (structure instanceof Mineshaft mineshaft) {
|
||||
SpiralIterator<CPos> spiralIterator = new SpiralIterator<>(new CPos(center.getX() >> 4, center.getZ() >> 4), new CPos(radius, radius), (x, y, z) -> new CPos(x, z));
|
||||
|
||||
return StreamSupport.stream(spiralIterator.spliterator(), false)
|
||||
.filter(cPos -> {
|
||||
kaptainwutax.featureutils.Feature.Data<Mineshaft> data = mineshaft.at(cPos.getX(), cPos.getZ());
|
||||
return data.testStart(source.getWorldSeed(), chunkRand) && data.testBiome(source) && data.testGenerate(terrainGenerator);
|
||||
})
|
||||
.findAny().map(cPos -> cPos.toBlockPos().add(9, 0, 9)).orElse(null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Dimension getDimension(Feature feature) {
|
||||
switch (feature) {
|
||||
case buried_treasure -> { return Dimension.OVERWORLD; }
|
||||
case mansion -> { return Dimension.OVERWORLD; }
|
||||
case stronghold -> { return Dimension.OVERWORLD; }
|
||||
case nether_fortress -> { return Dimension.NETHER; }
|
||||
case ocean_monument -> { return Dimension.OVERWORLD; }
|
||||
case bastion_remnant -> { return Dimension.NETHER; }
|
||||
case slime_chunk -> { return Dimension.OVERWORLD; }
|
||||
case village -> { return Dimension.OVERWORLD; }
|
||||
case mineshaft -> { return Dimension.OVERWORLD; }
|
||||
case end_city -> { return Dimension.END; }
|
||||
default -> { return Dimension.OVERWORLD; }
|
||||
}
|
||||
}
|
||||
|
||||
private static Structure<?, ?> getStructure(Feature feature, MCVersion version) {
|
||||
switch (feature) {
|
||||
case buried_treasure -> { return new BuriedTreasure(version); }
|
||||
case mansion -> { return new Mansion(version); }
|
||||
case stronghold -> { return new Stronghold(version); }
|
||||
case nether_fortress -> { return new Fortress(version); }
|
||||
case ocean_monument -> { return new Monument(version); }
|
||||
case bastion_remnant -> { return new BastionRemnant(version); }
|
||||
case end_city -> { return new EndCity(version); }
|
||||
case village -> { return new Village(version); }
|
||||
case mineshaft -> { return new Mineshaft(version); }
|
||||
default -> { return null;}
|
||||
}
|
||||
}
|
||||
|
||||
private static BlockPos toBlockPos(BPos pos) {
|
||||
return new BlockPos(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
private static boolean isValidMap(Feature feature, ItemStack stack) {
|
||||
if (!stack.hasTag()) return false;
|
||||
if (!stack.getTag().contains("display")) return false;
|
||||
NbtCompound displayTag = stack.getTag().getCompound("display");
|
||||
if (!displayTag.contains("Name")) return false;
|
||||
String nameTag = displayTag.getString("Name");
|
||||
if (!nameTag.contains("translate")) return false;
|
||||
|
||||
if (feature == Feature.buried_treasure) {
|
||||
return nameTag.contains("filled_map.buried_treasure");
|
||||
} else if (feature == Feature.ocean_monument) {
|
||||
return nameTag.contains("filled_map.monument");
|
||||
} else if (feature == Feature.mansion) {
|
||||
return nameTag.contains("filled_map.mansion");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static BlockPos getMapMarker(ItemStack stack) {
|
||||
if (!stack.hasTag()) return null;
|
||||
if (!stack.getTag().contains("Decorations")) return null;
|
||||
NbtList decorationsTag = stack.getTag().getList("Decorations", NbtElement.COMPOUND_TYPE);
|
||||
if (decorationsTag.size() < 1) return null;
|
||||
NbtCompound iconTag = decorationsTag.getCompound(0);
|
||||
return new BlockPos(
|
||||
(int)iconTag.getDouble("x"),
|
||||
(int)iconTag.getDouble("y"),
|
||||
(int)iconTag.getDouble("z")
|
||||
);
|
||||
}
|
||||
}
|
||||
53
src/main/java/cloudburst/rejects/utils/seeds/Seed.java
Normal file
53
src/main/java/cloudburst/rejects/utils/seeds/Seed.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package cloudburst.rejects.utils.seeds;
|
||||
|
||||
import kaptainwutax.mcutils.version.MCVersion;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtLong;
|
||||
import net.minecraft.nbt.NbtString;
|
||||
import net.minecraft.text.*;
|
||||
import net.minecraft.util.Formatting;
|
||||
|
||||
public class Seed {
|
||||
public final Long seed;
|
||||
public final MCVersion version;
|
||||
|
||||
public Seed(Long seed, MCVersion version) {
|
||||
this.seed = seed;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public NbtCompound toTag() {
|
||||
NbtCompound tag = new NbtCompound();
|
||||
tag.put("seed", NbtLong.of(seed));
|
||||
tag.put("version", NbtString.of(version.name()));
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static Seed fromTag(NbtCompound tag) {
|
||||
return new Seed(
|
||||
tag.getLong("seed"),
|
||||
MCVersion.valueOf(tag.getString("version"))
|
||||
);
|
||||
}
|
||||
|
||||
public Text toText() {
|
||||
BaseText text = new LiteralText(String.format("[%s%s%s] (%s)",
|
||||
Formatting.GREEN,
|
||||
seed.toString(),
|
||||
Formatting.WHITE,
|
||||
version.toString()
|
||||
));
|
||||
text.setStyle(text.getStyle()
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.COPY_TO_CLIPBOARD,
|
||||
seed.toString()
|
||||
))
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
new LiteralText("Copy to clipboard")
|
||||
))
|
||||
);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
70
src/main/java/cloudburst/rejects/utils/seeds/Seeds.java
Normal file
70
src/main/java/cloudburst/rejects/utils/seeds/Seeds.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package cloudburst.rejects.utils.seeds;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.minecraft.client.network.ServerInfo;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
|
||||
import kaptainwutax.mcutils.version.MCVersion;
|
||||
import meteordevelopment.meteorclient.MeteorClient;
|
||||
import meteordevelopment.meteorclient.systems.System;
|
||||
import meteordevelopment.meteorclient.utils.Utils;
|
||||
|
||||
import static meteordevelopment.meteorclient.utils.Utils.mc;
|
||||
|
||||
public class Seeds extends System<Seeds> {
|
||||
private static final Seeds INSTANCE = new Seeds();
|
||||
|
||||
public HashMap<String, Seed> seeds = new HashMap<>();
|
||||
|
||||
public Seeds() {
|
||||
super("seeds");
|
||||
init();
|
||||
load(MeteorClient.FOLDER);
|
||||
}
|
||||
|
||||
public static Seeds get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public Seed getSeed() {
|
||||
if (mc.isIntegratedServerRunning() && mc.getServer() != null)
|
||||
return new Seed(mc.getServer().getOverworld().getSeed(), MCVersion.fromString(mc.getServer().getVersion()));
|
||||
|
||||
return seeds.get(Utils.getWorldName());
|
||||
}
|
||||
|
||||
public void setSeed(long seed, MCVersion version) {
|
||||
if (mc.isIntegratedServerRunning()) return;
|
||||
|
||||
seeds.put(Utils.getWorldName(), new Seed(seed, version));
|
||||
}
|
||||
|
||||
public void setSeed(long seed) {
|
||||
ServerInfo server = mc.getCurrentServerEntry();
|
||||
MCVersion ver = null;
|
||||
if (server != null)
|
||||
ver = MCVersion.fromString(server.version.asString());
|
||||
if (ver == null)
|
||||
ver = MCVersion.latest();
|
||||
setSeed(seed, ver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toTag() {
|
||||
NbtCompound tag = new NbtCompound();
|
||||
seeds.forEach((key, seed) -> {
|
||||
if (seed == null) return;
|
||||
tag.put(key, seed.toTag());
|
||||
});
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Seeds fromTag(NbtCompound tag) {
|
||||
tag.getKeys().forEach(key -> {
|
||||
seeds.put(key, Seed.fromTag(tag.getCompound(key)));
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"client": [
|
||||
"modules.NoRenderAccessor",
|
||||
"CommandsMixin",
|
||||
"ConfigTabMixin",
|
||||
"GuiRendererAccessor",
|
||||
"HttpMixin"
|
||||
|
||||
Reference in New Issue
Block a user