diff --git a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/Terminator.java b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/Terminator.java index 328a4ad..6fb50ce 100644 --- a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/Terminator.java +++ b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/Terminator.java @@ -4,12 +4,14 @@ import com.mojang.authlib.GameProfile; import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import org.bukkit.util.BoundingBox; import org.bukkit.util.Vector; import java.util.List; @@ -32,6 +34,8 @@ public interface Terminator { boolean hasNeuralNetwork(); Location getLocation(); + + BoundingBox getBotBoundingBox(); boolean isBotAlive(); //Has to be named like this because paper re-obfuscates it @@ -120,4 +124,6 @@ public interface Terminator { UUID getTargetPlayer(); void setTargetPlayer(UUID target); + + World.Environment getDimension(); } diff --git a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java index b2a3fd1..2bd0d4c 100644 --- a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java +++ b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java @@ -26,6 +26,8 @@ import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.BoundingBox; import org.bukkit.util.Vector; +import com.google.common.base.Optional; + import java.util.*; import java.util.Map.Entry; import java.util.regex.Pattern; @@ -107,6 +109,8 @@ public class LegacyAgent extends Agent { Location loc = bot.getLocation(); LivingEntity livingTarget = locateTarget(bot, loc); + blockCheck.tryPreMLG(bot, loc); + if (livingTarget == null) { stopMining(bot); return; @@ -297,7 +301,7 @@ public class LegacyAgent extends Agent { Material itemType; - if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { + if (bot.getDimension() == World.Environment.NETHER) { itemType = Material.TWISTING_VINES; } else { itemType = Material.WATER_BUCKET; @@ -339,7 +343,7 @@ public class LegacyAgent extends Agent { Material placeType; Sound sound; Location groundLoc = null; - boolean nether = bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER; + boolean nether = bot.getDimension() == World.Environment.NETHER; double yPos = bot.getBukkitEntity().getLocation().getY(); if (nether) { @@ -359,7 +363,7 @@ public class LegacyAgent extends Agent { placeType = Material.WATER; for (Block block : event.getStandingOn()) { - if (LegacyMats.canPlaceWater(block, yPos)) { + if (LegacyMats.canPlaceWater(block, Optional.of(yPos))) { groundLoc = block.getLocation(); break; } @@ -1203,7 +1207,7 @@ public class LegacyAgent extends Agent { Location loc = bot.getLocation(); if (bot.isBotOnFire()) { - if (bot.getBukkitEntity().getWorld().getEnvironment() != World.Environment.NETHER) { + if (bot.getDimension() != World.Environment.NETHER) { placeWaterDown(bot, world, loc); } } @@ -1211,7 +1215,7 @@ public class LegacyAgent extends Agent { Material atType = loc.getBlock().getType(); if (atType == Material.FIRE || atType == Material.SOUL_FIRE) { - if (bot.getBukkitEntity().getWorld().getEnvironment() != World.Environment.NETHER) { + if (bot.getDimension() != World.Environment.NETHER) { placeWaterDown(bot, world, loc); world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); } else { @@ -1223,7 +1227,7 @@ public class LegacyAgent extends Agent { } if (atType == Material.LAVA) { - if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { + if (bot.getDimension() == World.Environment.NETHER) { bot.attemptBlockPlace(loc, Material.COBBLESTONE, false); } else { placeWaterDown(bot, world, loc); @@ -1234,7 +1238,7 @@ public class LegacyAgent extends Agent { Material headType = head.getBlock().getType(); if (headType == Material.LAVA) { - if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { + if (bot.getDimension() == World.Environment.NETHER) { bot.attemptBlockPlace(head, Material.COBBLESTONE, false); } else { placeWaterDown(bot, world, head); @@ -1242,7 +1246,7 @@ public class LegacyAgent extends Agent { } if (headType == Material.FIRE || headType == Material.SOUL_FIRE) { - if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { + if (bot.getDimension() == World.Environment.NETHER) { bot.look(BlockFace.DOWN); bot.punch(); world.playSound(head, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); diff --git a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyBlockCheck.java b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyBlockCheck.java index a9c2d12..54f290c 100644 --- a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyBlockCheck.java +++ b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyBlockCheck.java @@ -1,16 +1,25 @@ package net.nuggetmc.tplus.api.agent.legacyagent; import net.nuggetmc.tplus.api.Terminator; +import net.nuggetmc.tplus.api.utils.BotUtils; + import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Waterlogged; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; +import org.bukkit.util.BoundingBox; +import com.google.common.base.Optional; + +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.Iterator; +import java.util.List; import java.util.Set; public class LegacyBlockCheck { @@ -135,6 +144,90 @@ public class LegacyBlockCheck { all.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1); placeFinal(bot, player, block.getLocation()); } + + public boolean tryPreMLG(Terminator bot, Location botLoc) { + if(bot.isBotOnGround() || bot.getVelocity().getY() >= -0.8D) + return false; + if (tryPreMLG(bot, botLoc, 3)) + return true; + return tryPreMLG(bot, botLoc, 2); + } + + private boolean tryPreMLG(Terminator bot, Location botLoc, int blocksBelow) { + BoundingBox box = bot.getBotBoundingBox(); + double[] xVals = new double[]{ + box.getMinX(), + box.getMaxX() - 0.01 + }; + + double[] zVals = new double[]{ + box.getMinZ(), + box.getMaxZ() - 0.01 + }; + Set below2Set = new HashSet<>(); + + for (double x : xVals) { + for (double z : zVals) { + Location below = botLoc.clone(); + below.setX(x); + below.setZ(z); + below.setY(bot.getLocation().getBlockY()); + for (int i = 0; i < blocksBelow - 1; i++) { + below.setY(below.getY() - 1); + + // Blocks before must all be pass-through + Material type = below.getBlock().getType(); + if (type.isSolid() || LegacyMats.canStandOn(type)) + return false; + below = below.clone(); + } + below.setY(bot.getLocation().getBlockY() - blocksBelow); + below2Set.add(below.getBlock().getLocation()); + } + } + + // Second block below must have at least one unplaceable block (that is landable) + boolean nether = bot.getDimension() == World.Environment.NETHER; + Iterator itr = below2Set.iterator(); + while (itr.hasNext()) { + Block next = itr.next().getBlock(); + boolean placeable = nether ? LegacyMats.canPlaceTwistingVines(next) + : LegacyMats.canPlaceWater(next, Optional.absent()); + if (placeable || (!next.getType().isSolid() && !LegacyMats.canStandOn(next.getType()))) + itr.remove(); + } + + // Clutch + if (!below2Set.isEmpty()) { + List below2List = new ArrayList<>(below2Set); + below2List.sort((a, b) -> { + Block aBlock = a.clone().add(0, 1, 0).getBlock(); + Block bBlock = b.clone().add(0, 1, 0).getBlock(); + if (aBlock.getType().isAir() && !bBlock.getType().isAir()) + return -1; + if (!bBlock.getType().isAir() && aBlock.getType().isAir()) + return 1; + return Double.compare(BotUtils.getHorizSqDist(a, botLoc), BotUtils.getHorizSqDist(b, botLoc)); + }); + + Location faceLoc = below2List.get(0); + Location loc = faceLoc.clone().add(0, 1, 0); + bot.faceLocation(faceLoc); + bot.look(BlockFace.DOWN); + + Bukkit.getScheduler().runTaskLater(plugin, () -> { + bot.faceLocation(faceLoc); + }, 1); + + bot.punch(); + for (Player all : Bukkit.getOnlinePlayers()) + all.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1); + bot.setItem(new ItemStack(Material.COBBLESTONE)); + loc.getBlock().setType(Material.COBBLESTONE); + } + + return false; + } public void clutch(Terminator bot, LivingEntity target) { Location botLoc = bot.getLocation(); diff --git a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyMats.java b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyMats.java index ae5a399..9e00c02 100644 --- a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyMats.java +++ b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyMats.java @@ -8,6 +8,8 @@ import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Waterlogged; import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.type.*; + +import com.google.common.base.Optional; import com.google.common.collect.Lists; import java.util.ArrayList; @@ -292,7 +294,32 @@ public class LegacyMats { return materials; } - public static boolean canPlaceWater(Block block, double entityYPos) { + /** + * Checks for non-solid blocks that can hold an entity up. + */ + public static boolean canStandOn(Material mat) { + if(mat == Material.END_ROD || mat == Material.FLOWER_POT || mat == Material.REPEATER || mat == Material.COMPARATOR + || mat == Material.SNOW || mat == Material.LADDER || mat == Material.VINE || mat == Material.SCAFFOLDING + || mat == Material.AZALEA || mat == Material.FLOWERING_AZALEA || mat == Material.BIG_DRIPLEAF + || mat == Material.CHORUS_FLOWER || mat == Material.CHORUS_PLANT || mat == Material.COCOA + || mat == Material.LILY_PAD || mat == Material.SEA_PICKLE) + return true; + + if(mat.name().endsWith("_CARPET")) + return true; + + if(mat.name().startsWith("POTTED_")) + return true; + + if((mat.name().endsWith("_HEAD") || mat.name().endsWith("_SKULL")) && !mat.name().equals("PISTON_HEAD")) + return true; + + if(mat.data == Candle.class) + return true; + return false; + } + + public static boolean canPlaceWater(Block block, Optional entityYPos) { if (block.getType().isSolid()) { if (block.getType() == Material.CHAIN && ((Chain)block.getBlockData()).getAxis() == Axis.Y && !((Chain)block.getBlockData()).isWaterlogged()) @@ -308,7 +335,8 @@ public class LegacyMats { && !((Stairs)block.getBlockData()).isWaterlogged()) return false; if (block.getType().data == Stairs.class && ((Stairs)block.getBlockData()).getHalf() == Bisected.Half.BOTTOM - && !((Stairs)block.getBlockData()).isWaterlogged() && (int)entityYPos != block.getLocation().getBlockY()) + && !((Stairs)block.getBlockData()).isWaterlogged() + && (!entityYPos.isPresent() || (int)entityYPos.get().doubleValue() != block.getLocation().getBlockY())) return false; if ((block.getType().data == Fence.class || block.getType().data == Wall.class) && !((Waterlogged)block.getBlockData()).isWaterlogged()) diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java index ef63e98..9ef3a15 100644 --- a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java @@ -582,7 +582,7 @@ public class Bot extends ServerPlayer implements Terminator { Location loc = new Location(world, x, position().y - 0.01, z); Block block = world.getBlockAt(loc); - if ((block.getType().isSolid() || canStandOn(block.getType())) && BotUtils.overlaps(playerBox, block.getBoundingBox())) { + if ((block.getType().isSolid() || LegacyMats.canStandOn(block.getType())) && BotUtils.overlaps(playerBox, block.getBoundingBox())) { if (!locations.contains(block.getLocation())) { standingOn.add(block); locations.add(block.getLocation()); @@ -623,31 +623,6 @@ public class Bot extends ServerPlayer implements Terminator { return standingOn; } - /** - * Checks for non-solid blocks that can hold an entity up. - */ - private boolean canStandOn(Material mat) { - if(mat == Material.END_ROD || mat == Material.FLOWER_POT || mat == Material.REPEATER || mat == Material.COMPARATOR - || mat == Material.SNOW || mat == Material.LADDER || mat == Material.VINE || mat == Material.SCAFFOLDING - || mat == Material.AZALEA || mat == Material.FLOWERING_AZALEA || mat == Material.BIG_DRIPLEAF - || mat == Material.CHORUS_FLOWER || mat == Material.CHORUS_PLANT || mat == Material.COCOA - || mat == Material.LILY_PAD || mat == Material.SEA_PICKLE) - return true; - - if(mat.name().endsWith("_CARPET")) - return true; - - if(mat.name().startsWith("POTTED_")) - return true; - - if((mat.name().endsWith("_HEAD") || mat.name().endsWith("_SKULL")) && !mat.name().equals("PISTON_HEAD")) - return true; - - if(mat.data == Candle.class) - return true; - return false; - } - @Override public boolean isBotOnGround() { return groundTicks != 0; @@ -824,6 +799,11 @@ public class Bot extends ServerPlayer implements Terminator { public Location getLocation() { return getBukkitEntity().getLocation(); } + + @Override + public BoundingBox getBotBoundingBox() { + return getBukkitEntity().getBoundingBox(); + } @Override public void setBotPitch(float pitch) { @@ -940,4 +920,9 @@ public class Bot extends ServerPlayer implements Terminator { public void doTick() { baseTick(); } + + @Override + public World.Environment getDimension() { + return getBukkitEntity().getWorld().getEnvironment(); + } }