package anticope.rejects.modules; import anticope.rejects.MeteorRejectsAddon; import anticope.rejects.utils.WorldUtils; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.settings.BoolSetting; import meteordevelopment.meteorclient.settings.IntSetting; import meteordevelopment.meteorclient.settings.Setting; import meteordevelopment.meteorclient.settings.SettingGroup; import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.player.FindItemResult; import meteordevelopment.meteorclient.utils.player.InvUtils; import meteordevelopment.orbit.EventHandler; import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import org.apache.commons.lang3.tuple.Pair; import java.util.Comparator; import java.util.HashMap; import java.util.Map; public class MossBot extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); private final Setting range = sgGeneral.add(new IntSetting.Builder() .name("range") .description("The bonemeal range.") .defaultValue(4) .min(0) .build() ); private final Setting rotate = sgGeneral.add(new BoolSetting.Builder() .name("rotate") .description("Whether or not to rotate towards block while bonemealing.") .defaultValue(true) .build() ); private final Map mossMap = new HashMap<>(); public MossBot() { super(MeteorRejectsAddon.CATEGORY, "moss-bot", "Use bonemeal on moss blocks with maximized efficiency."); } @EventHandler private void onTick(TickEvent.Pre event) { mossMap.entrySet().removeIf(e -> e.setValue(e.getValue() - 1) == 0); FindItemResult findItemResult = InvUtils.findInHotbar(Items.BONE_MEAL); if (!findItemResult.found()) { return; } BlockPos bestBlock = BlockPos.streamOutwards(new BlockPos(mc.player.getEyePos()), range.get(), range.get(), range.get()) .filter(b -> mc.player.getEyePos().distanceTo(Vec3d.ofCenter(b)) <= range.get() && !mossMap.containsKey(b)) .map(b -> Pair.of(b.toImmutable(), getMossSpots(b))) .filter(p -> p.getRight() > 10) .map(Pair::getLeft) .max(Comparator.naturalOrder()).orElse(null); if (bestBlock != null) { if (!mc.world.isAir(bestBlock.up())) { mc.interactionManager.updateBlockBreakingProgress(bestBlock.up(), Direction.UP); } WorldUtils.interact(bestBlock, findItemResult, rotate.get()); mossMap.put(bestBlock, 100); } } private int getMossSpots(BlockPos pos) { if (mc.world.getBlockState(pos).getBlock() != Blocks.MOSS_BLOCK || mc.world.getBlockState(pos.up()).getHardness(mc.world, pos) != 0f) { return 0; } return (int) BlockPos.streamOutwards(pos, 3, 4, 3) .filter(b -> isMossGrowableOn(mc.world.getBlockState(b).getBlock()) && mc.world.isAir(b.up())) .count(); } private boolean isMossGrowableOn(Block block) { return block == Blocks.STONE || block == Blocks.GRANITE || block == Blocks.ANDESITE || block == Blocks.DIORITE || block == Blocks.DIRT || block == Blocks.COARSE_DIRT || block == Blocks.MYCELIUM || block == Blocks.GRASS_BLOCK || block == Blocks.PODZOL || block == Blocks.ROOTED_DIRT; } }