Merge pull request #57 from ThisTestUser/fixes

Bug fixes / Enhancements
This commit is contained in:
Badbird5907
2023-01-05 19:01:53 -05:00
committed by GitHub
16 changed files with 1544 additions and 374 deletions

32
.github/workflows/compile.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: "Compile"
on: [push, pull_request]
jobs:
gradle:
strategy:
matrix:
os: [ ubuntu-latest ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 17
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Execute Gradle build
run: ./gradlew build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.2.4
if: success()
with:
name: TerminatorPlus
path: build/libs/

View File

@@ -1,68 +0,0 @@
name: "CodeQL"
on: [push, pull_request]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Cache local repo
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
gradle:
strategy:
matrix:
os: [ ubuntu-latest ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 17
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Execute Gradle build
run: ./gradlew build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.2.4
if: success()
with:
name: TerminatorPlus
path: build/libs/

View File

@@ -10,13 +10,17 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
public interface BotManager { public interface BotManager {
Location getSpawnLoc();
void setSpawnLoc(Location loc);
Set<Terminator> fetch(); Set<Terminator> fetch();
Agent getAgent(); Agent getAgent();
void add(Terminator bot); void add(Terminator bot);
Terminator getFirst(String name); Terminator getFirst(String name, Location target);
List<String> fetchNames(); List<String> fetchNames();
@@ -50,4 +54,7 @@ public interface BotManager {
void setMobTarget(boolean mobTarget); void setMobTarget(boolean mobTarget);
boolean addToPlayerList();
void setAddToPlayerList(boolean addPlayerList);
} }

View File

@@ -4,13 +4,17 @@ import com.mojang.authlib.GameProfile;
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork; import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.List;
import java.util.UUID; import java.util.UUID;
public interface Terminator { public interface Terminator {
@@ -30,6 +34,8 @@ public interface Terminator {
boolean hasNeuralNetwork(); boolean hasNeuralNetwork();
Location getLocation(); Location getLocation();
BoundingBox getBotBoundingBox();
boolean isBotAlive(); //Has to be named like this because paper re-obfuscates it boolean isBotAlive(); //Has to be named like this because paper re-obfuscates it
@@ -37,8 +43,6 @@ public interface Terminator {
float getBotMaxHealth(); float getBotMaxHealth();
void ignite();
boolean isBotOnFire(); boolean isBotOnFire();
boolean isFalling(); boolean isFalling();
@@ -50,6 +54,8 @@ public interface Terminator {
boolean isBotInWater(); boolean isBotInWater();
boolean isBotOnGround(); boolean isBotOnGround();
List<Block> getStandingOn();
void setBotPitch(float pitch); void setBotPitch(float pitch);
@@ -106,14 +112,18 @@ public interface Terminator {
void addVelocity(Vector velocity); void addVelocity(Vector velocity);
int getAliveTicks(); int getAliveTicks();
int getNoFallTicks();
boolean tickDelay(int ticks); boolean tickDelay(int ticks);
void renderBot(Object packetListener, boolean login); void renderBot(Object packetListener, boolean login);
void setOnFirePackets(boolean onFire);
UUID getTargetPlayer(); UUID getTargetPlayer();
void setTargetPlayer(UUID target); void setTargetPlayer(UUID target);
boolean isInPlayerList();
World.Environment getDimension();
} }

View File

@@ -7,6 +7,7 @@ public enum EnumTargetGoal {
NEAREST_VULNERABLE_PLAYER("Locate the nearest real player that is in either Survival or Adventure mode."), NEAREST_VULNERABLE_PLAYER("Locate the nearest real player that is in either Survival or Adventure mode."),
NEAREST_PLAYER("Locate the nearest real online player, despite the gamemode."), NEAREST_PLAYER("Locate the nearest real online player, despite the gamemode."),
NEAREST_HOSTILE("Locate the nearest hostile entity."), NEAREST_HOSTILE("Locate the nearest hostile entity."),
NEAREST_RAIDER("Locate the nearest raider."),
NEAREST_MOB("Locate the nearest mob."), NEAREST_MOB("Locate the nearest mob."),
NEAREST_BOT("Locate the nearest bot."), NEAREST_BOT("Locate the nearest bot."),
NEAREST_BOT_DIFFER("Locate the nearest bot with a different username."), NEAREST_BOT_DIFFER("Locate the nearest bot with a different username."),
@@ -20,10 +21,12 @@ public enum EnumTargetGoal {
this.put("nearestvulnerableplayer", NEAREST_VULNERABLE_PLAYER); this.put("nearestvulnerableplayer", NEAREST_VULNERABLE_PLAYER);
this.put("nearestplayer", NEAREST_PLAYER); this.put("nearestplayer", NEAREST_PLAYER);
this.put("nearesthostile", NEAREST_HOSTILE); this.put("nearesthostile", NEAREST_HOSTILE);
this.put("nearestraider", NEAREST_RAIDER);
this.put("nearestmob", NEAREST_MOB); this.put("nearestmob", NEAREST_MOB);
this.put("nearestbot", NEAREST_BOT); this.put("nearestbot", NEAREST_BOT);
this.put("nearestbotdiffer", NEAREST_BOT_DIFFER); this.put("nearestbotdiffer", NEAREST_BOT_DIFFER);
this.put("nearestbotdifferalpha", NEAREST_BOT_DIFFER_ALPHA); this.put("nearestbotdifferalpha", NEAREST_BOT_DIFFER_ALPHA);
this.put("player", PLAYER);
} }
}; };

View File

@@ -11,18 +11,25 @@ import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent;
import net.nuggetmc.tplus.api.event.BotDeathEvent; import net.nuggetmc.tplus.api.event.BotDeathEvent;
import net.nuggetmc.tplus.api.event.BotFallDamageEvent; import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
import net.nuggetmc.tplus.api.event.TerminatorLocateTargetEvent; import net.nuggetmc.tplus.api.event.TerminatorLocateTargetEvent;
import net.nuggetmc.tplus.api.utils.BotUtils;
import net.nuggetmc.tplus.api.utils.MathUtils; import net.nuggetmc.tplus.api.utils.MathUtils;
import net.nuggetmc.tplus.api.utils.PlayerUtils; import net.nuggetmc.tplus.api.utils.PlayerUtils;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.*;
import org.bukkit.entity.*; import org.bukkit.entity.*;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import com.google.common.base.Optional;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Pattern; import java.util.regex.Pattern;
// Yes, this code is very unoptimized, I know. // Yes, this code is very unoptimized, I know.
@@ -43,24 +50,12 @@ public class LegacyAgent extends Agent {
private final Map<BukkitRunnable, Byte> mining = new HashMap<>(); private final Map<BukkitRunnable, Byte> mining = new HashMap<>();
private final Set<Terminator> fallDamageCooldown = new HashSet<>(); private final Set<Terminator> fallDamageCooldown = new HashSet<>();
public boolean offsets = true; public boolean offsets = true;
private List<Material> instantBreakBlocks = Arrays.asList( private List<LivingEntity> botsInPlayerList;
Material.TALL_GRASS,
Material.GRASS,
Material.KELP_PLANT,
Material.WHEAT,
Material.POTATOES,
Material.CARROT,
Material.BEETROOT,
Material.SUGAR_CANE,
Material.SWEET_BERRY_BUSH,
Material.LILY_PAD,
Material.DANDELION,
Material.POPPY,
Material.ROSE_BUSH,
Material.PUMPKIN_STEM,
Material.MELON_STEM
);
private EnumTargetGoal goal; private EnumTargetGoal goal;
private BoundingBox region;
private double regionWeightX;
private double regionWeightY;
private double regionWeightZ;
public LegacyAgent(BotManager manager, Plugin plugin) { public LegacyAgent(BotManager manager, Plugin plugin) {
super(manager, plugin); super(manager, plugin);
@@ -75,7 +70,8 @@ public class LegacyAgent extends Agent {
@Override @Override
protected void tick() { protected void tick() {
manager.fetch().forEach(this::tickBot); botsInPlayerList = manager.fetch().stream().filter(t -> t.isInPlayerList()).map(b -> b.getBukkitEntity()).toList();
manager.fetch().forEach(this::tickBot);
} }
private void center(Terminator bot) { private void center(Terminator bot) {
@@ -115,6 +111,8 @@ public class LegacyAgent extends Agent {
Location loc = bot.getLocation(); Location loc = bot.getLocation();
LivingEntity livingTarget = locateTarget(bot, loc); LivingEntity livingTarget = locateTarget(bot, loc);
blockCheck.tryPreMLG(bot, loc);
if (livingTarget == null) { if (livingTarget == null) {
stopMining(bot); stopMining(bot);
return; return;
@@ -180,11 +178,13 @@ public class LegacyAgent extends Agent {
if (checkAt(bot, block, botPlayer)) return; if (checkAt(bot, block, botPlayer)) return;
if (checkFence(bot, loc.getBlock(), botPlayer)) return; if (checkFenceAndGates(bot, loc.getBlock(), botPlayer)) return;
if (checkObstacles(bot, loc.getBlock(), botPlayer)) return;
if (checkDown(bot, botPlayer, livingTarget.getLocation(), bothXZ)) return; if (checkDown(bot, botPlayer, livingTarget.getLocation(), bothXZ)) return;
if ((withinTargetXZ || sameXZ) && checkUp(bot, livingTarget, botPlayer, target, withinTargetXZ)) return; if ((withinTargetXZ || sameXZ) && checkUp(bot, livingTarget, botPlayer, target, withinTargetXZ, sameXZ)) return;
if (bothXZ) sideResult = checkSide(bot, livingTarget, botPlayer); if (bothXZ) sideResult = checkSide(bot, livingTarget, botPlayer);
@@ -303,7 +303,7 @@ public class LegacyAgent extends Agent {
Material itemType; Material itemType;
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { if (bot.getDimension() == World.Environment.NETHER) {
itemType = Material.TWISTING_VINES; itemType = Material.TWISTING_VINES;
} else { } else {
itemType = Material.WATER_BUCKET; itemType = Material.WATER_BUCKET;
@@ -344,26 +344,50 @@ public class LegacyAgent extends Agent {
Material itemType; Material itemType;
Material placeType; Material placeType;
Sound sound; Sound sound;
Location groundLoc = null;
boolean nether = bot.getDimension() == World.Environment.NETHER;
double yPos = bot.getBukkitEntity().getLocation().getY();
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { if (nether) {
itemType = Material.TWISTING_VINES; itemType = Material.TWISTING_VINES;
sound = Sound.BLOCK_WEEPING_VINES_PLACE; sound = Sound.BLOCK_WEEPING_VINES_PLACE;
placeType = itemType; placeType = itemType;
for (Block block : event.getStandingOn()) {
if (LegacyMats.canPlaceTwistingVines(block)) {
groundLoc = block.getLocation();
break;
}
}
} else { } else {
itemType = Material.WATER_BUCKET; itemType = Material.WATER_BUCKET;
sound = Sound.ITEM_BUCKET_EMPTY; sound = Sound.ITEM_BUCKET_EMPTY;
placeType = Material.WATER; placeType = Material.WATER;
for (Block block : event.getStandingOn()) {
if (LegacyMats.canPlaceWater(block, Optional.of(yPos))) {
groundLoc = block.getLocation();
break;
}
}
} }
Location loc = bot.getLocation(); if (groundLoc == null) return;
if (!loc.clone().add(0, -1, 0).getBlock().getType().isSolid()) return; Location loc = !LegacyMats.shouldReplace(groundLoc.getBlock(), yPos, nether) ? groundLoc.add(0, 1, 0) : groundLoc;
boolean waterloggable = !nether && loc.getBlock().getBlockData() instanceof Waterlogged;
boolean waterlogged = waterloggable && ((Waterlogged)loc.getBlock().getBlockData()).isWaterlogged();
event.setCancelled(true); event.setCancelled(true);
if (loc.getBlock().getType() != placeType) { if (loc.getBlock().getType() != placeType && !waterlogged) {
bot.punch(); bot.punch();
loc.getBlock().setType(placeType); if (waterloggable) {
Waterlogged data = (Waterlogged)loc.getBlock().getBlockData();
data.setWaterlogged(true);
loc.getBlock().setBlockData(data);
} else
loc.getBlock().setType(placeType);
world.playSound(loc, sound, 1, 1); world.playSound(loc, sound, 1, 1);
if (itemType == Material.WATER_BUCKET) { if (itemType == Material.WATER_BUCKET) {
@@ -372,11 +396,18 @@ public class LegacyAgent extends Agent {
scheduler.runTaskLater(plugin, () -> { scheduler.runTaskLater(plugin, () -> {
Block block = loc.getBlock(); Block block = loc.getBlock();
if (block.getType() == Material.WATER) { boolean waterloggedNow = !nether && block.getBlockData() instanceof Waterlogged
&& ((Waterlogged)block.getBlockData()).isWaterlogged();
if (block.getType() == Material.WATER || waterloggedNow) {
bot.look(BlockFace.DOWN); bot.look(BlockFace.DOWN);
bot.setItem(new ItemStack(Material.WATER_BUCKET)); bot.setItem(new ItemStack(Material.WATER_BUCKET));
world.playSound(loc, Sound.ITEM_BUCKET_FILL, 1, 1); world.playSound(loc, Sound.ITEM_BUCKET_FILL, 1, 1);
block.setType(Material.AIR); if (waterloggedNow) {
Waterlogged data = (Waterlogged)loc.getBlock().getBlockData();
data.setWaterlogged(false);
loc.getBlock().setBlockData(data);
} else
block.setType(Material.AIR);
} }
}, 5); }, 5);
} }
@@ -442,7 +473,7 @@ public class LegacyAgent extends Agent {
if (level == null) { if (level == null) {
resetHand(npc, target, playerNPC); resetHand(npc, target, playerNPC);
return 1; return 1;
} else if (level.isSide()) { } else if (level.isSide() || level == LegacyLevel.BELOW || level == LegacyLevel.ABOVE) {
return 0; return 0;
} else { } else {
return 2; return 2;
@@ -457,6 +488,71 @@ public class LegacyAgent extends Agent {
BlockFace dir = player.getFacing(); BlockFace dir = player.getFacing();
LegacyLevel level = null; LegacyLevel level = null;
Block get = null; Block get = null;
BoundingBox box = player.getBoundingBox();
double[] xVals = new double[]{
box.getMinX(),
box.getMaxX() - 0.01
};
double[] zVals = new double[]{
box.getMinZ(),
box.getMaxZ() - 0.01
};
List<Location> locStanding = new ArrayList<>();
for (double x : xVals) {
for (double z : zVals) {
Location loc = new Location(player.getWorld(), Math.floor(x), npc.getLocation().getBlockY(), Math.floor(z));
if (!locStanding.contains(loc))
locStanding.add(loc);
}
}
Collections.sort(locStanding, (a, b) ->
Double.compare(BotUtils.getHorizSqDist(a, player.getLocation()), BotUtils.getHorizSqDist(b, player.getLocation())));
//Break potential obstructing walls
for (Location loc : locStanding) {
boolean up = false;
get = loc.getBlock();
if (!LegacyMats.FENCE.contains(get.getType())) {
up = true;
get = loc.add(0, 1, 0).getBlock();
if (!LegacyMats.FENCE.contains(get.getType())) {
get = null;
}
}
if (get != null) {
int distanceX = get.getLocation().getBlockX() - player.getLocation().getBlockX();
int distanceZ = get.getLocation().getBlockZ() - player.getLocation().getBlockZ();
if (distanceX == 1 && distanceZ == 0) {
if (dir == BlockFace.NORTH || dir == BlockFace.SOUTH) {
npc.faceLocation(get.getLocation());
level = up ? LegacyLevel.EAST : LegacyLevel.EAST_D;
}
} else if (distanceX == -1 && distanceZ == 0) {
if (dir == BlockFace.NORTH || dir == BlockFace.SOUTH) {
npc.faceLocation(get.getLocation());
level = up ? LegacyLevel.WEST : LegacyLevel.WEST_D;
}
} else if (distanceX == 0 && distanceZ == 1) {
if (dir == BlockFace.EAST || dir == BlockFace.WEST) {
npc.faceLocation(get.getLocation());
level = up ? LegacyLevel.SOUTH : LegacyLevel.SOUTH_D;
}
} else if (distanceX == 0 && distanceZ == -1) {
if (dir == BlockFace.EAST || dir == BlockFace.WEST) {
npc.faceLocation(get.getLocation());
level = up ? LegacyLevel.NORTH : LegacyLevel.NORTH_D;
}
}
if (level != null) {
preBreak(npc, player, get, level);
return level;
}
}
}
switch (dir) { switch (dir) {
case NORTH: case NORTH:
@@ -466,6 +562,35 @@ public class LegacyAgent extends Agent {
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) { } else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
get = get.getLocation().add(0, -1, 0).getBlock(); get = get.getLocation().add(0, -1, 0).getBlock();
level = LegacyLevel.NORTH_D; level = LegacyLevel.NORTH_D;
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
get = get.getLocation().add(0, -2, 0).getBlock();
level = LegacyLevel.NORTH_D_2;
} else {
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
if(standing == null)
break;
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
if(obstructed) {
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
//Break standing block
get = standing;
level = LegacyLevel.BELOW;
} else {
//Break above
Block above = npc.getLocation().add(0, 2, 0).getBlock();
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
if(!LegacyMats.BREAK.contains(above.getType())) {
get = above;
level = LegacyLevel.ABOVE;
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
get = aboveSide;
level = LegacyLevel.NORTH_U;
}
}
}
} }
break; break;
case SOUTH: case SOUTH:
@@ -475,6 +600,35 @@ public class LegacyAgent extends Agent {
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) { } else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
get = get.getLocation().add(0, -1, 0).getBlock(); get = get.getLocation().add(0, -1, 0).getBlock();
level = LegacyLevel.SOUTH_D; level = LegacyLevel.SOUTH_D;
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
get = get.getLocation().add(0, -2, 0).getBlock();
level = LegacyLevel.SOUTH_D_2;
} else {
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
if(standing == null)
break;
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
if(obstructed) {
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
//Break standing block
get = standing;
level = LegacyLevel.BELOW;
} else {
//Break above
Block above = npc.getLocation().add(0, 2, 0).getBlock();
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
if(!LegacyMats.BREAK.contains(above.getType())) {
get = above;
level = LegacyLevel.ABOVE;
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
get = aboveSide;
level = LegacyLevel.SOUTH_U;
}
}
}
} }
break; break;
case EAST: case EAST:
@@ -484,6 +638,35 @@ public class LegacyAgent extends Agent {
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) { } else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
get = get.getLocation().add(0, -1, 0).getBlock(); get = get.getLocation().add(0, -1, 0).getBlock();
level = LegacyLevel.EAST_D; level = LegacyLevel.EAST_D;
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
get = get.getLocation().add(0, -2, 0).getBlock();
level = LegacyLevel.EAST_D_2;
} else {
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
if(standing == null)
break;
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
if(obstructed) {
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
//Break standing block
get = standing;
level = LegacyLevel.BELOW;
} else {
//Break above
Block above = npc.getLocation().add(0, 2, 0).getBlock();
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
if(!LegacyMats.BREAK.contains(above.getType())) {
get = above;
level = LegacyLevel.ABOVE;
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
get = aboveSide;
level = LegacyLevel.EAST_U;
}
}
}
} }
break; break;
case WEST: case WEST:
@@ -493,27 +676,91 @@ public class LegacyAgent extends Agent {
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) { } else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
get = get.getLocation().add(0, -1, 0).getBlock(); get = get.getLocation().add(0, -1, 0).getBlock();
level = LegacyLevel.WEST_D; level = LegacyLevel.WEST_D;
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
get = get.getLocation().add(0, -2, 0).getBlock();
level = LegacyLevel.WEST_D_2;
} else {
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
if(standing == null)
break;
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
if(obstructed) {
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
//Break standing block
get = standing;
level = LegacyLevel.BELOW;
} else {
//Break above
Block above = npc.getLocation().add(0, 2, 0).getBlock();
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
if(!LegacyMats.BREAK.contains(above.getType())) {
get = above;
level = LegacyLevel.ABOVE;
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
get = aboveSide;
level = LegacyLevel.WEST_U;
}
}
}
} }
break; break;
default: default:
break; break;
} }
if (level == LegacyLevel.EAST_D || level == LegacyLevel.WEST_D || level == LegacyLevel.NORTH_D || level == LegacyLevel.SOUTH_D) { if (level == LegacyLevel.EAST_D || level == LegacyLevel.WEST_D || level == LegacyLevel.NORTH_D || level == LegacyLevel.SOUTH_D
|| level == LegacyLevel.EAST_D_2 || level == LegacyLevel.WEST_D_2 || level == LegacyLevel.NORTH_D_2 || level == LegacyLevel.SOUTH_D_2) {
if (LegacyMats.AIR.contains(player.getLocation().add(0, 2, 0).getBlock().getType()) if (LegacyMats.AIR.contains(player.getLocation().add(0, 2, 0).getBlock().getType())
&& LegacyMats.AIR.contains(get.getLocation().add(0, 2, 0).getBlock().getType())) { && LegacyMats.AIR.contains(get.getLocation().add(0, 2, 0).getBlock().getType())
&& !LegacyMats.FENCE.contains(get.getType()) && !LegacyMats.GATES.contains(get.getType())) {
return null; return null;
} }
} }
if (level == LegacyLevel.ABOVE || level == LegacyLevel.BELOW) {
Block check;
switch (dir) {
case NORTH:
check = player.getLocation().add(0, 2, -1).getBlock();
break;
case SOUTH:
check = player.getLocation().add(0, 2, 1).getBlock();
break;
case EAST:
check = player.getLocation().add(1, 2, 0).getBlock();
break;
case WEST:
check = player.getLocation().add(-1, 2, 0).getBlock();
break;
default:
check = null;
}
if (LegacyMats.AIR.contains(player.getLocation().add(0, 2, 0).getBlock().getType())
&& LegacyMats.AIR.contains(check.getType()))
return null;
}
if (level != null) { if (level != null) {
if (level == LegacyLevel.BELOW) {
noJump.add(player);
scheduler.runTaskLater(plugin, () -> {
noJump.remove(player);
}, 15);
npc.look(BlockFace.DOWN);
downMine(npc, player, get);
} else if (level == LegacyLevel.ABOVE)
npc.look(BlockFace.UP);
preBreak(npc, player, get, level); preBreak(npc, player, get, level);
} }
return level; return level;
} }
private boolean checkUp(Terminator npc, LivingEntity target, LivingEntity playerNPC, Location loc, boolean c) { private boolean checkUp(Terminator npc, LivingEntity target, LivingEntity playerNPC, Location loc, boolean c, boolean sameXZ) {
Location a = playerNPC.getLocation(); Location a = playerNPC.getLocation();
Location b = target.getLocation(); Location b = target.getLocation();
@@ -568,24 +815,25 @@ public class LegacyAgent extends Agent {
npc.look(BlockFace.DOWN); npc.look(BlockFace.DOWN);
// maybe put this in lower if statement onGround() // maybe put this in lower if statement onGround()
scheduler.runTaskLater(plugin, () -> { if (m0 != Material.WATER)
npc.sneak(); scheduler.runTaskLater(plugin, () -> {
npc.setItem(new ItemStack(Material.COBBLESTONE)); npc.sneak();
npc.punch(); npc.setItem(new ItemStack(Material.COBBLESTONE));
npc.look(BlockFace.DOWN); npc.punch();
npc.look(BlockFace.DOWN);
scheduler.runTaskLater(plugin, () -> {
npc.look(BlockFace.DOWN); scheduler.runTaskLater(plugin, () -> {
}, 1); npc.look(BlockFace.DOWN);
}, 1);
blockCheck.placeBlock(npc, playerNPC, place);
blockCheck.placeBlock(npc, playerNPC, place);
if (!towerList.containsKey(playerNPC)) {
if (c) { if (!towerList.containsKey(playerNPC)) {
towerList.put(playerNPC, playerNPC.getLocation()); if (c) {
} towerList.put(playerNPC, playerNPC.getLocation());
} }
}, 5); }
}, 3);
if (npc.isBotOnGround()) { if (npc.isBotOnGround()) {
if (target.getLocation().distance(playerNPC.getLocation()) < 16) { if (target.getLocation().distance(playerNPC.getLocation()) < 16) {
@@ -645,6 +893,16 @@ public class LegacyAgent extends Agent {
} }
return true; return true;
} else if (sameXZ && LegacyMats.BREAK.contains(m1)) {
Block block = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
if (block != null && block.getLocation().getBlockY() == playerNPC.getLocation().getBlockY()
&& !LegacyMats.BREAK.contains(block.getType())) {
npc.look(BlockFace.DOWN);
downMine(npc, playerNPC, block);
preBreak(npc, playerNPC, block, LegacyLevel.BELOW);
return true;
}
} }
} }
@@ -657,7 +915,9 @@ public class LegacyAgent extends Agent {
return false; return false;
if (c && npc.getLocation().getBlockY() > loc.getBlockY() + 1) { if (c && npc.getLocation().getBlockY() > loc.getBlockY() + 1) {
Block block = npc.getLocation().add(0, -1, 0).getBlock(); Block block = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
if (block == null)
return false;
npc.look(BlockFace.DOWN); npc.look(BlockFace.DOWN);
downMine(npc, player, block); downMine(npc, player, block);
@@ -671,7 +931,9 @@ public class LegacyAgent extends Agent {
b.setY(0); b.setY(0);
if (npc.getLocation().getBlockY() > loc.getBlockY() + 10 && a.distance(b) < 10) { if (npc.getLocation().getBlockY() > loc.getBlockY() + 10 && a.distance(b) < 10) {
Block block = npc.getLocation().add(0, -1, 0).getBlock(); Block block = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
if (block == null)
return false;
npc.look(BlockFace.DOWN); npc.look(BlockFace.DOWN);
downMine(npc, player, block); downMine(npc, player, block);
@@ -719,14 +981,31 @@ public class LegacyAgent extends Agent {
} }
} }
private boolean checkFence(Terminator bot, Block block, LivingEntity player) { private boolean checkFenceAndGates(Terminator bot, Block block, LivingEntity player) {
if (LegacyMats.FENCE.contains(block.getType())) { if (LegacyMats.FENCE.contains(block.getType()) || LegacyMats.GATES.contains(block.getType())) {
preBreak(bot, player, block, LegacyLevel.AT_D); preBreak(bot, player, block, LegacyLevel.AT_D);
return true; return true;
} }
return false; return false;
} }
private boolean checkObstacles(Terminator bot, Block block, LivingEntity player) {
if (LegacyMats.OBSTACLES.contains(block.getType()) || isDoorObstacle(block)) {
preBreak(bot, player, block, LegacyLevel.AT_D);
return true;
}
return false;
}
private boolean isDoorObstacle(Block block) {
if (block.getType().data == Door.class)
return true;
if (block.getType().data == TrapDoor.class && ((TrapDoor)block.getBlockData()).isOpen())
return true;
return false;
}
private boolean checkAt(Terminator bot, Block block, LivingEntity player) { private boolean checkAt(Terminator bot, Block block, LivingEntity player) {
if (LegacyMats.BREAK.contains(block.getType())) { if (LegacyMats.BREAK.contains(block.getType())) {
@@ -751,13 +1030,15 @@ public class LegacyAgent extends Agent {
bot.setItem(new ItemStack(item)); bot.setItem(new ItemStack(item));
if (level == LegacyLevel.EAST_D || level == LegacyLevel.NORTH_D || level == LegacyLevel.SOUTH_D || level == LegacyLevel.WEST_D) { if (level.isSideDown() || level.isSideDown2()) {
bot.setBotPitch(69); bot.setBotPitch(69);
scheduler.runTaskLater(plugin, () -> { scheduler.runTaskLater(plugin, () -> {
btCheck.put(player, true); btCheck.put(player, true);
}, 5); }, 5);
} else if (level == LegacyLevel.AT_D || level == LegacyLevel.AT) { } else if (level.isSideUp()) {
bot.setBotPitch(-53);
}else if (level == LegacyLevel.AT_D || level == LegacyLevel.AT) {
Location blockLoc = block.getLocation().add(0.5, -1, 0.5); Location blockLoc = block.getLocation().add(0.5, -1, 0.5);
bot.faceLocation(blockLoc); bot.faceLocation(blockLoc);
} }
@@ -777,10 +1058,10 @@ public class LegacyAgent extends Agent {
miningAnim.put(player, task); miningAnim.put(player, task);
} }
blockBreakEffect(player, block, level); blockBreakEffect(bot, player, block, new LegacyLevel.LevelWrapper(level));
} }
private void blockBreakEffect(LivingEntity player, Block block, LegacyLevel level) { private void blockBreakEffect(Terminator bot, LivingEntity player, Block block, LegacyLevel.LevelWrapper wrapper) {
if (LegacyMats.NO_CRACK.contains(block.getType())) return; if (LegacyMats.NO_CRACK.contains(block.getType())) return;
@@ -792,47 +1073,45 @@ public class LegacyAgent extends Agent {
byte i = mining.get(this); byte i = mining.get(this);
Block cur; Block cur;
switch (level) { if (wrapper.getLevel() == null)
case ABOVE: cur = player.getLocation().add(0, 1, 0).getBlock();
cur = player.getLocation().add(0, 2, 0).getBlock(); else if (wrapper.getLevel() == LegacyLevel.BELOW)
break; cur = bot.getStandingOn().isEmpty() ? null : bot.getStandingOn().get(0);
case BELOW: else
cur = player.getLocation().add(0, -1, 0).getBlock(); cur = wrapper.getLevel().offset(player.getLocation()).getBlock();
break;
case NORTH:
cur = player.getLocation().add(0, 1, -1).getBlock();
break;
case SOUTH:
cur = player.getLocation().add(0, 1, 1).getBlock();
break;
case EAST:
cur = player.getLocation().add(1, 1, 0).getBlock();
break;
case WEST:
cur = player.getLocation().add(-1, 1, 0).getBlock();
break;
case NORTH_D:
cur = player.getLocation().add(0, 0, -1).getBlock();
break;
case SOUTH_D:
cur = player.getLocation().add(0, 0, 1).getBlock();
break;
case EAST_D:
cur = player.getLocation().add(1, 0, 0).getBlock();
break;
case WEST_D:
cur = player.getLocation().add(-1, 0, 0).getBlock();
break;
case AT_D:
cur = player.getLocation().getBlock();
break;
default:
cur = player.getLocation().add(0, 1, 0).getBlock();
}
// Fix boat clutching while breaking block
// As a side effect, the bot is able to break multiple blocks at once while over lava
if ((wrapper.getLevel().isSideAt() || wrapper.getLevel().isSideUp())
&& bot.getLocation().add(0, -2, 0).getBlock().getType() == Material.LAVA
&& block.getLocation().clone().add(0, 1, 0).equals(cur.getLocation())) {
cur = block;
wrapper.setLevel(wrapper.getLevel().sideDown());
if (wrapper.getLevel().isSideDown() || wrapper.getLevel().isSideDown2())
bot.setBotPitch(69);
else if (wrapper.getLevel().isSideUp())
bot.setBotPitch(-53);
else if (wrapper.getLevel().isSide())
bot.setBotPitch(0);
}
if ((wrapper.getLevel().isSideAt() || wrapper.getLevel().isSideDown())
&& bot.getLocation().add(0, -1, 0).getBlock().getType() == Material.LAVA
&& block.getLocation().clone().add(0, -1, 0).equals(cur.getLocation())) {
cur = block;
wrapper.setLevel(wrapper.getLevel().sideUp());
if (wrapper.getLevel().isSideDown() || wrapper.getLevel().isSideDown2())
bot.setBotPitch(69);
else if (wrapper.getLevel().isSideUp())
bot.setBotPitch(-53);
else if (wrapper.getLevel().isSide())
bot.setBotPitch(0);
}
// wow this repeated code is so bad lmao // wow this repeated code is so bad lmao
if (player.isDead() || (!block.equals(cur) || block.getType() != cur.getType())) { if (player.isDead() || cur == null || (!block.equals(cur) || block.getType() != cur.getType())) {
this.cancel(); this.cancel();
TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1); TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1);
@@ -857,7 +1136,7 @@ public class LegacyAgent extends Agent {
block.breakNaturally(); block.breakNaturally();
if (level == LegacyLevel.ABOVE) { if (wrapper.getLevel() == LegacyLevel.ABOVE) {
noJump.add(player); noJump.add(player);
scheduler.runTaskLater(plugin, () -> { scheduler.runTaskLater(plugin, () -> {
@@ -875,10 +1154,13 @@ public class LegacyAgent extends Agent {
all.playSound(block.getLocation(), sound, SoundCategory.BLOCKS, (float) 0.3, 1); all.playSound(block.getLocation(), sound, SoundCategory.BLOCKS, (float) 0.3, 1);
} }
if (block.getType() == Material.BARRIER || block.getType() == Material.BEDROCK || block.getType() == Material.END_PORTAL_FRAME) if (block.getType() == Material.BARRIER || block.getType() == Material.BEDROCK || block.getType() == Material.END_PORTAL_FRAME
|| block.getType() == Material.STRUCTURE_BLOCK || block.getType() == Material.STRUCTURE_BLOCK
|| block.getType() == Material.COMMAND_BLOCK || block.getType() == Material.REPEATING_COMMAND_BLOCK
|| block.getType() == Material.CHAIN_COMMAND_BLOCK)
return; return;
if (instantBreakBlocks.contains(block.getType())) { // instant break blocks if (LegacyMats.INSTANT_BREAK.contains(block.getType())) { // instant break blocks
block.breakNaturally(); block.breakNaturally();
return; return;
} }
@@ -924,7 +1206,7 @@ public class LegacyAgent extends Agent {
Location loc = bot.getLocation(); Location loc = bot.getLocation();
if (bot.isBotOnFire()) { if (bot.isBotOnFire()) {
if (bot.getBukkitEntity().getWorld().getEnvironment() != World.Environment.NETHER) { if (bot.getDimension() != World.Environment.NETHER) {
placeWaterDown(bot, world, loc); placeWaterDown(bot, world, loc);
} }
} }
@@ -932,7 +1214,7 @@ public class LegacyAgent extends Agent {
Material atType = loc.getBlock().getType(); Material atType = loc.getBlock().getType();
if (atType == Material.FIRE || atType == Material.SOUL_FIRE) { 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); placeWaterDown(bot, world, loc);
world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
} else { } else {
@@ -944,7 +1226,7 @@ public class LegacyAgent extends Agent {
} }
if (atType == Material.LAVA) { if (atType == Material.LAVA) {
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { if (bot.getDimension() == World.Environment.NETHER) {
bot.attemptBlockPlace(loc, Material.COBBLESTONE, false); bot.attemptBlockPlace(loc, Material.COBBLESTONE, false);
} else { } else {
placeWaterDown(bot, world, loc); placeWaterDown(bot, world, loc);
@@ -955,7 +1237,7 @@ public class LegacyAgent extends Agent {
Material headType = head.getBlock().getType(); Material headType = head.getBlock().getType();
if (headType == Material.LAVA) { if (headType == Material.LAVA) {
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) { if (bot.getDimension() == World.Environment.NETHER) {
bot.attemptBlockPlace(head, Material.COBBLESTONE, false); bot.attemptBlockPlace(head, Material.COBBLESTONE, false);
} else { } else {
placeWaterDown(bot, world, head); placeWaterDown(bot, world, head);
@@ -963,7 +1245,7 @@ public class LegacyAgent extends Agent {
} }
if (headType == Material.FIRE || headType == Material.SOUL_FIRE) { 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.look(BlockFace.DOWN);
bot.punch(); bot.punch();
world.playSound(head, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); world.playSound(head, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
@@ -1111,12 +1393,39 @@ public class LegacyAgent extends Agent {
bot.attack(target); bot.attack(target);
} }
public void setRegion(BoundingBox region, double regionWeightX, double regionWeightY, double regionWeightZ) {
this.region = region;
this.regionWeightX = regionWeightX;
this.regionWeightY = regionWeightY;
this.regionWeightZ = regionWeightZ;
}
public BoundingBox getRegion() {
return region;
}
public double getRegionWeightX() {
return regionWeightX;
}
public double getRegionWeightY() {
return regionWeightY;
}
public double getRegionWeightZ() {
return regionWeightZ;
}
public EnumTargetGoal getTargetType() {
return goal;
}
public void setTargetType(EnumTargetGoal goal) { public void setTargetType(EnumTargetGoal goal) {
this.goal = goal; this.goal = goal;
} }
public LivingEntity locateTarget(Terminator bot, Location loc, EnumTargetGoal... targetGoal) { private LivingEntity locateTarget(Terminator bot, Location loc, EnumTargetGoal... targetGoal) {
LivingEntity result = null; LivingEntity result = null;
EnumTargetGoal g = goal; EnumTargetGoal g = goal;
@@ -1127,7 +1436,7 @@ public class LegacyAgent extends Agent {
case NEAREST_PLAYER: { case NEAREST_PLAYER: {
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
if (validateCloserEntity(player, loc, result)) { if (!botsInPlayerList.contains(player) && validateCloserEntity(player, loc, result)) {
result = player; result = player;
} }
} }
@@ -1137,7 +1446,7 @@ public class LegacyAgent extends Agent {
case NEAREST_VULNERABLE_PLAYER: { case NEAREST_VULNERABLE_PLAYER: {
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
if (!PlayerUtils.isInvincible(player.getGameMode()) && validateCloserEntity(player, loc, result)) { if (!botsInPlayerList.contains(player) && !PlayerUtils.isInvincible(player.getGameMode()) && validateCloserEntity(player, loc, result)) {
result = player; result = player;
} }
} }
@@ -1154,6 +1463,16 @@ public class LegacyAgent extends Agent {
break; break;
} }
case NEAREST_RAIDER: {
for (LivingEntity entity : bot.getBukkitEntity().getWorld().getLivingEntities()) {
if ((entity instanceof Raider || (entity instanceof Vex vex && vex.getSummoner() instanceof Raider)) && validateCloserEntity(entity, loc, result)) {
result = entity;
}
}
break;
}
case NEAREST_MOB: { case NEAREST_MOB: {
for (LivingEntity entity : bot.getBukkitEntity().getWorld().getLivingEntities()) { for (LivingEntity entity : bot.getBukkitEntity().getWorld().getLivingEntities()) {
@@ -1211,7 +1530,7 @@ public class LegacyAgent extends Agent {
case PLAYER: { //Target a single player. Defaults to NEAREST_VULNERABLE_PLAYER if no player found. case PLAYER: { //Target a single player. Defaults to NEAREST_VULNERABLE_PLAYER if no player found.
if (bot.getTargetPlayer() != null) { if (bot.getTargetPlayer() != null) {
Player player = Bukkit.getPlayer(bot.getTargetPlayer()); Player player = Bukkit.getPlayer(bot.getTargetPlayer());
if (player != null) { if (player != null && !botsInPlayerList.contains(player) && validateCloserEntity(player, loc, null)) {
return player; return player;
} }
} }
@@ -1225,6 +1544,36 @@ public class LegacyAgent extends Agent {
} }
private boolean validateCloserEntity(LivingEntity entity, Location loc, LivingEntity result) { private boolean validateCloserEntity(LivingEntity entity, Location loc, LivingEntity result) {
return loc.getWorld() == entity.getWorld() && !entity.isDead() && (result == null || loc.distance(entity.getLocation()) < loc.distance(result.getLocation())); double regionDistEntity = getWeightedRegionDist(entity.getLocation());
if (regionDistEntity == Double.MAX_VALUE)
return false;
double regionDistResult = result == null ? 0 : getWeightedRegionDist(result.getLocation());
return loc.getWorld() == entity.getWorld() && !entity.isDead()
&& (result == null || (loc.distanceSquared(entity.getLocation()) + regionDistEntity) < (loc.distanceSquared(result.getLocation())) + regionDistResult);
}
private double getWeightedRegionDist(Location loc) {
if (region == null)
return 0;
double diffX = Math.max(0, Math.abs(region.getCenterX() - loc.getX()) - region.getWidthX() * 0.5);
double diffY = Math.max(0, Math.abs(region.getCenterY() - loc.getY()) - region.getHeight() * 0.5);
double diffZ = Math.max(0, Math.abs(region.getCenterZ() - loc.getZ()) - region.getWidthZ() * 0.5);
if (regionWeightX == 0 && regionWeightY == 0 && regionWeightZ == 0)
if (diffX > 0 || diffY > 0 || diffZ > 0)
return Double.MAX_VALUE;
return diffX * diffX * regionWeightX + diffY * diffY * regionWeightY + diffZ * diffZ * regionWeightZ;
}
@Override
public void stopAllTasks() {
super.stopAllTasks();
Iterator<Entry<Block, Short>> itr = crackList.entrySet().iterator();
while(itr.hasNext()) {
Block block = itr.next().getKey();
TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1);
itr.remove();
}
mining.clear();
} }
} }

View File

@@ -1,6 +1,8 @@
package net.nuggetmc.tplus.api.agent.legacyagent; package net.nuggetmc.tplus.api.agent.legacyagent;
import net.nuggetmc.tplus.api.Terminator; import net.nuggetmc.tplus.api.Terminator;
import net.nuggetmc.tplus.api.utils.BotUtils;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
@@ -8,9 +10,15 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin; 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.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set; import java.util.Set;
public class LegacyBlockCheck { public class LegacyBlockCheck {
@@ -135,6 +143,90 @@ public class LegacyBlockCheck {
all.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1); all.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1);
placeFinal(bot, player, block.getLocation()); placeFinal(bot, player, block.getLocation());
} }
public boolean tryPreMLG(Terminator bot, Location botLoc) {
if(bot.isBotOnGround() || bot.getVelocity().getY() >= -0.8D || bot.getNoFallTicks() > 7)
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<Location> 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<Location> 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<Location> 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) { public void clutch(Terminator bot, LivingEntity target) {
Location botLoc = bot.getLocation(); Location botLoc = bot.getLocation();

View File

@@ -4,32 +4,162 @@ import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
public enum LegacyLevel { import org.bukkit.Location;
ABOVE,
BELOW,
AT,
AT_D,
NORTH,
SOUTH,
EAST,
WEST,
NORTH_D,
SOUTH_D,
EAST_D,
WEST_D;
private static final Set<LegacyLevel> SIDE = new HashSet<>(Arrays.asList( public enum LegacyLevel {
ABOVE(0, 2, 0),
BELOW(0, -1, 0),
AT(0, 1, 0),
AT_D(0, 0, 0),
NORTH_U(0, 2, -1),
SOUTH_U(0, 2, 1),
EAST_U(1, 2, 0),
WEST_U(-1, 2, 0),
NORTH(0, 1, -1),
SOUTH(0, 1, 1),
EAST(1, 1, 0),
WEST(-1, 1, 0),
NORTH_D(0, 0, -1),
SOUTH_D(0, 0, 1),
EAST_D(1, 0, 0),
WEST_D(-1, 0, 0),
NORTHWEST_D(-1, 0, -1),
SOUTHWEST_D(-1, 0, 1),
NORTHEAST_D(1, 0, -1),
SOUTHEAST_D(1, 0, 1),
NORTH_D_2(0, -1, -1),
SOUTH_D_2(0, -1, 1),
EAST_D_2(1, -1, 0),
WEST_D_2(-1, -1, 0);
private final int offsetX;
private final int offsetY;
private final int offsetZ;
private LegacyLevel(int offsetX, int offsetY, int offsetZ) {
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
}
private static final Set<LegacyLevel> NON_SIDE = new HashSet<>(Arrays.asList(
ABOVE,
BELOW,
AT,
AT_D
));
private static final Set<LegacyLevel> SIDE_AT = new HashSet<>(Arrays.asList(
NORTH, NORTH,
SOUTH, SOUTH,
EAST, EAST,
WEST, WEST
));
private static final Set<LegacyLevel> SIDE_UP = new HashSet<>(Arrays.asList(
NORTH_U,
SOUTH_U,
EAST_U,
WEST_U
));
private static final Set<LegacyLevel> SIDE_DOWN = new HashSet<>(Arrays.asList(
NORTH_D, NORTH_D,
SOUTH_D, SOUTH_D,
EAST_D, EAST_D,
WEST_D WEST_D
)); ));
private static final Set<LegacyLevel> SIDE_DOWN_2 = new HashSet<>(Arrays.asList(
NORTH_D_2,
SOUTH_D_2,
EAST_D_2,
WEST_D_2
));
public boolean isSide() { public boolean isSide() {
return SIDE.contains(this); return !NON_SIDE.contains(this);
}
public boolean isSideAt() {
return SIDE_AT.contains(this);
}
public boolean isSideUp() {
return SIDE_UP.contains(this);
}
public boolean isSideDown() {
return SIDE_DOWN.contains(this);
}
public boolean isSideDown2() {
return SIDE_DOWN_2.contains(this);
}
public LegacyLevel sideUp() {
switch(this) {
case NORTH: return NORTH_U;
case SOUTH: return SOUTH_U;
case EAST: return EAST_U;
case WEST: return WEST_U;
case NORTH_D: return NORTH;
case SOUTH_D: return SOUTH;
case EAST_D: return EAST;
case WEST_D: return WEST;
case NORTH_D_2: return NORTH_D;
case SOUTH_D_2: return SOUTH_D;
case EAST_D_2: return EAST_D;
case WEST_D_2: return WEST_D;
default:
return null;
}
}
public LegacyLevel sideDown() {
switch(this) {
case NORTH_U: return NORTH;
case SOUTH_U: return SOUTH;
case EAST_U: return EAST;
case WEST_U: return WEST;
case NORTH: return NORTH_D;
case SOUTH: return SOUTH_D;
case EAST: return EAST_D;
case WEST: return WEST_D;
case NORTH_D: return NORTH_D_2;
case SOUTH_D: return SOUTH_D_2;
case EAST_D: return EAST_D_2;
case WEST_D: return WEST_D_2;
default:
return null;
}
}
public static LegacyLevel getOffset(Location start, Location end) {
int diffX = end.getBlockX() - start.getBlockX();
int diffY = end.getBlockY() - start.getBlockY();
int diffZ = end.getBlockZ() - start.getBlockZ();
for (LegacyLevel level : LegacyLevel.values()) {
if (level.offsetX == diffX && level.offsetY == diffY && level.offsetZ == diffZ) {
return level;
}
}
return null;
}
public Location offset(Location loc) {
return loc.add(offsetX, offsetY, offsetZ);
}
public static class LevelWrapper {
private LegacyLevel level;
public LevelWrapper(LegacyLevel level) {
this.level = level;
}
public LegacyLevel getLevel() {
return level;
}
public void setLevel(LegacyLevel level) {
this.level = level;
}
} }
} }

View File

@@ -1,16 +1,29 @@
package net.nuggetmc.tplus.api.agent.legacyagent; package net.nuggetmc.tplus.api.agent.legacyagent;
import org.bukkit.Axis;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
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;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class LegacyMats { public class LegacyMats {
public static final Set<Material> AIR = new HashSet<>(Arrays.asList( public static final Set<Material> AIR = new HashSet<>(Arrays.asList(
Material.WATER, Material.WATER,
Material.OAK_TRAPDOOR,
Material.FIRE, Material.FIRE,
Material.LAVA, Material.LAVA,
Material.SNOW, Material.SNOW,
@@ -36,33 +49,49 @@ public class LegacyMats {
Material.FIRE, Material.FIRE,
Material.LAVA, Material.LAVA,
Material.CAVE_AIR, Material.CAVE_AIR,
Material.VOID_AIR,
Material.AIR,
Material.SOUL_FIRE Material.SOUL_FIRE
)); ));
public static final Set<Material> SHOVEL = new HashSet<>(Arrays.asList( public static final Set<Material> SHOVEL = new HashSet<>(concatTypes(Lists.newArrayList(
Material.CLAY,
Material.DIRT, Material.DIRT,
Material.GRASS_BLOCK,
Material.COARSE_DIRT,
Material.PODZOL,
Material.MYCELIUM,
Material.GRAVEL, Material.GRAVEL,
Material.MUD,
Material.MUDDY_MANGROVE_ROOTS,
Material.SAND, Material.SAND,
Material.SNOW Material.RED_SAND,
)); Material.SOUL_SAND,
Material.SOUL_SOIL,
Material.SNOW,
Material.SNOW_BLOCK
), Arrays.asList(), Arrays.asList(), m -> m.name().endsWith("_CONCRETE_POWDER")));
public static final Set<Material> AXE = new HashSet<>(Arrays.asList( public static final Set<Material> AXE = new HashSet<>(Arrays.asList(
Material.OAK_PLANKS, Material.OAK_DOOR, Material.OAK_FENCE, Material.OAK_FENCE_GATE, Material.OAK_LOG, Material.OAK_PLANKS, Material.OAK_PLANKS, Material.OAK_DOOR, Material.OAK_FENCE, Material.OAK_FENCE_GATE, Material.OAK_LOG,
Material.OAK_SIGN, Material.OAK_SLAB, Material.OAK_STAIRS, Material.OAK_TRAPDOOR, Material.OAK_WALL_SIGN, Material.OAK_WOOD, Material.OAK_SIGN, Material.OAK_SLAB, Material.OAK_STAIRS, Material.OAK_TRAPDOOR, Material.OAK_WALL_SIGN, Material.OAK_WOOD,
Material.DARK_OAK_PLANKS, Material.DARK_OAK_DOOR, Material.DARK_OAK_FENCE, Material.DARK_OAK_FENCE_GATE, Material.DARK_OAK_LOG, Material.DARK_OAK_PLANKS, Material.DARK_OAK_PLANKS, Material.DARK_OAK_DOOR, Material.DARK_OAK_FENCE, Material.DARK_OAK_FENCE_GATE, Material.DARK_OAK_LOG,
Material.DARK_OAK_SIGN, Material.DARK_OAK_SLAB, Material.DARK_OAK_STAIRS, Material.DARK_OAK_TRAPDOOR, Material.DARK_OAK_WALL_SIGN, Material.DARK_OAK_WOOD, Material.DARK_OAK_SIGN, Material.DARK_OAK_SLAB, Material.DARK_OAK_STAIRS, Material.DARK_OAK_TRAPDOOR, Material.DARK_OAK_WALL_SIGN, Material.DARK_OAK_WOOD,
Material.ACACIA_PLANKS, Material.ACACIA_DOOR, Material.ACACIA_FENCE, Material.ACACIA_FENCE_GATE, Material.ACACIA_LOG, Material.ACACIA_PLANKS, Material.ACACIA_PLANKS, Material.ACACIA_DOOR, Material.ACACIA_FENCE, Material.ACACIA_FENCE_GATE, Material.ACACIA_LOG,
Material.ACACIA_SIGN, Material.ACACIA_SLAB, Material.ACACIA_STAIRS, Material.ACACIA_TRAPDOOR, Material.ACACIA_WALL_SIGN, Material.ACACIA_WOOD, Material.ACACIA_SIGN, Material.ACACIA_SLAB, Material.ACACIA_STAIRS, Material.ACACIA_TRAPDOOR, Material.ACACIA_WALL_SIGN, Material.ACACIA_WOOD,
Material.BIRCH_PLANKS, Material.BIRCH_DOOR, Material.BIRCH_FENCE, Material.BIRCH_FENCE_GATE, Material.BIRCH_LOG, Material.BIRCH_PLANKS, Material.BIRCH_PLANKS, Material.BIRCH_DOOR, Material.BIRCH_FENCE, Material.BIRCH_FENCE_GATE, Material.BIRCH_LOG,
Material.BIRCH_SIGN, Material.BIRCH_SLAB, Material.BIRCH_STAIRS, Material.BIRCH_TRAPDOOR, Material.BIRCH_WALL_SIGN, Material.BIRCH_WOOD, Material.BIRCH_SIGN, Material.BIRCH_SLAB, Material.BIRCH_STAIRS, Material.BIRCH_TRAPDOOR, Material.BIRCH_WALL_SIGN, Material.BIRCH_WOOD,
Material.JUNGLE_PLANKS, Material.JUNGLE_DOOR, Material.JUNGLE_FENCE, Material.JUNGLE_FENCE_GATE, Material.JUNGLE_LOG, Material.JUNGLE_PLANKS, Material.JUNGLE_PLANKS, Material.JUNGLE_DOOR, Material.JUNGLE_FENCE, Material.JUNGLE_FENCE_GATE, Material.JUNGLE_LOG,
Material.JUNGLE_SIGN, Material.JUNGLE_SLAB, Material.JUNGLE_STAIRS, Material.JUNGLE_TRAPDOOR, Material.JUNGLE_WALL_SIGN, Material.JUNGLE_WOOD, Material.JUNGLE_SIGN, Material.JUNGLE_SLAB, Material.JUNGLE_STAIRS, Material.JUNGLE_TRAPDOOR, Material.JUNGLE_WALL_SIGN, Material.JUNGLE_WOOD,
Material.SPRUCE_PLANKS, Material.SPRUCE_DOOR, Material.SPRUCE_FENCE, Material.SPRUCE_FENCE_GATE, Material.SPRUCE_LOG, Material.SPRUCE_PLANKS, Material.SPRUCE_PLANKS, Material.SPRUCE_DOOR, Material.SPRUCE_FENCE, Material.SPRUCE_FENCE_GATE, Material.SPRUCE_LOG,
Material.SPRUCE_SIGN, Material.SPRUCE_SLAB, Material.SPRUCE_STAIRS, Material.SPRUCE_TRAPDOOR, Material.SPRUCE_WALL_SIGN, Material.SPRUCE_WOOD, Material.SPRUCE_SIGN, Material.SPRUCE_SLAB, Material.SPRUCE_STAIRS, Material.SPRUCE_TRAPDOOR, Material.SPRUCE_WALL_SIGN, Material.SPRUCE_WOOD,
Material.CRIMSON_PLANKS, Material.CRIMSON_DOOR, Material.CRIMSON_FENCE, Material.CRIMSON_FENCE_GATE, Material.CRIMSON_PLANKS, Material.MANGROVE_PLANKS, Material.MANGROVE_DOOR, Material.MANGROVE_FENCE, Material.MANGROVE_FENCE_GATE, Material.MANGROVE_LOG,
Material.MANGROVE_SIGN, Material.MANGROVE_SLAB, Material.MANGROVE_STAIRS, Material.MANGROVE_TRAPDOOR, Material.MANGROVE_WALL_SIGN, Material.MANGROVE_WOOD,
Material.CRIMSON_PLANKS, Material.CRIMSON_DOOR, Material.CRIMSON_FENCE, Material.CRIMSON_FENCE_GATE, Material.CRIMSON_STEM,
Material.CRIMSON_SIGN, Material.CRIMSON_SLAB, Material.CRIMSON_STAIRS, Material.CRIMSON_TRAPDOOR, Material.CRIMSON_WALL_SIGN, Material.CRIMSON_SIGN, Material.CRIMSON_SLAB, Material.CRIMSON_STAIRS, Material.CRIMSON_TRAPDOOR, Material.CRIMSON_WALL_SIGN,
Material.WARPED_PLANKS, Material.WARPED_DOOR, Material.WARPED_FENCE, Material.WARPED_FENCE_GATE, Material.WARPED_PLANKS, Material.WARPED_PLANKS, Material.WARPED_DOOR, Material.WARPED_FENCE, Material.WARPED_FENCE_GATE, Material.WARPED_STEM,
Material.WARPED_SIGN, Material.WARPED_SLAB, Material.WARPED_STAIRS, Material.WARPED_TRAPDOOR, Material.WARPED_WALL_SIGN Material.WARPED_SIGN, Material.WARPED_SLAB, Material.WARPED_STAIRS, Material.WARPED_TRAPDOOR, Material.WARPED_WALL_SIGN,
Material.CHEST, Material.TRAPPED_CHEST
)); ));
public static final Set<Material> BREAK = new HashSet<>(Arrays.asList( public static final Set<Material> BREAK = new HashSet<>(Arrays.asList(
@@ -70,14 +99,13 @@ public class LegacyMats {
Material.WATER, Material.WATER,
Material.LAVA, Material.LAVA,
Material.TALL_GRASS, Material.TALL_GRASS,
Material.SNOW,
Material.DIRT_PATH,
Material.CAVE_AIR, Material.CAVE_AIR,
Material.VINE, Material.VINE,
Material.FERN, Material.FERN,
Material.LARGE_FERN, Material.LARGE_FERN,
Material.SUGAR_CANE, Material.SUGAR_CANE,
Material.TWISTING_VINES, Material.TWISTING_VINES,
Material.TWISTING_VINES_PLANT,
Material.WEEPING_VINES, Material.WEEPING_VINES,
Material.SEAGRASS, Material.SEAGRASS,
Material.TALL_SEAGRASS, Material.TALL_SEAGRASS,
@@ -135,34 +163,356 @@ public class LegacyMats {
Material.WATER Material.WATER
)); ));
public static final Set<Material> FENCE = new HashSet<>(Arrays.asList( public static final Set<Material> FENCE = new HashSet<>(concatTypes(new ArrayList<>(),
Material.OAK_FENCE, Arrays.asList(Material.GLASS_PANE, Material.IRON_BARS), Arrays.asList(Fence.class, Wall.class)));
Material.ACACIA_FENCE,
Material.BIRCH_FENCE, public static final Set<Material> GATES = new HashSet<>(concatTypes(Gate.class));
Material.CRIMSON_FENCE,
Material.DARK_OAK_FENCE, public static final Set<Material> OBSTACLES = new HashSet<>(concatTypes(Lists.newArrayList(
Material.JUNGLE_FENCE, Material.IRON_BARS,
Material.NETHER_BRICK_FENCE, Material.CHAIN,
Material.SPRUCE_FENCE, Material.END_ROD,
Material.WARPED_FENCE, Material.LIGHTNING_ROD,
Material.COBBLESTONE_WALL, Material.COBWEB,
Material.ANDESITE_WALL, Material.SWEET_BERRY_BUSH,
Material.BLACKSTONE_WALL, Material.FLOWER_POT,
Material.BRICK_WALL, Material.GLASS_PANE
Material.GRANITE_WALL, ), Arrays.asList(), Arrays.asList(GlassPane.class), m -> m.name().startsWith("POTTED_")));
Material.DIORITE_WALL,
Material.SANDSTONE_WALL,
Material.RED_SANDSTONE_WALL,
Material.RED_NETHER_BRICK_WALL,
Material.IRON_BARS,
Material.COBWEB
));
public static final Set<Material> LEAVES = new HashSet<>(Arrays.asList( //Notice: We exclude blocks that cannot exist without a solid block below (such as rails or crops)
Material.BIRCH_LEAVES, public static final Set<Material> NONSOLID = new HashSet<>(concatTypes(Lists.newArrayList(
Material.DARK_OAK_LEAVES, Material.COBWEB,
Material.JUNGLE_LEAVES, Material.END_GATEWAY,
Material.OAK_LEAVES, Material.END_PORTAL,
Material.SPRUCE_LEAVES Material.NETHER_PORTAL,
)); Material.CAVE_VINES_PLANT,
Material.GLOW_LICHEN,
Material.HANGING_ROOTS,
Material.POWDER_SNOW,
Material.SCULK_VEIN,
Material.STRING,
Material.TRIPWIRE_HOOK,
Material.LADDER,
Material.VINE,
Material.SOUL_WALL_TORCH,
Material.REDSTONE_WALL_TORCH,
Material.WALL_TORCH,
Material.WEEPING_VINES_PLANT,
Material.WEEPING_VINES,
Material.CAVE_VINES_PLANT,
Material.CAVE_VINES
), Arrays.asList(), Arrays.asList(Switch.class, CoralWallFan.class, WallSign.class), m -> m.name().endsWith("_WALL_BANNER")));
public static final Set<Material> LEAVES = new HashSet<>(concatTypes(Leaves.class));
public static final Set<Material> INSTANT_BREAK = new HashSet<>(concatTypes(Lists.newArrayList(
Material.TALL_GRASS,
Material.GRASS,
Material.FERN,
Material.LARGE_FERN,
Material.KELP_PLANT,
Material.DEAD_BUSH,
Material.WHEAT_SEEDS,
Material.POTATOES,
Material.CARROTS,
Material.BEETROOT_SEEDS,
Material.PUMPKIN_STEM,
Material.MELON_STEM,
Material.SUGAR_CANE,
Material.SWEET_BERRY_BUSH,
Material.LILY_PAD,
Material.DANDELION,
Material.POPPY,
Material.BLUE_ORCHID,
Material.ALLIUM,
Material.AZURE_BLUET,
Material.RED_TULIP,
Material.ORANGE_TULIP,
Material.WHITE_TULIP,
Material.PINK_TULIP,
Material.OXEYE_DAISY,
Material.CORNFLOWER,
Material.LILY_OF_THE_VALLEY,
Material.WITHER_ROSE,
Material.SUNFLOWER,
Material.LILAC,
Material.ROSE_BUSH,
Material.PEONY,
Material.NETHER_WART,
Material.FLOWER_POT,
Material.AZALEA,
Material.FLOWERING_AZALEA,
Material.REPEATER,
Material.COMPARATOR,
Material.REDSTONE_WIRE,
Material.REDSTONE_TORCH,
Material.REDSTONE_WALL_TORCH,
Material.TORCH,
Material.WALL_TORCH,
Material.SOUL_TORCH,
Material.SOUL_WALL_TORCH,
Material.SCAFFOLDING,
Material.SLIME_BLOCK,
Material.HONEY_BLOCK,
Material.TNT,
Material.TRIPWIRE,
Material.TRIPWIRE_HOOK,
Material.SPORE_BLOSSOM,
Material.RED_MUSHROOM,
Material.BROWN_MUSHROOM,
Material.CRIMSON_FUNGUS,
Material.WARPED_FUNGUS,
Material.CRIMSON_ROOTS,
Material.WARPED_ROOTS,
Material.HANGING_ROOTS,
Material.WEEPING_VINES,
Material.WEEPING_VINES_PLANT,
Material.TWISTING_VINES,
Material.TWISTING_VINES_PLANT,
Material.CAVE_VINES,
Material.CAVE_VINES_PLANT,
Material.SEA_PICKLE
), Arrays.asList(), Arrays.asList(Sapling.class, CoralWallFan.class), m -> m.name().endsWith("_CORAL_FAN") || m.name().endsWith("_CORAL")
|| m.name().startsWith("POTTED_")));
private static List<Material> concatTypes(Class<?>... types) {
return concatTypes(new ArrayList<>(), Arrays.asList(types));
}
private static List<Material> concatTypes(List<Material> materials, List<Class<?>> types) {
return concatTypes(materials, Arrays.asList(), types);
}
private static List<Material> concatTypes(List<Material> materials, List<Material> exclusions, List<Class<?>> types) {
return concatTypes(materials, exclusions, types, m -> false);
}
private static List<Material> concatTypes(List<Material> materials, List<Material> exclusions, List<Class<?>> types, Predicate<Material> otherFilter) {
materials.addAll(Stream.of(Material.values()).filter(m -> (types.contains(m.data) || otherFilter.test(m))
&& !exclusions.contains(m) && !m.isLegacy()).toList());
return materials;
}
/**
* 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<Double> entityYPos) {
if (block.getType().isSolid()) {
if (block.getType() == Material.CHAIN && ((Chain)block.getBlockData()).getAxis() == Axis.Y
&& !((Chain)block.getBlockData()).isWaterlogged())
return false;
if ((block.getType().data == Leaves.class || block.getType() == Material.MANGROVE_ROOTS
|| block.getType() == Material.IRON_BARS || block.getType().name().endsWith("GLASS_PANE"))
&& !((Waterlogged)block.getBlockData()).isWaterlogged())
return false;
if (block.getType().data == Slab.class && ((Slab)block.getBlockData()).getType() == Slab.Type.TOP
&& !((Slab)block.getBlockData()).isWaterlogged())
return false;
if (block.getType().data == Stairs.class && ((Stairs)block.getBlockData()).getHalf() == Bisected.Half.TOP
&& !((Stairs)block.getBlockData()).isWaterlogged())
return false;
if (block.getType().data == Stairs.class && ((Stairs)block.getBlockData()).getHalf() == Bisected.Half.BOTTOM
&& !((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())
return false;
if (block.getType() == Material.LIGHTNING_ROD && !((LightningRod)block.getBlockData()).isWaterlogged()
&& (((LightningRod)block.getBlockData()).getFacing() == BlockFace.UP || ((LightningRod)block.getBlockData()).getFacing() == BlockFace.DOWN))
return false;
if (block.getType().data == TrapDoor.class && (((TrapDoor)block.getBlockData()).getHalf() == Half.TOP
|| (((TrapDoor)block.getBlockData()).getHalf() == Half.BOTTOM && ((TrapDoor)block.getBlockData()).isOpen()))
&& !((TrapDoor)block.getBlockData()).isWaterlogged())
return false;
return true;
} else {
if (block.getType().name().endsWith("_CARPET"))
return true;
if (block.getType().data == Candle.class)
return true;
if (block.getType().name().startsWith("POTTED_"))
return true;
if ((block.getType().name().endsWith("_HEAD") || block.getType().name().endsWith("_SKULL"))
&& !block.getType().name().equals("PISTON_HEAD"))
return true;
switch (block.getType()) {
case SNOW:
case AZALEA:
case FLOWERING_AZALEA:
case CHORUS_FLOWER:
case CHORUS_PLANT:
case COCOA:
case LILY_PAD:
case SEA_PICKLE:
case END_ROD:
case FLOWER_POT:
case SCAFFOLDING:
case COMPARATOR:
case REPEATER:
return true;
default:
break;
}
}
return false;
}
public static boolean canPlaceTwistingVines(Block block) {
if (block.getType().isSolid()) {
if (block.getType().data == Leaves.class)
return false;
if (block.getType().name().endsWith("_CORAL_FAN") || block.getType().name().endsWith("_CORAL")
|| block.getType().name().endsWith("_CORAL_WALL_FAN"))
return false;
if (block.getType().name().endsWith("GLASS_PANE"))
return false;
if (block.getType().data == Slab.class && ((Slab)block.getBlockData()).getType() == Slab.Type.BOTTOM)
return false;
if (block.getType().data == Stairs.class && ((Stairs)block.getBlockData()).getHalf() == Bisected.Half.BOTTOM)
return false;
if (block.getType().data == Fence.class || block.getType().data == Wall.class)
return false;
if (block.getType().name().endsWith("_BANNER"))
return false;
if (block.getType().name().endsWith("_WALL_BANNER"))
return false;
if (block.getType().data == Bed.class)
return false;
if (block.getType().name().endsWith("CANDLE_CAKE"))
return false;
if (block.getType().data == Door.class)
return false;
if (block.getType().data == Gate.class)
return false;
if (block.getType() == Material.PISTON_HEAD && ((PistonHead)block.getBlockData()).getFacing() != BlockFace.UP)
return false;
if (block.getType().data == Piston.class && ((Piston)block.getBlockData()).getFacing() != BlockFace.DOWN
&& ((Piston)block.getBlockData()).isExtended())
return false;
if (block.getType().data == TrapDoor.class && (((TrapDoor)block.getBlockData()).getHalf() == Half.BOTTOM
|| ((TrapDoor)block.getBlockData()).isOpen()))
return false;
switch (block.getType()) {
case POINTED_DRIPSTONE:
case SMALL_AMETHYST_BUD:
case MEDIUM_AMETHYST_BUD:
case LARGE_AMETHYST_BUD:
case AMETHYST_CLUSTER:
case BAMBOO:
case CACTUS:
case DRAGON_EGG:
case TURTLE_EGG:
case CHAIN:
case IRON_BARS:
case LANTERN:
case SOUL_LANTERN:
case ANVIL:
case BREWING_STAND:
case CHEST:
case ENDER_CHEST:
case TRAPPED_CHEST:
case ENCHANTING_TABLE:
case GRINDSTONE:
case LECTERN:
case STONECUTTER:
case BELL:
case CAKE:
case CAMPFIRE:
case SOUL_CAMPFIRE:
case CAULDRON:
case COMPOSTER:
case CONDUIT:
case END_PORTAL_FRAME:
case FARMLAND:
case DAYLIGHT_DETECTOR:
case HONEY_BLOCK:
case HOPPER:
case LIGHTNING_ROD:
case SCULK_SENSOR:
case SCULK_SHRIEKER:
return false;
default:
}
return true;
} else {
switch (block.getType()) {
case CHORUS_FLOWER:
case SCAFFOLDING:
case AZALEA:
case FLOWERING_AZALEA:
return true;
case SNOW:
return ((Snow)block.getBlockData()).getLayers() == 1 || ((Snow)block.getBlockData()).getLayers() == 8;
default:
}
}
return false;
}
public static boolean shouldReplace(Block block, double entityYPos, boolean nether) {
if ((int)entityYPos != block.getLocation().getBlockY())
return false;
if (nether) {
return false;
} else {
if (block.getType().name().endsWith("_CORAL_FAN") || block.getType().name().endsWith("_CORAL")
|| block.getType().name().endsWith("_CORAL_WALL_FAN"))
return true;
if (block.getType().data == Slab.class && ((Slab)block.getBlockData()).getType() == Slab.Type.BOTTOM)
return true;
if (block.getType().data == Stairs.class && !((Stairs)block.getBlockData()).isWaterlogged())
return true;
if (block.getType().data == Chain.class && !((Chain)block.getBlockData()).isWaterlogged())
return true;
if (block.getType().data == Candle.class)
return true;
if (block.getType().data == TrapDoor.class && !((TrapDoor)block.getBlockData()).isWaterlogged())
return true;
switch (block.getType()) {
case POINTED_DRIPSTONE:
case SMALL_AMETHYST_BUD:
case MEDIUM_AMETHYST_BUD:
case LARGE_AMETHYST_BUD:
case AMETHYST_CLUSTER:
case SEA_PICKLE:
case LANTERN:
case SOUL_LANTERN:
case CHEST:
case ENDER_CHEST:
case TRAPPED_CHEST:
case CAMPFIRE:
case SOUL_CAMPFIRE:
case CONDUIT:
case LIGHTNING_ROD:
case SCULK_SENSOR:
case SCULK_SHRIEKER:
return true;
default:
}
return false;
}
}
} }

View File

@@ -1,20 +1,30 @@
package net.nuggetmc.tplus.api.event; package net.nuggetmc.tplus.api.event;
import java.util.List;
import org.bukkit.block.Block;
import net.nuggetmc.tplus.api.Terminator; import net.nuggetmc.tplus.api.Terminator;
public class BotFallDamageEvent { public class BotFallDamageEvent {
private final Terminator bot; private final Terminator bot;
private final List<Block> standingOn;
private boolean cancelled; private boolean cancelled;
public BotFallDamageEvent(Terminator bot) { public BotFallDamageEvent(Terminator bot, List<Block> standingOn) {
this.bot = bot; this.bot = bot;
this.standingOn = standingOn;
} }
public Terminator getBot() { public Terminator getBot() {
return bot; return bot;
} }
public List<Block> getStandingOn() {
return standingOn;
}
public boolean isCancelled() { public boolean isCancelled() {
return cancelled; return cancelled;

View File

@@ -2,9 +2,8 @@ package net.nuggetmc.tplus.api.utils;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.util.BoundingBox; import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector; import org.bukkit.util.NumberConversions;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
@@ -17,6 +16,12 @@ public class BotUtils {
Material.WATER, Material.WATER,
Material.LAVA, Material.LAVA,
Material.TWISTING_VINES, Material.TWISTING_VINES,
Material.TWISTING_VINES_PLANT,
Material.WEEPING_VINES,
Material.WEEPING_VINES_PLANT,
Material.SWEET_BERRY_BUSH,
Material.POWDER_SNOW,
Material.COBWEB,
Material.VINE Material.VINE
)); ));
@@ -29,24 +34,12 @@ public class BotUtils {
return randomSteveUUID(); return randomSteveUUID();
} }
public static boolean solidAt(Location loc) { // not perfect, still cuts corners of fences public static boolean overlaps(BoundingBox playerBox, BoundingBox blockBox) {
Block block = loc.getBlock(); return playerBox.overlaps(blockBox);
BoundingBox box = block.getBoundingBox(); }
Vector position = loc.toVector();
public static double getHorizSqDist(Location blockLoc, Location pLoc) {
double x = position.getX(); return NumberConversions.square(blockLoc.getX() + 0.5 - pLoc.getX()) + NumberConversions.square(blockLoc.getZ() + 0.5 - pLoc.getZ());
double y = position.getY();
double z = position.getZ();
double minX = box.getMinX();
double minY = box.getMinY();
double minZ = box.getMinZ();
double maxX = box.getMaxX();
double maxY = box.getMaxY();
double maxZ = box.getMaxZ();
return x > minX && x < maxX && y > minY && y < maxY && z > minZ && z < maxZ;
} }
} }

View File

@@ -2,8 +2,6 @@ package net.nuggetmc.tplus.bot;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.network.Connection; import net.minecraft.network.Connection;
import net.minecraft.network.PacketSendListener; import net.minecraft.network.PacketSendListener;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
@@ -27,6 +25,7 @@ import net.minecraft.world.phys.Vec3;
import net.nuggetmc.tplus.TerminatorPlus; import net.nuggetmc.tplus.TerminatorPlus;
import net.nuggetmc.tplus.api.Terminator; import net.nuggetmc.tplus.api.Terminator;
import net.nuggetmc.tplus.api.agent.Agent; import net.nuggetmc.tplus.api.agent.Agent;
import net.nuggetmc.tplus.api.agent.legacyagent.LegacyMats;
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork; import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent; import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent;
import net.nuggetmc.tplus.api.event.BotFallDamageEvent; import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
@@ -35,6 +34,7 @@ import net.nuggetmc.tplus.api.utils.*;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.craftbukkit.v1_19_R1.CraftEquipmentSlot; import org.bukkit.craftbukkit.v1_19_R1.CraftEquipmentSlot;
import org.bukkit.craftbukkit.v1_19_R1.CraftServer; import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
@@ -45,11 +45,13 @@ import org.bukkit.entity.Damageable;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
@@ -69,13 +71,14 @@ public class Bot extends ServerPlayer implements Terminator {
private boolean removeOnDeath; private boolean removeOnDeath;
private int aliveTicks; private int aliveTicks;
private int kills; private int kills;
private byte fireTicks; // Fire animation isn't played? Bot still takes damage.
private byte groundTicks; private byte groundTicks;
private byte jumpTicks; private byte jumpTicks;
private byte noFallTicks; private byte noFallTicks;
private boolean ignoredByMobs = true; private List<Block> standingOn = new ArrayList<>();
private UUID targetPlayer = null; private UUID targetPlayer = null;
private Bot(MinecraftServer minecraftServer, ServerLevel worldServer, GameProfile profile) { private boolean inPlayerList;
private Bot(MinecraftServer minecraftServer, ServerLevel worldServer, GameProfile profile, boolean addToPlayerList) {
super(minecraftServer, worldServer, profile, null); super(minecraftServer, worldServer, profile, null);
this.plugin = TerminatorPlus.getInstance(); this.plugin = TerminatorPlus.getInstance();
@@ -85,9 +88,12 @@ public class Bot extends ServerPlayer implements Terminator {
this.velocity = new Vector(0, 0, 0); this.velocity = new Vector(0, 0, 0);
this.oldVelocity = velocity.clone(); this.oldVelocity = velocity.clone();
this.noFallTicks = 60; this.noFallTicks = 60;
this.fireTicks = 0;
this.removeOnDeath = true; this.removeOnDeath = true;
this.offset = MathUtils.circleOffset(3); this.offset = MathUtils.circleOffset(3);
if (addToPlayerList) {
minecraftServer.getPlayerList().getPlayers().add(this);
inPlayerList = true;
}
//this.entityData.set(new EntityDataAccessor<>(16, EntityDataSerializers.BYTE), (byte) 0xFF); //this.entityData.set(new EntityDataAccessor<>(16, EntityDataSerializers.BYTE), (byte) 0xFF);
} }
@@ -103,8 +109,10 @@ public class Bot extends ServerPlayer implements Terminator {
UUID uuid = BotUtils.randomSteveUUID(); UUID uuid = BotUtils.randomSteveUUID();
CustomGameProfile profile = new CustomGameProfile(uuid, ChatUtils.trim16(name), skin); CustomGameProfile profile = new CustomGameProfile(uuid, ChatUtils.trim16(name), skin);
boolean addPlayerList = TerminatorPlus.getInstance().getManager().addToPlayerList();
Bot bot = new Bot(nmsServer, nmsWorld, profile); Bot bot = new Bot(nmsServer, nmsWorld, profile, addPlayerList);
bot.connection = new ServerGamePacketListenerImpl(nmsServer, new Connection(PacketFlow.CLIENTBOUND) { bot.connection = new ServerGamePacketListenerImpl(nmsServer, new Connection(PacketFlow.CLIENTBOUND) {
@@ -119,7 +127,10 @@ public class Bot extends ServerPlayer implements Terminator {
bot.getBukkitEntity().setNoDamageTicks(0); bot.getBukkitEntity().setNoDamageTicks(0);
Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().connection.send( Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().connection.send(
new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, bot))); new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, bot)));
nmsWorld.addFreshEntity(bot); if (addPlayerList)
nmsWorld.addNewPlayer(bot);
else
nmsWorld.addFreshEntity(bot);
bot.renderAll(); bot.renderAll();
TerminatorPlus.getInstance().getManager().add(bot); TerminatorPlus.getInstance().getManager().add(bot);
@@ -243,6 +254,11 @@ public class Bot extends ServerPlayer implements Terminator {
public int getAliveTicks() { public int getAliveTicks() {
return aliveTicks; return aliveTicks;
} }
@Override
public int getNoFallTicks() {
return noFallTicks;
}
@Override @Override
public boolean tickDelay(int i) { public boolean tickDelay(int i) {
@@ -278,8 +294,6 @@ public class Bot extends ServerPlayer implements Terminator {
aliveTicks++; aliveTicks++;
if (fireTicks > 0) --fireTicks;
if (invulnerableTime > 0) --invulnerableTime;
if (jumpTicks > 0) --jumpTicks; if (jumpTicks > 0) --jumpTicks;
if (noFallTicks > 0) --noFallTicks; if (noFallTicks > 0) --noFallTicks;
@@ -290,6 +304,8 @@ public class Bot extends ServerPlayer implements Terminator {
} }
updateLocation(); updateLocation();
if (!isAlive()) return;
float health = getHealth(); float health = getHealth();
float maxHealth = getMaxHealth(); float maxHealth = getMaxHealth();
@@ -304,14 +320,11 @@ public class Bot extends ServerPlayer implements Terminator {
setHealth(amount); setHealth(amount);
fireDamageCheck();
fallDamageCheck(); fallDamageCheck();
if (position().y < -64) {
die(DamageSource.OUT_OF_WORLD);
}
oldVelocity = velocity.clone(); oldVelocity = velocity.clone();
doTick();
} }
private void loadChunks() { private void loadChunks() {
@@ -328,52 +341,6 @@ public class Bot extends ServerPlayer implements Terminator {
} }
} }
private void fireDamageCheck() {
if (!isAlive()) {
return; // maybe also have packet reset thing
}
Material type = getLocation().getBlock().getType();
if (type == Material.WATER) {
setOnFirePackets(false); // maybe also play extinguish noise?
fireTicks = 0;
return;
}
boolean lava = type == org.bukkit.Material.LAVA;
if (lava || type == org.bukkit.Material.FIRE || type == Material.SOUL_FIRE) {
ignite();
}
if (invulnerableTime == 0) {
if (lava) {
hurt(DamageSource.LAVA, 4);
invulnerableTime = 20;//this used to be 12 ticks but that would cause the bot to take damage too quickly
} else if (fireTicks > 1) {
hurt(DamageSource.IN_FIRE, 1);
invulnerableTime = 20;
}
}
if (fireTicks == 1) {
setOnFirePackets(false);
}
}
@Override
public void ignite() {
if (fireTicks <= 1) setOnFirePackets(true);
fireTicks = 100;
}
@Override
public void setOnFirePackets(boolean onFire) {
//entityData.set(new EntityDataAccessor<>(0, EntityDataSerializers.BYTE), onFire ? (byte) 1 : (byte) 0);
//sendPacket(new ClientboundSetEntityDataPacket(getId(), entityData, false));
}
@Override @Override
public UUID getTargetPlayer() { public UUID getTargetPlayer() {
return targetPlayer; return targetPlayer;
@@ -386,12 +353,12 @@ public class Bot extends ServerPlayer implements Terminator {
@Override @Override
public boolean isBotOnFire() { public boolean isBotOnFire() {
return fireTicks != 0; return this.isOnFire();
} }
private void fallDamageCheck() { // TODO create a better bot event system in the future, also have bot.getAgent() private void fallDamageCheck() { // TODO create a better bot event system in the future, also have bot.getAgent()
if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !BotUtils.NO_FALL.contains(getLocation().getBlock().getType())) { if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !isFallBlocked()) {
BotFallDamageEvent event = new BotFallDamageEvent(this); BotFallDamageEvent event = new BotFallDamageEvent(this, new ArrayList<>(getStandingOn()));
plugin.getManager().getAgent().onFallDamage(event); plugin.getManager().getAgent().onFallDamage(event);
@@ -400,6 +367,33 @@ public class Bot extends ServerPlayer implements Terminator {
} }
} }
} }
private boolean isFallBlocked() {
AABB box = getBoundingBox();
double[] xVals = new double[]{
box.minX,
box.maxX - 0.01
};
double[] zVals = new double[]{
box.minZ,
box.maxZ - 0.01
};
BoundingBox playerBox = new BoundingBox(box.minX, position().y - 0.01, box.minZ,
box.maxX, position().y + getBbHeight(), box.maxZ);
for (double x : xVals) {
for (double z : zVals) {
Location loc = new Location(getBukkitEntity().getWorld(), Math.floor(x), getLocation().getY(), Math.floor(z));
Block block = loc.getBlock();
if (block.getBlockData() instanceof Waterlogged wl && wl.isWaterlogged())
return true;
if (BotUtils.NO_FALL.contains(loc.getBlock().getType()) && (BotUtils.overlaps(playerBox, loc.getBlock().getBoundingBox())
|| loc.getBlock().getType() == Material.WATER || loc.getBlock().getType() == Material.LAVA))
return true;
}
}
return false;
}
@Override @Override
public boolean isFalling() { public boolean isFalling() {
@@ -525,7 +519,11 @@ public class Bot extends ServerPlayer implements Terminator {
return false; return false;
} }
World world = getBukkitEntity().getWorld(); return checkStandingOn();
}
public boolean checkStandingOn() {
World world = getBukkitEntity().getWorld();
AABB box = getBoundingBox(); AABB box = getBoundingBox();
double[] xVals = new double[]{ double[] xVals = new double[]{
@@ -537,19 +535,55 @@ public class Bot extends ServerPlayer implements Terminator {
box.minZ, box.minZ,
box.maxZ box.maxZ
}; };
BoundingBox playerBox = new BoundingBox(box.minX, position().y - 0.01, box.minZ,
box.maxX, position().y + getBbHeight(), box.maxZ);
List<Block> standingOn = new ArrayList<>();
List<Location> locations = new ArrayList<>();
for (double x : xVals) { for (double x : xVals) {
for (double z : zVals) { for (double z : zVals) {
Location loc = new Location(world, x, position().y - 0.01, z); Location loc = new Location(world, x, position().y - 0.01, z);
Block block = world.getBlockAt(loc); Block block = world.getBlockAt(loc);
if (block.getType().isSolid() && BotUtils.solidAt(loc)) { if ((block.getType().isSolid() || LegacyMats.canStandOn(block.getType())) && BotUtils.overlaps(playerBox, block.getBoundingBox())) {
return true; if (!locations.contains(block.getLocation())) {
standingOn.add(block);
locations.add(block.getLocation());
}
}
}
}
//Fence/wall check
for (double x : xVals) {
for (double z : zVals) {
Location loc = new Location(world, x, position().y - 0.51, z);
Block block = world.getBlockAt(loc);
BoundingBox blockBox = loc.getBlock().getBoundingBox();
BoundingBox modifiedBox = new BoundingBox(blockBox.getMinX(), blockBox.getMinY(), blockBox.getMinZ(), blockBox.getMaxX(),
blockBox.getMinY() + 1.5, blockBox.getMaxZ());
if ((LegacyMats.FENCE.contains(block.getType()) || LegacyMats.GATES.contains(block.getType()))
&& block.getType().isSolid() && BotUtils.overlaps(playerBox, modifiedBox)) {
if (!locations.contains(block.getLocation())) {
standingOn.add(block);
locations.add(block.getLocation());
}
} }
} }
} }
return false; //Closest block comes first
Collections.sort(standingOn, (a, b) ->
Double.compare(BotUtils.getHorizSqDist(a.getLocation(), getLocation()), BotUtils.getHorizSqDist(b.getLocation(), getLocation())));
this.standingOn = standingOn;
return !standingOn.isEmpty();
}
@Override
public List<Block> getStandingOn() {
return standingOn;
} }
@Override @Override
@@ -582,6 +616,8 @@ public class Bot extends ServerPlayer implements Terminator {
scheduler.runTask(plugin, () -> this.remove(RemovalReason.DISCARDED)); scheduler.runTask(plugin, () -> this.remove(RemovalReason.DISCARDED));
} }
this.removeVisually(); this.removeVisually();
if (inPlayerList)
this.server.getPlayerList().getPlayers().remove(this);
} }
private void removeTab() { private void removeTab() {
@@ -609,7 +645,7 @@ public class Bot extends ServerPlayer implements Terminator {
// this should fix the concurrentmodificationexception mentioned above, I used the ConcurrentHashMap.newKeySet to make a "ConcurrentHashSet" // this should fix the concurrentmodificationexception mentioned above, I used the ConcurrentHashMap.newKeySet to make a "ConcurrentHashSet"
plugin.getManager().remove(this); plugin.getManager().remove(this);
scheduler.runTaskLater(plugin, this::setDead, 30); scheduler.runTaskLater(plugin, this::removeBot, 20);
this.removeTab(); this.removeTab();
} }
@@ -728,6 +764,11 @@ public class Bot extends ServerPlayer implements Terminator {
public Location getLocation() { public Location getLocation() {
return getBukkitEntity().getLocation(); return getBukkitEntity().getLocation();
} }
@Override
public BoundingBox getBotBoundingBox() {
return getBukkitEntity().getBoundingBox();
}
@Override @Override
public void setBotPitch(float pitch) { public void setBotPitch(float pitch) {
@@ -842,25 +883,16 @@ public class Bot extends ServerPlayer implements Terminator {
@Override @Override
public void doTick() { public void doTick() {
if (this.hurtTime > 0) {
this.hurtTime -= 1;
}
baseTick(); baseTick();
tickEffects();
this.animStepO = (int) this.animStep;
this.yBodyRotO = this.yBodyRot;
this.yHeadRotO = this.yHeadRot;
this.yRotO = this.getYRot();
this.xRotO = this.getXRot();
} }
public boolean isIgnoredByMobs() { @Override
return ignoredByMobs; public boolean isInPlayerList() {
return inPlayerList;
} }
public void setIgnoredByMobs(boolean ignoredByMobs) { @Override
this.ignoredByMobs = ignoredByMobs; public World.Environment getDimension() {
return getBukkitEntity().getWorld().getEnvironment();
} }
} }

View File

@@ -35,11 +35,24 @@ public class BotManagerImpl implements BotManager, Listener {
public boolean joinMessages = false; public boolean joinMessages = false;
private boolean mobTarget = false; private boolean mobTarget = false;
private boolean addPlayerList = false;
private Location spawnLoc;
public BotManagerImpl() { public BotManagerImpl() {
this.agent = new LegacyAgent(this, TerminatorPlus.getInstance()); this.agent = new LegacyAgent(this, TerminatorPlus.getInstance());
this.bots = ConcurrentHashMap.newKeySet(); //should fix concurrentmodificationexception this.bots = ConcurrentHashMap.newKeySet(); //should fix concurrentmodificationexception
this.numberFormat = NumberFormat.getInstance(Locale.US); this.numberFormat = NumberFormat.getInstance(Locale.US);
} }
@Override
public Location getSpawnLoc() {
return spawnLoc;
}
@Override
public void setSpawnLoc(Location loc) {
spawnLoc = loc;
}
@Override @Override
public Set<Terminator> fetch() { public Set<Terminator> fetch() {
@@ -56,7 +69,17 @@ public class BotManagerImpl implements BotManager, Listener {
} }
@Override @Override
public Terminator getFirst(String name) { public Terminator getFirst(String name, Location target) {
if (target != null) {
Terminator closest = null;
for (Terminator bot : bots) {
if (name.equals(bot.getBotName()) && (closest == null
|| target.distanceSquared(bot.getLocation()) < target.distanceSquared(closest.getLocation()))) {
closest = bot;
}
}
return closest;
}
for (Terminator bot : bots) { for (Terminator bot : bots) {
if (name.equals(bot.getBotName())) { if (name.equals(bot.getBotName())) {
return bot; return bot;
@@ -98,7 +121,18 @@ public class BotManagerImpl implements BotManager, Listener {
skinName = skinName == null ? name : skinName; skinName = skinName == null ? name : skinName;
createBots(sender.getLocation(), name, MojangAPI.getSkin(skinName), n, network); if (spawnLoc != null) {
sender.sendMessage("The spawn location is "
+ ChatColor.BLUE + String.format("(%s, %s, %s)", spawnLoc.getX(), spawnLoc.getY(), spawnLoc.getZ()) + ChatColor.RESET
+ ". This will be reset to the player location next time.");
Location loc = sender.getLocation().clone();
loc.setX(spawnLoc.getX());
loc.setY(spawnLoc.getY());
loc.setZ(spawnLoc.getZ());
createBots(loc, name, MojangAPI.getSkin(skinName), n, network);
spawnLoc = null;
} else
createBots(sender.getLocation(), name, MojangAPI.getSkin(skinName), n, network);
sender.sendMessage("Process completed (" + ChatColor.RED + ((System.currentTimeMillis() - timestamp) / 1000D) + "s" + ChatColor.RESET + ")."); sender.sendMessage("Process completed (" + ChatColor.RED + ((System.currentTimeMillis() - timestamp) / 1000D) + "s" + ChatColor.RESET + ").");
} }
@@ -139,7 +173,6 @@ public class BotManagerImpl implements BotManager, Listener {
} else if (i > 1) { } else if (i > 1) {
bot.setVelocity(randomVelocity().multiply(f)); bot.setVelocity(randomVelocity().multiply(f));
} }
bot.setIgnoredByMobs(!mobTarget);
bots.add(bot); bots.add(bot);
i++; i++;
@@ -164,7 +197,7 @@ public class BotManagerImpl implements BotManager, Listener {
@Override @Override
public void reset() { public void reset() {
if (!bots.isEmpty()) { if (!bots.isEmpty()) {
bots.forEach(Terminator::removeVisually); bots.forEach(Terminator::removeBot);
bots.clear(); // Not always necessary, but a good security measure bots.clear(); // Not always necessary, but a good security measure
} }
@@ -204,6 +237,16 @@ public class BotManagerImpl implements BotManager, Listener {
public void setMobTarget(boolean mobTarget) { public void setMobTarget(boolean mobTarget) {
this.mobTarget = mobTarget; this.mobTarget = mobTarget;
} }
@Override
public boolean addToPlayerList() {
return addPlayerList;
}
@Override
public void setAddToPlayerList(boolean addPlayerList) {
this.addPlayerList = addPlayerList;
}
@EventHandler @EventHandler
public void onJoin(PlayerJoinEvent event) { public void onJoin(PlayerJoinEvent event) {
@@ -222,8 +265,10 @@ public class BotManagerImpl implements BotManager, Listener {
@EventHandler @EventHandler
public void onMobTarget(EntityTargetLivingEntityEvent event) { public void onMobTarget(EntityTargetLivingEntityEvent event) {
Bot bot = (Bot) getBot(event.getEntity().getUniqueId()); if (mobTarget || event.getTarget() == null)
if (bot != null && bot.isIgnoredByMobs()) { return;
Bot bot = (Bot) getBot(event.getTarget().getUniqueId());
if (bot != null) {
event.setCancelled(true); event.setCancelled(true);
} }
} }

View File

@@ -121,7 +121,7 @@ public class AICommand extends CommandInstance implements AIManager {
scheduler.runTaskAsynchronously(plugin, () -> { scheduler.runTaskAsynchronously(plugin, () -> {
try { try {
Terminator bot = manager.getFirst(name); Terminator bot = manager.getFirst(name, (sender instanceof Player pl) ? pl.getLocation() : null);
if (bot == null) { if (bot == null) {
sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!"); sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!");

View File

@@ -22,10 +22,13 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public class BotCommand extends CommandInstance { public class BotCommand extends CommandInstance {
@@ -141,7 +144,6 @@ public class BotCommand extends CommandInstance {
desc = "Gives all bots an armor set.", desc = "Gives all bots an armor set.",
autofill = "armorAutofill" autofill = "armorAutofill"
) )
@SuppressWarnings("deprecation")
public void armor(CommandSender sender, @Arg("armor-tier") String armorTier) { public void armor(CommandSender sender, @Arg("armor-tier") String armorTier) {
String tier = armorTier.toLowerCase(); String tier = armorTier.toLowerCase();
@@ -190,7 +192,7 @@ public class BotCommand extends CommandInstance {
scheduler.runTaskAsynchronously(plugin, () -> { scheduler.runTaskAsynchronously(plugin, () -> {
try { try {
Terminator bot = manager.getFirst(name); Terminator bot = manager.getFirst(name, (sender instanceof Player pl) ? pl.getLocation() : null);
if (bot == null) { if (bot == null) {
sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!"); sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!");
@@ -211,7 +213,7 @@ public class BotCommand extends CommandInstance {
String botName = bot.getBotName(); String botName = bot.getBotName();
String world = ChatColor.YELLOW + bot.getBukkitEntity().getWorld().getName(); String world = ChatColor.YELLOW + bot.getBukkitEntity().getWorld().getName();
Location loc = bot.getLocation(); Location loc = bot.getLocation();
String strLoc = ChatColor.YELLOW + formatter.format(loc.getBlockX()) + ", " + formatter.format(loc.getBlockY()) + ", " + formatter.format(loc.getBlockZ()); String strLoc = ChatColor.YELLOW + formatter.format(loc.getX()) + ", " + formatter.format(loc.getY()) + ", " + formatter.format(loc.getZ());
Vector vel = bot.getVelocity(); Vector vel = bot.getVelocity();
String strVel = ChatColor.AQUA + formatter.format(vel.getX()) + ", " + formatter.format(vel.getY()) + ", " + formatter.format(vel.getZ()); String strVel = ChatColor.AQUA + formatter.format(vel.getX()) + ", " + formatter.format(vel.getY()) + ", " + formatter.format(vel.getZ());
@@ -231,6 +233,23 @@ public class BotCommand extends CommandInstance {
public List<String> infoAutofill(CommandSender sender, String[] args) { public List<String> infoAutofill(CommandSender sender, String[] args) {
return args.length == 2 ? manager.fetchNames() : null; return args.length == 2 ? manager.fetchNames() : null;
} }
@Command(
name = "count",
desc = "Counts the amount of bots on screen by name."
)
public void count(CommandSender sender) {
List<String> names = manager.fetchNames();
Map<String, Integer> freqMap = names.stream().collect(Collectors.toMap(s -> s, s -> 1, Integer::sum));
List<Entry<String, Integer>> entries = freqMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toList());
sender.sendMessage(ChatUtils.LINE);
entries.forEach(en -> sender.sendMessage(ChatColor.GREEN + en.getKey()
+ ChatColor.RESET + " - " + ChatColor.BLUE + en.getValue().toString() + ChatColor.RESET));
sender.sendMessage("Total bots: " + ChatColor.BLUE + freqMap.values().stream().reduce(0, Integer::sum) + ChatColor.RESET);
sender.sendMessage(ChatUtils.LINE);
}
@Command( @Command(
name = "reset", name = "reset",
@@ -267,17 +286,68 @@ public class BotCommand extends CommandInstance {
String extra = ChatColor.GRAY + " [" + ChatColor.YELLOW + "/bot settings" + ChatColor.GRAY + "]"; String extra = ChatColor.GRAY + " [" + ChatColor.YELLOW + "/bot settings" + ChatColor.GRAY + "]";
if (arg1 == null || ((!arg1.equalsIgnoreCase("setgoal")) && !arg1.equalsIgnoreCase("mobtarget") && !arg1.equalsIgnoreCase("playertarget"))) { if (arg1 == null || (!arg1.equalsIgnoreCase("spawnloc") && !arg1.equalsIgnoreCase("setgoal") && !arg1.equalsIgnoreCase("mobtarget") && !arg1.equalsIgnoreCase("playertarget")
&& !arg1.equalsIgnoreCase("addplayerlist") && !arg1.equalsIgnoreCase("region"))) {
sender.sendMessage(ChatUtils.LINE); sender.sendMessage(ChatUtils.LINE);
sender.sendMessage(ChatColor.GOLD + "Bot Settings" + extra); sender.sendMessage(ChatColor.GOLD + "Bot Settings" + extra);
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "spawnloc" + ChatUtils.BULLET_FORMATTED + "Set the location where the bots should spawn. This will be reset after a spawn command is executed.");
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "setgoal" + ChatUtils.BULLET_FORMATTED + "Set the global bot target selection method."); sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "setgoal" + ChatUtils.BULLET_FORMATTED + "Set the global bot target selection method.");
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "mobtarget" + ChatUtils.BULLET_FORMATTED + "Allow all future bots spawned to be targeted by hostile mobs."); sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "mobtarget" + ChatUtils.BULLET_FORMATTED + "Allow all bots to be targeted by hostile mobs.");
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "playertarget" + ChatUtils.BULLET_FORMATTED + "Sets a player name for spawned bots to focus on if the goal is PLAYER.");
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "addplayerlist" + ChatUtils.BULLET_FORMATTED + "Adds newly spawned bots to the player list. This allows the bots to be affected by player selectors like @a and @p.");
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "region" + ChatUtils.BULLET_FORMATTED + "Sets a region for the bots to prioritize entities inside.");
sender.sendMessage(ChatUtils.LINE); sender.sendMessage(ChatUtils.LINE);
return; return;
} }
if (arg1.equalsIgnoreCase("setgoal")) { if (arg1.equalsIgnoreCase("spawnloc")) {
EnumTargetGoal goal = EnumTargetGoal.from(arg2 == null ? "" : arg2); if (arg2 == null) {
if (manager.getSpawnLoc() == null)
sender.sendMessage("No custom spawn location has been set. The bots will spawn at the player location.");
else {
Location loc = manager.getSpawnLoc();
sender.sendMessage("The next spawn location will be at " + ChatColor.BLUE + String.format("(%s, %s, %s)", loc.getX(), loc.getY(), loc.getZ()) + ChatColor.RESET + ".");
}
return;
}
if (arg2.equalsIgnoreCase("clear")) {
manager.setSpawnLoc(null);
sender.sendMessage("The spawn location has been reset to the player location.");
return;
}
if (arg2.equalsIgnoreCase("playerloc")) {
if (!(sender instanceof Player)) {
sender.sendMessage("You must be a player to do this!");
return;
}
Location loc = ((Player)sender).getLocation();
manager.setSpawnLoc(loc.clone());
sender.sendMessage("The spawn location has been set to " + ChatColor.BLUE + formatter.format(loc.getX()) + ", " + formatter.format(loc.getY()) + ", " + formatter.format(loc.getZ()) + ChatColor.RESET + ".");
return;
}
if (args.size() != 4) {
sender.sendMessage("Incorrect argument size. Correct syntax: " + ChatColor.YELLOW + "/bot settings spawnloc <x> <y> <z>" + ChatColor.RESET);
sender.sendMessage("Additionally, to specify a spawnloc at the current player position: " + ChatColor.YELLOW + "/bot settings spawnloc playerloc" + ChatColor.RESET);
return;
}
double x, y, z;
try {
x = Double.parseDouble(args.get(1));
y = Double.parseDouble(args.get(2));
z = Double.parseDouble(args.get(3));
} catch (NumberFormatException e) {
sender.sendMessage("The block coordinates must be doubles!");
sender.sendMessage("Correct syntax: " + ChatColor.YELLOW + "/bot settings spawnloc <x> <y> <z>" + ChatColor.RESET);
return;
}
manager.setSpawnLoc(new Location(null, x, y, z));
sender.sendMessage("The next spawn location has been set to " + ChatColor.BLUE + String.format("(%s, %s, %s)", x, y, z) + ChatColor.RESET + ".");
} else if (arg1.equalsIgnoreCase("setgoal")) {
if (arg2 == null) {
sender.sendMessage("The global bot goal is currently " + ChatColor.BLUE + agent.getTargetType() + ChatColor.RESET + ".");
return;
}
EnumTargetGoal goal = EnumTargetGoal.from(arg2);
if (goal == null) { if (goal == null) {
sender.sendMessage(ChatUtils.LINE); sender.sendMessage(ChatUtils.LINE);
@@ -290,14 +360,22 @@ public class BotCommand extends CommandInstance {
agent.setTargetType(goal); agent.setTargetType(goal);
sender.sendMessage("The global bot goal has been set to " + ChatColor.BLUE + goal.name() + ChatColor.RESET + "."); sender.sendMessage("The global bot goal has been set to " + ChatColor.BLUE + goal.name() + ChatColor.RESET + ".");
} else if (arg1.equalsIgnoreCase("mobtarget")) { } else if (arg1.equalsIgnoreCase("mobtarget")) {
manager.setMobTarget(!manager.isMobTarget()); if (arg2 == null) {
sender.sendMessage("Mob targeting is now " + (manager.isMobTarget() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ". (for all future bots)"); sender.sendMessage("Mob targeting is currently " + (manager.isMobTarget() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
return;
}
if (!arg2.equals("true") && !arg2.equals("false")) {
sender.sendMessage(ChatColor.RED + "You must specify true or false!");
return;
}
manager.setMobTarget(Boolean.parseBoolean(arg2));
sender.sendMessage("Mob targeting is now " + (manager.isMobTarget() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
} else if (arg1.equalsIgnoreCase("playertarget")) { } else if (arg1.equalsIgnoreCase("playertarget")) {
if (args.size() < 2) { if (args.size() < 2) {
sender.sendMessage(ChatColor.RED + "You must specify a player name!"); sender.sendMessage(ChatColor.RED + "You must specify a player name!");
return; return;
} }
String playerName = args.get(1); String playerName = arg2;
Player player = Bukkit.getPlayer(playerName); Player player = Bukkit.getPlayer(playerName);
if (player == null) { if (player == null) {
sender.sendMessage(ChatColor.RED + "Could not find player " + ChatColor.YELLOW + playerName + ChatColor.RED + "!"); sender.sendMessage(ChatColor.RED + "Could not find player " + ChatColor.YELLOW + playerName + ChatColor.RED + "!");
@@ -307,6 +385,88 @@ public class BotCommand extends CommandInstance {
fetch.setTargetPlayer(player.getUniqueId()); fetch.setTargetPlayer(player.getUniqueId());
} }
sender.sendMessage("All spawned bots are now set to target " + ChatColor.BLUE + player.getName() + ChatColor.RESET + ". They will target the closest player if they can't be found.\nYou may need to set the goal to PLAYER."); sender.sendMessage("All spawned bots are now set to target " + ChatColor.BLUE + player.getName() + ChatColor.RESET + ". They will target the closest player if they can't be found.\nYou may need to set the goal to PLAYER.");
} else if (arg1.equalsIgnoreCase("addplayerlist")) {
if (arg2 == null) {
sender.sendMessage("Adding bots to the player list is currently " + (manager.addToPlayerList() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
return;
}
if (!arg2.equals("true") && !arg2.equals("false")) {
sender.sendMessage(ChatColor.RED + "You must specify true or false!");
return;
}
manager.setAddToPlayerList(Boolean.parseBoolean(arg2));
sender.sendMessage("Adding bots to the player list is now " + (manager.addToPlayerList() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
} else if (arg1.equalsIgnoreCase("region")) {
if (arg2 == null) {
if (agent.getRegion() == null) {
sender.sendMessage("No region has been set.");
return;
}
sender.sendMessage("The current region is " + ChatColor.BLUE + agent.getRegion() + ChatColor.RESET + ".");
if (agent.getRegionWeightX() == 0 && agent.getRegionWeightY() == 0 && agent.getRegionWeightZ() == 0)
sender.sendMessage("Entities out of range will not be targeted.");
else {
sender.sendMessage("The region X weight is " + ChatColor.BLUE + agent.getRegionWeightX() + ChatColor.RESET + ".");
sender.sendMessage("The region Y weight is " + ChatColor.BLUE + agent.getRegionWeightY() + ChatColor.RESET + ".");
sender.sendMessage("The region Z weight is " + ChatColor.BLUE + agent.getRegionWeightZ() + ChatColor.RESET + ".");
}
return;
}
if (arg2.equalsIgnoreCase("clear")) {
agent.setRegion(null, 0, 0, 0);
sender.sendMessage("The region has been cleared.");
return;
}
boolean strict = args.size() == 8 && args.get(7).equalsIgnoreCase("strict");
if (args.size() != 10 && !strict) {
sender.sendMessage(ChatUtils.LINE);
sender.sendMessage(ChatColor.GOLD + "Bot Region Settings" + extra);
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "<x1> <y1> <z1> <x2> <y2> <z2> <wX> <wY> <wZ>" + ChatUtils.BULLET_FORMATTED
+ "Sets a region for bots to prioritize entities within.");
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "<x1> <y1> <z1> <x2> <y2> <z2> strict" + ChatUtils.BULLET_FORMATTED
+ "Sets a region so that the bots only target entities within the region.");
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "clear" + ChatUtils.BULLET_FORMATTED
+ "Clears the region.");
sender.sendMessage("Without strict mode, the entity distance from the region is multiplied by the weight values if outside the region.");
sender.sendMessage("The resulting value is added to the entity distance when selecting an entity.");
sender.sendMessage(ChatUtils.LINE);
return;
}
double x1, y1, z1, x2, y2, z2, wX, wY, wZ;
try {
Location loc = sender instanceof Player pl ? pl.getLocation() : null;
x1 = parseDoubleOrRelative(args.get(1), loc, 0);
y1 = parseDoubleOrRelative(args.get(2), loc, 1);
z1 = parseDoubleOrRelative(args.get(3), loc, 2);
x2 = parseDoubleOrRelative(args.get(4), loc, 0);
y2 = parseDoubleOrRelative(args.get(5), loc, 1);
z2 = parseDoubleOrRelative(args.get(6), loc, 2);
if (strict)
wX = wY = wZ = 0;
else {
wX = Double.parseDouble(args.get(7));
wY = Double.parseDouble(args.get(8));
wZ = Double.parseDouble(args.get(9));
if (wX <= 0 || wY <= 0 || wZ <= 0) {
sender.sendMessage("The region weights must be positive values!");
return;
}
}
} catch (NumberFormatException e) {
sender.sendMessage("The region bounds and weights must be valid numbers!");
sender.sendMessage("Correct syntax: " + ChatColor.YELLOW + "/bot settings region <x1> <y1> <z1> <x2> <y2> <z2> <wX> <wY> <wZ>"
+ ChatColor.RESET);
return;
}
agent.setRegion(new BoundingBox(x1, y1, z1, x2, y2, z2), wX, wY, wZ);
sender.sendMessage("The region has been set to " + ChatColor.BLUE + agent.getRegion() + ChatColor.RESET + ".");
if (wX == 0 && wY == 0 && wZ == 0)
sender.sendMessage("Entities out of range will not be targeted.");
else {
sender.sendMessage("The region X weight is " + ChatColor.BLUE + agent.getRegionWeightX() + ChatColor.RESET + ".");
sender.sendMessage("The region Y weight is " + ChatColor.BLUE + agent.getRegionWeightY() + ChatColor.RESET + ".");
sender.sendMessage("The region Z weight is " + ChatColor.BLUE + agent.getRegionWeightZ() + ChatColor.RESET + ".");
}
} }
} }
@@ -323,8 +483,12 @@ public class BotCommand extends CommandInstance {
// lookall // lookall
if (args.length == 2) { if (args.length == 2) {
output.add("spawnloc");
output.add("setgoal"); output.add("setgoal");
output.add("mobtarget"); output.add("mobtarget");
output.add("playertarget");
output.add("addplayerlist");
output.add("region");
} else if (args.length == 3) { } else if (args.length == 3) {
if (args[1].equalsIgnoreCase("setgoal")) { if (args[1].equalsIgnoreCase("setgoal")) {
Arrays.stream(EnumTargetGoal.values()).forEach(goal -> output.add(goal.name().replace("_", "").toLowerCase())); Arrays.stream(EnumTargetGoal.values()).forEach(goal -> output.add(goal.name().replace("_", "").toLowerCase()));
@@ -333,6 +497,15 @@ public class BotCommand extends CommandInstance {
output.add("true"); output.add("true");
output.add("false"); output.add("false");
} }
if (args[1].equalsIgnoreCase("playertarget")) {
for (Player player : Bukkit.getOnlinePlayers()) {
output.add(player.getName());
}
}
if (args[1].equalsIgnoreCase("addplayerlist")) {
output.add("true");
output.add("false");
}
} }
return output; return output;
@@ -346,4 +519,20 @@ public class BotCommand extends CommandInstance {
public void debug(CommandSender sender, @Arg("expression") String expression) { public void debug(CommandSender sender, @Arg("expression") String expression) {
new Debugger(sender).execute(expression); new Debugger(sender).execute(expression);
} }
private double parseDoubleOrRelative(String pos, Location loc, int type) {
if (loc == null || pos.length() == 0 || pos.charAt(0) != '~')
return Double.parseDouble(pos);
double relative = Double.parseDouble(pos.substring(1));
switch (type) {
case 0:
return relative + Math.round(loc.getX() * 1000) / 1000D;
case 1:
return relative + Math.round(loc.getY() * 1000) / 1000D;
case 2:
return relative + Math.round(loc.getZ() * 1000) / 1000D;
default:
return 0;
}
}
} }

View File

@@ -365,10 +365,6 @@ public class Debugger {
print("This has been established as a feature as \"" + ChatColor.AQUA + "/bot settings setgoal" + ChatColor.RESET + "\"!"); print("This has been established as a feature as \"" + ChatColor.AQUA + "/bot settings setgoal" + ChatColor.RESET + "\"!");
} }
public void fire(boolean b) {
TerminatorPlus.getInstance().getManager().fetch().forEach(bot -> bot.setOnFirePackets(b));
}
public void trackYVel() { public void trackYVel() {
if (!(sender instanceof Player)) return; if (!(sender instanceof Player)) return;