ObamaRuntz x GitGodGuap
Sponsored by the shadow government
This commit is contained in:
parent
788ed14efa
commit
4d9cae9cd9
44
Azurite1.19/pom.xml
Normal file
44
Azurite1.19/pom.xml
Normal 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>
|
@ -0,0 +1,145 @@
|
||||
package me.keano.azurite.modules.nametags.packet.type;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.nametags.NametagManager;
|
||||
import me.keano.azurite.modules.nametags.extra.NameInfo;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.nametags.packet.NametagPacket;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.EnumChatFormat;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.ScoreboardTeam;
|
||||
import net.minecraft.world.scores.ScoreboardTeamBase;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class NametagPacketV1_19_R3 extends NametagPacket {
|
||||
|
||||
private static final Field a = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "a");
|
||||
private static final Field b = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "b");
|
||||
private static final Field c = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "c");
|
||||
private static final Field d = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "d");
|
||||
private static final Field e = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "e");
|
||||
private static final Field f = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "f");
|
||||
private static final Field g = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "g");
|
||||
private static final Constructor<?> PACKET_SCORE_BOARD_CONSTRUCTOR = ReflectionUtils.accessConstructor(PacketPlayOutScoreboardTeam.class, 0);
|
||||
private static final ScoreboardTeam EMPTY_TEAM = new ScoreboardTeam(new Scoreboard(), "empty");
|
||||
|
||||
private static final Map<String, EnumChatFormat> FORMATS = Arrays
|
||||
.stream(EnumChatFormat.values())
|
||||
.collect(Collectors.toMap(EnumChatFormat::toString, e -> e));
|
||||
|
||||
private final Map<String, NameInfo> teams;
|
||||
private final Map<String, String> teamsByPlayer;
|
||||
|
||||
public NametagPacketV1_19_R3(NametagManager manager, Player player) {
|
||||
super(manager, player);
|
||||
this.teams = new ConcurrentHashMap<>();
|
||||
this.teamsByPlayer = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) { // Packet type is unknown 1.8+
|
||||
((CraftPlayer) player).getHandle().b.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToTeam(Player player, String name) {
|
||||
String currentTeam = teamsByPlayer.get(player.getName());
|
||||
NameInfo info = teams.get(name);
|
||||
|
||||
if (currentTeam != null && currentTeam.equals(name)) return;
|
||||
if (info == null) return;
|
||||
|
||||
teamsByPlayer.put(player.getName(), name);
|
||||
sendPacket(new ScoreboardPacket(info, 3, player).toPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
for (NameInfo info : teams.values()) {
|
||||
sendPacket(new ScoreboardPacket(info, 1).toPacket());
|
||||
}
|
||||
|
||||
teams.clear();
|
||||
teamsByPlayer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String name, String color, String prefix, String suffix, boolean friendlyInvis, NameVisibility visibility) {
|
||||
NameInfo current = teams.get(name);
|
||||
|
||||
if (current != null) {
|
||||
if (!current.getColor().equals(color) || !current.getPrefix().equals(prefix) || !current.getSuffix().equals(suffix)) {
|
||||
NameInfo newInfo = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, newInfo);
|
||||
sendPacket(new ScoreboardPacket(newInfo, 2).toPacket());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NameInfo info = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, info);
|
||||
sendPacket(new ScoreboardPacket(info, 0).toPacket());
|
||||
}
|
||||
|
||||
private static class ScoreboardPacket {
|
||||
|
||||
private final NameInfo info;
|
||||
private final Player target;
|
||||
private final int action;
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = null;
|
||||
}
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action, Player target) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public PacketPlayOutScoreboardTeam toPacket() {
|
||||
PacketPlayOutScoreboardTeam.b subPacket = new PacketPlayOutScoreboardTeam.b(EMPTY_TEAM);
|
||||
|
||||
a.set(subPacket, CraftChatMessage.fromString(info.getName())[0]);
|
||||
b.set(subPacket, CraftChatMessage.fromString(info.getPrefix())[0]);
|
||||
c.set(subPacket, CraftChatMessage.fromString(info.getSuffix())[0]);
|
||||
d.set(subPacket, info.getVisibility().getName());
|
||||
e.set(subPacket, ScoreboardTeamBase.EnumTeamPush.b.e);
|
||||
f.set(subPacket, getFormat(info.getColor()));
|
||||
g.set(subPacket, info.isFriendlyInvis() ? 3 : 0);
|
||||
|
||||
return (PacketPlayOutScoreboardTeam) PACKET_SCORE_BOARD_CONSTRUCTOR.newInstance(
|
||||
info.getName(), action,
|
||||
Optional.of(subPacket),
|
||||
(target != null ? Collections.singleton(target.getName()) : Collections.emptySet())
|
||||
);
|
||||
}
|
||||
|
||||
public EnumChatFormat getFormat(String string) {
|
||||
EnumChatFormat format = FORMATS.get(string);
|
||||
return format == null ? EnumChatFormat.v : format;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package me.keano.azurite.modules.tablist.packet.type;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import me.keano.azurite.modules.tablist.Tablist;
|
||||
import me.keano.azurite.modules.tablist.TablistManager;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistEntry;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.tablist.packet.TablistPacket;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.PlayerConnection;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TablistPacketV1_19_R3 extends TablistPacket {
|
||||
|
||||
private final Table<Integer, Integer, EntityPlayer> fakePlayers;
|
||||
private final int maxColumns;
|
||||
|
||||
// Cache them to see if we don't have to send a packet again.
|
||||
private String header;
|
||||
private String footer;
|
||||
|
||||
public TablistPacketV1_19_R3(TablistManager manager, Player player) {
|
||||
super(manager, player);
|
||||
|
||||
this.fakePlayers = HashBasedTable.create();
|
||||
this.header = "";
|
||||
this.footer = "";
|
||||
this.maxColumns = (Utils.getProtocolVersion(player) <= 5 ? 3 : 4);
|
||||
|
||||
this.loadFakes();
|
||||
this.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
this.sendHeaderFooter();
|
||||
|
||||
Tablist tablist = getManager().getAdapter().getInfo(player);
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
TablistEntry entry = tablist.getEntry(col, row);
|
||||
TablistSkin newSkin = entry.getSkin();
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
|
||||
if (fake == null) continue;
|
||||
|
||||
if (fake.e != entry.getPing()) {
|
||||
fake.e = entry.getPing();
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.e, fake));
|
||||
}
|
||||
|
||||
if (newSkin == null) {
|
||||
newSkin = getManager().getDefaultSkins().get(col, row);
|
||||
}
|
||||
|
||||
updateSkin(fake, newSkin);
|
||||
handleTeams(fake.getBukkitEntity(), entry.getText(), calcSlot(col, row));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSkin(EntityPlayer fake, TablistSkin skin) {
|
||||
GameProfile profile = fake.fI();
|
||||
Property old = profile.getProperties().get("textures").stream().findFirst().orElse(null);
|
||||
|
||||
// Verify if we should update
|
||||
if (old != null && old.getValue().equals(skin.getValue()) && old.getSignature().equals(skin.getSignature())) {
|
||||
return;
|
||||
}
|
||||
|
||||
profile.getProperties().clear();
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(profile.getId())));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.e, fake));
|
||||
}
|
||||
|
||||
private void loadFakes() {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
WorldServer worldServer = server.F().iterator().next();
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < 4; col++) {
|
||||
GameProfile profile = new GameProfile(UUID.randomUUID(), getName(col, row));
|
||||
EntityPlayer fake = new EntityPlayer(server, worldServer, profile);
|
||||
TablistSkin skin = getManager().getDefaultSkins().get(col, row);
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
fakePlayers.put(col, row, fake);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
if (fake == null) continue;
|
||||
// Some reason u have to send an add_packet and then following it with update display name.
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) {
|
||||
PlayerConnection connection = ((CraftPlayer) player).getHandle().b;
|
||||
connection.a(packet);
|
||||
}
|
||||
|
||||
private void sendHeaderFooter() {
|
||||
String headerJoined = String.join("\n", getManager().getAdapter().getHeader(player));
|
||||
String footerJoined = String.join("\n", getManager().getAdapter().getFooter(player));
|
||||
|
||||
// Refrain sending a packet again if same.
|
||||
if (footer.equals(headerJoined) && header.equals(headerJoined)) return;
|
||||
|
||||
this.header = headerJoined;
|
||||
this.footer = footerJoined;
|
||||
|
||||
PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(
|
||||
CraftChatMessage.fromJSONOrString(headerJoined, true),
|
||||
CraftChatMessage.fromJSONOrString(footerJoined, true)
|
||||
);
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
}
|
@ -0,0 +1,367 @@
|
||||
package me.keano.azurite.modules.versions.type;
|
||||
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.type.InvisibilityAbility;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.loggers.Logger;
|
||||
import me.keano.azurite.modules.nametags.Nametag;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostClass;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.versions.Version;
|
||||
import me.keano.azurite.modules.versions.VersionManager;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.core.BlockPosition;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.PlayerChunkMap;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EnumItemSlot;
|
||||
import net.minecraft.world.level.block.entity.TileEntity;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.util.CraftChatMessage;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityPotionEffectEvent;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class Version1_19_R3 extends Module<VersionManager> implements Version {
|
||||
|
||||
private static final Field ENTITY_ID = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "b");
|
||||
private static final Field SLOT = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "c");
|
||||
private static final Field ACTION = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "a");
|
||||
private static final Field DATA = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "b");
|
||||
private static final Field ENTITY_LOOKUP = ReflectionUtils.accessField(WorldServer.class, "entityLookup");
|
||||
|
||||
private static final Method ENTITY_GET = ReflectionUtils.accessMethod(
|
||||
ReflectionUtils.getClass("io.papermc.paper.chunk.system.entity.EntityLookup"), "get", int.class);
|
||||
|
||||
private static final Method SPAWN_PARTICLE = ReflectionUtils.accessMethod(
|
||||
CraftWorld.class, "spawnParticle", Particle.class, Location.class, int.class, Object.class
|
||||
);
|
||||
|
||||
public Version1_19_R3(VersionManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandMap getCommandMap() {
|
||||
try {
|
||||
|
||||
CraftServer server = (CraftServer) Bukkit.getServer();
|
||||
Method method = server.getClass().getMethod("getCommandMap");
|
||||
return (CommandMap) method.invoke(server);
|
||||
|
||||
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public Set<Player> getTrackedPlayers(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
|
||||
|
||||
if (tracker != null) {
|
||||
Set<Player> players = new HashSet<>();
|
||||
|
||||
for (ServerPlayerConnection connection : tracker.f) {
|
||||
players.add(connection.f().getBukkitEntity());
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotGapple(ItemStack item) {
|
||||
return item.getType() != Material.ENCHANTED_GOLDEN_APPLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
return craftPlayer.getHandle().e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand(Player player) {
|
||||
try {
|
||||
|
||||
Method method = player.getInventory().getClass().getMethod("getItemInMainHand");
|
||||
return (ItemStack) method.invoke(player.getInventory());
|
||||
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack addGlow(ItemStack itemStack) {
|
||||
itemStack.addUnsafeEnchantment(Enchantment.WATER_WORKER, 1);
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
itemStack.setItemMeta(meta);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInHand(Player player, ItemStack item) {
|
||||
try {
|
||||
|
||||
Method method = player.getInventory().getClass().getMethod("setItemInMainHand", ItemStack.class);
|
||||
method.invoke(player.getInventory(), item);
|
||||
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLoggerDeath(Logger logger) {
|
||||
EntityPlayer player = ((CraftPlayer) logger.getPlayer()).getHandle();
|
||||
player.getBukkitEntity().getInventory().clear();
|
||||
player.getBukkitEntity().getInventory().setArmorContents(null);
|
||||
player.getBukkitEntity().setHealth(0);
|
||||
player.getBukkitEntity().setExp(0.0F);
|
||||
player.removeAllEffects(EntityPotionEffectEvent.Cause.DEATH);
|
||||
player.getBukkitEntity().saveData(); // Save the inventory and everything we just modified
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEffect(Location location, String name, Object data) {
|
||||
try {
|
||||
|
||||
Particle particle = Particle.valueOf(name);
|
||||
SPAWN_PARTICLE.invoke(location.getWorld(), particle, location, 1, data);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Particle " + name + " does not exist.");
|
||||
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTPSColored() {
|
||||
double tps = MinecraftServer.getServer().recentTps[0];
|
||||
String color = (tps > 18 ? "§a" : tps > 16 ? "§e" : "§c");
|
||||
String asterisk = (tps > 20 ? "*" : "");
|
||||
return color + asterisk + Math.min(Math.round(tps * 100.0) / 100.0, 20.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
|
||||
|
||||
if (tracker != null) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(null)));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = entityPlayer.tracker;
|
||||
|
||||
if (tracker != null) {
|
||||
org.bukkit.inventory.PlayerInventory inventory = player.getInventory();
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(inventory.getBoots())));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(inventory.getLeggings())));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(inventory.getChestplate())));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(inventory.getHelmet())));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleNettyListener(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
ChannelPipeline pipeline = entityPlayer.b.h.m.pipeline();
|
||||
AbilityManager abilityManager = getInstance().getAbilityManager();
|
||||
InvisibilityAbility ability = (InvisibilityAbility) abilityManager.getAbility("Invisibility");
|
||||
GhostClass ghostClass = getInstance().getClassManager().getGhostClass();
|
||||
|
||||
if (pipeline.get("packet_handler") == null) {
|
||||
player.kickPlayer(Config.COULD_NOT_LOAD_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline.addBefore("packet_handler", "Azurite", new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
if (msg instanceof PacketPlayOutEntityEquipment packet) {
|
||||
WorldServer server = ((CraftWorld) player.getWorld()).getHandle();
|
||||
Entity entity = (Entity) ENTITY_GET.invoke(ENTITY_LOOKUP.get(server), (int) ENTITY_ID.get(packet));
|
||||
|
||||
if (entity != null) {
|
||||
if (ghostClass != null && ghostClass.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().e()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().e()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (msg instanceof ClientboundPlayerInfoUpdatePacket) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) msg;
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.a> actions = (EnumSet<ClientboundPlayerInfoUpdatePacket.a>) ACTION.get(packet);
|
||||
Nametag nametag = getInstance().getNametagManager().getNametags().get(player.getUniqueId());
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.a action : actions) {
|
||||
if (action == ClientboundPlayerInfoUpdatePacket.a.a && nametag != null) {
|
||||
List<ClientboundPlayerInfoUpdatePacket.b> data = (List<ClientboundPlayerInfoUpdatePacket.b>) DATA.get(packet);
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.b info : data) {
|
||||
Player targetPlayer = Bukkit.getPlayer(info.a());
|
||||
|
||||
if (targetPlayer == null) continue;
|
||||
|
||||
// Make tablist sort instantly
|
||||
nametag.getPacket().create("tablist", "", "", "", false, NameVisibility.ALWAYS);
|
||||
nametag.getPacket().addToTeam(targetPlayer, "tablist");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(Player player, String string) {
|
||||
ClientboundSetActionBarTextPacket packet = new ClientboundSetActionBarTextPacket(CraftChatMessage.fromJSONOrString(string, true));
|
||||
((CraftPlayer) player).getHandle().b.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToServer(Player player, String server) {
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
out.writeUTF("Connect");
|
||||
out.writeUTF(server);
|
||||
player.sendPluginMessage(getInstance(), "BungeeCord", out.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearArrows(Player player) {
|
||||
((CraftPlayer) player).getHandle().setArrowCount(0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getBlockDrops(Player pl, Block bl, ItemStack hand) {
|
||||
EntityPlayer serverPlayer = ((CraftPlayer) pl).getHandle();
|
||||
WorldServer serverLevel = serverPlayer.cG().getMinecraftWorld();
|
||||
BlockPosition blockPos = new BlockPosition(bl.getX(), bl.getY(), bl.getZ());
|
||||
IBlockData blockState = serverLevel.a_(blockPos);
|
||||
TileEntity blockEntity = serverLevel.c_(blockPos);
|
||||
|
||||
return net.minecraft.world.level.block.Block.a(blockState, serverLevel, blockPos, blockEntity, serverPlayer, serverPlayer.fJ().f())
|
||||
.stream().map(CraftItemStack::asBukkitCopy).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TablistSkin getSkinData(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
GameProfile profile = entityPlayer.fI();
|
||||
|
||||
if (profile.getProperties().get("textures").size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Property property = profile.getProperties().get("textures").iterator().next();
|
||||
return new TablistSkin(property.getValue(), property.getSignature());
|
||||
}
|
||||
}
|
BIN
Azurite1.20/libs/1.20.jar
Normal file
BIN
Azurite1.20/libs/1.20.jar
Normal file
Binary file not shown.
44
Azurite1.20/pom.xml
Normal file
44
Azurite1.20/pom.xml
Normal 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>
|
@ -0,0 +1,155 @@
|
||||
package me.keano.azurite.modules.nametags.packet.type;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.nametags.NametagManager;
|
||||
import me.keano.azurite.modules.nametags.extra.NameInfo;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.nametags.packet.NametagPacket;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.EnumChatFormat;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutScoreboardTeam;
|
||||
import net.minecraft.world.scores.Scoreboard;
|
||||
import net.minecraft.world.scores.ScoreboardTeam;
|
||||
import net.minecraft.world.scores.ScoreboardTeamBase;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class NametagPacketV1_20_R1 extends NametagPacket {
|
||||
|
||||
private static final Field a = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "a");
|
||||
private static final Field b = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "b");
|
||||
private static final Field c = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "c");
|
||||
private static final Field d = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "d");
|
||||
private static final Field e = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "e");
|
||||
private static final Field f = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "f");
|
||||
private static final Field g = ReflectionUtils.accessField(PacketPlayOutScoreboardTeam.b.class, "g");
|
||||
private static final ScoreboardTeam EMPTY_TEAM = new ScoreboardTeam(new Scoreboard(), "empty");
|
||||
private static final Constructor<?> PACKET_SCORE_BOARD_CONSTRUCTOR;
|
||||
|
||||
private static final Map<String, EnumChatFormat> FORMATS = Arrays
|
||||
.stream(EnumChatFormat.values())
|
||||
.collect(Collectors.toMap(EnumChatFormat::toString, e -> e));
|
||||
|
||||
private final Map<String, NameInfo> teams;
|
||||
private final Map<String, String> teamsByPlayer;
|
||||
|
||||
static {
|
||||
try {
|
||||
|
||||
PACKET_SCORE_BOARD_CONSTRUCTOR = PacketPlayOutScoreboardTeam.class.getDeclaredConstructor(
|
||||
String.class, int.class, Optional.class, Collection.class
|
||||
);
|
||||
PACKET_SCORE_BOARD_CONSTRUCTOR.setAccessible(true);
|
||||
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public NametagPacketV1_20_R1(NametagManager manager, Player player) {
|
||||
super(manager, player);
|
||||
this.teams = new ConcurrentHashMap<>();
|
||||
this.teamsByPlayer = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) { // Packet type is unknown 1.8+
|
||||
((CraftPlayer) player).getHandle().c.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToTeam(Player player, String name) {
|
||||
String currentTeam = teamsByPlayer.get(player.getName());
|
||||
NameInfo info = teams.get(name);
|
||||
|
||||
if (currentTeam != null && currentTeam.equals(name)) return;
|
||||
if (info == null) return;
|
||||
|
||||
teamsByPlayer.put(player.getName(), name);
|
||||
sendPacket(new ScoreboardPacket(info, 3, player).toPacket());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
for (NameInfo info : teams.values()) {
|
||||
sendPacket(new ScoreboardPacket(info, 1).toPacket());
|
||||
}
|
||||
|
||||
teams.clear();
|
||||
teamsByPlayer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String name, String color, String prefix, String suffix, boolean friendlyInvis, NameVisibility visibility) {
|
||||
NameInfo current = teams.get(name);
|
||||
|
||||
if (current != null) {
|
||||
if (!current.getColor().equals(color) || !current.getPrefix().equals(prefix) || !current.getSuffix().equals(suffix)) {
|
||||
NameInfo newInfo = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, newInfo);
|
||||
sendPacket(new ScoreboardPacket(newInfo, 2).toPacket());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NameInfo info = new NameInfo(name, color, prefix, suffix, visibility, friendlyInvis);
|
||||
teams.put(name, info);
|
||||
sendPacket(new ScoreboardPacket(info, 0).toPacket());
|
||||
}
|
||||
|
||||
private static class ScoreboardPacket {
|
||||
|
||||
private final NameInfo info;
|
||||
private final Player target;
|
||||
private final int action;
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = null;
|
||||
}
|
||||
|
||||
public ScoreboardPacket(NameInfo info, int action, Player target) {
|
||||
this.info = info;
|
||||
this.action = action;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public PacketPlayOutScoreboardTeam toPacket() {
|
||||
PacketPlayOutScoreboardTeam.b subPacket = new PacketPlayOutScoreboardTeam.b(EMPTY_TEAM);
|
||||
|
||||
a.set(subPacket, CraftChatMessage.fromString(info.getName())[0]);
|
||||
b.set(subPacket, CraftChatMessage.fromString(info.getPrefix())[0]);
|
||||
c.set(subPacket, CraftChatMessage.fromString(info.getSuffix())[0]);
|
||||
d.set(subPacket, info.getVisibility().getName());
|
||||
e.set(subPacket, ScoreboardTeamBase.EnumTeamPush.b.e);
|
||||
f.set(subPacket, getFormat(info.getColor()));
|
||||
g.set(subPacket, info.isFriendlyInvis() ? 3 : 0);
|
||||
|
||||
return (PacketPlayOutScoreboardTeam) PACKET_SCORE_BOARD_CONSTRUCTOR.newInstance(
|
||||
info.getName(), action,
|
||||
Optional.of(subPacket),
|
||||
(target != null ? Collections.singleton(target.getName()) : Collections.emptySet())
|
||||
);
|
||||
}
|
||||
|
||||
public EnumChatFormat getFormat(String string) {
|
||||
EnumChatFormat format = FORMATS.get(string);
|
||||
return format == null ? EnumChatFormat.v : format;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package me.keano.azurite.modules.tablist.packet.type;
|
||||
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import me.keano.azurite.modules.tablist.Tablist;
|
||||
import me.keano.azurite.modules.tablist.TablistManager;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistEntry;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.tablist.packet.TablistPacket;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutPlayerListHeaderFooter;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.PlayerConnection;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TablistPacketV1_20_R1 extends TablistPacket {
|
||||
|
||||
private final Table<Integer, Integer, EntityPlayer> fakePlayers;
|
||||
private final int maxColumns;
|
||||
|
||||
// Cache them to see if we don't have to send a packet again.
|
||||
private String header;
|
||||
private String footer;
|
||||
|
||||
public TablistPacketV1_20_R1(TablistManager manager, Player player) {
|
||||
super(manager, player);
|
||||
|
||||
this.fakePlayers = HashBasedTable.create();
|
||||
this.header = "";
|
||||
this.footer = "";
|
||||
this.maxColumns = (Utils.getProtocolVersion(player) <= 5 ? 3 : 4);
|
||||
|
||||
this.loadFakes();
|
||||
this.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
this.sendHeaderFooter();
|
||||
|
||||
Tablist tablist = getManager().getAdapter().getInfo(player);
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
TablistEntry entry = tablist.getEntry(col, row);
|
||||
TablistSkin newSkin = entry.getSkin();
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
|
||||
if (fake == null) continue;
|
||||
|
||||
if (fake.f != entry.getPing()) {
|
||||
fake.f = entry.getPing();
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.e, fake));
|
||||
}
|
||||
|
||||
if (newSkin == null) {
|
||||
newSkin = getManager().getDefaultSkins().get(col, row);
|
||||
}
|
||||
|
||||
updateSkin(fake, newSkin);
|
||||
handleTeams(fake.getBukkitEntity(), entry.getText(), calcSlot(col, row));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSkin(EntityPlayer fake, TablistSkin skin) {
|
||||
GameProfile profile = fake.fM();
|
||||
Property old = profile.getProperties().get("textures").stream().findFirst().orElse(null);
|
||||
|
||||
// Verify if we should update
|
||||
if (old != null && old.getValue().equals(skin.getValue()) && old.getSignature().equals(skin.getSignature())) {
|
||||
return;
|
||||
}
|
||||
|
||||
profile.getProperties().clear();
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
|
||||
sendPacket(new ClientboundPlayerInfoRemovePacket(Collections.singletonList(profile.getId())));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
}
|
||||
|
||||
private void loadFakes() {
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
WorldServer worldServer = server.F().iterator().next();
|
||||
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < 4; col++) {
|
||||
GameProfile profile = new GameProfile(UUID.randomUUID(), getName(col, row));
|
||||
EntityPlayer fake = new EntityPlayer(server, worldServer, profile);
|
||||
TablistSkin skin = getManager().getDefaultSkins().get(col, row);
|
||||
profile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
|
||||
fakePlayers.put(col, row, fake);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
for (int row = 0; row < 20; row++) {
|
||||
for (int col = 0; col < maxColumns; col++) {
|
||||
EntityPlayer fake = fakePlayers.get(col, row);
|
||||
if (fake == null) continue;
|
||||
// Some reason u have to send an add_packet and then following it with update display name.
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, fake));
|
||||
sendPacket(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, fake));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(Packet<?> packet) {
|
||||
PlayerConnection connection = ((CraftPlayer) player).getHandle().c;
|
||||
connection.a(packet);
|
||||
}
|
||||
|
||||
private void sendHeaderFooter() {
|
||||
String headerJoined = String.join("\n", getManager().getAdapter().getHeader(player));
|
||||
String footerJoined = String.join("\n", getManager().getAdapter().getFooter(player));
|
||||
|
||||
// Refrain sending a packet again if same.
|
||||
if (footer.equals(headerJoined) && header.equals(headerJoined)) return;
|
||||
|
||||
this.header = headerJoined;
|
||||
this.footer = footerJoined;
|
||||
|
||||
PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(
|
||||
CraftChatMessage.fromJSONOrString(headerJoined, true),
|
||||
CraftChatMessage.fromJSONOrString(footerJoined, true)
|
||||
);
|
||||
|
||||
sendPacket(packet);
|
||||
}
|
||||
}
|
@ -0,0 +1,362 @@
|
||||
package me.keano.azurite.modules.versions.type;
|
||||
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import lombok.SneakyThrows;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.type.InvisibilityAbility;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.loggers.Logger;
|
||||
import me.keano.azurite.modules.nametags.Nametag;
|
||||
import me.keano.azurite.modules.nametags.extra.NameVisibility;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostClass;
|
||||
import me.keano.azurite.modules.tablist.extra.TablistSkin;
|
||||
import me.keano.azurite.modules.versions.Version;
|
||||
import me.keano.azurite.modules.versions.VersionManager;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import net.minecraft.core.BlockPosition;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import net.minecraft.server.level.PlayerChunkMap;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.server.network.PlayerConnection;
|
||||
import net.minecraft.server.network.ServerPlayerConnection;
|
||||
import net.minecraft.world.EnumHand;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EnumItemSlot;
|
||||
import net.minecraft.world.level.block.entity.TileEntity;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityPotionEffectEvent;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public class Version1_20_R1 extends Module<VersionManager> implements Version {
|
||||
|
||||
private static final Field ENTITY_ID = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "b");
|
||||
private static final Field SLOT = ReflectionUtils.accessField(PacketPlayOutEntityEquipment.class, "c");
|
||||
private static final Field ACTION = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "a");
|
||||
private static final Field DATA = ReflectionUtils.accessField(ClientboundPlayerInfoUpdatePacket.class, "b");
|
||||
private static final Field NETWORK_MANAGER = ReflectionUtils.accessField(PlayerConnection.class, "h");
|
||||
private static final Field ENTITY_LOOKUP = ReflectionUtils.accessField(WorldServer.class, "entityLookup");
|
||||
|
||||
private static final Method ENTITY_GET = ReflectionUtils.accessMethod(
|
||||
ReflectionUtils.getClass("io.papermc.paper.chunk.system.entity.EntityLookup"), "get", int.class);
|
||||
|
||||
private static final Method SPAWN_PARTICLE = ReflectionUtils.accessMethod(
|
||||
CraftWorld.class, "spawnParticle", Particle.class, Location.class, int.class, Object.class
|
||||
);
|
||||
|
||||
public Version1_20_R1(VersionManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandMap getCommandMap() {
|
||||
try {
|
||||
|
||||
CraftServer server = (CraftServer) Bukkit.getServer();
|
||||
Method method = server.getClass().getMethod("getCommandMap");
|
||||
return (CommandMap) method.invoke(server);
|
||||
|
||||
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Player> getTrackedPlayers(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = ((WorldServer) entityPlayer.dI()).k().a.K.get(player.getEntityId());
|
||||
|
||||
if (tracker != null) {
|
||||
Set<Player> players = new HashSet<>();
|
||||
|
||||
for (ServerPlayerConnection connection : tracker.f) {
|
||||
players.add(connection.f().getBukkitEntity());
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotGapple(ItemStack item) {
|
||||
return item.getType() != Material.ENCHANTED_GOLDEN_APPLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPing(Player player) {
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
return craftPlayer.getHandle().f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand(Player player) {
|
||||
return player.getInventory().getItemInMainHand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack addGlow(ItemStack itemStack) {
|
||||
itemStack.addUnsafeEnchantment(Enchantment.WATER_WORKER, 1);
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
itemStack.setItemMeta(meta);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInHand(Player player, ItemStack item) {
|
||||
try {
|
||||
|
||||
Method method = player.getInventory().getClass().getMethod("setItemInMainHand", ItemStack.class);
|
||||
method.invoke(player.getInventory(), item);
|
||||
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLoggerDeath(Logger logger) {
|
||||
EntityPlayer player = ((CraftPlayer) logger.getPlayer()).getHandle();
|
||||
player.getBukkitEntity().getInventory().clear();
|
||||
player.getBukkitEntity().getInventory().setArmorContents(null);
|
||||
player.getBukkitEntity().setHealth(0);
|
||||
player.getBukkitEntity().setExp(0.0F);
|
||||
player.removeAllEffects(EntityPotionEffectEvent.Cause.DEATH);
|
||||
player.getBukkitEntity().saveData(); // Save the inventory and everything we just modified
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEffect(Location location, String name, Object data) {
|
||||
try {
|
||||
|
||||
Particle particle = Particle.valueOf(name);
|
||||
SPAWN_PARTICLE.invoke(location.getWorld(), particle, location, 1, data);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Particle " + name + " does not exist.");
|
||||
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTPSColored() {
|
||||
double tps = MinecraftServer.getServer().recentTps[0];
|
||||
String color = (tps > 18 ? "§a" : tps > 16 ? "§e" : "§c");
|
||||
String asterisk = (tps > 20 ? "*" : "");
|
||||
return color + asterisk + Math.min(Math.round(tps * 100.0) / 100.0, 20.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = ((WorldServer) entityPlayer.dI()).k().a.K.get(player.getEntityId());
|
||||
|
||||
if (tracker != null) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(null)));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(null)));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showArmor(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
PlayerChunkMap.EntityTracker tracker = ((WorldServer) entityPlayer.dI()).k().a.K.get(player.getEntityId());
|
||||
|
||||
if (tracker != null) {
|
||||
org.bukkit.inventory.PlayerInventory inventory = player.getInventory();
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> items = new ArrayList<>();
|
||||
|
||||
items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(inventory.getBoots())));
|
||||
items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(inventory.getLeggings())));
|
||||
items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(inventory.getChestplate())));
|
||||
items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(inventory.getHelmet())));
|
||||
|
||||
tracker.a(new PacketPlayOutEntityEquipment(player.getEntityId(), items));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void handleNettyListener(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
ChannelPipeline pipeline = ((NetworkManager) NETWORK_MANAGER.get(entityPlayer.c)).m.pipeline();
|
||||
AbilityManager abilityManager = getInstance().getAbilityManager();
|
||||
InvisibilityAbility ability = (InvisibilityAbility) abilityManager.getAbility("Invisibility");
|
||||
GhostClass ghostClass = getInstance().getClassManager().getGhostClass();
|
||||
|
||||
if (pipeline.get("packet_handler") == null) {
|
||||
player.kickPlayer(Config.COULD_NOT_LOAD_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline.addBefore("packet_handler", "Azurite", new ChannelDuplexHandler() {
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
if (msg instanceof PacketPlayOutEntityEquipment packet) {
|
||||
WorldServer server = ((CraftWorld) player.getWorld()).getHandle();
|
||||
Entity entity = (Entity) ENTITY_GET.invoke(ENTITY_LOOKUP.get(server), (int) ENTITY_ID.get(packet));
|
||||
|
||||
if (entity != null) {
|
||||
if (ghostClass != null && ghostClass.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().a() == EnumItemSlot.Function.b) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.getInvisible().contains(entity.getBukkitEntity().getUniqueId())) {
|
||||
List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> slot =
|
||||
(List<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>>) SLOT.get(packet);
|
||||
|
||||
Iterator<Pair<EnumItemSlot, net.minecraft.world.item.ItemStack>> iterator = slot.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<EnumItemSlot, net.minecraft.world.item.ItemStack> pair = iterator.next();
|
||||
|
||||
if (pair.getFirst().a() == EnumItemSlot.Function.b) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
SLOT.set(packet, slot); // update it in packet
|
||||
|
||||
if (slot.isEmpty()) {
|
||||
return; // Don't send the packet.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (msg instanceof ClientboundPlayerInfoUpdatePacket) {
|
||||
ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) msg;
|
||||
EnumSet<ClientboundPlayerInfoUpdatePacket.a> actions = (EnumSet<ClientboundPlayerInfoUpdatePacket.a>) ACTION.get(packet);
|
||||
Nametag nametag = getInstance().getNametagManager().getNametags().get(player.getUniqueId());
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.a action : actions) {
|
||||
if (action == ClientboundPlayerInfoUpdatePacket.a.a && nametag != null) {
|
||||
List<ClientboundPlayerInfoUpdatePacket.b> data = (List<ClientboundPlayerInfoUpdatePacket.b>) DATA.get(packet);
|
||||
|
||||
for (ClientboundPlayerInfoUpdatePacket.b info : data) {
|
||||
Player targetPlayer = Bukkit.getPlayer(info.a());
|
||||
|
||||
if (targetPlayer == null) continue;
|
||||
|
||||
// Make tablist sort instantly
|
||||
nametag.getPacket().create("tablist", "", "", "", false, NameVisibility.ALWAYS);
|
||||
nametag.getPacket().addToTeam(targetPlayer, "tablist");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(Player player, String string) {
|
||||
ClientboundSetActionBarTextPacket packet = new ClientboundSetActionBarTextPacket(CraftChatMessage.fromJSONOrString(string, true));
|
||||
((CraftPlayer) player).getHandle().c.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToServer(Player player, String server) {
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
out.writeUTF("Connect");
|
||||
out.writeUTF(server);
|
||||
player.sendPluginMessage(getInstance(), "BungeeCord", out.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearArrows(Player player) {
|
||||
((CraftPlayer) player).getHandle().setArrowCount(0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getBlockDrops(Player pl, Block bl, ItemStack hand) {
|
||||
EntityPlayer serverPlayer = ((CraftPlayer) pl).getHandle();
|
||||
WorldServer serverLevel = serverPlayer.x().getMinecraftWorld();
|
||||
BlockPosition blockPos = new BlockPosition(bl.getX(), bl.getY(), bl.getZ());
|
||||
IBlockData blockState = serverLevel.a_(blockPos);
|
||||
TileEntity blockEntity = serverLevel.c_(blockPos);
|
||||
return net.minecraft.world.level.block.Block.a(blockState, serverLevel, blockPos, blockEntity, serverPlayer, serverPlayer.b(EnumHand.a))
|
||||
.stream().map(CraftItemStack::asBukkitCopy).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TablistSkin getSkinData(Player player) {
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
GameProfile profile = entityPlayer.fM();
|
||||
|
||||
if (profile.getProperties().get("textures").size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Property property = profile.getProperties().get("textures").iterator().next();
|
||||
return new TablistSkin(property.getValue(), property.getSignature());
|
||||
}
|
||||
}
|
156
how-to.txt
Normal file
156
how-to.txt
Normal 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}'
|
BIN
libs/Citizens-2.0.29-b2490.jar
Normal file
BIN
libs/Citizens-2.0.29-b2490.jar
Normal file
Binary file not shown.
BIN
libs/LunarClientAPI.jar
Normal file
BIN
libs/LunarClientAPI.jar
Normal file
Binary file not shown.
BIN
libs/ProtocolSupport.jar
Normal file
BIN
libs/ProtocolSupport.jar
Normal file
Binary file not shown.
BIN
libs/Vault.jar
Normal file
BIN
libs/Vault.jar
Normal file
Binary file not shown.
BIN
libs/ViaVersion.jar
Normal file
BIN
libs/ViaVersion.jar
Normal file
Binary file not shown.
BIN
libs/WorldEdit.jar
Normal file
BIN
libs/WorldEdit.jar
Normal file
Binary file not shown.
BIN
libs/abilities/PandaAbilityAPI.jar
Normal file
BIN
libs/abilities/PandaAbilityAPI.jar
Normal file
Binary file not shown.
BIN
libs/abilities/SladeAPI.jar
Normal file
BIN
libs/abilities/SladeAPI.jar
Normal file
Binary file not shown.
BIN
libs/clients/CheatBreakerAPI.jar
Normal file
BIN
libs/clients/CheatBreakerAPI.jar
Normal file
Binary file not shown.
BIN
libs/clients/LunarClientAPI.jar
Normal file
BIN
libs/clients/LunarClientAPI.jar
Normal file
Binary file not shown.
BIN
libs/holograms/HolographicDisplays.jar
Normal file
BIN
libs/holograms/HolographicDisplays.jar
Normal file
Binary file not shown.
BIN
libs/pearls/VortexPearlsAPI.jar
Normal file
BIN
libs/pearls/VortexPearlsAPI.jar
Normal file
Binary file not shown.
BIN
libs/placeholders/PlaceholderAPI.jar
Normal file
BIN
libs/placeholders/PlaceholderAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/Akuma.jar
Normal file
BIN
libs/ranks/Akuma.jar
Normal file
Binary file not shown.
BIN
libs/ranks/Alchemist.jar
Normal file
BIN
libs/ranks/Alchemist.jar
Normal file
Binary file not shown.
BIN
libs/ranks/AquaCoreAPI.jar
Normal file
BIN
libs/ranks/AquaCoreAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/AtomAPI.jar
Normal file
BIN
libs/ranks/AtomAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/AzuriteCore.jar
Normal file
BIN
libs/ranks/AzuriteCore.jar
Normal file
Binary file not shown.
BIN
libs/ranks/CoreAPI.jar
Normal file
BIN
libs/ranks/CoreAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/DeluxeTags.jar
Normal file
BIN
libs/ranks/DeluxeTags.jar
Normal file
Binary file not shown.
BIN
libs/ranks/Helium.jar
Normal file
BIN
libs/ranks/Helium.jar
Normal file
Binary file not shown.
BIN
libs/ranks/HestiaAPI.jar
Normal file
BIN
libs/ranks/HestiaAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/Holiday.jar
Normal file
BIN
libs/ranks/Holiday.jar
Normal file
Binary file not shown.
BIN
libs/ranks/MizuAPI.jar
Normal file
BIN
libs/ranks/MizuAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/PowerfulPerms.jar
Normal file
BIN
libs/ranks/PowerfulPerms.jar
Normal file
Binary file not shown.
BIN
libs/ranks/Vault.jar
Normal file
BIN
libs/ranks/Vault.jar
Normal file
Binary file not shown.
BIN
libs/ranks/ZoomAPI.jar
Normal file
BIN
libs/ranks/ZoomAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/Zoot.jar
Normal file
BIN
libs/ranks/Zoot.jar
Normal file
Binary file not shown.
BIN
libs/ranks/pxAPI.jar
Normal file
BIN
libs/ranks/pxAPI.jar
Normal file
Binary file not shown.
BIN
libs/ranks/zPermissions.jar
Normal file
BIN
libs/ranks/zPermissions.jar
Normal file
Binary file not shown.
BIN
libs/spigots/1.16.jar
Normal file
BIN
libs/spigots/1.16.jar
Normal file
Binary file not shown.
BIN
libs/spigots/1.17.jar
Normal file
BIN
libs/spigots/1.17.jar
Normal file
Binary file not shown.
BIN
libs/spigots/1.7.10.jar
Normal file
BIN
libs/spigots/1.7.10.jar
Normal file
Binary file not shown.
BIN
libs/spigots/1.8.8.jar
Normal file
BIN
libs/spigots/1.8.8.jar
Normal file
Binary file not shown.
311
pom.xml
Normal file
311
pom.xml
Normal 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>
|
195
src/java/me/keano/azurite/HCF.java
Normal file
195
src/java/me/keano/azurite/HCF.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
201
src/java/me/keano/azurite/modules/ability/Ability.java
Normal file
201
src/java/me/keano/azurite/modules/ability/Ability.java
Normal 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) {
|
||||
}
|
||||
}
|
101
src/java/me/keano/azurite/modules/ability/AbilityManager.java
Normal file
101
src/java/me/keano/azurite/modules/ability/AbilityManager.java
Normal 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());
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package me.keano.azurite.modules.ability.command;
|
||||
|
||||
import me.keano.azurite.modules.ability.menu.AbilityListMenu;
|
||||
import me.keano.azurite.modules.commands.CommandManager;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.commands.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilitiesCommand extends Command {
|
||||
|
||||
public AbilitiesCommand(CommandManager manager) {
|
||||
super(
|
||||
manager,
|
||||
"abilities"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> aliases() {
|
||||
return Arrays.asList(
|
||||
"partneritems",
|
||||
"abilitymenu"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> usage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sendMessage(sender, Config.PLAYER_ONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
new AbilityListMenu(getInstance().getMenuManager(), player).open();
|
||||
}
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package me.keano.azurite.modules.ability.command;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.menu.AbilityToggleMenu;
|
||||
import me.keano.azurite.modules.commands.CommandManager;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.commands.Command;
|
||||
import me.keano.azurite.modules.framework.commands.extra.TabCompletion;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityCommand extends Command {
|
||||
|
||||
public AbilityCommand(CommandManager manager) {
|
||||
super(
|
||||
manager,
|
||||
"ability"
|
||||
);
|
||||
this.setPermissible("azurite.ability");
|
||||
this.completions.add(new TabCompletion(Arrays.asList("give", "list", "toggle", "getall"), 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> aliases() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> usage() {
|
||||
return getLanguageConfig().getStringList("ABILITY_COMMAND.USAGE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
if (!sender.hasPermission(permissible)) {
|
||||
sendMessage(sender, Config.INSUFFICIENT_PERM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sendUsage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "give":
|
||||
if (args.length < 4) {
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_GIVE.USAGE"));
|
||||
return;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayer(args[1]);
|
||||
Ability ability = getInstance().getAbilityManager().getAbility(args[2]);
|
||||
Integer amount = getInt(args[3]);
|
||||
|
||||
if (target == null) {
|
||||
sendMessage(sender, Config.PLAYER_NOT_FOUND
|
||||
.replace("%player%", args[1])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ability == null) {
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_GIVE.NOT_FOUND")
|
||||
.replace("%ability%", args[1])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount == null) {
|
||||
sendMessage(sender, Config.NOT_VALID_NUMBER
|
||||
.replace("%number%", args[3])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = ability.getItem().clone();
|
||||
itemStack.setAmount(amount);
|
||||
ItemUtils.giveItem(target, itemStack, target.getLocation());
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_GIVE.GAVE")
|
||||
.replace("%player%", target.getName())
|
||||
.replace("%amount%", String.valueOf(amount))
|
||||
.replace("%ability%", ability.getName())
|
||||
);
|
||||
return;
|
||||
|
||||
case "list":
|
||||
for (String s : getLanguageConfig().getStringList("ABILITY_COMMAND.ABILITY_LIST.ABILITIES")) {
|
||||
if (!s.equalsIgnoreCase("%abilities%")) {
|
||||
sendMessage(sender, s);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Ability abili : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
sendMessage(sender, getLanguageConfig().getString("ABILITY_COMMAND.ABILITY_LIST.ABILITY_FORMAT")
|
||||
.replace("%ability%", abili.getName().replaceAll(" ", ""))
|
||||
.replace("%cooldown%", String.valueOf(abili.getAbilityCooldown().getSeconds()))
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case "toggle":
|
||||
if (!(sender instanceof Player)) {
|
||||
sendMessage(sender, Config.PLAYER_ONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
new AbilityToggleMenu(getInstance().getMenuManager(), player).open();
|
||||
return;
|
||||
|
||||
case "getall":
|
||||
if (!(sender instanceof Player)) {
|
||||
sendMessage(sender, Config.PLAYER_ONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Ability add : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
((Player) sender).getInventory().addItem(add.getItem());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sendUsage(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(CommandSender sender, String[] args) {
|
||||
if (args.length == 3) {
|
||||
String string = args[args.length - 1];
|
||||
return getInstance().getAbilityManager().getAbilities().keySet()
|
||||
.stream()
|
||||
.filter(s -> s.regionMatches(true, 0, string, 0, string.length()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
return super.tabComplete(sender, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package me.keano.azurite.modules.ability.event;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class AbilityUseEvent extends Event {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private Ability ability;
|
||||
private Player player;
|
||||
private long cooldown;
|
||||
|
||||
public AbilityUseEvent(Ability ability, Player player, long cooldown) {
|
||||
this.ability = ability;
|
||||
this.player = player;
|
||||
this.cooldown = cooldown;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package me.keano.azurite.modules.ability.extra;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public enum AbilityUseType {
|
||||
|
||||
INTERACT,
|
||||
HIT_PLAYER,
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package me.keano.azurite.modules.ability.extra;
|
||||
|
||||
import me.keano.azurite.modules.hooks.abilities.AbilitiesHook;
|
||||
import me.keano.azurite.modules.timers.TimerManager;
|
||||
import me.keano.azurite.modules.timers.type.PlayerTimer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class GlobalCooldown extends PlayerTimer {
|
||||
|
||||
private final AbilitiesHook abilitiesHook;
|
||||
|
||||
public GlobalCooldown(TimerManager manager) {
|
||||
super(
|
||||
manager,
|
||||
false,
|
||||
"PartnerItem",
|
||||
"",
|
||||
manager.getAbilitiesConfig().getInt("GLOBAL_ABILITY.COOLDOWN")
|
||||
);
|
||||
this.abilitiesHook = manager.getInstance().getAbilitiesHook();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTimer(Player player) {
|
||||
return super.hasTimer(player) || getInstance().getAbilitiesHook().hasGlobalCooldown(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemainingString(Player player) {
|
||||
if (abilitiesHook.hasGlobalCooldown(player)) {
|
||||
return abilitiesHook.getRemainingGlobal(player);
|
||||
}
|
||||
|
||||
return super.getRemainingString(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemainingStringBoard(Player player) {
|
||||
if (abilitiesHook.hasGlobalCooldown(player)) {
|
||||
return abilitiesHook.getRemainingGlobal(player);
|
||||
}
|
||||
|
||||
return super.getRemainingStringBoard(player);
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package me.keano.azurite.modules.ability.listener;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.CooldownBarTask;
|
||||
import me.keano.azurite.modules.ability.type.AntiTrapBeaconAbility;
|
||||
import me.keano.azurite.modules.ability.type.PocketBardAbility;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityListener extends Module<AbilityManager> {
|
||||
|
||||
public AbilityListener(AbilityManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
ItemStack hand = getManager().getItemInHand(damager);
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.hasAbilityInHand(damager)) continue;
|
||||
if (ability.getUseType() != AbilityUseType.HIT_PLAYER) continue;
|
||||
ability.onHit(damager, damaged);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlace(BlockPlaceEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
ItemStack hand = getManager().getItemInHand(player);
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.hasAbilityInHand(player)) continue;
|
||||
if (ability instanceof AntiTrapBeaconAbility) continue;
|
||||
e.setCancelled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onSwitch(PlayerItemHeldEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
ItemStack hand = player.getInventory().getItem(e.getNewSlot());
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.isSimilar(hand)) continue;
|
||||
if (!ability.getAbilityCooldown().hasTimer(player)) continue;
|
||||
new CooldownBarTask(player, ability);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCooldown(PlayerInteractEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
ItemStack hand = player.getItemInHand();
|
||||
|
||||
if (hand == null || !hand.hasItemMeta()) return;
|
||||
if (!hand.getItemMeta().hasLore() || !hand.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
if (e.getAction().name().contains("RIGHT")) {
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
if (!ability.hasAbilityInHand(player)) continue;
|
||||
if (ability.getUseType() != AbilityUseType.INTERACT) continue;
|
||||
|
||||
e.setCancelled(true);
|
||||
ability.onClick(player);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (e.getAction() == Action.LEFT_CLICK_BLOCK) {
|
||||
// This is for cooldowns
|
||||
for (Ability ability : getManager().getAbilities().values()) {
|
||||
// Pocket bards have different items;
|
||||
if (ability instanceof PocketBardAbility) {
|
||||
PocketBardAbility pocketBard = (PocketBardAbility) ability;
|
||||
|
||||
if (pocketBard.getPocketBardInHand(player) != null && pocketBard.getAbilityCooldown().hasTimer(player)) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.COOLDOWN")
|
||||
.replace("%ability%", ability.getDisplayName())
|
||||
.replace("%time%", ability.getAbilityCooldown().getRemainingString(player))
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ability.hasAbilityInHand(player) && ability.getAbilityCooldown().hasTimer(player)) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.COOLDOWN")
|
||||
.replace("%ability%", ability.getDisplayName())
|
||||
.replace("%time%", ability.getAbilityCooldown().getRemainingString(player))
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package me.keano.azurite.modules.ability.menu;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.framework.menu.Menu;
|
||||
import me.keano.azurite.modules.framework.menu.MenuManager;
|
||||
import me.keano.azurite.modules.framework.menu.button.Button;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityListMenu extends Menu {
|
||||
|
||||
public AbilityListMenu(MenuManager manager, Player player) {
|
||||
super(
|
||||
manager,
|
||||
player,
|
||||
manager.getAbilitiesConfig().getString("GLOBAL_ABILITY.ABILITY_MENU_TITLE"),
|
||||
54,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Button> getButtons(Player player) {
|
||||
Map<Integer, Button> buttons = new HashMap<>();
|
||||
int slot = 1;
|
||||
|
||||
for (Ability ability : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
if (!ability.isEnabled()) continue;
|
||||
|
||||
buttons.put(slot, new Button() {
|
||||
@Override
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
if (!(e.getWhoClicked() instanceof Player)) return;
|
||||
|
||||
Player clicked = (Player) e.getWhoClicked();
|
||||
|
||||
if (clicked.hasPermission("azurite.abilitymenu.click")) {
|
||||
clicked.getInventory().addItem(ability.getItem().clone());
|
||||
}
|
||||
|
||||
e.setCancelled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack() {
|
||||
return ability.getItem();
|
||||
}
|
||||
});
|
||||
slot++;
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package me.keano.azurite.modules.ability.menu;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.framework.menu.Menu;
|
||||
import me.keano.azurite.modules.framework.menu.MenuManager;
|
||||
import me.keano.azurite.modules.framework.menu.button.Button;
|
||||
import me.keano.azurite.utils.ItemBuilder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AbilityToggleMenu extends Menu {
|
||||
|
||||
public AbilityToggleMenu(MenuManager manager, Player player) {
|
||||
super(
|
||||
manager,
|
||||
player,
|
||||
"Ability Toggles",
|
||||
54,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Button> getButtons(Player player) {
|
||||
Map<Integer, Button> buttons = new HashMap<>();
|
||||
|
||||
int slot = 1;
|
||||
|
||||
for (Ability ability : getInstance().getAbilityManager().getAbilities().values()) {
|
||||
buttons.put(slot, new Button() {
|
||||
@Override
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
e.setCancelled(true);
|
||||
ability.setEnabled(!ability.isEnabled());
|
||||
getAbilitiesConfig().set(ability.getNameConfig() + ".ENABLED", ability.isEnabled());
|
||||
getAbilitiesConfig().save();
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack() {
|
||||
ItemBuilder builder = new ItemBuilder(ability.getItem().clone());
|
||||
builder.setLore("&eEnabled: " + (ability.isEnabled() ? "&atrue" : "&cfalse"));
|
||||
return builder.toItemStack();
|
||||
}
|
||||
});
|
||||
slot++;
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package me.keano.azurite.modules.ability.task;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.users.User;
|
||||
import me.keano.azurite.modules.users.settings.ActionBar;
|
||||
import me.keano.azurite.modules.versions.Version;
|
||||
import me.keano.azurite.utils.CC;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class CooldownBarTask extends BukkitRunnable {
|
||||
|
||||
private final Player player;
|
||||
private final Ability ability;
|
||||
|
||||
public CooldownBarTask(Player player, Ability ability) {
|
||||
this.player = player;
|
||||
this.ability = ability;
|
||||
this.runTaskTimerAsynchronously(ability.getInstance(), 0L, 2L);
|
||||
}
|
||||
|
||||
private void destroy() {
|
||||
this.cancel();
|
||||
User user = ability.getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
if (user.getActionBar() == ActionBar.ABILITY) user.setActionBar(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (ability.getInstance().getStaffManager().isStaffEnabled(player)) return;
|
||||
|
||||
if (!player.isOnline()) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack hand = ability.getManager().getItemInHand(player);
|
||||
Version version = ability.getInstance().getVersionManager().getVersion();
|
||||
|
||||
if (hand == null || !ability.isSimilar(hand)) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ability.getAbilityCooldown().hasTimer(player)) {
|
||||
destroy();
|
||||
version.sendActionBar(player, CC.t("&7"));
|
||||
return;
|
||||
}
|
||||
|
||||
User user = ability.getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
ActionBar actionBar = user.getActionBar();
|
||||
|
||||
if (actionBar == null) user.setActionBar(ActionBar.ABILITY);
|
||||
|
||||
if (actionBar == ActionBar.ABILITY) {
|
||||
version.sendActionBar(player, Config.ABILITY_ACTION_BAR_STRING
|
||||
.replace("%abilityname%", ability.getDisplayName())
|
||||
.replace("%remaining%", ability.getAbilityCooldown().getRemainingStringBoard(player))
|
||||
.replace("%actionbar%", Utils.getProgressBar(
|
||||
ability.getAbilityCooldown().getRemaining(player),
|
||||
ability.getAbilityCooldown().getSeconds() * 1000L,
|
||||
Config.ABILITY_ACTION_BAR_BARS,
|
||||
Config.ABILITY_ACTION_BAR_SYMBOL,
|
||||
Config.ABILITY_ACTION_BAR_YES_COLOR,
|
||||
Config.ABILITY_ACTION_BAR_NO_COLOR
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package me.keano.azurite.modules.ability.task;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TeleportTask extends BukkitRunnable {
|
||||
|
||||
private final Runnable finish;
|
||||
private final Consumer<Integer> increment;
|
||||
private final int max;
|
||||
private int i;
|
||||
|
||||
public TeleportTask(Ability ability, Runnable finish, Consumer<Integer> increment, int max) {
|
||||
this.finish = finish;
|
||||
this.increment = increment;
|
||||
this.max = max;
|
||||
this.i = 0;
|
||||
this.runTaskTimer(ability.getInstance(), 0L, 20L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (i == max) {
|
||||
finish.run();
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
increment.accept(i);
|
||||
i++;
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.extra.Cooldown;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class AntiBuildAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Integer> hits;
|
||||
private final List<Material> deniedInteract;
|
||||
private final List<PotionEffect> effects;
|
||||
private final Cooldown antiBuild;
|
||||
|
||||
private final int maxHits;
|
||||
private final int antiBuildTime;
|
||||
|
||||
public AntiBuildAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Anti Build"
|
||||
);
|
||||
this.hits = new HashMap<>();
|
||||
this.deniedInteract = new ArrayList<>();
|
||||
this.effects = new ArrayList<>();
|
||||
this.antiBuild = new Cooldown(manager);
|
||||
|
||||
this.maxHits = getAbilitiesConfig().getInt(nameConfig + ".HITS_REQUIRED");
|
||||
this.antiBuildTime = getAbilitiesConfig().getInt(nameConfig + ".ANTI_BUILD_TIME");
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList(nameConfig + ".DISABLED_INTERACT")) {
|
||||
deniedInteract.add(ItemUtils.getMat(s));
|
||||
}
|
||||
|
||||
for (String s : getAbilitiesConfig().getStringList(nameConfig + ".EFFECTS_DAMAGER")) {
|
||||
effects.add(Serializer.getEffect(s));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
UUID damagerUUID = damager.getUniqueId();
|
||||
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
if (!hits.containsKey(damagerUUID)) hits.put(damagerUUID, 0);
|
||||
|
||||
int current = hits.get(damagerUUID) + 1;
|
||||
hits.put(damagerUUID, current);
|
||||
|
||||
if (current == maxHits) {
|
||||
hits.remove(damager.getUniqueId());
|
||||
antiBuild.applyCooldown(damaged, antiBuildTime);
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(damager, effect); // So it restores properly
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_BUILD.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
.replace("%seconds%", String.valueOf(antiBuildTime))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_BUILD.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(antiBuildTime))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBuild(BlockBreakEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
// Disable block breaking
|
||||
if (antiBuild.hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_BUILD.DENIED_BUILD")
|
||||
.replace("%seconds%", antiBuild.getRemaining(player))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBreak(BlockPlaceEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
// Disable block placing
|
||||
if (antiBuild.hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_BUILD.DENIED_BUILD")
|
||||
.replace("%seconds%", antiBuild.getRemaining(player))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getClickedBlock();
|
||||
|
||||
if (block == null) return;
|
||||
if (!antiBuild.hasCooldown(player)) return;
|
||||
|
||||
// Disable pressure plate interaction
|
||||
if (e.getAction() == Action.PHYSICAL) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable opening chests, etc...
|
||||
if (e.getAction() == Action.RIGHT_CLICK_BLOCK && deniedInteract.contains(block.getType())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_BUILD.DENIED_BUILD")
|
||||
.replace("%seconds%", antiBuild.getRemaining(player))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
hits.remove(player.getUniqueId());
|
||||
antiBuild.removeCooldown(player);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
hits.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiPearlAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Integer> hits;
|
||||
private final int maxHits;
|
||||
private final int seconds;
|
||||
|
||||
public AntiPearlAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Anti Pearl"
|
||||
);
|
||||
this.hits = new HashMap<>();
|
||||
this.maxHits = getAbilitiesConfig().getInt("ANTI_PEARL.HITS_REQUIRED");
|
||||
this.seconds = getAbilitiesConfig().getInt("ANTI_PEARL.ENDERPEARL_SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
UUID damagerUUID = damager.getUniqueId();
|
||||
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
if (!hits.containsKey(damagerUUID)) hits.put(damagerUUID, 0);
|
||||
|
||||
int current = hits.get(damagerUUID) + 1;
|
||||
hits.put(damagerUUID, current);
|
||||
|
||||
if (current == maxHits) {
|
||||
hits.remove(damagerUUID);
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
getInstance().getTimerManager().getEnderpearlTimer().applyTimer(damaged, seconds * 1000L);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_PEARL.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_PEARL.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.teams.Team;
|
||||
import me.keano.azurite.modules.teams.type.PlayerTeam;
|
||||
import me.keano.azurite.modules.teams.type.WildernessTeam;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiTrapBeaconAbility extends Ability {
|
||||
|
||||
private final List<Location> denied;
|
||||
private final List<Material> deniedInteract;
|
||||
private final Map<Location, BeaconData> beacons;
|
||||
|
||||
private final boolean denyPlace;
|
||||
private final boolean denyBreak;
|
||||
private final boolean denyInteract;
|
||||
|
||||
private final int radius;
|
||||
private final int despawn;
|
||||
private final int hitpoints;
|
||||
|
||||
public AntiTrapBeaconAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Anti Trap Beacon"
|
||||
);
|
||||
this.denied = new ArrayList<>(); // we need duplicates otherwise if 2 beacons placed near it will bug out.
|
||||
this.beacons = new HashMap<>();
|
||||
this.deniedInteract = getAbilitiesConfig().getStringList("ANTI_TRAP_BEACON.DENIED_INTERACT").stream().map(ItemUtils::getMat).collect(Collectors.toList());
|
||||
|
||||
this.denyPlace = getAbilitiesConfig().getBoolean("ANTI_TRAP_BEACON.DENY_PLACE");
|
||||
this.denyBreak = getAbilitiesConfig().getBoolean("ANTI_TRAP_BEACON.DENY_BREAK");
|
||||
this.denyInteract = getAbilitiesConfig().getBoolean("ANTI_TRAP_BEACON.DENY_INTERACT");
|
||||
|
||||
this.radius = getAbilitiesConfig().getInt("ANTI_TRAP_BEACON.RADIUS");
|
||||
this.despawn = getAbilitiesConfig().getInt("ANTI_TRAP_BEACON.DESPAWN");
|
||||
this.hitpoints = getAbilitiesConfig().getInt("ANTI_TRAP_BEACON.HITPOINTS");
|
||||
}
|
||||
|
||||
public void handlePlace(BlockPlaceEvent e, Team atPlace) {
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getBlock();
|
||||
Material replaced = e.getBlockReplacedState().getType();
|
||||
|
||||
if (!(atPlace instanceof PlayerTeam) && !(atPlace instanceof WildernessTeam)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_PLACE"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (replaced.isBlock() && replaced != Material.AIR) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.BLOCK_EMPTY"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!block.getRelative(BlockFace.DOWN).getType().isSolid()) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.BLOCK_BELOW"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerTeam pt = getInstance().getTeamManager().getByPlayer(player.getUniqueId());
|
||||
List<Location> cloned = new ArrayList<>();
|
||||
int oldX = block.getX();
|
||||
int oldY = block.getY();
|
||||
int oldZ = block.getZ();
|
||||
|
||||
applyCooldown(player);
|
||||
takeItem(player);
|
||||
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
Location location = new Location(player.getWorld(), oldX + x, oldY + y, oldZ + z);
|
||||
denied.add(location);
|
||||
cloned.add(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BeaconData data = new BeaconData(player.getUniqueId(), block.getLocation(), cloned, hitpoints);
|
||||
data.setRemoveTask(new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
destroyBeacon(data);
|
||||
data.setRemoveTask(null);
|
||||
}
|
||||
}.runTaskLater(getInstance(), despawn * 20L));
|
||||
|
||||
beacons.put(block.getLocation(), data);
|
||||
|
||||
if (pt != null) {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_BEACON.TEAM_MESSAGE")) {
|
||||
pt.broadcast(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%loc%", Utils.formatLocation(block.getLocation()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (atPlace instanceof PlayerTeam) {
|
||||
PlayerTeam enemyTeam = (PlayerTeam) atPlace;
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_BEACON.ENEMY_MESSAGE")) {
|
||||
enemyTeam.broadcast(s);
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_BEACON.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlace(BlockPlaceEvent e) {
|
||||
if (!denyPlace) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getBlock();
|
||||
|
||||
if (denied.contains(block.getLocation()) && !beacons.containsKey(block.getLocation())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_USE"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBreak(BlockBreakEvent e) {
|
||||
if (!denyBreak) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getBlock();
|
||||
|
||||
if (denied.contains(block.getLocation())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_USE"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBreakBeacon(BlockBreakEvent e) {
|
||||
if (beacons.containsKey(e.getBlock().getLocation())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("BLOCK")) return;
|
||||
if (!e.hasBlock()) return;
|
||||
if (!denyInteract) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Block block = e.getClickedBlock();
|
||||
BeaconData beacon = beacons.get(block.getLocation());
|
||||
|
||||
if (beacon != null) {
|
||||
e.setCancelled(true);
|
||||
beacon.setHitpoints(beacon.getHitpoints() - 1);
|
||||
|
||||
if (beacon.getHitpoints() <= 0) {
|
||||
destroyBeacon(beacon);
|
||||
|
||||
if (beacon.getRemoveTask() != null) {
|
||||
beacon.getRemoveTask().cancel();
|
||||
beacon.setRemoveTask(null);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (denied.contains(block.getLocation()) && deniedInteract.contains(block.getType())) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.CANNOT_USE"));
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyBeacon(BeaconData data) {
|
||||
Player player = Bukkit.getPlayer(data.getPlayer());
|
||||
Block block = data.getLocation().getBlock();
|
||||
|
||||
if (block.getType() == item.getType()) {
|
||||
block.setType(Material.AIR);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_BEACON.BEACON_DESTROYED"));
|
||||
}
|
||||
|
||||
for (Location location : data.getDenied()) {
|
||||
denied.remove(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private static class BeaconData {
|
||||
|
||||
private UUID player;
|
||||
private Location location;
|
||||
private List<Location> denied;
|
||||
private BukkitTask removeTask;
|
||||
private int hitpoints;
|
||||
|
||||
public BeaconData(UUID player, Location location, List<Location> denied, int hitpoints) {
|
||||
this.player = player;
|
||||
this.location = location;
|
||||
this.denied = denied;
|
||||
this.removeTask = null;
|
||||
this.hitpoints = hitpoints;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiTrapHaloAbility extends Ability {
|
||||
|
||||
private final Set<UUID> halo;
|
||||
private final List<Material> denied;
|
||||
private final int seconds;
|
||||
private final int radius;
|
||||
private final boolean denyPlace;
|
||||
private final boolean denyBreak;
|
||||
private final boolean denyInteract;
|
||||
|
||||
public AntiTrapHaloAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"AntiTrap Halo"
|
||||
);
|
||||
this.halo = new HashSet<>();
|
||||
this.denied = getAbilitiesConfig().getStringList("ANTITRAP_HALO.DENIED_INTERACT").stream().map(ItemUtils::getMat).collect(Collectors.toList());
|
||||
this.seconds = getAbilitiesConfig().getInt("ANTITRAP_HALO.SECONDS_ANTI_BUILD");
|
||||
this.radius = getAbilitiesConfig().getInt("ANTITRAP_HALO.RADIUS");
|
||||
this.denyPlace = getAbilitiesConfig().getBoolean("ANTITRAP_HALO.DENY_PLACE");
|
||||
this.denyBreak = getAbilitiesConfig().getBoolean("ANTITRAP_HALO.DENY_BREAK");
|
||||
this.denyInteract = getAbilitiesConfig().getBoolean("ANTITRAP_HALO.DENY_INTERACT");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
halo.add(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_HALO.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
Tasks.executeLater(getManager(), seconds * 20L, () -> {
|
||||
halo.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_HALO.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlace(BlockPlaceEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (denyPlace && checkNear(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_HALO.DENIED"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBreak(BlockBreakEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (denyBreak && checkNear(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_HALO.DENIED"));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("BLOCK")) return;
|
||||
if (e.getClickedBlock() == null) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (denyInteract && denied.contains(e.getClickedBlock().getType()) && checkNear(player)) {
|
||||
e.setCancelled(true);
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_HALO.DENIED"));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkNear(Player player) {
|
||||
for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player near = (Player) entity;
|
||||
|
||||
if (halo.contains(near.getUniqueId()) && !getInstance().getTeamManager().canHit(player, near, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.extra.Pair;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AntiTrapStarAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Pair<UUID, Long>> lastDamage;
|
||||
private final int hitsValid;
|
||||
private final int seconds;
|
||||
|
||||
public AntiTrapStarAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Anti Trap Star"
|
||||
);
|
||||
this.lastDamage = new HashMap<>();
|
||||
this.hitsValid = getAbilitiesConfig().getInt("ANTI_TRAP_STAR.HITS_VALID");
|
||||
this.seconds = getAbilitiesConfig().getInt("ANTI_TRAP_STAR.SECONDS");
|
||||
getManager().getTasks().add(Bukkit.getScheduler().runTaskTimer(getInstance(), this::cleanDamageStore, 0, (20 * 60) * 5L));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
Player damager = getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.ANTI_TRAP_STAR_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_STAR_ABILITY.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_STAR_ABILITY.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ANTI_TRAP_STAR_ABILITY.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamageStore(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamagerProjectileOnly(e.getDamager()); // only projectiles for focus mode
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
lastDamage.put(damaged.getUniqueId(), new Pair<>(damager.getUniqueId(), System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
private void cleanDamageStore() {
|
||||
Iterator<Map.Entry<UUID, Pair<UUID, Long>>> iterator = lastDamage.entrySet().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<UUID, Long> pair = iterator.next().getValue();
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= (60 * 1000L); // 60s
|
||||
if (!valid) iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public Player getDamager(Player player, int secondsValid) {
|
||||
Pair<UUID, Long> pair = lastDamage.get(player.getUniqueId());
|
||||
|
||||
// This will get the last damage depending on the seconds it is valid till.
|
||||
if (pair != null) {
|
||||
Player damager = Bukkit.getPlayer(pair.getKey());
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= secondsValid * 1000L;
|
||||
|
||||
// Damager can be null if they logged out.
|
||||
if (damager != null && valid) {
|
||||
return damager;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class BelchBombAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> effects;
|
||||
private final int radius;
|
||||
|
||||
public BelchBombAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Belch Bomb"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("BELCH_BOMB.EFFECTS")
|
||||
.stream()
|
||||
.map(Serializer::getEffect)
|
||||
.collect(Collectors.toList());
|
||||
this.radius = getAbilitiesConfig().getInt("BELCH_BOMB.RADIUS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
int enemies = 0;
|
||||
|
||||
for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
Player target = (Player) entity;
|
||||
if (!getInstance().getTeamManager().canHit(player, target, false)) continue;
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(target, effect);
|
||||
}
|
||||
enemies++;
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.BELCH_BOMB.USED")) {
|
||||
player.sendMessage(s
|
||||
.replace("%enemies%", String.valueOf(enemies))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class BerserkAbility extends Ability {
|
||||
|
||||
private final Set<UUID> berserkers;
|
||||
private final Set<ItemStack> deniedPotions;
|
||||
private final Set<PotionEffect> effects;
|
||||
private final int berserkSeconds;
|
||||
|
||||
public BerserkAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Berserk"
|
||||
);
|
||||
this.berserkers = new HashSet<>();
|
||||
this.deniedPotions = new HashSet<>();
|
||||
this.effects = getAbilitiesConfig().getStringList("BERSERK.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toSet());
|
||||
this.berserkSeconds = getAbilitiesConfig().getInt("BERSERK.BERSERK_TIME");
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList("BERSERK.DENY_POTION")) {
|
||||
String[] split = s.split(", ");
|
||||
deniedPotions.add(ItemUtils.tryGetPotion(getManager(), ItemUtils.getMat(split[0]), Integer.parseInt(split[1])));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
berserkers.add(player.getUniqueId());
|
||||
Tasks.executeLater(getManager(), 20L * berserkSeconds, () -> berserkers.remove(player.getUniqueId()));
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.BERSERK.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onThrow(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
if (!getAbilitiesConfig().getBoolean("BERSERK.DENY_POT")) return;
|
||||
if (e.getItem() == null) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
ItemStack item = e.getItem();
|
||||
|
||||
if (!berserkers.contains(player.getUniqueId())) return;
|
||||
|
||||
for (ItemStack deniedPotion : deniedPotions) {
|
||||
if (deniedPotion.isSimilar(item)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.BERSERK.DENY_POT"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class CloseCallAbility extends Ability {
|
||||
|
||||
private final Set<PotionEffect> effects;
|
||||
private final String usageMessage;
|
||||
private final double healthRequired;
|
||||
|
||||
public CloseCallAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Close Call"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("CLOSE_CALL.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toSet());
|
||||
this.usageMessage = "%%__USER__%%";
|
||||
this.healthRequired = getAbilitiesConfig().getDouble("CLOSE_CALL.HEALTH_REQUIRED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
if ((player.getHealth() / 2.0) <= healthRequired) {
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CLOSE_CALL.USED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CLOSE_CALL.USED_UNSUCCESSFULLY")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
src/java/me/keano/azurite/modules/ability/type/ComboAbility.java
Normal file
101
src/java/me/keano/azurite/modules/ability/type/ComboAbility.java
Normal 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))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class CraftingChaosAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Integer> hits;
|
||||
private final Map<UUID, UUID> craftingChaos;
|
||||
private final int seconds;
|
||||
private final int maxHits;
|
||||
private final int chance;
|
||||
|
||||
public CraftingChaosAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Crafting Chaos"
|
||||
);
|
||||
this.hits = new HashMap<>();
|
||||
this.craftingChaos = new HashMap<>();
|
||||
this.seconds = getAbilitiesConfig().getInt("CRAFTING_CHAOS.SECONDS");
|
||||
this.maxHits = getAbilitiesConfig().getInt("CRAFTING_CHAOS.HITS_REQUIRED");
|
||||
this.chance = getAbilitiesConfig().getInt("CRAFTING_CHAOS.CHANCE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
UUID damagerUUID = damager.getUniqueId();
|
||||
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
if (!hits.containsKey(damagerUUID)) hits.put(damagerUUID, 0);
|
||||
|
||||
int current = hits.get(damagerUUID) + 1;
|
||||
hits.put(damagerUUID, current);
|
||||
|
||||
if (current == maxHits) {
|
||||
hits.remove(damagerUUID);
|
||||
craftingChaos.put(damagerUUID, damaged.getUniqueId());
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
craftingChaos.remove(damagerUUID);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.EXPIRED")) {
|
||||
damager.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = (Player) e.getDamager();
|
||||
|
||||
if (!craftingChaos.containsKey(damager.getUniqueId())) return;
|
||||
if (!craftingChaos.get(damager.getUniqueId()).equals(damaged.getUniqueId())) return;
|
||||
|
||||
if (ThreadLocalRandom.current().nextInt(100 + 1) <= chance) {
|
||||
damaged.openWorkbench(null, true);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.CRAFTING_CHAOS.MADE_OPEN"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
hits.remove(player.getUniqueId());
|
||||
craftingChaos.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.fastparticles.ParticleType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class ExplosiveEggAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> ballsThrown;
|
||||
private final ParticleType particleType;
|
||||
private final double multiplier;
|
||||
private final double yMultiplier;
|
||||
private final int radius;
|
||||
|
||||
public ExplosiveEggAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Explosive Egg"
|
||||
);
|
||||
this.ballsThrown = new HashMap<>();
|
||||
this.particleType = ParticleType.of(getAbilitiesConfig().getString("EXPLOSIVE_EGG.EFFECT"));
|
||||
this.multiplier = getAbilitiesConfig().getDouble("EXPLOSIVE_EGG.MULTIPLIER");
|
||||
this.yMultiplier = getAbilitiesConfig().getDouble("EXPLOSIVE_EGG.Y_MULTIPLIER");
|
||||
this.radius = getAbilitiesConfig().getInt("EXPLOSIVE_EGG.RADIUS");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory(); // Refund item
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onThrow(ProjectileLaunchEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
Player player = Utils.getDamager(projectile);
|
||||
|
||||
if (player == null) return;
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
ballsThrown.put(projectile.getUniqueId(), player.getUniqueId());
|
||||
applyCooldown(player);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.EXPLOSIVE_EGG.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLand(ProjectileHitEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
UUID uuid = ballsThrown.remove(projectile.getUniqueId());
|
||||
|
||||
if (uuid != null) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) return;
|
||||
|
||||
particleType.spawn(player.getWorld(), projectile.getLocation(), 1);
|
||||
|
||||
for (Entity entity : projectile.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player other = (Player) entity;
|
||||
|
||||
if (getInstance().getTeamManager().canHit(player, other, false)) {
|
||||
pullEntityToLocation(other, player.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pullEntityToLocation(Entity entity, Location loc) {
|
||||
Vector explosion = loc.toVector().subtract(entity.getLocation().toVector());
|
||||
explosion.multiply(multiplier);
|
||||
explosion.setY(explosion.getY() + yMultiplier);
|
||||
entity.setVelocity(explosion);
|
||||
}
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.extra.Pair;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class FocusModeAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> focusMode;
|
||||
private final Map<UUID, Pair<UUID, Long>> lastDamage;
|
||||
private final double multiplier;
|
||||
private final int seconds;
|
||||
private final int hitsValid;
|
||||
|
||||
public FocusModeAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Focus Mode"
|
||||
);
|
||||
this.focusMode = new HashMap<>();
|
||||
this.lastDamage = new HashMap<>();
|
||||
this.multiplier = getAbilitiesConfig().getDouble("FOCUS_MODE.DAMAGE_MULTIPLIER");
|
||||
this.seconds = getAbilitiesConfig().getInt("FOCUS_MODE.SECONDS");
|
||||
this.hitsValid = getAbilitiesConfig().getInt("FOCUS_MODE.HITS_VALID");
|
||||
getManager().getTasks().add(Bukkit.getScheduler().runTaskTimer(getInstance(), this::cleanDamageStore, 0L, (20 * 60) * 5L));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
Player damager = getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.FOCUS_MODE.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
focusMode.put(player.getUniqueId(), damager.getUniqueId());
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
focusMode.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.FOCUS_MODE.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.FOCUS_MODE.USED"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.FOCUS_MODE.BEEN_HIT"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
);
|
||||
}
|
||||
|
||||
// Focus Mode = LOW, Archer Class = NORMAL, Strength = HIGH
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = (Player) e.getDamager();
|
||||
|
||||
if (!focusMode.containsKey(damager.getUniqueId())) return;
|
||||
if (!focusMode.get(damager.getUniqueId()).equals(damaged.getUniqueId())) return;
|
||||
|
||||
e.setDamage(e.getDamage() * multiplier);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
focusMode.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamageStore(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
lastDamage.put(damaged.getUniqueId(), new Pair<>(damager.getUniqueId(), System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
private void cleanDamageStore() {
|
||||
Iterator<Map.Entry<UUID, Pair<UUID, Long>>> iterator = lastDamage.entrySet().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Pair<UUID, Long> pair = iterator.next().getValue();
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= (60 * 1000L); // 60s
|
||||
if (!valid) iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public Player getDamager(Player player, int secondsValid) {
|
||||
Pair<UUID, Long> pair = lastDamage.get(player.getUniqueId());
|
||||
|
||||
// This will get the last damage depending on the seconds it is valid till.
|
||||
if (pair != null) {
|
||||
Player damager = Bukkit.getPlayer(pair.getKey());
|
||||
boolean valid = (System.currentTimeMillis() - pair.getValue()) <= secondsValid * 1000L;
|
||||
|
||||
// Damager can be null if they logged out.
|
||||
if (damager != null && valid) {
|
||||
return damager;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.utils.ReflectionUtils;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.FishHook;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerFishEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class GrappleAbility extends Ability {
|
||||
|
||||
private static final Field HOOK_ENTITY = ReflectionUtils.accessField(org.bukkit.event.player.PlayerFishEvent.class, "hookEntity");
|
||||
|
||||
private final double multiplier;
|
||||
private final double yMultiplier;
|
||||
|
||||
public GrappleAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Grapple"
|
||||
);
|
||||
this.multiplier = getAbilitiesConfig().getDouble("GRAPPLE.MULTIPLIER");
|
||||
this.yMultiplier = getAbilitiesConfig().getDouble("GRAPPLE.Y_MULTIPLIER");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLaunch(PlayerInteractEvent e) {
|
||||
if (!(e.getAction().name().contains("RIGHT"))) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFish(PlayerFishEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
// State when the rod is in the air
|
||||
if (e.getState() == PlayerFishEvent.State.FISHING) return;
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
// FOR SOME FUCKING REASON "FISH" ENTITY DOESN'T FUCKING WORK ON 1.16+ FUCK
|
||||
try {
|
||||
|
||||
applyCooldown(player);
|
||||
takeItem(player);
|
||||
pullEntityToLocation(player, (Utils.isModernVer() ? (FishHook) HOOK_ENTITY.get(e) : e.getHook()));
|
||||
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void pullEntityToLocation(Entity entity, Entity loc) {
|
||||
if (loc.getLocation().subtract(0, 1, 0).getBlock().getType() == Material.AIR) return;
|
||||
Vector grapple = loc.getLocation().toVector().subtract(entity.getLocation().toVector());
|
||||
grapple.multiply(multiplier);
|
||||
grapple.setY(grapple.getY() + yMultiplier);
|
||||
entity.setVelocity(grapple);
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class InvisibilityAbility extends Ability {
|
||||
|
||||
private final Set<UUID> invisible;
|
||||
private final PotionEffect invisEffect;
|
||||
private final boolean removeInvis;
|
||||
|
||||
public InvisibilityAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Invisibility"
|
||||
);
|
||||
this.invisible = new HashSet<>();
|
||||
this.invisEffect = Serializer.getEffect(getAbilitiesConfig().getString("INVISIBILITY.INVIS_EFFECT"));
|
||||
this.removeInvis = getAbilitiesConfig().getBoolean("INVISIBILITY.TAKE_INVIS_ON_HIT");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
hideArmor(player);
|
||||
|
||||
if (!player.hasPotionEffect(PotionEffectType.INVISIBILITY)) {
|
||||
getInstance().getClassManager().addEffect(player, invisEffect);
|
||||
}
|
||||
|
||||
// Ticks later
|
||||
Tasks.executeLater(getManager(), 5L, () -> invisible.add(player.getUniqueId()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.INVISIBILITY.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
player.setFireTicks(0);
|
||||
getInstance().getVersionManager().getVersion().clearArrows(player);
|
||||
|
||||
Tasks.executeLater(getManager(), invisEffect.getDuration(), () -> {
|
||||
if (player.isOnline() && invisible.remove(player.getUniqueId())) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.INVISIBILITY.EXPIRED"));
|
||||
}
|
||||
|
||||
// Ticks later
|
||||
Tasks.executeLater(getManager(), 5L, () -> showArmor(player));
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
|
||||
for (UUID uuid : invisible) {
|
||||
Player toRemove = Bukkit.getPlayer(uuid);
|
||||
if (toRemove != null) hideArmor(player);
|
||||
}
|
||||
|
||||
getInstance().getVersionManager().getVersion().handleNettyListener(player);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
if (invisible.remove(damaged.getUniqueId())) {
|
||||
if (removeInvis) {
|
||||
damaged.removePotionEffect(PotionEffectType.INVISIBILITY);
|
||||
}
|
||||
|
||||
damaged.sendMessage(getLanguageConfig().getString("ABILITIES.INVISIBILITY.DAMAGED"));
|
||||
Tasks.executeLater(getManager(), 5L, () -> showArmor(damaged));
|
||||
}
|
||||
}
|
||||
|
||||
private void hideArmor(Player player) {
|
||||
getInstance().getVersionManager().getVersion().hideArmor(player);
|
||||
}
|
||||
|
||||
private void showArmor(Player player) {
|
||||
getInstance().getVersionManager().getVersion().showArmor(player);
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class LightningAbility extends Ability {
|
||||
|
||||
private final List<UUID> lightnings;
|
||||
private final int chance;
|
||||
private final int seconds;
|
||||
private final double damage;
|
||||
|
||||
public LightningAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Lightning"
|
||||
);
|
||||
this.lightnings = new ArrayList<>();
|
||||
this.chance = getAbilitiesConfig().getInt("LIGHTNING.CHANCE");
|
||||
this.seconds = getAbilitiesConfig().getInt("LIGHTNING.SECONDS");
|
||||
this.damage = getAbilitiesConfig().getDouble("LIGHTNING.DAMAGE") * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
lightnings.add(player.getUniqueId());
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
lightnings.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (lightnings.contains(damager.getUniqueId()) && ThreadLocalRandom.current().nextInt(100 + 1) <= chance) {
|
||||
damaged.getWorld().strikeLightningEffect(damaged.getLocation());
|
||||
damaged.setHealth(Math.max(damaged.getHealth() - damage, 0D));
|
||||
e.setDamage(0D); // We only do the lightning damage
|
||||
|
||||
// Fix double death bug
|
||||
if (damaged.isDead()) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.STRUCK_LIGHTNING"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LIGHTNING.STRUCK_BY_LIGHTNING"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
lightnings.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class LuckyModeAbility extends Ability {
|
||||
|
||||
private final Map<UUID, Double> luckyMode;
|
||||
private final DecimalFormat formatter;
|
||||
private final double minimum;
|
||||
private final double maximum;
|
||||
private final int seconds;
|
||||
|
||||
public LuckyModeAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Lucky Mode"
|
||||
);
|
||||
this.luckyMode = new HashMap<>();
|
||||
this.formatter = new DecimalFormat("##");
|
||||
this.minimum = getAbilitiesConfig().getDouble("LUCKY_MODE.MINIMUM_MULTIPLIER");
|
||||
this.maximum = getAbilitiesConfig().getDouble("LUCKY_MODE.MAXIMUM_MULTIPLIER");
|
||||
this.seconds = getAbilitiesConfig().getInt("LUCKY_MODE.SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
double multiplier = ThreadLocalRandom.current().nextDouble(minimum, maximum + 1);
|
||||
luckyMode.put(player.getUniqueId(), multiplier);
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> {
|
||||
luckyMode.remove(player.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LUCKY_MODE.EXPIRED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
});
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.LUCKY_MODE.USED"))
|
||||
player.sendMessage(s
|
||||
.replace("%amount%", formatter.format(multiplier))
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
|
||||
if (!luckyMode.containsKey(damager.getUniqueId())) return;
|
||||
|
||||
double percent = luckyMode.get(damager.getUniqueId());
|
||||
|
||||
// No change
|
||||
if (percent == 0) return;
|
||||
|
||||
// This will convert 35% to actual percent (1.35, 1.25, 0.90) etc..
|
||||
if (percent > 0) {
|
||||
e.setDamage(e.getDamage() * (percent / 100 + 1));
|
||||
|
||||
} else {
|
||||
e.setDamage(e.getDamage() * (1 / (Math.abs(percent) / 100 + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player player = e.getEntity();
|
||||
luckyMode.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class MagicRockAbility extends Ability {
|
||||
|
||||
private final Map<Integer, PotionEffect> effects;
|
||||
|
||||
public MagicRockAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.HIT_PLAYER,
|
||||
"Magic Rock"
|
||||
);
|
||||
this.effects = new HashMap<>();
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList("MAGIC_ROCK.EFFECTS_PER_BLOCK")) {
|
||||
String[] split = s.split(": ");
|
||||
effects.put(Integer.parseInt(split[0]), Serializer.getEffect(split[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHit(Player damager, Player damaged) {
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
|
||||
int height = getBaseHeight(damaged);
|
||||
PotionEffect effect = effects.get(height);
|
||||
|
||||
if (height == 0 || effect == null) {
|
||||
damager.sendMessage(getLanguageConfig().getString("ABILITIES.MAGIC_ROCK.NOT_FOUND"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
getInstance().getClassManager().addEffect(damager, effect);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.MAGIC_ROCK.USED")) {
|
||||
damager.sendMessage(s
|
||||
.replace("%height%", String.valueOf(height))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public int getBaseHeight(Player player) {
|
||||
Location location = player.getLocation().clone();
|
||||
|
||||
int height = 0;
|
||||
|
||||
for (int i = location.getBlockY(); i < location.getWorld().getMaxHeight(); i++) {
|
||||
Block block = location.getWorld().getBlockAt(location.getBlockX(), i, location.getBlockZ());
|
||||
|
||||
if (block.getType() != Material.AIR && block.getType().isBlock()) {
|
||||
height = i - location.getBlockY();
|
||||
}
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class MedKitAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> effects;
|
||||
|
||||
public MedKitAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Med Kit"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("MED_KIT.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.MED_KIT.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class NinjaAbility extends Ability {
|
||||
|
||||
private final int seconds;
|
||||
private final int hitsValid;
|
||||
|
||||
public NinjaAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Ninja Ability"
|
||||
);
|
||||
this.seconds = getAbilitiesConfig().getInt("NINJA_ABILITY.SECONDS");
|
||||
this.hitsValid = getAbilitiesConfig().getInt("NINJA_ABILITY.HITS_VALID");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
// I already coded a way to get last damager for focus mode, so just use that.
|
||||
Player damager = ((FocusModeAbility) getManager().getAbility("FocusMode")).getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.NINJA_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.NINJA_ABILITY.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.NINJA_ABILITY.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.NINJA_ABILITY.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%target%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.framework.menu.Menu;
|
||||
import me.keano.azurite.modules.framework.menu.MenuManager;
|
||||
import me.keano.azurite.modules.framework.menu.button.Button;
|
||||
import me.keano.azurite.modules.pvpclass.PvPClassManager;
|
||||
import me.keano.azurite.modules.pvpclass.type.bard.BardEffect;
|
||||
import me.keano.azurite.utils.ItemBuilder;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class PocketBardAbility extends Ability {
|
||||
|
||||
private final Map<String, PocketBard> pocketBards;
|
||||
|
||||
public PocketBardAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"PocketBard"
|
||||
);
|
||||
this.pocketBards = new HashMap<>();
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String key : getAbilitiesConfig().getConfigurationSection("POCKETBARD.TYPES").getKeys(false)) {
|
||||
String path = "POCKETBARD.TYPES." + key + ".";
|
||||
ItemStack item = new ItemBuilder(ItemUtils.getMat(getAbilitiesConfig().getString(path + "MATERIAL")))
|
||||
.setName(getAbilitiesConfig().getString(path + "NAME"))
|
||||
.setLore(getAbilitiesConfig().getStringList(path + "LORE"))
|
||||
.data(getManager(), (short) getAbilitiesConfig().getInt(path + "DATA"))
|
||||
.toItemStack();
|
||||
|
||||
item.setAmount(getAbilitiesConfig().getInt(path + "AMOUNT"));
|
||||
pocketBards.put(key, new PocketBard(
|
||||
getInstance().getClassManager(),
|
||||
Serializer.getEffect(getAbilitiesConfig().getString(path + "EFFECT")),
|
||||
(getAbilitiesConfig().getBoolean(nameConfig + ".ADD_GLOW") ?
|
||||
getInstance().getVersionManager().getVersion().addGlow(item) :
|
||||
item))
|
||||
);
|
||||
}
|
||||
|
||||
// This will handle the menu items.
|
||||
for (String key : getAbilitiesConfig().getConfigurationSection("POCKETBARD.POCKETBARD_MENU.ITEMS").getKeys(false)) {
|
||||
String path = "POCKETBARD.POCKETBARD_MENU.ITEMS." + key + ".";
|
||||
PocketBard pocketBard = pocketBards.get(getAbilitiesConfig().getString(path + "POCKET_BARD"));
|
||||
ItemBuilder builder = new ItemBuilder(ItemUtils.getMat(getAbilitiesConfig().getString(path + "MATERIAL")))
|
||||
.setName(getAbilitiesConfig().getString(path + "NAME"))
|
||||
.setLore(getAbilitiesConfig().getStringList(path + "LORE"))
|
||||
.data(getManager(), (short) getAbilitiesConfig().getInt(path + "DATA"));
|
||||
|
||||
pocketBard.setMenuItem(builder.toItemStack());
|
||||
pocketBard.setSlot(getAbilitiesConfig().getInt(path + "SLOT"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
new PocketBardMenu(getInstance().getMenuManager(), this, player).open();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteractPocket(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
PocketBard pocketBard = getPocketBardInHand(player);
|
||||
|
||||
if (pocketBard != null) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
pocketBard.getEffect().applyEffect(player);
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public PocketBard getPocketBardInHand(Player player) {
|
||||
ItemStack hand = getManager().getItemInHand(player);
|
||||
|
||||
if (hand == null) return null;
|
||||
|
||||
for (PocketBard pocketBard : pocketBards.values()) {
|
||||
if (!pocketBard.getItem().isSimilar(hand)) continue;
|
||||
return pocketBard;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private static class PocketBard {
|
||||
|
||||
private BardEffect effect;
|
||||
private ItemStack item;
|
||||
private ItemStack menuItem;
|
||||
private int slot;
|
||||
|
||||
public PocketBard(PvPClassManager manager, PotionEffect effect, ItemStack item) {
|
||||
this.effect = new BardEffect(manager, true, effect);
|
||||
this.item = item;
|
||||
this.menuItem = null;
|
||||
this.slot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PocketBardMenu extends Menu {
|
||||
|
||||
private final PocketBardAbility ability;
|
||||
|
||||
public PocketBardMenu(MenuManager manager, PocketBardAbility ability, Player player) {
|
||||
super(
|
||||
manager,
|
||||
player,
|
||||
manager.getAbilitiesConfig().getString("POCKETBARD.POCKETBARD_MENU.TITLE"),
|
||||
manager.getAbilitiesConfig().getInt("POCKETBARD.POCKETBARD_MENU.SIZE"),
|
||||
false
|
||||
);
|
||||
this.ability = ability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, Button> getButtons(Player player) {
|
||||
Map<Integer, Button> buttons = new HashMap<>();
|
||||
|
||||
for (PocketBard pocketBard : ability.getPocketBards().values()) {
|
||||
buttons.put(pocketBard.getSlot(), new Button() {
|
||||
@Override
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
// Check first and then check after aswell.
|
||||
if (!ability.hasAbilityInHand(player)) {
|
||||
e.setCancelled(true);
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
e.setCancelled(true);
|
||||
getManager().takeItemInHand(player, 1);
|
||||
ItemUtils.giveItem(player, pocketBard.getItem(), player.getLocation());
|
||||
if (!ability.hasAbilityInHand(player)) player.closeInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack() {
|
||||
return pocketBard.getMenuItem();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.type.archer.ArcherClass;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class PortableArcherAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> usedPortableArcher; // player -> arrow
|
||||
|
||||
public PortableArcherAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Portable Archer"
|
||||
);
|
||||
this.usedPortableArcher = new HashMap<>();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onShoot(EntityShootBowEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player player = (Player) e.getEntity();
|
||||
ItemStack bow = e.getBow();
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
usedPortableArcher.put(player.getUniqueId(), e.getProjectile().getUniqueId());
|
||||
getManager().setData(bow, getManager().getData(bow) + 1);
|
||||
|
||||
if (getManager().getData(bow) == bow.getType().getMaxDurability()) {
|
||||
getManager().takeItemInHand(player, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDamage(PlayerItemDamageEvent e) {
|
||||
ItemStack damage = e.getItem();
|
||||
|
||||
if (!damage.hasItemMeta()) return;
|
||||
if (!damage.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
ItemMeta itemMeta = damage.getItemMeta();
|
||||
ItemMeta abilityMeta = item.getItemMeta();
|
||||
|
||||
if (itemMeta.getDisplayName().equals(abilityMeta.getDisplayName()) && itemMeta.getLore().equals(abilityMeta.getLore())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Arrow)) return;
|
||||
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
|
||||
UUID arrow = usedPortableArcher.remove(damager.getUniqueId());
|
||||
|
||||
if (arrow != null && e.getDamager().getUniqueId().equals(arrow)) {
|
||||
ArcherClass archerClass = getInstance().getClassManager().getArcherClass();
|
||||
if (archerClass != null) archerClass.archerTag(e);
|
||||
applyCooldown(damager);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,289 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.type.bard.BardEffect;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.extra.Cooldown;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class PortableBardAbility extends Ability {
|
||||
|
||||
private final Map<UUID, PortableBard> portableBards;
|
||||
private final Map<UUID, UUID> byEntity;
|
||||
private final List<PortableBardEffect> effects;
|
||||
|
||||
private final Cooldown regenCooldown;
|
||||
private final EntityType entityType;
|
||||
private final String name;
|
||||
private final int radius;
|
||||
private final int timeUpgrade;
|
||||
private final int health;
|
||||
private final int timeAlive;
|
||||
|
||||
public PortableBardAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Portable Bard"
|
||||
);
|
||||
this.portableBards = new HashMap<>();
|
||||
this.byEntity = new HashMap<>();
|
||||
this.effects = new ArrayList<>();
|
||||
|
||||
this.regenCooldown = new Cooldown(getManager());
|
||||
this.entityType = EntityType.valueOf(getAbilitiesConfig().getString("PORTABLE_BARD.ENTITY_TYPE"));
|
||||
this.name = getAbilitiesConfig().getString("PORTABLE_BARD.NAME");
|
||||
this.radius = getAbilitiesConfig().getInt("PORTABLE_BARD.RADIUS");
|
||||
this.timeUpgrade = getAbilitiesConfig().getInt("PORTABLE_BARD.UPGRADE_EVERY");
|
||||
this.health = getAbilitiesConfig().getInt("PORTABLE_BARD.HEALTH");
|
||||
this.timeAlive = getAbilitiesConfig().getInt("PORTABLE_BARD.TIME_ALIVE");
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String key : getAbilitiesConfig().getConfigurationSection("PORTABLE_BARD.EFFECTS").getKeys(false)) {
|
||||
String path = "PORTABLE_BARD.EFFECTS." + key + ".";
|
||||
effects.add(new PortableBardEffect(
|
||||
Serializer.getEffect(getAbilitiesConfig().getString(path + "EFFECT")),
|
||||
Serializer.getEffect(getAbilitiesConfig().getString(path + "EFFECT_UPGRADE")),
|
||||
ItemUtils.getMatItem(getAbilitiesConfig().getString(path + "MATERIAL"))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
for (PortableBard portableBard : portableBards.values()) {
|
||||
portableBard.getLivingEntity().remove();
|
||||
portableBard.getTickTask().cancel();
|
||||
}
|
||||
|
||||
byEntity.clear();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
if (!e.hasItem()) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
Location toSpawn = (e.hasBlock() ? e.getClickedBlock().getLocation().add(0.5, 1.0, 0.5) : player.getLocation());
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
e.setCancelled(true);
|
||||
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
if (getInstance().getTimerManager().getPvpTimer().hasTimer(player)) return;
|
||||
if (getInstance().getTimerManager().getInvincibilityTimer().hasTimer(player)) return;
|
||||
|
||||
PortableBard old = portableBards.remove(player.getUniqueId());
|
||||
|
||||
if (old != null) {
|
||||
byEntity.remove(old.getLivingEntity().getUniqueId());
|
||||
old.delete();
|
||||
}
|
||||
|
||||
PortableBard portableBard = new PortableBard(player, toSpawn, entityType);
|
||||
portableBards.put(player.getUniqueId(), portableBard);
|
||||
byEntity.put(portableBard.getLivingEntity().getUniqueId(), player.getUniqueId());
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof LivingEntity)) return;
|
||||
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
LivingEntity entity = (LivingEntity) e.getEntity();
|
||||
UUID playerBard = byEntity.get(entity.getUniqueId());
|
||||
|
||||
if (playerBard != null) {
|
||||
PortableBard portableBard = portableBards.get(playerBard);
|
||||
|
||||
if (portableBard != null) {
|
||||
if (damager.getUniqueId() == portableBard.getPlayer().getUniqueId() ||
|
||||
!getInstance().getTeamManager().canHit(damager, portableBard.getPlayer(), false)) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
e.setDamage(0D);
|
||||
portableBard.setHealth(portableBard.getHealth() - 1);
|
||||
portableBard.updateName();
|
||||
|
||||
if (portableBard.getHealth() <= 0) {
|
||||
portableBard.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDeath(EntityDeathEvent e) {
|
||||
if (byEntity.containsKey(e.getEntity().getUniqueId())) {
|
||||
e.getDrops().clear();
|
||||
e.setDroppedExp(0);
|
||||
}
|
||||
}
|
||||
|
||||
public class PortableBardTask extends BukkitRunnable {
|
||||
|
||||
private final PortableBard portableBard;
|
||||
private int i;
|
||||
|
||||
public PortableBardTask(PortableBard portableBard) {
|
||||
this.portableBard = portableBard;
|
||||
this.i = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (portableBard.getLivingEntity().isDead() || i == timeAlive) {
|
||||
portableBard.delete();
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = portableBard.getPlayer();
|
||||
PortableBardEffect random = effects.get(ThreadLocalRandom.current().nextInt(effects.size()));
|
||||
|
||||
for (PortableBardEffect effect : effects) {
|
||||
if (effect.getEffect() == null) continue;
|
||||
|
||||
if (effect.getEffect().getEffect().getType().equals(PotionEffectType.REGENERATION)) {
|
||||
if (regenCooldown.hasCooldown(player)) continue;
|
||||
regenCooldown.applyCooldownTicks(player, 3000);
|
||||
}
|
||||
|
||||
if (shouldEffectPlayer()) {
|
||||
getInstance().getClassManager().addEffect(player, effect.getEffect().getEffect());
|
||||
}
|
||||
|
||||
effect.getEffect().applyEffect(player);
|
||||
}
|
||||
|
||||
if (i % timeUpgrade == 0 && i != 0) {
|
||||
if (shouldEffectPlayer()) {
|
||||
getInstance().getClassManager().addEffect(player, random.getUpgrade().getEffect());
|
||||
}
|
||||
|
||||
random.getUpgrade().applyEffect(player);
|
||||
}
|
||||
|
||||
i++;
|
||||
portableBard.getLivingEntity().getEquipment().setItemInHand(random.getHand());
|
||||
portableBard.updateName();
|
||||
}
|
||||
|
||||
public boolean shouldEffectPlayer() {
|
||||
return portableBard.getLivingEntity().getLocation().distance(portableBard.getPlayer().getLocation()) <= radius;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public class PortableBardEffect {
|
||||
|
||||
private final BardEffect effect;
|
||||
private final BardEffect upgrade;
|
||||
private final ItemStack hand;
|
||||
|
||||
public PortableBardEffect(PotionEffect effect, PotionEffect upgrade, ItemStack hand) {
|
||||
this.effect = (effect != null ? new BardEffect(getInstance().getClassManager(), false, effect) : null);
|
||||
this.upgrade = (upgrade != null ? new BardEffect(getInstance().getClassManager(), false, upgrade) : null);
|
||||
this.hand = hand;
|
||||
if (effect != null && upgrade != null) load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
effect.setEffectSelf(false);
|
||||
upgrade.setEffectSelf(false);
|
||||
effect.setBardDistance(radius);
|
||||
upgrade.setBardDistance(radius);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PortableBard {
|
||||
|
||||
private Player player;
|
||||
private LivingEntity livingEntity;
|
||||
private BukkitTask tickTask;
|
||||
private int health;
|
||||
|
||||
public PortableBard(Player player, Location location, EntityType entityType) {
|
||||
if (!entityType.isAlive()) {
|
||||
throw new IllegalArgumentException("Portable bard has to be a living entity");
|
||||
}
|
||||
|
||||
this.player = player;
|
||||
this.livingEntity = (LivingEntity) location.getWorld().spawnEntity(location, entityType);
|
||||
this.tickTask = new PortableBardTask(this).runTaskTimer(getInstance(), 0, 20);
|
||||
this.health = PortableBardAbility.this.health;
|
||||
|
||||
// Equipment
|
||||
livingEntity.getEquipment().setHelmet(new ItemStack(ItemUtils.getMat("GOLD_HELMET")));
|
||||
livingEntity.getEquipment().setChestplate(new ItemStack(ItemUtils.getMat("GOLD_CHESTPLATE")));
|
||||
livingEntity.getEquipment().setLeggings(new ItemStack(ItemUtils.getMat("GOLD_LEGGINGS")));
|
||||
livingEntity.getEquipment().setBoots(new ItemStack(ItemUtils.getMat("GOLD_BOOTS")));
|
||||
|
||||
// Name
|
||||
livingEntity.setCustomNameVisible(true);
|
||||
this.updateName();
|
||||
|
||||
// So they can't move
|
||||
livingEntity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, Integer.MAX_VALUE, 100, false, false));
|
||||
livingEntity.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 100, false, false));
|
||||
|
||||
// Make sure Adult
|
||||
if (livingEntity instanceof Ageable) {
|
||||
Ageable ageable = (Ageable) livingEntity;
|
||||
ageable.setAdult();
|
||||
ageable.setBreed(false);
|
||||
ageable.setAgeLock(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateName() {
|
||||
livingEntity.setCustomName(name
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%health%", String.valueOf(health)));
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
portableBards.remove(player.getUniqueId());
|
||||
byEntity.remove(livingEntity.getUniqueId());
|
||||
livingEntity.remove();
|
||||
tickTask.cancel();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.cooldown.CustomCooldown;
|
||||
import me.keano.azurite.modules.pvpclass.type.rogue.RogueBackstabEvent;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class PortableRogueAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> backstabEffects;
|
||||
|
||||
public PortableRogueAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Portable Rogue"
|
||||
);
|
||||
this.backstabEffects = new ArrayList<>();
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
this.backstabEffects.addAll(getAbilitiesConfig().getStringList("PORTABLE_ROGUE.BACKSTAB_EFFECTS")
|
||||
.stream()
|
||||
.map(Serializer::getEffect)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (!hasAbilityInHand(damager)) return;
|
||||
if (cannotUse(damager)) return;
|
||||
if (hasCooldown(damager)) return;
|
||||
|
||||
// Used to calculate the direction to make sure they are behind the player.
|
||||
Vector damagerVector = damager.getLocation().getDirection().setY(0);
|
||||
Vector damagedVector = damaged.getLocation().getDirection().setY(0);
|
||||
CustomCooldown backstabCooldown = getInstance().getClassManager().getRogueClass().getBackstabCooldown();
|
||||
|
||||
double degree = damagerVector.angle(damagedVector);
|
||||
double backstabDamage = getAbilitiesConfig().getDouble("PORTABLE_ROGUE.BACKSTAB_DAMAGE") * 2.0;
|
||||
|
||||
if (Math.abs(degree) < 1.4) {
|
||||
if (backstabCooldown.hasCooldown(damager)) {
|
||||
damager.sendMessage(getLanguageConfig().getString("PVP_CLASSES.ROGUE_CLASS.BACKSTAB_COOLDOWN")
|
||||
.replace("%seconds%", backstabCooldown.getRemaining(damager))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
backstabCooldown.applyCooldown(damager, getAbilitiesConfig().getInt("PORTABLE_ROGUE.BACKSTAB_COOLDOWN"));
|
||||
getManager().playSound(damaged, getAbilitiesConfig().getString("PORTABLE_ROGUE.BACKSTAB_SOUND"), true);
|
||||
|
||||
takeItem(damager);
|
||||
applyCooldown(damager);
|
||||
|
||||
getInstance().getVersionManager().getVersion().playEffect(
|
||||
damaged.getLocation().add(0, 1, 0), // add 1
|
||||
Effect.STEP_SOUND.name(),
|
||||
ItemUtils.getMat(getAbilitiesConfig().getString("PORTABLE_ROGUE.BACKSTAB_EFFECT"))
|
||||
);
|
||||
|
||||
damaged.setLastDamageCause(new RogueBackstabEvent(damaged, damager, EntityDamageEvent.DamageCause.CUSTOM, backstabDamage));
|
||||
damaged.setHealth(Math.max(damaged.getHealth() - backstabDamage, 0));
|
||||
|
||||
e.setDamage(0D);
|
||||
|
||||
if (damaged.isDead()) {
|
||||
e.setCancelled(true); // we cancel the event so PlayerDeathEvent doesn't get called twice.
|
||||
}
|
||||
|
||||
// add the slowness and all that
|
||||
for (PotionEffect backstabEffect : backstabEffects) {
|
||||
damager.addPotionEffect(backstabEffect);
|
||||
}
|
||||
|
||||
} else {
|
||||
damager.sendMessage(getLanguageConfig().getString("PVP_CLASSES.ROGUE_CLASS.BACKSTAB_FAILED"));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.pvpclass.PvPClassManager;
|
||||
import me.keano.azurite.modules.teams.type.PlayerTeam;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class RageBallAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> ballsThrown;
|
||||
private final List<PotionEffect> friendlyEffects;
|
||||
private final List<PotionEffect> enemyEffects;
|
||||
private final String rageBallEffect;
|
||||
private final boolean wholeTeamCooldown;
|
||||
private final int radius;
|
||||
|
||||
public RageBallAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Rage Ball"
|
||||
);
|
||||
this.ballsThrown = new HashMap<>();
|
||||
this.friendlyEffects = new ArrayList<>();
|
||||
this.enemyEffects = new ArrayList<>();
|
||||
this.rageBallEffect = getAbilitiesConfig().getString("RAGE_BALL.EFFECT");
|
||||
this.wholeTeamCooldown = getAbilitiesConfig().getBoolean("RAGE_BALL.COOLDOWN_WHOLE_TEAM");
|
||||
this.radius = getAbilitiesConfig().getInt("RAGE_BALL.RADIUS");
|
||||
this.load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (String s : getAbilitiesConfig().getStringList("RAGE_BALL.FRIENDLY_EFFECTS")) {
|
||||
friendlyEffects.add(Serializer.getEffect(s));
|
||||
}
|
||||
|
||||
for (String s : getAbilitiesConfig().getStringList("RAGE_BALL.ENEMY_EFFECTS")) {
|
||||
enemyEffects.add(Serializer.getEffect(s));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory(); // Refund item
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onThrow(ProjectileLaunchEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
Player player = Utils.getDamager(projectile);
|
||||
|
||||
if (player == null) return;
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
ballsThrown.put(projectile.getUniqueId(), player.getUniqueId());
|
||||
applyCooldown(player);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.RAGE_BALL.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLand(ProjectileHitEvent e) {
|
||||
Projectile projectile = e.getEntity();
|
||||
UUID uuid = ballsThrown.remove(projectile.getUniqueId());
|
||||
|
||||
if (uuid != null) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) return;
|
||||
|
||||
PlayerTeam pt = getInstance().getTeamManager().getByPlayer(player.getUniqueId());
|
||||
PvPClassManager classManager = getInstance().getClassManager();
|
||||
|
||||
// The effect
|
||||
getInstance().getVersionManager().getVersion().playEffect(projectile.getLocation(), rageBallEffect, null);
|
||||
|
||||
for (Entity entity : projectile.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player other = (Player) entity;
|
||||
|
||||
if (other == player) {
|
||||
for (PotionEffect friendlyEffect : friendlyEffects) classManager.addEffect(player, friendlyEffect);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (getInstance().getTeamManager().canHit(player, other, false)) {
|
||||
for (PotionEffect enemyEffect : enemyEffects) classManager.addEffect(other, enemyEffect);
|
||||
}
|
||||
|
||||
if (pt != null && pt.getPlayers().contains(other.getUniqueId())) {
|
||||
if (wholeTeamCooldown) abilityCooldown.applyTimer(other);
|
||||
for (PotionEffect friendlyEffect : friendlyEffects) classManager.addEffect(other, friendlyEffect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class RocketAbility extends Ability {
|
||||
|
||||
private final Set<UUID> fall;
|
||||
private final double multiplier;
|
||||
private final double y;
|
||||
|
||||
public RocketAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Rocket"
|
||||
);
|
||||
this.fall = new HashSet<>();
|
||||
this.multiplier = getAbilitiesConfig().getDouble("ROCKET.MULTIPLIER");
|
||||
this.y = getAbilitiesConfig().getDouble("ROCKET.Y_VALUE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Vector vector = player.getEyeLocation().getDirection();
|
||||
vector.multiply(multiplier);
|
||||
if (y != 0) vector.setY(y);
|
||||
player.setVelocity(vector);
|
||||
|
||||
fall.add(player.getUniqueId());
|
||||
Tasks.executeLater(getManager(), 20L * 15, () -> fall.remove(player.getUniqueId()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ROCKET.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (e.getCause() != EntityDamageEvent.DamageCause.FALL) return;
|
||||
|
||||
Player player = (Player) e.getEntity();
|
||||
|
||||
if (fall.remove(player.getUniqueId())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import me.keano.azurite.modules.timers.listeners.playertimers.EnderpearlTimer;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class SamuraiAbility extends Ability {
|
||||
|
||||
private final Set<PotionEffect> effects;
|
||||
private final int hitsValid;
|
||||
private final int seconds;
|
||||
private final int antiBuildTime;
|
||||
private final int enderPearlTime;
|
||||
|
||||
public SamuraiAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Samurai"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("SAMURAI.EFFECTS_ON_TELEPORT").stream().map(Serializer::getEffect).collect(Collectors.toSet());
|
||||
this.hitsValid = getAbilitiesConfig().getInt("SAMURAI.HITS_VALID");
|
||||
this.seconds = getAbilitiesConfig().getInt("SAMURAI.SECONDS");
|
||||
this.antiBuildTime = getAbilitiesConfig().getInt("SAMURAI.ANTI_BUILD_TIME");
|
||||
this.enderPearlTime = getAbilitiesConfig().getInt("SAMURAI.ENDER_PEARL_TIME");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
// I already coded a way to get last damager for focus mode, so just use that.
|
||||
Player damager = ((FocusModeAbility) getManager().getAbility("FocusMode")).getDamager(player, hitsValid);
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.SAMURAI_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
AntiBuildAbility antiBuildAbility = (AntiBuildAbility) getManager().getAbility("AntiBuild");
|
||||
EnderpearlTimer enderpearlTimer = getInstance().getTimerManager().getEnderpearlTimer();
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
antiBuildAbility.getAntiBuild().applyCooldown(damager, antiBuildTime);
|
||||
enderpearlTimer.applyTimer(damager, enderPearlTime * 1000L);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SAMURAI_ABILITY.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SAMURAI_ABILITY.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SAMURAI_ABILITY.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class SwitchStickAbility extends Ability {
|
||||
|
||||
private final Set<UUID> switchSticks;
|
||||
private final int chance;
|
||||
private final int degrees;
|
||||
private final int time;
|
||||
|
||||
public SwitchStickAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Switch Stick"
|
||||
);
|
||||
this.switchSticks = new HashSet<>();
|
||||
this.chance = getAbilitiesConfig().getInt("SWITCH_STICK.CHANCE");
|
||||
this.degrees = getAbilitiesConfig().getInt("SWITCH_STICK.DEGREES");
|
||||
this.time = getAbilitiesConfig().getInt("SWITCH_STICK.TIME");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
switchSticks.add(player.getUniqueId());
|
||||
Tasks.executeLater(getManager(), 20L * time, () -> switchSticks.remove(player.getUniqueId()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCH_STICK.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getDamager() instanceof Player)) return;
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player damager = (Player) e.getDamager();
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (!switchSticks.contains(damager.getUniqueId())) return;
|
||||
|
||||
int random = ThreadLocalRandom.current().nextInt(100 + 1);
|
||||
|
||||
if (random <= chance) {
|
||||
// https://www.spigotmc.org/threads/setting-a-players-yaw-pitch.97825/
|
||||
Location cloned = damaged.getLocation().clone();
|
||||
cloned.setYaw(cloned.getYaw() + degrees);
|
||||
damaged.teleport(cloned);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCH_STICK.ACTIVATED")) {
|
||||
damager.sendMessage(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.utils.ItemUtils;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Egg;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Snowball;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class SwitcherAbility extends Ability {
|
||||
|
||||
private final Set<UUID> switchers;
|
||||
private final int distance;
|
||||
|
||||
public SwitcherAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Switcher"
|
||||
);
|
||||
this.switchers = new HashSet<>();
|
||||
this.distance = getAbilitiesConfig().getInt("SWITCHER.DISTANCE");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
applyCooldown(player);
|
||||
switchers.add(player.getUniqueId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onHit(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (getItem().getType() == ItemUtils.getMat("SNOW_BALL") && !(e.getDamager() instanceof Snowball)) return;
|
||||
if (getItem().getType() == ItemUtils.getMat("EGG") && !(e.getDamager() instanceof Egg)) return;
|
||||
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
Player damaged = (Player) e.getEntity();
|
||||
|
||||
if (damager == null) return;
|
||||
if (!switchers.contains(damager.getUniqueId())) return;
|
||||
|
||||
if (e.isCancelled()) {
|
||||
damager.getInventory().addItem(item);
|
||||
damager.updateInventory(); // refund it
|
||||
return;
|
||||
}
|
||||
|
||||
if (damager.getLocation().distance(damaged.getLocation()) > distance) {
|
||||
damager.getInventory().addItem(item);
|
||||
damager.updateInventory(); // refund it
|
||||
damager.sendMessage(getLanguageConfig().getString("ABILITIES.SWITCHER.TOO_FAR"));
|
||||
return;
|
||||
}
|
||||
|
||||
Location clonedFirst = damaged.getLocation().clone();
|
||||
Location clonedSecond = damager.getLocation().clone();
|
||||
|
||||
damaged.teleport(clonedSecond);
|
||||
damager.teleport(clonedFirst);
|
||||
|
||||
switchers.remove(damager.getUniqueId());
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCHER.USED"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.SWITCHER.BEEN_HIT"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TankIngotAbility extends Ability {
|
||||
|
||||
private final int radius;
|
||||
private final int maxDuration;
|
||||
private final int durationPerPlayer;
|
||||
private final List<String> effects;
|
||||
|
||||
public TankIngotAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Tank Ingot"
|
||||
);
|
||||
this.radius = getAbilitiesConfig().getInt("TANK_INGOT.RADIUS");
|
||||
this.maxDuration = getAbilitiesConfig().getInt("TANK_INGOT.MAX_DURATION");
|
||||
this.durationPerPlayer = getAbilitiesConfig().getInt("TANK_INGOT.DURATION_PER_PLAYER");
|
||||
this.effects = getAbilitiesConfig().getStringList("TANK_INGOT.EFFECTS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
int enemies = countEnemies(player);
|
||||
applyEffects(player, enemies);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TANK_INGOT.USED")) {
|
||||
player.sendMessage(s
|
||||
.replace("%nearby%", String.valueOf(enemies))
|
||||
.replace("%time%", String.valueOf(durationPerPlayer * enemies))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private int countEnemies(Player player) {
|
||||
int i = 0;
|
||||
|
||||
for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
|
||||
if (!(entity instanceof Player)) continue;
|
||||
|
||||
Player nearby = (Player) entity;
|
||||
|
||||
if (getInstance().getTeamManager().canHit(player, nearby, false)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private void applyEffects(Player player, int nearby) {
|
||||
if (nearby == 0) return;
|
||||
|
||||
for (String effect : effects) {
|
||||
String[] split = effect.split(", ");
|
||||
PotionEffect potionEffect = new PotionEffect(
|
||||
PotionEffectType.getByName(split[0]),
|
||||
Math.min(durationPerPlayer * nearby, maxDuration) * 20,
|
||||
Integer.parseInt(split[2]) - 1);
|
||||
getInstance().getClassManager().addEffect(player, potionEffect);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TeleportBowAbility extends Ability {
|
||||
|
||||
private final Map<UUID, UUID> usedTeleportBow; // player -> arrow
|
||||
private final int seconds;
|
||||
|
||||
public TeleportBowAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
null,
|
||||
"Teleport Bow"
|
||||
);
|
||||
this.usedTeleportBow = new HashMap<>();
|
||||
this.seconds = getAbilitiesConfig().getInt("TELEPORT_BOW.SECONDS");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onShoot(EntityShootBowEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
|
||||
Player player = (Player) e.getEntity();
|
||||
ItemStack bow = e.getBow();
|
||||
|
||||
if (hasAbilityInHand(player)) {
|
||||
usedTeleportBow.put(player.getUniqueId(), e.getProjectile().getUniqueId());
|
||||
getManager().setData(bow, getManager().getData(bow) + 1);
|
||||
|
||||
if (getManager().getData(bow) == bow.getType().getMaxDurability()) {
|
||||
getManager().takeItemInHand(player, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(PlayerInteractEvent e) {
|
||||
if (!e.getAction().name().contains("RIGHT")) return;
|
||||
|
||||
Player player = e.getPlayer();
|
||||
|
||||
if (!hasAbilityInHand(player)) return;
|
||||
|
||||
if (cannotUse(player) || hasCooldown(player)) {
|
||||
e.setCancelled(true);
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDamage(PlayerItemDamageEvent e) {
|
||||
ItemStack damage = e.getItem();
|
||||
|
||||
if (!damage.hasItemMeta()) return;
|
||||
if (!damage.getItemMeta().hasDisplayName()) return;
|
||||
|
||||
ItemMeta itemMeta = damage.getItemMeta();
|
||||
ItemMeta abilityMeta = item.getItemMeta();
|
||||
|
||||
if (itemMeta.getDisplayName().equals(abilityMeta.getDisplayName()) && itemMeta.getLore().equals(abilityMeta.getLore())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamage(EntityDamageByEntityEvent e) {
|
||||
if (!(e.getEntity() instanceof Player)) return;
|
||||
if (!(e.getDamager() instanceof Arrow)) return;
|
||||
|
||||
Player damaged = (Player) e.getEntity();
|
||||
Player damager = Utils.getDamager(e.getDamager());
|
||||
|
||||
if (damager == null) return;
|
||||
if (damager == damaged) return;
|
||||
|
||||
UUID arrow = usedTeleportBow.remove(damager.getUniqueId());
|
||||
|
||||
if (arrow != null && e.getDamager().getUniqueId().equals(arrow)) {
|
||||
applyCooldown(damager);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
damager.teleport(damaged);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_BOW.TELEPORTED_SUCCESSFULLY")) {
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_BOW.TELEPORTING"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", damaged.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_BOW.TELEPORTING_ATTACKER"))
|
||||
damaged.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.modules.ability.task.TeleportTask;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TeleportEyeAbility extends Ability {
|
||||
|
||||
private final int hitsValid;
|
||||
private final int seconds;
|
||||
|
||||
public TeleportEyeAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Teleport Eye"
|
||||
);
|
||||
this.hitsValid = getAbilitiesConfig().getInt("TELEPORT_EYE.HITS_VALID");
|
||||
this.seconds = getAbilitiesConfig().getInt("TELEPORT_EYE.SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
Block block = player.getLocation().getBlock();
|
||||
Player damager = ((FocusModeAbility) getManager().getAbility("FocusMode")).getDamager(player, hitsValid);
|
||||
|
||||
if (!block.isLiquid()) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.TELEPORT_EYE.NOT_IN_LIQUID"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (damager == null) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.NINJA_ABILITY.NO_LAST_HIT"));
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
new TeleportTask(this, () -> {
|
||||
player.teleport(damager);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_EYE.TELEPORTED_SUCCESSFULLY")) {
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
);
|
||||
}
|
||||
}, (i) -> {
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_EYE.TELEPORTING"))
|
||||
player.sendMessage(s
|
||||
.replace("%player%", damager.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TELEPORT_EYE.TELEPORTING_ATTACKER"))
|
||||
damager.sendMessage(s
|
||||
.replace("%player%", player.getName())
|
||||
.replace("%seconds%", String.valueOf(seconds - i))
|
||||
);
|
||||
}, seconds);
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EnderPearl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class TimeWarpAbility extends Ability {
|
||||
|
||||
private final Map<UUID, TimeWarpData> timeWarps;
|
||||
private final int seconds;
|
||||
private final int delay;
|
||||
|
||||
public TimeWarpAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Time Warp"
|
||||
);
|
||||
this.timeWarps = new HashMap<>();
|
||||
this.seconds = getAbilitiesConfig().getInt("TIME_WARP.PEARL_DELAY");
|
||||
this.delay = getAbilitiesConfig().getInt("TIME_WARP.DELAY");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (hasCooldown(player)) return;
|
||||
if (cannotUse(player)) return;
|
||||
|
||||
TimeWarpData data = timeWarps.remove(player.getUniqueId());
|
||||
|
||||
if (data == null || data.getValidTill() < System.currentTimeMillis()) {
|
||||
player.sendMessage(getLanguageConfig().getString("ABILITIES.TIMEWARP.INVALID_PEARL")
|
||||
.replace("%seconds%", String.valueOf(seconds))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
Tasks.executeLater(getManager(), 20L * delay, () -> player.teleport(data.getLocation()));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.TIMEWARP.USED"))
|
||||
player.sendMessage(s
|
||||
.replace("%seconds%", String.valueOf(delay))
|
||||
);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onThrow(ProjectileLaunchEvent e) {
|
||||
if (e.isCancelled()) return;
|
||||
if (!(e.getEntity() instanceof EnderPearl)) return;
|
||||
|
||||
Player player = Utils.getDamager(e.getEntity());
|
||||
|
||||
if (player != null) {
|
||||
timeWarps.put(player.getUniqueId(), new TimeWarpData(player.getLocation(), seconds));
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
private static class TimeWarpData {
|
||||
|
||||
private final Location location;
|
||||
private final long validTill;
|
||||
|
||||
public TimeWarpData(Location location, int usableSeconds) {
|
||||
this.location = location;
|
||||
this.validTill = System.currentTimeMillis() + (usableSeconds * 1000L);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package me.keano.azurite.modules.ability.type;
|
||||
|
||||
import me.keano.azurite.modules.ability.Ability;
|
||||
import me.keano.azurite.modules.ability.AbilityManager;
|
||||
import me.keano.azurite.modules.ability.extra.AbilityUseType;
|
||||
import me.keano.azurite.utils.Serializer;
|
||||
import me.keano.azurite.utils.Tasks;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class UltimateAbility extends Ability {
|
||||
|
||||
private final List<PotionEffect> effects;
|
||||
private final int seconds;
|
||||
|
||||
public UltimateAbility(AbilityManager manager) {
|
||||
super(
|
||||
manager,
|
||||
AbilityUseType.INTERACT,
|
||||
"Ultimate Ability"
|
||||
);
|
||||
this.effects = getAbilitiesConfig().getStringList("ULTIMATE_ABILITY.EFFECTS").stream().map(Serializer::getEffect).collect(Collectors.toList());
|
||||
this.seconds = getAbilitiesConfig().getInt("ULTIMATE_ABILITY.SECONDS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player) {
|
||||
if (cannotUse(player)) return;
|
||||
if (hasCooldown(player)) return;
|
||||
|
||||
takeItem(player);
|
||||
applyCooldown(player);
|
||||
|
||||
Location location = player.getLocation();
|
||||
Tasks.executeLater(getManager(), 20L * seconds, () -> player.teleport(location));
|
||||
|
||||
for (String s : getLanguageConfig().getStringList("ABILITIES.ULTIMATE_ABILITY.USED")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
||||
for (PotionEffect effect : effects) {
|
||||
getInstance().getClassManager().addEffect(player, effect);
|
||||
}
|
||||
}
|
||||
}
|
107
src/java/me/keano/azurite/modules/api/AzuriteAPI.java
Normal file
107
src/java/me/keano/azurite/modules/api/AzuriteAPI.java
Normal 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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
268
src/java/me/keano/azurite/modules/balance/type/VaultBalance.java
Normal file
268
src/java/me/keano/azurite/modules/balance/type/VaultBalance.java
Normal 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;
|
||||
}
|
||||
}
|
51
src/java/me/keano/azurite/modules/board/Board.java
Normal file
51
src/java/me/keano/azurite/modules/board/Board.java
Normal 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);
|
||||
}
|
||||
}
|
18
src/java/me/keano/azurite/modules/board/BoardAdapter.java
Normal file
18
src/java/me/keano/azurite/modules/board/BoardAdapter.java
Normal 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);
|
||||
|
||||
}
|
69
src/java/me/keano/azurite/modules/board/BoardManager.java
Normal file
69
src/java/me/keano/azurite/modules/board/BoardManager.java
Normal 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,522 @@
|
||||
package me.keano.azurite.modules.board.adapter;
|
||||
|
||||
import me.keano.azurite.modules.ability.extra.GlobalCooldown;
|
||||
import me.keano.azurite.modules.board.BoardAdapter;
|
||||
import me.keano.azurite.modules.board.BoardManager;
|
||||
import me.keano.azurite.modules.deathban.Deathban;
|
||||
import me.keano.azurite.modules.events.conquest.Conquest;
|
||||
import me.keano.azurite.modules.events.conquest.extra.Capzone;
|
||||
import me.keano.azurite.modules.events.conquest.extra.ConquestType;
|
||||
import me.keano.azurite.modules.events.koth.Koth;
|
||||
import me.keano.azurite.modules.events.sotw.SOTWManager;
|
||||
import me.keano.azurite.modules.framework.Config;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
import me.keano.azurite.modules.pvpclass.PvPClass;
|
||||
import me.keano.azurite.modules.pvpclass.cooldown.CustomCooldown;
|
||||
import me.keano.azurite.modules.pvpclass.type.bard.BardClass;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostClass;
|
||||
import me.keano.azurite.modules.pvpclass.type.ghost.GhostData;
|
||||
import me.keano.azurite.modules.pvpclass.type.mage.MageClass;
|
||||
import me.keano.azurite.modules.pvpclass.type.miner.MinerClass;
|
||||
import me.keano.azurite.modules.staff.StaffManager;
|
||||
import me.keano.azurite.modules.teams.Team;
|
||||
import me.keano.azurite.modules.teams.enums.TeamType;
|
||||
import me.keano.azurite.modules.teams.type.PlayerTeam;
|
||||
import me.keano.azurite.modules.timers.listeners.playertimers.AbilityTimer;
|
||||
import me.keano.azurite.modules.timers.listeners.playertimers.AppleTimer;
|
||||
import me.keano.azurite.modules.timers.type.CustomTimer;
|
||||
import me.keano.azurite.modules.timers.type.PlayerTimer;
|
||||
import me.keano.azurite.modules.users.User;
|
||||
import me.keano.azurite.utils.Formatter;
|
||||
import me.keano.azurite.utils.Utils;
|
||||
import me.keano.azurite.utils.cuboid.Cuboid;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
public class AzuriteBoard extends Module<BoardManager> implements BoardAdapter {
|
||||
|
||||
private final SOTWManager sotwManager;
|
||||
private final StaffManager staffManager;
|
||||
private final boolean linesEnabled;
|
||||
private final boolean lastLineEnabled;
|
||||
|
||||
private final List<String> kingLines;
|
||||
private final List<String> focusLines;
|
||||
private final List<String> focusSystemLines;
|
||||
private final List<String> conquestLines;
|
||||
private final List<String> kitsLines;
|
||||
private final List<String> noModMode;
|
||||
private final List<String> modMode;
|
||||
private final List<String> footerLines;
|
||||
private final List<String> claim;
|
||||
private final List<String> kothLines;
|
||||
|
||||
private final String line;
|
||||
private final String antiClean;
|
||||
private final String sotwOff;
|
||||
private final String sotw;
|
||||
private final String appleLimit;
|
||||
private final String className;
|
||||
private final String eotw;
|
||||
private final String purge;
|
||||
private final String bardEnergy;
|
||||
private final String mageEnergy;
|
||||
private final String minerInvis;
|
||||
private final String minerDiamonds;
|
||||
private final String ghostMode;
|
||||
private final String globalAbilities;
|
||||
private final String customTimerFormat;
|
||||
private final String deathbanInfo;
|
||||
private final String deathbanLives;
|
||||
|
||||
private final boolean footerEnabled;
|
||||
private final boolean focusEnabled;
|
||||
private final boolean kingEnabled;
|
||||
private final boolean staffEnabled;
|
||||
private final boolean kitsInfoOnlySpawn;
|
||||
private final boolean conquestOnlyTeam;
|
||||
private final boolean claimEnabled;
|
||||
private final boolean kothEnabled;
|
||||
private final boolean onlyPositiveKillstreak;
|
||||
|
||||
public AzuriteBoard(BoardManager manager) {
|
||||
super(manager);
|
||||
|
||||
this.sotwManager = getInstance().getSotwManager();
|
||||
this.staffManager = getInstance().getStaffManager();
|
||||
this.linesEnabled = getScoreboardConfig().getBoolean("SCOREBOARD_INFO.LINES_ENABLED");
|
||||
this.lastLineEnabled = getScoreboardConfig().getBoolean("SCOREBOARD_INFO.LAST_LINE_ENABLED");
|
||||
|
||||
this.kingLines = getScoreboardConfig().getStringList("KILL_THE_KING.LINES");
|
||||
this.focusLines = getScoreboardConfig().getStringList("TEAM_FOCUS.LINES_PLAYER");
|
||||
this.focusSystemLines = getScoreboardConfig().getStringList("TEAM_FOCUS.LINES_SYSTEM");
|
||||
this.conquestLines = getScoreboardConfig().getStringList("CONQUEST.LINES");
|
||||
this.kitsLines = getScoreboardConfig().getStringList("KITS_INFO");
|
||||
this.noModMode = getScoreboardConfig().getStringList("STAFF_MODE.VANISH_NO_MODMODE");
|
||||
this.modMode = getScoreboardConfig().getStringList("STAFF_MODE.MOD_MODE");
|
||||
this.footerLines = getScoreboardConfig().getStringList("FOOTER.LINES");
|
||||
this.claim = getScoreboardConfig().getStringList("CLAIM.LINES");
|
||||
this.kothLines = getScoreboardConfig().getStringList("KOTH.LINES");
|
||||
|
||||
this.line = getScoreboardConfig().getString("SCOREBOARD_INFO.LINES");
|
||||
this.antiClean = getString("PLAYER_TIMERS.ANTI_CLEAN");
|
||||
this.sotwOff = getString("PLAYER_TIMERS.SOTW_OFF");
|
||||
this.sotw = getString("PLAYER_TIMERS.SOTW");
|
||||
this.appleLimit = getString("PLAYER_TIMERS.APPLE_LIMIT");
|
||||
this.className = getString("PLAYER_TIMERS.ACTIVE_CLASS");
|
||||
this.eotw = getString("PLAYER_TIMERS.PRE_EOTW");
|
||||
this.purge = getString("PLAYER_TIMERS.PURGE");
|
||||
this.bardEnergy = getString("BARD_CLASS.BARD_ENERGY");
|
||||
this.mageEnergy = getString("MAGE_CLASS.MAGE_ENERGY");
|
||||
this.minerInvis = getString("MINER_CLASS.INVIS");
|
||||
this.minerDiamonds = getString("MINER_CLASS.DIAMONDS");
|
||||
this.ghostMode = getString("GHOST_CLASS.MODE");
|
||||
this.globalAbilities = getString("PLAYER_TIMERS.GLOBAL_ABILITIES");
|
||||
this.customTimerFormat = getString("CUSTOM_TIMERS.FORMAT");
|
||||
this.deathbanInfo = getString("DEATHBAN_INFO.TIME");
|
||||
this.deathbanLives = getString("DEATHBAN_INFO.LIVES");
|
||||
|
||||
this.footerEnabled = getScoreboardConfig().getBoolean("FOOTER.ENABLED");
|
||||
this.focusEnabled = getScoreboardConfig().getBoolean("TEAM_FOCUS.ENABLED");
|
||||
this.kingEnabled = getScoreboardConfig().getBoolean("KILL_THE_KING.ENABLED");
|
||||
this.staffEnabled = getScoreboardConfig().getBoolean("STAFF_MODE.ENABLED");
|
||||
this.kitsInfoOnlySpawn = getConfig().getBoolean("KITS_INFO_ONLY_SPAWN");
|
||||
this.conquestOnlyTeam = getConfig().getBoolean("CONQUEST.SCOREBOARD_ONLY_CONQUEST_CLAIM");
|
||||
this.claimEnabled = getScoreboardConfig().getBoolean("CLAIM.ENABLED");
|
||||
this.kothEnabled = getScoreboardConfig().getBoolean("KOTH.ENABLED");
|
||||
this.onlyPositiveKillstreak = getScoreboardConfig().getBoolean("SCOREBOARD_INFO.SHOW_KILLSTREAK_ONLY_POSITIVE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle(Player player) {
|
||||
return Config.SCOREBOARD_TITLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLines(Player player) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
PlayerTeam pt = getInstance().getTeamManager().getByPlayer(player.getUniqueId());
|
||||
User user = getInstance().getUserManager().getByUUID(player.getUniqueId());
|
||||
GlobalCooldown globalCooldown = getInstance().getAbilityManager().getGlobalCooldown();
|
||||
Conquest conquest = getInstance().getConquestManager().getConquest();
|
||||
Deathban deathban = user.getDeathban();
|
||||
Team atPlayer = null;
|
||||
|
||||
boolean mod = false;
|
||||
boolean vanish = false;
|
||||
boolean focus = false;
|
||||
int focusSize = 0;
|
||||
int footer = (footerEnabled ? footerLines.size() : 0);
|
||||
int numberOfLines = (lastLineEnabled ? 2 : 1);
|
||||
|
||||
if (deathban != null) {
|
||||
if (linesEnabled) lines.add(line);
|
||||
|
||||
lines.add(deathbanInfo + Formatter.getRemaining(deathban.getTime(), false));
|
||||
lines.add(deathbanLives + user.getLives());
|
||||
|
||||
if (footerEnabled) {
|
||||
for (String s : footerLines)
|
||||
lines.add(s
|
||||
.replace("%footer%", getManager().getFooter().getCurrent())
|
||||
);
|
||||
}
|
||||
|
||||
if (linesEnabled) lines.add(line);
|
||||
return getInstance().getPlaceholderHook().replace(player, lines);
|
||||
}
|
||||
|
||||
if (!user.isScoreboard()) return null;
|
||||
|
||||
if (staffEnabled) {
|
||||
boolean vanished = staffManager.isVanished(player);
|
||||
boolean staffActive = staffManager.isStaffEnabled(player);
|
||||
|
||||
if (vanished && !staffActive) {
|
||||
vanish = true;
|
||||
|
||||
for (String s : noModMode)
|
||||
lines.add(s
|
||||
.replace("%vanished%", Config.STAFF_TRUE_PLACEHOLDER)
|
||||
);
|
||||
|
||||
} else if (staffActive) {
|
||||
mod = true;
|
||||
|
||||
for (String s : modMode)
|
||||
lines.add(s
|
||||
.replace("%vanished%", (vanished ? Config.STAFF_TRUE_PLACEHOLDER : Config.STAFF_FALSE_PLACEHOLDER))
|
||||
.replace("%staffbuild%", staffManager.isStaffBuild(player) ? Config.STAFF_TRUE_PLACEHOLDER : Config.STAFF_FALSE_PLACEHOLDER)
|
||||
.replace("%hidestaff%", staffManager.isHideStaff(player) ? Config.STAFF_TRUE_PLACEHOLDER : Config.STAFF_FALSE_PLACEHOLDER)
|
||||
.replace("%players%", String.valueOf(Bukkit.getOnlinePlayers().size()))
|
||||
.replace("%staff%", String.valueOf(staffManager.getStaffMembers().size()))
|
||||
.replace("%tps%", getInstance().getVersionManager().getVersion().getTPSColored())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (claimEnabled && user.isScoreboardClaim()) {
|
||||
atPlayer = getInstance().getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
|
||||
for (String s : claim)
|
||||
lines.add(s
|
||||
.replace("%claim%", atPlayer.getDisplayName(player))
|
||||
);
|
||||
}
|
||||
|
||||
if (getInstance().isKits()) {
|
||||
boolean add = false;
|
||||
|
||||
if (kitsInfoOnlySpawn) {
|
||||
if (atPlayer == null) {
|
||||
atPlayer = getInstance().getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
}
|
||||
|
||||
if (atPlayer.getType() == TeamType.SAFEZONE) {
|
||||
add = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
add = true;
|
||||
}
|
||||
|
||||
if (add) {
|
||||
for (String s : kitsLines) {
|
||||
if (onlyPositiveKillstreak && s.contains("%killstreak%") && user.getKillstreak() <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add(s
|
||||
.replace("%kills%", String.valueOf(user.getKills()))
|
||||
.replace("%deaths%", String.valueOf(user.getDeaths()))
|
||||
.replace("%killstreak%", String.valueOf(user.getKillstreak()))
|
||||
.replace("%balance%", String.valueOf(user.getBalance()))
|
||||
.replace("%kdr%", user.getKDRString())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kingEnabled && getInstance().getKingManager().isActive()) {
|
||||
Player king = getInstance().getKingManager().getKing();
|
||||
double currentHealth = king.getHealth() / 2;
|
||||
|
||||
for (String s : kingLines)
|
||||
lines.add(s
|
||||
.replace("%king%", king.getName())
|
||||
.replace("%loc%", Utils.formatLocation(king.getLocation()))
|
||||
.replace("%reward%", getInstance().getKingManager().getReward())
|
||||
.replace("%health%", Formatter.formatHealth(currentHealth))
|
||||
);
|
||||
}
|
||||
|
||||
if (kothEnabled) {
|
||||
for (Koth activeKoth : getInstance().getKothManager().getKoths().values()) {
|
||||
if (!activeKoth.isActive()) continue;
|
||||
|
||||
Cuboid capzone = activeKoth.getCaptureZone();
|
||||
|
||||
for (String s : kothLines)
|
||||
lines.add(s
|
||||
.replace("%color%", activeKoth.getColor())
|
||||
.replace("%koth%", activeKoth.getName())
|
||||
.replace("%rem%", Formatter.getRemaining(activeKoth.getRemaining(), false))
|
||||
.replace("%loc%", (capzone == null ? "None" : Utils.formatLocation(capzone.getCenter())))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (pt != null && antiClean != null) {
|
||||
PlayerTeam antiCleanTeam = pt.getAntiCleanTeam();
|
||||
long rem = pt.getAntiCleanRemaining();
|
||||
|
||||
if (antiCleanTeam != null && rem > 0L) {
|
||||
lines.add(antiClean + Formatter.getRemaining(rem, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (sotwManager.isActive()) {
|
||||
if (sotwManager.getEnabled().contains(player.getUniqueId())) {
|
||||
if (sotwOff != null) lines.add(sotwOff + sotwManager.getRemainingString());
|
||||
|
||||
} else {
|
||||
if (sotw != null) lines.add(sotw + sotwManager.getRemainingString());
|
||||
}
|
||||
}
|
||||
|
||||
AppleTimer appleTimer = getInstance().getTimerManager().getAppleTimer();
|
||||
World.Environment environment = player.getWorld().getEnvironment();
|
||||
|
||||
if (appleTimer.isLimited(environment)) {
|
||||
if (appleLimit != null)
|
||||
lines.add(appleLimit
|
||||
.replace("%amount%", String.valueOf(appleTimer.getLimit(player)))
|
||||
.replace("%max-amount%", String.valueOf(appleTimer.getMaxLimit(environment)))
|
||||
);
|
||||
}
|
||||
|
||||
for (CustomTimer timer : getInstance().getTimerManager().getCustomTimers().values()) {
|
||||
if (timer.getName().equals("EOTW")) {
|
||||
if (eotw != null) lines.add(eotw + timer.getRemainingString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (timer.getName().equals("Purge")) {
|
||||
if (purge != null) lines.add(purge + timer.getRemainingString());
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add(customTimerFormat
|
||||
.replace("%displayName%", timer.getDisplayName()) + timer.getRemainingString()
|
||||
);
|
||||
}
|
||||
|
||||
PvPClass activeClass = getInstance().getClassManager().getActiveClasses().get(player.getUniqueId());
|
||||
|
||||
if (activeClass != null) {
|
||||
if (className != null) lines.add(className + activeClass.getName());
|
||||
|
||||
if (activeClass instanceof BardClass) {
|
||||
BardClass bardClass = (BardClass) activeClass;
|
||||
|
||||
if (bardEnergy != null) {
|
||||
lines.add(bardEnergy + Formatter.formatBardEnergy(bardClass.getEnergyCooldown(player).getEnergy()));
|
||||
}
|
||||
|
||||
} else if (activeClass instanceof MageClass) {
|
||||
MageClass mageClass = (MageClass) activeClass;
|
||||
|
||||
if (mageEnergy != null) {
|
||||
lines.add(mageEnergy + Formatter.formatBardEnergy(mageClass.getEnergyCooldown(player).getEnergy()));
|
||||
}
|
||||
|
||||
} else if (activeClass instanceof MinerClass) {
|
||||
MinerClass minerClass = (MinerClass) activeClass;
|
||||
|
||||
if (minerInvis != null) {
|
||||
lines.add(minerInvis + (minerClass.getInvisible().contains(player.getUniqueId()) ? "true" : "false"));
|
||||
}
|
||||
|
||||
if (minerDiamonds != null) {
|
||||
lines.add(minerDiamonds + user.getDiamonds());
|
||||
}
|
||||
|
||||
} else if (activeClass instanceof GhostClass) {
|
||||
GhostClass ghostClass = (GhostClass) activeClass;
|
||||
GhostData data = ghostClass.getData().get(player.getUniqueId());
|
||||
|
||||
if (ghostMode != null) {
|
||||
lines.add(ghostMode + data.getMode());
|
||||
}
|
||||
}
|
||||
|
||||
// basically all your speeds, jump
|
||||
for (CustomCooldown customCooldown : activeClass.getCustomCooldowns()) {
|
||||
String name = customCooldown.getDisplayName();
|
||||
|
||||
if (name == null) continue;
|
||||
if (!customCooldown.hasCooldown(player)) continue;
|
||||
|
||||
lines.add(name + customCooldown.getRemainingOld(player));
|
||||
}
|
||||
}
|
||||
|
||||
if (globalCooldown.hasTimer(player)) {
|
||||
if (globalAbilities != null) lines.add(globalAbilities + globalCooldown.getRemainingString(player));
|
||||
}
|
||||
|
||||
for (PlayerTimer timer : getInstance().getTimerManager().getPlayerTimers().values()) {
|
||||
if (timer instanceof GlobalCooldown) continue;
|
||||
|
||||
String name = timer.getScoreboard();
|
||||
|
||||
if (!timer.hasTimer(player)) continue;
|
||||
if (name == null) continue;
|
||||
|
||||
// These need to be replaced, so handle differently
|
||||
if (timer instanceof AbilityTimer) {
|
||||
AbilityTimer abilityTimer = (AbilityTimer) timer;
|
||||
lines.add(name.replace("%ability%", abilityTimer.getAbility().getDisplayName()) + timer.getRemainingStringBoard(player));
|
||||
continue;
|
||||
}
|
||||
|
||||
lines.add(name + timer.getRemainingStringBoard(player));
|
||||
}
|
||||
|
||||
lines.addAll(getInstance().getAbilitiesHook().getScoreboardLines(player));
|
||||
|
||||
if (conquest.isActive()) {
|
||||
if (atPlayer == null) {
|
||||
atPlayer = getInstance().getTeamManager().getClaimManager().getTeam(player.getLocation());
|
||||
}
|
||||
|
||||
if (!conquestOnlyTeam || atPlayer.getType() == TeamType.CONQUEST) {
|
||||
Map<ConquestType, Capzone> conquests = conquest.getCapzones();
|
||||
|
||||
for (String conquestLine : conquestLines)
|
||||
lines.add(conquestLine
|
||||
.replace("%points-1%", conquest.getPoints(1))
|
||||
.replace("%points-2%", conquest.getPoints(2))
|
||||
.replace("%points-3%", conquest.getPoints(3))
|
||||
.replace("%red%", conquests.get(ConquestType.RED).getRemainingString())
|
||||
.replace("%yellow%", conquests.get(ConquestType.YELLOW).getRemainingString())
|
||||
.replace("%green%", conquests.get(ConquestType.GREEN).getRemainingString())
|
||||
.replace("%blue%", conquests.get(ConquestType.BLUE).getRemainingString())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (focusEnabled && pt != null && pt.getFocus() != null) {
|
||||
Team focusedTeam = pt.getFocusedTeam();
|
||||
|
||||
if (focusedTeam != null) {
|
||||
focus = true;
|
||||
|
||||
if (focusedTeam.getType() == TeamType.PLAYER) {
|
||||
focusSize = focusLines.size();
|
||||
PlayerTeam focusPT = (PlayerTeam) focusedTeam;
|
||||
|
||||
for (String focusLine : focusLines)
|
||||
lines.add(focusLine
|
||||
.replace("%team%", focusPT.getName())
|
||||
.replace("%hq%", focusPT.getHQFormatted())
|
||||
.replace("%online%", String.valueOf(focusPT.getOnlinePlayersSize(false)))
|
||||
.replace("%max-online%", String.valueOf(focusPT.getPlayers().size()))
|
||||
.replace("%dtr-color%", focusPT.getDtrColor())
|
||||
.replace("%dtr%", focusPT.getDtrString())
|
||||
.replace("%dtr-symbol%", focusPT.getDtrSymbol())
|
||||
);
|
||||
|
||||
} else {
|
||||
focusSize = focusSystemLines.size();
|
||||
|
||||
for (String s : focusSystemLines)
|
||||
lines.add(s
|
||||
.replace("%team%", focusedTeam.getName())
|
||||
.replace("%hq%", focusedTeam.getHQFormatted())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (footerEnabled) {
|
||||
for (String s : footerLines)
|
||||
lines.add(s
|
||||
.replace("%footer%", getManager().getFooter().getCurrent())
|
||||
);
|
||||
}
|
||||
|
||||
if (lines.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (linesEnabled) {
|
||||
List<String> clone = new ArrayList<>();
|
||||
|
||||
if (!lines.get(0).equals(line)) {
|
||||
clone.add(line);
|
||||
}
|
||||
|
||||
clone.addAll(lines);
|
||||
|
||||
if (!lines.get(lines.size() - 1).equals(line) && lastLineEnabled) {
|
||||
clone.add(line);
|
||||
}
|
||||
|
||||
lines = clone;
|
||||
|
||||
if (lines.size() == numberOfLines + footer) return null;
|
||||
}
|
||||
|
||||
if (!linesEnabled && footerEnabled && lines.size() == footerLines.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Below handles all the double lines which shouldn't be there.
|
||||
|
||||
int totalSize = numberOfLines + footer;
|
||||
boolean lastLineModMode = modMode.get(modMode.size() - 1).equals(line);
|
||||
boolean lastLineNoModMode = noModMode.get(noModMode.size() - 1).equals(line);
|
||||
|
||||
if (mod && lines.size() == totalSize + modMode.size() && lastLineModMode) {
|
||||
lines.remove(modMode.size());
|
||||
}
|
||||
|
||||
if (vanish && lines.size() == totalSize + noModMode.size() && lastLineNoModMode) {
|
||||
lines.remove(noModMode.size());
|
||||
}
|
||||
|
||||
if (mod && lastLineModMode && focus && lines.size() == totalSize + modMode.size() + focusSize) {
|
||||
String modModeLine = lines.get(modMode.size() + 1);
|
||||
|
||||
if (modModeLine.equals(line) || modModeLine.isEmpty()) {
|
||||
lines.remove(modMode.size() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (vanish && lastLineNoModMode && focus && lines.size() == totalSize + noModMode.size() + focusSize) {
|
||||
String noModModeLine = lines.get(noModMode.size() + 1);
|
||||
|
||||
if (noModModeLine.equals(line) || noModModeLine.isEmpty()) {
|
||||
lines.remove(noModMode.size() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return getInstance().getPlaceholderHook().replace(player, lines);
|
||||
}
|
||||
|
||||
public String getString(String path) {
|
||||
String string = getScoreboardConfig().getString(path);
|
||||
return (string.isEmpty() ? null : string);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package me.keano.azurite.modules.board.extra;
|
||||
|
||||
import lombok.Getter;
|
||||
import me.keano.azurite.modules.framework.Manager;
|
||||
import me.keano.azurite.modules.framework.Module;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023. Keano
|
||||
* Use or redistribution of source or file is
|
||||
* only permitted if given explicit permission.
|
||||
*/
|
||||
@Getter
|
||||
public class AnimatedString extends Module<Manager> {
|
||||
|
||||
private final List<String> changes;
|
||||
private final long delay;
|
||||
|
||||
private String current;
|
||||
private long ticks;
|
||||
private int index;
|
||||
|
||||
public AnimatedString(Manager manager, List<String> changes, long delay) {
|
||||
super(manager);
|
||||
this.changes = changes;
|
||||
this.delay = delay;
|
||||
this.current = "";
|
||||
this.ticks = System.currentTimeMillis();
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (ticks < System.currentTimeMillis()) {
|
||||
ticks = System.currentTimeMillis() + delay;
|
||||
|
||||
if (index == changes.size()) {
|
||||
index = 0; // Reset the index
|
||||
current = changes.get(0);
|
||||
return;
|
||||
}
|
||||
|
||||
String nextTitle = changes.get(index);
|
||||
index++;
|
||||
current = nextTitle;
|
||||
}
|
||||
}
|
||||
}
|
596
src/java/me/keano/azurite/modules/board/fastboard/FastBoard.java
Normal file
596
src/java/me/keano/azurite/modules/board/fastboard/FastBoard.java
Normal 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
Loading…
Reference in New Issue
Block a user