ObamaRuntz x GitGodGuap

Sponsored by the shadow government
This commit is contained in:
John Pork (obamaruntz) 2024-09-05 11:35:18 +01:00
parent 788ed14efa
commit 4d9cae9cd9
646 changed files with 69072 additions and 0 deletions

44
Azurite1.19/pom.xml Normal file
View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

BIN
Azurite1.20/libs/1.20.jar Normal file

Binary file not shown.

44
Azurite1.20/pom.xml Normal file
View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

156
how-to.txt Normal file
View File

@ -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.

BIN
libs/LunarClientAPI.jar Normal file

Binary file not shown.

BIN
libs/ProtocolSupport.jar Normal file

Binary file not shown.

BIN
libs/Vault.jar Normal file

Binary file not shown.

BIN
libs/ViaVersion.jar Normal file

Binary file not shown.

BIN
libs/WorldEdit.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/abilities/SladeAPI.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/ranks/Akuma.jar Normal file

Binary file not shown.

BIN
libs/ranks/Alchemist.jar Normal file

Binary file not shown.

BIN
libs/ranks/AquaCoreAPI.jar Normal file

Binary file not shown.

BIN
libs/ranks/AtomAPI.jar Normal file

Binary file not shown.

BIN
libs/ranks/AzuriteCore.jar Normal file

Binary file not shown.

BIN
libs/ranks/CoreAPI.jar Normal file

Binary file not shown.

BIN
libs/ranks/DeluxeTags.jar Normal file

Binary file not shown.

BIN
libs/ranks/Helium.jar Normal file

Binary file not shown.

BIN
libs/ranks/HestiaAPI.jar Normal file

Binary file not shown.

BIN
libs/ranks/Holiday.jar Normal file

Binary file not shown.

BIN
libs/ranks/MizuAPI.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/ranks/Vault.jar Normal file

Binary file not shown.

BIN
libs/ranks/ZoomAPI.jar Normal file

Binary file not shown.

BIN
libs/ranks/Zoot.jar Normal file

Binary file not shown.

BIN
libs/ranks/pxAPI.jar Normal file

Binary file not shown.

BIN
libs/ranks/zPermissions.jar Normal file

Binary file not shown.

BIN
libs/spigots/1.16.jar Normal file

Binary file not shown.

BIN
libs/spigots/1.17.jar Normal file

Binary file not shown.

BIN
libs/spigots/1.7.10.jar Normal file

Binary file not shown.

BIN
libs/spigots/1.8.8.jar Normal file

Binary file not shown.

311
pom.xml Normal file
View File

@ -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>

View File

@ -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());
}
}
}

View File

@ -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) {
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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,
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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
))
);
}
}
}

View File

@ -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++;
}
}

View File

@ -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());
}
}

View File

@ -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())
);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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))
);
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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))
);
}
}
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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"));
}
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}

View File

@ -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())
);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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