ObamaRuntz x GitGodGuap
Sponsored by the shadow government
This commit is contained in:
parent
788ed14efa
commit
4d9cae9cd9
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>Azurite1.19</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.24</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-1.19</artifactId>
|
||||
<version>1.19</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/1.19.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>Azurite</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,145 @@
|
|||
package me.keano.azurite.modules.nametags.packet.type;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.nametags.NametagManager;
|
||||
import me.keano.azurite.modules.nametags.extra.NameInfo;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.nametags.packet.NametagPacket;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.EnumChatFormat;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.ScoreboardTeam;
|
||||
import net.minecraft.world.scores.ScoreboardTeamBase;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class NametagPacketV1_19_R3 extends NametagPacket {
|
||||
|
||||
private static final Field a = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "a");
|
||||
private static final Field b = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "b");
|
||||
private static final Field c = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "c");
|
||||
private static final Field d = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "d");
|
||||
private static final Field e = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "e");
|
||||
private static final Field f = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "f");
|
||||
private static final Field g = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "g");
|
||||
private static final Constructor<?> PACKET_SCORE_BOARD_CONSTRUCTOR = ReflectionUtils.accessConstructor(PacketPlayOutScoreboardTeam.class, 0);
|
||||
private static final ScoreboardTeam EMPTY_TEAM = new ScoreboardTeam(new Scoreboard(), "empty");
|
||||
|
||||
private static final Map<String, EnumChatFormat> FORMATS = Arrays
|
||||
.stream(EnumChatFormat.values())
|
||||
.collect(Collectors.toMap(EnumChatFormat::toString, e -> e));
|
||||
|
||||
private final Map<String, NameInfo> teams;
|
||||
private final Map<String, String> teamsByPlayer;
|
||||
|
||||
public NametagPacketV1_19_R3(NametagManager manager, Player player) {
|
||||
super(manager, player);
|
||||
this.teams = new ConcurrentHashMap<>();
|
||||
this.teamsByPlayer = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) { // Packet type is unknown 1.8+
|
||||
((CraftPlayer) player).getHandle().b.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToTeam(Player player, String name) {
|
||||
String currentTeam = teamsByPlayer.get(player.getName());
|
||||
NameInfo info = teams.get(name);
|
||||
|
||||
if (currentTeam != null && currentTeam.equals(name)) return;
|
||||
if (info == null) return;
|
||||
|
||||
teamsByPlayer.put(player.getName(), name);
|
||||
sendPacket(new ScoreboardPacket(info, 3, player).toPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
for (NameInfo info : teams.values()) {
|
||||
sendPacket(new ScoreboardPacket(info, 1).toPacket());
|
||||
}
|
||||
|
||||
teams.clear();
|
||||
teamsByPlayer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String name, String color, String prefix, String suffix, boolean friendlyInvis, NameVisibility visibility) {
|
||||
NameInfo current = teams.get(name);
|
||||
|
||||
if (current != null) {
|
||||
if (!current.getColor().equals(color) || !current.getPrefix().equals(prefix) || !current.getSuffix().equals(suffix)) {
|
||||
NameInfo newInfo = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, newInfo);
|
||||
sendPacket(new ScoreboardPacket(newInfo, 2).toPacket());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NameInfo info = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, info);
|
||||
sendPacket(new ScoreboardPacket(info, 0).toPacket());
|
||||
}
|
||||
|
||||
private static class ScoreboardPacket {
|
||||
|
||||
private final NameInfo info;
|
||||
private final Player target;
|
||||
private final int action;
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = null;
|
||||
}
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action, Player target) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public PacketPlayOutScoreboardTeam toPacket() {
|
||||
PacketPlayOutScoreboardTeam.b subPacket = new PacketPlayOutScoreboardTeam.b(EMPTY_TEAM);
|
||||
|
||||
a.set(subPacket, CraftChatMessage.fromString(info.getName())[0]);
|
||||
b.set(subPacket, CraftChatMessage.fromString(info.getPrefix())[0]);
|
||||
c.set(subPacket, CraftChatMessage.fromString(info.getSuffix())[0]);
|
||||
d.set(subPacket, info.getVisibility().getName());
|
||||
e.set(subPacket, ScoreboardTeamBase.EnumTeamPush.b.e);
|
||||
f.set(subPacket, getFormat(info.getColor()));
|
||||
g.set(subPacket, info.isFriendlyInvis() ? 3 : 0);
|
||||
|
||||
return (PacketPlayOutScoreboardTeam) PACKET_SCORE_BOARD_CONSTRUCTOR.newInstance(
|
||||
info.getName(), action,
|
||||
Optional.of(subPacket),
|
||||
(target != null ? Collections.singleton(target.getName()) : Collections.emptySet())
|
||||
);
|
||||
}
|
||||
|
||||
public EnumChatFormat getFormat(String string) {
|
||||
EnumChatFormat format = FORMATS.get(string);
|
||||
return format == null ? EnumChatFormat.v : format;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package me.keano.azurite.modules.tablist.packet.type;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import me.keano.azurite.modules.tablist.Tablist;
|
||||
import me.keano.azurite.modules.tablist.TablistManager;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistEntry;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.tablist.packet.TablistPacket;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.PlayerConnection;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TablistPacketV1_19_R3 extends TablistPacket {
|
||||
|
||||
private final Table<Integer, Integer, EntityPlayer> fakePlayers;
|
||||
private final int maxColumns;
|
||||
|
||||
// Cache them to see if we don't have to send a packet again.
|
||||
private String header;
|
||||
private String footer;
|
||||
|
||||
public TablistPacketV1_19_R3(TablistManager manager, Player player) {
|
||||
super(manager, player);
|
||||
|
||||
this.fakePlayers = HashBasedTable.create();
|
||||
this.header = "";
|
||||
this.footer = "";
|
||||
this.maxColumns = (Utils.getProtocolVersion(player) <= 5 ? 3 : 4);
|
||||
|
||||
this.loadFakes();
|
||||
this.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
this.sendHeaderFooter();
|
||||
|
||||
Tablist tablist = getManager().getAdapter().getInfo(player);
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
TablistEntry entry = tablist.getEntry(col, row);
|
||||
TablistSkin newSkin = entry.getSkin();
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
|
||||
if (fake == null) continue;
|
||||
|
||||
if (fake.e != entry.getPing()) {
|
||||
fake.e = entry.getPing();
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.e, fake));
|
||||
}
|
||||
|
||||
if (newSkin == null) {
|
||||
newSkin = getManager().getDefaultSkins().get(col, row);
|
||||
}
|
||||
|
||||
updateSkin(fake, newSkin);
|
||||
handleTeams(fake.getBukkitEntity(), entry.getText(), calcSlot(col, row));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSkin(EntityPlayer fake, TablistSkin skin) {
|
||||
GameProfile profile = fake.fI();
|
||||
Property old = profile.getProperties().get("textures").stream().findFirst().orElse(null);
|
||||
|
||||
// Verify if we should update
|
||||
if (old != null && old.getValue().equals(skin.getValue()) && old.getSignature().equals(skin.getSignature())) {
|
||||
return;
|
||||
}
|
||||
|
||||
profile.getProperties().clear();
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(profile.getId())));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.e, fake));
|
||||
}
|
||||
|
||||
private void loadFakes() {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
WorldServer worldServer = server.F().iterator().next();
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < 4; col++) {
|
||||
GameProfile profile = new GameProfile(UUID.randomUUID(), getName(col, row));
|
||||
EntityPlayer fake = new EntityPlayer(server, worldServer, profile);
|
||||
TablistSkin skin = getManager().getDefaultSkins().get(col, row);
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
fakePlayers.put(col, row, fake);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
if (fake == null) continue;
|
||||
// Some reason u have to send an add_packet and then following it with update display name.
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) {
|
||||
PlayerConnection connection = ((CraftPlayer) player).getHandle().b;
|
||||
connection.a(packet);
|
||||
}
|
||||
|
||||
private void sendHeaderFooter() {
|
||||
String headerJoined = String.join("\n", getManager().getAdapter().getHeader(player));
|
||||
String footerJoined = String.join("\n", getManager().getAdapter().getFooter(player));
|
||||
|
||||
// Refrain sending a packet again if same.
|
||||
if (footer.equals(headerJoined) && header.equals(headerJoined)) return;
|
||||
|
||||
this.header = headerJoined;
|
||||
this.footer = footerJoined;
|
||||
|
||||
PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(
|
||||
CraftChatMessage.fromJSONOrString(headerJoined, true),
|
||||
CraftChatMessage.fromJSONOrString(footerJoined, true)
|
||||
);
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,367 @@
|
|||
package me.keano.azurite.modules.versions.type;
|
||||
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.type.InvisibilityAbility;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.loggers.Logger;
|
||||
import me.keano.azurite.modules.nametags.Nametag;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostClass;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.versions.Version;
|
||||
import me.keano.azurite.modules.versions.VersionManager;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.core.BlockPosition;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.PlayerChunkMap;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EnumItemSlot;
|
||||
import net.minecraft.world.level.block.entity.TileEntity;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.util.CraftChatMessage;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityPotionEffectEvent;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class Version1_19_R3 extends Module<VersionManager> implements Version {
|
||||
|
||||
private static final Field ENTITY_ID = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "b");
|
||||
private static final Field SLOT = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "c");
|
||||
private static final Field ACTION = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "a");
|
||||
private static final Field DATA = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "b");
|
||||
private static final Field ENTITY_LOOKUP = ReflectionUtils.accessField(WorldServer.class, "entityLookup");
|
||||
|
||||
private static final Method ENTITY_GET = ReflectionUtils.accessMethod(
|
||||
ReflectionUtils.getClass("io.papermc.paper.chunk.system.entity.EntityLookup"), "get", int.class);
|
||||
|
||||
private static final Method SPAWN_PARTICLE = ReflectionUtils.accessMethod(
|
||||
CraftWorld.class, "spawnParticle", Particle.class, Location.class, int.class, Object.class
|
||||
);
|
||||
|
||||
public Version1_19_R3(VersionManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandMap getCommandMap() {
|
||||
try {
|
||||
|
||||
CraftServer server = (CraftServer) Bukkit.getServer();
|
||||
Method method = server.getClass().getMethod("getCommandMap");
|
||||
return (CommandMap) method.invoke(server);
|
||||
|
||||
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public Set<Player> getTrackedPlayers(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
|
||||
|
||||
if (tracker != null) {
|
||||
Set<Player> players = new HashSet<>();
|
||||
|
||||
for (ServerPlayerConnection connection : tracker.f) {
|
||||
players.add(connection.f().getBukkitEntity());
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotGapple(ItemStack item) {
|
||||
return item.getType() != Material.ENCHANTED_GOLDEN_APPLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
return craftPlayer.getHandle().e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand(Player player) {
|
||||
try {
|
||||
|
||||
Method method = player.getInventory().getClass().getMethod("getItemInMainHand");
|
||||
return (ItemStack) method.invoke(player.getInventory());
|
||||
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack addGlow(ItemStack itemStack) {
|
||||
itemStack.addUnsafeEnchantment(Enchantment.WATER_WORKER, 1);
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
itemStack.setItemMeta(meta);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInHand(Player player, ItemStack item) {
|
||||
try {
|
||||
|
||||
Method method = player.getInventory().getClass().getMethod("setItemInMainHand", ItemStack.class);
|
||||
method.invoke(player.getInventory(), item);
|
||||
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLoggerDeath(Logger logger) {
|
||||
EntityPlayer player = ((CraftPlayer) logger.getPlayer()).getHandle();
|
||||
player.getBukkitEntity().getInventory().clear();
|
||||
player.getBukkitEntity().getInventory().setArmorContents(null);
|
||||
player.getBukkitEntity().setHealth(0);
|
||||
player.getBukkitEntity().setExp(0.0F);
|
||||
player.removeAllEffects(EntityPotionEffectEvent.Cause.DEATH);
|
||||
player.getBukkitEntity().saveData(); // Save the inventory and everything we just modified
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEffect(Location location, String name, Object data) {
|
||||
try {
|
||||
|
||||
Particle particle = Particle.valueOf(name);
|
||||
SPAWN_PARTICLE.invoke(location.getWorld(), particle, location, 1, data);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Particle " + name + " does not exist.");
|
||||
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTPSColored() {
|
||||
double tps = MinecraftServer.getServer().recentTps[0];
|
||||
String color = (tps > 18 ? "§a" : tps > 16 ? "§e" : "§c");
|
||||
String asterisk = (tps > 20 ? "*" : "");
|
||||
return color + asterisk + Math.min(Math.round(tps * 100.0) / 100.0, 20.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
|
||||
|
||||
if (tracker != null) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(null)));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
|
||||
|
||||
if (tracker != null) {
|
||||
org.bukkit.inventory.PlayerInventory inventory = player.getInventory();
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(inventory.getBoots())));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(inventory.getLeggings())));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(inventory.getChestplate())));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(inventory.getHelmet())));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleNettyListener(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
ChannelPipeline pipeline = entityPlayer.b.h.m.pipeline();
|
||||
AbilityManager abilityManager = getInstance().getAbilityManager();
|
||||
InvisibilityAbility ability = (InvisibilityAbility) abilityManager.getAbility("Invisibility");
|
||||
GhostClass ghostClass = getInstance().getClassManager().getGhostClass();
|
||||
|
||||
if (pipeline.get("packet_handler") == null) {
|
||||
player.kickPlayer(Config.COULD_NOT_LOAD_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline.addBefore("packet_handler", "Azurite", new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
if (msg instanceof PacketPlayOutEntityEquipment packet) {
|
||||
WorldServer server = ((CraftWorld) player.getWorld()).getHandle();
|
||||
Entity entity = (Entity) ENTITY_GET.invoke(ENTITY_LOOKUP.get(server), (int) ENTITY_ID.get(packet));
|
||||
|
||||
if (entity != null) {
|
||||
if (ghostClass != null && ghostClass.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().e()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().e()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (msg instanceof ClientboundPlayerInfoUpdatePacket) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) msg;
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.a> actions = (EnumSet<ClientboundPlayerInfoUpdatePacket.a>) ACTION.get(packet);
|
||||
Nametag nametag = getInstance().getNametagManager().getNametags().get(player.getUniqueId());
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.a action : actions) {
|
||||
if (action == ClientboundPlayerInfoUpdatePacket.a.a && nametag != null) {
|
||||
List<ClientboundPlayerInfoUpdatePacket.b> data = (List<ClientboundPlayerInfoUpdatePacket.b>) DATA.get(packet);
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.b info : data) {
|
||||
Player targetPlayer = Bukkit.getPlayer(info.a());
|
||||
|
||||
if (targetPlayer == null) continue;
|
||||
|
||||
// Make tablist sort instantly
|
||||
nametag.getPacket().create("tablist", "", "", "", false, NameVisibility.ALWAYS);
|
||||
nametag.getPacket().addToTeam(targetPlayer, "tablist");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(Player player, String string) {
|
||||
ClientboundSetActionBarTextPacket packet = new ClientboundSetActionBarTextPacket(CraftChatMessage.fromJSONOrString(string, true));
|
||||
((CraftPlayer) player).getHandle().b.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToServer(Player player, String server) {
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
out.writeUTF("Connect");
|
||||
out.writeUTF(server);
|
||||
player.sendPluginMessage(getInstance(), "BungeeCord", out.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearArrows(Player player) {
|
||||
((CraftPlayer) player).getHandle().setArrowCount(0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getBlockDrops(Player pl, Block bl, ItemStack hand) {
|
||||
EntityPlayer serverPlayer = ((CraftPlayer) pl).getHandle();
|
||||
WorldServer serverLevel = serverPlayer.cG().getMinecraftWorld();
|
||||
BlockPosition blockPos = new BlockPosition(bl.getX(), bl.getY(), bl.getZ());
|
||||
IBlockData blockState = serverLevel.a_(blockPos);
|
||||
TileEntity blockEntity = serverLevel.c_(blockPos);
|
||||
|
||||
return net.minecraft.world.level.block.Block.a(blockState, serverLevel, blockPos, blockEntity, serverPlayer, serverPlayer.fJ().f())
|
||||
.stream().map(CraftItemStack::asBukkitCopy).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TablistSkin getSkinData(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
GameProfile profile = entityPlayer.fI();
|
||||
|
||||
if (profile.getProperties().get("textures").size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Property property = profile.getProperties().get("textures").iterator().next();
|
||||
return new TablistSkin(property.getValue(), property.getSignature());
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>Azurite1.20</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.24</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-1.20</artifactId>
|
||||
<version>1.20</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/1.20.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>Azurite</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,155 @@
|
|||
package me.keano.azurite.modules.nametags.packet.type;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.nametags.NametagManager;
|
||||
import me.keano.azurite.modules.nametags.extra.NameInfo;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.nametags.packet.NametagPacket;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.EnumChatFormat;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.ScoreboardTeam;
|
||||
import net.minecraft.world.scores.ScoreboardTeamBase;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class NametagPacketV1_20_R1 extends NametagPacket {
|
||||
|
||||
private static final Field a = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "a");
|
||||
private static final Field b = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "b");
|
||||
private static final Field c = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "c");
|
||||
private static final Field d = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "d");
|
||||
private static final Field e = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "e");
|
||||
private static final Field f = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "f");
|
||||
private static final Field g = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "g");
|
||||
private static final ScoreboardTeam EMPTY_TEAM = new ScoreboardTeam(new Scoreboard(), "empty");
|
||||
private static final Constructor<?> PACKET_SCORE_BOARD_CONSTRUCTOR;
|
||||
|
||||
private static final Map<String, EnumChatFormat> FORMATS = Arrays
|
||||
.stream(EnumChatFormat.values())
|
||||
.collect(Collectors.toMap(EnumChatFormat::toString, e -> e));
|
||||
|
||||
private final Map<String, NameInfo> teams;
|
||||
private final Map<String, String> teamsByPlayer;
|
||||
|
||||
static {
|
||||
try {
|
||||
|
||||
PACKET_SCORE_BOARD_CONSTRUCTOR = PacketPlayOutScoreboardTeam.class.getDeclaredConstructor(
|
||||
String.class, int.class, Optional.class, Collection.class
|
||||
);
|
||||
PACKET_SCORE_BOARD_CONSTRUCTOR.setAccessible(true);
|
||||
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public NametagPacketV1_20_R1(NametagManager manager, Player player) {
|
||||
super(manager, player);
|
||||
this.teams = new ConcurrentHashMap<>();
|
||||
this.teamsByPlayer = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) { // Packet type is unknown 1.8+
|
||||
((CraftPlayer) player).getHandle().c.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToTeam(Player player, String name) {
|
||||
String currentTeam = teamsByPlayer.get(player.getName());
|
||||
NameInfo info = teams.get(name);
|
||||
|
||||
if (currentTeam != null && currentTeam.equals(name)) return;
|
||||
if (info == null) return;
|
||||
|
||||
teamsByPlayer.put(player.getName(), name);
|
||||
sendPacket(new ScoreboardPacket(info, 3, player).toPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
for (NameInfo info : teams.values()) {
|
||||
sendPacket(new ScoreboardPacket(info, 1).toPacket());
|
||||
}
|
||||
|
||||
teams.clear();
|
||||
teamsByPlayer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String name, String color, String prefix, String suffix, boolean friendlyInvis, NameVisibility visibility) {
|
||||
NameInfo current = teams.get(name);
|
||||
|
||||
if (current != null) {
|
||||
if (!current.getColor().equals(color) || !current.getPrefix().equals(prefix) || !current.getSuffix().equals(suffix)) {
|
||||
NameInfo newInfo = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, newInfo);
|
||||
sendPacket(new ScoreboardPacket(newInfo, 2).toPacket());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NameInfo info = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, info);
|
||||
sendPacket(new ScoreboardPacket(info, 0).toPacket());
|
||||
}
|
||||
|
||||
private static class ScoreboardPacket {
|
||||
|
||||
private final NameInfo info;
|
||||
private final Player target;
|
||||
private final int action;
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = null;
|
||||
}
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action, Player target) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public PacketPlayOutScoreboardTeam toPacket() {
|
||||
PacketPlayOutScoreboardTeam.b subPacket = new PacketPlayOutScoreboardTeam.b(EMPTY_TEAM);
|
||||
|
||||
a.set(subPacket, CraftChatMessage.fromString(info.getName())[0]);
|
||||
b.set(subPacket, CraftChatMessage.fromString(info.getPrefix())[0]);
|
||||
c.set(subPacket, CraftChatMessage.fromString(info.getSuffix())[0]);
|
||||
d.set(subPacket, info.getVisibility().getName());
|
||||
e.set(subPacket, ScoreboardTeamBase.EnumTeamPush.b.e);
|
||||
f.set(subPacket, getFormat(info.getColor()));
|
||||
g.set(subPacket, info.isFriendlyInvis() ? 3 : 0);
|
||||
|
||||
return (PacketPlayOutScoreboardTeam) PACKET_SCORE_BOARD_CONSTRUCTOR.newInstance(
|
||||
info.getName(), action,
|
||||
Optional.of(subPacket),
|
||||
(target != null ? Collections.singleton(target.getName()) : Collections.emptySet())
|
||||
);
|
||||
}
|
||||
|
||||
public EnumChatFormat getFormat(String string) {
|
||||
EnumChatFormat format = FORMATS.get(string);
|
||||
return format == null ? EnumChatFormat.v : format;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package me.keano.azurite.modules.tablist.packet.type;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import me.keano.azurite.modules.tablist.Tablist;
|
||||
import me.keano.azurite.modules.tablist.TablistManager;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistEntry;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.tablist.packet.TablistPacket;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.PlayerConnection;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TablistPacketV1_20_R1 extends TablistPacket {
|
||||
|
||||
private final Table<Integer, Integer, EntityPlayer> fakePlayers;
|
||||
private final int maxColumns;
|
||||
|
||||
// Cache them to see if we don't have to send a packet again.
|
||||
private String header;
|
||||
private String footer;
|
||||
|
||||
public TablistPacketV1_20_R1(TablistManager manager, Player player) {
|
||||
super(manager, player);
|
||||
|
||||
this.fakePlayers = HashBasedTable.create();
|
||||
this.header = "";
|
||||
this.footer = "";
|
||||
this.maxColumns = (Utils.getProtocolVersion(player) <= 5 ? 3 : 4);
|
||||
|
||||
this.loadFakes();
|
||||
this.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
this.sendHeaderFooter();
|
||||
|
||||
Tablist tablist = getManager().getAdapter().getInfo(player);
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
TablistEntry entry = tablist.getEntry(col, row);
|
||||
TablistSkin newSkin = entry.getSkin();
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
|
||||
if (fake == null) continue;
|
||||
|
||||
if (fake.f != entry.getPing()) {
|
||||
fake.f = entry.getPing();
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.e, fake));
|
||||
}
|
||||
|
||||
if (newSkin == null) {
|
||||
newSkin = getManager().getDefaultSkins().get(col, row);
|
||||
}
|
||||
|
||||
updateSkin(fake, newSkin);
|
||||
handleTeams(fake.getBukkitEntity(), entry.getText(), calcSlot(col, row));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSkin(EntityPlayer fake, TablistSkin skin) {
|
||||
GameProfile profile = fake.fM();
|
||||
Property old = profile.getProperties().get("textures").stream().findFirst().orElse(null);
|
||||
|
||||
// Verify if we should update
|
||||
if (old != null && old.getValue().equals(skin.getValue()) && old.getSignature().equals(skin.getSignature())) {
|
||||
return;
|
||||
}
|
||||
|
||||
profile.getProperties().clear();
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(profile.getId())));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
}
|
||||
|
||||
private void loadFakes() {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
WorldServer worldServer = server.F().iterator().next();
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < 4; col++) {
|
||||
GameProfile profile = new GameProfile(UUID.randomUUID(), getName(col, row));
|
||||
EntityPlayer fake = new EntityPlayer(server, worldServer, profile);
|
||||
TablistSkin skin = getManager().getDefaultSkins().get(col, row);
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
fakePlayers.put(col, row, fake);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
if (fake == null) continue;
|
||||
// Some reason u have to send an add_packet and then following it with update display name.
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) {
|
||||
PlayerConnection connection = ((CraftPlayer) player).getHandle().c;
|
||||
connection.a(packet);
|
||||
}
|
||||
|
||||
private void sendHeaderFooter() {
|
||||
String headerJoined = String.join("\n", getManager().getAdapter().getHeader(player));
|
||||
String footerJoined = String.join("\n", getManager().getAdapter().getFooter(player));
|
||||
|
||||
// Refrain sending a packet again if same.
|
||||
if (footer.equals(headerJoined) && header.equals(headerJoined)) return;
|
||||
|
||||
this.header = headerJoined;
|
||||
this.footer = footerJoined;
|
||||
|
||||
PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(
|
||||
CraftChatMessage.fromJSONOrString(headerJoined, true),
|
||||
CraftChatMessage.fromJSONOrString(footerJoined, true)
|
||||
);
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,362 @@
|
|||
package me.keano.azurite.modules.versions.type;
|
||||
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.type.InvisibilityAbility;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.loggers.Logger;
|
||||
import me.keano.azurite.modules.nametags.Nametag;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostClass;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.versions.Version;
|
||||
import me.keano.azurite.modules.versions.VersionManager;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.core.BlockPosition;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.PlayerChunkMap;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.PlayerConnection;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import net.minecraft.world.EnumHand;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EnumItemSlot;
|
||||
import net.minecraft.world.level.block.entity.TileEntity;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityPotionEffectEvent;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class Version1_20_R1 extends Module<VersionManager> implements Version {
|
||||
|
||||
private static final Field ENTITY_ID = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "b");
|
||||
private static final Field SLOT = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "c");
|
||||
private static final Field ACTION = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "a");
|
||||
private static final Field DATA = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "b");
|
||||
private static final Field NETWORK_MANAGER = ReflectionUtils.accessField(PlayerConnection.class, "h");
|
||||
private static final Field ENTITY_LOOKUP = ReflectionUtils.accessField(WorldServer.class, "entityLookup");
|
||||
|
||||
private static final Method ENTITY_GET = ReflectionUtils.accessMethod(
|
||||
ReflectionUtils.getClass("io.papermc.paper.chunk.system.entity.EntityLookup"), "get", int.class);
|
||||
|
||||
private static final Method SPAWN_PARTICLE = ReflectionUtils.accessMethod(
|
||||
CraftWorld.class, "spawnParticle", Particle.class, Location.class, int.class, Object.class
|
||||
);
|
||||
|
||||
public Version1_20_R1(VersionManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandMap getCommandMap() {
|
||||
try {
|
||||
|
||||
CraftServer server = (CraftServer) Bukkit.getServer();
|
||||
Method method = server.getClass().getMethod("getCommandMap");
|
||||
return (CommandMap) method.invoke(server);
|
||||
|
||||
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Player> getTrackedPlayers(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = ((WorldServer) entityPlayer.dI()).k().a.K.get(player.getEntityId());
|
||||
|
||||
if (tracker != null) {
|
||||
Set<Player> players = new HashSet<>();
|
||||
|
||||
for (ServerPlayerConnection connection : tracker.f) {
|
||||
players.add(connection.f().getBukkitEntity());
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotGapple(ItemStack item) {
|
||||
return item.getType() != Material.ENCHANTED_GOLDEN_APPLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
return craftPlayer.getHandle().f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand(Player player) {
|
||||
return player.getInventory().getItemInMainHand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack addGlow(ItemStack itemStack) {
|
||||
itemStack.addUnsafeEnchantment(Enchantment.WATER_WORKER, 1);
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
itemStack.setItemMeta(meta);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInHand(Player player, ItemStack item) {
|
||||
try {
|
||||
|
||||
Method method = player.getInventory().getClass().getMethod("setItemInMainHand", ItemStack.class);
|
||||
method.invoke(player.getInventory(), item);
|
||||
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLoggerDeath(Logger logger) {
|
||||
EntityPlayer player = ((CraftPlayer) logger.getPlayer()).getHandle();
|
||||
player.getBukkitEntity().getInventory().clear();
|
||||
player.getBukkitEntity().getInventory().setArmorContents(null);
|
||||
player.getBukkitEntity().setHealth(0);
|
||||
player.getBukkitEntity().setExp(0.0F);
|
||||
player.removeAllEffects(EntityPotionEffectEvent.Cause.DEATH);
|
||||
player.getBukkitEntity().saveData(); // Save the inventory and everything we just modified
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEffect(Location location, String name, Object data) {
|
||||
try {
|
||||
|
||||
Particle particle = Particle.valueOf(name);
|
||||
SPAWN_PARTICLE.invoke(location.getWorld(), particle, location, 1, data);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Particle " + name + " does not exist.");
|
||||
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTPSColored() {
|
||||
double tps = MinecraftServer.getServer().recentTps[0];
|
||||
String color = (tps > 18 ? "§a" : tps > 16 ? "§e" : "§c");
|
||||
String asterisk = (tps > 20 ? "*" : "");
|
||||
return color + asterisk + Math.min(Math.round(tps * 100.0) / 100.0, 20.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = ((WorldServer) entityPlayer.dI()).k().a.K.get(player.getEntityId());
|
||||
|
||||
if (tracker != null) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(null)));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = ((WorldServer) entityPlayer.dI()).k().a.K.get(player.getEntityId());
|
||||
|
||||
if (tracker != null) {
|
||||
org.bukkit.inventory.PlayerInventory inventory = player.getInventory();
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(inventory.getBoots())));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(inventory.getLeggings())));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(inventory.getChestplate())));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(inventory.getHelmet())));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void handleNettyListener(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
ChannelPipeline pipeline = ((NetworkManager) NETWORK_MANAGER.get(entityPlayer.c)).m.pipeline();
|
||||
AbilityManager abilityManager = getInstance().getAbilityManager();
|
||||
InvisibilityAbility ability = (InvisibilityAbility) abilityManager.getAbility("Invisibility");
|
||||
GhostClass ghostClass = getInstance().getClassManager().getGhostClass();
|
||||
|
||||
if (pipeline.get("packet_handler") == null) {
|
||||
player.kickPlayer(Config.COULD_NOT_LOAD_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline.addBefore("packet_handler", "Azurite", new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
if (msg instanceof PacketPlayOutEntityEquipment packet) {
|
||||
WorldServer server = ((CraftWorld) player.getWorld()).getHandle();
|
||||
Entity entity = (Entity) ENTITY_GET.invoke(ENTITY_LOOKUP.get(server), (int) ENTITY_ID.get(packet));
|
||||
|
||||
if (entity != null) {
|
||||
if (ghostClass != null && ghostClass.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().a() == EnumItemSlot.Function.b) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().a() == EnumItemSlot.Function.b) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (msg instanceof ClientboundPlayerInfoUpdatePacket) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) msg;
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.a> actions = (EnumSet<ClientboundPlayerInfoUpdatePacket.a>) ACTION.get(packet);
|
||||
Nametag nametag = getInstance().getNametagManager().getNametags().get(player.getUniqueId());
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.a action : actions) {
|
||||
if (action == ClientboundPlayerInfoUpdatePacket.a.a && nametag != null) {
|
||||
List<ClientboundPlayerInfoUpdatePacket.b> data = (List<ClientboundPlayerInfoUpdatePacket.b>) DATA.get(packet);
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.b info : data) {
|
||||
Player targetPlayer = Bukkit.getPlayer(info.a());
|
||||
|
||||
if (targetPlayer == null) continue;
|
||||
|
||||
// Make tablist sort instantly
|
||||
nametag.getPacket().create("tablist", "", "", "", false, NameVisibility.ALWAYS);
|
||||
nametag.getPacket().addToTeam(targetPlayer, "tablist");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(Player player, String string) {
|
||||
ClientboundSetActionBarTextPacket packet = new ClientboundSetActionBarTextPacket(CraftChatMessage.fromJSONOrString(string, true));
|
||||
((CraftPlayer) player).getHandle().c.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToServer(Player player, String server) {
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
out.writeUTF("Connect");
|
||||
out.writeUTF(server);
|
||||
player.sendPluginMessage(getInstance(), "BungeeCord", out.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearArrows(Player player) {
|
||||
((CraftPlayer) player).getHandle().setArrowCount(0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getBlockDrops(Player pl, Block bl, ItemStack hand) {
|
||||
EntityPlayer serverPlayer = ((CraftPlayer) pl).getHandle();
|
||||
WorldServer serverLevel = serverPlayer.x().getMinecraftWorld();
|
||||
BlockPosition blockPos = new BlockPosition(bl.getX(), bl.getY(), bl.getZ());
|
||||
IBlockData blockState = serverLevel.a_(blockPos);
|
||||
TileEntity blockEntity = serverLevel.c_(blockPos);
|
||||
return net.minecraft.world.level.block.Block.a(blockState, serverLevel, blockPos, blockEntity, serverPlayer, serverPlayer.b(EnumHand.a))
|
||||
.stream().map(CraftItemStack::asBukkitCopy).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TablistSkin getSkinData(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
GameProfile profile = entityPlayer.fM();
|
||||
|
||||
if (profile.getProperties().get("textures").size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Property property = profile.getProperties().get("textures").iterator().next();
|
||||
return new TablistSkin(property.getValue(), property.getSignature());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
Commands:
|
||||
- azurite.resetreclaim
|
||||
- azurite.reload
|
||||
- azurite.ecomanage
|
||||
- azurite.livesmanage
|
||||
- azurite.setend
|
||||
- azurite.strengthnerf
|
||||
- azurite.broadcast
|
||||
- azurite.clearchat
|
||||
- azurite.clear
|
||||
- azurite.craft
|
||||
- azurite.feed
|
||||
- azurite.gamemode
|
||||
- azurite.gmc
|
||||
- azurite.gms
|
||||
- azurite.heal
|
||||
- azurite.kill
|
||||
- azurite.rename
|
||||
- azurite.repair
|
||||
- azurite.top
|
||||
- azurite.tpall
|
||||
- azurite.teleport
|
||||
- azurite.teleporthere
|
||||
- azurite.tploc
|
||||
- azurite.tprandom
|
||||
- azurite.world
|
||||
- azurite.abilities
|
||||
- azurite.ability
|
||||
- azurite.deathban
|
||||
- azurite.spawner
|
||||
- azurite.freeze
|
||||
- azurite.staffbuild
|
||||
- azurite.staff
|
||||
- azurite.crowbar
|
||||
- azurite.purge
|
||||
- azurite.resetredeem
|
||||
- azurite.managefalltraptoken
|
||||
- azurite.managebasetoken
|
||||
- azurite.vanish
|
||||
- azurite.timer
|
||||
- azurite.keyall
|
||||
|
||||
- azurite.eotw
|
||||
- azurite.customtimer
|
||||
- azurite.sotw.admin
|
||||
- azurite.spawn.admin
|
||||
- azurite.pvptimer.admin
|
||||
- azurite.spawner.bypass
|
||||
|
||||
Team Commands:
|
||||
- azurite.team.teleport
|
||||
- azurite.team.setregen
|
||||
- azurite.team.setpoints
|
||||
- azurite.team.setleader
|
||||
- azurite.team.setdtr
|
||||
- azurite.team.setcaps
|
||||
- azurite.team.setbal
|
||||
- azurite.systeam
|
||||
- azurite.mountain
|
||||
- azurite.citadel
|
||||
|
||||
Miscellaneous:
|
||||
- azurite.deathban.bypass
|
||||
- azurite.eotw.bypass
|
||||
- azurite.claim.nomoney
|
||||
- azurite.claim.bypass
|
||||
- azurite.freeze.bypass
|
||||
- azurite.customsigns
|
||||
- azurite.donor
|
||||
- azurite.autosmelt
|
||||
- azurite.chat.bypass
|
||||
- azurite.repair.all
|
||||
- azurite.abilitymenu.click
|
||||
- azurite.citadel.entry
|
||||
- azurite.event.entry
|
||||
- azurite.potionlimit.bypass
|
||||
|
||||
How to claim spawn:
|
||||
- /st create <name of spawn> SAFEZONE
|
||||
- /st claim <name of spawn>
|
||||
- /st sethq <name of spawn> (shows in /f info)
|
||||
|
||||
How to claim koths
|
||||
- /koth create <name of koth> <color> <mins> <pointsreward>
|
||||
- Color has to be color coded, &9, &5, etc.
|
||||
- /koth claimzone <name of koth>
|
||||
- /st create <name of koth> EVENT
|
||||
- /st claim <name of koth>
|
||||
- /st sethq <name of koth> (shows in /f info)
|
||||
|
||||
How to claim glowstone
|
||||
- /st create <name of glowstone> GLOWSTONE
|
||||
- /st claim <name of glowstone>
|
||||
- /st sethq <name of glowstone> (shows in /f info and waypoint)
|
||||
- After all the glowstone is placed, run /mountain reload <name of glowstone> to save the glowstone blocks
|
||||
- Give it some time to store all the blocks, after a few seconds break a glowstone and type /mountain respawn <name of glowstone> to see if it works.
|
||||
|
||||
How to claim ore mountain
|
||||
- /st create <name of oremountain> ORE_MOUNTAIN
|
||||
- /st claim <name of oremountain>
|
||||
- /st sethq <name of oremountain> (shows in /f info and waypoint)
|
||||
- After all the chests and valuables are placed, run /mountain reload <name of oremountain> to save the chests and blocks
|
||||
- Give it some time to store all the blocks, after a few seconds break an ore and type /mountain respawn <name of oremountain> to see if it works.
|
||||
- Check the chests and some loot should have spawned.
|
||||
|
||||
How to setup deathban arena
|
||||
- /deathban setarenaspawn (Where the player spawns when they die)
|
||||
- /kit edit deathban (Edit to your liking, kit is created already)
|
||||
- Create your kit sign where you would like with the kit name as "Deathban"
|
||||
- Create a sign with [lives] on the first line to create the lives sign (click to revive)
|
||||
- Create a sign with [deathlocsign] on the first line to create the death location info sign.
|
||||
- Create a sign with [killedbysign] on the first line to create the killed by info sign.
|
||||
|
||||
How to setup a keyall
|
||||
- Run /keyall create <name> <displayName> <time> <command>
|
||||
- Displayname shows on scoreboard
|
||||
- command runs when the timer runs out
|
||||
- Example: /keyall create SOTW &a&lSOTW-KEY 10m crate giveall SOTW 3
|
||||
|
||||
How to setup eotw
|
||||
- Create a koth with the name u have set in config.yml
|
||||
- Run /eotw start <time>
|
||||
- When Pre-EOTW ends no player would be allowed to join and eotw koth will be started and every team will be raidable.
|
||||
|
||||
How to setup citadel
|
||||
- /st create <name of citadel> CITADEL
|
||||
- /st claim <name of citadel>
|
||||
- /koth create <name of citadel> <color> <mins> <pointsreward>
|
||||
- /koth claimzone <name of citadel>
|
||||
- After all the chests are placed, run /citadel reload <name of citadel> to save the chests.
|
||||
- Give it some time to store all the blocks, after a few seconds type /mountain respawn and check the chests and some loot should have spawned.
|
||||
|
||||
How to setup end exits
|
||||
- Run /setend exit at the location you would like the end waypoint to be (In end dimension)
|
||||
- Run /setend worldexit at the location you would like the player to teleport to when they move in water in end dimension
|
||||
|
||||
How to setup holograms
|
||||
- Make sure you have holographic displays installed
|
||||
- Create a hologram of choice and the lines should be one of the following:
|
||||
- {team_top%number%} - Please note the number is capped at 10
|
||||
- {kills_top%number%} - Please note the number is capped at 10
|
||||
- {deaths_top%number%} - Please note the number is capped at 10
|
||||
- {kdr_top%number%} - Please note the number is capped at 10
|
||||
- {killstreak_top%number%} - Please note the number is capped at 10
|
||||
- Your hologram should look something like this:
|
||||
- '&3&lTeam Top'
|
||||
- '{team_top1}'
|
||||
- '{team_top2}'
|
||||
- '{team_top3}'
|
||||
- '{team_top4}'
|
||||
- '{team_top5}'
|
||||
- '{team_top6}'
|
||||
- '{team_top7}'
|
||||
- '{team_top8}'
|
||||
- '{team_top9}'
|
||||
- '{team_top10}'
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,311 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>Azurite</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>central</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>minecraft.net</id>
|
||||
<url>https://libraries.minecraft.net</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>placeholderapi</id>
|
||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!-- Misc -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.22</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>3.12.10</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mkremins</groupId>
|
||||
<artifactId>fanciful</artifactId>
|
||||
<version>0.4.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.milkbowl.vault.Vault</groupId>
|
||||
<artifactId>Vault</artifactId>
|
||||
<version>1.7.1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/Vault.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.MylesIsCool</groupId>
|
||||
<artifactId>ViaVersion</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ViaVersion.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ProtocolSupport</groupId>
|
||||
<artifactId>ProtocolSupport</artifactId>
|
||||
<version>f188eb2ea8</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ProtocolSupport.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- Holograms -->
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>HologramAPI</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/holograms/HolographicDisplays.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- Clients -->
|
||||
<dependency>
|
||||
<groupId>com.lunarclient</groupId>
|
||||
<artifactId>lunar-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/clients/LunarClientAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.cheatbreaker</groupId>
|
||||
<artifactId>CheatBreaker-API</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/clients/CheatBreakerAPI.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- Abilities -->
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>AbilityAPI</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/abilities/PandaAbilityAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>AbilityAPI1</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/abilities/SladeAPI.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- Pearls -->
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>PearlAPI</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/pearls/VortexPearlsAPI.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- Placeholders -->
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.11.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spigots -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-1.8.8</artifactId>
|
||||
<version>1.8.8</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/spigots/1.8.8.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-1.16</artifactId>
|
||||
<version>1.16</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/spigots/1.16.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-1.7.10</artifactId>
|
||||
<version>1.7.10</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/spigots/1.7.10.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-1.17</artifactId>
|
||||
<version>1.17</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/spigots/1.17.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- Rank Cores -->
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/AquaCoreAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI1</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/Zoot.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI2</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/ZoomAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI3</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/Vault.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI4</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/MizuAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI5</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/AtomAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI6</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/CoreAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI7</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/zPermissions.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI8</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/HestiaAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI9</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/pxAPI.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI10</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/Alchemist.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI11</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/Holiday.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI12</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/Akuma.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI13</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/AzuriteCore.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>RankAPI14</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/Helium.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- Tags -->
|
||||
<dependency>
|
||||
<groupId>me.keano.azurite</groupId>
|
||||
<artifactId>TagAPI1</artifactId>
|
||||
<version>1</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/libs/ranks/DeluxeTags.jar</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,195 @@
|
|||
package me.keano.azurite;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.balance.BalanceManager;
|
||||
import me.keano.azurite.modules.board.BoardManager;
|
||||
import me.keano.azurite.modules.commands.CommandManager;
|
||||
import me.keano.azurite.modules.deathban.DeathbanManager;
|
||||
import me.keano.azurite.modules.events.conquest.ConquestManager;
|
||||
import me.keano.azurite.modules.events.eotw.EOTWManager;
|
||||
import me.keano.azurite.modules.events.king.KingManager;
|
||||
import me.keano.azurite.modules.events.koth.KothManager;
|
||||
import me.keano.azurite.modules.events.purge.PurgeManager;
|
||||
import me.keano.azurite.modules.events.sotw.SOTWManager;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Manager;
|
||||
import me.keano.azurite.modules.framework.extra.Configs;
|
||||
import me.keano.azurite.modules.framework.menu.MenuManager;
|
||||
import me.keano.azurite.modules.hooks.abilities.AbilitiesHook;
|
||||
import me.keano.azurite.modules.hooks.clients.ClientHook;
|
||||
import me.keano.azurite.modules.hooks.pearls.PearlHook;
|
||||
import me.keano.azurite.modules.hooks.placeholder.PlaceholderHook;
|
||||
import me.keano.azurite.modules.hooks.ranks.RankHook;
|
||||
import me.keano.azurite.modules.hooks.tags.TagHook;
|
||||
import me.keano.azurite.modules.killstreaks.KillstreakManager;
|
||||
import me.keano.azurite.modules.killtag.KilltagManager;
|
||||
import me.keano.azurite.modules.kits.KitManager;
|
||||
import me.keano.azurite.modules.listeners.ListenerManager;
|
||||
import me.keano.azurite.modules.listeners.type.GlitchListener;
|
||||
import me.keano.azurite.modules.loggers.LoggerManager;
|
||||
import me.keano.azurite.modules.nametags.NametagManager;
|
||||
import me.keano.azurite.modules.pvpclass.PvPClassManager;
|
||||
import me.keano.azurite.modules.reclaims.ReclaimManager;
|
||||
import me.keano.azurite.modules.scheduler.ScheduleManager;
|
||||
import me.keano.azurite.modules.signs.CustomSignManager;
|
||||
import me.keano.azurite.modules.spawners.SpawnerManager;
|
||||
import me.keano.azurite.modules.staff.StaffManager;
|
||||
import me.keano.azurite.modules.storage.StorageManager;
|
||||
import me.keano.azurite.modules.tablist.TablistManager;
|
||||
import me.keano.azurite.modules.teams.TeamManager;
|
||||
import me.keano.azurite.modules.timers.TimerManager;
|
||||
import me.keano.azurite.modules.tips.TipManager;
|
||||
import me.keano.azurite.modules.users.UserManager;
|
||||
import me.keano.azurite.modules.versions.VersionManager;
|
||||
import me.keano.azurite.modules.walls.WallManager;
|
||||
import me.keano.azurite.modules.waypoints.WaypointManager;
|
||||
import me.keano.azurite.utils.Logger;
|
||||
import me.keano.azurite.utils.configs.ConfigYML;
|
||||
import me.keano.azurite.utils.extra.Cooldown;
|
||||
import me.keano.azurite.utils.extra.CooldownClearTask;
|
||||
import me.keano.azurite.utils.extra.TeamCooldown;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public final class HCF extends JavaPlugin {
|
||||
|
||||
private List<Manager> managers;
|
||||
private List<ConfigYML> configs; // used for easier reloading
|
||||
private List<Cooldown> cooldowns; // used for clearing cache/mem
|
||||
private List<TeamCooldown> teamCooldowns;
|
||||
|
||||
private Configs configsObject;
|
||||
|
||||
private Gson gson; // used for serialization / deserialization
|
||||
private GlitchListener glitchListener; // Used to check glitch cooldown
|
||||
|
||||
// Managers
|
||||
private UserManager userManager;
|
||||
private VersionManager versionManager;
|
||||
private TimerManager timerManager;
|
||||
private BalanceManager balanceManager;
|
||||
private WaypointManager waypointManager;
|
||||
private NametagManager nametagManager;
|
||||
private TeamManager teamManager;
|
||||
private WallManager wallManager;
|
||||
private SpawnerManager spawnerManager;
|
||||
private DeathbanManager deathbanManager;
|
||||
private ReclaimManager reclaimManager;
|
||||
private KitManager kitManager;
|
||||
private RankHook rankHook;
|
||||
private TagHook tagHook;
|
||||
private PlaceholderHook placeholderHook;
|
||||
private ClientHook clientHook;
|
||||
private AbilitiesHook abilitiesHook;
|
||||
private PvPClassManager classManager;
|
||||
private LoggerManager loggerManager;
|
||||
private AbilityManager abilityManager;
|
||||
private StorageManager storageManager;
|
||||
private ScheduleManager scheduleManager;
|
||||
private StaffManager staffManager;
|
||||
private KillstreakManager killstreakManager;
|
||||
private KilltagManager killtagManager;
|
||||
private MenuManager menuManager;
|
||||
private ListenerManager listenerManager;
|
||||
|
||||
// Events
|
||||
private KothManager kothManager;
|
||||
private KingManager kingManager;
|
||||
private SOTWManager sotwManager;
|
||||
private EOTWManager eotwManager;
|
||||
private PurgeManager purgeManager;
|
||||
private ConquestManager conquestManager;
|
||||
|
||||
private boolean loaded = false;
|
||||
private boolean kits;
|
||||
public String load;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.managers = new ArrayList<>();
|
||||
this.configs = new ArrayList<>();
|
||||
this.cooldowns = new ArrayList<>();
|
||||
this.teamCooldowns = new ArrayList<>();
|
||||
|
||||
this.gson = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
(this.configsObject = new Configs()).load(this);
|
||||
|
||||
this.userManager = new UserManager(this);
|
||||
this.versionManager = new VersionManager(this);
|
||||
this.timerManager = new TimerManager(this);
|
||||
this.balanceManager = new BalanceManager(this);
|
||||
this.waypointManager = new WaypointManager(this);
|
||||
this.nametagManager = new NametagManager(this);
|
||||
this.teamManager = new TeamManager(this);
|
||||
this.wallManager = new WallManager(this);
|
||||
this.spawnerManager = new SpawnerManager(this);
|
||||
this.deathbanManager = new DeathbanManager(this);
|
||||
this.reclaimManager = new ReclaimManager(this);
|
||||
this.kitManager = new KitManager(this);
|
||||
this.rankHook = new RankHook(this);
|
||||
this.tagHook = new TagHook(this);
|
||||
this.abilitiesHook = new AbilitiesHook(this);
|
||||
this.placeholderHook = new PlaceholderHook(this);
|
||||
this.clientHook = new ClientHook(this);
|
||||
this.classManager = new PvPClassManager(this);
|
||||
this.loggerManager = new LoggerManager(this);
|
||||
this.abilityManager = new AbilityManager(this);
|
||||
this.storageManager = new StorageManager(this);
|
||||
this.scheduleManager = new ScheduleManager(this);
|
||||
this.staffManager = new StaffManager(this);
|
||||
this.killstreakManager = new KillstreakManager(this);
|
||||
this.killtagManager = new KilltagManager(this);
|
||||
this.menuManager = new MenuManager(this);
|
||||
this.listenerManager = new ListenerManager(this);
|
||||
|
||||
this.kothManager = new KothManager(this);
|
||||
this.kingManager = new KingManager(this);
|
||||
this.sotwManager = new SOTWManager(this);
|
||||
this.eotwManager = new EOTWManager(this);
|
||||
this.purgeManager = new PurgeManager(this);
|
||||
this.conquestManager = new ConquestManager(this);
|
||||
|
||||
this.glitchListener = new GlitchListener(listenerManager);
|
||||
this.kits = getConfig().getBoolean("KITMAP_MODE");
|
||||
|
||||
new PearlHook(this);
|
||||
new CommandManager(this);
|
||||
new CustomSignManager(this);
|
||||
new TipManager(this);
|
||||
new BoardManager(this);
|
||||
new CooldownClearTask(this);
|
||||
|
||||
if (Config.TABLIST_ENABLED) new TablistManager(this);
|
||||
|
||||
this.managers.forEach(Manager::enable);
|
||||
this.loaded = true;
|
||||
|
||||
Logger.state("Enabled", managers.size(),
|
||||
teamManager.getTeams().size(), userManager.getUsers().size(),
|
||||
kitManager.getKits().size(), kothManager.getKoths().size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (teamManager != null && userManager != null) {
|
||||
this.managers.forEach(Manager::disable);
|
||||
Logger.state("Disabled", managers.size(),
|
||||
teamManager.getTeams().size(), userManager.getUsers().size(),
|
||||
kitManager.getKits().size(), kothManager.getKoths().size());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
package me.keano.azurite.modules.ability;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.event.AbilityUseEvent;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.CooldownBarTask;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.teams.Team;
|
||||
import me.keano.azurite.modules.teams.type.CitadelTeam;
|
||||
import me.keano.azurite.modules.teams.type.EventTeam;
|
||||
import me.keano.azurite.modules.teams.type.SafezoneTeam;
|
||||
import me.keano.azurite.modules.timers.listeners.playertimers.AbilityTimer;
|
||||
import me.keano.azurite.utils.ItemBuilder;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class Ability extends Module<AbilityManager> {
|
||||
|
||||
protected String name;
|
||||
protected String displayName;
|
||||
protected String nameConfig;
|
||||
protected AbilityUseType useType;
|
||||
protected AbilityTimer abilityCooldown;
|
||||
protected ItemStack item;
|
||||
protected boolean enabled;
|
||||
|
||||
public Ability(AbilityManager manager, AbilityUseType useType, String name) {
|
||||
super(manager);
|
||||
|
||||
this.name = name;
|
||||
this.useType = useType;
|
||||
this.nameConfig = name.replaceAll(" ", "_").toUpperCase();
|
||||
this.displayName = getAbilitiesConfig().getString(nameConfig + ".DISPLAY_NAME");
|
||||
this.abilityCooldown = new AbilityTimer(getInstance().getTimerManager(), this, "PLAYER_TIMERS.ABILITIES");
|
||||
this.item = loadItem();
|
||||
this.enabled = getAbilitiesConfig().getBoolean(nameConfig + ".ENABLED");
|
||||
|
||||
manager.getAbilities().put(name.toUpperCase().replaceAll(" ", ""), this);
|
||||
}
|
||||
|
||||
private ItemStack loadItem() {
|
||||
Material material = ItemUtils.getMat(getAbilitiesConfig().getString(nameConfig + ".MATERIAL"));
|
||||
ItemBuilder builder = new ItemBuilder(material);
|
||||
|
||||
builder.setName(getAbilitiesConfig().getString(nameConfig + ".DISPLAY_NAME"));
|
||||
builder.setLore(getAbilitiesConfig().getStringList(nameConfig + ".LORE"));
|
||||
builder.data(getManager(), (short) getAbilitiesConfig().getInt(nameConfig + ".DATA"));
|
||||
|
||||
if (getAbilitiesConfig().contains(nameConfig + ".DURABILITY")) {
|
||||
short setting = (short) getAbilitiesConfig().getInt(nameConfig + ".DURABILITY");
|
||||
builder.setDurability(getManager(), (short) (material.getMaxDurability() - setting));
|
||||
}
|
||||
|
||||
if (getAbilitiesConfig().contains(nameConfig + ".ENCHANTS")) {
|
||||
for (String s : getAbilitiesConfig().getStringList(nameConfig + ".ENCHANTS")) {
|
||||
String[] split = s.split(", ");
|
||||
builder.addUnsafeEnchantment(Enchantment.getByName(split[0]), Integer.parseInt(split[1]));
|
||||
}
|
||||
}
|
||||
|
||||
if (getAbilitiesConfig().getBoolean(nameConfig + ".ADD_GLOW")) {
|
||||
return getInstance().getVersionManager().getVersion().addGlow(builder.toItemStack());
|
||||
}
|
||||
|
||||
return builder.toItemStack();
|
||||
}
|
||||
|
||||
public boolean hasAbilityInHand(Player player) {
|
||||
ItemStack hand = getManager().getItemInHand(player);
|
||||
return isSimilar(hand);
|
||||
}
|
||||
|
||||
public boolean isSimilar(ItemStack hand) {
|
||||
if (hand == null) return false;
|
||||
if (!hand.hasItemMeta()) return false;
|
||||
if (!hand.getItemMeta().hasDisplayName()) return false;
|
||||
if (!hand.getItemMeta().hasLore()) return false;
|
||||
|
||||
// Don't use ItemStack#isSimilar because that checks durability too
|
||||
ItemMeta handMeta = hand.getItemMeta();
|
||||
ItemMeta itemMeta = item.getItemMeta();
|
||||
return handMeta.getDisplayName().equals(itemMeta.getDisplayName()) && handMeta.getLore().equals(itemMeta.getLore());
|
||||
}
|
||||
|
||||
public boolean hasCooldown(Player player) {
|
||||
if (getManager().getGlobalCooldown().hasTimer(player)) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.GLOBAL_COOLDOWN")
|
||||
.replace("%time%", getManager().getGlobalCooldown().getRemainingString(player))
|
||||
);
|
||||
return true;
|
||||
|
||||
} else if (abilityCooldown.hasTimer(player)) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.COOLDOWN")
|
||||
.replace("%ability%", displayName)
|
||||
.replace("%time%", abilityCooldown.getRemainingString(player))
|
||||
);
|
||||
return true;
|
||||
|
||||
} else return false;
|
||||
}
|
||||
|
||||
public void takeItem(Player player) {
|
||||
if (getAbilitiesConfig().getBoolean(nameConfig + ".TAKE_ITEM")) {
|
||||
getManager().takeItemInHand(player, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void applyCooldown(Player player) {
|
||||
if (getAbilitiesConfig().getBoolean("GLOBAL_ABILITY.ENABLED")) {
|
||||
getManager().getGlobalCooldown().applyTimer(player);
|
||||
}
|
||||
|
||||
AbilityUseEvent event = new AbilityUseEvent(this, player, abilityCooldown.getSeconds() * 1000L);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
abilityCooldown.applyTimer(player, event.getCooldown()); // call event and update with the time if changed.
|
||||
new CooldownBarTask(player, this);
|
||||
}
|
||||
|
||||
public boolean cannotUse(Player damager) {
|
||||
if (!enabled) {
|
||||
damager.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED"));
|
||||
return true;
|
||||
}
|
||||
|
||||
return checkUsage(damager);
|
||||
}
|
||||
|
||||
private boolean checkUsage(Player player) {
|
||||
World.Environment environment = player.getWorld().getEnvironment();
|
||||
|
||||
if (getAbilitiesConfig().getBoolean("GLOBAL_ABILITY.DISABLE_IN_END") && environment == World.Environment.THE_END) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED_END"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getAbilitiesConfig().getBoolean("GLOBAL_ABILITY.DISABLE_IN_NETHER") && environment == World.Environment.NETHER) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED_NETHER"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Team team = getInstance().getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
|
||||
if (getAbilitiesConfig().getBoolean("GLOBAL_ABILITY.DISABLE_IN_CITADEL") && team instanceof CitadelTeam) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED_CITADEL"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getAbilitiesConfig().getBoolean("GLOBAL_ABILITY.DISABLE_IN_EVENTS") && team instanceof EventTeam) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED_EVENT"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (team instanceof SafezoneTeam) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED_SPAWN"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!team.isAbilities()) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED_TOGGLED"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (checkRadius(player.getLocation()) && !player.hasPermission("azurite.abilityradius.bypass")) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.DISABLED_RADIUS")
|
||||
.replace("%radius%", String.valueOf(Config.ABILITY_DISABLED_RADIUS))
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkRadius(Location location) {
|
||||
int x = location.getBlockX();
|
||||
int z = location.getBlockZ();
|
||||
return (x <= Config.ABILITY_DISABLED_RADIUS && x >= -Config.ABILITY_DISABLED_RADIUS
|
||||
&& z <= Config.ABILITY_DISABLED_RADIUS && z >= -Config.ABILITY_DISABLED_RADIUS);
|
||||
}
|
||||
|
||||
public void onClick(Player player) {
|
||||
}
|
||||
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package me.keano.azurite.modules.ability;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.HCF;
|
||||
import me.keano.azurite.modules.ability.extra.GlobalCooldown;
|
||||
import me.keano.azurite.modules.ability.listener.AbilityListener;
|
||||
import me.keano.azurite.modules.ability.type.*;
|
||||
import me.keano.azurite.modules.framework.Manager;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class AbilityManager extends Manager {
|
||||
|
||||
private final Map<String, Ability> abilities;
|
||||
private final List<BukkitTask> tasks;
|
||||
private final GlobalCooldown globalCooldown;
|
||||
|
||||
public AbilityManager(HCF instance) {
|
||||
super(instance);
|
||||
|
||||
this.abilities = new HashMap<>();
|
||||
this.tasks = new ArrayList<>();
|
||||
this.globalCooldown = new GlobalCooldown(instance.getTimerManager());
|
||||
|
||||
new AbilityListener(this);
|
||||
this.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
PortableBardAbility ability = (PortableBardAbility) getAbility("PortableBard");
|
||||
ability.disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
for (Ability ability : abilities.values()) {
|
||||
HandlerList.unregisterAll(ability);
|
||||
}
|
||||
|
||||
Utils.iterate(tasks, (task) -> {
|
||||
task.cancel();
|
||||
return true;
|
||||
});
|
||||
|
||||
abilities.clear();
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
new SwitcherAbility(this);
|
||||
new AntiBuildAbility(this);
|
||||
new TimeWarpAbility(this);
|
||||
new PocketBardAbility(this);
|
||||
new InvisibilityAbility(this);
|
||||
new PortableArcherAbility(this);
|
||||
new LightningAbility(this);
|
||||
new RageBallAbility(this);
|
||||
new CraftingChaosAbility(this);
|
||||
new ComboAbility(this);
|
||||
new FocusModeAbility(this);
|
||||
new LuckyModeAbility(this);
|
||||
new NinjaAbility(this);
|
||||
new BerserkAbility(this);
|
||||
new CloseCallAbility(this);
|
||||
new SwitchStickAbility(this);
|
||||
new TeleportEyeAbility(this);
|
||||
new SamuraiAbility(this);
|
||||
new MagicRockAbility(this);
|
||||
new BelchBombAbility(this);
|
||||
new AntiTrapStarAbility(this);
|
||||
new MedKitAbility(this);
|
||||
new RocketAbility(this);
|
||||
new AntiTrapBeaconAbility(this);
|
||||
new AntiPearlAbility(this);
|
||||
new UltimateAbility(this);
|
||||
new GrappleAbility(this);
|
||||
new TankIngotAbility(this);
|
||||
new TeleportBowAbility(this);
|
||||
new ExplosiveEggAbility(this);
|
||||
new PortableBardAbility(this);
|
||||
new PortableRogueAbility(this);
|
||||
new AntiTrapHaloAbility(this);
|
||||
}
|
||||
|
||||
public Ability getAbility(String name) {
|
||||
return abilities.get(name.toUpperCase());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package me.keano.azurite.modules.ability.command;
|
||||
|
||||
import me.keano.azurite.modules.ability.menu.AbilityListMenu;
|
||||
import me.keano.azurite.modules.commands.CommandManager;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.commands.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilitiesCommand extends Command {
|
||||
|
||||
public AbilitiesCommand(CommandManager manager) {
|
||||
super(
|
||||
manager,
|
||||
"abilities"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> aliases() {
|
||||
return Arrays.asList(
|
||||
"partneritems",
|
||||
"abilitymenu"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> usage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sendMessage(sender, Config.PLAYER_ONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
new AbilityListMenu(getInstance().getMenuManager(), player).open();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
package me.keano.azurite.modules.ability.command;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.menu.AbilityToggleMenu;
|
||||
import me.keano.azurite.modules.commands.CommandManager;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.commands.Command;
|
||||
import me.keano.azurite.modules.framework.commands.extra.TabCompletion;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityCommand extends Command {
|
||||
|
||||
public AbilityCommand(CommandManager manager) {
|
||||
super(
|
||||
manager,
|
||||
"ability"
|
||||
);
|
||||
this.setPermissible("azurite.ability");
|
||||
this.completions.add(new TabCompletion(Arrays.asList("give", "list", "toggle", "getall"), 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> aliases() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> usage() {
|
||||
return getLanguageConfig().getStringList("ABILITY_COMMAND.USAGE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
if (!sender.hasPermission(permissible)) {
|
||||
sendMessage(sender, Config.INSUFFICIENT_PERM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sendUsage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "give":
|
||||
if (args.length < 4) {
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_GIVE.USAGE"));
|
||||
return;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayer(args[1]);
|
||||
Ability ability = getInstance().getAbilityManager().getAbility(args[2]);
|
||||
Integer amount = getInt(args[3]);
|
||||
|
||||
if (target == null) {
|
||||
sendMessage(sender, Config.PLAYER_NOT_FOUND
|
||||
.replace("%player%", args[1])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ability == null) {
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_GIVE.NOT_FOUND")
|
||||
.replace("%ability%", args[1])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount == null) {
|
||||
sendMessage(sender, Config.NOT_VALID_NUMBER
|
||||
.replace("%number%", args[3])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = ability.getItem().clone();
|
||||
itemStack.setAmount(amount);
|
||||
ItemUtils.giveItem(target, itemStack, target.getLocation());
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_GIVE.GAVE")
|
||||
.replace("%player%", target.getName())
|
||||
.replace("%amount%", String.valueOf(amount))
|
||||
.replace("%ability%", ability.getName())
|
||||
);
|
||||
return;
|
||||
|
||||
case "list":
|
||||
for (String s : getLanguageConfig().getStringList("ABILITY_COMMAND.ABILITY_LIST.ABILITIES")) {
|
||||
if (!s.equalsIgnoreCase("%abilities%")) {
|
||||
sendMessage(sender, s);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Ability abili : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_LIST.ABILITY_FORMAT")
|
||||
.replace("%ability%", abili.getName().replaceAll(" ", ""))
|
||||
.replace("%cooldown%", String.valueOf(abili.getAbilityCooldown().getSeconds()))
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case "toggle":
|
||||
if (!(sender instanceof Player)) {
|
||||
sendMessage(sender, Config.PLAYER_ONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
new AbilityToggleMenu(getInstance().getMenuManager(), player).open();
|
||||
return;
|
||||
|
||||
case "getall":
|
||||
if (!(sender instanceof Player)) {
|
||||
sendMessage(sender, Config.PLAYER_ONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Ability add : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
((Player) sender).getInventory().addItem(add.getItem());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sendUsage(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(CommandSender sender, String[] args) {
|
||||
if (args.length == 3) {
|
||||
String string = args[args.length - 1];
|
||||
return getInstance().getAbilityManager().getAbilities().keySet()
|
||||
.stream()
|
||||
.filter(s -> s.regionMatches(true, 0, string, 0, string.length()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return super.tabComplete(sender, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package me.keano.azurite.modules.ability.event;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class AbilityUseEvent extends Event {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private Ability ability;
|
||||
private Player player;
|
||||
private long cooldown;
|
||||
|
||||
public AbilityUseEvent(Ability ability, Player player, long cooldown) {
|
||||
this.ability = ability;
|
||||
this.player = player;
|
||||
this.cooldown = cooldown;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package me.keano.azurite.modules.ability.extra;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public enum AbilityUseType {
|
||||
|
||||
INTERACT,
|
||||
HIT_PLAYER,
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package me.keano.azurite.modules.ability.extra;
|
||||
|
||||
import me.keano.azurite.modules.hooks.abilities.AbilitiesHook;
|
||||
import me.keano.azurite.modules.timers.TimerManager;
|
||||
import me.keano.azurite.modules.timers.type.PlayerTimer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class GlobalCooldown extends PlayerTimer {
|
||||
|
||||
private final AbilitiesHook abilitiesHook;
|
||||
|
||||
public GlobalCooldown(TimerManager manager) {
|
||||
super(
|
||||
manager,
|
||||
false,
|
||||
"PartnerItem",
|
||||
"",
|
||||
manager.getAbilitiesConfig().getInt("GLOBAL_ABILITY.COOLDOWN")
|
||||
);
|
||||
this.abilitiesHook = manager.getInstance().getAbilitiesHook();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTimer(Player player) {
|
||||
return super.hasTimer(player) || getInstance().getAbilitiesHook().hasGlobalCooldown(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemainingString(Player player) {
|
||||
if (abilitiesHook.hasGlobalCooldown(player)) {
|
||||
return abilitiesHook.getRemainingGlobal(player);
|
||||
}
|
||||
|
||||
return super.getRemainingString(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemainingStringBoard(Player player) {
|
||||
if (abilitiesHook.hasGlobalCooldown(player)) {
|
||||
return abilitiesHook.getRemainingGlobal(player);
|
||||
}
|
||||
|
||||
return super.getRemainingStringBoard(player);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package me.keano.azurite.modules.ability.listener;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.CooldownBarTask;
|
||||
import me.keano.azurite.modules.ability.type.AntiTrapBeaconAbility;
|
||||
import me.keano.azurite.modules.ability.type.PocketBardAbility;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityListener extends Module<AbilityManager> {
|
||||
|
||||
public AbilityListener(AbilityManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
ItemStack hand = getManager().getItemInHand(damager);
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.hasAbilityInHand(damager)) continue;
|
||||
if (ability.getUseType() != AbilityUseType.HIT_PLAYER) continue;
|
||||
ability.onHit(damager, damaged);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlace(BlockPlaceEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
ItemStack hand = getManager().getItemInHand(player);
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.hasAbilityInHand(player)) continue;
|
||||
if (ability instanceof AntiTrapBeaconAbility) continue;
|
||||
e.setCancelled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSwitch(PlayerItemHeldEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
ItemStack hand = player.getInventory().getItem(e.getNewSlot());
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.isSimilar(hand)) continue;
|
||||
if (!ability.getAbilityCooldown().hasTimer(player)) continue;
|
||||
new CooldownBarTask(player, ability);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCooldown(PlayerInteractEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
ItemStack hand = player.getItemInHand();
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
if (e.getAction().name().contains("RIGHT")) {
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.hasAbilityInHand(player)) continue;
|
||||
if (ability.getUseType() != AbilityUseType.INTERACT) continue;
|
||||
|
||||
e.setCancelled(true);
|
||||
ability.onClick(player);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (e.getAction() == Action.LEFT_CLICK_BLOCK) {
|
||||
// This is for cooldowns
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
// Pocket bards have different items;
|
||||
if (ability instanceof PocketBardAbility) {
|
||||
PocketBardAbility pocketBard = (PocketBardAbility) ability;
|
||||
|
||||
if (pocketBard.getPocketBardInHand(player) != null && pocketBard.getAbilityCooldown().hasTimer(player)) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.COOLDOWN")
|
||||
.replace("%ability%", ability.getDisplayName())
|
||||
.replace("%time%", ability.getAbilityCooldown().getRemainingString(player))
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.hasAbilityInHand(player) && ability.getAbilityCooldown().hasTimer(player)) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.COOLDOWN")
|
||||
.replace("%ability%", ability.getDisplayName())
|
||||
.replace("%time%", ability.getAbilityCooldown().getRemainingString(player))
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package me.keano.azurite.modules.ability.menu;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.framework.menu.Menu;
|
||||
import me.keano.azurite.modules.framework.menu.MenuManager;
|
||||
import me.keano.azurite.modules.framework.menu.button.Button;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityListMenu extends Menu {
|
||||
|
||||
public AbilityListMenu(MenuManager manager, Player player) {
|
||||
super(
|
||||
manager,
|
||||
player,
|
||||
manager.getAbilitiesConfig().getString("GLOBAL_ABILITY.ABILITY_MENU_TITLE"),
|
||||
54,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Button> getButtons(Player player) {
|
||||
Map<Integer, Button> buttons = new HashMap<>();
|
||||
int slot = 1;
|
||||
|
||||
for (Ability ability : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
if (!ability.isEnabled()) continue;
|
||||
|
||||
buttons.put(slot, new Button() {
|
||||
@Override
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
if (!(e.getWhoClicked() instanceof Player)) return;
|
||||
|
||||
Player clicked = (Player) e.getWhoClicked();
|
||||
|
||||
if (clicked.hasPermission("azurite.abilitymenu.click")) {
|
||||
clicked.getInventory().addItem(ability.getItem().clone());
|
||||
}
|
||||
|
||||
e.setCancelled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack() {
|
||||
return ability.getItem();
|
||||
}
|
||||
});
|
||||
slot++;
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package me.keano.azurite.modules.ability.menu;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.framework.menu.Menu;
|
||||
import me.keano.azurite.modules.framework.menu.MenuManager;
|
||||
import me.keano.azurite.modules.framework.menu.button.Button;
|
||||
import me.keano.azurite.utils.ItemBuilder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityToggleMenu extends Menu {
|
||||
|
||||
public AbilityToggleMenu(MenuManager manager, Player player) {
|
||||
super(
|
||||
manager,
|
||||
player,
|
||||
"Ability Toggles",
|
||||
54,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Button> getButtons(Player player) {
|
||||
Map<Integer, Button> buttons = new HashMap<>();
|
||||
|
||||
int slot = 1;
|
||||
|
||||
for (Ability ability : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
buttons.put(slot, new Button() {
|
||||
@Override
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
e.setCancelled(true);
|
||||
ability.setEnabled(!ability.isEnabled());
|
||||
getAbilitiesConfig().set(ability.getNameConfig() + ".ENABLED", ability.isEnabled());
|
||||
getAbilitiesConfig().save();
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack() {
|
||||
ItemBuilder builder = new ItemBuilder(ability.getItem().clone());
|
||||
builder.setLore("&eEnabled: " + (ability.isEnabled() ? "&atrue" : "&cfalse"));
|
||||
return builder.toItemStack();
|
||||
}
|
||||
});
|
||||
slot++;
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package me.keano.azurite.modules.ability.task;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.users.User;
|
||||
import me.keano.azurite.modules.users.settings.ActionBar;
|
||||
import me.keano.azurite.modules.versions.Version;
|
||||
import me.keano.azurite.utils.CC;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class CooldownBarTask extends BukkitRunnable {
|
||||
|
||||
private final Player player;
|
||||
private final Ability ability;
|
||||
|
||||
public CooldownBarTask(Player player, Ability ability) {
|
||||
this.player = player;
|
||||
this.ability = ability;
|
||||
this.runTaskTimerAsynchronously(ability.getInstance(), 0L, 2L);
|
||||
}
|
||||
|
||||
private void destroy() {
|
||||
this.cancel();
|
||||
User user = ability.getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
if (user.getActionBar() == ActionBar.ABILITY) user.setActionBar(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (ability.getInstance().getStaffManager().isStaffEnabled(player)) return;
|
||||
|
||||
if (!player.isOnline()) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack hand = ability.getManager().getItemInHand(player);
|
||||
Version version = ability.getInstance().getVersionManager().getVersion();
|
||||
|
||||
if (hand == null || !ability.isSimilar(hand)) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ability.getAbilityCooldown().hasTimer(player)) {
|
||||
destroy();
|
||||
version.sendActionBar(player, CC.t("&7"));
|
||||
return;
|
||||
}
|
||||
|
||||
User user = ability.getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
ActionBar actionBar = user.getActionBar();
|
||||
|
||||
if (actionBar == null) user.setActionBar(ActionBar.ABILITY);
|
||||
|
||||
if (actionBar == ActionBar.ABILITY) {
|
||||
version.sendActionBar(player, Config.ABILITY_ACTION_BAR_STRING
|
||||
.replace("%abilityname%", ability.getDisplayName())
|
||||
.replace("%remaining%", ability.getAbilityCooldown().getRemainingStringBoard(player))
|
||||
.replace("%actionbar%", Utils.getProgressBar(
|
||||
ability.getAbilityCooldown().getRemaining(player),
|
||||
ability.getAbilityCooldown().getSeconds() * 1000L,
|
||||
Config.ABILITY_ACTION_BAR_BARS,
|
||||
Config.ABILITY_ACTION_BAR_SYMBOL,
|
||||
Config.ABILITY_ACTION_BAR_YES_COLOR,
|
||||
Config.ABILITY_ACTION_BAR_NO_COLOR
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package me.keano.azurite.modules.ability.task;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TeleportTask extends BukkitRunnable {
|
||||
|
||||
private final Runnable finish;
|
||||
private final Consumer<Integer> increment;
|
||||
private final int max;
|
||||
private int i;
|
||||
|
||||
public TeleportTask(Ability ability, Runnable finish, Consumer<Integer> increment, int max) {
|
||||
this.finish = finish;
|
||||
this.increment = increment;
|
||||
this.max = max;
|
||||
this.i = 0;
|
||||
this.runTaskTimer(ability.getInstance(), 0L, 20L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (i == max) {
|
||||
finish.run();
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
increment.accept(i);
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.extra.Cooldown;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class AntiBuildAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Integer> hits;
|
||||
private final List<Material> deniedInteract;
|
||||
private final List<PotionEffect> effects;
|
||||
private final Cooldown antiBuild;
|
||||
|
||||
private final int maxHits;
|
||||
private final int antiBuildTime;
|
||||
|
||||
public AntiBuildAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Anti Build"
|
||||
);
|
||||
this.hits = new HashMap<>();
|
||||
this.deniedInteract = new ArrayList<>();
|
||||
this.effects = new ArrayList<>();
|
||||
this.antiBuild = new Cooldown(manager);
|
||||
|
||||
this.maxHits = getAbilitiesConfig().getInt(nameConfig + ".HITS_REQUIRED");
|
||||
this.antiBuildTime = getAbilitiesConfig().getInt(nameConfig + ".ANTI_BUILD_TIME");
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList(nameConfig + ".DISABLED_INTERACT")) {
|
||||
deniedInteract.add(ItemUtils.getMat(s));
|
||||
}
|
||||
|
||||
for (String s : getAbilitiesConfig().getStringList(nameConfig + ".EFFECTS_DAMAGER")) {
|
||||
effects.add(Serializer.getEffect(s));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
UUID damagerUUID = damager.getUniqueId();
|
||||
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
if (!hits.containsKey(damagerUUID)) hits.put(damagerUUID, 0);
|
||||
|
||||
int current = hits.get(damagerUUID) + 1;
|
||||
hits.put(damagerUUID, current);
|
||||
|
||||
if (current == maxHits) {
|
||||
hits.remove(damager.getUniqueId());
|
||||
antiBuild.applyCooldown(damaged, antiBuildTime);
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(damager, effect); // So it restores properly
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_BUILD.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
.replace("%seconds%", String.valueOf(antiBuildTime))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_BUILD.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(antiBuildTime))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBuild(BlockBreakEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
// Disable block breaking
|
||||
if (antiBuild.hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_BUILD.DENIED_BUILD")
|
||||
.replace("%seconds%", antiBuild.getRemaining(player))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBreak(BlockPlaceEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
// Disable block placing
|
||||
if (antiBuild.hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_BUILD.DENIED_BUILD")
|
||||
.replace("%seconds%", antiBuild.getRemaining(player))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getClickedBlock();
|
||||
|
||||
if (block == null) return;
|
||||
if (!antiBuild.hasCooldown(player)) return;
|
||||
|
||||
// Disable pressure plate interaction
|
||||
if (e.getAction() == Action.PHYSICAL) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable opening chests, etc...
|
||||
if (e.getAction() == Action.RIGHT_CLICK_BLOCK && deniedInteract.contains(block.getType())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_BUILD.DENIED_BUILD")
|
||||
.replace("%seconds%", antiBuild.getRemaining(player))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
hits.remove(player.getUniqueId());
|
||||
antiBuild.removeCooldown(player);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
hits.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiPearlAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Integer> hits;
|
||||
private final int maxHits;
|
||||
private final int seconds;
|
||||
|
||||
public AntiPearlAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Anti Pearl"
|
||||
);
|
||||
this.hits = new HashMap<>();
|
||||
this.maxHits = getAbilitiesConfig().getInt("ANTI_PEARL.HITS_REQUIRED");
|
||||
this.seconds = getAbilitiesConfig().getInt("ANTI_PEARL.ENDERPEARL_SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
UUID damagerUUID = damager.getUniqueId();
|
||||
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
if (!hits.containsKey(damagerUUID)) hits.put(damagerUUID, 0);
|
||||
|
||||
int current = hits.get(damagerUUID) + 1;
|
||||
hits.put(damagerUUID, current);
|
||||
|
||||
if (current == maxHits) {
|
||||
hits.remove(damagerUUID);
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
getInstance().getTimerManager().getEnderpearlTimer().applyTimer(damaged, seconds * 1000L);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_PEARL.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_PEARL.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.teams.Team;
|
||||
import me.keano.azurite.modules.teams.type.PlayerTeam;
|
||||
import me.keano.azurite.modules.teams.type.WildernessTeam;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiTrapBeaconAbility extends Ability {
|
||||
|
||||
private final List<Location> denied;
|
||||
private final List<Material> deniedInteract;
|
||||
private final Map<Location, BeaconData> beacons;
|
||||
|
||||
private final boolean denyPlace;
|
||||
private final boolean denyBreak;
|
||||
private final boolean denyInteract;
|
||||
|
||||
private final int radius;
|
||||
private final int despawn;
|
||||
private final int hitpoints;
|
||||
|
||||
public AntiTrapBeaconAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Anti Trap Beacon"
|
||||
);
|
||||
this.denied = new ArrayList<>(); // we need duplicates otherwise if 2 beacons placed near it will bug out.
|
||||
this.beacons = new HashMap<>();
|
||||
this.deniedInteract = getAbilitiesConfig().getStringList("ANTI_TRAP_BEACON.DENIED_INTERACT").stream().map(ItemUtils::getMat).collect(Collectors.toList());
|
||||
|
||||
this.denyPlace = getAbilitiesConfig().getBoolean("ANTI_TRAP_BEACON.DENY_PLACE");
|
||||
this.denyBreak = getAbilitiesConfig().getBoolean("ANTI_TRAP_BEACON.DENY_BREAK");
|
||||
this.denyInteract = getAbilitiesConfig().getBoolean("ANTI_TRAP_BEACON.DENY_INTERACT");
|
||||
|
||||
this.radius = getAbilitiesConfig().getInt("ANTI_TRAP_BEACON.RADIUS");
|
||||
this.despawn = getAbilitiesConfig().getInt("ANTI_TRAP_BEACON.DESPAWN");
|
||||
this.hitpoints = getAbilitiesConfig().getInt("ANTI_TRAP_BEACON.HITPOINTS");
|
||||
}
|
||||
|
||||
public void handlePlace(BlockPlaceEvent e, Team atPlace) {
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getBlock();
|
||||
Material replaced = e.getBlockReplacedState().getType();
|
||||
|
||||
if (!(atPlace instanceof PlayerTeam) && !(atPlace instanceof WildernessTeam)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_PLACE"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (replaced.isBlock() && replaced != Material.AIR) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.BLOCK_EMPTY"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!block.getRelative(BlockFace.DOWN).getType().isSolid()) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.BLOCK_BELOW"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerTeam pt = getInstance().getTeamManager().getByPlayer(player.getUniqueId());
|
||||
List<Location> cloned = new ArrayList<>();
|
||||
int oldX = block.getX();
|
||||
int oldY = block.getY();
|
||||
int oldZ = block.getZ();
|
||||
|
||||
applyCooldown(player);
|
||||
takeItem(player);
|
||||
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
Location location = new Location(player.getWorld(), oldX + x, oldY + y, oldZ + z);
|
||||
denied.add(location);
|
||||
cloned.add(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BeaconData data = new BeaconData(player.getUniqueId(), block.getLocation(), cloned, hitpoints);
|
||||
data.setRemoveTask(new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
destroyBeacon(data);
|
||||
data.setRemoveTask(null);
|
||||
}
|
||||
}.runTaskLater(getInstance(), despawn * 20L));
|
||||
|
||||
beacons.put(block.getLocation(), data);
|
||||
|
||||
if (pt != null) {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_BEACON.TEAM_MESSAGE")) {
|
||||
pt.broadcast(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%loc%", Utils.formatLocation(block.getLocation()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (atPlace instanceof PlayerTeam) {
|
||||
PlayerTeam enemyTeam = (PlayerTeam) atPlace;
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_BEACON.ENEMY_MESSAGE")) {
|
||||
enemyTeam.broadcast(s);
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_BEACON.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlace(BlockPlaceEvent e) {
|
||||
if (!denyPlace) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getBlock();
|
||||
|
||||
if (denied.contains(block.getLocation()) && !beacons.containsKey(block.getLocation())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_USE"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBreak(BlockBreakEvent e) {
|
||||
if (!denyBreak) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getBlock();
|
||||
|
||||
if (denied.contains(block.getLocation())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_USE"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBreakBeacon(BlockBreakEvent e) {
|
||||
if (beacons.containsKey(e.getBlock().getLocation())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("BLOCK")) return;
|
||||
if (!e.hasBlock()) return;
|
||||
if (!denyInteract) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getClickedBlock();
|
||||
BeaconData beacon = beacons.get(block.getLocation());
|
||||
|
||||
if (beacon != null) {
|
||||
e.setCancelled(true);
|
||||
beacon.setHitpoints(beacon.getHitpoints() - 1);
|
||||
|
||||
if (beacon.getHitpoints() <= 0) {
|
||||
destroyBeacon(beacon);
|
||||
|
||||
if (beacon.getRemoveTask() != null) {
|
||||
beacon.getRemoveTask().cancel();
|
||||
beacon.setRemoveTask(null);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (denied.contains(block.getLocation()) && deniedInteract.contains(block.getType())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_USE"));
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyBeacon(BeaconData data) {
|
||||
Player player = Bukkit.getPlayer(data.getPlayer());
|
||||
Block block = data.getLocation().getBlock();
|
||||
|
||||
if (block.getType() == item.getType()) {
|
||||
block.setType(Material.AIR);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.BEACON_DESTROYED"));
|
||||
}
|
||||
|
||||
for (Location location : data.getDenied()) {
|
||||
denied.remove(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private static class BeaconData {
|
||||
|
||||
private UUID player;
|
||||
private Location location;
|
||||
private List<Location> denied;
|
||||
private BukkitTask removeTask;
|
||||
private int hitpoints;
|
||||
|
||||
public BeaconData(UUID player, Location location, List<Location> denied, int hitpoints) {
|
||||
this.player = player;
|
||||
this.location = location;
|
||||
this.denied = denied;
|
||||
this.removeTask = null;
|
||||
this.hitpoints = hitpoints;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiTrapHaloAbility extends Ability {
|
||||
|
||||
private final Set<UUID> halo;
|
||||
private final List<Material> denied;
|
||||
private final int seconds;
|
||||
private final int radius;
|
||||
private final boolean denyPlace;
|
||||
private final boolean denyBreak;
|
||||
private final boolean denyInteract;
|
||||
|
||||
public AntiTrapHaloAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"AntiTrap Halo"
|
||||
);
|
||||
this.halo = new HashSet<>();
|
||||
this.denied = getAbilitiesConfig().getStringList("ANTITRAP_HALO.DENIED_INTERACT").stream().map(ItemUtils::getMat).collect(Collectors.toList());
|
||||
this.seconds = getAbilitiesConfig().getInt("ANTITRAP_HALO.SECONDS_ANTI_BUILD");
|
||||
this.radius = getAbilitiesConfig().getInt("ANTITRAP_HALO.RADIUS");
|
||||
this.denyPlace = getAbilitiesConfig().getBoolean("ANTITRAP_HALO.DENY_PLACE");
|
||||
this.denyBreak = getAbilitiesConfig().getBoolean("ANTITRAP_HALO.DENY_BREAK");
|
||||
this.denyInteract = getAbilitiesConfig().getBoolean("ANTITRAP_HALO.DENY_INTERACT");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
halo.add(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_HALO.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
Tasks.executeLater(getManager(), seconds * 20L, () -> {
|
||||
halo.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_HALO.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlace(BlockPlaceEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (denyPlace && checkNear(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_HALO.DENIED"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBreak(BlockBreakEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (denyBreak && checkNear(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_HALO.DENIED"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("BLOCK")) return;
|
||||
if (e.getClickedBlock() == null) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (denyInteract && denied.contains(e.getClickedBlock().getType()) && checkNear(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_HALO.DENIED"));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkNear(Player player) {
|
||||
for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player near = (Player) entity;
|
||||
|
||||
if (halo.contains(near.getUniqueId()) && !getInstance().getTeamManager().canHit(player, near, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.extra.Pair;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiTrapStarAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Pair<UUID, Long>> lastDamage;
|
||||
private final int hitsValid;
|
||||
private final int seconds;
|
||||
|
||||
public AntiTrapStarAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Anti Trap Star"
|
||||
);
|
||||
this.lastDamage = new HashMap<>();
|
||||
this.hitsValid = getAbilitiesConfig().getInt("ANTI_TRAP_STAR.HITS_VALID");
|
||||
this.seconds = getAbilitiesConfig().getInt("ANTI_TRAP_STAR.SECONDS");
|
||||
getManager().getTasks().add(Bukkit.getScheduler().runTaskTimer(getInstance(), this::cleanDamageStore, 0, (20 * 60) * 5L));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
Player damager = getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_STAR_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_STAR_ABILITY.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_STAR_ABILITY.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_STAR_ABILITY.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamageStore(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamagerProjectileOnly(e.getDamager()); // only projectiles for focus mode
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
lastDamage.put(damaged.getUniqueId(), new Pair<>(damager.getUniqueId(), System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
private void cleanDamageStore() {
|
||||
Iterator<Map.Entry<UUID, Pair<UUID, Long>>> iterator = lastDamage.entrySet().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<UUID, Long> pair = iterator.next().getValue();
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= (60 * 1000L); // 60s
|
||||
if (!valid) iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public Player getDamager(Player player, int secondsValid) {
|
||||
Pair<UUID, Long> pair = lastDamage.get(player.getUniqueId());
|
||||
|
||||
// This will get the last damage depending on the seconds it is valid till.
|
||||
if (pair != null) {
|
||||
Player damager = Bukkit.getPlayer(pair.getKey());
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= secondsValid * 1000L;
|
||||
|
||||
// Damager can be null if they logged out.
|
||||
if (damager != null && valid) {
|
||||
return damager;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class BelchBombAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> effects;
|
||||
private final int radius;
|
||||
|
||||
public BelchBombAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Belch Bomb"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("BELCH_BOMB.EFFECTS")
|
||||
.stream()
|
||||
.map(Serializer::getEffect)
|
||||
.collect(Collectors.toList());
|
||||
this.radius = getAbilitiesConfig().getInt("BELCH_BOMB.RADIUS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
int enemies = 0;
|
||||
|
||||
for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
Player target = (Player) entity;
|
||||
if (!getInstance().getTeamManager().canHit(player, target, false)) continue;
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(target, effect);
|
||||
}
|
||||
enemies++;
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.BELCH_BOMB.USED")) {
|
||||
player.sendMessage(s
|
||||
.replace("%enemies%", String.valueOf(enemies))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class BerserkAbility extends Ability {
|
||||
|
||||
private final Set<UUID> berserkers;
|
||||
private final Set<ItemStack> deniedPotions;
|
||||
private final Set<PotionEffect> effects;
|
||||
private final int berserkSeconds;
|
||||
|
||||
public BerserkAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Berserk"
|
||||
);
|
||||
this.berserkers = new HashSet<>();
|
||||
this.deniedPotions = new HashSet<>();
|
||||
this.effects = getAbilitiesConfig().getStringList("BERSERK.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toSet());
|
||||
this.berserkSeconds = getAbilitiesConfig().getInt("BERSERK.BERSERK_TIME");
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList("BERSERK.DENY_POTION")) {
|
||||
String[] split = s.split(", ");
|
||||
deniedPotions.add(ItemUtils.tryGetPotion(getManager(), ItemUtils.getMat(split[0]), Integer.parseInt(split[1])));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
berserkers.add(player.getUniqueId());
|
||||
Tasks.executeLater(getManager(), 20L * berserkSeconds, () -> berserkers.remove(player.getUniqueId()));
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.BERSERK.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onThrow(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
if (!getAbilitiesConfig().getBoolean("BERSERK.DENY_POT")) return;
|
||||
if (e.getItem() == null) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
ItemStack item = e.getItem();
|
||||
|
||||
if (!berserkers.contains(player.getUniqueId())) return;
|
||||
|
||||
for (ItemStack deniedPotion : deniedPotions) {
|
||||
if (deniedPotion.isSimilar(item)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.BERSERK.DENY_POT"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class CloseCallAbility extends Ability {
|
||||
|
||||
private final Set<PotionEffect> effects;
|
||||
private final String usageMessage;
|
||||
private final double healthRequired;
|
||||
|
||||
public CloseCallAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Close Call"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("CLOSE_CALL.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toSet());
|
||||
this.usageMessage = "%%__USER__%%";
|
||||
this.healthRequired = getAbilitiesConfig().getDouble("CLOSE_CALL.HEALTH_REQUIRED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
if ((player.getHealth() / 2.0) <= healthRequired) {
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CLOSE_CALL.USED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CLOSE_CALL.USED_UNSUCCESSFULLY")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class ComboAbility extends Ability {
|
||||
|
||||
private final Set<UUID> combo;
|
||||
private final Map<UUID, Integer> hits;
|
||||
private final int maxHits;
|
||||
private final int amountPerHit;
|
||||
private final int seconds;
|
||||
|
||||
public ComboAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Combo Ability"
|
||||
);
|
||||
this.combo = new HashSet<>();
|
||||
this.hits = new HashMap<>();
|
||||
this.maxHits = getAbilitiesConfig().getInt("COMBO_ABILITY.MAX_HITS");
|
||||
this.amountPerHit = getAbilitiesConfig().getInt("COMBO_ABILITY.AMOUNT_PER_HIT");
|
||||
this.seconds = getAbilitiesConfig().getInt("COMBO_ABILITY.SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
combo.add(player.getUniqueId());
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> handleEffect(player));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.COMBO_ABILITY.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onHit(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
UUID damagerUUID = damager.getUniqueId();
|
||||
|
||||
if (combo.contains(damagerUUID)) {
|
||||
hits.putIfAbsent(damagerUUID, 0);
|
||||
int current = hits.get(damagerUUID);
|
||||
|
||||
if (current < maxHits) {
|
||||
hits.put(damagerUUID, current + amountPerHit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
hits.remove(player.getUniqueId());
|
||||
combo.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
private void handleEffect(Player player) {
|
||||
Integer amount = hits.remove(player.getUniqueId());
|
||||
combo.remove(player.getUniqueId());
|
||||
|
||||
if (amount != null) {
|
||||
String[] split = getAbilitiesConfig().getString("COMBO_ABILITY.EFFECT").split(", ");
|
||||
PotionEffectType type = PotionEffectType.getByName(split[0]);
|
||||
int amplifier = Integer.parseInt(split[1]) - 1;
|
||||
getInstance().getClassManager().addEffect(player, new PotionEffect(type, 20 * amount, amplifier));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.COMBO_ABILITY.GAINED_EFFECT")) {
|
||||
player.sendMessage(s
|
||||
.replace("%amount%", String.valueOf(amount))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class CraftingChaosAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Integer> hits;
|
||||
private final Map<UUID, UUID> craftingChaos;
|
||||
private final int seconds;
|
||||
private final int maxHits;
|
||||
private final int chance;
|
||||
|
||||
public CraftingChaosAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Crafting Chaos"
|
||||
);
|
||||
this.hits = new HashMap<>();
|
||||
this.craftingChaos = new HashMap<>();
|
||||
this.seconds = getAbilitiesConfig().getInt("CRAFTING_CHAOS.SECONDS");
|
||||
this.maxHits = getAbilitiesConfig().getInt("CRAFTING_CHAOS.HITS_REQUIRED");
|
||||
this.chance = getAbilitiesConfig().getInt("CRAFTING_CHAOS.CHANCE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
UUID damagerUUID = damager.getUniqueId();
|
||||
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
if (!hits.containsKey(damagerUUID)) hits.put(damagerUUID, 0);
|
||||
|
||||
int current = hits.get(damagerUUID) + 1;
|
||||
hits.put(damagerUUID, current);
|
||||
|
||||
if (current == maxHits) {
|
||||
hits.remove(damagerUUID);
|
||||
craftingChaos.put(damagerUUID, damaged.getUniqueId());
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
craftingChaos.remove(damagerUUID);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.EXPIRED")) {
|
||||
damager.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = (Player) e.getDamager();
|
||||
|
||||
if (!craftingChaos.containsKey(damager.getUniqueId())) return;
|
||||
if (!craftingChaos.get(damager.getUniqueId()).equals(damaged.getUniqueId())) return;
|
||||
|
||||
if (ThreadLocalRandom.current().nextInt(100 + 1) <= chance) {
|
||||
damaged.openWorkbench(null, true);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.MADE_OPEN"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
hits.remove(player.getUniqueId());
|
||||
craftingChaos.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.fastparticles.ParticleType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class ExplosiveEggAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> ballsThrown;
|
||||
private final ParticleType particleType;
|
||||
private final double multiplier;
|
||||
private final double yMultiplier;
|
||||
private final int radius;
|
||||
|
||||
public ExplosiveEggAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Explosive Egg"
|
||||
);
|
||||
this.ballsThrown = new HashMap<>();
|
||||
this.particleType = ParticleType.of(getAbilitiesConfig().getString("EXPLOSIVE_EGG.EFFECT"));
|
||||
this.multiplier = getAbilitiesConfig().getDouble("EXPLOSIVE_EGG.MULTIPLIER");
|
||||
this.yMultiplier = getAbilitiesConfig().getDouble("EXPLOSIVE_EGG.Y_MULTIPLIER");
|
||||
this.radius = getAbilitiesConfig().getInt("EXPLOSIVE_EGG.RADIUS");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory(); // Refund item
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onThrow(ProjectileLaunchEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
Player player = Utils.getDamager(projectile);
|
||||
|
||||
if (player == null) return;
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
ballsThrown.put(projectile.getUniqueId(), player.getUniqueId());
|
||||
applyCooldown(player);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.EXPLOSIVE_EGG.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLand(ProjectileHitEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
UUID uuid = ballsThrown.remove(projectile.getUniqueId());
|
||||
|
||||
if (uuid != null) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) return;
|
||||
|
||||
particleType.spawn(player.getWorld(), projectile.getLocation(), 1);
|
||||
|
||||
for (Entity entity : projectile.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player other = (Player) entity;
|
||||
|
||||
if (getInstance().getTeamManager().canHit(player, other, false)) {
|
||||
pullEntityToLocation(other, player.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pullEntityToLocation(Entity entity, Location loc) {
|
||||
Vector explosion = loc.toVector().subtract(entity.getLocation().toVector());
|
||||
explosion.multiply(multiplier);
|
||||
explosion.setY(explosion.getY() + yMultiplier);
|
||||
entity.setVelocity(explosion);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.extra.Pair;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class FocusModeAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> focusMode;
|
||||
private final Map<UUID, Pair<UUID, Long>> lastDamage;
|
||||
private final double multiplier;
|
||||
private final int seconds;
|
||||
private final int hitsValid;
|
||||
|
||||
public FocusModeAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Focus Mode"
|
||||
);
|
||||
this.focusMode = new HashMap<>();
|
||||
this.lastDamage = new HashMap<>();
|
||||
this.multiplier = getAbilitiesConfig().getDouble("FOCUS_MODE.DAMAGE_MULTIPLIER");
|
||||
this.seconds = getAbilitiesConfig().getInt("FOCUS_MODE.SECONDS");
|
||||
this.hitsValid = getAbilitiesConfig().getInt("FOCUS_MODE.HITS_VALID");
|
||||
getManager().getTasks().add(Bukkit.getScheduler().runTaskTimer(getInstance(), this::cleanDamageStore, 0L, (20 * 60) * 5L));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
Player damager = getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.FOCUS_MODE.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
focusMode.put(player.getUniqueId(), damager.getUniqueId());
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
focusMode.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.FOCUS_MODE.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.FOCUS_MODE.USED"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.FOCUS_MODE.BEEN_HIT"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
);
|
||||
}
|
||||
|
||||
// Focus Mode = LOW, Archer Class = NORMAL, Strength = HIGH
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = (Player) e.getDamager();
|
||||
|
||||
if (!focusMode.containsKey(damager.getUniqueId())) return;
|
||||
if (!focusMode.get(damager.getUniqueId()).equals(damaged.getUniqueId())) return;
|
||||
|
||||
e.setDamage(e.getDamage() * multiplier);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
focusMode.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamageStore(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
lastDamage.put(damaged.getUniqueId(), new Pair<>(damager.getUniqueId(), System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
private void cleanDamageStore() {
|
||||
Iterator<Map.Entry<UUID, Pair<UUID, Long>>> iterator = lastDamage.entrySet().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<UUID, Long> pair = iterator.next().getValue();
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= (60 * 1000L); // 60s
|
||||
if (!valid) iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public Player getDamager(Player player, int secondsValid) {
|
||||
Pair<UUID, Long> pair = lastDamage.get(player.getUniqueId());
|
||||
|
||||
// This will get the last damage depending on the seconds it is valid till.
|
||||
if (pair != null) {
|
||||
Player damager = Bukkit.getPlayer(pair.getKey());
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= secondsValid * 1000L;
|
||||
|
||||
// Damager can be null if they logged out.
|
||||
if (damager != null && valid) {
|
||||
return damager;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.FishHook;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerFishEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class GrappleAbility extends Ability {
|
||||
|
||||
private static final Field HOOK_ENTITY = ReflectionUtils.accessField(org.bukkit.event.player.PlayerFishEvent.class, "hookEntity");
|
||||
|
||||
private final double multiplier;
|
||||
private final double yMultiplier;
|
||||
|
||||
public GrappleAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Grapple"
|
||||
);
|
||||
this.multiplier = getAbilitiesConfig().getDouble("GRAPPLE.MULTIPLIER");
|
||||
this.yMultiplier = getAbilitiesConfig().getDouble("GRAPPLE.Y_MULTIPLIER");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLaunch(PlayerInteractEvent e) {
|
||||
if (!(e.getAction().name().contains("RIGHT"))) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFish(PlayerFishEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
// State when the rod is in the air
|
||||
if (e.getState() == PlayerFishEvent.State.FISHING) return;
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
// FOR SOME FUCKING REASON "FISH" ENTITY DOESN'T FUCKING WORK ON 1.16+ FUCK
|
||||
try {
|
||||
|
||||
applyCooldown(player);
|
||||
takeItem(player);
|
||||
pullEntityToLocation(player, (Utils.isModernVer() ? (FishHook) HOOK_ENTITY.get(e) : e.getHook()));
|
||||
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void pullEntityToLocation(Entity entity, Entity loc) {
|
||||
if (loc.getLocation().subtract(0, 1, 0).getBlock().getType() == Material.AIR) return;
|
||||
Vector grapple = loc.getLocation().toVector().subtract(entity.getLocation().toVector());
|
||||
grapple.multiply(multiplier);
|
||||
grapple.setY(grapple.getY() + yMultiplier);
|
||||
entity.setVelocity(grapple);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class InvisibilityAbility extends Ability {
|
||||
|
||||
private final Set<UUID> invisible;
|
||||
private final PotionEffect invisEffect;
|
||||
private final boolean removeInvis;
|
||||
|
||||
public InvisibilityAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Invisibility"
|
||||
);
|
||||
this.invisible = new HashSet<>();
|
||||
this.invisEffect = Serializer.getEffect(getAbilitiesConfig().getString("INVISIBILITY.INVIS_EFFECT"));
|
||||
this.removeInvis = getAbilitiesConfig().getBoolean("INVISIBILITY.TAKE_INVIS_ON_HIT");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
hideArmor(player);
|
||||
|
||||
if (!player.hasPotionEffect(PotionEffectType.INVISIBILITY)) {
|
||||
getInstance().getClassManager().addEffect(player, invisEffect);
|
||||
}
|
||||
|
||||
// Ticks later
|
||||
Tasks.executeLater(getManager(), 5L, () -> invisible.add(player.getUniqueId()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.INVISIBILITY.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
player.setFireTicks(0);
|
||||
getInstance().getVersionManager().getVersion().clearArrows(player);
|
||||
|
||||
Tasks.executeLater(getManager(), invisEffect.getDuration(), () -> {
|
||||
if (player.isOnline() && invisible.remove(player.getUniqueId())) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.INVISIBILITY.EXPIRED"));
|
||||
}
|
||||
|
||||
// Ticks later
|
||||
Tasks.executeLater(getManager(), 5L, () -> showArmor(player));
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
for (UUID uuid : invisible) {
|
||||
Player toRemove = Bukkit.getPlayer(uuid);
|
||||
if (toRemove != null) hideArmor(player);
|
||||
}
|
||||
|
||||
getInstance().getVersionManager().getVersion().handleNettyListener(player);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
if (invisible.remove(damaged.getUniqueId())) {
|
||||
if (removeInvis) {
|
||||
damaged.removePotionEffect(PotionEffectType.INVISIBILITY);
|
||||
}
|
||||
|
||||
damaged.sendMessage(getLanguageConfig().getString("ABILITIES.INVISIBILITY.DAMAGED"));
|
||||
Tasks.executeLater(getManager(), 5L, () -> showArmor(damaged));
|
||||
}
|
||||
}
|
||||
|
||||
private void hideArmor(Player player) {
|
||||
getInstance().getVersionManager().getVersion().hideArmor(player);
|
||||
}
|
||||
|
||||
private void showArmor(Player player) {
|
||||
getInstance().getVersionManager().getVersion().showArmor(player);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class LightningAbility extends Ability {
|
||||
|
||||
private final List<UUID> lightnings;
|
||||
private final int chance;
|
||||
private final int seconds;
|
||||
private final double damage;
|
||||
|
||||
public LightningAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Lightning"
|
||||
);
|
||||
this.lightnings = new ArrayList<>();
|
||||
this.chance = getAbilitiesConfig().getInt("LIGHTNING.CHANCE");
|
||||
this.seconds = getAbilitiesConfig().getInt("LIGHTNING.SECONDS");
|
||||
this.damage = getAbilitiesConfig().getDouble("LIGHTNING.DAMAGE") * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
lightnings.add(player.getUniqueId());
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
lightnings.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (lightnings.contains(damager.getUniqueId()) && ThreadLocalRandom.current().nextInt(100 + 1) <= chance) {
|
||||
damaged.getWorld().strikeLightningEffect(damaged.getLocation());
|
||||
damaged.setHealth(Math.max(damaged.getHealth() - damage, 0D));
|
||||
e.setDamage(0D); // We only do the lightning damage
|
||||
|
||||
// Fix double death bug
|
||||
if (damaged.isDead()) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.STRUCK_LIGHTNING"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.STRUCK_BY_LIGHTNING"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
lightnings.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class LuckyModeAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Double> luckyMode;
|
||||
private final DecimalFormat formatter;
|
||||
private final double minimum;
|
||||
private final double maximum;
|
||||
private final int seconds;
|
||||
|
||||
public LuckyModeAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Lucky Mode"
|
||||
);
|
||||
this.luckyMode = new HashMap<>();
|
||||
this.formatter = new DecimalFormat("##");
|
||||
this.minimum = getAbilitiesConfig().getDouble("LUCKY_MODE.MINIMUM_MULTIPLIER");
|
||||
this.maximum = getAbilitiesConfig().getDouble("LUCKY_MODE.MAXIMUM_MULTIPLIER");
|
||||
this.seconds = getAbilitiesConfig().getInt("LUCKY_MODE.SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
double multiplier = ThreadLocalRandom.current().nextDouble(minimum, maximum + 1);
|
||||
luckyMode.put(player.getUniqueId(), multiplier);
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
luckyMode.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LUCKY_MODE.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LUCKY_MODE.USED"))
|
||||
player.sendMessage(s
|
||||
.replace("%amount%", formatter.format(multiplier))
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
|
||||
if (!luckyMode.containsKey(damager.getUniqueId())) return;
|
||||
|
||||
double percent = luckyMode.get(damager.getUniqueId());
|
||||
|
||||
// No change
|
||||
if (percent == 0) return;
|
||||
|
||||
// This will convert 35% to actual percent (1.35, 1.25, 0.90) etc..
|
||||
if (percent > 0) {
|
||||
e.setDamage(e.getDamage() * (percent / 100 + 1));
|
||||
|
||||
} else {
|
||||
e.setDamage(e.getDamage() * (1 / (Math.abs(percent) / 100 + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
luckyMode.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class MagicRockAbility extends Ability {
|
||||
|
||||
private final Map<Integer, PotionEffect> effects;
|
||||
|
||||
public MagicRockAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Magic Rock"
|
||||
);
|
||||
this.effects = new HashMap<>();
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList("MAGIC_ROCK.EFFECTS_PER_BLOCK")) {
|
||||
String[] split = s.split(": ");
|
||||
effects.put(Integer.parseInt(split[0]), Serializer.getEffect(split[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
|
||||
int height = getBaseHeight(damaged);
|
||||
PotionEffect effect = effects.get(height);
|
||||
|
||||
if (height == 0 || effect == null) {
|
||||
damager.sendMessage(getLanguageConfig().getString("ABILITIES.MAGIC_ROCK.NOT_FOUND"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
getInstance().getClassManager().addEffect(damager, effect);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.MAGIC_ROCK.USED")) {
|
||||
damager.sendMessage(s
|
||||
.replace("%height%", String.valueOf(height))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public int getBaseHeight(Player player) {
|
||||
Location location = player.getLocation().clone();
|
||||
|
||||
int height = 0;
|
||||
|
||||
for (int i = location.getBlockY(); i < location.getWorld().getMaxHeight(); i++) {
|
||||
Block block = location.getWorld().getBlockAt(location.getBlockX(), i, location.getBlockZ());
|
||||
|
||||
if (block.getType() != Material.AIR && block.getType().isBlock()) {
|
||||
height = i - location.getBlockY();
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class MedKitAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> effects;
|
||||
|
||||
public MedKitAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Med Kit"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("MED_KIT.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.MED_KIT.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class NinjaAbility extends Ability {
|
||||
|
||||
private final int seconds;
|
||||
private final int hitsValid;
|
||||
|
||||
public NinjaAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Ninja Ability"
|
||||
);
|
||||
this.seconds = getAbilitiesConfig().getInt("NINJA_ABILITY.SECONDS");
|
||||
this.hitsValid = getAbilitiesConfig().getInt("NINJA_ABILITY.HITS_VALID");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
// I already coded a way to get last damager for focus mode, so just use that.
|
||||
Player damager = ((FocusModeAbility) getManager().getAbility("FocusMode")).getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.NINJA_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.NINJA_ABILITY.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.NINJA_ABILITY.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.NINJA_ABILITY.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%target%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.framework.menu.Menu;
|
||||
import me.keano.azurite.modules.framework.menu.MenuManager;
|
||||
import me.keano.azurite.modules.framework.menu.button.Button;
|
||||
import me.keano.azurite.modules.pvpclass.PvPClassManager;
|
||||
import me.keano.azurite.modules.pvpclass.type.bard.BardEffect;
|
||||
import me.keano.azurite.utils.ItemBuilder;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class PocketBardAbility extends Ability {
|
||||
|
||||
private final Map<String, PocketBard> pocketBards;
|
||||
|
||||
public PocketBardAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"PocketBard"
|
||||
);
|
||||
this.pocketBards = new HashMap<>();
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String key : getAbilitiesConfig().getConfigurationSection("POCKETBARD.TYPES").getKeys(false)) {
|
||||
String path = "POCKETBARD.TYPES." + key + ".";
|
||||
ItemStack item = new ItemBuilder(ItemUtils.getMat(getAbilitiesConfig().getString(path + "MATERIAL")))
|
||||
.setName(getAbilitiesConfig().getString(path + "NAME"))
|
||||
.setLore(getAbilitiesConfig().getStringList(path + "LORE"))
|
||||
.data(getManager(), (short) getAbilitiesConfig().getInt(path + "DATA"))
|
||||
.toItemStack();
|
||||
|
||||
item.setAmount(getAbilitiesConfig().getInt(path + "AMOUNT"));
|
||||
pocketBards.put(key, new PocketBard(
|
||||
getInstance().getClassManager(),
|
||||
Serializer.getEffect(getAbilitiesConfig().getString(path + "EFFECT")),
|
||||
(getAbilitiesConfig().getBoolean(nameConfig + ".ADD_GLOW") ?
|
||||
getInstance().getVersionManager().getVersion().addGlow(item) :
|
||||
item))
|
||||
);
|
||||
}
|
||||
|
||||
// This will handle the menu items.
|
||||
for (String key : getAbilitiesConfig().getConfigurationSection("POCKETBARD.POCKETBARD_MENU.ITEMS").getKeys(false)) {
|
||||
String path = "POCKETBARD.POCKETBARD_MENU.ITEMS." + key + ".";
|
||||
PocketBard pocketBard = pocketBards.get(getAbilitiesConfig().getString(path + "POCKET_BARD"));
|
||||
ItemBuilder builder = new ItemBuilder(ItemUtils.getMat(getAbilitiesConfig().getString(path + "MATERIAL")))
|
||||
.setName(getAbilitiesConfig().getString(path + "NAME"))
|
||||
.setLore(getAbilitiesConfig().getStringList(path + "LORE"))
|
||||
.data(getManager(), (short) getAbilitiesConfig().getInt(path + "DATA"));
|
||||
|
||||
pocketBard.setMenuItem(builder.toItemStack());
|
||||
pocketBard.setSlot(getAbilitiesConfig().getInt(path + "SLOT"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
new PocketBardMenu(getInstance().getMenuManager(), this, player).open();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteractPocket(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
PocketBard pocketBard = getPocketBardInHand(player);
|
||||
|
||||
if (pocketBard != null) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
pocketBard.getEffect().applyEffect(player);
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public PocketBard getPocketBardInHand(Player player) {
|
||||
ItemStack hand = getManager().getItemInHand(player);
|
||||
|
||||
if (hand == null) return null;
|
||||
|
||||
for (PocketBard pocketBard : pocketBards.values()) {
|
||||
if (!pocketBard.getItem().isSimilar(hand)) continue;
|
||||
return pocketBard;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private static class PocketBard {
|
||||
|
||||
private BardEffect effect;
|
||||
private ItemStack item;
|
||||
private ItemStack menuItem;
|
||||
private int slot;
|
||||
|
||||
public PocketBard(PvPClassManager manager, PotionEffect effect, ItemStack item) {
|
||||
this.effect = new BardEffect(manager, true, effect);
|
||||
this.item = item;
|
||||
this.menuItem = null;
|
||||
this.slot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PocketBardMenu extends Menu {
|
||||
|
||||
private final PocketBardAbility ability;
|
||||
|
||||
public PocketBardMenu(MenuManager manager, PocketBardAbility ability, Player player) {
|
||||
super(
|
||||
manager,
|
||||
player,
|
||||
manager.getAbilitiesConfig().getString("POCKETBARD.POCKETBARD_MENU.TITLE"),
|
||||
manager.getAbilitiesConfig().getInt("POCKETBARD.POCKETBARD_MENU.SIZE"),
|
||||
false
|
||||
);
|
||||
this.ability = ability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Button> getButtons(Player player) {
|
||||
Map<Integer, Button> buttons = new HashMap<>();
|
||||
|
||||
for (PocketBard pocketBard : ability.getPocketBards().values()) {
|
||||
buttons.put(pocketBard.getSlot(), new Button() {
|
||||
@Override
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
// Check first and then check after aswell.
|
||||
if (!ability.hasAbilityInHand(player)) {
|
||||
e.setCancelled(true);
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
e.setCancelled(true);
|
||||
getManager().takeItemInHand(player, 1);
|
||||
ItemUtils.giveItem(player, pocketBard.getItem(), player.getLocation());
|
||||
if (!ability.hasAbilityInHand(player)) player.closeInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack() {
|
||||
return pocketBard.getMenuItem();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.type.archer.ArcherClass;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class PortableArcherAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> usedPortableArcher; // player -> arrow
|
||||
|
||||
public PortableArcherAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Portable Archer"
|
||||
);
|
||||
this.usedPortableArcher = new HashMap<>();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onShoot(EntityShootBowEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player player = (Player) e.getEntity();
|
||||
ItemStack bow = e.getBow();
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
usedPortableArcher.put(player.getUniqueId(), e.getProjectile().getUniqueId());
|
||||
getManager().setData(bow, getManager().getData(bow) + 1);
|
||||
|
||||
if (getManager().getData(bow) == bow.getType().getMaxDurability()) {
|
||||
getManager().takeItemInHand(player, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDamage(PlayerItemDamageEvent e) {
|
||||
ItemStack damage = e.getItem();
|
||||
|
||||
if (!damage.hasItemMeta()) return;
|
||||
if (!damage.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
ItemMeta itemMeta = damage.getItemMeta();
|
||||
ItemMeta abilityMeta = item.getItemMeta();
|
||||
|
||||
if (itemMeta.getDisplayName().equals(abilityMeta.getDisplayName()) && itemMeta.getLore().equals(abilityMeta.getLore())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Arrow)) return;
|
||||
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
|
||||
UUID arrow = usedPortableArcher.remove(damager.getUniqueId());
|
||||
|
||||
if (arrow != null && e.getDamager().getUniqueId().equals(arrow)) {
|
||||
ArcherClass archerClass = getInstance().getClassManager().getArcherClass();
|
||||
if (archerClass != null) archerClass.archerTag(e);
|
||||
applyCooldown(damager);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.type.bard.BardEffect;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.extra.Cooldown;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class PortableBardAbility extends Ability {
|
||||
|
||||
private final Map<UUID, PortableBard> portableBards;
|
||||
private final Map<UUID, UUID> byEntity;
|
||||
private final List<PortableBardEffect> effects;
|
||||
|
||||
private final Cooldown regenCooldown;
|
||||
private final EntityType entityType;
|
||||
private final String name;
|
||||
private final int radius;
|
||||
private final int timeUpgrade;
|
||||
private final int health;
|
||||
private final int timeAlive;
|
||||
|
||||
public PortableBardAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Portable Bard"
|
||||
);
|
||||
this.portableBards = new HashMap<>();
|
||||
this.byEntity = new HashMap<>();
|
||||
this.effects = new ArrayList<>();
|
||||
|
||||
this.regenCooldown = new Cooldown(getManager());
|
||||
this.entityType = EntityType.valueOf(getAbilitiesConfig().getString("PORTABLE_BARD.ENTITY_TYPE"));
|
||||
this.name = getAbilitiesConfig().getString("PORTABLE_BARD.NAME");
|
||||
this.radius = getAbilitiesConfig().getInt("PORTABLE_BARD.RADIUS");
|
||||
this.timeUpgrade = getAbilitiesConfig().getInt("PORTABLE_BARD.UPGRADE_EVERY");
|
||||
this.health = getAbilitiesConfig().getInt("PORTABLE_BARD.HEALTH");
|
||||
this.timeAlive = getAbilitiesConfig().getInt("PORTABLE_BARD.TIME_ALIVE");
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String key : getAbilitiesConfig().getConfigurationSection("PORTABLE_BARD.EFFECTS").getKeys(false)) {
|
||||
String path = "PORTABLE_BARD.EFFECTS." + key + ".";
|
||||
effects.add(new PortableBardEffect(
|
||||
Serializer.getEffect(getAbilitiesConfig().getString(path + "EFFECT")),
|
||||
Serializer.getEffect(getAbilitiesConfig().getString(path + "EFFECT_UPGRADE")),
|
||||
ItemUtils.getMatItem(getAbilitiesConfig().getString(path + "MATERIAL"))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
for (PortableBard portableBard : portableBards.values()) {
|
||||
portableBard.getLivingEntity().remove();
|
||||
portableBard.getTickTask().cancel();
|
||||
}
|
||||
|
||||
byEntity.clear();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
if (!e.hasItem()) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Location toSpawn = (e.hasBlock() ? e.getClickedBlock().getLocation().add(0.5, 1.0, 0.5) : player.getLocation());
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
e.setCancelled(true);
|
||||
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
if (getInstance().getTimerManager().getPvpTimer().hasTimer(player)) return;
|
||||
if (getInstance().getTimerManager().getInvincibilityTimer().hasTimer(player)) return;
|
||||
|
||||
PortableBard old = portableBards.remove(player.getUniqueId());
|
||||
|
||||
if (old != null) {
|
||||
byEntity.remove(old.getLivingEntity().getUniqueId());
|
||||
old.delete();
|
||||
}
|
||||
|
||||
PortableBard portableBard = new PortableBard(player, toSpawn, entityType);
|
||||
portableBards.put(player.getUniqueId(), portableBard);
|
||||
byEntity.put(portableBard.getLivingEntity().getUniqueId(), player.getUniqueId());
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof LivingEntity)) return;
|
||||
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
LivingEntity entity = (LivingEntity) e.getEntity();
|
||||
UUID playerBard = byEntity.get(entity.getUniqueId());
|
||||
|
||||
if (playerBard != null) {
|
||||
PortableBard portableBard = portableBards.get(playerBard);
|
||||
|
||||
if (portableBard != null) {
|
||||
if (damager.getUniqueId() == portableBard.getPlayer().getUniqueId() ||
|
||||
!getInstance().getTeamManager().canHit(damager, portableBard.getPlayer(), false)) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
e.setDamage(0D);
|
||||
portableBard.setHealth(portableBard.getHealth() - 1);
|
||||
portableBard.updateName();
|
||||
|
||||
if (portableBard.getHealth() <= 0) {
|
||||
portableBard.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(EntityDeathEvent e) {
|
||||
if (byEntity.containsKey(e.getEntity().getUniqueId())) {
|
||||
e.getDrops().clear();
|
||||
e.setDroppedExp(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class PortableBardTask extends BukkitRunnable {
|
||||
|
||||
private final PortableBard portableBard;
|
||||
private int i;
|
||||
|
||||
public PortableBardTask(PortableBard portableBard) {
|
||||
this.portableBard = portableBard;
|
||||
this.i = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (portableBard.getLivingEntity().isDead() || i == timeAlive) {
|
||||
portableBard.delete();
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = portableBard.getPlayer();
|
||||
PortableBardEffect random = effects.get(ThreadLocalRandom.current().nextInt(effects.size()));
|
||||
|
||||
for (PortableBardEffect effect : effects) {
|
||||
if (effect.getEffect() == null) continue;
|
||||
|
||||
if (effect.getEffect().getEffect().getType().equals(PotionEffectType.REGENERATION)) {
|
||||
if (regenCooldown.hasCooldown(player)) continue;
|
||||
regenCooldown.applyCooldownTicks(player, 3000);
|
||||
}
|
||||
|
||||
if (shouldEffectPlayer()) {
|
||||
getInstance().getClassManager().addEffect(player, effect.getEffect().getEffect());
|
||||
}
|
||||
|
||||
effect.getEffect().applyEffect(player);
|
||||
}
|
||||
|
||||
if (i % timeUpgrade == 0 && i != 0) {
|
||||
if (shouldEffectPlayer()) {
|
||||
getInstance().getClassManager().addEffect(player, random.getUpgrade().getEffect());
|
||||
}
|
||||
|
||||
random.getUpgrade().applyEffect(player);
|
||||
}
|
||||
|
||||
i++;
|
||||
portableBard.getLivingEntity().getEquipment().setItemInHand(random.getHand());
|
||||
portableBard.updateName();
|
||||
}
|
||||
|
||||
public boolean shouldEffectPlayer() {
|
||||
return portableBard.getLivingEntity().getLocation().distance(portableBard.getPlayer().getLocation()) <= radius;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public class PortableBardEffect {
|
||||
|
||||
private final BardEffect effect;
|
||||
private final BardEffect upgrade;
|
||||
private final ItemStack hand;
|
||||
|
||||
public PortableBardEffect(PotionEffect effect, PotionEffect upgrade, ItemStack hand) {
|
||||
this.effect = (effect != null ? new BardEffect(getInstance().getClassManager(), false, effect) : null);
|
||||
this.upgrade = (upgrade != null ? new BardEffect(getInstance().getClassManager(), false, upgrade) : null);
|
||||
this.hand = hand;
|
||||
if (effect != null && upgrade != null) load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
effect.setEffectSelf(false);
|
||||
upgrade.setEffectSelf(false);
|
||||
effect.setBardDistance(radius);
|
||||
upgrade.setBardDistance(radius);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PortableBard {
|
||||
|
||||
private Player player;
|
||||
private LivingEntity livingEntity;
|
||||
private BukkitTask tickTask;
|
||||
private int health;
|
||||
|
||||
public PortableBard(Player player, Location location, EntityType entityType) {
|
||||
if (!entityType.isAlive()) {
|
||||
throw new IllegalArgumentException("Portable bard has to be a living entity");
|
||||
}
|
||||
|
||||
this.player = player;
|
||||
this.livingEntity = (LivingEntity) location.getWorld().spawnEntity(location, entityType);
|
||||
this.tickTask = new PortableBardTask(this).runTaskTimer(getInstance(), 0, 20);
|
||||
this.health = PortableBardAbility.this.health;
|
||||
|
||||
// Equipment
|
||||
livingEntity.getEquipment().setHelmet(new ItemStack(ItemUtils.getMat("GOLD_HELMET")));
|
||||
livingEntity.getEquipment().setChestplate(new ItemStack(ItemUtils.getMat("GOLD_CHESTPLATE")));
|
||||
livingEntity.getEquipment().setLeggings(new ItemStack(ItemUtils.getMat("GOLD_LEGGINGS")));
|
||||
livingEntity.getEquipment().setBoots(new ItemStack(ItemUtils.getMat("GOLD_BOOTS")));
|
||||
|
||||
// Name
|
||||
livingEntity.setCustomNameVisible(true);
|
||||
this.updateName();
|
||||
|
||||
// So they can't move
|
||||
livingEntity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, Integer.MAX_VALUE, 100, false, false));
|
||||
livingEntity.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 100, false, false));
|
||||
|
||||
// Make sure Adult
|
||||
if (livingEntity instanceof Ageable) {
|
||||
Ageable ageable = (Ageable) livingEntity;
|
||||
ageable.setAdult();
|
||||
ageable.setBreed(false);
|
||||
ageable.setAgeLock(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateName() {
|
||||
livingEntity.setCustomName(name
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%health%", String.valueOf(health)));
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
portableBards.remove(player.getUniqueId());
|
||||
byEntity.remove(livingEntity.getUniqueId());
|
||||
livingEntity.remove();
|
||||
tickTask.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.cooldown.CustomCooldown;
|
||||
import me.keano.azurite.modules.pvpclass.type.rogue.RogueBackstabEvent;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class PortableRogueAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> backstabEffects;
|
||||
|
||||
public PortableRogueAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Portable Rogue"
|
||||
);
|
||||
this.backstabEffects = new ArrayList<>();
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
this.backstabEffects.addAll(getAbilitiesConfig().getStringList("PORTABLE_ROGUE.BACKSTAB_EFFECTS")
|
||||
.stream()
|
||||
.map(Serializer::getEffect)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (!hasAbilityInHand(damager)) return;
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
|
||||
// Used to calculate the direction to make sure they are behind the player.
|
||||
Vector damagerVector = damager.getLocation().getDirection().setY(0);
|
||||
Vector damagedVector = damaged.getLocation().getDirection().setY(0);
|
||||
CustomCooldown backstabCooldown = getInstance().getClassManager().getRogueClass().getBackstabCooldown();
|
||||
|
||||
double degree = damagerVector.angle(damagedVector);
|
||||
double backstabDamage = getAbilitiesConfig().getDouble("PORTABLE_ROGUE.BACKSTAB_DAMAGE") * 2.0;
|
||||
|
||||
if (Math.abs(degree) < 1.4) {
|
||||
if (backstabCooldown.hasCooldown(damager)) {
|
||||
damager.sendMessage(getLanguageConfig().getString("PVP_CLASSES.ROGUE_CLASS.BACKSTAB_COOLDOWN")
|
||||
.replace("%seconds%", backstabCooldown.getRemaining(damager))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
backstabCooldown.applyCooldown(damager, getAbilitiesConfig().getInt("PORTABLE_ROGUE.BACKSTAB_COOLDOWN"));
|
||||
getManager().playSound(damaged, getAbilitiesConfig().getString("PORTABLE_ROGUE.BACKSTAB_SOUND"), true);
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
|
||||
getInstance().getVersionManager().getVersion().playEffect(
|
||||
damaged.getLocation().add(0, 1, 0), // add 1
|
||||
Effect.STEP_SOUND.name(),
|
||||
ItemUtils.getMat(getAbilitiesConfig().getString("PORTABLE_ROGUE.BACKSTAB_EFFECT"))
|
||||
);
|
||||
|
||||
damaged.setLastDamageCause(new RogueBackstabEvent(damaged, damager, EntityDamageEvent.DamageCause.CUSTOM, backstabDamage));
|
||||
damaged.setHealth(Math.max(damaged.getHealth() - backstabDamage, 0));
|
||||
|
||||
e.setDamage(0D);
|
||||
|
||||
if (damaged.isDead()) {
|
||||
e.setCancelled(true); // we cancel the event so PlayerDeathEvent doesn't get called twice.
|
||||
}
|
||||
|
||||
// add the slowness and all that
|
||||
for (PotionEffect backstabEffect : backstabEffects) {
|
||||
damager.addPotionEffect(backstabEffect);
|
||||
}
|
||||
|
||||
} else {
|
||||
damager.sendMessage(getLanguageConfig().getString("PVP_CLASSES.ROGUE_CLASS.BACKSTAB_FAILED"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.PvPClassManager;
|
||||
import me.keano.azurite.modules.teams.type.PlayerTeam;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class RageBallAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> ballsThrown;
|
||||
private final List<PotionEffect> friendlyEffects;
|
||||
private final List<PotionEffect> enemyEffects;
|
||||
private final String rageBallEffect;
|
||||
private final boolean wholeTeamCooldown;
|
||||
private final int radius;
|
||||
|
||||
public RageBallAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Rage Ball"
|
||||
);
|
||||
this.ballsThrown = new HashMap<>();
|
||||
this.friendlyEffects = new ArrayList<>();
|
||||
this.enemyEffects = new ArrayList<>();
|
||||
this.rageBallEffect = getAbilitiesConfig().getString("RAGE_BALL.EFFECT");
|
||||
this.wholeTeamCooldown = getAbilitiesConfig().getBoolean("RAGE_BALL.COOLDOWN_WHOLE_TEAM");
|
||||
this.radius = getAbilitiesConfig().getInt("RAGE_BALL.RADIUS");
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList("RAGE_BALL.FRIENDLY_EFFECTS")) {
|
||||
friendlyEffects.add(Serializer.getEffect(s));
|
||||
}
|
||||
|
||||
for (String s : getAbilitiesConfig().getStringList("RAGE_BALL.ENEMY_EFFECTS")) {
|
||||
enemyEffects.add(Serializer.getEffect(s));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory(); // Refund item
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onThrow(ProjectileLaunchEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
Player player = Utils.getDamager(projectile);
|
||||
|
||||
if (player == null) return;
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
ballsThrown.put(projectile.getUniqueId(), player.getUniqueId());
|
||||
applyCooldown(player);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.RAGE_BALL.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLand(ProjectileHitEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
UUID uuid = ballsThrown.remove(projectile.getUniqueId());
|
||||
|
||||
if (uuid != null) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) return;
|
||||
|
||||
PlayerTeam pt = getInstance().getTeamManager().getByPlayer(player.getUniqueId());
|
||||
PvPClassManager classManager = getInstance().getClassManager();
|
||||
|
||||
// The effect
|
||||
getInstance().getVersionManager().getVersion().playEffect(projectile.getLocation(), rageBallEffect, null);
|
||||
|
||||
for (Entity entity : projectile.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player other = (Player) entity;
|
||||
|
||||
if (other == player) {
|
||||
for (PotionEffect friendlyEffect : friendlyEffects) classManager.addEffect(player, friendlyEffect);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (getInstance().getTeamManager().canHit(player, other, false)) {
|
||||
for (PotionEffect enemyEffect : enemyEffects) classManager.addEffect(other, enemyEffect);
|
||||
}
|
||||
|
||||
if (pt != null && pt.getPlayers().contains(other.getUniqueId())) {
|
||||
if (wholeTeamCooldown) abilityCooldown.applyTimer(other);
|
||||
for (PotionEffect friendlyEffect : friendlyEffects) classManager.addEffect(other, friendlyEffect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class RocketAbility extends Ability {
|
||||
|
||||
private final Set<UUID> fall;
|
||||
private final double multiplier;
|
||||
private final double y;
|
||||
|
||||
public RocketAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Rocket"
|
||||
);
|
||||
this.fall = new HashSet<>();
|
||||
this.multiplier = getAbilitiesConfig().getDouble("ROCKET.MULTIPLIER");
|
||||
this.y = getAbilitiesConfig().getDouble("ROCKET.Y_VALUE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Vector vector = player.getEyeLocation().getDirection();
|
||||
vector.multiply(multiplier);
|
||||
if (y != 0) vector.setY(y);
|
||||
player.setVelocity(vector);
|
||||
|
||||
fall.add(player.getUniqueId());
|
||||
Tasks.executeLater(getManager(), 20L * 15, () -> fall.remove(player.getUniqueId()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ROCKET.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (e.getCause() != EntityDamageEvent.DamageCause.FALL) return;
|
||||
|
||||
Player player = (Player) e.getEntity();
|
||||
|
||||
if (fall.remove(player.getUniqueId())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import me.keano.azurite.modules.timers.listeners.playertimers.EnderpearlTimer;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class SamuraiAbility extends Ability {
|
||||
|
||||
private final Set<PotionEffect> effects;
|
||||
private final int hitsValid;
|
||||
private final int seconds;
|
||||
private final int antiBuildTime;
|
||||
private final int enderPearlTime;
|
||||
|
||||
public SamuraiAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Samurai"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("SAMURAI.EFFECTS_ON_TELEPORT").stream().map(Serializer::getEffect).collect(Collectors.toSet());
|
||||
this.hitsValid = getAbilitiesConfig().getInt("SAMURAI.HITS_VALID");
|
||||
this.seconds = getAbilitiesConfig().getInt("SAMURAI.SECONDS");
|
||||
this.antiBuildTime = getAbilitiesConfig().getInt("SAMURAI.ANTI_BUILD_TIME");
|
||||
this.enderPearlTime = getAbilitiesConfig().getInt("SAMURAI.ENDER_PEARL_TIME");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
// I already coded a way to get last damager for focus mode, so just use that.
|
||||
Player damager = ((FocusModeAbility) getManager().getAbility("FocusMode")).getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.SAMURAI_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
AntiBuildAbility antiBuildAbility = (AntiBuildAbility) getManager().getAbility("AntiBuild");
|
||||
EnderpearlTimer enderpearlTimer = getInstance().getTimerManager().getEnderpearlTimer();
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
antiBuildAbility.getAntiBuild().applyCooldown(damager, antiBuildTime);
|
||||
enderpearlTimer.applyTimer(damager, enderPearlTime * 1000L);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SAMURAI_ABILITY.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SAMURAI_ABILITY.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SAMURAI_ABILITY.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class SwitchStickAbility extends Ability {
|
||||
|
||||
private final Set<UUID> switchSticks;
|
||||
private final int chance;
|
||||
private final int degrees;
|
||||
private final int time;
|
||||
|
||||
public SwitchStickAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Switch Stick"
|
||||
);
|
||||
this.switchSticks = new HashSet<>();
|
||||
this.chance = getAbilitiesConfig().getInt("SWITCH_STICK.CHANCE");
|
||||
this.degrees = getAbilitiesConfig().getInt("SWITCH_STICK.DEGREES");
|
||||
this.time = getAbilitiesConfig().getInt("SWITCH_STICK.TIME");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
switchSticks.add(player.getUniqueId());
|
||||
Tasks.executeLater(getManager(), 20L * time, () -> switchSticks.remove(player.getUniqueId()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCH_STICK.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (!switchSticks.contains(damager.getUniqueId())) return;
|
||||
|
||||
int random = ThreadLocalRandom.current().nextInt(100 + 1);
|
||||
|
||||
if (random <= chance) {
|
||||
// https://www.spigotmc.org/threads/setting-a-players-yaw-pitch.97825/
|
||||
Location cloned = damaged.getLocation().clone();
|
||||
cloned.setYaw(cloned.getYaw() + degrees);
|
||||
damaged.teleport(cloned);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCH_STICK.ACTIVATED")) {
|
||||
damager.sendMessage(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Egg;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Snowball;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class SwitcherAbility extends Ability {
|
||||
|
||||
private final Set<UUID> switchers;
|
||||
private final int distance;
|
||||
|
||||
public SwitcherAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Switcher"
|
||||
);
|
||||
this.switchers = new HashSet<>();
|
||||
this.distance = getAbilitiesConfig().getInt("SWITCHER.DISTANCE");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
applyCooldown(player);
|
||||
switchers.add(player.getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onHit(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (getItem().getType() == ItemUtils.getMat("SNOW_BALL") && !(e.getDamager() instanceof Snowball)) return;
|
||||
if (getItem().getType() == ItemUtils.getMat("EGG") && !(e.getDamager() instanceof Egg)) return;
|
||||
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (damager == null) return;
|
||||
if (!switchers.contains(damager.getUniqueId())) return;
|
||||
|
||||
if (e.isCancelled()) {
|
||||
damager.getInventory().addItem(item);
|
||||
damager.updateInventory(); // refund it
|
||||
return;
|
||||
}
|
||||
|
||||
if (damager.getLocation().distance(damaged.getLocation()) > distance) {
|
||||
damager.getInventory().addItem(item);
|
||||
damager.updateInventory(); // refund it
|
||||
damager.sendMessage(getLanguageConfig().getString("ABILITIES.SWITCHER.TOO_FAR"));
|
||||
return;
|
||||
}
|
||||
|
||||
Location clonedFirst = damaged.getLocation().clone();
|
||||
Location clonedSecond = damager.getLocation().clone();
|
||||
|
||||
damaged.teleport(clonedSecond);
|
||||
damager.teleport(clonedFirst);
|
||||
|
||||
switchers.remove(damager.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCHER.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCHER.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TankIngotAbility extends Ability {
|
||||
|
||||
private final int radius;
|
||||
private final int maxDuration;
|
||||
private final int durationPerPlayer;
|
||||
private final List<String> effects;
|
||||
|
||||
public TankIngotAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Tank Ingot"
|
||||
);
|
||||
this.radius = getAbilitiesConfig().getInt("TANK_INGOT.RADIUS");
|
||||
this.maxDuration = getAbilitiesConfig().getInt("TANK_INGOT.MAX_DURATION");
|
||||
this.durationPerPlayer = getAbilitiesConfig().getInt("TANK_INGOT.DURATION_PER_PLAYER");
|
||||
this.effects = getAbilitiesConfig().getStringList("TANK_INGOT.EFFECTS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
int enemies = countEnemies(player);
|
||||
applyEffects(player, enemies);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TANK_INGOT.USED")) {
|
||||
player.sendMessage(s
|
||||
.replace("%nearby%", String.valueOf(enemies))
|
||||
.replace("%time%", String.valueOf(durationPerPlayer * enemies))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private int countEnemies(Player player) {
|
||||
int i = 0;
|
||||
|
||||
for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player nearby = (Player) entity;
|
||||
|
||||
if (getInstance().getTeamManager().canHit(player, nearby, false)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private void applyEffects(Player player, int nearby) {
|
||||
if (nearby == 0) return;
|
||||
|
||||
for (String effect : effects) {
|
||||
String[] split = effect.split(", ");
|
||||
PotionEffect potionEffect = new PotionEffect(
|
||||
PotionEffectType.getByName(split[0]),
|
||||
Math.min(durationPerPlayer * nearby, maxDuration) * 20,
|
||||
Integer.parseInt(split[2]) - 1);
|
||||
getInstance().getClassManager().addEffect(player, potionEffect);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TeleportBowAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> usedTeleportBow; // player -> arrow
|
||||
private final int seconds;
|
||||
|
||||
public TeleportBowAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Teleport Bow"
|
||||
);
|
||||
this.usedTeleportBow = new HashMap<>();
|
||||
this.seconds = getAbilitiesConfig().getInt("TELEPORT_BOW.SECONDS");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onShoot(EntityShootBowEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player player = (Player) e.getEntity();
|
||||
ItemStack bow = e.getBow();
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
usedTeleportBow.put(player.getUniqueId(), e.getProjectile().getUniqueId());
|
||||
getManager().setData(bow, getManager().getData(bow) + 1);
|
||||
|
||||
if (getManager().getData(bow) == bow.getType().getMaxDurability()) {
|
||||
getManager().takeItemInHand(player, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDamage(PlayerItemDamageEvent e) {
|
||||
ItemStack damage = e.getItem();
|
||||
|
||||
if (!damage.hasItemMeta()) return;
|
||||
if (!damage.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
ItemMeta itemMeta = damage.getItemMeta();
|
||||
ItemMeta abilityMeta = item.getItemMeta();
|
||||
|
||||
if (itemMeta.getDisplayName().equals(abilityMeta.getDisplayName()) && itemMeta.getLore().equals(abilityMeta.getLore())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Arrow)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
UUID arrow = usedTeleportBow.remove(damager.getUniqueId());
|
||||
|
||||
if (arrow != null && e.getDamager().getUniqueId().equals(arrow)) {
|
||||
applyCooldown(damager);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
damager.teleport(damaged);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_BOW.TELEPORTED_SUCCESSFULLY")) {
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_BOW.TELEPORTING"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_BOW.TELEPORTING_ATTACKER"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TeleportEyeAbility extends Ability {
|
||||
|
||||
private final int hitsValid;
|
||||
private final int seconds;
|
||||
|
||||
public TeleportEyeAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Teleport Eye"
|
||||
);
|
||||
this.hitsValid = getAbilitiesConfig().getInt("TELEPORT_EYE.HITS_VALID");
|
||||
this.seconds = getAbilitiesConfig().getInt("TELEPORT_EYE.SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
Block block = player.getLocation().getBlock();
|
||||
Player damager = ((FocusModeAbility) getManager().getAbility("FocusMode")).getDamager(player, hitsValid);
|
||||
|
||||
if (!block.isLiquid()) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.TELEPORT_EYE.NOT_IN_LIQUID"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.NINJA_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_EYE.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_EYE.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_EYE.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EnderPearl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TimeWarpAbility extends Ability {
|
||||
|
||||
private final Map<UUID, TimeWarpData> timeWarps;
|
||||
private final int seconds;
|
||||
private final int delay;
|
||||
|
||||
public TimeWarpAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Time Warp"
|
||||
);
|
||||
this.timeWarps = new HashMap<>();
|
||||
this.seconds = getAbilitiesConfig().getInt("TIME_WARP.PEARL_DELAY");
|
||||
this.delay = getAbilitiesConfig().getInt("TIME_WARP.DELAY");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (hasCooldown(player)) return;
|
||||
if (cannotUse(player)) return;
|
||||
|
||||
TimeWarpData data = timeWarps.remove(player.getUniqueId());
|
||||
|
||||
if (data == null || data.getValidTill() < System.currentTimeMillis()) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.TIMEWARP.INVALID_PEARL")
|
||||
.replace("%seconds%", String.valueOf(seconds))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
Tasks.executeLater(getManager(), 20L * delay, () -> player.teleport(data.getLocation()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TIMEWARP.USED"))
|
||||
player.sendMessage(s
|
||||
.replace("%seconds%", String.valueOf(delay))
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onThrow(ProjectileLaunchEvent e) {
|
||||
if (e.isCancelled()) return;
|
||||
if (!(e.getEntity() instanceof EnderPearl)) return;
|
||||
|
||||
Player player = Utils.getDamager(e.getEntity());
|
||||
|
||||
if (player != null) {
|
||||
timeWarps.put(player.getUniqueId(), new TimeWarpData(player.getLocation(), seconds));
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
private static class TimeWarpData {
|
||||
|
||||
private final Location location;
|
||||
private final long validTill;
|
||||
|
||||
public TimeWarpData(Location location, int usableSeconds) {
|
||||
this.location = location;
|
||||
this.validTill = System.currentTimeMillis() + (usableSeconds * 1000L);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class UltimateAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> effects;
|
||||
private final int seconds;
|
||||
|
||||
public UltimateAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Ultimate Ability"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("ULTIMATE_ABILITY.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toList());
|
||||
this.seconds = getAbilitiesConfig().getInt("ULTIMATE_ABILITY.SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Location location = player.getLocation();
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> player.teleport(location));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ULTIMATE_ABILITY.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package me.keano.azurite.modules.api;
|
||||
|
||||
import me.keano.azurite.HCF;
|
||||
import me.keano.azurite.modules.teams.Team;
|
||||
import me.keano.azurite.modules.teams.type.*;
|
||||
import me.keano.azurite.utils.extra.Pair;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AzuriteAPI {
|
||||
|
||||
private final HCF hcf;
|
||||
|
||||
public AzuriteAPI(JavaPlugin plugin) {
|
||||
Plugin hcf = plugin.getServer().getPluginManager().getPlugin("Azurite");
|
||||
|
||||
if (hcf == null) {
|
||||
throw new IllegalArgumentException("Azurite is not loaded");
|
||||
}
|
||||
|
||||
this.hcf = (HCF) hcf;
|
||||
}
|
||||
|
||||
public boolean isConquest(Location location) {
|
||||
return hcf.getTeamManager().getClaimManager().getTeam(location) instanceof ConquestTeam;
|
||||
}
|
||||
|
||||
public boolean isSpawn(Location location) {
|
||||
return hcf.getTeamManager().getClaimManager().getTeam(location) instanceof SafezoneTeam;
|
||||
}
|
||||
|
||||
public boolean isCitadel(Location location) {
|
||||
return hcf.getTeamManager().getClaimManager().getTeam(location) instanceof CitadelTeam;
|
||||
}
|
||||
|
||||
public boolean isKoth(Location location) {
|
||||
return hcf.getTeamManager().getClaimManager().getTeam(location) instanceof EventTeam;
|
||||
}
|
||||
|
||||
public boolean isSotwActive(Player player) {
|
||||
return hcf.getSotwManager().isActive() && !hcf.getSotwManager().getEnabled().contains(player.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean isInSpawn(Player player) {
|
||||
return hcf.getTeamManager().getClaimManager().getTeam(player.getLocation()) instanceof SafezoneTeam;
|
||||
}
|
||||
|
||||
public boolean isInOwnClaim(Player player) {
|
||||
Team team = hcf.getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
return team instanceof PlayerTeam && ((PlayerTeam) team).getPlayers().contains(player.getUniqueId());
|
||||
}
|
||||
|
||||
public boolean hasGlobalAbilityCooldown(Player player) {
|
||||
return hcf.getAbilityManager().getGlobalCooldown().hasTimer(player);
|
||||
}
|
||||
|
||||
public boolean hasCombatTag(Player player) {
|
||||
return hcf.getTimerManager().getCombatTimer().hasTimer(player);
|
||||
}
|
||||
|
||||
public String getPlayerFaction(Player player) {
|
||||
PlayerTeam pt = hcf.getTeamManager().getByPlayer(player.getUniqueId());
|
||||
return (pt != null ? pt.getName() : null);
|
||||
}
|
||||
|
||||
public void giveArcherTag(Player player, long time) {
|
||||
hcf.getTimerManager().getArcherTagTimer().applyTimer(player, time);
|
||||
}
|
||||
|
||||
public int getBalance(Player player) {
|
||||
return hcf.getBalanceManager().getBalance(player.getUniqueId());
|
||||
}
|
||||
|
||||
public List<Pair<Location, Location>> getClaims(Player player) {
|
||||
PlayerTeam pt = hcf.getTeamManager().getByPlayer(player.getUniqueId());
|
||||
|
||||
if (pt != null) {
|
||||
return pt.getClaims().stream().map(c -> new Pair<>(
|
||||
new Location(c.getWorld(), c.getX1(), c.getY1(), c.getZ1()),
|
||||
new Location(c.getWorld(), c.getX2(), c.getY2(), c.getZ2())
|
||||
)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public List<Player> getOnlineTeammates(Player player) {
|
||||
PlayerTeam pt = hcf.getTeamManager().getByPlayer(player.getUniqueId());
|
||||
|
||||
if (pt != null) {
|
||||
return pt.getOnlinePlayers(false);
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package me.keano.azurite.modules.balance;
|
||||
|
||||
import me.keano.azurite.HCF;
|
||||
import me.keano.azurite.modules.balance.type.VaultBalance;
|
||||
import me.keano.azurite.modules.framework.Manager;
|
||||
import me.keano.azurite.modules.users.User;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class BalanceManager extends Manager {
|
||||
|
||||
public BalanceManager(HCF instance) {
|
||||
super(instance);
|
||||
|
||||
Plugin vault = Bukkit.getPluginManager().getPlugin("Vault");
|
||||
|
||||
if (vault != null && vault.isEnabled()) {
|
||||
Bukkit.getServicesManager().register(Economy.class, new VaultBalance(this), getInstance(), ServicePriority.Normal);
|
||||
}
|
||||
}
|
||||
|
||||
public void takeBalance(OfflinePlayer player, int amount) {
|
||||
User user = getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
user.setBalance(Math.max(user.getBalance() - amount, 0));
|
||||
user.save();
|
||||
}
|
||||
|
||||
public void giveBalance(OfflinePlayer player, int amount) {
|
||||
User user = getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
user.setBalance(Math.max(user.getBalance() + amount, 0));
|
||||
user.save();
|
||||
}
|
||||
|
||||
public void giveBalance(UUID uuid, int amount) {
|
||||
User user = getInstance().getUserManager().getByUUID(uuid);
|
||||
user.setBalance(Math.max(user.getBalance() + amount, 0));
|
||||
user.save();
|
||||
}
|
||||
|
||||
public void setBalance(OfflinePlayer player, int amount) {
|
||||
User user = getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
user.setBalance(Math.max(amount, 0));
|
||||
user.save();
|
||||
}
|
||||
|
||||
public boolean hasBalance(OfflinePlayer player, int amount) {
|
||||
User user = getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
return user.getBalance() >= amount;
|
||||
}
|
||||
|
||||
public int getBalance(UUID player) {
|
||||
User user = getInstance().getUserManager().getByUUID(player);
|
||||
return user.getBalance();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
package me.keano.azurite.modules.balance.type;
|
||||
|
||||
import me.keano.azurite.modules.balance.BalanceManager;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.users.User;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import net.milkbowl.vault.economy.EconomyResponse;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class VaultBalance extends Module<BalanceManager> implements Economy {
|
||||
|
||||
public VaultBalance(BalanceManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return getInstance().isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Azurite";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBankSupport() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fractionalDigits() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(double v) {
|
||||
return String.valueOf(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String currencyNamePlural() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String currencyNameSingular() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAccount(OfflinePlayer offlinePlayer) {
|
||||
return getInstance().getUserManager().getByUUID(offlinePlayer.getUniqueId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAccount(String s) {
|
||||
return hasAccount(Bukkit.getOfflinePlayer(s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAccount(String s, String s1) {
|
||||
return hasAccount(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAccount(OfflinePlayer offlinePlayer, String s) {
|
||||
return hasAccount(offlinePlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBalance(String s) {
|
||||
return getInstance().getUserManager().getByName(s).getBalance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBalance(OfflinePlayer offlinePlayer) {
|
||||
return getBalance(offlinePlayer.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBalance(String s, String s1) {
|
||||
return getBalance(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBalance(OfflinePlayer offlinePlayer, String s) {
|
||||
return getBalance(offlinePlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String s, double v) {
|
||||
return getBalance(s) >= v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(OfflinePlayer offlinePlayer, double v) {
|
||||
return has(offlinePlayer.getName(), v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String s, String s1, double v) {
|
||||
return has(s, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(OfflinePlayer offlinePlayer, String s, double v) {
|
||||
return has(offlinePlayer, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse withdrawPlayer(OfflinePlayer offlinePlayer, double v) {
|
||||
User user = getInstance().getUserManager().getByUUID(offlinePlayer.getUniqueId());
|
||||
|
||||
if (user == null) {
|
||||
return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "never joined!");
|
||||
|
||||
} else if (user.getBalance() < 0) {
|
||||
return new EconomyResponse(0, user.getBalance(), EconomyResponse.ResponseType.FAILURE, "negative funds");
|
||||
|
||||
} else if (user.getBalance() < v) {
|
||||
return new EconomyResponse(0, user.getBalance(), EconomyResponse.ResponseType.FAILURE, "insufficient funds");
|
||||
|
||||
} else {
|
||||
user.setBalance(user.getBalance() - (int) v);
|
||||
user.save();
|
||||
return new EconomyResponse(v, user.getBalance(), EconomyResponse.ResponseType.SUCCESS, "");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse withdrawPlayer(String s, double v) {
|
||||
return withdrawPlayer(Bukkit.getOfflinePlayer(s), v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse withdrawPlayer(String s, String s1, double v) {
|
||||
return withdrawPlayer(s, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse withdrawPlayer(OfflinePlayer offlinePlayer, String s, double v) {
|
||||
return withdrawPlayer(offlinePlayer, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse depositPlayer(OfflinePlayer offlinePlayer, double v) {
|
||||
User user = getInstance().getUserManager().getByUUID(offlinePlayer.getUniqueId());
|
||||
|
||||
if (user == null) {
|
||||
return new EconomyResponse(0, 0, EconomyResponse.ResponseType.FAILURE, "never joined!");
|
||||
|
||||
} else if (user.getBalance() < 0) {
|
||||
return new EconomyResponse(0, user.getBalance(), EconomyResponse.ResponseType.FAILURE, "negative funds");
|
||||
|
||||
} else {
|
||||
user.setBalance(user.getBalance() + (int) Math.ceil(v)); // round up
|
||||
user.save();
|
||||
return new EconomyResponse(v, user.getBalance(), EconomyResponse.ResponseType.SUCCESS, "");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse depositPlayer(String s, double v) {
|
||||
return depositPlayer(Bukkit.getOfflinePlayer(s), v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse depositPlayer(String s, String s1, double v) {
|
||||
return depositPlayer(s, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse depositPlayer(OfflinePlayer offlinePlayer, String s, double v) {
|
||||
return depositPlayer(offlinePlayer, v);
|
||||
}
|
||||
|
||||
// BELOW DISABLED!
|
||||
|
||||
@Override
|
||||
public EconomyResponse createBank(String s, String s1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse createBank(String s, OfflinePlayer offlinePlayer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse deleteBank(String s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse bankBalance(String s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse bankHas(String s, double v) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse bankWithdraw(String s, double v) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse bankDeposit(String s, double v) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse isBankOwner(String s, String s1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse isBankOwner(String s, OfflinePlayer offlinePlayer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse isBankMember(String s, String s1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconomyResponse isBankMember(String s, OfflinePlayer offlinePlayer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getBanks() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createPlayerAccount(String s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createPlayerAccount(OfflinePlayer offlinePlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createPlayerAccount(String s, String s1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createPlayerAccount(OfflinePlayer offlinePlayer, String s) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package me.keano.azurite.modules.board;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.board.fastboard.FastBoard;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class Board extends Module<BoardManager> {
|
||||
|
||||
private Player player;
|
||||
private FastBoard fastBoard;
|
||||
|
||||
public Board(BoardManager manager, Player player) {
|
||||
super(manager);
|
||||
this.player = player;
|
||||
this.fastBoard = new FastBoard(player);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
List<String> lines = getManager().getAdapter().getLines(player);
|
||||
|
||||
// We destroy the board if the lines are null or empty
|
||||
if (lines == null || lines.isEmpty()) {
|
||||
if (!fastBoard.isDeleted()) fastBoard.delete();
|
||||
return;
|
||||
}
|
||||
|
||||
// create a new fast-board otherwise updating a deleted one will throw an exception.
|
||||
if (fastBoard.isDeleted()) {
|
||||
fastBoard = new FastBoard(player);
|
||||
}
|
||||
|
||||
if (Config.SCOREBOARD_CHANGER_ENABLED) {
|
||||
fastBoard.setTitle(getManager().getTitle().getCurrent());
|
||||
|
||||
} else fastBoard.setTitle(getManager().getAdapter().getTitle(player));
|
||||
|
||||
fastBoard.setLines(lines);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package me.keano.azurite.modules.board;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public interface BoardAdapter {
|
||||
|
||||
String getTitle(Player player);
|
||||
|
||||
List<String> getLines(Player player);
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package me.keano.azurite.modules.board;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.HCF;
|
||||
import me.keano.azurite.modules.board.adapter.AzuriteBoard;
|
||||
import me.keano.azurite.modules.board.extra.AnimatedString;
|
||||
import me.keano.azurite.modules.board.listener.BoardListener;
|
||||
import me.keano.azurite.modules.board.task.BoardTask;
|
||||
import me.keano.azurite.modules.framework.Manager;
|
||||
import me.keano.azurite.utils.NameThreadFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class BoardManager extends Manager {
|
||||
|
||||
private final Map<UUID, Board> boards;
|
||||
private final ScheduledExecutorService executor;
|
||||
|
||||
private BoardAdapter adapter;
|
||||
private AnimatedString title;
|
||||
private AnimatedString footer;
|
||||
|
||||
public BoardManager(HCF instance) {
|
||||
super(instance);
|
||||
|
||||
this.boards = new ConcurrentHashMap<>();
|
||||
this.adapter = new AzuriteBoard(this);
|
||||
|
||||
this.title = new AnimatedString(this, getStringList("TITLE_CONFIG.CHANGES"), getLong("TITLE_CONFIG.CHANGER_TICKS"));
|
||||
this.footer = new AnimatedString(this, getStringList("FOOTER_CONFIG.CHANGES"), getLong("FOOTER_CONFIG.CHANGER_TICKS"));
|
||||
|
||||
this.executor = Executors.newScheduledThreadPool(1, new NameThreadFactory("Azurite - BoardThread"));
|
||||
this.executor.scheduleAtFixedRate(new BoardTask(this), 0L, 100L, TimeUnit.MILLISECONDS);
|
||||
|
||||
new BoardListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.adapter = new AzuriteBoard(this); // re-fetch the values
|
||||
this.title = new AnimatedString(this, getStringList("TITLE_CONFIG.CHANGES"), getLong("TITLE_CONFIG.CHANGER_TICKS"));
|
||||
this.footer = new AnimatedString(this, getStringList("FOOTER_CONFIG.CHANGES"), getLong("FOOTER_CONFIG.CHANGER_TICKS"));
|
||||
}
|
||||
|
||||
public List<String> getStringList(String path) {
|
||||
return getScoreboardConfig().getStringList(path);
|
||||
}
|
||||
|
||||
public long getLong(String path) {
|
||||
return getScoreboardConfig().getLong(path);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,522 @@
|
|||
package me.keano.azurite.modules.board.adapter;
|
||||
|
||||
import me.keano.azurite.modules.ability.extra.GlobalCooldown;
|
||||
import me.keano.azurite.modules.board.BoardAdapter;
|
||||
import me.keano.azurite.modules.board.BoardManager;
|
||||
import me.keano.azurite.modules.deathban.Deathban;
|
||||
import me.keano.azurite.modules.events.conquest.Conquest;
|
||||
import me.keano.azurite.modules.events.conquest.extra.Capzone;
|
||||
import me.keano.azurite.modules.events.conquest.extra.ConquestType;
|
||||
import me.keano.azurite.modules.events.koth.Koth;
|
||||
import me.keano.azurite.modules.events.sotw.SOTWManager;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.pvpclass.PvPClass;
|
||||
import me.keano.azurite.modules.pvpclass.cooldown.CustomCooldown;
|
||||
import me.keano.azurite.modules.pvpclass.type.bard.BardClass;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostClass;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostData;
|
||||
import me.keano.azurite.modules.pvpclass.type.mage.MageClass;
|
||||
import me.keano.azurite.modules.pvpclass.type.miner.MinerClass;
|
||||
import me.keano.azurite.modules.staff.StaffManager;
|
||||
import me.keano.azurite.modules.teams.Team;
|
||||
import me.keano.azurite.modules.teams.enums.TeamType;
|
||||
import me.keano.azurite.modules.teams.type.PlayerTeam;
|
||||
import me.keano.azurite.modules.timers.listeners.playertimers.AbilityTimer;
|
||||
import me.keano.azurite.modules.timers.listeners.playertimers.AppleTimer;
|
||||
import me.keano.azurite.modules.timers.type.CustomTimer;
|
||||
import me.keano.azurite.modules.timers.type.PlayerTimer;
|
||||
import me.keano.azurite.modules.users.User;
|
||||
import me.keano.azurite.utils.Formatter;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.cuboid.Cuboid;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AzuriteBoard extends Module<BoardManager> implements BoardAdapter {
|
||||
|
||||
private final SOTWManager sotwManager;
|
||||
private final StaffManager staffManager;
|
||||
private final boolean linesEnabled;
|
||||
private final boolean lastLineEnabled;
|
||||
|
||||
private final List<String> kingLines;
|
||||
private final List<String> focusLines;
|
||||
private final List<String> focusSystemLines;
|
||||
private final List<String> conquestLines;
|
||||
private final List<String> kitsLines;
|
||||
private final List<String> noModMode;
|
||||
private final List<String> modMode;
|
||||
private final List<String> footerLines;
|
||||
private final List<String> claim;
|
||||
private final List<String> kothLines;
|
||||
|
||||
private final String line;
|
||||
private final String antiClean;
|
||||
private final String sotwOff;
|
||||
private final String sotw;
|
||||
private final String appleLimit;
|
||||
private final String className;
|
||||
private final String eotw;
|
||||
private final String purge;
|
||||
private final String bardEnergy;
|
||||
private final String mageEnergy;
|
||||
private final String minerInvis;
|
||||
private final String minerDiamonds;
|
||||
private final String ghostMode;
|
||||
private final String globalAbilities;
|
||||
private final String customTimerFormat;
|
||||
private final String deathbanInfo;
|
||||
private final String deathbanLives;
|
||||
|
||||
private final boolean footerEnabled;
|
||||
private final boolean focusEnabled;
|
||||
private final boolean kingEnabled;
|
||||
private final boolean staffEnabled;
|
||||
private final boolean kitsInfoOnlySpawn;
|
||||
private final boolean conquestOnlyTeam;
|
||||
private final boolean claimEnabled;
|
||||
private final boolean kothEnabled;
|
||||
private final boolean onlyPositiveKillstreak;
|
||||
|
||||
public AzuriteBoard(BoardManager manager) {
|
||||
super(manager);
|
||||
|
||||
this.sotwManager = getInstance().getSotwManager();
|
||||
this.staffManager = getInstance().getStaffManager();
|
||||
this.linesEnabled = getScoreboardConfig().getBoolean("SCOREBOARD_INFO.LINES_ENABLED");
|
||||
this.lastLineEnabled = getScoreboardConfig().getBoolean("SCOREBOARD_INFO.LAST_LINE_ENABLED");
|
||||
|
||||
this.kingLines = getScoreboardConfig().getStringList("KILL_THE_KING.LINES");
|
||||
this.focusLines = getScoreboardConfig().getStringList("TEAM_FOCUS.LINES_PLAYER");
|
||||
this.focusSystemLines = getScoreboardConfig().getStringList("TEAM_FOCUS.LINES_SYSTEM");
|
||||
this.conquestLines = getScoreboardConfig().getStringList("CONQUEST.LINES");
|
||||
this.kitsLines = getScoreboardConfig().getStringList("KITS_INFO");
|
||||
this.noModMode = getScoreboardConfig().getStringList("STAFF_MODE.VANISH_NO_MODMODE");
|
||||
this.modMode = getScoreboardConfig().getStringList("STAFF_MODE.MOD_MODE");
|
||||
this.footerLines = getScoreboardConfig().getStringList("FOOTER.LINES");
|
||||
this.claim = getScoreboardConfig().getStringList("CLAIM.LINES");
|
||||
this.kothLines = getScoreboardConfig().getStringList("KOTH.LINES");
|
||||
|
||||
this.line = getScoreboardConfig().getString("SCOREBOARD_INFO.LINES");
|
||||
this.antiClean = getString("PLAYER_TIMERS.ANTI_CLEAN");
|
||||
this.sotwOff = getString("PLAYER_TIMERS.SOTW_OFF");
|
||||
this.sotw = getString("PLAYER_TIMERS.SOTW");
|
||||
this.appleLimit = getString("PLAYER_TIMERS.APPLE_LIMIT");
|
||||
this.className = getString("PLAYER_TIMERS.ACTIVE_CLASS");
|
||||
this.eotw = getString("PLAYER_TIMERS.PRE_EOTW");
|
||||
this.purge = getString("PLAYER_TIMERS.PURGE");
|
||||
this.bardEnergy = getString("BARD_CLASS.BARD_ENERGY");
|
||||
this.mageEnergy = getString("MAGE_CLASS.MAGE_ENERGY");
|
||||
this.minerInvis = getString("MINER_CLASS.INVIS");
|
||||
this.minerDiamonds = getString("MINER_CLASS.DIAMONDS");
|
||||
this.ghostMode = getString("GHOST_CLASS.MODE");
|
||||
this.globalAbilities = getString("PLAYER_TIMERS.GLOBAL_ABILITIES");
|
||||
this.customTimerFormat = getString("CUSTOM_TIMERS.FORMAT");
|
||||
this.deathbanInfo = getString("DEATHBAN_INFO.TIME");
|
||||
this.deathbanLives = getString("DEATHBAN_INFO.LIVES");
|
||||
|
||||
this.footerEnabled = getScoreboardConfig().getBoolean("FOOTER.ENABLED");
|
||||
this.focusEnabled = getScoreboardConfig().getBoolean("TEAM_FOCUS.ENABLED");
|
||||
this.kingEnabled = getScoreboardConfig().getBoolean("KILL_THE_KING.ENABLED");
|
||||
this.staffEnabled = getScoreboardConfig().getBoolean("STAFF_MODE.ENABLED");
|
||||
this.kitsInfoOnlySpawn = getConfig().getBoolean("KITS_INFO_ONLY_SPAWN");
|
||||
this.conquestOnlyTeam = getConfig().getBoolean("CONQUEST.SCOREBOARD_ONLY_CONQUEST_CLAIM");
|
||||
this.claimEnabled = getScoreboardConfig().getBoolean("CLAIM.ENABLED");
|
||||
this.kothEnabled = getScoreboardConfig().getBoolean("KOTH.ENABLED");
|
||||
this.onlyPositiveKillstreak = getScoreboardConfig().getBoolean("SCOREBOARD_INFO.SHOW_KILLSTREAK_ONLY_POSITIVE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle(Player player) {
|
||||
return Config.SCOREBOARD_TITLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLines(Player player) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
PlayerTeam pt = getInstance().getTeamManager().getByPlayer(player.getUniqueId());
|
||||
User user = getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
GlobalCooldown globalCooldown = getInstance().getAbilityManager().getGlobalCooldown();
|
||||
Conquest conquest = getInstance().getConquestManager().getConquest();
|
||||
Deathban deathban = user.getDeathban();
|
||||
Team atPlayer = null;
|
||||
|
||||
boolean mod = false;
|
||||
boolean vanish = false;
|
||||
boolean focus = false;
|
||||
int focusSize = 0;
|
||||
int footer = (footerEnabled ? footerLines.size() : 0);
|
||||
int numberOfLines = (lastLineEnabled ? 2 : 1);
|
||||
|
||||
if (deathban != null) {
|
||||
if (linesEnabled) lines.add(line);
|
||||
|
||||
lines.add(deathbanInfo + Formatter.getRemaining(deathban.getTime(), false));
|
||||
lines.add(deathbanLives + user.getLives());
|
||||
|
||||
if (footerEnabled) {
|
||||
for (String s : footerLines)
|
||||
lines.add(s
|
||||
.replace("%footer%", getManager().getFooter().getCurrent())
|
||||
);
|
||||
}
|
||||
|
||||
if (linesEnabled) lines.add(line);
|
||||
return getInstance().getPlaceholderHook().replace(player, lines);
|
||||
}
|
||||
|
||||
if (!user.isScoreboard()) return null;
|
||||
|
||||
if (staffEnabled) {
|
||||
boolean vanished = staffManager.isVanished(player);
|
||||
boolean staffActive = staffManager.isStaffEnabled(player);
|
||||
|
||||
if (vanished && !staffActive) {
|
||||
vanish = true;
|
||||
|
||||
for (String s : noModMode)
|
||||
lines.add(s
|
||||
.replace("%vanished%", Config.STAFF_TRUE_PLACEHOLDER)
|
||||
);
|
||||
|
||||
} else if (staffActive) {
|
||||
mod = true;
|
||||
|
||||
for (String s : modMode)
|
||||
lines.add(s
|
||||
.replace("%vanished%", (vanished ? Config.STAFF_TRUE_PLACEHOLDER : Config.STAFF_FALSE_PLACEHOLDER))
|
||||
.replace("%staffbuild%", staffManager.isStaffBuild(player) ? Config.STAFF_TRUE_PLACEHOLDER : Config.STAFF_FALSE_PLACEHOLDER)
|
||||
.replace("%hidestaff%", staffManager.isHideStaff(player) ? Config.STAFF_TRUE_PLACEHOLDER : Config.STAFF_FALSE_PLACEHOLDER)
|
||||
.replace("%players%", String.valueOf(Bukkit.getOnlinePlayers().size()))
|
||||
.replace("%staff%", String.valueOf(staffManager.getStaffMembers().size()))
|
||||
.replace("%tps%", getInstance().getVersionManager().getVersion().getTPSColored())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (claimEnabled && user.isScoreboardClaim()) {
|
||||
atPlayer = getInstance().getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
|
||||
for (String s : claim)
|
||||
lines.add(s
|
||||
.replace("%claim%", atPlayer.getDisplayName(player))
|
||||
);
|
||||
}
|
||||
|
||||
if (getInstance().isKits()) {
|
||||
boolean add = false;
|
||||
|
||||
if (kitsInfoOnlySpawn) {
|
||||
if (atPlayer == null) {
|
||||
atPlayer = getInstance().getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
}
|
||||
|
||||
if (atPlayer.getType() == TeamType.SAFEZONE) {
|
||||
add = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
add = true;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
for (String s : kitsLines) {
|
||||
if (onlyPositiveKillstreak && s.contains("%killstreak%") && user.getKillstreak() <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add(s
|
||||
.replace("%kills%", String.valueOf(user.getKills()))
|
||||
.replace("%deaths%", String.valueOf(user.getDeaths()))
|
||||
.replace("%killstreak%", String.valueOf(user.getKillstreak()))
|
||||
.replace("%balance%", String.valueOf(user.getBalance()))
|
||||
.replace("%kdr%", user.getKDRString())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kingEnabled && getInstance().getKingManager().isActive()) {
|
||||
Player king = getInstance().getKingManager().getKing();
|
||||
double currentHealth = king.getHealth() / 2;
|
||||
|
||||
for (String s : kingLines)
|
||||
lines.add(s
|
||||
.replace("%king%", king.getName())
|
||||
.replace("%loc%", Utils.formatLocation(king.getLocation()))
|
||||
.replace("%reward%", getInstance().getKingManager().getReward())
|
||||
.replace("%health%", Formatter.formatHealth(currentHealth))
|
||||
);
|
||||
}
|
||||
|
||||
if (kothEnabled) {
|
||||
for (Koth activeKoth : getInstance().getKothManager().getKoths().values()) {
|
||||
if (!activeKoth.isActive()) continue;
|
||||
|
||||
Cuboid capzone = activeKoth.getCaptureZone();
|
||||
|
||||
for (String s : kothLines)
|
||||
lines.add(s
|
||||
.replace("%color%", activeKoth.getColor())
|
||||
.replace("%koth%", activeKoth.getName())
|
||||
.replace("%rem%", Formatter.getRemaining(activeKoth.getRemaining(), false))
|
||||
.replace("%loc%", (capzone == null ? "None" : Utils.formatLocation(capzone.getCenter())))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (pt != null && antiClean != null) {
|
||||
PlayerTeam antiCleanTeam = pt.getAntiCleanTeam();
|
||||
long rem = pt.getAntiCleanRemaining();
|
||||
|
||||
if (antiCleanTeam != null && rem > 0L) {
|
||||
lines.add(antiClean + Formatter.getRemaining(rem, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (sotwManager.isActive()) {
|
||||
if (sotwManager.getEnabled().contains(player.getUniqueId())) {
|
||||
if (sotwOff != null) lines.add(sotwOff + sotwManager.getRemainingString());
|
||||
|
||||
} else {
|
||||
if (sotw != null) lines.add(sotw + sotwManager.getRemainingString());
|
||||
}
|
||||
}
|
||||
|
||||
AppleTimer appleTimer = getInstance().getTimerManager().getAppleTimer();
|
||||
World.Environment environment = player.getWorld().getEnvironment();
|
||||
|
||||
if (appleTimer.isLimited(environment)) {
|
||||
if (appleLimit != null)
|
||||
lines.add(appleLimit
|
||||
.replace("%amount%", String.valueOf(appleTimer.getLimit(player)))
|
||||
.replace("%max-amount%", String.valueOf(appleTimer.getMaxLimit(environment)))
|
||||
);
|
||||
}
|
||||
|
||||
for (CustomTimer timer : getInstance().getTimerManager().getCustomTimers().values()) {
|
||||
if (timer.getName().equals("EOTW")) {
|
||||
if (eotw != null) lines.add(eotw + timer.getRemainingString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (timer.getName().equals("Purge")) {
|
||||
if (purge != null) lines.add(purge + timer.getRemainingString());
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add(customTimerFormat
|
||||
.replace("%displayName%", timer.getDisplayName()) + timer.getRemainingString()
|
||||
);
|
||||
}
|
||||
|
||||
PvPClass activeClass = getInstance().getClassManager().getActiveClasses().get(player.getUniqueId());
|
||||
|
||||
if (activeClass != null) {
|
||||
if (className != null) lines.add(className + activeClass.getName());
|
||||
|
||||
if (activeClass instanceof BardClass) {
|
||||
BardClass bardClass = (BardClass) activeClass;
|
||||
|
||||
if (bardEnergy != null) {
|
||||
lines.add(bardEnergy + Formatter.formatBardEnergy(bardClass.getEnergyCooldown(player).getEnergy()));
|
||||
}
|
||||
|
||||
} else if (activeClass instanceof MageClass) {
|
||||
MageClass mageClass = (MageClass) activeClass;
|
||||
|
||||
if (mageEnergy != null) {
|
||||
lines.add(mageEnergy + Formatter.formatBardEnergy(mageClass.getEnergyCooldown(player).getEnergy()));
|
||||
}
|
||||
|
||||
} else if (activeClass instanceof MinerClass) {
|
||||
MinerClass minerClass = (MinerClass) activeClass;
|
||||
|
||||
if (minerInvis != null) {
|
||||
lines.add(minerInvis + (minerClass.getInvisible().contains(player.getUniqueId()) ? "true" : "false"));
|
||||
}
|
||||
|
||||
if (minerDiamonds != null) {
|
||||
lines.add(minerDiamonds + user.getDiamonds());
|
||||
}
|
||||
|
||||
} else if (activeClass instanceof GhostClass) {
|
||||
GhostClass ghostClass = (GhostClass) activeClass;
|
||||
GhostData data = ghostClass.getData().get(player.getUniqueId());
|
||||
|
||||
if (ghostMode != null) {
|
||||
lines.add(ghostMode + data.getMode());
|
||||
}
|
||||
}
|
||||
|
||||
// basically all your speeds, jump
|
||||
for (CustomCooldown customCooldown : activeClass.getCustomCooldowns()) {
|
||||
String name = customCooldown.getDisplayName();
|
||||
|
||||
if (name == null) continue;
|
||||
if (!customCooldown.hasCooldown(player)) continue;
|
||||
|
||||
lines.add(name + customCooldown.getRemainingOld(player));
|
||||
}
|
||||
}
|
||||
|
||||
if (globalCooldown.hasTimer(player)) {
|
||||
if (globalAbilities != null) lines.add(globalAbilities + globalCooldown.getRemainingString(player));
|
||||
}
|
||||
|
||||
for (PlayerTimer timer : getInstance().getTimerManager().getPlayerTimers().values()) {
|
||||
if (timer instanceof GlobalCooldown) continue;
|
||||
|
||||
String name = timer.getScoreboard();
|
||||
|
||||
if (!timer.hasTimer(player)) continue;
|
||||
if (name == null) continue;
|
||||
|
||||
// These need to be replaced, so handle differently
|
||||
if (timer instanceof AbilityTimer) {
|
||||
AbilityTimer abilityTimer = (AbilityTimer) timer;
|
||||
lines.add(name.replace("%ability%", abilityTimer.getAbility().getDisplayName()) + timer.getRemainingStringBoard(player));
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add(name + timer.getRemainingStringBoard(player));
|
||||
}
|
||||
|
||||
lines.addAll(getInstance().getAbilitiesHook().getScoreboardLines(player));
|
||||
|
||||
if (conquest.isActive()) {
|
||||
if (atPlayer == null) {
|
||||
atPlayer = getInstance().getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
}
|
||||
|
||||
if (!conquestOnlyTeam || atPlayer.getType() == TeamType.CONQUEST) {
|
||||
Map<ConquestType, Capzone> conquests = conquest.getCapzones();
|
||||
|
||||
for (String conquestLine : conquestLines)
|
||||
lines.add(conquestLine
|
||||
.replace("%points-1%", conquest.getPoints(1))
|
||||
.replace("%points-2%", conquest.getPoints(2))
|
||||
.replace("%points-3%", conquest.getPoints(3))
|
||||
.replace("%red%", conquests.get(ConquestType.RED).getRemainingString())
|
||||
.replace("%yellow%", conquests.get(ConquestType.YELLOW).getRemainingString())
|
||||
.replace("%green%", conquests.get(ConquestType.GREEN).getRemainingString())
|
||||
.replace("%blue%", conquests.get(ConquestType.BLUE).getRemainingString())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (focusEnabled && pt != null && pt.getFocus() != null) {
|
||||
Team focusedTeam = pt.getFocusedTeam();
|
||||
|
||||
if (focusedTeam != null) {
|
||||
focus = true;
|
||||
|
||||
if (focusedTeam.getType() == TeamType.PLAYER) {
|
||||
focusSize = focusLines.size();
|
||||
PlayerTeam focusPT = (PlayerTeam) focusedTeam;
|
||||
|
||||
for (String focusLine : focusLines)
|
||||
lines.add(focusLine
|
||||
.replace("%team%", focusPT.getName())
|
||||
.replace("%hq%", focusPT.getHQFormatted())
|
||||
.replace("%online%", String.valueOf(focusPT.getOnlinePlayersSize(false)))
|
||||
.replace("%max-online%", String.valueOf(focusPT.getPlayers().size()))
|
||||
.replace("%dtr-color%", focusPT.getDtrColor())
|
||||
.replace("%dtr%", focusPT.getDtrString())
|
||||
.replace("%dtr-symbol%", focusPT.getDtrSymbol())
|
||||
);
|
||||
|
||||
} else {
|
||||
focusSize = focusSystemLines.size();
|
||||
|
||||
for (String s : focusSystemLines)
|
||||
lines.add(s
|
||||
.replace("%team%", focusedTeam.getName())
|
||||
.replace("%hq%", focusedTeam.getHQFormatted())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (footerEnabled) {
|
||||
for (String s : footerLines)
|
||||
lines.add(s
|
||||
.replace("%footer%", getManager().getFooter().getCurrent())
|
||||
);
|
||||
}
|
||||
|
||||
if (lines.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (linesEnabled) {
|
||||
List<String> clone = new ArrayList<>();
|
||||
|
||||
if (!lines.get(0).equals(line)) {
|
||||
clone.add(line);
|
||||
}
|
||||
|
||||
clone.addAll(lines);
|
||||
|
||||
if (!lines.get(lines.size() - 1).equals(line) && lastLineEnabled) {
|
||||
clone.add(line);
|
||||
}
|
||||
|
||||
lines = clone;
|
||||
|
||||
if (lines.size() == numberOfLines + footer) return null;
|
||||
}
|
||||
|
||||
if (!linesEnabled && footerEnabled && lines.size() == footerLines.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Below handles all the double lines which shouldn't be there.
|
||||
|
||||
int totalSize = numberOfLines + footer;
|
||||
boolean lastLineModMode = modMode.get(modMode.size() - 1).equals(line);
|
||||
boolean lastLineNoModMode = noModMode.get(noModMode.size() - 1).equals(line);
|
||||
|
||||
if (mod && lines.size() == totalSize + modMode.size() && lastLineModMode) {
|
||||
lines.remove(modMode.size());
|
||||
}
|
||||
|
||||
if (vanish && lines.size() == totalSize + noModMode.size() && lastLineNoModMode) {
|
||||
lines.remove(noModMode.size());
|
||||
}
|
||||
|
||||
if (mod && lastLineModMode && focus && lines.size() == totalSize + modMode.size() + focusSize) {
|
||||
String modModeLine = lines.get(modMode.size() + 1);
|
||||
|
||||
if (modModeLine.equals(line) || modModeLine.isEmpty()) {
|
||||
lines.remove(modMode.size() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (vanish && lastLineNoModMode && focus && lines.size() == totalSize + noModMode.size() + focusSize) {
|
||||
String noModModeLine = lines.get(noModMode.size() + 1);
|
||||
|
||||
if (noModModeLine.equals(line) || noModModeLine.isEmpty()) {
|
||||
lines.remove(noModMode.size() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return getInstance().getPlaceholderHook().replace(player, lines);
|
||||
}
|
||||
|
||||
public String getString(String path) {
|
||||
String string = getScoreboardConfig().getString(path);
|
||||
return (string.isEmpty() ? null : string);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package me.keano.azurite.modules.board.extra;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.framework.Manager;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class AnimatedString extends Module<Manager> {
|
||||
|
||||
private final List<String> changes;
|
||||
private final long delay;
|
||||
|
||||
private String current;
|
||||
private long ticks;
|
||||
private int index;
|
||||
|
||||
public AnimatedString(Manager manager, List<String> changes, long delay) {
|
||||
super(manager);
|
||||
this.changes = changes;
|
||||
this.delay = delay;
|
||||
this.current = "";
|
||||
this.ticks = System.currentTimeMillis();
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (ticks < System.currentTimeMillis()) {
|
||||
ticks = System.currentTimeMillis() + delay;
|
||||
|
||||
if (index == changes.size()) {
|
||||
index = 0; // Reset the index
|
||||
current = changes.get(0);
|
||||
return;
|
||||
}
|
||||
|
||||
String nextTitle = changes.get(index);
|
||||
index++;
|
||||
current = nextTitle;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,596 @@
|
|||
/*
|
||||
* This file is part of FastBoard, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) 2019-2021 MrMicky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package me.keano.azurite.modules.board.fastboard;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Lightweight packet-based scoreboard API for Bukkit plugins.
|
||||
* It can be safely used asynchronously as everything is at packet level.
|
||||
* <p>
|
||||
* The project is on <a href="https://github.com/MrMicky-FR/FastBoard">GitHub</a>.
|
||||
*
|
||||
* @author MrMicky
|
||||
* @version 1.2.1
|
||||
*/
|
||||
public class FastBoard {
|
||||
|
||||
private static final Map<Class<?>, Field[]> PACKETS = new HashMap<>(8);
|
||||
private static final String[] COLOR_CODES = Arrays.stream(ChatColor.values())
|
||||
.map(Object::toString)
|
||||
.toArray(String[]::new);
|
||||
private static final VersionType VERSION_TYPE;
|
||||
// Packets and components
|
||||
private static final Class<?> CHAT_COMPONENT_CLASS;
|
||||
private static final Class<?> CHAT_FORMAT_ENUM;
|
||||
private static final Object EMPTY_MESSAGE;
|
||||
private static final Object RESET_FORMATTING;
|
||||
private static final MethodHandle MESSAGE_FROM_STRING;
|
||||
private static final MethodHandle PLAYER_CONNECTION;
|
||||
private static final MethodHandle SEND_PACKET;
|
||||
private static final MethodHandle PLAYER_GET_HANDLE;
|
||||
// Scoreboard packets
|
||||
private static final FastReflection.PacketConstructor PACKET_SB_OBJ;
|
||||
private static final FastReflection.PacketConstructor PACKET_SB_DISPLAY_OBJ;
|
||||
private static final FastReflection.PacketConstructor PACKET_SB_SCORE;
|
||||
private static final FastReflection.PacketConstructor PACKET_SB_TEAM;
|
||||
private static final FastReflection.PacketConstructor PACKET_SB_SERIALIZABLE_TEAM;
|
||||
// Scoreboard enums
|
||||
private static final Class<?> ENUM_SB_HEALTH_DISPLAY;
|
||||
private static final Class<?> ENUM_SB_ACTION;
|
||||
private static final Object ENUM_SB_HEALTH_DISPLAY_INTEGER;
|
||||
private static final Object ENUM_SB_ACTION_CHANGE;
|
||||
private static final Object ENUM_SB_ACTION_REMOVE;
|
||||
|
||||
static {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
|
||||
if (FastReflection.isRepackaged()) {
|
||||
VERSION_TYPE = VersionType.V1_17;
|
||||
} else if (FastReflection.nmsOptionalClass(null, "ScoreboardServer$Action").isPresent()) {
|
||||
VERSION_TYPE = VersionType.V1_13;
|
||||
} else if (FastReflection.nmsOptionalClass(null, "IScoreboardCriteria$EnumScoreboardHealthDisplay").isPresent()) {
|
||||
VERSION_TYPE = VersionType.V1_8;
|
||||
} else {
|
||||
VERSION_TYPE = VersionType.V1_7;
|
||||
}
|
||||
|
||||
String gameProtocolPackage = "network.protocol.game";
|
||||
Class<?> craftPlayerClass = FastReflection.obcClass("entity.CraftPlayer");
|
||||
Class<?> craftChatMessageClass = FastReflection.obcClass("util.CraftChatMessage");
|
||||
Class<?> entityPlayerClass = FastReflection.nmsClass("server.level", "EntityPlayer");
|
||||
Class<?> playerConnectionClass = FastReflection.nmsClass("server.network", "PlayerConnection");
|
||||
Class<?> packetClass = FastReflection.nmsClass("network.protocol", "Packet");
|
||||
Class<?> packetSbObjClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardObjective");
|
||||
Class<?> packetSbDisplayObjClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardDisplayObjective");
|
||||
Class<?> packetSbScoreClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardScore");
|
||||
Class<?> packetSbTeamClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardTeam");
|
||||
Class<?> sbTeamClass = VersionType.V1_17.isHigherOrEqual()
|
||||
? FastReflection.innerClass(packetSbTeamClass, innerClass -> !innerClass.isEnum()) : null;
|
||||
Field playerConnectionField = Arrays.stream(entityPlayerClass.getFields())
|
||||
.filter(field -> field.getType().isAssignableFrom(playerConnectionClass))
|
||||
.findFirst().orElseThrow(NoSuchFieldException::new);
|
||||
Method sendPacketMethod = Arrays.stream(playerConnectionClass.getMethods())
|
||||
.filter(m -> m.getParameterCount() == 1 && m.getParameterTypes()[0] == packetClass)
|
||||
.findFirst().orElseThrow(NoSuchMethodException::new);
|
||||
|
||||
MESSAGE_FROM_STRING = lookup.unreflect(craftChatMessageClass.getMethod("fromString", String.class));
|
||||
CHAT_COMPONENT_CLASS = FastReflection.nmsClass("network.chat", "IChatBaseComponent");
|
||||
CHAT_FORMAT_ENUM = FastReflection.nmsClass(null, "EnumChatFormat");
|
||||
EMPTY_MESSAGE = Array.get(MESSAGE_FROM_STRING.invoke(""), 0);
|
||||
RESET_FORMATTING = FastReflection.enumValueOf(CHAT_FORMAT_ENUM, "RESET", 21);
|
||||
PLAYER_GET_HANDLE = lookup.findVirtual(craftPlayerClass, "getHandle", MethodType.methodType(entityPlayerClass));
|
||||
PLAYER_CONNECTION = lookup.unreflectGetter(playerConnectionField);
|
||||
SEND_PACKET = lookup.unreflect(sendPacketMethod);
|
||||
PACKET_SB_OBJ = FastReflection.findPacketConstructor(packetSbObjClass, lookup);
|
||||
PACKET_SB_DISPLAY_OBJ = FastReflection.findPacketConstructor(packetSbDisplayObjClass, lookup);
|
||||
PACKET_SB_SCORE = FastReflection.findPacketConstructor(packetSbScoreClass, lookup);
|
||||
PACKET_SB_TEAM = FastReflection.findPacketConstructor(packetSbTeamClass, lookup);
|
||||
PACKET_SB_SERIALIZABLE_TEAM = sbTeamClass == null ? null : FastReflection.findPacketConstructor(sbTeamClass, lookup);
|
||||
|
||||
for (Class<?> clazz : Arrays.asList(packetSbObjClass, packetSbDisplayObjClass, packetSbScoreClass, packetSbTeamClass, sbTeamClass)) {
|
||||
if (clazz == null) {
|
||||
continue;
|
||||
}
|
||||
Field[] fields = Arrays.stream(clazz.getDeclaredFields())
|
||||
.filter(field -> !Modifier.isStatic(field.getModifiers()))
|
||||
.toArray(Field[]::new);
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
PACKETS.put(clazz, fields);
|
||||
}
|
||||
|
||||
if (VersionType.V1_8.isHigherOrEqual()) {
|
||||
String enumSbActionClass = VersionType.V1_13.isHigherOrEqual()
|
||||
? "ScoreboardServer$Action"
|
||||
: "PacketPlayOutScoreboardScore$EnumScoreboardAction";
|
||||
ENUM_SB_HEALTH_DISPLAY = FastReflection.nmsClass("world.scores.criteria", "IScoreboardCriteria$EnumScoreboardHealthDisplay");
|
||||
ENUM_SB_ACTION = FastReflection.nmsClass("server", enumSbActionClass);
|
||||
ENUM_SB_HEALTH_DISPLAY_INTEGER = FastReflection.enumValueOf(ENUM_SB_HEALTH_DISPLAY, "INTEGER", 0);
|
||||
ENUM_SB_ACTION_CHANGE = FastReflection.enumValueOf(ENUM_SB_ACTION, "CHANGE", 0);
|
||||
ENUM_SB_ACTION_REMOVE = FastReflection.enumValueOf(ENUM_SB_ACTION, "REMOVE", 1);
|
||||
} else {
|
||||
ENUM_SB_HEALTH_DISPLAY = null;
|
||||
ENUM_SB_ACTION = null;
|
||||
ENUM_SB_HEALTH_DISPLAY_INTEGER = null;
|
||||
ENUM_SB_ACTION_CHANGE = null;
|
||||
ENUM_SB_ACTION_REMOVE = null;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new ExceptionInInitializerError(t);
|
||||
}
|
||||
}
|
||||
|
||||
private final Player player;
|
||||
private final String id;
|
||||
|
||||
private final List<String> lines = new ArrayList<>();
|
||||
private final Map<Integer, String> scores = new HashMap<>();
|
||||
private String title = ChatColor.RESET.toString();
|
||||
|
||||
private boolean deleted = false;
|
||||
|
||||
/**
|
||||
* Creates a new FastBoard.
|
||||
*
|
||||
* @param player the owner of the scoreboard
|
||||
*/
|
||||
public FastBoard(Player player) {
|
||||
this.player = Objects.requireNonNull(player, "player");
|
||||
this.id = "fb-" + Integer.toHexString(ThreadLocalRandom.current().nextInt());
|
||||
|
||||
try {
|
||||
sendObjectivePacket(ObjectiveMode.CREATE);
|
||||
sendDisplayObjectivePacket();
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Unable to create scoreboard", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scoreboard title.
|
||||
*
|
||||
* @return the scoreboard title
|
||||
*/
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the scoreboard title.
|
||||
*
|
||||
* @param title the new scoreboard title
|
||||
* @throws IllegalArgumentException if the title is longer than 32 chars on 1.12 or lower
|
||||
* @throws IllegalStateException if {@link #delete()} was call before
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
if (this.title.equals(Objects.requireNonNull(title, "title"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!VersionType.V1_13.isHigherOrEqual() && title.length() > 32) {
|
||||
throw new IllegalArgumentException("Title is longer than 32 chars");
|
||||
}
|
||||
|
||||
this.title = title;
|
||||
|
||||
try {
|
||||
sendObjectivePacket(ObjectiveMode.UPDATE);
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Unable to update scoreboard title", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scoreboard lines.
|
||||
*
|
||||
* @return the scoreboard lines
|
||||
*/
|
||||
public List<String> getLines() {
|
||||
return new ArrayList<>(this.lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the lines of the scoreboard
|
||||
*
|
||||
* @param lines the new scoreboard lines
|
||||
* @throws IllegalArgumentException if one line is longer than 48 chars on 1.12 or lower
|
||||
* @throws IllegalStateException if {@link #delete()} was call before
|
||||
*/
|
||||
public synchronized void setLines(List<String> lines) {
|
||||
if (lines.size() >= 21) {
|
||||
lines = lines.subList(0, 21);
|
||||
}
|
||||
|
||||
if (!VersionType.V1_13.isHigherOrEqual()) {
|
||||
int lineCount = 0;
|
||||
for (String s : lines) {
|
||||
if (s != null && s.length() > 48) {
|
||||
throw new IllegalArgumentException("Line " + lineCount + " is longer than 48 chars");
|
||||
}
|
||||
lineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
List<String> oldLines = new ArrayList<>(this.lines);
|
||||
this.lines.clear();
|
||||
this.lines.addAll(lines);
|
||||
|
||||
int linesSize = this.lines.size();
|
||||
|
||||
try {
|
||||
if (oldLines.size() != linesSize) {
|
||||
List<String> oldLinesCopy = new ArrayList<>(oldLines);
|
||||
|
||||
if (oldLines.size() > linesSize) {
|
||||
for (int i = oldLinesCopy.size(); i > linesSize; i--) {
|
||||
String score = this.scores.remove(i - 1);
|
||||
|
||||
if (score == null) {
|
||||
score = COLOR_CODES[i - 1];
|
||||
}
|
||||
|
||||
sendTeamPacket(i - 1);
|
||||
sendScorePacket(ScoreboardAction.REMOVE, score, 0);
|
||||
|
||||
oldLines.remove(0);
|
||||
}
|
||||
} else {
|
||||
for (int i = oldLinesCopy.size(); i < linesSize; i++) {
|
||||
sendScoreChange(i, null, null);
|
||||
sendTeamPacket(i, TeamMode.CREATE, "", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < linesSize; i++) {
|
||||
if (!Objects.equals(getLineByScore(oldLines, i), getLineByScore(i))) {
|
||||
sendLineChange(i);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Unable to update scoreboard lines", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player who has the scoreboard.
|
||||
*
|
||||
* @return current player for this FastBoard
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if the scoreboard is deleted.
|
||||
*
|
||||
* @return true if the scoreboard is deleted
|
||||
*/
|
||||
public boolean isDeleted() {
|
||||
return this.deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scoreboard size (the number of lines).
|
||||
*
|
||||
* @return the size
|
||||
*/
|
||||
public int size() {
|
||||
return this.lines.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this FastBoard, and will remove the scoreboard for the associated player if he is online.
|
||||
* After this, all uses of {@link #setLines(List)} and {@link #setTitle(String)} will throw an {@link IllegalStateException}
|
||||
*
|
||||
* @throws IllegalStateException if this was already call before
|
||||
*/
|
||||
public void delete() {
|
||||
try {
|
||||
for (int i = 0; i < this.lines.size(); i++) {
|
||||
sendTeamPacket(i);
|
||||
}
|
||||
|
||||
sendObjectivePacket(ObjectiveMode.REMOVE);
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Unable to delete scoreboard", t);
|
||||
}
|
||||
|
||||
this.deleted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the player has a prefix/suffix characters limit.
|
||||
* By default, it returns true only in 1.12 or lower.
|
||||
* This method can be overridden to fix compatibility with some versions support plugin.
|
||||
*
|
||||
* @return max length
|
||||
*/
|
||||
protected boolean hasLinesMaxLength() {
|
||||
return !VersionType.V1_13.isHigherOrEqual();
|
||||
}
|
||||
|
||||
private String getLineByScore(int score) {
|
||||
return getLineByScore(this.lines, score);
|
||||
}
|
||||
|
||||
private String getLineByScore(List<String> lines, int score) {
|
||||
return score < lines.size() ? lines.get(lines.size() - score - 1) : null;
|
||||
}
|
||||
|
||||
private void sendObjectivePacket(ObjectiveMode mode) throws Throwable {
|
||||
Object packet = PACKET_SB_OBJ.invoke();
|
||||
|
||||
setField(packet, String.class, this.id);
|
||||
setField(packet, int.class, mode.ordinal());
|
||||
|
||||
if (mode != ObjectiveMode.REMOVE) {
|
||||
setComponentField(packet, this.title, 1);
|
||||
|
||||
if (VersionType.V1_8.isHigherOrEqual()) {
|
||||
setField(packet, ENUM_SB_HEALTH_DISPLAY, ENUM_SB_HEALTH_DISPLAY_INTEGER);
|
||||
}
|
||||
} else if (VERSION_TYPE == VersionType.V1_7) {
|
||||
setField(packet, String.class, "", 1);
|
||||
}
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private void sendDisplayObjectivePacket() throws Throwable {
|
||||
Object packet = PACKET_SB_DISPLAY_OBJ.invoke();
|
||||
|
||||
setField(packet, int.class, 1); // Position (1: sidebar)
|
||||
setField(packet, String.class, this.id); // Score Name
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private void sendScorePacket(ScoreboardAction action, String name, int score)
|
||||
throws Throwable {
|
||||
Object packet = PACKET_SB_SCORE.invoke();
|
||||
|
||||
Objects.requireNonNull(name, "name");
|
||||
|
||||
setField(packet, String.class, name, 0); // Player Name
|
||||
|
||||
if (VersionType.V1_8.isHigherOrEqual()) {
|
||||
Object enumAction = action == ScoreboardAction.REMOVE
|
||||
? ENUM_SB_ACTION_REMOVE : ENUM_SB_ACTION_CHANGE;
|
||||
setField(packet, ENUM_SB_ACTION, enumAction);
|
||||
} else {
|
||||
setField(packet, int.class, action.ordinal(), 1); // Action
|
||||
}
|
||||
|
||||
if (action == ScoreboardAction.CHANGE) {
|
||||
setField(packet, String.class, this.id, 1); // Objective Name
|
||||
setField(packet, int.class, score); // Score
|
||||
}
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private void sendTeamPacket(int score) throws Throwable {
|
||||
sendTeamPacket(score, TeamMode.REMOVE, null, null);
|
||||
}
|
||||
|
||||
private void sendTeamPacket(int score, TeamMode mode, String prefix, String suffix)
|
||||
throws Throwable {
|
||||
if (mode == TeamMode.ADD_PLAYERS || mode == TeamMode.REMOVE_PLAYERS) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
Object packet = PACKET_SB_TEAM.invoke();
|
||||
|
||||
setField(packet, String.class, this.id + ':' + score); // Team name
|
||||
setField(packet, int.class, mode.ordinal(), VERSION_TYPE == VersionType.V1_8 ? 1 : 0); // Update mode
|
||||
|
||||
if (mode == TeamMode.CREATE || mode == TeamMode.UPDATE) {
|
||||
Objects.requireNonNull(prefix, "prefix");
|
||||
Objects.requireNonNull(suffix, "suffix");
|
||||
|
||||
if (VersionType.V1_17.isHigherOrEqual()) {
|
||||
Object team = PACKET_SB_SERIALIZABLE_TEAM.invoke();
|
||||
// Since the packet is initialized with null values, we need to change more things.
|
||||
setComponentField(team, "", 0); // Display name
|
||||
setField(team, CHAT_FORMAT_ENUM, RESET_FORMATTING); // Color
|
||||
setComponentField(team, prefix, 1); // Prefix
|
||||
setComponentField(team, suffix, 2); // Suffix
|
||||
setField(team, String.class, "always", 0); // Visibility
|
||||
setField(team, String.class, "always", 1); // Collisions
|
||||
setField(packet, Optional.class, Optional.of(team));
|
||||
} else {
|
||||
setComponentField(packet, prefix, 2); // Prefix
|
||||
setComponentField(packet, suffix, 3); // Suffix
|
||||
setField(packet, String.class, "always", 4); // Visibility for 1.8+
|
||||
setField(packet, String.class, "always", 5); // Collisions for 1.9+
|
||||
}
|
||||
|
||||
if (mode == TeamMode.CREATE) {
|
||||
String player = this.scores.get(score);
|
||||
|
||||
if (player == null) {
|
||||
player = COLOR_CODES[score];
|
||||
}
|
||||
|
||||
setField(packet, Collection.class, Collections.singletonList(player)); // Players in the team
|
||||
}
|
||||
}
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
private void sendLineChange(int score) throws Throwable {
|
||||
int maxLength = hasLinesMaxLength() ? 16 : 1024;
|
||||
String line = getLineByScore(score);
|
||||
String prefix;
|
||||
String name = null;
|
||||
String suffix = null;
|
||||
|
||||
if (line == null || line.isEmpty()) {
|
||||
prefix = COLOR_CODES[score] + ChatColor.RESET;
|
||||
} else if (line.length() <= maxLength) {
|
||||
prefix = line;
|
||||
} else {
|
||||
int i = line.charAt(maxLength - 1) == ChatColor.COLOR_CHAR
|
||||
? (maxLength - 1) : maxLength;
|
||||
if (line.length() <= 28) {
|
||||
// Prevent splitting color codes
|
||||
prefix = line.substring(0, i);
|
||||
String suffixTmp = line.substring(i);
|
||||
ChatColor chatColor = null;
|
||||
|
||||
if (suffixTmp.length() >= 2 && suffixTmp.charAt(0) == ChatColor.COLOR_CHAR) {
|
||||
chatColor = ChatColor.getByChar(suffixTmp.charAt(1));
|
||||
}
|
||||
|
||||
String color = ChatColor.getLastColors(prefix);
|
||||
boolean addColor = chatColor == null || chatColor.isFormat();
|
||||
|
||||
suffix = (addColor ? (color.isEmpty() ? ChatColor.RESET.toString() : color) : "") + suffixTmp;
|
||||
} else {
|
||||
int suffixLength = Math.min(maxLength, line.length() - i);
|
||||
int index2 = line.charAt(line.length() - suffixLength - 1) == ChatColor.COLOR_CHAR
|
||||
? (line.length() - suffixLength - 1) : (line.length() - suffixLength);
|
||||
|
||||
prefix = line.substring(0, i);
|
||||
name = line.substring(i, index2);
|
||||
suffix = line.substring(index2);
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix.length() > maxLength || (suffix != null && suffix.length() > maxLength)) {
|
||||
// Something went wrong, just cut to prevent client crash/kick
|
||||
prefix = prefix.substring(0, maxLength);
|
||||
suffix = (suffix != null) ? suffix.substring(0, maxLength) : null;
|
||||
}
|
||||
|
||||
if (sendScoreChange(score, name, prefix)) {
|
||||
sendTeamPacket(score);
|
||||
sendTeamPacket(score, TeamMode.CREATE, prefix, suffix != null ? suffix : "");
|
||||
} else {
|
||||
sendTeamPacket(score, TeamMode.UPDATE, prefix, suffix != null ? suffix : "");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendScoreChange(int score, String value, String prefix) throws Throwable {
|
||||
String oldValue = this.scores.get(score);
|
||||
String newValue = value != null ? value : COLOR_CODES[score];
|
||||
|
||||
if (Objects.equals(oldValue, newValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.scores.containsValue(newValue)) {
|
||||
String colors = COLOR_CODES[score] + ChatColor.getLastColors(prefix + value);
|
||||
newValue = newValue + colors;
|
||||
}
|
||||
|
||||
if (Objects.equals(oldValue, newValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.scores.put(score, newValue);
|
||||
|
||||
if (oldValue != null) {
|
||||
sendScorePacket(ScoreboardAction.REMOVE, oldValue, score);
|
||||
}
|
||||
|
||||
sendScorePacket(ScoreboardAction.CHANGE, newValue, score);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendPacket(Object packet) throws Throwable {
|
||||
if (this.deleted) {
|
||||
throw new IllegalStateException("This FastBoard is deleted");
|
||||
}
|
||||
|
||||
if (this.player.isOnline()) {
|
||||
Object entityPlayer = PLAYER_GET_HANDLE.invoke(this.player);
|
||||
Object playerConnection = PLAYER_CONNECTION.invoke(entityPlayer);
|
||||
SEND_PACKET.invoke(playerConnection, packet);
|
||||
}
|
||||
}
|
||||
|
||||
private void setField(Object object, Class<?> fieldType, Object value) throws ReflectiveOperationException {
|
||||
setField(object, fieldType, value, 0);
|
||||
}
|
||||
|
||||
private void setField(Object packet, Class<?> fieldType, Object value, int count) throws ReflectiveOperationException {
|
||||
int i = 0;
|
||||
for (Field field : PACKETS.get(packet.getClass())) {
|
||||
if (field.getType() == fieldType && count == i++) {
|
||||
field.set(packet, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setComponentField(Object packet, String value, int count) throws Throwable {
|
||||
if (!VersionType.V1_13.isHigherOrEqual()) {
|
||||
setField(packet, String.class, value, count);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (Field field : PACKETS.get(packet.getClass())) {
|
||||
if ((field.getType() == String.class || field.getType() == CHAT_COMPONENT_CLASS) && count == i++) {
|
||||
field.set(packet, value.isEmpty() ? EMPTY_MESSAGE : Array.get(MESSAGE_FROM_STRING.invoke(value), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ObjectiveMode {
|
||||
CREATE, REMOVE, UPDATE
|
||||
}
|
||||
|
||||
enum TeamMode {
|
||||
CREATE, REMOVE, UPDATE, ADD_PLAYERS, REMOVE_PLAYERS
|
||||
}
|
||||
|
||||
enum ScoreboardAction {
|
||||
CHANGE, REMOVE
|
||||
}
|
||||
|
||||
enum VersionType {
|
||||
V1_7, V1_8, V1_13, V1_17;
|
||||
|
||||
public boolean isHigherOrEqual() {
|
||||
return VERSION_TYPE.ordinal() >= ordinal();
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue