Merge pull request #102 from Old-Chum/master

Upgrade Nuker
This commit is contained in:
noil 2023-03-31 12:45:53 -04:00 committed by GitHub
commit 3992120726
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 432 additions and 113 deletions

View File

@ -0,0 +1,169 @@
package me.rigamortis.seppuku.impl.command;
import me.rigamortis.seppuku.Seppuku;
import me.rigamortis.seppuku.api.command.Command;
import me.rigamortis.seppuku.api.util.StringUtil;
import me.rigamortis.seppuku.impl.config.NukerFilterConfig;
import me.rigamortis.seppuku.impl.module.world.NukerModule;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.event.HoverEvent;
/**
* @author Old Chum
* @since 3/30/2023
*/
public class NukerFilterCommand extends Command {
private final String[] addAlias = new String[]{"Add", "A"};
private final String[] removeAlias = new String[]{"Remove", "Rem", "R", "Delete", "Del", "D"};
private final String[] listAlias = new String[]{"List", "Lst"};
private final String[] clearAlias = new String[]{"Clear", "C"};
public NukerFilterCommand() {
super("NukerFilter", new String[]{"NukerF", "FilterN"}, "Allows you to change what blocks nuker mines",
"NukerFilter Add <Block_Name>\n" +
"NukerFilter Add <ID>\n" +
"NukerFilter Remove <Block_Name>\n" +
"NukerFilter Remove <ID>\n" +
"NukerFilter List\n" +
"NukerFilter Clear");
}
@Override
public void exec(String input) {
if (!this.clamp(input, 2, 3)) {
this.printUsage();
return;
}
final String[] split = input.split(" ");
final NukerModule nuker = (NukerModule) Seppuku.INSTANCE.getModuleManager().find(NukerModule.class);
if (nuker != null) {
if (equals(addAlias, split[1])) {
if (!this.clamp(input, 3, 3)) {
this.printUsage();
return;
}
if (StringUtil.isInt(split[2])) {
final int id = Integer.parseInt(split[2]);
if (id > 0) {
final Block block = Block.getBlockById(id);
if (nuker.contains(block)) {
Seppuku.INSTANCE.logChat("Nuker already contains " + block.getLocalizedName());
} else {
nuker.add(Block.getIdFromBlock(block));
Seppuku.INSTANCE.getConfigManager().save(NukerFilterConfig.class);
Seppuku.INSTANCE.logChat("Added " + block.getLocalizedName() + " to nuker");
}
} else {
Seppuku.INSTANCE.errorChat("Cannot add Air to nuker");
}
} else {
final Block block = Block.getBlockFromName(split[2].toLowerCase());
if (block != null) {
if (block == Blocks.AIR) {
Seppuku.INSTANCE.errorChat("Cannot add Air to nuker");
} else {
if (nuker.contains(block)) {
Seppuku.INSTANCE.logChat("Nuker already contains " + block.getLocalizedName());
} else {
nuker.add(Block.getIdFromBlock(block));
Seppuku.INSTANCE.getConfigManager().save(NukerFilterConfig.class);
Seppuku.INSTANCE.logChat("Added " + block.getLocalizedName() + " to nuker");
}
}
} else {
Seppuku.INSTANCE.logChat("\247c" + split[2] + "\247f is not a valid block");
}
}
} else if (equals(removeAlias, split[1])) {
if (!this.clamp(input, 3, 3)) {
this.printUsage();
return;
}
if (StringUtil.isInt(split[2])) {
final int id = Integer.parseInt(split[2]);
if (id > 0) {
final Block block = Block.getBlockById(id);
if (nuker.contains(block)) {
nuker.remove(Block.getIdFromBlock(block));
Seppuku.INSTANCE.getConfigManager().save(NukerFilterConfig.class);
Seppuku.INSTANCE.logChat("Removed " + block.getLocalizedName() + " from nuker");
} else {
Seppuku.INSTANCE.logChat("Nuker doesn't contain " + block.getLocalizedName());
}
} else {
Seppuku.INSTANCE.errorChat("Cannot remove Air from nuker");
}
} else {
final Block block = Block.getBlockFromName(split[2].toLowerCase());
if (block != null) {
if (block == Blocks.AIR) {
Seppuku.INSTANCE.errorChat("Cannot remove Air from nuker");
} else {
if (nuker.contains(block)) {
nuker.remove(Block.getIdFromBlock(block));
Seppuku.INSTANCE.getConfigManager().save(NukerFilterConfig.class);
Seppuku.INSTANCE.logChat("Removed " + block.getLocalizedName() + " from nuker");
} else {
Seppuku.INSTANCE.logChat("Nuker doesn't contain " + block.getLocalizedName());
}
}
} else {
Seppuku.INSTANCE.logChat("\247c" + split[2] + "\247f is not a valid block");
}
}
} else if (equals(listAlias, split[1])) {
if (!this.clamp(input, 2, 2)) {
this.printUsage();
return;
}
if (nuker.getFilter().getValue().size() > 0) {
final TextComponentString msg = new TextComponentString("\2477Nuker IDs: ");
for (Block block : nuker.getFilter().getValue()) {
msg.appendSibling(new TextComponentString("\2477[\247a" + Block.getIdFromBlock(block) + "\2477] ")
.setStyle(new Style()
.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(block.getLocalizedName())))));
}
Seppuku.INSTANCE.logcChat(msg);
} else {
Seppuku.INSTANCE.logChat("You don't have any nuker ids");
}
} else if (equals(clearAlias, split[1])) {
if (!this.clamp(input, 2, 2)) {
this.printUsage();
return;
}
nuker.clear();
Seppuku.INSTANCE.getConfigManager().save(NukerFilterConfig.class);
Seppuku.INSTANCE.logChat("Cleared all blocks from nuker");
} else {
Seppuku.INSTANCE.errorChat("Unknown input " + "\247f\"" + input + "\"");
this.printUsage();
}
} else {
Seppuku.INSTANCE.errorChat("Nuker not present");
}
}
}

