Merge pull request #57 from ThisTestUser/fixes
Bug fixes / Enhancements
This commit is contained in:
32
.github/workflows/compile.yml
vendored
Normal file
32
.github/workflows/compile.yml
vendored
Normal 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/
|
||||
68
.github/workflows/dev-analysis.yml
vendored
68
.github/workflows/dev-analysis.yml
vendored
@@ -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/
|
||||
@@ -10,13 +10,17 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface BotManager {
|
||||
Location getSpawnLoc();
|
||||
|
||||
void setSpawnLoc(Location loc);
|
||||
|
||||
Set<Terminator> fetch();
|
||||
|
||||
Agent getAgent();
|
||||
|
||||
void add(Terminator bot);
|
||||
|
||||
Terminator getFirst(String name);
|
||||
Terminator getFirst(String name, Location target);
|
||||
|
||||
List<String> fetchNames();
|
||||
|
||||
@@ -50,4 +54,7 @@ public interface BotManager {
|
||||
|
||||
void setMobTarget(boolean mobTarget);
|
||||
|
||||
boolean addToPlayerList();
|
||||
|
||||
void setAddToPlayerList(boolean addPlayerList);
|
||||
}
|
||||
|
||||
@@ -4,13 +4,17 @@ import com.mojang.authlib.GameProfile;
|
||||
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Terminator {
|
||||
@@ -31,14 +35,14 @@ public interface Terminator {
|
||||
|
||||
Location getLocation();
|
||||
|
||||
BoundingBox getBotBoundingBox();
|
||||
|
||||
boolean isBotAlive(); //Has to be named like this because paper re-obfuscates it
|
||||
|
||||
float getBotHealth();
|
||||
|
||||
float getBotMaxHealth();
|
||||
|
||||
void ignite();
|
||||
|
||||
boolean isBotOnFire();
|
||||
|
||||
boolean isFalling();
|
||||
@@ -51,6 +55,8 @@ public interface Terminator {
|
||||
|
||||
boolean isBotOnGround();
|
||||
|
||||
List<Block> getStandingOn();
|
||||
|
||||
void setBotPitch(float pitch);
|
||||
|
||||
default void setBotXRot(float pitch) {
|
||||
@@ -107,13 +113,17 @@ public interface Terminator {
|
||||
|
||||
int getAliveTicks();
|
||||
|
||||
int getNoFallTicks();
|
||||
|
||||
boolean tickDelay(int ticks);
|
||||
|
||||
void renderBot(Object packetListener, boolean login);
|
||||
|
||||
void setOnFirePackets(boolean onFire);
|
||||
|
||||
UUID getTargetPlayer();
|
||||
|
||||
void setTargetPlayer(UUID target);
|
||||
|
||||
boolean isInPlayerList();
|
||||
|
||||
World.Environment getDimension();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ public enum EnumTargetGoal {
|
||||
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_HOSTILE("Locate the nearest hostile entity."),
|
||||
NEAREST_RAIDER("Locate the nearest raider."),
|
||||
NEAREST_MOB("Locate the nearest mob."),
|
||||
NEAREST_BOT("Locate the nearest bot."),
|
||||
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("nearestplayer", NEAREST_PLAYER);
|
||||
this.put("nearesthostile", NEAREST_HOSTILE);
|
||||
this.put("nearestraider", NEAREST_RAIDER);
|
||||
this.put("nearestmob", NEAREST_MOB);
|
||||
this.put("nearestbot", NEAREST_BOT);
|
||||
this.put("nearestbotdiffer", NEAREST_BOT_DIFFER);
|
||||
this.put("nearestbotdifferalpha", NEAREST_BOT_DIFFER_ALPHA);
|
||||
this.put("player", PLAYER);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,18 +11,25 @@ import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent;
|
||||
import net.nuggetmc.tplus.api.event.BotDeathEvent;
|
||||
import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
|
||||
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.PlayerUtils;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.Waterlogged;
|
||||
import org.bukkit.block.data.type.*;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
// 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 Set<Terminator> fallDamageCooldown = new HashSet<>();
|
||||
public boolean offsets = true;
|
||||
private List<Material> instantBreakBlocks = Arrays.asList(
|
||||
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 List<LivingEntity> botsInPlayerList;
|
||||
private EnumTargetGoal goal;
|
||||
private BoundingBox region;
|
||||
private double regionWeightX;
|
||||
private double regionWeightY;
|
||||
private double regionWeightZ;
|
||||
|
||||
public LegacyAgent(BotManager manager, Plugin plugin) {
|
||||
super(manager, plugin);
|
||||
@@ -75,7 +70,8 @@ public class LegacyAgent extends Agent {
|
||||
|
||||
@Override
|
||||
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) {
|
||||
@@ -115,6 +111,8 @@ public class LegacyAgent extends Agent {
|
||||
Location loc = bot.getLocation();
|
||||
LivingEntity livingTarget = locateTarget(bot, loc);
|
||||
|
||||
blockCheck.tryPreMLG(bot, loc);
|
||||
|
||||
if (livingTarget == null) {
|
||||
stopMining(bot);
|
||||
return;
|
||||
@@ -180,11 +178,13 @@ public class LegacyAgent extends Agent {
|
||||
|
||||
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 ((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);
|
||||
|
||||
@@ -303,7 +303,7 @@ public class LegacyAgent extends Agent {
|
||||
|
||||
Material itemType;
|
||||
|
||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
||||
if (bot.getDimension() == World.Environment.NETHER) {
|
||||
itemType = Material.TWISTING_VINES;
|
||||
} else {
|
||||
itemType = Material.WATER_BUCKET;
|
||||
@@ -344,26 +344,50 @@ public class LegacyAgent extends Agent {
|
||||
Material itemType;
|
||||
Material placeType;
|
||||
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;
|
||||
sound = Sound.BLOCK_WEEPING_VINES_PLACE;
|
||||
placeType = itemType;
|
||||
|
||||
for (Block block : event.getStandingOn()) {
|
||||
if (LegacyMats.canPlaceTwistingVines(block)) {
|
||||
groundLoc = block.getLocation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
itemType = Material.WATER_BUCKET;
|
||||
sound = Sound.ITEM_BUCKET_EMPTY;
|
||||
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);
|
||||
|
||||
if (loc.getBlock().getType() != placeType) {
|
||||
if (loc.getBlock().getType() != placeType && !waterlogged) {
|
||||
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);
|
||||
|
||||
if (itemType == Material.WATER_BUCKET) {
|
||||
@@ -372,11 +396,18 @@ public class LegacyAgent extends Agent {
|
||||
scheduler.runTaskLater(plugin, () -> {
|
||||
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.setItem(new ItemStack(Material.WATER_BUCKET));
|
||||
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);
|
||||
}
|
||||
@@ -442,7 +473,7 @@ public class LegacyAgent extends Agent {
|
||||
if (level == null) {
|
||||
resetHand(npc, target, playerNPC);
|
||||
return 1;
|
||||
} else if (level.isSide()) {
|
||||
} else if (level.isSide() || level == LegacyLevel.BELOW || level == LegacyLevel.ABOVE) {
|
||||
return 0;
|
||||
} else {
|
||||
return 2;
|
||||
@@ -458,6 +489,71 @@ public class LegacyAgent extends Agent {
|
||||
LegacyLevel level = 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) {
|
||||
case NORTH:
|
||||
get = player.getLocation().add(0, 1, -1).getBlock();
|
||||
@@ -466,6 +562,35 @@ public class LegacyAgent extends Agent {
|
||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||
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;
|
||||
case SOUTH:
|
||||
@@ -475,6 +600,35 @@ public class LegacyAgent extends Agent {
|
||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||
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;
|
||||
case EAST:
|
||||
@@ -484,6 +638,35 @@ public class LegacyAgent extends Agent {
|
||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||
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;
|
||||
case WEST:
|
||||
@@ -493,27 +676,91 @@ public class LegacyAgent extends Agent {
|
||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||
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;
|
||||
default:
|
||||
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())
|
||||
&& 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;
|
||||
}
|
||||
}
|
||||
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 == 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);
|
||||
}
|
||||
|
||||
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 b = target.getLocation();
|
||||
|
||||
@@ -568,24 +815,25 @@ public class LegacyAgent extends Agent {
|
||||
npc.look(BlockFace.DOWN);
|
||||
|
||||
// maybe put this in lower if statement onGround()
|
||||
scheduler.runTaskLater(plugin, () -> {
|
||||
npc.sneak();
|
||||
npc.setItem(new ItemStack(Material.COBBLESTONE));
|
||||
npc.punch();
|
||||
npc.look(BlockFace.DOWN);
|
||||
if (m0 != Material.WATER)
|
||||
scheduler.runTaskLater(plugin, () -> {
|
||||
npc.sneak();
|
||||
npc.setItem(new ItemStack(Material.COBBLESTONE));
|
||||
npc.punch();
|
||||
npc.look(BlockFace.DOWN);
|
||||
|
||||
scheduler.runTaskLater(plugin, () -> {
|
||||
npc.look(BlockFace.DOWN);
|
||||
}, 1);
|
||||
scheduler.runTaskLater(plugin, () -> {
|
||||
npc.look(BlockFace.DOWN);
|
||||
}, 1);
|
||||
|
||||
blockCheck.placeBlock(npc, playerNPC, place);
|
||||
blockCheck.placeBlock(npc, playerNPC, place);
|
||||
|
||||
if (!towerList.containsKey(playerNPC)) {
|
||||
if (c) {
|
||||
towerList.put(playerNPC, playerNPC.getLocation());
|
||||
}
|
||||
}
|
||||
}, 5);
|
||||
if (!towerList.containsKey(playerNPC)) {
|
||||
if (c) {
|
||||
towerList.put(playerNPC, playerNPC.getLocation());
|
||||
}
|
||||
}
|
||||
}, 3);
|
||||
|
||||
if (npc.isBotOnGround()) {
|
||||
if (target.getLocation().distance(playerNPC.getLocation()) < 16) {
|
||||
@@ -645,6 +893,16 @@ public class LegacyAgent extends Agent {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
downMine(npc, player, block);
|
||||
@@ -671,7 +931,9 @@ public class LegacyAgent extends Agent {
|
||||
b.setY(0);
|
||||
|
||||
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);
|
||||
|
||||
downMine(npc, player, block);
|
||||
@@ -719,8 +981,8 @@ public class LegacyAgent extends Agent {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkFence(Terminator bot, Block block, LivingEntity player) {
|
||||
if (LegacyMats.FENCE.contains(block.getType())) {
|
||||
private boolean checkFenceAndGates(Terminator bot, Block block, LivingEntity player) {
|
||||
if (LegacyMats.FENCE.contains(block.getType()) || LegacyMats.GATES.contains(block.getType())) {
|
||||
preBreak(bot, player, block, LegacyLevel.AT_D);
|
||||
return true;
|
||||
}
|
||||
@@ -728,6 +990,23 @@ public class LegacyAgent extends Agent {
|
||||
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) {
|
||||
if (LegacyMats.BREAK.contains(block.getType())) {
|
||||
return false;
|
||||
@@ -751,13 +1030,15 @@ public class LegacyAgent extends Agent {
|
||||
|
||||
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);
|
||||
|
||||
scheduler.runTaskLater(plugin, () -> {
|
||||
btCheck.put(player, true);
|
||||
}, 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);
|
||||
bot.faceLocation(blockLoc);
|
||||
}
|
||||
@@ -777,10 +1058,10 @@ public class LegacyAgent extends Agent {
|
||||
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;
|
||||
|
||||
@@ -792,47 +1073,45 @@ public class LegacyAgent extends Agent {
|
||||
byte i = mining.get(this);
|
||||
|
||||
Block cur;
|
||||
switch (level) {
|
||||
case ABOVE:
|
||||
cur = player.getLocation().add(0, 2, 0).getBlock();
|
||||
break;
|
||||
case BELOW:
|
||||
cur = player.getLocation().add(0, -1, 0).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();
|
||||
if (wrapper.getLevel() == null)
|
||||
cur = player.getLocation().add(0, 1, 0).getBlock();
|
||||
else if (wrapper.getLevel() == LegacyLevel.BELOW)
|
||||
cur = bot.getStandingOn().isEmpty() ? null : bot.getStandingOn().get(0);
|
||||
else
|
||||
cur = wrapper.getLevel().offset(player.getLocation()).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
|
||||
|
||||
if (player.isDead() || (!block.equals(cur) || block.getType() != cur.getType())) {
|
||||
if (player.isDead() || cur == null || (!block.equals(cur) || block.getType() != cur.getType())) {
|
||||
this.cancel();
|
||||
|
||||
TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1);
|
||||
@@ -857,7 +1136,7 @@ public class LegacyAgent extends Agent {
|
||||
|
||||
block.breakNaturally();
|
||||
|
||||
if (level == LegacyLevel.ABOVE) {
|
||||
if (wrapper.getLevel() == LegacyLevel.ABOVE) {
|
||||
noJump.add(player);
|
||||
|
||||
scheduler.runTaskLater(plugin, () -> {
|
||||
@@ -875,10 +1154,13 @@ public class LegacyAgent extends Agent {
|
||||
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;
|
||||
|
||||
if (instantBreakBlocks.contains(block.getType())) { // instant break blocks
|
||||
if (LegacyMats.INSTANT_BREAK.contains(block.getType())) { // instant break blocks
|
||||
block.breakNaturally();
|
||||
return;
|
||||
}
|
||||
@@ -924,7 +1206,7 @@ public class LegacyAgent extends Agent {
|
||||
Location loc = bot.getLocation();
|
||||
|
||||
if (bot.isBotOnFire()) {
|
||||
if (bot.getBukkitEntity().getWorld().getEnvironment() != World.Environment.NETHER) {
|
||||
if (bot.getDimension() != World.Environment.NETHER) {
|
||||
placeWaterDown(bot, world, loc);
|
||||
}
|
||||
}
|
||||
@@ -932,7 +1214,7 @@ public class LegacyAgent extends Agent {
|
||||
Material atType = loc.getBlock().getType();
|
||||
|
||||
if (atType == Material.FIRE || atType == Material.SOUL_FIRE) {
|
||||
if (bot.getBukkitEntity().getWorld().getEnvironment() != World.Environment.NETHER) {
|
||||
if (bot.getDimension() != World.Environment.NETHER) {
|
||||
placeWaterDown(bot, world, loc);
|
||||
world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
|
||||
} else {
|
||||
@@ -944,7 +1226,7 @@ public class LegacyAgent extends Agent {
|
||||
}
|
||||
|
||||
if (atType == Material.LAVA) {
|
||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
||||
if (bot.getDimension() == World.Environment.NETHER) {
|
||||
bot.attemptBlockPlace(loc, Material.COBBLESTONE, false);
|
||||
} else {
|
||||
placeWaterDown(bot, world, loc);
|
||||
@@ -955,7 +1237,7 @@ public class LegacyAgent extends Agent {
|
||||
Material headType = head.getBlock().getType();
|
||||
|
||||
if (headType == Material.LAVA) {
|
||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
||||
if (bot.getDimension() == World.Environment.NETHER) {
|
||||
bot.attemptBlockPlace(head, Material.COBBLESTONE, false);
|
||||
} else {
|
||||
placeWaterDown(bot, world, head);
|
||||
@@ -963,7 +1245,7 @@ public class LegacyAgent extends Agent {
|
||||
}
|
||||
|
||||
if (headType == Material.FIRE || headType == Material.SOUL_FIRE) {
|
||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
||||
if (bot.getDimension() == World.Environment.NETHER) {
|
||||
bot.look(BlockFace.DOWN);
|
||||
bot.punch();
|
||||
world.playSound(head, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
|
||||
@@ -1112,11 +1394,38 @@ public class LegacyAgent extends Agent {
|
||||
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) {
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
public LivingEntity locateTarget(Terminator bot, Location loc, EnumTargetGoal... targetGoal) {
|
||||
private LivingEntity locateTarget(Terminator bot, Location loc, EnumTargetGoal... targetGoal) {
|
||||
LivingEntity result = null;
|
||||
|
||||
EnumTargetGoal g = goal;
|
||||
@@ -1127,7 +1436,7 @@ public class LegacyAgent extends Agent {
|
||||
|
||||
case NEAREST_PLAYER: {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (validateCloserEntity(player, loc, result)) {
|
||||
if (!botsInPlayerList.contains(player) && validateCloserEntity(player, loc, result)) {
|
||||
result = player;
|
||||
}
|
||||
}
|
||||
@@ -1137,7 +1446,7 @@ public class LegacyAgent extends Agent {
|
||||
|
||||
case NEAREST_VULNERABLE_PLAYER: {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1155,6 +1464,16 @@ public class LegacyAgent extends Agent {
|
||||
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: {
|
||||
for (LivingEntity entity : bot.getBukkitEntity().getWorld().getLivingEntities()) {
|
||||
if (entity instanceof Mob && validateCloserEntity(entity, loc, result)) {
|
||||
@@ -1211,7 +1530,7 @@ public class LegacyAgent extends Agent {
|
||||
case PLAYER: { //Target a single player. Defaults to NEAREST_VULNERABLE_PLAYER if no player found.
|
||||
if (bot.getTargetPlayer() != null) {
|
||||
Player player = Bukkit.getPlayer(bot.getTargetPlayer());
|
||||
if (player != null) {
|
||||
if (player != null && !botsInPlayerList.contains(player) && validateCloserEntity(player, loc, null)) {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -1225,6 +1544,36 @@ public class LegacyAgent extends Agent {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent;
|
||||
|
||||
import net.nuggetmc.tplus.api.Terminator;
|
||||
import net.nuggetmc.tplus.api.utils.BotUtils;
|
||||
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
@@ -8,9 +10,15 @@ import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class LegacyBlockCheck {
|
||||
@@ -136,6 +144,90 @@ public class LegacyBlockCheck {
|
||||
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) {
|
||||
Location botLoc = bot.getLocation();
|
||||
|
||||
|
||||
@@ -4,32 +4,162 @@ import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public enum LegacyLevel {
|
||||
ABOVE,
|
||||
BELOW,
|
||||
AT,
|
||||
AT_D,
|
||||
NORTH,
|
||||
SOUTH,
|
||||
EAST,
|
||||
WEST,
|
||||
NORTH_D,
|
||||
SOUTH_D,
|
||||
EAST_D,
|
||||
WEST_D;
|
||||
import org.bukkit.Location;
|
||||
|
||||
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,
|
||||
SOUTH,
|
||||
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,
|
||||
SOUTH_D,
|
||||
EAST_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() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent;
|
||||
|
||||
import org.bukkit.Axis;
|
||||
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.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class LegacyMats {
|
||||
|
||||
public static final Set<Material> AIR = new HashSet<>(Arrays.asList(
|
||||
Material.WATER,
|
||||
Material.OAK_TRAPDOOR,
|
||||
Material.FIRE,
|
||||
Material.LAVA,
|
||||
Material.SNOW,
|
||||
@@ -36,33 +49,49 @@ public class LegacyMats {
|
||||
Material.FIRE,
|
||||
Material.LAVA,
|
||||
Material.CAVE_AIR,
|
||||
Material.VOID_AIR,
|
||||
Material.AIR,
|
||||
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.GRASS_BLOCK,
|
||||
Material.COARSE_DIRT,
|
||||
Material.PODZOL,
|
||||
Material.MYCELIUM,
|
||||
Material.GRAVEL,
|
||||
Material.MUD,
|
||||
Material.MUDDY_MANGROVE_ROOTS,
|
||||
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(
|
||||
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.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.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.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.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.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.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.WARPED_PLANKS, Material.WARPED_DOOR, Material.WARPED_FENCE, Material.WARPED_FENCE_GATE, Material.WARPED_PLANKS,
|
||||
Material.WARPED_SIGN, Material.WARPED_SLAB, Material.WARPED_STAIRS, Material.WARPED_TRAPDOOR, Material.WARPED_WALL_SIGN
|
||||
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.CHEST, Material.TRAPPED_CHEST
|
||||
));
|
||||
|
||||
public static final Set<Material> BREAK = new HashSet<>(Arrays.asList(
|
||||
@@ -70,14 +99,13 @@ public class LegacyMats {
|
||||
Material.WATER,
|
||||
Material.LAVA,
|
||||
Material.TALL_GRASS,
|
||||
Material.SNOW,
|
||||
Material.DIRT_PATH,
|
||||
Material.CAVE_AIR,
|
||||
Material.VINE,
|
||||
Material.FERN,
|
||||
Material.LARGE_FERN,
|
||||
Material.SUGAR_CANE,
|
||||
Material.TWISTING_VINES,
|
||||
Material.TWISTING_VINES_PLANT,
|
||||
Material.WEEPING_VINES,
|
||||
Material.SEAGRASS,
|
||||
Material.TALL_SEAGRASS,
|
||||
@@ -135,34 +163,356 @@ public class LegacyMats {
|
||||
Material.WATER
|
||||
));
|
||||
|
||||
public static final Set<Material> FENCE = new HashSet<>(Arrays.asList(
|
||||
Material.OAK_FENCE,
|
||||
Material.ACACIA_FENCE,
|
||||
Material.BIRCH_FENCE,
|
||||
Material.CRIMSON_FENCE,
|
||||
Material.DARK_OAK_FENCE,
|
||||
Material.JUNGLE_FENCE,
|
||||
Material.NETHER_BRICK_FENCE,
|
||||
Material.SPRUCE_FENCE,
|
||||
Material.WARPED_FENCE,
|
||||
Material.COBBLESTONE_WALL,
|
||||
Material.ANDESITE_WALL,
|
||||
Material.BLACKSTONE_WALL,
|
||||
Material.BRICK_WALL,
|
||||
Material.GRANITE_WALL,
|
||||
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> FENCE = new HashSet<>(concatTypes(new ArrayList<>(),
|
||||
Arrays.asList(Material.GLASS_PANE, Material.IRON_BARS), Arrays.asList(Fence.class, Wall.class)));
|
||||
|
||||
public static final Set<Material> LEAVES = new HashSet<>(Arrays.asList(
|
||||
Material.BIRCH_LEAVES,
|
||||
Material.DARK_OAK_LEAVES,
|
||||
Material.JUNGLE_LEAVES,
|
||||
Material.OAK_LEAVES,
|
||||
Material.SPRUCE_LEAVES
|
||||
));
|
||||
public static final Set<Material> GATES = new HashSet<>(concatTypes(Gate.class));
|
||||
|
||||
public static final Set<Material> OBSTACLES = new HashSet<>(concatTypes(Lists.newArrayList(
|
||||
Material.IRON_BARS,
|
||||
Material.CHAIN,
|
||||
Material.END_ROD,
|
||||
Material.LIGHTNING_ROD,
|
||||
Material.COBWEB,
|
||||
Material.SWEET_BERRY_BUSH,
|
||||
Material.FLOWER_POT,
|
||||
Material.GLASS_PANE
|
||||
), Arrays.asList(), Arrays.asList(GlassPane.class), m -> m.name().startsWith("POTTED_")));
|
||||
|
||||
//Notice: We exclude blocks that cannot exist without a solid block below (such as rails or crops)
|
||||
public static final Set<Material> NONSOLID = new HashSet<>(concatTypes(Lists.newArrayList(
|
||||
Material.COBWEB,
|
||||
Material.END_GATEWAY,
|
||||
Material.END_PORTAL,
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
package net.nuggetmc.tplus.api.event;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import net.nuggetmc.tplus.api.Terminator;
|
||||
|
||||
public class BotFallDamageEvent {
|
||||
|
||||
private final Terminator bot;
|
||||
private final List<Block> standingOn;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
public BotFallDamageEvent(Terminator bot) {
|
||||
public BotFallDamageEvent(Terminator bot, List<Block> standingOn) {
|
||||
this.bot = bot;
|
||||
this.standingOn = standingOn;
|
||||
}
|
||||
|
||||
public Terminator getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
public List<Block> getStandingOn() {
|
||||
return standingOn;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ package net.nuggetmc.tplus.api.utils;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
@@ -17,6 +16,12 @@ public class BotUtils {
|
||||
Material.WATER,
|
||||
Material.LAVA,
|
||||
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
|
||||
));
|
||||
|
||||
@@ -30,23 +35,11 @@ public class BotUtils {
|
||||
return randomSteveUUID();
|
||||
}
|
||||
|
||||
public static boolean solidAt(Location loc) { // not perfect, still cuts corners of fences
|
||||
Block block = loc.getBlock();
|
||||
BoundingBox box = block.getBoundingBox();
|
||||
Vector position = loc.toVector();
|
||||
public static boolean overlaps(BoundingBox playerBox, BoundingBox blockBox) {
|
||||
return playerBox.overlaps(blockBox);
|
||||
}
|
||||
|
||||
double x = position.getX();
|
||||
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;
|
||||
public static double getHorizSqDist(Location blockLoc, Location pLoc) {
|
||||
return NumberConversions.square(blockLoc.getX() + 0.5 - pLoc.getX()) + NumberConversions.square(blockLoc.getZ() + 0.5 - pLoc.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package net.nuggetmc.tplus.bot;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
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.PacketSendListener;
|
||||
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.api.Terminator;
|
||||
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.event.BotDamageByPlayerEvent;
|
||||
import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
|
||||
@@ -35,6 +34,7 @@ import net.nuggetmc.tplus.api.utils.*;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
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.CraftServer;
|
||||
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.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -69,13 +71,14 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
private boolean removeOnDeath;
|
||||
private int aliveTicks;
|
||||
private int kills;
|
||||
private byte fireTicks; // Fire animation isn't played? Bot still takes damage.
|
||||
private byte groundTicks;
|
||||
private byte jumpTicks;
|
||||
private byte noFallTicks;
|
||||
private boolean ignoredByMobs = true;
|
||||
private List<Block> standingOn = new ArrayList<>();
|
||||
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);
|
||||
|
||||
this.plugin = TerminatorPlus.getInstance();
|
||||
@@ -85,9 +88,12 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
this.velocity = new Vector(0, 0, 0);
|
||||
this.oldVelocity = velocity.clone();
|
||||
this.noFallTicks = 60;
|
||||
this.fireTicks = 0;
|
||||
this.removeOnDeath = true;
|
||||
this.offset = MathUtils.circleOffset(3);
|
||||
if (addToPlayerList) {
|
||||
minecraftServer.getPlayerList().getPlayers().add(this);
|
||||
inPlayerList = true;
|
||||
}
|
||||
|
||||
//this.entityData.set(new EntityDataAccessor<>(16, EntityDataSerializers.BYTE), (byte) 0xFF);
|
||||
}
|
||||
@@ -104,7 +110,9 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
|
||||
CustomGameProfile profile = new CustomGameProfile(uuid, ChatUtils.trim16(name), skin);
|
||||
|
||||
Bot bot = new Bot(nmsServer, nmsWorld, profile);
|
||||
boolean addPlayerList = TerminatorPlus.getInstance().getManager().addToPlayerList();
|
||||
|
||||
Bot bot = new Bot(nmsServer, nmsWorld, profile, addPlayerList);
|
||||
|
||||
bot.connection = new ServerGamePacketListenerImpl(nmsServer, new Connection(PacketFlow.CLIENTBOUND) {
|
||||
|
||||
@@ -119,7 +127,10 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
bot.getBukkitEntity().setNoDamageTicks(0);
|
||||
Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().connection.send(
|
||||
new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, bot)));
|
||||
nmsWorld.addFreshEntity(bot);
|
||||
if (addPlayerList)
|
||||
nmsWorld.addNewPlayer(bot);
|
||||
else
|
||||
nmsWorld.addFreshEntity(bot);
|
||||
bot.renderAll();
|
||||
|
||||
TerminatorPlus.getInstance().getManager().add(bot);
|
||||
@@ -244,6 +255,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
return aliveTicks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNoFallTicks() {
|
||||
return noFallTicks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tickDelay(int i) {
|
||||
return aliveTicks % i == 0;
|
||||
@@ -278,8 +294,6 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
|
||||
aliveTicks++;
|
||||
|
||||
if (fireTicks > 0) --fireTicks;
|
||||
if (invulnerableTime > 0) --invulnerableTime;
|
||||
if (jumpTicks > 0) --jumpTicks;
|
||||
if (noFallTicks > 0) --noFallTicks;
|
||||
|
||||
@@ -291,6 +305,8 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
|
||||
updateLocation();
|
||||
|
||||
if (!isAlive()) return;
|
||||
|
||||
float health = getHealth();
|
||||
float maxHealth = getMaxHealth();
|
||||
float regenAmount = 0.025f;
|
||||
@@ -304,14 +320,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
|
||||
setHealth(amount);
|
||||
|
||||
fireDamageCheck();
|
||||
fallDamageCheck();
|
||||
|
||||
if (position().y < -64) {
|
||||
die(DamageSource.OUT_OF_WORLD);
|
||||
}
|
||||
|
||||
oldVelocity = velocity.clone();
|
||||
|
||||
doTick();
|
||||
}
|
||||
|
||||
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
|
||||
public UUID getTargetPlayer() {
|
||||
return targetPlayer;
|
||||
@@ -386,12 +353,12 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
|
||||
@Override
|
||||
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()
|
||||
if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !BotUtils.NO_FALL.contains(getLocation().getBlock().getType())) {
|
||||
BotFallDamageEvent event = new BotFallDamageEvent(this);
|
||||
if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !isFallBlocked()) {
|
||||
BotFallDamageEvent event = new BotFallDamageEvent(this, new ArrayList<>(getStandingOn()));
|
||||
|
||||
plugin.getManager().getAgent().onFallDamage(event);
|
||||
|
||||
@@ -401,6 +368,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
|
||||
public boolean isFalling() {
|
||||
return velocity.getY() < -0.8;
|
||||
@@ -525,7 +519,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
return false;
|
||||
}
|
||||
|
||||
World world = getBukkitEntity().getWorld();
|
||||
return checkStandingOn();
|
||||
}
|
||||
|
||||
public boolean checkStandingOn() {
|
||||
World world = getBukkitEntity().getWorld();
|
||||
AABB box = getBoundingBox();
|
||||
|
||||
double[] xVals = new double[]{
|
||||
@@ -537,19 +535,55 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
box.minZ,
|
||||
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 z : zVals) {
|
||||
Location loc = new Location(world, x, position().y - 0.01, z);
|
||||
Block block = world.getBlockAt(loc);
|
||||
|
||||
if (block.getType().isSolid() && BotUtils.solidAt(loc)) {
|
||||
return true;
|
||||
if ((block.getType().isSolid() || LegacyMats.canStandOn(block.getType())) && BotUtils.overlaps(playerBox, block.getBoundingBox())) {
|
||||
if (!locations.contains(block.getLocation())) {
|
||||
standingOn.add(block);
|
||||
locations.add(block.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
//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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
@@ -582,6 +616,8 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
scheduler.runTask(plugin, () -> this.remove(RemovalReason.DISCARDED));
|
||||
}
|
||||
this.removeVisually();
|
||||
if (inPlayerList)
|
||||
this.server.getPlayerList().getPlayers().remove(this);
|
||||
}
|
||||
|
||||
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"
|
||||
plugin.getManager().remove(this);
|
||||
|
||||
scheduler.runTaskLater(plugin, this::setDead, 30);
|
||||
scheduler.runTaskLater(plugin, this::removeBot, 20);
|
||||
|
||||
this.removeTab();
|
||||
}
|
||||
@@ -729,6 +765,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
return getBukkitEntity().getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoundingBox getBotBoundingBox() {
|
||||
return getBukkitEntity().getBoundingBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBotPitch(float pitch) {
|
||||
super.setXRot(pitch);
|
||||
@@ -842,25 +883,16 @@ public class Bot extends ServerPlayer implements Terminator {
|
||||
|
||||
@Override
|
||||
public void doTick() {
|
||||
if (this.hurtTime > 0) {
|
||||
this.hurtTime -= 1;
|
||||
}
|
||||
|
||||
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() {
|
||||
return ignoredByMobs;
|
||||
@Override
|
||||
public boolean isInPlayerList() {
|
||||
return inPlayerList;
|
||||
}
|
||||
|
||||
public void setIgnoredByMobs(boolean ignoredByMobs) {
|
||||
this.ignoredByMobs = ignoredByMobs;
|
||||
@Override
|
||||
public World.Environment getDimension() {
|
||||
return getBukkitEntity().getWorld().getEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,12 +35,25 @@ public class BotManagerImpl implements BotManager, Listener {
|
||||
|
||||
public boolean joinMessages = false;
|
||||
private boolean mobTarget = false;
|
||||
private boolean addPlayerList = false;
|
||||
private Location spawnLoc;
|
||||
|
||||
public BotManagerImpl() {
|
||||
this.agent = new LegacyAgent(this, TerminatorPlus.getInstance());
|
||||
this.bots = ConcurrentHashMap.newKeySet(); //should fix concurrentmodificationexception
|
||||
this.numberFormat = NumberFormat.getInstance(Locale.US);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getSpawnLoc() {
|
||||
return spawnLoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpawnLoc(Location loc) {
|
||||
spawnLoc = loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Terminator> fetch() {
|
||||
return bots;
|
||||
@@ -56,7 +69,17 @@ public class BotManagerImpl implements BotManager, Listener {
|
||||
}
|
||||
|
||||
@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) {
|
||||
if (name.equals(bot.getBotName())) {
|
||||
return bot;
|
||||
@@ -98,7 +121,18 @@ public class BotManagerImpl implements BotManager, Listener {
|
||||
|
||||
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 + ").");
|
||||
}
|
||||
@@ -139,7 +173,6 @@ public class BotManagerImpl implements BotManager, Listener {
|
||||
} else if (i > 1) {
|
||||
bot.setVelocity(randomVelocity().multiply(f));
|
||||
}
|
||||
bot.setIgnoredByMobs(!mobTarget);
|
||||
|
||||
bots.add(bot);
|
||||
i++;
|
||||
@@ -164,7 +197,7 @@ public class BotManagerImpl implements BotManager, Listener {
|
||||
@Override
|
||||
public void reset() {
|
||||
if (!bots.isEmpty()) {
|
||||
bots.forEach(Terminator::removeVisually);
|
||||
bots.forEach(Terminator::removeBot);
|
||||
bots.clear(); // Not always necessary, but a good security measure
|
||||
}
|
||||
|
||||
@@ -205,6 +238,16 @@ public class BotManagerImpl implements BotManager, Listener {
|
||||
this.mobTarget = mobTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToPlayerList() {
|
||||
return addPlayerList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAddToPlayerList(boolean addPlayerList) {
|
||||
this.addPlayerList = addPlayerList;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
ServerGamePacketListenerImpl connection = ((CraftPlayer) event.getPlayer()).getHandle().connection;
|
||||
@@ -222,8 +265,10 @@ public class BotManagerImpl implements BotManager, Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onMobTarget(EntityTargetLivingEntityEvent event) {
|
||||
Bot bot = (Bot) getBot(event.getEntity().getUniqueId());
|
||||
if (bot != null && bot.isIgnoredByMobs()) {
|
||||
if (mobTarget || event.getTarget() == null)
|
||||
return;
|
||||
Bot bot = (Bot) getBot(event.getTarget().getUniqueId());
|
||||
if (bot != null) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class AICommand extends CommandInstance implements AIManager {
|
||||
|
||||
scheduler.runTaskAsynchronously(plugin, () -> {
|
||||
try {
|
||||
Terminator bot = manager.getFirst(name);
|
||||
Terminator bot = manager.getFirst(name, (sender instanceof Player pl) ? pl.getLocation() : null);
|
||||
|
||||
if (bot == null) {
|
||||
sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!");
|
||||
|
||||
@@ -22,10 +22,13 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BotCommand extends CommandInstance {
|
||||
|
||||
@@ -141,7 +144,6 @@ public class BotCommand extends CommandInstance {
|
||||
desc = "Gives all bots an armor set.",
|
||||
autofill = "armorAutofill"
|
||||
)
|
||||
@SuppressWarnings("deprecation")
|
||||
public void armor(CommandSender sender, @Arg("armor-tier") String armorTier) {
|
||||
String tier = armorTier.toLowerCase();
|
||||
|
||||
@@ -190,7 +192,7 @@ public class BotCommand extends CommandInstance {
|
||||
|
||||
scheduler.runTaskAsynchronously(plugin, () -> {
|
||||
try {
|
||||
Terminator bot = manager.getFirst(name);
|
||||
Terminator bot = manager.getFirst(name, (sender instanceof Player pl) ? pl.getLocation() : null);
|
||||
|
||||
if (bot == null) {
|
||||
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 world = ChatColor.YELLOW + bot.getBukkitEntity().getWorld().getName();
|
||||
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();
|
||||
String strVel = ChatColor.AQUA + formatter.format(vel.getX()) + ", " + formatter.format(vel.getY()) + ", " + formatter.format(vel.getZ());
|
||||
|
||||
@@ -232,6 +234,23 @@ public class BotCommand extends CommandInstance {
|
||||
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(
|
||||
name = "reset",
|
||||
desc = "Remove all loaded bots."
|
||||
@@ -267,17 +286,68 @@ public class BotCommand extends CommandInstance {
|
||||
|
||||
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(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 + "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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg1.equalsIgnoreCase("setgoal")) {
|
||||
EnumTargetGoal goal = EnumTargetGoal.from(arg2 == null ? "" : arg2);
|
||||
if (arg1.equalsIgnoreCase("spawnloc")) {
|
||||
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) {
|
||||
sender.sendMessage(ChatUtils.LINE);
|
||||
@@ -290,14 +360,22 @@ public class BotCommand extends CommandInstance {
|
||||
agent.setTargetType(goal);
|
||||
sender.sendMessage("The global bot goal has been set to " + ChatColor.BLUE + goal.name() + ChatColor.RESET + ".");
|
||||
} else if (arg1.equalsIgnoreCase("mobtarget")) {
|
||||
manager.setMobTarget(!manager.isMobTarget());
|
||||
sender.sendMessage("Mob targeting is now " + (manager.isMobTarget() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ". (for all future bots)");
|
||||
if (arg2 == null) {
|
||||
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")) {
|
||||
if (args.size() < 2) {
|
||||
if (args.size() < 2) {
|
||||
sender.sendMessage(ChatColor.RED + "You must specify a player name!");
|
||||
return;
|
||||
}
|
||||
String playerName = args.get(1);
|
||||
String playerName = arg2;
|
||||
Player player = Bukkit.getPlayer(playerName);
|
||||
if (player == null) {
|
||||
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());
|
||||
}
|
||||
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
|
||||
|
||||
if (args.length == 2) {
|
||||
output.add("spawnloc");
|
||||
output.add("setgoal");
|
||||
output.add("mobtarget");
|
||||
output.add("playertarget");
|
||||
output.add("addplayerlist");
|
||||
output.add("region");
|
||||
} else if (args.length == 3) {
|
||||
if (args[1].equalsIgnoreCase("setgoal")) {
|
||||
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("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;
|
||||
@@ -346,4 +519,20 @@ public class BotCommand extends CommandInstance {
|
||||
public void debug(CommandSender sender, @Arg("expression") String 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,10 +365,6 @@ public class Debugger {
|
||||
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() {
|
||||
if (!(sender instanceof Player)) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user