Merge remote-tracking branch 'origin/master'
# Conflicts: # .github/workflows/dev-analysis.yml
This commit is contained in:
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Community Support
|
- name: Community Support
|
||||||
url: https://discord.gg/horsenuggets
|
url: https://discord.gg/vZVSf2D6mz
|
||||||
about: Please ask and answer questions here.
|
about: Please ask and answer questions here.
|
||||||
- name: Project Channel
|
- name: Project Channel
|
||||||
url: https://youtube.com/HorseNuggets
|
url: https://youtube.com/HorseNuggets
|
||||||
|
|||||||
@@ -1,19 +1,12 @@
|
|||||||
name: "CodeQL"
|
name: "Compile"
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
gradle:
|
gradle:
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-latest ]
|
os: [ ubuntu-latest ]
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'java' ]
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -37,12 +30,3 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: TerminatorPlus
|
name: TerminatorPlus
|
||||||
path: build/libs/
|
path: build/libs/
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v1
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v1
|
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
### Download
|
### Download
|
||||||
|
|
||||||
Releases are currently available on our Discord server, which can be found [here](https://discord.gg/horsenuggets).
|
Releases are currently available on our Discord server, which can be found [here](https://discord.gg/vZVSf2D6mz).
|
||||||
|
|
||||||
### Machine Learning
|
### Machine Learning
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "net.nuggetmc"
|
group = "net.nuggetmc"
|
||||||
version = "3.2-BETA"
|
version = "3.3.1-BETA"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -17,6 +17,6 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("io.papermc.paper:paper-api:1.19-R0.1-SNAPSHOT")
|
compileOnly("io.papermc.paper:paper-api:1.19.2-R0.1-SNAPSHOT")
|
||||||
compileOnly("com.mojang:authlib:3.2.38")
|
compileOnly("com.mojang:authlib:3.2.38")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,17 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface BotManager {
|
public interface BotManager {
|
||||||
|
Location getSpawnLoc();
|
||||||
|
|
||||||
|
void setSpawnLoc(Location loc);
|
||||||
|
|
||||||
Set<Terminator> fetch();
|
Set<Terminator> fetch();
|
||||||
|
|
||||||
Agent getAgent();
|
Agent getAgent();
|
||||||
|
|
||||||
void add(Terminator bot);
|
void add(Terminator bot);
|
||||||
|
|
||||||
Terminator getFirst(String name);
|
Terminator getFirst(String name, Location target);
|
||||||
|
|
||||||
List<String> fetchNames();
|
List<String> fetchNames();
|
||||||
|
|
||||||
@@ -50,4 +54,7 @@ public interface BotManager {
|
|||||||
|
|
||||||
void setMobTarget(boolean mobTarget);
|
void setMobTarget(boolean mobTarget);
|
||||||
|
|
||||||
|
boolean addToPlayerList();
|
||||||
|
|
||||||
|
void setAddToPlayerList(boolean addPlayerList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,17 @@ import com.mojang.authlib.GameProfile;
|
|||||||
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
|
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface Terminator {
|
public interface Terminator {
|
||||||
@@ -30,6 +34,8 @@ public interface Terminator {
|
|||||||
boolean hasNeuralNetwork();
|
boolean hasNeuralNetwork();
|
||||||
|
|
||||||
Location getLocation();
|
Location getLocation();
|
||||||
|
|
||||||
|
BoundingBox getBotBoundingBox();
|
||||||
|
|
||||||
boolean isBotAlive(); //Has to be named like this because paper re-obfuscates it
|
boolean isBotAlive(); //Has to be named like this because paper re-obfuscates it
|
||||||
|
|
||||||
@@ -37,8 +43,6 @@ public interface Terminator {
|
|||||||
|
|
||||||
float getBotMaxHealth();
|
float getBotMaxHealth();
|
||||||
|
|
||||||
void ignite();
|
|
||||||
|
|
||||||
boolean isBotOnFire();
|
boolean isBotOnFire();
|
||||||
|
|
||||||
boolean isFalling();
|
boolean isFalling();
|
||||||
@@ -50,6 +54,8 @@ public interface Terminator {
|
|||||||
boolean isBotInWater();
|
boolean isBotInWater();
|
||||||
|
|
||||||
boolean isBotOnGround();
|
boolean isBotOnGround();
|
||||||
|
|
||||||
|
List<Block> getStandingOn();
|
||||||
|
|
||||||
void setBotPitch(float pitch);
|
void setBotPitch(float pitch);
|
||||||
|
|
||||||
@@ -106,14 +112,18 @@ public interface Terminator {
|
|||||||
void addVelocity(Vector velocity);
|
void addVelocity(Vector velocity);
|
||||||
|
|
||||||
int getAliveTicks();
|
int getAliveTicks();
|
||||||
|
|
||||||
|
int getNoFallTicks();
|
||||||
|
|
||||||
boolean tickDelay(int ticks);
|
boolean tickDelay(int ticks);
|
||||||
|
|
||||||
void renderBot(Object packetListener, boolean login);
|
void renderBot(Object packetListener, boolean login);
|
||||||
|
|
||||||
void setOnFirePackets(boolean onFire);
|
|
||||||
|
|
||||||
UUID getTargetPlayer();
|
UUID getTargetPlayer();
|
||||||
|
|
||||||
void setTargetPlayer(UUID target);
|
void setTargetPlayer(UUID target);
|
||||||
|
|
||||||
|
boolean isInPlayerList();
|
||||||
|
|
||||||
|
World.Environment getDimension();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ public enum EnumTargetGoal {
|
|||||||
NEAREST_VULNERABLE_PLAYER("Locate the nearest real player that is in either Survival or Adventure mode."),
|
NEAREST_VULNERABLE_PLAYER("Locate the nearest real player that is in either Survival or Adventure mode."),
|
||||||
NEAREST_PLAYER("Locate the nearest real online player, despite the gamemode."),
|
NEAREST_PLAYER("Locate the nearest real online player, despite the gamemode."),
|
||||||
NEAREST_HOSTILE("Locate the nearest hostile entity."),
|
NEAREST_HOSTILE("Locate the nearest hostile entity."),
|
||||||
|
NEAREST_RAIDER("Locate the nearest raider."),
|
||||||
NEAREST_MOB("Locate the nearest mob."),
|
NEAREST_MOB("Locate the nearest mob."),
|
||||||
NEAREST_BOT("Locate the nearest bot."),
|
NEAREST_BOT("Locate the nearest bot."),
|
||||||
NEAREST_BOT_DIFFER("Locate the nearest bot with a different username."),
|
NEAREST_BOT_DIFFER("Locate the nearest bot with a different username."),
|
||||||
@@ -20,10 +21,12 @@ public enum EnumTargetGoal {
|
|||||||
this.put("nearestvulnerableplayer", NEAREST_VULNERABLE_PLAYER);
|
this.put("nearestvulnerableplayer", NEAREST_VULNERABLE_PLAYER);
|
||||||
this.put("nearestplayer", NEAREST_PLAYER);
|
this.put("nearestplayer", NEAREST_PLAYER);
|
||||||
this.put("nearesthostile", NEAREST_HOSTILE);
|
this.put("nearesthostile", NEAREST_HOSTILE);
|
||||||
|
this.put("nearestraider", NEAREST_RAIDER);
|
||||||
this.put("nearestmob", NEAREST_MOB);
|
this.put("nearestmob", NEAREST_MOB);
|
||||||
this.put("nearestbot", NEAREST_BOT);
|
this.put("nearestbot", NEAREST_BOT);
|
||||||
this.put("nearestbotdiffer", NEAREST_BOT_DIFFER);
|
this.put("nearestbotdiffer", NEAREST_BOT_DIFFER);
|
||||||
this.put("nearestbotdifferalpha", NEAREST_BOT_DIFFER_ALPHA);
|
this.put("nearestbotdifferalpha", NEAREST_BOT_DIFFER_ALPHA);
|
||||||
|
this.put("player", PLAYER);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,18 +11,25 @@ import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent;
|
|||||||
import net.nuggetmc.tplus.api.event.BotDeathEvent;
|
import net.nuggetmc.tplus.api.event.BotDeathEvent;
|
||||||
import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
|
import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
|
||||||
import net.nuggetmc.tplus.api.event.TerminatorLocateTargetEvent;
|
import net.nuggetmc.tplus.api.event.TerminatorLocateTargetEvent;
|
||||||
|
import net.nuggetmc.tplus.api.utils.BotUtils;
|
||||||
import net.nuggetmc.tplus.api.utils.MathUtils;
|
import net.nuggetmc.tplus.api.utils.MathUtils;
|
||||||
import net.nuggetmc.tplus.api.utils.PlayerUtils;
|
import net.nuggetmc.tplus.api.utils.PlayerUtils;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.Waterlogged;
|
||||||
|
import org.bukkit.block.data.type.*;
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
// Yes, this code is very unoptimized, I know.
|
// Yes, this code is very unoptimized, I know.
|
||||||
@@ -43,24 +50,12 @@ public class LegacyAgent extends Agent {
|
|||||||
private final Map<BukkitRunnable, Byte> mining = new HashMap<>();
|
private final Map<BukkitRunnable, Byte> mining = new HashMap<>();
|
||||||
private final Set<Terminator> fallDamageCooldown = new HashSet<>();
|
private final Set<Terminator> fallDamageCooldown = new HashSet<>();
|
||||||
public boolean offsets = true;
|
public boolean offsets = true;
|
||||||
private List<Material> instantBreakBlocks = Arrays.asList(
|
private List<LivingEntity> botsInPlayerList;
|
||||||
Material.TALL_GRASS,
|
|
||||||
Material.GRASS,
|
|
||||||
Material.KELP_PLANT,
|
|
||||||
Material.WHEAT,
|
|
||||||
Material.POTATOES,
|
|
||||||
Material.CARROT,
|
|
||||||
Material.BEETROOT,
|
|
||||||
Material.SUGAR_CANE,
|
|
||||||
Material.SWEET_BERRY_BUSH,
|
|
||||||
Material.LILY_PAD,
|
|
||||||
Material.DANDELION,
|
|
||||||
Material.POPPY,
|
|
||||||
Material.ROSE_BUSH,
|
|
||||||
Material.PUMPKIN_STEM,
|
|
||||||
Material.MELON_STEM
|
|
||||||
);
|
|
||||||
private EnumTargetGoal goal;
|
private EnumTargetGoal goal;
|
||||||
|
private BoundingBox region;
|
||||||
|
private double regionWeightX;
|
||||||
|
private double regionWeightY;
|
||||||
|
private double regionWeightZ;
|
||||||
|
|
||||||
public LegacyAgent(BotManager manager, Plugin plugin) {
|
public LegacyAgent(BotManager manager, Plugin plugin) {
|
||||||
super(manager, plugin);
|
super(manager, plugin);
|
||||||
@@ -75,7 +70,8 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tick() {
|
protected void tick() {
|
||||||
manager.fetch().forEach(this::tickBot);
|
botsInPlayerList = manager.fetch().stream().filter(t -> t.isInPlayerList()).map(b -> b.getBukkitEntity()).toList();
|
||||||
|
manager.fetch().forEach(this::tickBot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void center(Terminator bot) {
|
private void center(Terminator bot) {
|
||||||
@@ -115,6 +111,8 @@ public class LegacyAgent extends Agent {
|
|||||||
Location loc = bot.getLocation();
|
Location loc = bot.getLocation();
|
||||||
LivingEntity livingTarget = locateTarget(bot, loc);
|
LivingEntity livingTarget = locateTarget(bot, loc);
|
||||||
|
|
||||||
|
blockCheck.tryPreMLG(bot, loc);
|
||||||
|
|
||||||
if (livingTarget == null) {
|
if (livingTarget == null) {
|
||||||
stopMining(bot);
|
stopMining(bot);
|
||||||
return;
|
return;
|
||||||
@@ -180,11 +178,13 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
if (checkAt(bot, block, botPlayer)) return;
|
if (checkAt(bot, block, botPlayer)) return;
|
||||||
|
|
||||||
if (checkFence(bot, loc.getBlock(), botPlayer)) return;
|
if (checkFenceAndGates(bot, loc.getBlock(), botPlayer)) return;
|
||||||
|
|
||||||
|
if (checkObstacles(bot, loc.getBlock(), botPlayer)) return;
|
||||||
|
|
||||||
if (checkDown(bot, botPlayer, livingTarget.getLocation(), bothXZ)) return;
|
if (checkDown(bot, botPlayer, livingTarget.getLocation(), bothXZ)) return;
|
||||||
|
|
||||||
if ((withinTargetXZ || sameXZ) && checkUp(bot, livingTarget, botPlayer, target, withinTargetXZ)) return;
|
if ((withinTargetXZ || sameXZ) && checkUp(bot, livingTarget, botPlayer, target, withinTargetXZ, sameXZ)) return;
|
||||||
|
|
||||||
if (bothXZ) sideResult = checkSide(bot, livingTarget, botPlayer);
|
if (bothXZ) sideResult = checkSide(bot, livingTarget, botPlayer);
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
Material itemType;
|
Material itemType;
|
||||||
|
|
||||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
if (bot.getDimension() == World.Environment.NETHER) {
|
||||||
itemType = Material.TWISTING_VINES;
|
itemType = Material.TWISTING_VINES;
|
||||||
} else {
|
} else {
|
||||||
itemType = Material.WATER_BUCKET;
|
itemType = Material.WATER_BUCKET;
|
||||||
@@ -344,26 +344,50 @@ public class LegacyAgent extends Agent {
|
|||||||
Material itemType;
|
Material itemType;
|
||||||
Material placeType;
|
Material placeType;
|
||||||
Sound sound;
|
Sound sound;
|
||||||
|
Location groundLoc = null;
|
||||||
|
boolean nether = bot.getDimension() == World.Environment.NETHER;
|
||||||
|
double yPos = bot.getBukkitEntity().getLocation().getY();
|
||||||
|
|
||||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
if (nether) {
|
||||||
itemType = Material.TWISTING_VINES;
|
itemType = Material.TWISTING_VINES;
|
||||||
sound = Sound.BLOCK_WEEPING_VINES_PLACE;
|
sound = Sound.BLOCK_WEEPING_VINES_PLACE;
|
||||||
placeType = itemType;
|
placeType = itemType;
|
||||||
|
|
||||||
|
for (Block block : event.getStandingOn()) {
|
||||||
|
if (LegacyMats.canPlaceTwistingVines(block)) {
|
||||||
|
groundLoc = block.getLocation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
itemType = Material.WATER_BUCKET;
|
itemType = Material.WATER_BUCKET;
|
||||||
sound = Sound.ITEM_BUCKET_EMPTY;
|
sound = Sound.ITEM_BUCKET_EMPTY;
|
||||||
placeType = Material.WATER;
|
placeType = Material.WATER;
|
||||||
|
|
||||||
|
for (Block block : event.getStandingOn()) {
|
||||||
|
if (LegacyMats.canPlaceWater(block, Optional.of(yPos))) {
|
||||||
|
groundLoc = block.getLocation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Location loc = bot.getLocation();
|
if (groundLoc == null) return;
|
||||||
|
|
||||||
if (!loc.clone().add(0, -1, 0).getBlock().getType().isSolid()) return;
|
Location loc = !LegacyMats.shouldReplace(groundLoc.getBlock(), yPos, nether) ? groundLoc.add(0, 1, 0) : groundLoc;
|
||||||
|
boolean waterloggable = !nether && loc.getBlock().getBlockData() instanceof Waterlogged;
|
||||||
|
boolean waterlogged = waterloggable && ((Waterlogged)loc.getBlock().getBlockData()).isWaterlogged();
|
||||||
|
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
||||||
if (loc.getBlock().getType() != placeType) {
|
if (loc.getBlock().getType() != placeType && !waterlogged) {
|
||||||
bot.punch();
|
bot.punch();
|
||||||
loc.getBlock().setType(placeType);
|
if (waterloggable) {
|
||||||
|
Waterlogged data = (Waterlogged)loc.getBlock().getBlockData();
|
||||||
|
data.setWaterlogged(true);
|
||||||
|
loc.getBlock().setBlockData(data);
|
||||||
|
} else
|
||||||
|
loc.getBlock().setType(placeType);
|
||||||
world.playSound(loc, sound, 1, 1);
|
world.playSound(loc, sound, 1, 1);
|
||||||
|
|
||||||
if (itemType == Material.WATER_BUCKET) {
|
if (itemType == Material.WATER_BUCKET) {
|
||||||
@@ -372,11 +396,18 @@ public class LegacyAgent extends Agent {
|
|||||||
scheduler.runTaskLater(plugin, () -> {
|
scheduler.runTaskLater(plugin, () -> {
|
||||||
Block block = loc.getBlock();
|
Block block = loc.getBlock();
|
||||||
|
|
||||||
if (block.getType() == Material.WATER) {
|
boolean waterloggedNow = !nether && block.getBlockData() instanceof Waterlogged
|
||||||
|
&& ((Waterlogged)block.getBlockData()).isWaterlogged();
|
||||||
|
if (block.getType() == Material.WATER || waterloggedNow) {
|
||||||
bot.look(BlockFace.DOWN);
|
bot.look(BlockFace.DOWN);
|
||||||
bot.setItem(new ItemStack(Material.WATER_BUCKET));
|
bot.setItem(new ItemStack(Material.WATER_BUCKET));
|
||||||
world.playSound(loc, Sound.ITEM_BUCKET_FILL, 1, 1);
|
world.playSound(loc, Sound.ITEM_BUCKET_FILL, 1, 1);
|
||||||
block.setType(Material.AIR);
|
if (waterloggedNow) {
|
||||||
|
Waterlogged data = (Waterlogged)loc.getBlock().getBlockData();
|
||||||
|
data.setWaterlogged(false);
|
||||||
|
loc.getBlock().setBlockData(data);
|
||||||
|
} else
|
||||||
|
block.setType(Material.AIR);
|
||||||
}
|
}
|
||||||
}, 5);
|
}, 5);
|
||||||
}
|
}
|
||||||
@@ -442,7 +473,7 @@ public class LegacyAgent extends Agent {
|
|||||||
if (level == null) {
|
if (level == null) {
|
||||||
resetHand(npc, target, playerNPC);
|
resetHand(npc, target, playerNPC);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (level.isSide()) {
|
} else if (level.isSide() || level == LegacyLevel.BELOW || level == LegacyLevel.ABOVE) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 2;
|
return 2;
|
||||||
@@ -457,6 +488,71 @@ public class LegacyAgent extends Agent {
|
|||||||
BlockFace dir = player.getFacing();
|
BlockFace dir = player.getFacing();
|
||||||
LegacyLevel level = null;
|
LegacyLevel level = null;
|
||||||
Block get = null;
|
Block get = null;
|
||||||
|
|
||||||
|
BoundingBox box = player.getBoundingBox();
|
||||||
|
double[] xVals = new double[]{
|
||||||
|
box.getMinX(),
|
||||||
|
box.getMaxX() - 0.01
|
||||||
|
};
|
||||||
|
|
||||||
|
double[] zVals = new double[]{
|
||||||
|
box.getMinZ(),
|
||||||
|
box.getMaxZ() - 0.01
|
||||||
|
};
|
||||||
|
List<Location> locStanding = new ArrayList<>();
|
||||||
|
for (double x : xVals) {
|
||||||
|
for (double z : zVals) {
|
||||||
|
Location loc = new Location(player.getWorld(), Math.floor(x), npc.getLocation().getBlockY(), Math.floor(z));
|
||||||
|
if (!locStanding.contains(loc))
|
||||||
|
locStanding.add(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(locStanding, (a, b) ->
|
||||||
|
Double.compare(BotUtils.getHorizSqDist(a, player.getLocation()), BotUtils.getHorizSqDist(b, player.getLocation())));
|
||||||
|
|
||||||
|
//Break potential obstructing walls
|
||||||
|
for (Location loc : locStanding) {
|
||||||
|
boolean up = false;
|
||||||
|
get = loc.getBlock();
|
||||||
|
if (!LegacyMats.FENCE.contains(get.getType())) {
|
||||||
|
up = true;
|
||||||
|
get = loc.add(0, 1, 0).getBlock();
|
||||||
|
if (!LegacyMats.FENCE.contains(get.getType())) {
|
||||||
|
get = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get != null) {
|
||||||
|
int distanceX = get.getLocation().getBlockX() - player.getLocation().getBlockX();
|
||||||
|
int distanceZ = get.getLocation().getBlockZ() - player.getLocation().getBlockZ();
|
||||||
|
if (distanceX == 1 && distanceZ == 0) {
|
||||||
|
if (dir == BlockFace.NORTH || dir == BlockFace.SOUTH) {
|
||||||
|
npc.faceLocation(get.getLocation());
|
||||||
|
level = up ? LegacyLevel.EAST : LegacyLevel.EAST_D;
|
||||||
|
}
|
||||||
|
} else if (distanceX == -1 && distanceZ == 0) {
|
||||||
|
if (dir == BlockFace.NORTH || dir == BlockFace.SOUTH) {
|
||||||
|
npc.faceLocation(get.getLocation());
|
||||||
|
level = up ? LegacyLevel.WEST : LegacyLevel.WEST_D;
|
||||||
|
}
|
||||||
|
} else if (distanceX == 0 && distanceZ == 1) {
|
||||||
|
if (dir == BlockFace.EAST || dir == BlockFace.WEST) {
|
||||||
|
npc.faceLocation(get.getLocation());
|
||||||
|
level = up ? LegacyLevel.SOUTH : LegacyLevel.SOUTH_D;
|
||||||
|
}
|
||||||
|
} else if (distanceX == 0 && distanceZ == -1) {
|
||||||
|
if (dir == BlockFace.EAST || dir == BlockFace.WEST) {
|
||||||
|
npc.faceLocation(get.getLocation());
|
||||||
|
level = up ? LegacyLevel.NORTH : LegacyLevel.NORTH_D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level != null) {
|
||||||
|
preBreak(npc, player, get, level);
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case NORTH:
|
case NORTH:
|
||||||
@@ -466,6 +562,35 @@ public class LegacyAgent extends Agent {
|
|||||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||||
level = LegacyLevel.NORTH_D;
|
level = LegacyLevel.NORTH_D;
|
||||||
|
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
|
||||||
|
get = get.getLocation().add(0, -2, 0).getBlock();
|
||||||
|
level = LegacyLevel.NORTH_D_2;
|
||||||
|
} else {
|
||||||
|
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
|
||||||
|
if(standing == null)
|
||||||
|
break;
|
||||||
|
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|
||||||
|
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
|
||||||
|
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
|
||||||
|
if(obstructed) {
|
||||||
|
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
|
||||||
|
//Break standing block
|
||||||
|
get = standing;
|
||||||
|
level = LegacyLevel.BELOW;
|
||||||
|
} else {
|
||||||
|
//Break above
|
||||||
|
Block above = npc.getLocation().add(0, 2, 0).getBlock();
|
||||||
|
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(above.getType())) {
|
||||||
|
get = above;
|
||||||
|
level = LegacyLevel.ABOVE;
|
||||||
|
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
|
||||||
|
get = aboveSide;
|
||||||
|
level = LegacyLevel.NORTH_U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOUTH:
|
case SOUTH:
|
||||||
@@ -475,6 +600,35 @@ public class LegacyAgent extends Agent {
|
|||||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||||
level = LegacyLevel.SOUTH_D;
|
level = LegacyLevel.SOUTH_D;
|
||||||
|
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
|
||||||
|
get = get.getLocation().add(0, -2, 0).getBlock();
|
||||||
|
level = LegacyLevel.SOUTH_D_2;
|
||||||
|
} else {
|
||||||
|
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
|
||||||
|
if(standing == null)
|
||||||
|
break;
|
||||||
|
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|
||||||
|
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
|
||||||
|
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
|
||||||
|
if(obstructed) {
|
||||||
|
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
|
||||||
|
//Break standing block
|
||||||
|
get = standing;
|
||||||
|
level = LegacyLevel.BELOW;
|
||||||
|
} else {
|
||||||
|
//Break above
|
||||||
|
Block above = npc.getLocation().add(0, 2, 0).getBlock();
|
||||||
|
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(above.getType())) {
|
||||||
|
get = above;
|
||||||
|
level = LegacyLevel.ABOVE;
|
||||||
|
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
|
||||||
|
get = aboveSide;
|
||||||
|
level = LegacyLevel.SOUTH_U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EAST:
|
case EAST:
|
||||||
@@ -484,6 +638,35 @@ public class LegacyAgent extends Agent {
|
|||||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||||
level = LegacyLevel.EAST_D;
|
level = LegacyLevel.EAST_D;
|
||||||
|
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
|
||||||
|
get = get.getLocation().add(0, -2, 0).getBlock();
|
||||||
|
level = LegacyLevel.EAST_D_2;
|
||||||
|
} else {
|
||||||
|
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
|
||||||
|
if(standing == null)
|
||||||
|
break;
|
||||||
|
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|
||||||
|
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
|
||||||
|
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
|
||||||
|
if(obstructed) {
|
||||||
|
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
|
||||||
|
//Break standing block
|
||||||
|
get = standing;
|
||||||
|
level = LegacyLevel.BELOW;
|
||||||
|
} else {
|
||||||
|
//Break above
|
||||||
|
Block above = npc.getLocation().add(0, 2, 0).getBlock();
|
||||||
|
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(above.getType())) {
|
||||||
|
get = above;
|
||||||
|
level = LegacyLevel.ABOVE;
|
||||||
|
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
|
||||||
|
get = aboveSide;
|
||||||
|
level = LegacyLevel.EAST_U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WEST:
|
case WEST:
|
||||||
@@ -493,27 +676,91 @@ public class LegacyAgent extends Agent {
|
|||||||
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
} else if (checkSideBreak(get.getLocation().add(0, -1, 0).getBlock().getType())) {
|
||||||
get = get.getLocation().add(0, -1, 0).getBlock();
|
get = get.getLocation().add(0, -1, 0).getBlock();
|
||||||
level = LegacyLevel.WEST_D;
|
level = LegacyLevel.WEST_D;
|
||||||
|
} else if (LegacyMats.FENCE.contains(get.getLocation().add(0, -2, 0).getBlock().getType())) {
|
||||||
|
get = get.getLocation().add(0, -2, 0).getBlock();
|
||||||
|
level = LegacyLevel.WEST_D_2;
|
||||||
|
} else {
|
||||||
|
Block standing = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
|
||||||
|
if(standing == null)
|
||||||
|
break;
|
||||||
|
boolean obstructed = standing.getLocation().getBlockY() == player.getLocation().getBlockY()
|
||||||
|
|| (standing.getLocation().getBlockY() + 1 == player.getLocation().getBlockY()
|
||||||
|
&& (LegacyMats.FENCE.contains(standing.getType()) || LegacyMats.GATES.contains(standing.getType())));
|
||||||
|
if(obstructed) {
|
||||||
|
Block belowStanding = standing.getLocation().add(0, -1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(belowStanding.getType()) && !LegacyMats.NONSOLID.contains(belowStanding.getType())) {
|
||||||
|
//Break standing block
|
||||||
|
get = standing;
|
||||||
|
level = LegacyLevel.BELOW;
|
||||||
|
} else {
|
||||||
|
//Break above
|
||||||
|
Block above = npc.getLocation().add(0, 2, 0).getBlock();
|
||||||
|
Block aboveSide = get.getLocation().add(0, 1, 0).getBlock();
|
||||||
|
if(!LegacyMats.BREAK.contains(above.getType())) {
|
||||||
|
get = above;
|
||||||
|
level = LegacyLevel.ABOVE;
|
||||||
|
} else if(!LegacyMats.BREAK.contains(aboveSide.getType())) {
|
||||||
|
get = aboveSide;
|
||||||
|
level = LegacyLevel.WEST_U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level == LegacyLevel.EAST_D || level == LegacyLevel.WEST_D || level == LegacyLevel.NORTH_D || level == LegacyLevel.SOUTH_D) {
|
if (level == LegacyLevel.EAST_D || level == LegacyLevel.WEST_D || level == LegacyLevel.NORTH_D || level == LegacyLevel.SOUTH_D
|
||||||
|
|| level == LegacyLevel.EAST_D_2 || level == LegacyLevel.WEST_D_2 || level == LegacyLevel.NORTH_D_2 || level == LegacyLevel.SOUTH_D_2) {
|
||||||
if (LegacyMats.AIR.contains(player.getLocation().add(0, 2, 0).getBlock().getType())
|
if (LegacyMats.AIR.contains(player.getLocation().add(0, 2, 0).getBlock().getType())
|
||||||
&& LegacyMats.AIR.contains(get.getLocation().add(0, 2, 0).getBlock().getType())) {
|
&& LegacyMats.AIR.contains(get.getLocation().add(0, 2, 0).getBlock().getType())
|
||||||
|
&& !LegacyMats.FENCE.contains(get.getType()) && !LegacyMats.GATES.contains(get.getType())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (level == LegacyLevel.ABOVE || level == LegacyLevel.BELOW) {
|
||||||
|
Block check;
|
||||||
|
|
||||||
|
switch (dir) {
|
||||||
|
case NORTH:
|
||||||
|
check = player.getLocation().add(0, 2, -1).getBlock();
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
check = player.getLocation().add(0, 2, 1).getBlock();
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
check = player.getLocation().add(1, 2, 0).getBlock();
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
check = player.getLocation().add(-1, 2, 0).getBlock();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
check = null;
|
||||||
|
}
|
||||||
|
if (LegacyMats.AIR.contains(player.getLocation().add(0, 2, 0).getBlock().getType())
|
||||||
|
&& LegacyMats.AIR.contains(check.getType()))
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
|
if (level == LegacyLevel.BELOW) {
|
||||||
|
noJump.add(player);
|
||||||
|
scheduler.runTaskLater(plugin, () -> {
|
||||||
|
noJump.remove(player);
|
||||||
|
}, 15);
|
||||||
|
|
||||||
|
npc.look(BlockFace.DOWN);
|
||||||
|
downMine(npc, player, get);
|
||||||
|
} else if (level == LegacyLevel.ABOVE)
|
||||||
|
npc.look(BlockFace.UP);
|
||||||
preBreak(npc, player, get, level);
|
preBreak(npc, player, get, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkUp(Terminator npc, LivingEntity target, LivingEntity playerNPC, Location loc, boolean c) {
|
private boolean checkUp(Terminator npc, LivingEntity target, LivingEntity playerNPC, Location loc, boolean c, boolean sameXZ) {
|
||||||
Location a = playerNPC.getLocation();
|
Location a = playerNPC.getLocation();
|
||||||
Location b = target.getLocation();
|
Location b = target.getLocation();
|
||||||
|
|
||||||
@@ -568,24 +815,25 @@ public class LegacyAgent extends Agent {
|
|||||||
npc.look(BlockFace.DOWN);
|
npc.look(BlockFace.DOWN);
|
||||||
|
|
||||||
// maybe put this in lower if statement onGround()
|
// maybe put this in lower if statement onGround()
|
||||||
scheduler.runTaskLater(plugin, () -> {
|
if (m0 != Material.WATER)
|
||||||
npc.sneak();
|
scheduler.runTaskLater(plugin, () -> {
|
||||||
npc.setItem(new ItemStack(Material.COBBLESTONE));
|
npc.sneak();
|
||||||
npc.punch();
|
npc.setItem(new ItemStack(Material.COBBLESTONE));
|
||||||
npc.look(BlockFace.DOWN);
|
npc.punch();
|
||||||
|
npc.look(BlockFace.DOWN);
|
||||||
scheduler.runTaskLater(plugin, () -> {
|
|
||||||
npc.look(BlockFace.DOWN);
|
scheduler.runTaskLater(plugin, () -> {
|
||||||
}, 1);
|
npc.look(BlockFace.DOWN);
|
||||||
|
}, 1);
|
||||||
blockCheck.placeBlock(npc, playerNPC, place);
|
|
||||||
|
blockCheck.placeBlock(npc, playerNPC, place);
|
||||||
if (!towerList.containsKey(playerNPC)) {
|
|
||||||
if (c) {
|
if (!towerList.containsKey(playerNPC)) {
|
||||||
towerList.put(playerNPC, playerNPC.getLocation());
|
if (c) {
|
||||||
}
|
towerList.put(playerNPC, playerNPC.getLocation());
|
||||||
}
|
}
|
||||||
}, 5);
|
}
|
||||||
|
}, 3);
|
||||||
|
|
||||||
if (npc.isBotOnGround()) {
|
if (npc.isBotOnGround()) {
|
||||||
if (target.getLocation().distance(playerNPC.getLocation()) < 16) {
|
if (target.getLocation().distance(playerNPC.getLocation()) < 16) {
|
||||||
@@ -645,6 +893,16 @@ public class LegacyAgent extends Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (sameXZ && LegacyMats.BREAK.contains(m1)) {
|
||||||
|
Block block = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
|
||||||
|
if (block != null && block.getLocation().getBlockY() == playerNPC.getLocation().getBlockY()
|
||||||
|
&& !LegacyMats.BREAK.contains(block.getType())) {
|
||||||
|
npc.look(BlockFace.DOWN);
|
||||||
|
|
||||||
|
downMine(npc, playerNPC, block);
|
||||||
|
preBreak(npc, playerNPC, block, LegacyLevel.BELOW);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,7 +915,9 @@ public class LegacyAgent extends Agent {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (c && npc.getLocation().getBlockY() > loc.getBlockY() + 1) {
|
if (c && npc.getLocation().getBlockY() > loc.getBlockY() + 1) {
|
||||||
Block block = npc.getLocation().add(0, -1, 0).getBlock();
|
Block block = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
|
||||||
|
if (block == null)
|
||||||
|
return false;
|
||||||
npc.look(BlockFace.DOWN);
|
npc.look(BlockFace.DOWN);
|
||||||
|
|
||||||
downMine(npc, player, block);
|
downMine(npc, player, block);
|
||||||
@@ -671,7 +931,9 @@ public class LegacyAgent extends Agent {
|
|||||||
b.setY(0);
|
b.setY(0);
|
||||||
|
|
||||||
if (npc.getLocation().getBlockY() > loc.getBlockY() + 10 && a.distance(b) < 10) {
|
if (npc.getLocation().getBlockY() > loc.getBlockY() + 10 && a.distance(b) < 10) {
|
||||||
Block block = npc.getLocation().add(0, -1, 0).getBlock();
|
Block block = npc.getStandingOn().isEmpty() ? null : npc.getStandingOn().get(0);
|
||||||
|
if (block == null)
|
||||||
|
return false;
|
||||||
npc.look(BlockFace.DOWN);
|
npc.look(BlockFace.DOWN);
|
||||||
|
|
||||||
downMine(npc, player, block);
|
downMine(npc, player, block);
|
||||||
@@ -719,14 +981,31 @@ public class LegacyAgent extends Agent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkFence(Terminator bot, Block block, LivingEntity player) {
|
private boolean checkFenceAndGates(Terminator bot, Block block, LivingEntity player) {
|
||||||
if (LegacyMats.FENCE.contains(block.getType())) {
|
if (LegacyMats.FENCE.contains(block.getType()) || LegacyMats.GATES.contains(block.getType())) {
|
||||||
preBreak(bot, player, block, LegacyLevel.AT_D);
|
preBreak(bot, player, block, LegacyLevel.AT_D);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean checkObstacles(Terminator bot, Block block, LivingEntity player) {
|
||||||
|
if (LegacyMats.OBSTACLES.contains(block.getType()) || isDoorObstacle(block)) {
|
||||||
|
preBreak(bot, player, block, LegacyLevel.AT_D);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDoorObstacle(Block block) {
|
||||||
|
if (block.getType().data == Door.class)
|
||||||
|
return true;
|
||||||
|
if (block.getType().data == TrapDoor.class && ((TrapDoor)block.getBlockData()).isOpen())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkAt(Terminator bot, Block block, LivingEntity player) {
|
private boolean checkAt(Terminator bot, Block block, LivingEntity player) {
|
||||||
if (LegacyMats.BREAK.contains(block.getType())) {
|
if (LegacyMats.BREAK.contains(block.getType())) {
|
||||||
@@ -751,13 +1030,15 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
bot.setItem(new ItemStack(item));
|
bot.setItem(new ItemStack(item));
|
||||||
|
|
||||||
if (level == LegacyLevel.EAST_D || level == LegacyLevel.NORTH_D || level == LegacyLevel.SOUTH_D || level == LegacyLevel.WEST_D) {
|
if (level.isSideDown() || level.isSideDown2()) {
|
||||||
bot.setBotPitch(69);
|
bot.setBotPitch(69);
|
||||||
|
|
||||||
scheduler.runTaskLater(plugin, () -> {
|
scheduler.runTaskLater(plugin, () -> {
|
||||||
btCheck.put(player, true);
|
btCheck.put(player, true);
|
||||||
}, 5);
|
}, 5);
|
||||||
} else if (level == LegacyLevel.AT_D || level == LegacyLevel.AT) {
|
} else if (level.isSideUp()) {
|
||||||
|
bot.setBotPitch(-53);
|
||||||
|
}else if (level == LegacyLevel.AT_D || level == LegacyLevel.AT) {
|
||||||
Location blockLoc = block.getLocation().add(0.5, -1, 0.5);
|
Location blockLoc = block.getLocation().add(0.5, -1, 0.5);
|
||||||
bot.faceLocation(blockLoc);
|
bot.faceLocation(blockLoc);
|
||||||
}
|
}
|
||||||
@@ -777,10 +1058,10 @@ public class LegacyAgent extends Agent {
|
|||||||
miningAnim.put(player, task);
|
miningAnim.put(player, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
blockBreakEffect(player, block, level);
|
blockBreakEffect(bot, player, block, new LegacyLevel.LevelWrapper(level));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void blockBreakEffect(LivingEntity player, Block block, LegacyLevel level) {
|
private void blockBreakEffect(Terminator bot, LivingEntity player, Block block, LegacyLevel.LevelWrapper wrapper) {
|
||||||
|
|
||||||
if (LegacyMats.NO_CRACK.contains(block.getType())) return;
|
if (LegacyMats.NO_CRACK.contains(block.getType())) return;
|
||||||
|
|
||||||
@@ -792,47 +1073,45 @@ public class LegacyAgent extends Agent {
|
|||||||
byte i = mining.get(this);
|
byte i = mining.get(this);
|
||||||
|
|
||||||
Block cur;
|
Block cur;
|
||||||
switch (level) {
|
if (wrapper.getLevel() == null)
|
||||||
case ABOVE:
|
cur = player.getLocation().add(0, 1, 0).getBlock();
|
||||||
cur = player.getLocation().add(0, 2, 0).getBlock();
|
else if (wrapper.getLevel() == LegacyLevel.BELOW)
|
||||||
break;
|
cur = bot.getStandingOn().isEmpty() ? null : bot.getStandingOn().get(0);
|
||||||
case BELOW:
|
else
|
||||||
cur = player.getLocation().add(0, -1, 0).getBlock();
|
cur = wrapper.getLevel().offset(player.getLocation()).getBlock();
|
||||||
break;
|
|
||||||
case NORTH:
|
|
||||||
cur = player.getLocation().add(0, 1, -1).getBlock();
|
|
||||||
break;
|
|
||||||
case SOUTH:
|
|
||||||
cur = player.getLocation().add(0, 1, 1).getBlock();
|
|
||||||
break;
|
|
||||||
case EAST:
|
|
||||||
cur = player.getLocation().add(1, 1, 0).getBlock();
|
|
||||||
break;
|
|
||||||
case WEST:
|
|
||||||
cur = player.getLocation().add(-1, 1, 0).getBlock();
|
|
||||||
break;
|
|
||||||
case NORTH_D:
|
|
||||||
cur = player.getLocation().add(0, 0, -1).getBlock();
|
|
||||||
break;
|
|
||||||
case SOUTH_D:
|
|
||||||
cur = player.getLocation().add(0, 0, 1).getBlock();
|
|
||||||
break;
|
|
||||||
case EAST_D:
|
|
||||||
cur = player.getLocation().add(1, 0, 0).getBlock();
|
|
||||||
break;
|
|
||||||
case WEST_D:
|
|
||||||
cur = player.getLocation().add(-1, 0, 0).getBlock();
|
|
||||||
break;
|
|
||||||
case AT_D:
|
|
||||||
cur = player.getLocation().getBlock();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cur = player.getLocation().add(0, 1, 0).getBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Fix boat clutching while breaking block
|
||||||
|
// As a side effect, the bot is able to break multiple blocks at once while over lava
|
||||||
|
if ((wrapper.getLevel().isSideAt() || wrapper.getLevel().isSideUp())
|
||||||
|
&& bot.getLocation().add(0, -2, 0).getBlock().getType() == Material.LAVA
|
||||||
|
&& block.getLocation().clone().add(0, 1, 0).equals(cur.getLocation())) {
|
||||||
|
cur = block;
|
||||||
|
wrapper.setLevel(wrapper.getLevel().sideDown());
|
||||||
|
|
||||||
|
if (wrapper.getLevel().isSideDown() || wrapper.getLevel().isSideDown2())
|
||||||
|
bot.setBotPitch(69);
|
||||||
|
else if (wrapper.getLevel().isSideUp())
|
||||||
|
bot.setBotPitch(-53);
|
||||||
|
else if (wrapper.getLevel().isSide())
|
||||||
|
bot.setBotPitch(0);
|
||||||
|
}
|
||||||
|
if ((wrapper.getLevel().isSideAt() || wrapper.getLevel().isSideDown())
|
||||||
|
&& bot.getLocation().add(0, -1, 0).getBlock().getType() == Material.LAVA
|
||||||
|
&& block.getLocation().clone().add(0, -1, 0).equals(cur.getLocation())) {
|
||||||
|
cur = block;
|
||||||
|
wrapper.setLevel(wrapper.getLevel().sideUp());
|
||||||
|
|
||||||
|
if (wrapper.getLevel().isSideDown() || wrapper.getLevel().isSideDown2())
|
||||||
|
bot.setBotPitch(69);
|
||||||
|
else if (wrapper.getLevel().isSideUp())
|
||||||
|
bot.setBotPitch(-53);
|
||||||
|
else if (wrapper.getLevel().isSide())
|
||||||
|
bot.setBotPitch(0);
|
||||||
|
}
|
||||||
|
|
||||||
// wow this repeated code is so bad lmao
|
// wow this repeated code is so bad lmao
|
||||||
|
|
||||||
if (player.isDead() || (!block.equals(cur) || block.getType() != cur.getType())) {
|
if (player.isDead() || cur == null || (!block.equals(cur) || block.getType() != cur.getType())) {
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
|
||||||
TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1);
|
TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1);
|
||||||
@@ -857,7 +1136,7 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
block.breakNaturally();
|
block.breakNaturally();
|
||||||
|
|
||||||
if (level == LegacyLevel.ABOVE) {
|
if (wrapper.getLevel() == LegacyLevel.ABOVE) {
|
||||||
noJump.add(player);
|
noJump.add(player);
|
||||||
|
|
||||||
scheduler.runTaskLater(plugin, () -> {
|
scheduler.runTaskLater(plugin, () -> {
|
||||||
@@ -875,10 +1154,13 @@ public class LegacyAgent extends Agent {
|
|||||||
all.playSound(block.getLocation(), sound, SoundCategory.BLOCKS, (float) 0.3, 1);
|
all.playSound(block.getLocation(), sound, SoundCategory.BLOCKS, (float) 0.3, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.getType() == Material.BARRIER || block.getType() == Material.BEDROCK || block.getType() == Material.END_PORTAL_FRAME)
|
if (block.getType() == Material.BARRIER || block.getType() == Material.BEDROCK || block.getType() == Material.END_PORTAL_FRAME
|
||||||
|
|| block.getType() == Material.STRUCTURE_BLOCK || block.getType() == Material.STRUCTURE_BLOCK
|
||||||
|
|| block.getType() == Material.COMMAND_BLOCK || block.getType() == Material.REPEATING_COMMAND_BLOCK
|
||||||
|
|| block.getType() == Material.CHAIN_COMMAND_BLOCK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (instantBreakBlocks.contains(block.getType())) { // instant break blocks
|
if (LegacyMats.INSTANT_BREAK.contains(block.getType())) { // instant break blocks
|
||||||
block.breakNaturally();
|
block.breakNaturally();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -924,7 +1206,7 @@ public class LegacyAgent extends Agent {
|
|||||||
Location loc = bot.getLocation();
|
Location loc = bot.getLocation();
|
||||||
|
|
||||||
if (bot.isBotOnFire()) {
|
if (bot.isBotOnFire()) {
|
||||||
if (bot.getBukkitEntity().getWorld().getEnvironment() != World.Environment.NETHER) {
|
if (bot.getDimension() != World.Environment.NETHER) {
|
||||||
placeWaterDown(bot, world, loc);
|
placeWaterDown(bot, world, loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -932,7 +1214,7 @@ public class LegacyAgent extends Agent {
|
|||||||
Material atType = loc.getBlock().getType();
|
Material atType = loc.getBlock().getType();
|
||||||
|
|
||||||
if (atType == Material.FIRE || atType == Material.SOUL_FIRE) {
|
if (atType == Material.FIRE || atType == Material.SOUL_FIRE) {
|
||||||
if (bot.getBukkitEntity().getWorld().getEnvironment() != World.Environment.NETHER) {
|
if (bot.getDimension() != World.Environment.NETHER) {
|
||||||
placeWaterDown(bot, world, loc);
|
placeWaterDown(bot, world, loc);
|
||||||
world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
|
world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
|
||||||
} else {
|
} else {
|
||||||
@@ -944,7 +1226,7 @@ public class LegacyAgent extends Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (atType == Material.LAVA) {
|
if (atType == Material.LAVA) {
|
||||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
if (bot.getDimension() == World.Environment.NETHER) {
|
||||||
bot.attemptBlockPlace(loc, Material.COBBLESTONE, false);
|
bot.attemptBlockPlace(loc, Material.COBBLESTONE, false);
|
||||||
} else {
|
} else {
|
||||||
placeWaterDown(bot, world, loc);
|
placeWaterDown(bot, world, loc);
|
||||||
@@ -955,7 +1237,7 @@ public class LegacyAgent extends Agent {
|
|||||||
Material headType = head.getBlock().getType();
|
Material headType = head.getBlock().getType();
|
||||||
|
|
||||||
if (headType == Material.LAVA) {
|
if (headType == Material.LAVA) {
|
||||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
if (bot.getDimension() == World.Environment.NETHER) {
|
||||||
bot.attemptBlockPlace(head, Material.COBBLESTONE, false);
|
bot.attemptBlockPlace(head, Material.COBBLESTONE, false);
|
||||||
} else {
|
} else {
|
||||||
placeWaterDown(bot, world, head);
|
placeWaterDown(bot, world, head);
|
||||||
@@ -963,7 +1245,7 @@ public class LegacyAgent extends Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (headType == Material.FIRE || headType == Material.SOUL_FIRE) {
|
if (headType == Material.FIRE || headType == Material.SOUL_FIRE) {
|
||||||
if (bot.getBukkitEntity().getWorld().getEnvironment() == World.Environment.NETHER) {
|
if (bot.getDimension() == World.Environment.NETHER) {
|
||||||
bot.look(BlockFace.DOWN);
|
bot.look(BlockFace.DOWN);
|
||||||
bot.punch();
|
bot.punch();
|
||||||
world.playSound(head, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
|
world.playSound(head, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1);
|
||||||
@@ -1111,12 +1393,39 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
bot.attack(target);
|
bot.attack(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRegion(BoundingBox region, double regionWeightX, double regionWeightY, double regionWeightZ) {
|
||||||
|
this.region = region;
|
||||||
|
this.regionWeightX = regionWeightX;
|
||||||
|
this.regionWeightY = regionWeightY;
|
||||||
|
this.regionWeightZ = regionWeightZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundingBox getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRegionWeightX() {
|
||||||
|
return regionWeightX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRegionWeightY() {
|
||||||
|
return regionWeightY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRegionWeightZ() {
|
||||||
|
return regionWeightZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumTargetGoal getTargetType() {
|
||||||
|
return goal;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTargetType(EnumTargetGoal goal) {
|
public void setTargetType(EnumTargetGoal goal) {
|
||||||
this.goal = goal;
|
this.goal = goal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LivingEntity locateTarget(Terminator bot, Location loc, EnumTargetGoal... targetGoal) {
|
private LivingEntity locateTarget(Terminator bot, Location loc, EnumTargetGoal... targetGoal) {
|
||||||
LivingEntity result = null;
|
LivingEntity result = null;
|
||||||
|
|
||||||
EnumTargetGoal g = goal;
|
EnumTargetGoal g = goal;
|
||||||
@@ -1127,7 +1436,7 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
case NEAREST_PLAYER: {
|
case NEAREST_PLAYER: {
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
if (validateCloserEntity(player, loc, result)) {
|
if (!botsInPlayerList.contains(player) && validateCloserEntity(player, loc, result)) {
|
||||||
result = player;
|
result = player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1137,7 +1446,7 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
case NEAREST_VULNERABLE_PLAYER: {
|
case NEAREST_VULNERABLE_PLAYER: {
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
if (!PlayerUtils.isInvincible(player.getGameMode()) && validateCloserEntity(player, loc, result)) {
|
if (!botsInPlayerList.contains(player) && !PlayerUtils.isInvincible(player.getGameMode()) && validateCloserEntity(player, loc, result)) {
|
||||||
result = player;
|
result = player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1154,6 +1463,16 @@ public class LegacyAgent extends Agent {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case NEAREST_RAIDER: {
|
||||||
|
for (LivingEntity entity : bot.getBukkitEntity().getWorld().getLivingEntities()) {
|
||||||
|
if ((entity instanceof Raider || (entity instanceof Vex vex && vex.getSummoner() instanceof Raider)) && validateCloserEntity(entity, loc, result)) {
|
||||||
|
result = entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NEAREST_MOB: {
|
case NEAREST_MOB: {
|
||||||
for (LivingEntity entity : bot.getBukkitEntity().getWorld().getLivingEntities()) {
|
for (LivingEntity entity : bot.getBukkitEntity().getWorld().getLivingEntities()) {
|
||||||
@@ -1211,7 +1530,7 @@ public class LegacyAgent extends Agent {
|
|||||||
case PLAYER: { //Target a single player. Defaults to NEAREST_VULNERABLE_PLAYER if no player found.
|
case PLAYER: { //Target a single player. Defaults to NEAREST_VULNERABLE_PLAYER if no player found.
|
||||||
if (bot.getTargetPlayer() != null) {
|
if (bot.getTargetPlayer() != null) {
|
||||||
Player player = Bukkit.getPlayer(bot.getTargetPlayer());
|
Player player = Bukkit.getPlayer(bot.getTargetPlayer());
|
||||||
if (player != null) {
|
if (player != null && !botsInPlayerList.contains(player) && validateCloserEntity(player, loc, null)) {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1225,6 +1544,36 @@ public class LegacyAgent extends Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateCloserEntity(LivingEntity entity, Location loc, LivingEntity result) {
|
private boolean validateCloserEntity(LivingEntity entity, Location loc, LivingEntity result) {
|
||||||
return loc.getWorld() == entity.getWorld() && !entity.isDead() && (result == null || loc.distance(entity.getLocation()) < loc.distance(result.getLocation()));
|
double regionDistEntity = getWeightedRegionDist(entity.getLocation());
|
||||||
|
if (regionDistEntity == Double.MAX_VALUE)
|
||||||
|
return false;
|
||||||
|
double regionDistResult = result == null ? 0 : getWeightedRegionDist(result.getLocation());
|
||||||
|
return loc.getWorld() == entity.getWorld() && !entity.isDead()
|
||||||
|
&& (result == null || (loc.distanceSquared(entity.getLocation()) + regionDistEntity) < (loc.distanceSquared(result.getLocation())) + regionDistResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getWeightedRegionDist(Location loc) {
|
||||||
|
if (region == null)
|
||||||
|
return 0;
|
||||||
|
double diffX = Math.max(0, Math.abs(region.getCenterX() - loc.getX()) - region.getWidthX() * 0.5);
|
||||||
|
double diffY = Math.max(0, Math.abs(region.getCenterY() - loc.getY()) - region.getHeight() * 0.5);
|
||||||
|
double diffZ = Math.max(0, Math.abs(region.getCenterZ() - loc.getZ()) - region.getWidthZ() * 0.5);
|
||||||
|
if (regionWeightX == 0 && regionWeightY == 0 && regionWeightZ == 0)
|
||||||
|
if (diffX > 0 || diffY > 0 || diffZ > 0)
|
||||||
|
return Double.MAX_VALUE;
|
||||||
|
return diffX * diffX * regionWeightX + diffY * diffY * regionWeightY + diffZ * diffZ * regionWeightZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopAllTasks() {
|
||||||
|
super.stopAllTasks();
|
||||||
|
|
||||||
|
Iterator<Entry<Block, Short>> itr = crackList.entrySet().iterator();
|
||||||
|
while(itr.hasNext()) {
|
||||||
|
Block block = itr.next().getKey();
|
||||||
|
TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1);
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
mining.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package net.nuggetmc.tplus.api.agent.legacyagent;
|
package net.nuggetmc.tplus.api.agent.legacyagent;
|
||||||
|
|
||||||
import net.nuggetmc.tplus.api.Terminator;
|
import net.nuggetmc.tplus.api.Terminator;
|
||||||
|
import net.nuggetmc.tplus.api.utils.BotUtils;
|
||||||
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
@@ -8,9 +10,15 @@ import org.bukkit.entity.LivingEntity;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class LegacyBlockCheck {
|
public class LegacyBlockCheck {
|
||||||
@@ -135,6 +143,90 @@ public class LegacyBlockCheck {
|
|||||||
all.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1);
|
all.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1);
|
||||||
placeFinal(bot, player, block.getLocation());
|
placeFinal(bot, player, block.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean tryPreMLG(Terminator bot, Location botLoc) {
|
||||||
|
if(bot.isBotOnGround() || bot.getVelocity().getY() >= -0.8D || bot.getNoFallTicks() > 7)
|
||||||
|
return false;
|
||||||
|
if (tryPreMLG(bot, botLoc, 3))
|
||||||
|
return true;
|
||||||
|
return tryPreMLG(bot, botLoc, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryPreMLG(Terminator bot, Location botLoc, int blocksBelow) {
|
||||||
|
BoundingBox box = bot.getBotBoundingBox();
|
||||||
|
double[] xVals = new double[]{
|
||||||
|
box.getMinX(),
|
||||||
|
box.getMaxX() - 0.01
|
||||||
|
};
|
||||||
|
|
||||||
|
double[] zVals = new double[]{
|
||||||
|
box.getMinZ(),
|
||||||
|
box.getMaxZ() - 0.01
|
||||||
|
};
|
||||||
|
Set<Location> below2Set = new HashSet<>();
|
||||||
|
|
||||||
|
for (double x : xVals) {
|
||||||
|
for (double z : zVals) {
|
||||||
|
Location below = botLoc.clone();
|
||||||
|
below.setX(x);
|
||||||
|
below.setZ(z);
|
||||||
|
below.setY(bot.getLocation().getBlockY());
|
||||||
|
for (int i = 0; i < blocksBelow - 1; i++) {
|
||||||
|
below.setY(below.getY() - 1);
|
||||||
|
|
||||||
|
// Blocks before must all be pass-through
|
||||||
|
Material type = below.getBlock().getType();
|
||||||
|
if (type.isSolid() || LegacyMats.canStandOn(type))
|
||||||
|
return false;
|
||||||
|
below = below.clone();
|
||||||
|
}
|
||||||
|
below.setY(bot.getLocation().getBlockY() - blocksBelow);
|
||||||
|
below2Set.add(below.getBlock().getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second block below must have at least one unplaceable block (that is landable)
|
||||||
|
boolean nether = bot.getDimension() == World.Environment.NETHER;
|
||||||
|
Iterator<Location> itr = below2Set.iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
Block next = itr.next().getBlock();
|
||||||
|
boolean placeable = nether ? LegacyMats.canPlaceTwistingVines(next)
|
||||||
|
: LegacyMats.canPlaceWater(next, Optional.absent());
|
||||||
|
if (placeable || (!next.getType().isSolid() && !LegacyMats.canStandOn(next.getType())))
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clutch
|
||||||
|
if (!below2Set.isEmpty()) {
|
||||||
|
List<Location> below2List = new ArrayList<>(below2Set);
|
||||||
|
below2List.sort((a, b) -> {
|
||||||
|
Block aBlock = a.clone().add(0, 1, 0).getBlock();
|
||||||
|
Block bBlock = b.clone().add(0, 1, 0).getBlock();
|
||||||
|
if (aBlock.getType().isAir() && !bBlock.getType().isAir())
|
||||||
|
return -1;
|
||||||
|
if (!bBlock.getType().isAir() && aBlock.getType().isAir())
|
||||||
|
return 1;
|
||||||
|
return Double.compare(BotUtils.getHorizSqDist(a, botLoc), BotUtils.getHorizSqDist(b, botLoc));
|
||||||
|
});
|
||||||
|
|
||||||
|
Location faceLoc = below2List.get(0);
|
||||||
|
Location loc = faceLoc.clone().add(0, 1, 0);
|
||||||
|
bot.faceLocation(faceLoc);
|
||||||
|
bot.look(BlockFace.DOWN);
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||||
|
bot.faceLocation(faceLoc);
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
bot.punch();
|
||||||
|
for (Player all : Bukkit.getOnlinePlayers())
|
||||||
|
all.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1);
|
||||||
|
bot.setItem(new ItemStack(Material.COBBLESTONE));
|
||||||
|
loc.getBlock().setType(Material.COBBLESTONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void clutch(Terminator bot, LivingEntity target) {
|
public void clutch(Terminator bot, LivingEntity target) {
|
||||||
Location botLoc = bot.getLocation();
|
Location botLoc = bot.getLocation();
|
||||||
|
|||||||
@@ -4,32 +4,162 @@ import java.util.Arrays;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public enum LegacyLevel {
|
import org.bukkit.Location;
|
||||||
ABOVE,
|
|
||||||
BELOW,
|
|
||||||
AT,
|
|
||||||
AT_D,
|
|
||||||
NORTH,
|
|
||||||
SOUTH,
|
|
||||||
EAST,
|
|
||||||
WEST,
|
|
||||||
NORTH_D,
|
|
||||||
SOUTH_D,
|
|
||||||
EAST_D,
|
|
||||||
WEST_D;
|
|
||||||
|
|
||||||
private static final Set<LegacyLevel> SIDE = new HashSet<>(Arrays.asList(
|
public enum LegacyLevel {
|
||||||
|
ABOVE(0, 2, 0),
|
||||||
|
BELOW(0, -1, 0),
|
||||||
|
AT(0, 1, 0),
|
||||||
|
AT_D(0, 0, 0),
|
||||||
|
NORTH_U(0, 2, -1),
|
||||||
|
SOUTH_U(0, 2, 1),
|
||||||
|
EAST_U(1, 2, 0),
|
||||||
|
WEST_U(-1, 2, 0),
|
||||||
|
NORTH(0, 1, -1),
|
||||||
|
SOUTH(0, 1, 1),
|
||||||
|
EAST(1, 1, 0),
|
||||||
|
WEST(-1, 1, 0),
|
||||||
|
NORTH_D(0, 0, -1),
|
||||||
|
SOUTH_D(0, 0, 1),
|
||||||
|
EAST_D(1, 0, 0),
|
||||||
|
WEST_D(-1, 0, 0),
|
||||||
|
NORTHWEST_D(-1, 0, -1),
|
||||||
|
SOUTHWEST_D(-1, 0, 1),
|
||||||
|
NORTHEAST_D(1, 0, -1),
|
||||||
|
SOUTHEAST_D(1, 0, 1),
|
||||||
|
NORTH_D_2(0, -1, -1),
|
||||||
|
SOUTH_D_2(0, -1, 1),
|
||||||
|
EAST_D_2(1, -1, 0),
|
||||||
|
WEST_D_2(-1, -1, 0);
|
||||||
|
|
||||||
|
private final int offsetX;
|
||||||
|
private final int offsetY;
|
||||||
|
private final int offsetZ;
|
||||||
|
|
||||||
|
private LegacyLevel(int offsetX, int offsetY, int offsetZ) {
|
||||||
|
this.offsetX = offsetX;
|
||||||
|
this.offsetY = offsetY;
|
||||||
|
this.offsetZ = offsetZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Set<LegacyLevel> NON_SIDE = new HashSet<>(Arrays.asList(
|
||||||
|
ABOVE,
|
||||||
|
BELOW,
|
||||||
|
AT,
|
||||||
|
AT_D
|
||||||
|
));
|
||||||
|
private static final Set<LegacyLevel> SIDE_AT = new HashSet<>(Arrays.asList(
|
||||||
NORTH,
|
NORTH,
|
||||||
SOUTH,
|
SOUTH,
|
||||||
EAST,
|
EAST,
|
||||||
WEST,
|
WEST
|
||||||
|
));
|
||||||
|
private static final Set<LegacyLevel> SIDE_UP = new HashSet<>(Arrays.asList(
|
||||||
|
NORTH_U,
|
||||||
|
SOUTH_U,
|
||||||
|
EAST_U,
|
||||||
|
WEST_U
|
||||||
|
));
|
||||||
|
private static final Set<LegacyLevel> SIDE_DOWN = new HashSet<>(Arrays.asList(
|
||||||
NORTH_D,
|
NORTH_D,
|
||||||
SOUTH_D,
|
SOUTH_D,
|
||||||
EAST_D,
|
EAST_D,
|
||||||
WEST_D
|
WEST_D
|
||||||
));
|
));
|
||||||
|
private static final Set<LegacyLevel> SIDE_DOWN_2 = new HashSet<>(Arrays.asList(
|
||||||
|
NORTH_D_2,
|
||||||
|
SOUTH_D_2,
|
||||||
|
EAST_D_2,
|
||||||
|
WEST_D_2
|
||||||
|
));
|
||||||
|
|
||||||
public boolean isSide() {
|
public boolean isSide() {
|
||||||
return SIDE.contains(this);
|
return !NON_SIDE.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSideAt() {
|
||||||
|
return SIDE_AT.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSideUp() {
|
||||||
|
return SIDE_UP.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSideDown() {
|
||||||
|
return SIDE_DOWN.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSideDown2() {
|
||||||
|
return SIDE_DOWN_2.contains(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LegacyLevel sideUp() {
|
||||||
|
switch(this) {
|
||||||
|
case NORTH: return NORTH_U;
|
||||||
|
case SOUTH: return SOUTH_U;
|
||||||
|
case EAST: return EAST_U;
|
||||||
|
case WEST: return WEST_U;
|
||||||
|
case NORTH_D: return NORTH;
|
||||||
|
case SOUTH_D: return SOUTH;
|
||||||
|
case EAST_D: return EAST;
|
||||||
|
case WEST_D: return WEST;
|
||||||
|
case NORTH_D_2: return NORTH_D;
|
||||||
|
case SOUTH_D_2: return SOUTH_D;
|
||||||
|
case EAST_D_2: return EAST_D;
|
||||||
|
case WEST_D_2: return WEST_D;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LegacyLevel sideDown() {
|
||||||
|
switch(this) {
|
||||||
|
case NORTH_U: return NORTH;
|
||||||
|
case SOUTH_U: return SOUTH;
|
||||||
|
case EAST_U: return EAST;
|
||||||
|
case WEST_U: return WEST;
|
||||||
|
case NORTH: return NORTH_D;
|
||||||
|
case SOUTH: return SOUTH_D;
|
||||||
|
case EAST: return EAST_D;
|
||||||
|
case WEST: return WEST_D;
|
||||||
|
case NORTH_D: return NORTH_D_2;
|
||||||
|
case SOUTH_D: return SOUTH_D_2;
|
||||||
|
case EAST_D: return EAST_D_2;
|
||||||
|
case WEST_D: return WEST_D_2;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LegacyLevel getOffset(Location start, Location end) {
|
||||||
|
int diffX = end.getBlockX() - start.getBlockX();
|
||||||
|
int diffY = end.getBlockY() - start.getBlockY();
|
||||||
|
int diffZ = end.getBlockZ() - start.getBlockZ();
|
||||||
|
for (LegacyLevel level : LegacyLevel.values()) {
|
||||||
|
if (level.offsetX == diffX && level.offsetY == diffY && level.offsetZ == diffZ) {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location offset(Location loc) {
|
||||||
|
return loc.add(offsetX, offsetY, offsetZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LevelWrapper {
|
||||||
|
private LegacyLevel level;
|
||||||
|
|
||||||
|
public LevelWrapper(LegacyLevel level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LegacyLevel getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(LegacyLevel level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,29 @@
|
|||||||
package net.nuggetmc.tplus.api.agent.legacyagent;
|
package net.nuggetmc.tplus.api.agent.legacyagent;
|
||||||
|
|
||||||
|
import org.bukkit.Axis;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.Bisected;
|
||||||
|
import org.bukkit.block.data.Waterlogged;
|
||||||
|
import org.bukkit.block.data.Bisected.Half;
|
||||||
|
import org.bukkit.block.data.type.*;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class LegacyMats {
|
public class LegacyMats {
|
||||||
|
|
||||||
public static final Set<Material> AIR = new HashSet<>(Arrays.asList(
|
public static final Set<Material> AIR = new HashSet<>(Arrays.asList(
|
||||||
Material.WATER,
|
Material.WATER,
|
||||||
Material.OAK_TRAPDOOR,
|
|
||||||
Material.FIRE,
|
Material.FIRE,
|
||||||
Material.LAVA,
|
Material.LAVA,
|
||||||
Material.SNOW,
|
Material.SNOW,
|
||||||
@@ -36,33 +49,49 @@ public class LegacyMats {
|
|||||||
Material.FIRE,
|
Material.FIRE,
|
||||||
Material.LAVA,
|
Material.LAVA,
|
||||||
Material.CAVE_AIR,
|
Material.CAVE_AIR,
|
||||||
|
Material.VOID_AIR,
|
||||||
|
Material.AIR,
|
||||||
Material.SOUL_FIRE
|
Material.SOUL_FIRE
|
||||||
));
|
));
|
||||||
|
|
||||||
public static final Set<Material> SHOVEL = new HashSet<>(Arrays.asList(
|
public static final Set<Material> SHOVEL = new HashSet<>(concatTypes(Lists.newArrayList(
|
||||||
|
Material.CLAY,
|
||||||
Material.DIRT,
|
Material.DIRT,
|
||||||
|
Material.GRASS_BLOCK,
|
||||||
|
Material.COARSE_DIRT,
|
||||||
|
Material.PODZOL,
|
||||||
|
Material.MYCELIUM,
|
||||||
Material.GRAVEL,
|
Material.GRAVEL,
|
||||||
|
Material.MUD,
|
||||||
|
Material.MUDDY_MANGROVE_ROOTS,
|
||||||
Material.SAND,
|
Material.SAND,
|
||||||
Material.SNOW
|
Material.RED_SAND,
|
||||||
));
|
Material.SOUL_SAND,
|
||||||
|
Material.SOUL_SOIL,
|
||||||
|
Material.SNOW,
|
||||||
|
Material.SNOW_BLOCK
|
||||||
|
), Arrays.asList(), Arrays.asList(), m -> m.name().endsWith("_CONCRETE_POWDER")));
|
||||||
|
|
||||||
public static final Set<Material> AXE = new HashSet<>(Arrays.asList(
|
public static final Set<Material> AXE = new HashSet<>(Arrays.asList(
|
||||||
Material.OAK_PLANKS, Material.OAK_DOOR, Material.OAK_FENCE, Material.OAK_FENCE_GATE, Material.OAK_LOG, Material.OAK_PLANKS,
|
Material.OAK_PLANKS, Material.OAK_DOOR, Material.OAK_FENCE, Material.OAK_FENCE_GATE, Material.OAK_LOG,
|
||||||
Material.OAK_SIGN, Material.OAK_SLAB, Material.OAK_STAIRS, Material.OAK_TRAPDOOR, Material.OAK_WALL_SIGN, Material.OAK_WOOD,
|
Material.OAK_SIGN, Material.OAK_SLAB, Material.OAK_STAIRS, Material.OAK_TRAPDOOR, Material.OAK_WALL_SIGN, Material.OAK_WOOD,
|
||||||
Material.DARK_OAK_PLANKS, Material.DARK_OAK_DOOR, Material.DARK_OAK_FENCE, Material.DARK_OAK_FENCE_GATE, Material.DARK_OAK_LOG, Material.DARK_OAK_PLANKS,
|
Material.DARK_OAK_PLANKS, Material.DARK_OAK_DOOR, Material.DARK_OAK_FENCE, Material.DARK_OAK_FENCE_GATE, Material.DARK_OAK_LOG,
|
||||||
Material.DARK_OAK_SIGN, Material.DARK_OAK_SLAB, Material.DARK_OAK_STAIRS, Material.DARK_OAK_TRAPDOOR, Material.DARK_OAK_WALL_SIGN, Material.DARK_OAK_WOOD,
|
Material.DARK_OAK_SIGN, Material.DARK_OAK_SLAB, Material.DARK_OAK_STAIRS, Material.DARK_OAK_TRAPDOOR, Material.DARK_OAK_WALL_SIGN, Material.DARK_OAK_WOOD,
|
||||||
Material.ACACIA_PLANKS, Material.ACACIA_DOOR, Material.ACACIA_FENCE, Material.ACACIA_FENCE_GATE, Material.ACACIA_LOG, Material.ACACIA_PLANKS,
|
Material.ACACIA_PLANKS, Material.ACACIA_DOOR, Material.ACACIA_FENCE, Material.ACACIA_FENCE_GATE, Material.ACACIA_LOG,
|
||||||
Material.ACACIA_SIGN, Material.ACACIA_SLAB, Material.ACACIA_STAIRS, Material.ACACIA_TRAPDOOR, Material.ACACIA_WALL_SIGN, Material.ACACIA_WOOD,
|
Material.ACACIA_SIGN, Material.ACACIA_SLAB, Material.ACACIA_STAIRS, Material.ACACIA_TRAPDOOR, Material.ACACIA_WALL_SIGN, Material.ACACIA_WOOD,
|
||||||
Material.BIRCH_PLANKS, Material.BIRCH_DOOR, Material.BIRCH_FENCE, Material.BIRCH_FENCE_GATE, Material.BIRCH_LOG, Material.BIRCH_PLANKS,
|
Material.BIRCH_PLANKS, Material.BIRCH_DOOR, Material.BIRCH_FENCE, Material.BIRCH_FENCE_GATE, Material.BIRCH_LOG,
|
||||||
Material.BIRCH_SIGN, Material.BIRCH_SLAB, Material.BIRCH_STAIRS, Material.BIRCH_TRAPDOOR, Material.BIRCH_WALL_SIGN, Material.BIRCH_WOOD,
|
Material.BIRCH_SIGN, Material.BIRCH_SLAB, Material.BIRCH_STAIRS, Material.BIRCH_TRAPDOOR, Material.BIRCH_WALL_SIGN, Material.BIRCH_WOOD,
|
||||||
Material.JUNGLE_PLANKS, Material.JUNGLE_DOOR, Material.JUNGLE_FENCE, Material.JUNGLE_FENCE_GATE, Material.JUNGLE_LOG, Material.JUNGLE_PLANKS,
|
Material.JUNGLE_PLANKS, Material.JUNGLE_DOOR, Material.JUNGLE_FENCE, Material.JUNGLE_FENCE_GATE, Material.JUNGLE_LOG,
|
||||||
Material.JUNGLE_SIGN, Material.JUNGLE_SLAB, Material.JUNGLE_STAIRS, Material.JUNGLE_TRAPDOOR, Material.JUNGLE_WALL_SIGN, Material.JUNGLE_WOOD,
|
Material.JUNGLE_SIGN, Material.JUNGLE_SLAB, Material.JUNGLE_STAIRS, Material.JUNGLE_TRAPDOOR, Material.JUNGLE_WALL_SIGN, Material.JUNGLE_WOOD,
|
||||||
Material.SPRUCE_PLANKS, Material.SPRUCE_DOOR, Material.SPRUCE_FENCE, Material.SPRUCE_FENCE_GATE, Material.SPRUCE_LOG, Material.SPRUCE_PLANKS,
|
Material.SPRUCE_PLANKS, Material.SPRUCE_DOOR, Material.SPRUCE_FENCE, Material.SPRUCE_FENCE_GATE, Material.SPRUCE_LOG,
|
||||||
Material.SPRUCE_SIGN, Material.SPRUCE_SLAB, Material.SPRUCE_STAIRS, Material.SPRUCE_TRAPDOOR, Material.SPRUCE_WALL_SIGN, Material.SPRUCE_WOOD,
|
Material.SPRUCE_SIGN, Material.SPRUCE_SLAB, Material.SPRUCE_STAIRS, Material.SPRUCE_TRAPDOOR, Material.SPRUCE_WALL_SIGN, Material.SPRUCE_WOOD,
|
||||||
Material.CRIMSON_PLANKS, Material.CRIMSON_DOOR, Material.CRIMSON_FENCE, Material.CRIMSON_FENCE_GATE, Material.CRIMSON_PLANKS,
|
Material.MANGROVE_PLANKS, Material.MANGROVE_DOOR, Material.MANGROVE_FENCE, Material.MANGROVE_FENCE_GATE, Material.MANGROVE_LOG,
|
||||||
|
Material.MANGROVE_SIGN, Material.MANGROVE_SLAB, Material.MANGROVE_STAIRS, Material.MANGROVE_TRAPDOOR, Material.MANGROVE_WALL_SIGN, Material.MANGROVE_WOOD,
|
||||||
|
Material.CRIMSON_PLANKS, Material.CRIMSON_DOOR, Material.CRIMSON_FENCE, Material.CRIMSON_FENCE_GATE, Material.CRIMSON_STEM,
|
||||||
Material.CRIMSON_SIGN, Material.CRIMSON_SLAB, Material.CRIMSON_STAIRS, Material.CRIMSON_TRAPDOOR, Material.CRIMSON_WALL_SIGN,
|
Material.CRIMSON_SIGN, Material.CRIMSON_SLAB, Material.CRIMSON_STAIRS, Material.CRIMSON_TRAPDOOR, Material.CRIMSON_WALL_SIGN,
|
||||||
Material.WARPED_PLANKS, Material.WARPED_DOOR, Material.WARPED_FENCE, Material.WARPED_FENCE_GATE, Material.WARPED_PLANKS,
|
Material.WARPED_PLANKS, Material.WARPED_DOOR, Material.WARPED_FENCE, Material.WARPED_FENCE_GATE, Material.WARPED_STEM,
|
||||||
Material.WARPED_SIGN, Material.WARPED_SLAB, Material.WARPED_STAIRS, Material.WARPED_TRAPDOOR, Material.WARPED_WALL_SIGN
|
Material.WARPED_SIGN, Material.WARPED_SLAB, Material.WARPED_STAIRS, Material.WARPED_TRAPDOOR, Material.WARPED_WALL_SIGN,
|
||||||
|
Material.CHEST, Material.TRAPPED_CHEST
|
||||||
));
|
));
|
||||||
|
|
||||||
public static final Set<Material> BREAK = new HashSet<>(Arrays.asList(
|
public static final Set<Material> BREAK = new HashSet<>(Arrays.asList(
|
||||||
@@ -70,14 +99,13 @@ public class LegacyMats {
|
|||||||
Material.WATER,
|
Material.WATER,
|
||||||
Material.LAVA,
|
Material.LAVA,
|
||||||
Material.TALL_GRASS,
|
Material.TALL_GRASS,
|
||||||
Material.SNOW,
|
|
||||||
Material.DIRT_PATH,
|
|
||||||
Material.CAVE_AIR,
|
Material.CAVE_AIR,
|
||||||
Material.VINE,
|
Material.VINE,
|
||||||
Material.FERN,
|
Material.FERN,
|
||||||
Material.LARGE_FERN,
|
Material.LARGE_FERN,
|
||||||
Material.SUGAR_CANE,
|
Material.SUGAR_CANE,
|
||||||
Material.TWISTING_VINES,
|
Material.TWISTING_VINES,
|
||||||
|
Material.TWISTING_VINES_PLANT,
|
||||||
Material.WEEPING_VINES,
|
Material.WEEPING_VINES,
|
||||||
Material.SEAGRASS,
|
Material.SEAGRASS,
|
||||||
Material.TALL_SEAGRASS,
|
Material.TALL_SEAGRASS,
|
||||||
@@ -135,34 +163,356 @@ public class LegacyMats {
|
|||||||
Material.WATER
|
Material.WATER
|
||||||
));
|
));
|
||||||
|
|
||||||
public static final Set<Material> FENCE = new HashSet<>(Arrays.asList(
|
public static final Set<Material> FENCE = new HashSet<>(concatTypes(new ArrayList<>(),
|
||||||
Material.OAK_FENCE,
|
Arrays.asList(Material.GLASS_PANE, Material.IRON_BARS), Arrays.asList(Fence.class, Wall.class)));
|
||||||
Material.ACACIA_FENCE,
|
|
||||||
Material.BIRCH_FENCE,
|
public static final Set<Material> GATES = new HashSet<>(concatTypes(Gate.class));
|
||||||
Material.CRIMSON_FENCE,
|
|
||||||
Material.DARK_OAK_FENCE,
|
public static final Set<Material> OBSTACLES = new HashSet<>(concatTypes(Lists.newArrayList(
|
||||||
Material.JUNGLE_FENCE,
|
Material.IRON_BARS,
|
||||||
Material.NETHER_BRICK_FENCE,
|
Material.CHAIN,
|
||||||
Material.SPRUCE_FENCE,
|
Material.END_ROD,
|
||||||
Material.WARPED_FENCE,
|
Material.LIGHTNING_ROD,
|
||||||
Material.COBBLESTONE_WALL,
|
Material.COBWEB,
|
||||||
Material.ANDESITE_WALL,
|
Material.SWEET_BERRY_BUSH,
|
||||||
Material.BLACKSTONE_WALL,
|
Material.FLOWER_POT,
|
||||||
Material.BRICK_WALL,
|
Material.GLASS_PANE
|
||||||
Material.GRANITE_WALL,
|
), Arrays.asList(), Arrays.asList(GlassPane.class), m -> m.name().startsWith("POTTED_")));
|
||||||
Material.DIORITE_WALL,
|
|
||||||
Material.SANDSTONE_WALL,
|
|
||||||
Material.RED_SANDSTONE_WALL,
|
|
||||||
Material.RED_NETHER_BRICK_WALL,
|
|
||||||
Material.IRON_BARS,
|
|
||||||
Material.COBWEB
|
|
||||||
));
|
|
||||||
|
|
||||||
public static final Set<Material> LEAVES = new HashSet<>(Arrays.asList(
|
//Notice: We exclude blocks that cannot exist without a solid block below (such as rails or crops)
|
||||||
Material.BIRCH_LEAVES,
|
public static final Set<Material> NONSOLID = new HashSet<>(concatTypes(Lists.newArrayList(
|
||||||
Material.DARK_OAK_LEAVES,
|
Material.COBWEB,
|
||||||
Material.JUNGLE_LEAVES,
|
Material.END_GATEWAY,
|
||||||
Material.OAK_LEAVES,
|
Material.END_PORTAL,
|
||||||
Material.SPRUCE_LEAVES
|
Material.NETHER_PORTAL,
|
||||||
));
|
Material.CAVE_VINES_PLANT,
|
||||||
|
Material.GLOW_LICHEN,
|
||||||
|
Material.HANGING_ROOTS,
|
||||||
|
Material.POWDER_SNOW,
|
||||||
|
Material.SCULK_VEIN,
|
||||||
|
Material.STRING,
|
||||||
|
Material.TRIPWIRE_HOOK,
|
||||||
|
Material.LADDER,
|
||||||
|
Material.VINE,
|
||||||
|
Material.SOUL_WALL_TORCH,
|
||||||
|
Material.REDSTONE_WALL_TORCH,
|
||||||
|
Material.WALL_TORCH,
|
||||||
|
Material.WEEPING_VINES_PLANT,
|
||||||
|
Material.WEEPING_VINES,
|
||||||
|
Material.CAVE_VINES_PLANT,
|
||||||
|
Material.CAVE_VINES
|
||||||
|
), Arrays.asList(), Arrays.asList(Switch.class, CoralWallFan.class, WallSign.class), m -> m.name().endsWith("_WALL_BANNER")));
|
||||||
|
|
||||||
|
public static final Set<Material> LEAVES = new HashSet<>(concatTypes(Leaves.class));
|
||||||
|
|
||||||
|
public static final Set<Material> INSTANT_BREAK = new HashSet<>(concatTypes(Lists.newArrayList(
|
||||||
|
Material.TALL_GRASS,
|
||||||
|
Material.GRASS,
|
||||||
|
Material.FERN,
|
||||||
|
Material.LARGE_FERN,
|
||||||
|
Material.KELP_PLANT,
|
||||||
|
Material.DEAD_BUSH,
|
||||||
|
Material.WHEAT_SEEDS,
|
||||||
|
Material.POTATOES,
|
||||||
|
Material.CARROTS,
|
||||||
|
Material.BEETROOT_SEEDS,
|
||||||
|
Material.PUMPKIN_STEM,
|
||||||
|
Material.MELON_STEM,
|
||||||
|
Material.SUGAR_CANE,
|
||||||
|
Material.SWEET_BERRY_BUSH,
|
||||||
|
Material.LILY_PAD,
|
||||||
|
Material.DANDELION,
|
||||||
|
Material.POPPY,
|
||||||
|
Material.BLUE_ORCHID,
|
||||||
|
Material.ALLIUM,
|
||||||
|
Material.AZURE_BLUET,
|
||||||
|
Material.RED_TULIP,
|
||||||
|
Material.ORANGE_TULIP,
|
||||||
|
Material.WHITE_TULIP,
|
||||||
|
Material.PINK_TULIP,
|
||||||
|
Material.OXEYE_DAISY,
|
||||||
|
Material.CORNFLOWER,
|
||||||
|
Material.LILY_OF_THE_VALLEY,
|
||||||
|
Material.WITHER_ROSE,
|
||||||
|
Material.SUNFLOWER,
|
||||||
|
Material.LILAC,
|
||||||
|
Material.ROSE_BUSH,
|
||||||
|
Material.PEONY,
|
||||||
|
Material.NETHER_WART,
|
||||||
|
Material.FLOWER_POT,
|
||||||
|
Material.AZALEA,
|
||||||
|
Material.FLOWERING_AZALEA,
|
||||||
|
Material.REPEATER,
|
||||||
|
Material.COMPARATOR,
|
||||||
|
Material.REDSTONE_WIRE,
|
||||||
|
Material.REDSTONE_TORCH,
|
||||||
|
Material.REDSTONE_WALL_TORCH,
|
||||||
|
Material.TORCH,
|
||||||
|
Material.WALL_TORCH,
|
||||||
|
Material.SOUL_TORCH,
|
||||||
|
Material.SOUL_WALL_TORCH,
|
||||||
|
Material.SCAFFOLDING,
|
||||||
|
Material.SLIME_BLOCK,
|
||||||
|
Material.HONEY_BLOCK,
|
||||||
|
Material.TNT,
|
||||||
|
Material.TRIPWIRE,
|
||||||
|
Material.TRIPWIRE_HOOK,
|
||||||
|
Material.SPORE_BLOSSOM,
|
||||||
|
Material.RED_MUSHROOM,
|
||||||
|
Material.BROWN_MUSHROOM,
|
||||||
|
Material.CRIMSON_FUNGUS,
|
||||||
|
Material.WARPED_FUNGUS,
|
||||||
|
Material.CRIMSON_ROOTS,
|
||||||
|
Material.WARPED_ROOTS,
|
||||||
|
Material.HANGING_ROOTS,
|
||||||
|
Material.WEEPING_VINES,
|
||||||
|
Material.WEEPING_VINES_PLANT,
|
||||||
|
Material.TWISTING_VINES,
|
||||||
|
Material.TWISTING_VINES_PLANT,
|
||||||
|
Material.CAVE_VINES,
|
||||||
|
Material.CAVE_VINES_PLANT,
|
||||||
|
Material.SEA_PICKLE
|
||||||
|
), Arrays.asList(), Arrays.asList(Sapling.class, CoralWallFan.class), m -> m.name().endsWith("_CORAL_FAN") || m.name().endsWith("_CORAL")
|
||||||
|
|| m.name().startsWith("POTTED_")));
|
||||||
|
|
||||||
|
private static List<Material> concatTypes(Class<?>... types) {
|
||||||
|
return concatTypes(new ArrayList<>(), Arrays.asList(types));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Material> concatTypes(List<Material> materials, List<Class<?>> types) {
|
||||||
|
return concatTypes(materials, Arrays.asList(), types);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Material> concatTypes(List<Material> materials, List<Material> exclusions, List<Class<?>> types) {
|
||||||
|
return concatTypes(materials, exclusions, types, m -> false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Material> concatTypes(List<Material> materials, List<Material> exclusions, List<Class<?>> types, Predicate<Material> otherFilter) {
|
||||||
|
materials.addAll(Stream.of(Material.values()).filter(m -> (types.contains(m.data) || otherFilter.test(m))
|
||||||
|
&& !exclusions.contains(m) && !m.isLegacy()).toList());
|
||||||
|
return materials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for non-solid blocks that can hold an entity up.
|
||||||
|
*/
|
||||||
|
public static boolean canStandOn(Material mat) {
|
||||||
|
if(mat == Material.END_ROD || mat == Material.FLOWER_POT || mat == Material.REPEATER || mat == Material.COMPARATOR
|
||||||
|
|| mat == Material.SNOW || mat == Material.LADDER || mat == Material.VINE || mat == Material.SCAFFOLDING
|
||||||
|
|| mat == Material.AZALEA || mat == Material.FLOWERING_AZALEA || mat == Material.BIG_DRIPLEAF
|
||||||
|
|| mat == Material.CHORUS_FLOWER || mat == Material.CHORUS_PLANT || mat == Material.COCOA
|
||||||
|
|| mat == Material.LILY_PAD || mat == Material.SEA_PICKLE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(mat.name().endsWith("_CARPET"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(mat.name().startsWith("POTTED_"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if((mat.name().endsWith("_HEAD") || mat.name().endsWith("_SKULL")) && !mat.name().equals("PISTON_HEAD"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(mat.data == Candle.class)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canPlaceWater(Block block, Optional<Double> entityYPos) {
|
||||||
|
if (block.getType().isSolid()) {
|
||||||
|
if (block.getType() == Material.CHAIN && ((Chain)block.getBlockData()).getAxis() == Axis.Y
|
||||||
|
&& !((Chain)block.getBlockData()).isWaterlogged())
|
||||||
|
return false;
|
||||||
|
if ((block.getType().data == Leaves.class || block.getType() == Material.MANGROVE_ROOTS
|
||||||
|
|| block.getType() == Material.IRON_BARS || block.getType().name().endsWith("GLASS_PANE"))
|
||||||
|
&& !((Waterlogged)block.getBlockData()).isWaterlogged())
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Slab.class && ((Slab)block.getBlockData()).getType() == Slab.Type.TOP
|
||||||
|
&& !((Slab)block.getBlockData()).isWaterlogged())
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Stairs.class && ((Stairs)block.getBlockData()).getHalf() == Bisected.Half.TOP
|
||||||
|
&& !((Stairs)block.getBlockData()).isWaterlogged())
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Stairs.class && ((Stairs)block.getBlockData()).getHalf() == Bisected.Half.BOTTOM
|
||||||
|
&& !((Stairs)block.getBlockData()).isWaterlogged()
|
||||||
|
&& (!entityYPos.isPresent() || (int)entityYPos.get().doubleValue() != block.getLocation().getBlockY()))
|
||||||
|
return false;
|
||||||
|
if ((block.getType().data == Fence.class || block.getType().data == Wall.class)
|
||||||
|
&& !((Waterlogged)block.getBlockData()).isWaterlogged())
|
||||||
|
return false;
|
||||||
|
if (block.getType() == Material.LIGHTNING_ROD && !((LightningRod)block.getBlockData()).isWaterlogged()
|
||||||
|
&& (((LightningRod)block.getBlockData()).getFacing() == BlockFace.UP || ((LightningRod)block.getBlockData()).getFacing() == BlockFace.DOWN))
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == TrapDoor.class && (((TrapDoor)block.getBlockData()).getHalf() == Half.TOP
|
||||||
|
|| (((TrapDoor)block.getBlockData()).getHalf() == Half.BOTTOM && ((TrapDoor)block.getBlockData()).isOpen()))
|
||||||
|
&& !((TrapDoor)block.getBlockData()).isWaterlogged())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (block.getType().name().endsWith("_CARPET"))
|
||||||
|
return true;
|
||||||
|
if (block.getType().data == Candle.class)
|
||||||
|
return true;
|
||||||
|
if (block.getType().name().startsWith("POTTED_"))
|
||||||
|
return true;
|
||||||
|
if ((block.getType().name().endsWith("_HEAD") || block.getType().name().endsWith("_SKULL"))
|
||||||
|
&& !block.getType().name().equals("PISTON_HEAD"))
|
||||||
|
return true;
|
||||||
|
switch (block.getType()) {
|
||||||
|
case SNOW:
|
||||||
|
case AZALEA:
|
||||||
|
case FLOWERING_AZALEA:
|
||||||
|
case CHORUS_FLOWER:
|
||||||
|
case CHORUS_PLANT:
|
||||||
|
case COCOA:
|
||||||
|
case LILY_PAD:
|
||||||
|
case SEA_PICKLE:
|
||||||
|
case END_ROD:
|
||||||
|
case FLOWER_POT:
|
||||||
|
case SCAFFOLDING:
|
||||||
|
case COMPARATOR:
|
||||||
|
case REPEATER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canPlaceTwistingVines(Block block) {
|
||||||
|
if (block.getType().isSolid()) {
|
||||||
|
if (block.getType().data == Leaves.class)
|
||||||
|
return false;
|
||||||
|
if (block.getType().name().endsWith("_CORAL_FAN") || block.getType().name().endsWith("_CORAL")
|
||||||
|
|| block.getType().name().endsWith("_CORAL_WALL_FAN"))
|
||||||
|
return false;
|
||||||
|
if (block.getType().name().endsWith("GLASS_PANE"))
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Slab.class && ((Slab)block.getBlockData()).getType() == Slab.Type.BOTTOM)
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Stairs.class && ((Stairs)block.getBlockData()).getHalf() == Bisected.Half.BOTTOM)
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Fence.class || block.getType().data == Wall.class)
|
||||||
|
return false;
|
||||||
|
if (block.getType().name().endsWith("_BANNER"))
|
||||||
|
return false;
|
||||||
|
if (block.getType().name().endsWith("_WALL_BANNER"))
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Bed.class)
|
||||||
|
return false;
|
||||||
|
if (block.getType().name().endsWith("CANDLE_CAKE"))
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Door.class)
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Gate.class)
|
||||||
|
return false;
|
||||||
|
if (block.getType() == Material.PISTON_HEAD && ((PistonHead)block.getBlockData()).getFacing() != BlockFace.UP)
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == Piston.class && ((Piston)block.getBlockData()).getFacing() != BlockFace.DOWN
|
||||||
|
&& ((Piston)block.getBlockData()).isExtended())
|
||||||
|
return false;
|
||||||
|
if (block.getType().data == TrapDoor.class && (((TrapDoor)block.getBlockData()).getHalf() == Half.BOTTOM
|
||||||
|
|| ((TrapDoor)block.getBlockData()).isOpen()))
|
||||||
|
return false;
|
||||||
|
switch (block.getType()) {
|
||||||
|
case POINTED_DRIPSTONE:
|
||||||
|
case SMALL_AMETHYST_BUD:
|
||||||
|
case MEDIUM_AMETHYST_BUD:
|
||||||
|
case LARGE_AMETHYST_BUD:
|
||||||
|
case AMETHYST_CLUSTER:
|
||||||
|
case BAMBOO:
|
||||||
|
case CACTUS:
|
||||||
|
case DRAGON_EGG:
|
||||||
|
case TURTLE_EGG:
|
||||||
|
case CHAIN:
|
||||||
|
case IRON_BARS:
|
||||||
|
case LANTERN:
|
||||||
|
case SOUL_LANTERN:
|
||||||
|
case ANVIL:
|
||||||
|
case BREWING_STAND:
|
||||||
|
case CHEST:
|
||||||
|
case ENDER_CHEST:
|
||||||
|
case TRAPPED_CHEST:
|
||||||
|
case ENCHANTING_TABLE:
|
||||||
|
case GRINDSTONE:
|
||||||
|
case LECTERN:
|
||||||
|
case STONECUTTER:
|
||||||
|
case BELL:
|
||||||
|
case CAKE:
|
||||||
|
case CAMPFIRE:
|
||||||
|
case SOUL_CAMPFIRE:
|
||||||
|
case CAULDRON:
|
||||||
|
case COMPOSTER:
|
||||||
|
case CONDUIT:
|
||||||
|
case END_PORTAL_FRAME:
|
||||||
|
case FARMLAND:
|
||||||
|
case DAYLIGHT_DETECTOR:
|
||||||
|
case HONEY_BLOCK:
|
||||||
|
case HOPPER:
|
||||||
|
case LIGHTNING_ROD:
|
||||||
|
case SCULK_SENSOR:
|
||||||
|
case SCULK_SHRIEKER:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
switch (block.getType()) {
|
||||||
|
case CHORUS_FLOWER:
|
||||||
|
case SCAFFOLDING:
|
||||||
|
case AZALEA:
|
||||||
|
case FLOWERING_AZALEA:
|
||||||
|
return true;
|
||||||
|
case SNOW:
|
||||||
|
return ((Snow)block.getBlockData()).getLayers() == 1 || ((Snow)block.getBlockData()).getLayers() == 8;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean shouldReplace(Block block, double entityYPos, boolean nether) {
|
||||||
|
if ((int)entityYPos != block.getLocation().getBlockY())
|
||||||
|
return false;
|
||||||
|
if (nether) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (block.getType().name().endsWith("_CORAL_FAN") || block.getType().name().endsWith("_CORAL")
|
||||||
|
|| block.getType().name().endsWith("_CORAL_WALL_FAN"))
|
||||||
|
return true;
|
||||||
|
if (block.getType().data == Slab.class && ((Slab)block.getBlockData()).getType() == Slab.Type.BOTTOM)
|
||||||
|
return true;
|
||||||
|
if (block.getType().data == Stairs.class && !((Stairs)block.getBlockData()).isWaterlogged())
|
||||||
|
return true;
|
||||||
|
if (block.getType().data == Chain.class && !((Chain)block.getBlockData()).isWaterlogged())
|
||||||
|
return true;
|
||||||
|
if (block.getType().data == Candle.class)
|
||||||
|
return true;
|
||||||
|
if (block.getType().data == TrapDoor.class && !((TrapDoor)block.getBlockData()).isWaterlogged())
|
||||||
|
return true;
|
||||||
|
switch (block.getType()) {
|
||||||
|
case POINTED_DRIPSTONE:
|
||||||
|
case SMALL_AMETHYST_BUD:
|
||||||
|
case MEDIUM_AMETHYST_BUD:
|
||||||
|
case LARGE_AMETHYST_BUD:
|
||||||
|
case AMETHYST_CLUSTER:
|
||||||
|
case SEA_PICKLE:
|
||||||
|
case LANTERN:
|
||||||
|
case SOUL_LANTERN:
|
||||||
|
case CHEST:
|
||||||
|
case ENDER_CHEST:
|
||||||
|
case TRAPPED_CHEST:
|
||||||
|
case CAMPFIRE:
|
||||||
|
case SOUL_CAMPFIRE:
|
||||||
|
case CONDUIT:
|
||||||
|
case LIGHTNING_ROD:
|
||||||
|
case SCULK_SENSOR:
|
||||||
|
case SCULK_SHRIEKER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,30 @@
|
|||||||
package net.nuggetmc.tplus.api.event;
|
package net.nuggetmc.tplus.api.event;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
import net.nuggetmc.tplus.api.Terminator;
|
import net.nuggetmc.tplus.api.Terminator;
|
||||||
|
|
||||||
public class BotFallDamageEvent {
|
public class BotFallDamageEvent {
|
||||||
|
|
||||||
private final Terminator bot;
|
private final Terminator bot;
|
||||||
|
private final List<Block> standingOn;
|
||||||
|
|
||||||
private boolean cancelled;
|
private boolean cancelled;
|
||||||
|
|
||||||
public BotFallDamageEvent(Terminator bot) {
|
public BotFallDamageEvent(Terminator bot, List<Block> standingOn) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
|
this.standingOn = standingOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Terminator getBot() {
|
public Terminator getBot() {
|
||||||
return bot;
|
return bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Block> getStandingOn() {
|
||||||
|
return standingOn;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return cancelled;
|
return cancelled;
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ package net.nuggetmc.tplus.api.utils;
|
|||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.util.BoundingBox;
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.NumberConversions;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -17,6 +16,12 @@ public class BotUtils {
|
|||||||
Material.WATER,
|
Material.WATER,
|
||||||
Material.LAVA,
|
Material.LAVA,
|
||||||
Material.TWISTING_VINES,
|
Material.TWISTING_VINES,
|
||||||
|
Material.TWISTING_VINES_PLANT,
|
||||||
|
Material.WEEPING_VINES,
|
||||||
|
Material.WEEPING_VINES_PLANT,
|
||||||
|
Material.SWEET_BERRY_BUSH,
|
||||||
|
Material.POWDER_SNOW,
|
||||||
|
Material.COBWEB,
|
||||||
Material.VINE
|
Material.VINE
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -29,24 +34,12 @@ public class BotUtils {
|
|||||||
|
|
||||||
return randomSteveUUID();
|
return randomSteveUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean solidAt(Location loc) { // not perfect, still cuts corners of fences
|
public static boolean overlaps(BoundingBox playerBox, BoundingBox blockBox) {
|
||||||
Block block = loc.getBlock();
|
return playerBox.overlaps(blockBox);
|
||||||
BoundingBox box = block.getBoundingBox();
|
}
|
||||||
Vector position = loc.toVector();
|
|
||||||
|
public static double getHorizSqDist(Location blockLoc, Location pLoc) {
|
||||||
double x = position.getX();
|
return NumberConversions.square(blockLoc.getX() + 0.5 - pLoc.getX()) + NumberConversions.square(blockLoc.getZ() + 0.5 - pLoc.getZ());
|
||||||
double y = position.getY();
|
|
||||||
double z = position.getZ();
|
|
||||||
|
|
||||||
double minX = box.getMinX();
|
|
||||||
double minY = box.getMinY();
|
|
||||||
double minZ = box.getMinZ();
|
|
||||||
|
|
||||||
double maxX = box.getMaxX();
|
|
||||||
double maxY = box.getMaxY();
|
|
||||||
double maxZ = box.getMaxZ();
|
|
||||||
|
|
||||||
return x > minX && x < maxX && y > minY && y < maxY && z > minZ && z < maxZ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "net.nuggetmc"
|
group = "net.nuggetmc"
|
||||||
version = "3.2-BETA"
|
version = "3.3.1-BETA"
|
||||||
description = "TerminatorPlus"
|
description = "TerminatorPlus"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -13,7 +13,7 @@ java {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
paperDevBundle("1.19-R0.1-SNAPSHOT")
|
paperDevBundle("1.19.2-R0.1-SNAPSHOT")
|
||||||
|
|
||||||
//add the TerminatorPlus-API module
|
//add the TerminatorPlus-API module
|
||||||
implementation(project(":TerminatorPlus-API"))
|
implementation(project(":TerminatorPlus-API"))
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import net.nuggetmc.tplus.api.TerminatorPlusAPI;
|
|||||||
import net.nuggetmc.tplus.bot.BotManagerImpl;
|
import net.nuggetmc.tplus.bot.BotManagerImpl;
|
||||||
import net.nuggetmc.tplus.bridge.InternalBridgeImpl;
|
import net.nuggetmc.tplus.bridge.InternalBridgeImpl;
|
||||||
import net.nuggetmc.tplus.command.CommandHandler;
|
import net.nuggetmc.tplus.command.CommandHandler;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
@@ -11,8 +12,13 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
public class TerminatorPlus extends JavaPlugin {
|
public class TerminatorPlus extends JavaPlugin {
|
||||||
|
|
||||||
|
public static final String REQUIRED_VERSION = "1.19.2";
|
||||||
|
|
||||||
private static TerminatorPlus instance;
|
private static TerminatorPlus instance;
|
||||||
private static String version;
|
private static String version;
|
||||||
|
private static String mcVersion;
|
||||||
|
|
||||||
|
private static boolean correctVersion;
|
||||||
|
|
||||||
private BotManagerImpl manager;
|
private BotManagerImpl manager;
|
||||||
private CommandHandler handler;
|
private CommandHandler handler;
|
||||||
@@ -38,6 +44,14 @@ public class TerminatorPlus extends JavaPlugin {
|
|||||||
instance = this;
|
instance = this;
|
||||||
version = getDescription().getVersion();
|
version = getDescription().getVersion();
|
||||||
|
|
||||||
|
String version = Bukkit.getVersion();
|
||||||
|
correctVersion = version.contains(REQUIRED_VERSION);
|
||||||
|
if (version.contains("MC:")) { // git-ABX-123 (MC: ABCD)
|
||||||
|
version = version.substring(version.indexOf("MC:") + 3, version.indexOf(")")).trim();
|
||||||
|
}
|
||||||
|
mcVersion = version;
|
||||||
|
getLogger().info("Running on version: " + version + ", required version: " + REQUIRED_VERSION + ", correct version: " + correctVersion);
|
||||||
|
|
||||||
// Create Instances
|
// Create Instances
|
||||||
this.manager = new BotManagerImpl();
|
this.manager = new BotManagerImpl();
|
||||||
this.handler = new CommandHandler(this);
|
this.handler = new CommandHandler(this);
|
||||||
@@ -47,6 +61,16 @@ public class TerminatorPlus extends JavaPlugin {
|
|||||||
|
|
||||||
// Register event listeners
|
// Register event listeners
|
||||||
this.registerEvents(manager);
|
this.registerEvents(manager);
|
||||||
|
|
||||||
|
if (!correctVersion) {
|
||||||
|
for (int i = 0; i < 20; i++) { // Kids are stupid so we need to make sure they see this
|
||||||
|
getLogger().severe("----------------------------------------");
|
||||||
|
getLogger().severe("TerminatorPlus is not compatible with your server version!");
|
||||||
|
getLogger().severe("You are running on version: " + version + ", required version: " + REQUIRED_VERSION);
|
||||||
|
getLogger().severe("Either download the correct version of TerminatorPlus or update your server. (https://papermc.io/downloads)");
|
||||||
|
getLogger().severe("----------------------------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -57,4 +81,12 @@ public class TerminatorPlus extends JavaPlugin {
|
|||||||
private void registerEvents(Listener... listeners) {
|
private void registerEvents(Listener... listeners) {
|
||||||
Arrays.stream(listeners).forEach(li -> this.getServer().getPluginManager().registerEvents(li, this));
|
Arrays.stream(listeners).forEach(li -> this.getServer().getPluginManager().registerEvents(li, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isCorrectVersion() {
|
||||||
|
return correctVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMcVersion() {
|
||||||
|
return mcVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ package net.nuggetmc.tplus.bot;
|
|||||||
|
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import io.netty.util.concurrent.Future;
|
|
||||||
import io.netty.util.concurrent.GenericFutureListener;
|
|
||||||
import net.minecraft.network.Connection;
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.PacketSendListener;
|
||||||
import net.minecraft.network.protocol.Packet;
|
import net.minecraft.network.protocol.Packet;
|
||||||
import net.minecraft.network.protocol.PacketFlow;
|
import net.minecraft.network.protocol.PacketFlow;
|
||||||
import net.minecraft.network.protocol.game.*;
|
import net.minecraft.network.protocol.game.*;
|
||||||
@@ -26,6 +25,7 @@ import net.minecraft.world.phys.Vec3;
|
|||||||
import net.nuggetmc.tplus.TerminatorPlus;
|
import net.nuggetmc.tplus.TerminatorPlus;
|
||||||
import net.nuggetmc.tplus.api.Terminator;
|
import net.nuggetmc.tplus.api.Terminator;
|
||||||
import net.nuggetmc.tplus.api.agent.Agent;
|
import net.nuggetmc.tplus.api.agent.Agent;
|
||||||
|
import net.nuggetmc.tplus.api.agent.legacyagent.LegacyMats;
|
||||||
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
|
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
|
||||||
import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent;
|
import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent;
|
||||||
import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
|
import net.nuggetmc.tplus.api.event.BotFallDamageEvent;
|
||||||
@@ -34,6 +34,7 @@ import net.nuggetmc.tplus.api.utils.*;
|
|||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.Waterlogged;
|
||||||
import org.bukkit.craftbukkit.v1_19_R1.CraftEquipmentSlot;
|
import org.bukkit.craftbukkit.v1_19_R1.CraftEquipmentSlot;
|
||||||
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
|
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
|
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
|
||||||
@@ -44,11 +45,13 @@ import org.bukkit.entity.Damageable;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -68,13 +71,14 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
private boolean removeOnDeath;
|
private boolean removeOnDeath;
|
||||||
private int aliveTicks;
|
private int aliveTicks;
|
||||||
private int kills;
|
private int kills;
|
||||||
private byte fireTicks; // Fire animation isn't played? Bot still takes damage.
|
|
||||||
private byte groundTicks;
|
private byte groundTicks;
|
||||||
private byte jumpTicks;
|
private byte jumpTicks;
|
||||||
private byte noFallTicks;
|
private byte noFallTicks;
|
||||||
private boolean ignoredByMobs = true;
|
private List<Block> standingOn = new ArrayList<>();
|
||||||
private UUID targetPlayer = null;
|
private UUID targetPlayer = null;
|
||||||
private Bot(MinecraftServer minecraftServer, ServerLevel worldServer, GameProfile profile) {
|
private boolean inPlayerList;
|
||||||
|
|
||||||
|
private Bot(MinecraftServer minecraftServer, ServerLevel worldServer, GameProfile profile, boolean addToPlayerList) {
|
||||||
super(minecraftServer, worldServer, profile, null);
|
super(minecraftServer, worldServer, profile, null);
|
||||||
|
|
||||||
this.plugin = TerminatorPlus.getInstance();
|
this.plugin = TerminatorPlus.getInstance();
|
||||||
@@ -84,9 +88,12 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
this.velocity = new Vector(0, 0, 0);
|
this.velocity = new Vector(0, 0, 0);
|
||||||
this.oldVelocity = velocity.clone();
|
this.oldVelocity = velocity.clone();
|
||||||
this.noFallTicks = 60;
|
this.noFallTicks = 60;
|
||||||
this.fireTicks = 0;
|
|
||||||
this.removeOnDeath = true;
|
this.removeOnDeath = true;
|
||||||
this.offset = MathUtils.circleOffset(3);
|
this.offset = MathUtils.circleOffset(3);
|
||||||
|
if (addToPlayerList) {
|
||||||
|
minecraftServer.getPlayerList().getPlayers().add(this);
|
||||||
|
inPlayerList = true;
|
||||||
|
}
|
||||||
|
|
||||||
//this.entityData.set(new EntityDataAccessor<>(16, EntityDataSerializers.BYTE), (byte) 0xFF);
|
//this.entityData.set(new EntityDataAccessor<>(16, EntityDataSerializers.BYTE), (byte) 0xFF);
|
||||||
}
|
}
|
||||||
@@ -102,13 +109,15 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
UUID uuid = BotUtils.randomSteveUUID();
|
UUID uuid = BotUtils.randomSteveUUID();
|
||||||
|
|
||||||
CustomGameProfile profile = new CustomGameProfile(uuid, ChatUtils.trim16(name), skin);
|
CustomGameProfile profile = new CustomGameProfile(uuid, ChatUtils.trim16(name), skin);
|
||||||
|
|
||||||
|
boolean addPlayerList = TerminatorPlus.getInstance().getManager().addToPlayerList();
|
||||||
|
|
||||||
Bot bot = new Bot(nmsServer, nmsWorld, profile);
|
Bot bot = new Bot(nmsServer, nmsWorld, profile, addPlayerList);
|
||||||
|
|
||||||
bot.connection = new ServerGamePacketListenerImpl(nmsServer, new Connection(PacketFlow.CLIENTBOUND) {
|
bot.connection = new ServerGamePacketListenerImpl(nmsServer, new Connection(PacketFlow.CLIENTBOUND) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> genericfuturelistener) {
|
public void send(Packet<?> packet, @Nullable PacketSendListener callbacks) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}, bot);
|
}, bot);
|
||||||
@@ -118,7 +127,10 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
bot.getBukkitEntity().setNoDamageTicks(0);
|
bot.getBukkitEntity().setNoDamageTicks(0);
|
||||||
Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().connection.send(
|
Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().connection.send(
|
||||||
new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, bot)));
|
new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, bot)));
|
||||||
nmsWorld.addFreshEntity(bot);
|
if (addPlayerList)
|
||||||
|
nmsWorld.addNewPlayer(bot);
|
||||||
|
else
|
||||||
|
nmsWorld.addFreshEntity(bot);
|
||||||
bot.renderAll();
|
bot.renderAll();
|
||||||
|
|
||||||
TerminatorPlus.getInstance().getManager().add(bot);
|
TerminatorPlus.getInstance().getManager().add(bot);
|
||||||
@@ -242,6 +254,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
public int getAliveTicks() {
|
public int getAliveTicks() {
|
||||||
return aliveTicks;
|
return aliveTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNoFallTicks() {
|
||||||
|
return noFallTicks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tickDelay(int i) {
|
public boolean tickDelay(int i) {
|
||||||
@@ -277,8 +294,6 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
|
|
||||||
aliveTicks++;
|
aliveTicks++;
|
||||||
|
|
||||||
if (fireTicks > 0) --fireTicks;
|
|
||||||
if (invulnerableTime > 0) --invulnerableTime;
|
|
||||||
if (jumpTicks > 0) --jumpTicks;
|
if (jumpTicks > 0) --jumpTicks;
|
||||||
if (noFallTicks > 0) --noFallTicks;
|
if (noFallTicks > 0) --noFallTicks;
|
||||||
|
|
||||||
@@ -289,6 +304,8 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateLocation();
|
updateLocation();
|
||||||
|
|
||||||
|
if (!isAlive()) return;
|
||||||
|
|
||||||
float health = getHealth();
|
float health = getHealth();
|
||||||
float maxHealth = getMaxHealth();
|
float maxHealth = getMaxHealth();
|
||||||
@@ -303,14 +320,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
|
|
||||||
setHealth(amount);
|
setHealth(amount);
|
||||||
|
|
||||||
fireDamageCheck();
|
|
||||||
fallDamageCheck();
|
fallDamageCheck();
|
||||||
|
|
||||||
if (position().y < -64) {
|
|
||||||
die(DamageSource.OUT_OF_WORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
oldVelocity = velocity.clone();
|
oldVelocity = velocity.clone();
|
||||||
|
|
||||||
|
doTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadChunks() {
|
private void loadChunks() {
|
||||||
@@ -327,52 +341,6 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fireDamageCheck() {
|
|
||||||
if (!isAlive()) {
|
|
||||||
return; // maybe also have packet reset thing
|
|
||||||
}
|
|
||||||
|
|
||||||
Material type = getLocation().getBlock().getType();
|
|
||||||
|
|
||||||
if (type == Material.WATER) {
|
|
||||||
setOnFirePackets(false); // maybe also play extinguish noise?
|
|
||||||
fireTicks = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean lava = type == org.bukkit.Material.LAVA;
|
|
||||||
|
|
||||||
if (lava || type == org.bukkit.Material.FIRE || type == Material.SOUL_FIRE) {
|
|
||||||
ignite();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invulnerableTime == 0) {
|
|
||||||
if (lava) {
|
|
||||||
hurt(DamageSource.LAVA, 4);
|
|
||||||
invulnerableTime = 20;//this used to be 12 ticks but that would cause the bot to take damage too quickly
|
|
||||||
} else if (fireTicks > 1) {
|
|
||||||
hurt(DamageSource.IN_FIRE, 1);
|
|
||||||
invulnerableTime = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fireTicks == 1) {
|
|
||||||
setOnFirePackets(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ignite() {
|
|
||||||
if (fireTicks <= 1) setOnFirePackets(true);
|
|
||||||
fireTicks = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOnFirePackets(boolean onFire) {
|
|
||||||
//entityData.set(new EntityDataAccessor<>(0, EntityDataSerializers.BYTE), onFire ? (byte) 1 : (byte) 0);
|
|
||||||
//sendPacket(new ClientboundSetEntityDataPacket(getId(), entityData, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID getTargetPlayer() {
|
public UUID getTargetPlayer() {
|
||||||
return targetPlayer;
|
return targetPlayer;
|
||||||
@@ -385,12 +353,12 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBotOnFire() {
|
public boolean isBotOnFire() {
|
||||||
return fireTicks != 0;
|
return this.isOnFire();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fallDamageCheck() { // TODO create a better bot event system in the future, also have bot.getAgent()
|
private void fallDamageCheck() { // TODO create a better bot event system in the future, also have bot.getAgent()
|
||||||
if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !BotUtils.NO_FALL.contains(getLocation().getBlock().getType())) {
|
if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !isFallBlocked()) {
|
||||||
BotFallDamageEvent event = new BotFallDamageEvent(this);
|
BotFallDamageEvent event = new BotFallDamageEvent(this, new ArrayList<>(getStandingOn()));
|
||||||
|
|
||||||
plugin.getManager().getAgent().onFallDamage(event);
|
plugin.getManager().getAgent().onFallDamage(event);
|
||||||
|
|
||||||
@@ -399,6 +367,33 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isFallBlocked() {
|
||||||
|
AABB box = getBoundingBox();
|
||||||
|
double[] xVals = new double[]{
|
||||||
|
box.minX,
|
||||||
|
box.maxX - 0.01
|
||||||
|
};
|
||||||
|
|
||||||
|
double[] zVals = new double[]{
|
||||||
|
box.minZ,
|
||||||
|
box.maxZ - 0.01
|
||||||
|
};
|
||||||
|
BoundingBox playerBox = new BoundingBox(box.minX, position().y - 0.01, box.minZ,
|
||||||
|
box.maxX, position().y + getBbHeight(), box.maxZ);
|
||||||
|
for (double x : xVals) {
|
||||||
|
for (double z : zVals) {
|
||||||
|
Location loc = new Location(getBukkitEntity().getWorld(), Math.floor(x), getLocation().getY(), Math.floor(z));
|
||||||
|
Block block = loc.getBlock();
|
||||||
|
if (block.getBlockData() instanceof Waterlogged wl && wl.isWaterlogged())
|
||||||
|
return true;
|
||||||
|
if (BotUtils.NO_FALL.contains(loc.getBlock().getType()) && (BotUtils.overlaps(playerBox, loc.getBlock().getBoundingBox())
|
||||||
|
|| loc.getBlock().getType() == Material.WATER || loc.getBlock().getType() == Material.LAVA))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFalling() {
|
public boolean isFalling() {
|
||||||
@@ -524,7 +519,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
World world = getBukkitEntity().getWorld();
|
return checkStandingOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkStandingOn() {
|
||||||
|
World world = getBukkitEntity().getWorld();
|
||||||
AABB box = getBoundingBox();
|
AABB box = getBoundingBox();
|
||||||
|
|
||||||
double[] xVals = new double[]{
|
double[] xVals = new double[]{
|
||||||
@@ -536,19 +535,55 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
box.minZ,
|
box.minZ,
|
||||||
box.maxZ
|
box.maxZ
|
||||||
};
|
};
|
||||||
|
BoundingBox playerBox = new BoundingBox(box.minX, position().y - 0.01, box.minZ,
|
||||||
|
box.maxX, position().y + getBbHeight(), box.maxZ);
|
||||||
|
List<Block> standingOn = new ArrayList<>();
|
||||||
|
List<Location> locations = new ArrayList<>();
|
||||||
|
|
||||||
for (double x : xVals) {
|
for (double x : xVals) {
|
||||||
for (double z : zVals) {
|
for (double z : zVals) {
|
||||||
Location loc = new Location(world, x, position().y - 0.01, z);
|
Location loc = new Location(world, x, position().y - 0.01, z);
|
||||||
Block block = world.getBlockAt(loc);
|
Block block = world.getBlockAt(loc);
|
||||||
|
|
||||||
if (block.getType().isSolid() && BotUtils.solidAt(loc)) {
|
if ((block.getType().isSolid() || LegacyMats.canStandOn(block.getType())) && BotUtils.overlaps(playerBox, block.getBoundingBox())) {
|
||||||
return true;
|
if (!locations.contains(block.getLocation())) {
|
||||||
|
standingOn.add(block);
|
||||||
|
locations.add(block.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fence/wall check
|
||||||
|
for (double x : xVals) {
|
||||||
|
for (double z : zVals) {
|
||||||
|
Location loc = new Location(world, x, position().y - 0.51, z);
|
||||||
|
Block block = world.getBlockAt(loc);
|
||||||
|
BoundingBox blockBox = loc.getBlock().getBoundingBox();
|
||||||
|
BoundingBox modifiedBox = new BoundingBox(blockBox.getMinX(), blockBox.getMinY(), blockBox.getMinZ(), blockBox.getMaxX(),
|
||||||
|
blockBox.getMinY() + 1.5, blockBox.getMaxZ());
|
||||||
|
|
||||||
|
if ((LegacyMats.FENCE.contains(block.getType()) || LegacyMats.GATES.contains(block.getType()))
|
||||||
|
&& block.getType().isSolid() && BotUtils.overlaps(playerBox, modifiedBox)) {
|
||||||
|
if (!locations.contains(block.getLocation())) {
|
||||||
|
standingOn.add(block);
|
||||||
|
locations.add(block.getLocation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
//Closest block comes first
|
||||||
|
Collections.sort(standingOn, (a, b) ->
|
||||||
|
Double.compare(BotUtils.getHorizSqDist(a.getLocation(), getLocation()), BotUtils.getHorizSqDist(b.getLocation(), getLocation())));
|
||||||
|
|
||||||
|
this.standingOn = standingOn;
|
||||||
|
return !standingOn.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Block> getStandingOn() {
|
||||||
|
return standingOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -581,6 +616,8 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
scheduler.runTask(plugin, () -> this.remove(RemovalReason.DISCARDED));
|
scheduler.runTask(plugin, () -> this.remove(RemovalReason.DISCARDED));
|
||||||
}
|
}
|
||||||
this.removeVisually();
|
this.removeVisually();
|
||||||
|
if (inPlayerList)
|
||||||
|
this.server.getPlayerList().getPlayers().remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeTab() {
|
private void removeTab() {
|
||||||
@@ -608,7 +645,7 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
// this should fix the concurrentmodificationexception mentioned above, I used the ConcurrentHashMap.newKeySet to make a "ConcurrentHashSet"
|
// this should fix the concurrentmodificationexception mentioned above, I used the ConcurrentHashMap.newKeySet to make a "ConcurrentHashSet"
|
||||||
plugin.getManager().remove(this);
|
plugin.getManager().remove(this);
|
||||||
|
|
||||||
scheduler.runTaskLater(plugin, this::setDead, 30);
|
scheduler.runTaskLater(plugin, this::removeBot, 20);
|
||||||
|
|
||||||
this.removeTab();
|
this.removeTab();
|
||||||
}
|
}
|
||||||
@@ -727,6 +764,11 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
public Location getLocation() {
|
public Location getLocation() {
|
||||||
return getBukkitEntity().getLocation();
|
return getBukkitEntity().getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BoundingBox getBotBoundingBox() {
|
||||||
|
return getBukkitEntity().getBoundingBox();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBotPitch(float pitch) {
|
public void setBotPitch(float pitch) {
|
||||||
@@ -841,25 +883,16 @@ public class Bot extends ServerPlayer implements Terminator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doTick() {
|
public void doTick() {
|
||||||
if (this.hurtTime > 0) {
|
|
||||||
this.hurtTime -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
baseTick();
|
baseTick();
|
||||||
tickEffects();
|
|
||||||
|
|
||||||
this.animStepO = (int) this.animStep;
|
|
||||||
this.yBodyRotO = this.yBodyRot;
|
|
||||||
this.yHeadRotO = this.yHeadRot;
|
|
||||||
this.yRotO = this.getYRot();
|
|
||||||
this.xRotO = this.getXRot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIgnoredByMobs() {
|
@Override
|
||||||
return ignoredByMobs;
|
public boolean isInPlayerList() {
|
||||||
|
return inPlayerList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIgnoredByMobs(boolean ignoredByMobs) {
|
@Override
|
||||||
this.ignoredByMobs = ignoredByMobs;
|
public World.Environment getDimension() {
|
||||||
|
return getBukkitEntity().getWorld().getEnvironment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,24 @@ public class BotManagerImpl implements BotManager, Listener {
|
|||||||
|
|
||||||
public boolean joinMessages = false;
|
public boolean joinMessages = false;
|
||||||
private boolean mobTarget = false;
|
private boolean mobTarget = false;
|
||||||
|
private boolean addPlayerList = false;
|
||||||
|
private Location spawnLoc;
|
||||||
|
|
||||||
public BotManagerImpl() {
|
public BotManagerImpl() {
|
||||||
this.agent = new LegacyAgent(this, TerminatorPlus.getInstance());
|
this.agent = new LegacyAgent(this, TerminatorPlus.getInstance());
|
||||||
this.bots = ConcurrentHashMap.newKeySet(); //should fix concurrentmodificationexception
|
this.bots = ConcurrentHashMap.newKeySet(); //should fix concurrentmodificationexception
|
||||||
this.numberFormat = NumberFormat.getInstance(Locale.US);
|
this.numberFormat = NumberFormat.getInstance(Locale.US);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Location getSpawnLoc() {
|
||||||
|
return spawnLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpawnLoc(Location loc) {
|
||||||
|
spawnLoc = loc;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Terminator> fetch() {
|
public Set<Terminator> fetch() {
|
||||||
@@ -56,7 +69,17 @@ public class BotManagerImpl implements BotManager, Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminator getFirst(String name) {
|
public Terminator getFirst(String name, Location target) {
|
||||||
|
if (target != null) {
|
||||||
|
Terminator closest = null;
|
||||||
|
for (Terminator bot : bots) {
|
||||||
|
if (name.equals(bot.getBotName()) && (closest == null
|
||||||
|
|| target.distanceSquared(bot.getLocation()) < target.distanceSquared(closest.getLocation()))) {
|
||||||
|
closest = bot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
for (Terminator bot : bots) {
|
for (Terminator bot : bots) {
|
||||||
if (name.equals(bot.getBotName())) {
|
if (name.equals(bot.getBotName())) {
|
||||||
return bot;
|
return bot;
|
||||||
@@ -98,7 +121,18 @@ public class BotManagerImpl implements BotManager, Listener {
|
|||||||
|
|
||||||
skinName = skinName == null ? name : skinName;
|
skinName = skinName == null ? name : skinName;
|
||||||
|
|
||||||
createBots(sender.getLocation(), name, MojangAPI.getSkin(skinName), n, network);
|
if (spawnLoc != null) {
|
||||||
|
sender.sendMessage("The spawn location is "
|
||||||
|
+ ChatColor.BLUE + String.format("(%s, %s, %s)", spawnLoc.getX(), spawnLoc.getY(), spawnLoc.getZ()) + ChatColor.RESET
|
||||||
|
+ ". This will be reset to the player location next time.");
|
||||||
|
Location loc = sender.getLocation().clone();
|
||||||
|
loc.setX(spawnLoc.getX());
|
||||||
|
loc.setY(spawnLoc.getY());
|
||||||
|
loc.setZ(spawnLoc.getZ());
|
||||||
|
createBots(loc, name, MojangAPI.getSkin(skinName), n, network);
|
||||||
|
spawnLoc = null;
|
||||||
|
} else
|
||||||
|
createBots(sender.getLocation(), name, MojangAPI.getSkin(skinName), n, network);
|
||||||
|
|
||||||
sender.sendMessage("Process completed (" + ChatColor.RED + ((System.currentTimeMillis() - timestamp) / 1000D) + "s" + ChatColor.RESET + ").");
|
sender.sendMessage("Process completed (" + ChatColor.RED + ((System.currentTimeMillis() - timestamp) / 1000D) + "s" + ChatColor.RESET + ").");
|
||||||
}
|
}
|
||||||
@@ -139,7 +173,6 @@ public class BotManagerImpl implements BotManager, Listener {
|
|||||||
} else if (i > 1) {
|
} else if (i > 1) {
|
||||||
bot.setVelocity(randomVelocity().multiply(f));
|
bot.setVelocity(randomVelocity().multiply(f));
|
||||||
}
|
}
|
||||||
bot.setIgnoredByMobs(!mobTarget);
|
|
||||||
|
|
||||||
bots.add(bot);
|
bots.add(bot);
|
||||||
i++;
|
i++;
|
||||||
@@ -164,7 +197,7 @@ public class BotManagerImpl implements BotManager, Listener {
|
|||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
if (!bots.isEmpty()) {
|
if (!bots.isEmpty()) {
|
||||||
bots.forEach(Terminator::removeVisually);
|
bots.forEach(Terminator::removeBot);
|
||||||
bots.clear(); // Not always necessary, but a good security measure
|
bots.clear(); // Not always necessary, but a good security measure
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +237,16 @@ public class BotManagerImpl implements BotManager, Listener {
|
|||||||
public void setMobTarget(boolean mobTarget) {
|
public void setMobTarget(boolean mobTarget) {
|
||||||
this.mobTarget = mobTarget;
|
this.mobTarget = mobTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addToPlayerList() {
|
||||||
|
return addPlayerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAddToPlayerList(boolean addPlayerList) {
|
||||||
|
this.addPlayerList = addPlayerList;
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onJoin(PlayerJoinEvent event) {
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
@@ -222,8 +265,10 @@ public class BotManagerImpl implements BotManager, Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onMobTarget(EntityTargetLivingEntityEvent event) {
|
public void onMobTarget(EntityTargetLivingEntityEvent event) {
|
||||||
Bot bot = (Bot) getBot(event.getEntity().getUniqueId());
|
if (mobTarget || event.getTarget() == null)
|
||||||
if (bot != null && bot.isIgnoredByMobs()) {
|
return;
|
||||||
|
Bot bot = (Bot) getBot(event.getTarget().getUniqueId());
|
||||||
|
if (bot != null) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.nuggetmc.tplus.command;
|
package net.nuggetmc.tplus.command;
|
||||||
|
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.nuggetmc.tplus.TerminatorPlus;
|
||||||
import net.nuggetmc.tplus.api.utils.ChatUtils;
|
import net.nuggetmc.tplus.api.utils.ChatUtils;
|
||||||
import net.nuggetmc.tplus.command.annotation.Arg;
|
import net.nuggetmc.tplus.command.annotation.Arg;
|
||||||
import net.nuggetmc.tplus.command.annotation.OptArg;
|
import net.nuggetmc.tplus.command.annotation.OptArg;
|
||||||
@@ -9,6 +9,7 @@ import net.nuggetmc.tplus.command.exception.ArgCountException;
|
|||||||
import net.nuggetmc.tplus.command.exception.ArgParseException;
|
import net.nuggetmc.tplus.command.exception.ArgParseException;
|
||||||
import net.nuggetmc.tplus.command.exception.NonPlayerException;
|
import net.nuggetmc.tplus.command.exception.NonPlayerException;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.defaults.BukkitCommand;
|
import org.bukkit.command.defaults.BukkitCommand;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -47,6 +48,12 @@ public abstract class CommandInstance extends BukkitCommand {
|
|||||||
@Override
|
@Override
|
||||||
public boolean execute(@Nonnull CommandSender sender, @Nonnull String label, @Nonnull String[] args) {
|
public boolean execute(@Nonnull CommandSender sender, @Nonnull String label, @Nonnull String[] args) {
|
||||||
if (!sender.hasPermission(MANAGE_PERMISSION)) {
|
if (!sender.hasPermission(MANAGE_PERMISSION)) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command. (Check if you are OP.)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!TerminatorPlus.isCorrectVersion()) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "You are not running the correct server version of Minecraft!");
|
||||||
|
sender.sendMessage(ChatColor.RED + "You are using MC server version " + TerminatorPlus.getMcVersion() + " but this plugin requires " + TerminatorPlus.REQUIRED_VERSION);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public class AICommand extends CommandInstance implements AIManager {
|
|||||||
|
|
||||||
scheduler.runTaskAsynchronously(plugin, () -> {
|
scheduler.runTaskAsynchronously(plugin, () -> {
|
||||||
try {
|
try {
|
||||||
Terminator bot = manager.getFirst(name);
|
Terminator bot = manager.getFirst(name, (sender instanceof Player pl) ? pl.getLocation() : null);
|
||||||
|
|
||||||
if (bot == null) {
|
if (bot == null) {
|
||||||
sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!");
|
sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!");
|
||||||
|
|||||||
@@ -22,10 +22,13 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class BotCommand extends CommandInstance {
|
public class BotCommand extends CommandInstance {
|
||||||
|
|
||||||
@@ -141,7 +144,6 @@ public class BotCommand extends CommandInstance {
|
|||||||
desc = "Gives all bots an armor set.",
|
desc = "Gives all bots an armor set.",
|
||||||
autofill = "armorAutofill"
|
autofill = "armorAutofill"
|
||||||
)
|
)
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void armor(CommandSender sender, @Arg("armor-tier") String armorTier) {
|
public void armor(CommandSender sender, @Arg("armor-tier") String armorTier) {
|
||||||
String tier = armorTier.toLowerCase();
|
String tier = armorTier.toLowerCase();
|
||||||
|
|
||||||
@@ -190,7 +192,7 @@ public class BotCommand extends CommandInstance {
|
|||||||
|
|
||||||
scheduler.runTaskAsynchronously(plugin, () -> {
|
scheduler.runTaskAsynchronously(plugin, () -> {
|
||||||
try {
|
try {
|
||||||
Terminator bot = manager.getFirst(name);
|
Terminator bot = manager.getFirst(name, (sender instanceof Player pl) ? pl.getLocation() : null);
|
||||||
|
|
||||||
if (bot == null) {
|
if (bot == null) {
|
||||||
sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!");
|
sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!");
|
||||||
@@ -211,7 +213,7 @@ public class BotCommand extends CommandInstance {
|
|||||||
String botName = bot.getBotName();
|
String botName = bot.getBotName();
|
||||||
String world = ChatColor.YELLOW + bot.getBukkitEntity().getWorld().getName();
|
String world = ChatColor.YELLOW + bot.getBukkitEntity().getWorld().getName();
|
||||||
Location loc = bot.getLocation();
|
Location loc = bot.getLocation();
|
||||||
String strLoc = ChatColor.YELLOW + formatter.format(loc.getBlockX()) + ", " + formatter.format(loc.getBlockY()) + ", " + formatter.format(loc.getBlockZ());
|
String strLoc = ChatColor.YELLOW + formatter.format(loc.getX()) + ", " + formatter.format(loc.getY()) + ", " + formatter.format(loc.getZ());
|
||||||
Vector vel = bot.getVelocity();
|
Vector vel = bot.getVelocity();
|
||||||
String strVel = ChatColor.AQUA + formatter.format(vel.getX()) + ", " + formatter.format(vel.getY()) + ", " + formatter.format(vel.getZ());
|
String strVel = ChatColor.AQUA + formatter.format(vel.getX()) + ", " + formatter.format(vel.getY()) + ", " + formatter.format(vel.getZ());
|
||||||
|
|
||||||
@@ -231,6 +233,23 @@ public class BotCommand extends CommandInstance {
|
|||||||
public List<String> infoAutofill(CommandSender sender, String[] args) {
|
public List<String> infoAutofill(CommandSender sender, String[] args) {
|
||||||
return args.length == 2 ? manager.fetchNames() : null;
|
return args.length == 2 ? manager.fetchNames() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
name = "count",
|
||||||
|
desc = "Counts the amount of bots on screen by name."
|
||||||
|
)
|
||||||
|
public void count(CommandSender sender) {
|
||||||
|
List<String> names = manager.fetchNames();
|
||||||
|
Map<String, Integer> freqMap = names.stream().collect(Collectors.toMap(s -> s, s -> 1, Integer::sum));
|
||||||
|
List<Entry<String, Integer>> entries = freqMap.entrySet().stream()
|
||||||
|
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
sender.sendMessage(ChatUtils.LINE);
|
||||||
|
entries.forEach(en -> sender.sendMessage(ChatColor.GREEN + en.getKey()
|
||||||
|
+ ChatColor.RESET + " - " + ChatColor.BLUE + en.getValue().toString() + ChatColor.RESET));
|
||||||
|
sender.sendMessage("Total bots: " + ChatColor.BLUE + freqMap.values().stream().reduce(0, Integer::sum) + ChatColor.RESET);
|
||||||
|
sender.sendMessage(ChatUtils.LINE);
|
||||||
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "reset",
|
name = "reset",
|
||||||
@@ -267,17 +286,68 @@ public class BotCommand extends CommandInstance {
|
|||||||
|
|
||||||
String extra = ChatColor.GRAY + " [" + ChatColor.YELLOW + "/bot settings" + ChatColor.GRAY + "]";
|
String extra = ChatColor.GRAY + " [" + ChatColor.YELLOW + "/bot settings" + ChatColor.GRAY + "]";
|
||||||
|
|
||||||
if (arg1 == null || ((!arg1.equalsIgnoreCase("setgoal")) && !arg1.equalsIgnoreCase("mobtarget") && !arg1.equalsIgnoreCase("playertarget"))) {
|
if (arg1 == null || (!arg1.equalsIgnoreCase("spawnloc") && !arg1.equalsIgnoreCase("setgoal") && !arg1.equalsIgnoreCase("mobtarget") && !arg1.equalsIgnoreCase("playertarget")
|
||||||
|
&& !arg1.equalsIgnoreCase("addplayerlist") && !arg1.equalsIgnoreCase("region"))) {
|
||||||
sender.sendMessage(ChatUtils.LINE);
|
sender.sendMessage(ChatUtils.LINE);
|
||||||
sender.sendMessage(ChatColor.GOLD + "Bot Settings" + extra);
|
sender.sendMessage(ChatColor.GOLD + "Bot Settings" + extra);
|
||||||
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "spawnloc" + ChatUtils.BULLET_FORMATTED + "Set the location where the bots should spawn. This will be reset after a spawn command is executed.");
|
||||||
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "setgoal" + ChatUtils.BULLET_FORMATTED + "Set the global bot target selection method.");
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "setgoal" + ChatUtils.BULLET_FORMATTED + "Set the global bot target selection method.");
|
||||||
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "mobtarget" + ChatUtils.BULLET_FORMATTED + "Allow all future bots spawned to be targeted by hostile mobs.");
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "mobtarget" + ChatUtils.BULLET_FORMATTED + "Allow all bots to be targeted by hostile mobs.");
|
||||||
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "playertarget" + ChatUtils.BULLET_FORMATTED + "Sets a player name for spawned bots to focus on if the goal is PLAYER.");
|
||||||
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "addplayerlist" + ChatUtils.BULLET_FORMATTED + "Adds newly spawned bots to the player list. This allows the bots to be affected by player selectors like @a and @p.");
|
||||||
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "region" + ChatUtils.BULLET_FORMATTED + "Sets a region for the bots to prioritize entities inside.");
|
||||||
sender.sendMessage(ChatUtils.LINE);
|
sender.sendMessage(ChatUtils.LINE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg1.equalsIgnoreCase("setgoal")) {
|
if (arg1.equalsIgnoreCase("spawnloc")) {
|
||||||
EnumTargetGoal goal = EnumTargetGoal.from(arg2 == null ? "" : arg2);
|
if (arg2 == null) {
|
||||||
|
if (manager.getSpawnLoc() == null)
|
||||||
|
sender.sendMessage("No custom spawn location has been set. The bots will spawn at the player location.");
|
||||||
|
else {
|
||||||
|
Location loc = manager.getSpawnLoc();
|
||||||
|
sender.sendMessage("The next spawn location will be at " + ChatColor.BLUE + String.format("(%s, %s, %s)", loc.getX(), loc.getY(), loc.getZ()) + ChatColor.RESET + ".");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (arg2.equalsIgnoreCase("clear")) {
|
||||||
|
manager.setSpawnLoc(null);
|
||||||
|
sender.sendMessage("The spawn location has been reset to the player location.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (arg2.equalsIgnoreCase("playerloc")) {
|
||||||
|
if (!(sender instanceof Player)) {
|
||||||
|
sender.sendMessage("You must be a player to do this!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Location loc = ((Player)sender).getLocation();
|
||||||
|
manager.setSpawnLoc(loc.clone());
|
||||||
|
sender.sendMessage("The spawn location has been set to " + ChatColor.BLUE + formatter.format(loc.getX()) + ", " + formatter.format(loc.getY()) + ", " + formatter.format(loc.getZ()) + ChatColor.RESET + ".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.size() != 4) {
|
||||||
|
sender.sendMessage("Incorrect argument size. Correct syntax: " + ChatColor.YELLOW + "/bot settings spawnloc <x> <y> <z>" + ChatColor.RESET);
|
||||||
|
sender.sendMessage("Additionally, to specify a spawnloc at the current player position: " + ChatColor.YELLOW + "/bot settings spawnloc playerloc" + ChatColor.RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double x, y, z;
|
||||||
|
try {
|
||||||
|
x = Double.parseDouble(args.get(1));
|
||||||
|
y = Double.parseDouble(args.get(2));
|
||||||
|
z = Double.parseDouble(args.get(3));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
sender.sendMessage("The block coordinates must be doubles!");
|
||||||
|
sender.sendMessage("Correct syntax: " + ChatColor.YELLOW + "/bot settings spawnloc <x> <y> <z>" + ChatColor.RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
manager.setSpawnLoc(new Location(null, x, y, z));
|
||||||
|
sender.sendMessage("The next spawn location has been set to " + ChatColor.BLUE + String.format("(%s, %s, %s)", x, y, z) + ChatColor.RESET + ".");
|
||||||
|
} else if (arg1.equalsIgnoreCase("setgoal")) {
|
||||||
|
if (arg2 == null) {
|
||||||
|
sender.sendMessage("The global bot goal is currently " + ChatColor.BLUE + agent.getTargetType() + ChatColor.RESET + ".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EnumTargetGoal goal = EnumTargetGoal.from(arg2);
|
||||||
|
|
||||||
if (goal == null) {
|
if (goal == null) {
|
||||||
sender.sendMessage(ChatUtils.LINE);
|
sender.sendMessage(ChatUtils.LINE);
|
||||||
@@ -290,14 +360,22 @@ public class BotCommand extends CommandInstance {
|
|||||||
agent.setTargetType(goal);
|
agent.setTargetType(goal);
|
||||||
sender.sendMessage("The global bot goal has been set to " + ChatColor.BLUE + goal.name() + ChatColor.RESET + ".");
|
sender.sendMessage("The global bot goal has been set to " + ChatColor.BLUE + goal.name() + ChatColor.RESET + ".");
|
||||||
} else if (arg1.equalsIgnoreCase("mobtarget")) {
|
} else if (arg1.equalsIgnoreCase("mobtarget")) {
|
||||||
manager.setMobTarget(!manager.isMobTarget());
|
if (arg2 == null) {
|
||||||
sender.sendMessage("Mob targeting is now " + (manager.isMobTarget() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ". (for all future bots)");
|
sender.sendMessage("Mob targeting is currently " + (manager.isMobTarget() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!arg2.equals("true") && !arg2.equals("false")) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "You must specify true or false!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
manager.setMobTarget(Boolean.parseBoolean(arg2));
|
||||||
|
sender.sendMessage("Mob targeting is now " + (manager.isMobTarget() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
|
||||||
} else if (arg1.equalsIgnoreCase("playertarget")) {
|
} else if (arg1.equalsIgnoreCase("playertarget")) {
|
||||||
if (args.size() < 2) {
|
if (args.size() < 2) {
|
||||||
sender.sendMessage(ChatColor.RED + "You must specify a player name!");
|
sender.sendMessage(ChatColor.RED + "You must specify a player name!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String playerName = args.get(1);
|
String playerName = arg2;
|
||||||
Player player = Bukkit.getPlayer(playerName);
|
Player player = Bukkit.getPlayer(playerName);
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
sender.sendMessage(ChatColor.RED + "Could not find player " + ChatColor.YELLOW + playerName + ChatColor.RED + "!");
|
sender.sendMessage(ChatColor.RED + "Could not find player " + ChatColor.YELLOW + playerName + ChatColor.RED + "!");
|
||||||
@@ -307,6 +385,88 @@ public class BotCommand extends CommandInstance {
|
|||||||
fetch.setTargetPlayer(player.getUniqueId());
|
fetch.setTargetPlayer(player.getUniqueId());
|
||||||
}
|
}
|
||||||
sender.sendMessage("All spawned bots are now set to target " + ChatColor.BLUE + player.getName() + ChatColor.RESET + ". They will target the closest player if they can't be found.\nYou may need to set the goal to PLAYER.");
|
sender.sendMessage("All spawned bots are now set to target " + ChatColor.BLUE + player.getName() + ChatColor.RESET + ". They will target the closest player if they can't be found.\nYou may need to set the goal to PLAYER.");
|
||||||
|
} else if (arg1.equalsIgnoreCase("addplayerlist")) {
|
||||||
|
if (arg2 == null) {
|
||||||
|
sender.sendMessage("Adding bots to the player list is currently " + (manager.addToPlayerList() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!arg2.equals("true") && !arg2.equals("false")) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "You must specify true or false!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
manager.setAddToPlayerList(Boolean.parseBoolean(arg2));
|
||||||
|
sender.sendMessage("Adding bots to the player list is now " + (manager.addToPlayerList() ? ChatColor.GREEN + "enabled" : ChatColor.RED + "disabled") + ChatColor.RESET + ".");
|
||||||
|
} else if (arg1.equalsIgnoreCase("region")) {
|
||||||
|
if (arg2 == null) {
|
||||||
|
if (agent.getRegion() == null) {
|
||||||
|
sender.sendMessage("No region has been set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sender.sendMessage("The current region is " + ChatColor.BLUE + agent.getRegion() + ChatColor.RESET + ".");
|
||||||
|
if (agent.getRegionWeightX() == 0 && agent.getRegionWeightY() == 0 && agent.getRegionWeightZ() == 0)
|
||||||
|
sender.sendMessage("Entities out of range will not be targeted.");
|
||||||
|
else {
|
||||||
|
sender.sendMessage("The region X weight is " + ChatColor.BLUE + agent.getRegionWeightX() + ChatColor.RESET + ".");
|
||||||
|
sender.sendMessage("The region Y weight is " + ChatColor.BLUE + agent.getRegionWeightY() + ChatColor.RESET + ".");
|
||||||
|
sender.sendMessage("The region Z weight is " + ChatColor.BLUE + agent.getRegionWeightZ() + ChatColor.RESET + ".");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (arg2.equalsIgnoreCase("clear")) {
|
||||||
|
agent.setRegion(null, 0, 0, 0);
|
||||||
|
sender.sendMessage("The region has been cleared.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean strict = args.size() == 8 && args.get(7).equalsIgnoreCase("strict");
|
||||||
|
if (args.size() != 10 && !strict) {
|
||||||
|
sender.sendMessage(ChatUtils.LINE);
|
||||||
|
sender.sendMessage(ChatColor.GOLD + "Bot Region Settings" + extra);
|
||||||
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "<x1> <y1> <z1> <x2> <y2> <z2> <wX> <wY> <wZ>" + ChatUtils.BULLET_FORMATTED
|
||||||
|
+ "Sets a region for bots to prioritize entities within.");
|
||||||
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "<x1> <y1> <z1> <x2> <y2> <z2> strict" + ChatUtils.BULLET_FORMATTED
|
||||||
|
+ "Sets a region so that the bots only target entities within the region.");
|
||||||
|
sender.sendMessage(ChatUtils.BULLET_FORMATTED + ChatColor.YELLOW + "clear" + ChatUtils.BULLET_FORMATTED
|
||||||
|
+ "Clears the region.");
|
||||||
|
sender.sendMessage("Without strict mode, the entity distance from the region is multiplied by the weight values if outside the region.");
|
||||||
|
sender.sendMessage("The resulting value is added to the entity distance when selecting an entity.");
|
||||||
|
sender.sendMessage(ChatUtils.LINE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double x1, y1, z1, x2, y2, z2, wX, wY, wZ;
|
||||||
|
try {
|
||||||
|
Location loc = sender instanceof Player pl ? pl.getLocation() : null;
|
||||||
|
x1 = parseDoubleOrRelative(args.get(1), loc, 0);
|
||||||
|
y1 = parseDoubleOrRelative(args.get(2), loc, 1);
|
||||||
|
z1 = parseDoubleOrRelative(args.get(3), loc, 2);
|
||||||
|
x2 = parseDoubleOrRelative(args.get(4), loc, 0);
|
||||||
|
y2 = parseDoubleOrRelative(args.get(5), loc, 1);
|
||||||
|
z2 = parseDoubleOrRelative(args.get(6), loc, 2);
|
||||||
|
if (strict)
|
||||||
|
wX = wY = wZ = 0;
|
||||||
|
else {
|
||||||
|
wX = Double.parseDouble(args.get(7));
|
||||||
|
wY = Double.parseDouble(args.get(8));
|
||||||
|
wZ = Double.parseDouble(args.get(9));
|
||||||
|
if (wX <= 0 || wY <= 0 || wZ <= 0) {
|
||||||
|
sender.sendMessage("The region weights must be positive values!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
sender.sendMessage("The region bounds and weights must be valid numbers!");
|
||||||
|
sender.sendMessage("Correct syntax: " + ChatColor.YELLOW + "/bot settings region <x1> <y1> <z1> <x2> <y2> <z2> <wX> <wY> <wZ>"
|
||||||
|
+ ChatColor.RESET);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
agent.setRegion(new BoundingBox(x1, y1, z1, x2, y2, z2), wX, wY, wZ);
|
||||||
|
sender.sendMessage("The region has been set to " + ChatColor.BLUE + agent.getRegion() + ChatColor.RESET + ".");
|
||||||
|
if (wX == 0 && wY == 0 && wZ == 0)
|
||||||
|
sender.sendMessage("Entities out of range will not be targeted.");
|
||||||
|
else {
|
||||||
|
sender.sendMessage("The region X weight is " + ChatColor.BLUE + agent.getRegionWeightX() + ChatColor.RESET + ".");
|
||||||
|
sender.sendMessage("The region Y weight is " + ChatColor.BLUE + agent.getRegionWeightY() + ChatColor.RESET + ".");
|
||||||
|
sender.sendMessage("The region Z weight is " + ChatColor.BLUE + agent.getRegionWeightZ() + ChatColor.RESET + ".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,8 +483,12 @@ public class BotCommand extends CommandInstance {
|
|||||||
// lookall
|
// lookall
|
||||||
|
|
||||||
if (args.length == 2) {
|
if (args.length == 2) {
|
||||||
|
output.add("spawnloc");
|
||||||
output.add("setgoal");
|
output.add("setgoal");
|
||||||
output.add("mobtarget");
|
output.add("mobtarget");
|
||||||
|
output.add("playertarget");
|
||||||
|
output.add("addplayerlist");
|
||||||
|
output.add("region");
|
||||||
} else if (args.length == 3) {
|
} else if (args.length == 3) {
|
||||||
if (args[1].equalsIgnoreCase("setgoal")) {
|
if (args[1].equalsIgnoreCase("setgoal")) {
|
||||||
Arrays.stream(EnumTargetGoal.values()).forEach(goal -> output.add(goal.name().replace("_", "").toLowerCase()));
|
Arrays.stream(EnumTargetGoal.values()).forEach(goal -> output.add(goal.name().replace("_", "").toLowerCase()));
|
||||||
@@ -333,6 +497,15 @@ public class BotCommand extends CommandInstance {
|
|||||||
output.add("true");
|
output.add("true");
|
||||||
output.add("false");
|
output.add("false");
|
||||||
}
|
}
|
||||||
|
if (args[1].equalsIgnoreCase("playertarget")) {
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
output.add(player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args[1].equalsIgnoreCase("addplayerlist")) {
|
||||||
|
output.add("true");
|
||||||
|
output.add("false");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
@@ -346,4 +519,20 @@ public class BotCommand extends CommandInstance {
|
|||||||
public void debug(CommandSender sender, @Arg("expression") String expression) {
|
public void debug(CommandSender sender, @Arg("expression") String expression) {
|
||||||
new Debugger(sender).execute(expression);
|
new Debugger(sender).execute(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double parseDoubleOrRelative(String pos, Location loc, int type) {
|
||||||
|
if (loc == null || pos.length() == 0 || pos.charAt(0) != '~')
|
||||||
|
return Double.parseDouble(pos);
|
||||||
|
double relative = Double.parseDouble(pos.substring(1));
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
return relative + Math.round(loc.getX() * 1000) / 1000D;
|
||||||
|
case 1:
|
||||||
|
return relative + Math.round(loc.getY() * 1000) / 1000D;
|
||||||
|
case 2:
|
||||||
|
return relative + Math.round(loc.getZ() * 1000) / 1000D;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,12 @@ import net.nuggetmc.tplus.api.utils.ChatUtils;
|
|||||||
import net.nuggetmc.tplus.command.CommandHandler;
|
import net.nuggetmc.tplus.command.CommandHandler;
|
||||||
import net.nuggetmc.tplus.command.CommandInstance;
|
import net.nuggetmc.tplus.command.CommandInstance;
|
||||||
import net.nuggetmc.tplus.command.annotation.Command;
|
import net.nuggetmc.tplus.command.annotation.Command;
|
||||||
|
import net.nuggetmc.tplus.utils.MCLogs;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class MainCommand extends CommandInstance {
|
public class MainCommand extends CommandInstance {
|
||||||
|
|
||||||
private BaseComponent[] rootInfo;
|
private BaseComponent[] rootInfo;
|
||||||
@@ -29,6 +32,23 @@ public class MainCommand extends CommandInstance {
|
|||||||
|
|
||||||
sender.spigot().sendMessage(rootInfo);
|
sender.spigot().sendMessage(rootInfo);
|
||||||
}
|
}
|
||||||
|
@Command(
|
||||||
|
name = "debuginfo",
|
||||||
|
desc = "Upload debug info to mclo.gs"
|
||||||
|
)
|
||||||
|
public void debugInfo(CommandSender sender) {
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Uploading debug info to mclogs...");
|
||||||
|
String url = null;
|
||||||
|
try {
|
||||||
|
url = MCLogs.postInfo();
|
||||||
|
} catch (IOException e) {
|
||||||
|
String error = e.getMessage();
|
||||||
|
sender.sendMessage(ChatColor.RED + "Failed to upload debug info to mclogs: " + error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sender.sendMessage(ChatColor.GREEN + "Debug info uploaded to " + url);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void rootInfoSetup() {
|
private void rootInfoSetup() {
|
||||||
ComponentBuilder message = new ComponentBuilder();
|
ComponentBuilder message = new ComponentBuilder();
|
||||||
@@ -46,7 +66,7 @@ public class MainCommand extends CommandInstance {
|
|||||||
message.event((ClickEvent) null);
|
message.event((ClickEvent) null);
|
||||||
message.event((HoverEvent) null);
|
message.event((HoverEvent) null);
|
||||||
message.append(ChatColor.BLUE + "Discord");
|
message.append(ChatColor.BLUE + "Discord");
|
||||||
message.event(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://discord.gg/horsenuggets"));
|
message.event(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://discord.gg/vZVSf2D6mz"));
|
||||||
message.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click to visit HorseNuggets' " + ChatColor.BLUE + "Discord" + ChatColor.RESET + "!")));
|
message.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("Click to visit HorseNuggets' " + ChatColor.BLUE + "Discord" + ChatColor.RESET + "!")));
|
||||||
message.append("\n");
|
message.append("\n");
|
||||||
message.event((ClickEvent) null);
|
message.event((ClickEvent) null);
|
||||||
|
|||||||
@@ -365,10 +365,6 @@ public class Debugger {
|
|||||||
print("This has been established as a feature as \"" + ChatColor.AQUA + "/bot settings setgoal" + ChatColor.RESET + "\"!");
|
print("This has been established as a feature as \"" + ChatColor.AQUA + "/bot settings setgoal" + ChatColor.RESET + "\"!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fire(boolean b) {
|
|
||||||
TerminatorPlus.getInstance().getManager().fetch().forEach(bot -> bot.setOnFirePackets(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void trackYVel() {
|
public void trackYVel() {
|
||||||
if (!(sender instanceof Player)) return;
|
if (!(sender instanceof Player)) return;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package net.nuggetmc.tplus.utils;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import net.nuggetmc.tplus.TerminatorPlus;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for debug logs.
|
||||||
|
*/
|
||||||
|
public class MCLogs {
|
||||||
|
|
||||||
|
private static final String FORMAT =
|
||||||
|
"""
|
||||||
|
====== TERMINATOR PLUS DEBUG INFO ======
|
||||||
|
Plugin Version: %s
|
||||||
|
Server Version: %s
|
||||||
|
Server Software: %s
|
||||||
|
Server Plugins: %s
|
||||||
|
Server TPS: %s
|
||||||
|
Server Memory: %s
|
||||||
|
|
||||||
|
Correct Version: %s
|
||||||
|
Required Version: %s
|
||||||
|
====== TERMINATOR PLUS DEBUG INFO ======
|
||||||
|
""";
|
||||||
|
|
||||||
|
public static String postInfo() throws IOException {
|
||||||
|
String serverVersion = Bukkit.getVersion();
|
||||||
|
String pluginVersion = TerminatorPlus.getVersion();
|
||||||
|
String serverSoftware = Bukkit.getName();
|
||||||
|
String serverPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(plugin -> plugin.getName() + " v" + plugin.getDescription().getVersion()).reduce((s, s2) -> s + ", " + s2).orElse("No plugins");
|
||||||
|
String serverTPS = Arrays.stream(Bukkit.getTPS()).mapToObj(tps -> String.format("%.2f", tps)).reduce((s, s2) -> s + ", " + s2).orElse("No TPS");
|
||||||
|
String serverMemory = String.format("%.2f", (double) (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024) + "MB";
|
||||||
|
|
||||||
|
String info = String.format(FORMAT, pluginVersion, serverVersion, serverSoftware, serverPlugins, serverTPS, serverMemory, TerminatorPlus.isCorrectVersion(), TerminatorPlus.REQUIRED_VERSION);
|
||||||
|
return pasteText(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String pasteText(String text) throws IOException {
|
||||||
|
URL url = new URL("https://api.mclo.gs/1/log"); // application/x-www-form-urlencoded
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
|
||||||
|
try (OutputStream os = connection.getOutputStream()) {
|
||||||
|
os.write(("content=" + text).getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
String response = new BufferedReader(new InputStreamReader(connection.getInputStream())).readLine();
|
||||||
|
JsonObject json = JsonParser.parseString(response).getAsJsonObject();
|
||||||
|
return json.get("url").getAsString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "net.nuggetmc"
|
group = "net.nuggetmc"
|
||||||
version = "3.2-BETA"
|
version = "3.3.1-BETA"
|
||||||
|
|
||||||
val jarName = "TerminatorPlus-" + version;
|
val jarName = "TerminatorPlus-" + version;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: TerminatorPlus
|
name: TerminatorPlus
|
||||||
main: net.nuggetmc.tplus.TerminatorPlus
|
main: net.nuggetmc.tplus.TerminatorPlus
|
||||||
version: ${version}
|
version: ${version}
|
||||||
api-version: 1.16
|
api-version: 1.16 # Set to 1.16 so the plugin loads, and we can tell the user that it may not be compatible with their version, because people can't scroll up.
|
||||||
author: HorseNuggets
|
author: HorseNuggets
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
Reference in New Issue
Block a user