View File

@ -0,0 +1,64 @@
package me.rigamortis.seppuku.impl.config;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import me.rigamortis.seppuku.Seppuku;
import me.rigamortis.seppuku.api.config.Configurable;
import me.rigamortis.seppuku.api.util.FileUtil;
import me.rigamortis.seppuku.impl.module.world.NukerModule;
import net.minecraft.block.Block;
import java.io.File;
/**
* @author Old Chum
* @since 3/30/2023
*/
public class NukerFilterConfig extends Configurable {
private final NukerModule nukerModule;
public NukerFilterConfig(File dir) {
super(FileUtil.createJsonFile(dir, "NukerFilter"));
this.nukerModule = (NukerModule) Seppuku.INSTANCE.getModuleManager().find("Nuker");
}
@Override
public void onLoad() {
super.onLoad();
if (this.nukerModule == null)
return;
JsonArray xrayIdsJsonArray = null;
final JsonElement blockIds = this.getJsonObject().get("NukerFilterIds");
if (blockIds != null)
xrayIdsJsonArray = blockIds.getAsJsonArray();
final NukerModule nukerModule = (NukerModule) Seppuku.INSTANCE.getModuleManager().find("Nuker");
if (nukerModule != null) {
if (xrayIdsJsonArray != null) {
for (JsonElement jsonElement : xrayIdsJsonArray) {
nukerModule.add(jsonElement.getAsInt());
}
}
}
}
@Override
public void onSave() {
if (this.nukerModule == null)
return;
JsonObject save = new JsonObject();
JsonArray xrayIdsJsonArray = new JsonArray();
for (Block block : this.nukerModule.getFilter().getValue())
xrayIdsJsonArray.add(Block.getIdFromBlock(block));
save.add("NukerFilterIds", xrayIdsJsonArray);
this.saveJsonObjectToFile(save);
}
}

View File

@ -76,6 +76,7 @@ public final class CommandManager {
this.commandList.add(new LocateFeatureCommand());
this.commandList.add(new MainMenuCommand());
this.commandList.add(new ConfigCommand());
this.commandList.add(new NukerFilterCommand());
//create commands for every value within every module
loadValueCommands();

View File

@ -100,6 +100,7 @@ public final class ConfigManager {
this.configurableList.add(new IgnoreConfig(configDir));
this.configurableList.add(new AutoIgnoreConfig(configDir));
this.configurableList.add(new AltConfig(configDir));
this.configurableList.add(new NukerFilterConfig(configDir));
if (this.firstLaunch) {
this.saveAll();

View File

@ -1,11 +1,9 @@
package me.rigamortis.seppuku.impl.module.world;
import me.rigamortis.seppuku.Seppuku;
import me.rigamortis.seppuku.api.event.player.EventRightClickBlock;
import me.rigamortis.seppuku.api.event.player.EventUpdateWalkingPlayer;
import me.rigamortis.seppuku.api.module.Module;
import me.rigamortis.seppuku.api.task.rotation.RotationTask;
import me.rigamortis.seppuku.api.util.BlockUtil;
import me.rigamortis.seppuku.api.util.EntityUtil;
import me.rigamortis.seppuku.api.util.MathUtil;
import me.rigamortis.seppuku.api.value.Value;
@ -13,27 +11,43 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.init.Blocks;
import net.minecraft.network.play.client.CPacketPlayerDigging;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import team.stiff.pomelo.impl.annotated.handler.annotation.Listener;
import java.util.*;
/**
* Author Seth
* 6/10/2019 @ 2:31 PM.
*/
public final class NukerModule extends Module {
public final Value<Mode> mode = new Value<Mode>("Mode", new String[]{"Mode", "M"}, "The nuker mode to use.", Mode.SELECTION);
public final Value<Mode> mode = new Value<Mode>("Mode", new String[]{"M"}, "The way that nuker mines blocks", Mode.NORMAL);
public final Value<Float> distance = new Value<Float>("Distance", new String[]{"Dist", "D"}, "Maximum distance in blocks the nuker will reach", 4.5f, 0.0f, 5.0f, 0.1f);
public final Value<Boolean> fixed = new Value<Boolean>("FixedDistance", new String[]{"Fixed", "fdist", "F"}, "Use vertical and horizontal distances in blocks instead of distances relative to the camera", false);
public final Value<Boolean> flatten = new Value<Boolean>("Flatten", new String[]{"flat"}, "Ensures nuker does not mine blocks below your feet", false);
public final Value<Float> vDistance = new Value<Float>("VerticalDistance", new String[]{"Vertical", "vdist", "VD"}, "Maximum vertical distance in blocks the nuker will reach", 4.5f, 0.0f, 5.0f, 0.1f);
public final Value<Float> hDistance = new Value<Float>("HorizontalDistance", new String[]{"Horizontal", "hist", "HD"}, "Maximum horizontal distance in blocks the nuker will reach", 3f, 0.0f, 5.0f, 0.1f);
public final Value<Integer> timeout = new Value<Integer>("Timeout", new String[]{"TO, t"}, "How long to wait (in ms) until trying to break a specific block again (PACKET Mode)", 1000, 0, 5000, 10);
public final Value<Float> minMineSpeed = new Value<Float>("MinMineSpeed", new String[]{"Min", "Speed", "MineSpeed"}, "How fast you should be able to mine a block for nuker to attempt to mine it (0-1, 0 to allow all blocks, 1 to only allow instantly minable blocks)", 0.2f, 0f, 1.0f, 0.1f);
// TODO: FilterMode does not show up in the gui (noil's fault).
public final Value<FilterMode> filterMode = new Value<FilterMode>("FilterMode", new String[]{"fm", "fmode"}, "Controls how blocks should be checked against the filter", FilterMode.WHITE);
public final Value<List<Block>> filter = new Value<List<Block>>("Filter", new String[]{}, "Controls what block id's nuker will mine");
private final RotationTask rotationTask = new RotationTask("NukerTask", 2);
private Block selected = null;
private BlockPos currentPos = null;
private final Map<BlockPos, Long> attemptedBreaks = new HashMap<>();
public NukerModule() {
super("Nuker", new String[]{"Nuke"}, "Automatically mines blocks within reach", "NONE", -1, ModuleType.WORLD);
}
@ -41,7 +55,7 @@ public final class NukerModule extends Module {
@Override
public void onToggle() {
super.onToggle();
this.selected = null;
this.filter.setValue(new ArrayList<>());
}
@Override
@ -63,67 +77,82 @@ public final class NukerModule extends Module {
switch (event.getStage()) {
case PRE:
this.currentPos = null;
if (this.mode.getValue() == Mode.PACKET) {
// PACKET mode does not need to rotate. The few servers it works on probably don't care about rotation.
// It also tries to break more than one block per event, and I am not sure how to handle that using the
// rotation task.
List<BlockPos> blocks = getSortedBlocks();
switch (this.mode.getValue()) {
case SELECTION:
this.currentPos = this.getClosestBlock(true);
break;
case ALL:
this.currentPos = this.getClosestBlock(false);
break;
}
for (BlockPos pos : blocks) {
if (shouldBreak(pos)) {
if (!this.attemptedBreaks.containsKey(pos)) {
mc.player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.START_DESTROY_BLOCK, pos, EnumFacing.NORTH));
mc.player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.STOP_DESTROY_BLOCK, pos, EnumFacing.NORTH));
if (this.currentPos != null) {
Seppuku.INSTANCE.getRotationManager().startTask(this.rotationTask);
if (this.rotationTask.isOnline()) {
final float[] angle = MathUtil.calcAngle(mc.player.getPositionEyes(mc.getRenderPartialTicks()), new Vec3d(this.currentPos.getX() + 0.5f, this.currentPos.getY() + 0.5f, this.currentPos.getZ() + 0.5f));
Seppuku.INSTANCE.getRotationManager().setPlayerRotations(angle[0], angle[1]);
this.attemptedBreaks.put(pos, System.currentTimeMillis());
}
}
}
List<BlockPos> toRemove = new ArrayList<>();
for (BlockPos pos : attemptedBreaks.keySet()) {
if (System.currentTimeMillis() - attemptedBreaks.get(pos) >= timeout.getValue()) {
toRemove.add(pos);
}
}
for (BlockPos pos : toRemove) {
attemptedBreaks.remove(pos);
}
} else {
this.currentPos = this.getClosestBlock();
if (this.currentPos != null) {
Seppuku.INSTANCE.getRotationManager().startTask(this.rotationTask);
if (this.rotationTask.isOnline()) {
final float[] angle = MathUtil.calcAngle(mc.player.getPositionEyes(mc.getRenderPartialTicks()), new Vec3d(this.currentPos.getX() + 0.5f, this.currentPos.getY() + 0.5f, this.currentPos.getZ() + 0.5f));
Seppuku.INSTANCE.getRotationManager().setPlayerRotations(angle[0], angle[1]);
}
}
}
break;
case POST:
if (this.mode.getValue().equals(Mode.CREATIVE)) {
if (this.mode.getValue() == Mode.CREATIVE) {
if (mc.player.capabilities.isCreativeMode) {
/* the amazing creative 'nuker' straight from the latch hacked client */
for (double y = Math.round(mc.player.posY - 1) + this.vDistance.getValue(); y > Math.round(mc.player.posY - 1); y -= 1.0D) {
for (double x = mc.player.posX - this.hDistance.getValue(); x < mc.player.posX + this.hDistance.getValue(); x += 1.0D) {
for (double z = mc.player.posZ - this.hDistance.getValue(); z < mc.player.posZ + this.hDistance.getValue(); z += 1.0D) {
final BlockPos blockPos = new BlockPos(x, y, z);
final Block block = BlockUtil.getBlock(blockPos);
if (block == Blocks.AIR || !mc.world.getBlockState(blockPos).isFullBlock())
continue;
for (BlockPos blockPos : getBoxIterable()) {
if (!shouldBreak(blockPos) || !mc.world.getBlockState(blockPos).isFullBlock())
continue;
final Vec3d eyesPos = new Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight(), mc.player.posZ);
final Vec3d posVec = new Vec3d(blockPos).add(0.5f, 0.5f, 0.5f);
double distanceSqPosVec = eyesPos.squareDistanceTo(posVec);
final Vec3d eyesPos = new Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight(), mc.player.posZ);
final Vec3d posVec = new Vec3d(blockPos).add(0.5f, 0.5f, 0.5f);
double distanceSqPosVec = eyesPos.squareDistanceTo(posVec);
for (EnumFacing side : EnumFacing.values()) {
final Vec3d hitVec = posVec.add(new Vec3d(side.getDirectionVec()).scale(0.5f));
double distanceSqHitVec = eyesPos.squareDistanceTo(hitVec);
for (EnumFacing side : EnumFacing.values()) {
final Vec3d hitVec = posVec.add(new Vec3d(side.getDirectionVec()).scale(0.5f));
double distanceSqHitVec = eyesPos.squareDistanceTo(hitVec);
// check if hitVec is within range (6 blocks)
if (distanceSqHitVec > 36)
continue;
// check if hitVec is within range (6 blocks)
if (distanceSqHitVec > 36)
continue;
// check if side is facing towards player
if (distanceSqHitVec >= distanceSqPosVec)
continue;
// check if side is facing towards player
if (distanceSqHitVec >= distanceSqPosVec)
continue;
// face block
final float[] rotations = EntityUtil.getRotations(hitVec.x, hitVec.y, hitVec.z);
Seppuku.INSTANCE.getRotationManager().setPlayerRotations(rotations[0], rotations[1]);
// face block
final float[] rotations = EntityUtil.getRotations(hitVec.x, hitVec.y, hitVec.z);
Seppuku.INSTANCE.getRotationManager().setPlayerRotations(rotations[0], rotations[1]);
// damage block
if (mc.playerController.onPlayerDamageBlock(blockPos, side)) {
mc.player.swingArm(EnumHand.MAIN_HAND);
}
}
// damage block
if (mc.playerController.onPlayerDamageBlock(blockPos, side)) {
mc.player.swingArm(EnumHand.MAIN_HAND);
}
}
}
}
} else {
} else if (this.mode.getValue() == Mode.NORMAL) {
if (this.currentPos != null) {
if (this.rotationTask.isOnline()) {
if (SpeedMineModule.autoPos != null) {
@ -145,89 +174,144 @@ public final class NukerModule extends Module {
}
}
@Listener
public void clickBlock(EventRightClickBlock event) {
if (this.mode.getValue() == Mode.SELECTION) {
final Block block = Minecraft.getMinecraft().world.getBlockState(event.getPos()).getBlock();
if (block != this.selected) {
this.selected = block;
Seppuku.INSTANCE.logChat("Nuker block set to " + block.getLocalizedName());
event.setCanceled(true);
}
}
}
private boolean canBreak(BlockPos pos) {
final IBlockState blockState = Minecraft.getMinecraft().world.getBlockState(pos);
final Block block = blockState.getBlock();
return block.getBlockHardness(blockState, Minecraft.getMinecraft().world, pos) != -1;
return block.getBlockHardness(blockState, Minecraft.getMinecraft().world, pos) >= minMineSpeed.getValue();
}
private BlockPos getClosestBlock(boolean selection) {
private boolean shouldBreak(BlockPos pos) {
final Minecraft mc = Minecraft.getMinecraft();
BlockPos ret = null;
boolean isFiltered = false;
if (this.filterMode.getValue() != FilterMode.DISABLED) {
// Did a truth table for this and this just so happens to be a XOR
isFiltered = this.filter.getValue().contains(mc.world.getBlockState(pos).getBlock()) ^ this.filterMode.getValue() == FilterMode.WHITE;
}
return mc.world.getBlockState(pos).getBlock() != Blocks.AIR
&& !(mc.world.getBlockState(pos).getBlock() instanceof BlockLiquid)
&& this.canBreak(pos)
&& !pos.equals(SpeedMineModule.autoPos)
&& !isFiltered;
}
private Iterable<BlockPos> getBoxIterable () {
final Minecraft mc = Minecraft.getMinecraft();
AxisAlignedBB bb;
if (this.fixed.getValue()) {
float maxVDist = this.vDistance.getValue();
float maxHDist = this.hDistance.getValue();
for (float x = 0; x <= maxHDist; x++) {
for (float y = 0; y <= maxVDist; y++) {
for (float z = 0; z <= maxHDist; z++) {
for (int revX = 0; revX <= 1; revX++, x = -x) {
for (int revZ = 0; revZ <= 1; revZ++, z = -z) {
final BlockPos pos = new BlockPos(mc.player.posX + x, mc.player.posY + y, mc.player.posZ + z);
if (pos.equals(SpeedMineModule.autoPos)) {
continue;
}
if ((mc.world.getBlockState(pos).getBlock() != Blocks.AIR &&
!(mc.world.getBlockState(pos).getBlock() instanceof BlockLiquid)) &&
this.canBreak(pos)) {
if (selection) {
if ((this.selected == null) || !mc.world.getBlockState(pos).getBlock().equals(this.selected)) {
continue;
}
}
ret = pos;
}
}
}
}
}
}
bb = new AxisAlignedBB(
(int) mc.player.posX - hDistance.getValue(),
(int) (this.flatten.getValue() ? mc.player.posY : mc.player.posY - vDistance.getValue()),
(int) mc.player.posZ - hDistance.getValue(),
(int) mc.player.posX + hDistance.getValue(),
(int) mc.player.posY + vDistance.getValue(),
(int) mc.player.posZ + hDistance.getValue());
} else {
float maxDist = this.distance.getValue();
for (float x = maxDist; x >= -maxDist; x--) {
for (float y = maxDist; y >= -maxDist; y--) {
for (float z = maxDist; z >= -maxDist; z--) {
final BlockPos pos = new BlockPos(mc.player.posX + x, mc.player.posY + y, mc.player.posZ + z);
final double dist = mc.player.getDistance(pos.getX(), pos.getY(), pos.getZ());
if (pos.equals(SpeedMineModule.autoPos)) {
continue;
}
if (dist <= maxDist && (mc.world.getBlockState(pos).getBlock() != Blocks.AIR && !(mc.world.getBlockState(pos).getBlock() instanceof BlockLiquid)) && canBreak(pos)) {
if (selection) {
if ((this.selected == null) || !mc.world.getBlockState(pos).getBlock().equals(this.selected)) {
continue;
}
}
bb = new AxisAlignedBB(
(int) mc.player.posX - distance.getValue(),
(int) (this.flatten.getValue() ? mc.player.posY : mc.player.posY - vDistance.getValue()),
(int) mc.player.posZ - distance.getValue(),
(int) mc.player.posX + distance.getValue(),
(int) mc.player.posY + distance.getValue(),
(int) mc.player.posZ + distance.getValue());
}
if (pos.getY() < mc.player.posY)
continue;
return BlockPos.getAllInBox((int) bb.minX, (int) bb.minY, (int) bb.minZ, (int) bb.maxX, (int) bb.maxY, (int) bb.maxZ);
}
maxDist = (float) dist;
ret = pos;
}
}
private BlockPos getClosestBlock() {
final Minecraft mc = Minecraft.getMinecraft();
BlockPos closest = null;
double closestDist = Double.POSITIVE_INFINITY;
for (BlockPos pos : getBoxIterable()) {
double dist = pos.distanceSqToCenter(mc.player.posX, mc.player.getEyeHeight(), mc.player.posZ);
if (shouldBreak(pos)) {
if (dist < closestDist) {
closestDist = dist;
closest = pos;
}
}
}
return closest;
}
/*
* Not very good performance wise. A better way to do this would be to directly iterate from the player's head,
* but that is difficult, and we don't expect SUPER huge input for this. At most the player would probably have a
* cube of 'radius' 6, +1 if the bounding box is aligned right, so we would have around 13^3 = 2197 blocks to
* iterate and sort.
*/
private List<BlockPos> getSortedBlocks() {
EntityPlayerSP player = Minecraft.getMinecraft().player;
List<BlockPos> ret = new ArrayList<>();
for (BlockPos pos : getBoxIterable()) {
ret.add(new BlockPos(pos));
}
ret.sort(Comparator.comparingDouble(o -> o.distanceSqToCenter(player.posX, player.posY, player.posZ)));
return ret;
}
private enum Mode {
SELECTION, ALL, CREATIVE
public Value<List<Block>> getFilter() {
return filter;
}
public boolean contains(Block block) {
return this.filter.getValue().contains(block);
}
public void add(int id) {
final Block blockFromID = Block.getBlockById(id);
if (!contains(blockFromID)) {
this.filter.getValue().add(blockFromID);
}
}
public void add(String name) {
final Block blockFromName = Block.getBlockFromName(name);
if (blockFromName != null) {
if (!contains(blockFromName)) {
this.filter.getValue().add(blockFromName);
}
}
}
public void remove(int id) {
for (Block block : this.filter.getValue()) {
final int blockID = Block.getIdFromBlock(block);
if (blockID == id) {
this.filter.getValue().remove(block);
break;
}
}
}
public void remove(String name) {
final Block blockFromName = Block.getBlockFromName(name);
if (blockFromName != null) {
if (contains(blockFromName)) {
this.filter.getValue().remove(blockFromName);
}
}
}
public int clear() {
final int count = this.filter.getValue().size();
this.filter.getValue().clear();
return count;
}
private enum Mode {
NORMAL, PACKET, CREATIVE
}
private enum FilterMode {
WHITE, BLACK, DISABLED
}
}