Added trust protections, made broadcasting not spam console, updated unique and armor checks.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -19,3 +19,7 @@ commands:
|
|||||||
aliases:
|
aliases:
|
||||||
- asmp
|
- asmp
|
||||||
- armor_smp
|
- armor_smp
|
||||||
|
ability:
|
||||||
|
description: Utilize unique abilities.
|
||||||
|
aliases:
|
||||||
|
- a
|
||||||
Binary file not shown.
@@ -1,6 +1,7 @@
|
|||||||
package me.trouper.armorsmp;
|
package me.trouper.armorsmp;
|
||||||
|
|
||||||
import io.github.itzispyder.pdk.PDK;
|
import io.github.itzispyder.pdk.PDK;
|
||||||
|
import io.github.itzispyder.pdk.utils.misc.Timer;
|
||||||
import me.trouper.armorsmp.server.Manager;
|
import me.trouper.armorsmp.server.Manager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
@@ -8,9 +9,11 @@ public final class ArmorSMP extends JavaPlugin {
|
|||||||
|
|
||||||
private static ArmorSMP instance;
|
private static ArmorSMP instance;
|
||||||
private Manager manager;
|
private Manager manager;
|
||||||
|
private Timer timer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
|
timer = Timer.start();
|
||||||
getLogger().info("Instantiating Plugin");
|
getLogger().info("Instantiating Plugin");
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
||||||
@@ -25,6 +28,7 @@ public final class ArmorSMP extends JavaPlugin {
|
|||||||
|
|
||||||
getLogger().info("Initializing Manager");
|
getLogger().info("Initializing Manager");
|
||||||
manager.init();
|
manager.init();
|
||||||
|
getLogger().info("Successfully enabled ArmorSMP in %s".formatted(timer.end().getStampPrecise()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,15 +1,26 @@
|
|||||||
package me.trouper.armorsmp.data;
|
package me.trouper.armorsmp.data;
|
||||||
|
|
||||||
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
|
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
|
||||||
|
import io.github.itzispyder.pdk.utils.raytracers.CustomDisplayRaytracer;
|
||||||
|
import me.trouper.armorsmp.ArmorSMP;
|
||||||
import me.trouper.armorsmp.utils.Text;
|
import me.trouper.armorsmp.utils.Text;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.AreaEffectCloud;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.potion.PotionEffect;
|
import org.bukkit.potion.PotionEffect;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public enum Unique {
|
public enum Unique {
|
||||||
HELMET(ItemBuilder.create()
|
HELMET(ItemBuilder.create()
|
||||||
@@ -46,6 +57,25 @@ public enum Unique {
|
|||||||
p.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH,21,0,true,false,false));
|
p.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH,21,0,true,false,false));
|
||||||
p.addPotionEffect(new PotionEffect(PotionEffectType.RESISTANCE,21,0,true,false,false));
|
p.addPotionEffect(new PotionEffect(PotionEffectType.RESISTANCE,21,0,true,false,false));
|
||||||
}, (p) -> {
|
}, (p) -> {
|
||||||
|
// TODO: Test Dragon's Breath
|
||||||
|
World world = p.getWorld();
|
||||||
|
|
||||||
|
Location eyeLocation = p.getEyeLocation();
|
||||||
|
Vector direction = eyeLocation.getDirection();
|
||||||
|
|
||||||
|
Location hit = CustomDisplayRaytracer.trace(eyeLocation,direction,30,point -> {
|
||||||
|
Location particleLocation = point.getLoc();
|
||||||
|
world.spawnParticle(Particle.DRAGON_BREATH, particleLocation, 10, 0.2, 0.2, 0.2, 0.01);
|
||||||
|
return !point.getBlock().isPassable();
|
||||||
|
}).getLoc();
|
||||||
|
|
||||||
|
AreaEffectCloud cloud = (AreaEffectCloud) world.spawnEntity(hit, EntityType.AREA_EFFECT_CLOUD);
|
||||||
|
cloud.setRadius(3.0f);
|
||||||
|
cloud.setDuration(200);
|
||||||
|
cloud.setParticle(Particle.DRAGON_BREATH);
|
||||||
|
cloud.addCustomEffect(PotionEffectType.INSTANT_DAMAGE.createEffect(1,1),true);
|
||||||
|
cloud.setOwnerUniqueId(p.getUniqueId());
|
||||||
|
|
||||||
}, 50),
|
}, 50),
|
||||||
LEGGINGS(ItemBuilder.create()
|
LEGGINGS(ItemBuilder.create()
|
||||||
.material(Material.NETHERITE_LEGGINGS)
|
.material(Material.NETHERITE_LEGGINGS)
|
||||||
@@ -61,9 +91,23 @@ public enum Unique {
|
|||||||
.build(),
|
.build(),
|
||||||
"Netherite Leggings", (p) -> {
|
"Netherite Leggings", (p) -> {
|
||||||
p.addPotionEffect(new PotionEffect(PotionEffectType.RESISTANCE,21,0,true,false,false));
|
p.addPotionEffect(new PotionEffect(PotionEffectType.RESISTANCE,21,0,true,false,false));
|
||||||
|
|
||||||
}, (p) -> {
|
}, (p) -> {
|
||||||
// TODO: yoink shield ability from OgreDupeAlias
|
// TODO: Test Shield
|
||||||
|
Stream<Entity> toKnockBack = p.getNearbyEntities(10,10,10).stream().filter(target -> {
|
||||||
|
if (!(target instanceof Player v)) return false;
|
||||||
|
boolean tooClose = target.getLocation().distance(p.getLocation()) < 10;
|
||||||
|
boolean self = target.getUniqueId().equals(p.getUniqueId());
|
||||||
|
boolean trusted = ArmorSMP.getInstance().getManager().trust.getTrustees(p).contains(v.getUniqueId().toString());
|
||||||
|
return tooClose && !self && !trusted;
|
||||||
|
});
|
||||||
|
toKnockBack.forEach((target -> {
|
||||||
|
Vector direction = target.getLocation().toVector().subtract(p.getLocation().toVector());
|
||||||
|
direction.normalize();
|
||||||
|
direction.multiply(2);
|
||||||
|
direction.setY(direction.getY() + 0.5);
|
||||||
|
|
||||||
|
target.setVelocity(direction);
|
||||||
|
}));
|
||||||
}, 45),
|
}, 45),
|
||||||
BOOTS(ItemBuilder.create()
|
BOOTS(ItemBuilder.create()
|
||||||
.material(Material.NETHERITE_BOOTS)
|
.material(Material.NETHERITE_BOOTS)
|
||||||
@@ -82,7 +126,10 @@ public enum Unique {
|
|||||||
"Netherite Boots", (p) -> {
|
"Netherite Boots", (p) -> {
|
||||||
p.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,21,0,true,false,false));
|
p.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,21,0,true,false,false));
|
||||||
}, (p) -> {
|
}, (p) -> {
|
||||||
// TODO: Vector math for dash ability
|
Vector direction = p.getLocation().getDirection();
|
||||||
|
Vector velocity = direction.multiply(4); // TODO: Test Vector
|
||||||
|
|
||||||
|
p.setVelocity(velocity);
|
||||||
}, 50),
|
}, 50),
|
||||||
MACE(ItemBuilder.create()
|
MACE(ItemBuilder.create()
|
||||||
.material(Material.MACE)
|
.material(Material.MACE)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import io.github.itzispyder.pdk.commands.CustomCommand;
|
|||||||
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
|
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
|
||||||
import io.github.itzispyder.pdk.utils.misc.Cooldown;
|
import io.github.itzispyder.pdk.utils.misc.Cooldown;
|
||||||
import io.github.itzispyder.pdk.utils.misc.Pair;
|
import io.github.itzispyder.pdk.utils.misc.Pair;
|
||||||
|
import me.trouper.armorsmp.ArmorSMP;
|
||||||
import me.trouper.armorsmp.data.Unique;
|
import me.trouper.armorsmp.data.Unique;
|
||||||
import me.trouper.armorsmp.utils.Text;
|
import me.trouper.armorsmp.utils.Text;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@@ -13,12 +14,13 @@ import org.bukkit.command.CommandSender;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@CommandRegistry(value = "ability", printStackTrace = true, playersOnly = true)
|
@CommandRegistry(value = "ability", printStackTrace = true, playersOnly = true)
|
||||||
public class AbilityCommand implements CustomCommand {
|
public class AbilityCommand implements CustomCommand {
|
||||||
|
|
||||||
Cooldown<Pair<Unique, UUID>> abilityCooldown = new Cooldown<>();
|
private final Cooldown<Pair<Unique, UUID>> abilityCooldown = new Cooldown<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispatchCommand(CommandSender sender, Command command, String label, Args args) {
|
public void dispatchCommand(CommandSender sender, Command command, String label, Args args) {
|
||||||
@@ -28,6 +30,10 @@ public class AbilityCommand implements CustomCommand {
|
|||||||
Text.sendMessage(false, Text.Pallet.ERROR, sender, "Error: {0} is not a valid unique. Please choose from these values: ", args.get(2).toString(), Arrays.toString(Unique.values()));
|
Text.sendMessage(false, Text.Pallet.ERROR, sender, "Error: {0} is not a valid unique. Please choose from these values: ", args.get(2).toString(), Arrays.toString(Unique.values()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (p.getUniqueId().toString().equals(ArmorSMP.getInstance().getManager().io.storage.uniques.owners.get(piece))) {
|
||||||
|
Text.sendMessage(false, Text.Pallet.WARNING, sender, "You do not own {0}.",piece.getCanonical());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (abilityCooldown.isOnCooldown(Pair.of(piece,p.getUniqueId()))) {
|
if (abilityCooldown.isOnCooldown(Pair.of(piece,p.getUniqueId()))) {
|
||||||
Text.sendMessage(false, Text.Pallet.WARNING, sender, "The ability for your {0} is on cooldown for {1} seconds.",piece.getCanonical(),abilityCooldown.getCooldownSec(Pair.of(piece,p.getUniqueId())));
|
Text.sendMessage(false, Text.Pallet.WARNING, sender, "The ability for your {0} is on cooldown for {1} seconds.",piece.getCanonical(),abilityCooldown.getCooldownSec(Pair.of(piece,p.getUniqueId())));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import io.papermc.paper.event.entity.EntityDamageItemEvent;
|
|||||||
import me.trouper.armorsmp.data.Unique;
|
import me.trouper.armorsmp.data.Unique;
|
||||||
import org.bukkit.entity.Item;
|
import org.bukkit.entity.Item;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.entity.EntityDamageByBlockEvent;
|
import org.bukkit.event.entity.*;
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
||||||
import org.bukkit.event.entity.ItemDespawnEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
public class ItemDestroyEvents implements CustomListener {
|
public class ItemDestroyEvents implements CustomListener {
|
||||||
@@ -28,7 +26,31 @@ public class ItemDestroyEvents implements CustomListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBlockDamage(EntityDamageByEntityEvent e) {
|
public void onEntityDamage(EntityDamageByEntityEvent e) {
|
||||||
|
if (!(e.getEntity() instanceof Item i)) return;
|
||||||
|
if (!Unique.isUnique(i.getItemStack())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onCombust(EntityCombustEvent e) {
|
||||||
|
if (!(e.getEntity() instanceof Item i)) return;
|
||||||
|
if (!Unique.isUnique(i.getItemStack())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onEntityCombust(EntityCombustByEntityEvent e) {
|
||||||
|
if (!(e.getEntity() instanceof Item i)) return;
|
||||||
|
if (!Unique.isUnique(i.getItemStack())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockCombust(EntityCombustByBlockEvent e) {
|
||||||
if (!(e.getEntity() instanceof Item i)) return;
|
if (!(e.getEntity() instanceof Item i)) return;
|
||||||
if (!Unique.isUnique(i.getItemStack())) return;
|
if (!Unique.isUnique(i.getItemStack())) return;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class JoinEvent implements CustomListener {
|
|||||||
final Map<String, Boolean> armorCache = ArmorSMP.getInstance().getManager().io.storage.armorUpdateCache;
|
final Map<String, Boolean> armorCache = ArmorSMP.getInstance().getManager().io.storage.armorUpdateCache;
|
||||||
if (armorCache.containsKey(p.getUniqueId().toString()) || !ArmorSMP.getInstance().getManager().armor.verifyArmor(p)) {
|
if (armorCache.containsKey(p.getUniqueId().toString()) || !ArmorSMP.getInstance().getManager().armor.verifyArmor(p)) {
|
||||||
Verbose.send("Updating armor");
|
Verbose.send("Updating armor");
|
||||||
ArmorSMP.getInstance().getManager().armor.queueUpdate(p,armorCache.get(p.getUniqueId().toString()));
|
ArmorSMP.getInstance().getManager().armor.queueUpdate(p,armorCache.getOrDefault(p.getUniqueId().toString(),true));
|
||||||
ArmorSMP.getInstance().getManager().io.storage.armorUpdateCache.remove(p.getUniqueId().toString());
|
ArmorSMP.getInstance().getManager().io.storage.armorUpdateCache.remove(p.getUniqueId().toString());
|
||||||
}
|
}
|
||||||
final Set<String> uniquesCache = ArmorSMP.getInstance().getManager().io.storage.uniqueUpdateCache;
|
final Set<String> uniquesCache = ArmorSMP.getInstance().getManager().io.storage.uniqueUpdateCache;
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package me.trouper.armorsmp.server.events;
|
||||||
|
|
||||||
|
import io.github.itzispyder.pdk.events.CustomListener;
|
||||||
|
import me.trouper.armorsmp.ArmorSMP;
|
||||||
|
import org.bukkit.entity.AreaEffectCloud;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class TrustEvents implements CustomListener {
|
||||||
|
@EventHandler
|
||||||
|
public void onDamage(EntityDamageByEntityEvent e) {
|
||||||
|
if (!(e.getEntity() instanceof Player v)) return;
|
||||||
|
Set<String> trustees = ArmorSMP.getInstance().getManager().trust.getTrustees(v);
|
||||||
|
String damager = e.getDamager().getUniqueId().toString();
|
||||||
|
|
||||||
|
if (trustees.contains(damager)) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.getDamager() instanceof AreaEffectCloud aoe && aoe.getOwnerUniqueId() != null) {
|
||||||
|
if (trustees.contains(aoe.getOwnerUniqueId().toString())) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,7 +51,7 @@ public class ArmorBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean upTier(OfflinePlayer target) {
|
public boolean upTier(OfflinePlayer target) {
|
||||||
int numeric = storage.userData.playerTiers.get(target.getUniqueId().toString()).getNumeric();
|
int numeric = storage.userData.playerTiers.computeIfAbsent(target.getUniqueId().toString(),tier->ArmorTier.NONE).getNumeric();
|
||||||
Verbose.send("Upgrading %s, current numeric: %s",target.getName(),numeric);
|
Verbose.send("Upgrading %s, current numeric: %s",target.getName(),numeric);
|
||||||
if (numeric > 4) return false;
|
if (numeric > 4) return false;
|
||||||
numeric++;
|
numeric++;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import io.github.itzispyder.pdk.utils.misc.Randomizer;
|
|||||||
import me.trouper.armorsmp.ArmorSMP;
|
import me.trouper.armorsmp.ArmorSMP;
|
||||||
import me.trouper.armorsmp.data.io.IO;
|
import me.trouper.armorsmp.data.io.IO;
|
||||||
import me.trouper.armorsmp.utils.Text;
|
import me.trouper.armorsmp.utils.Text;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public class Broadcaster {
|
public class Broadcaster {
|
||||||
|
|
||||||
@@ -15,6 +16,9 @@ public class Broadcaster {
|
|||||||
|
|
||||||
public void broadcastTip() {
|
public void broadcastTip() {
|
||||||
String tip = new Randomizer().getRandomElement(io.config.tips.tipList);
|
String tip = new Randomizer().getRandomElement(io.config.tips.tipList);
|
||||||
ArmorSMP.getInstance().getServer().broadcast(Text.getMessage(false, Text.Pallet.NEUTRAL,tip));
|
for (Player onlinePlayer : ArmorSMP.getInstance().getServer().getOnlinePlayers()) {
|
||||||
|
if (ArmorSMP.getInstance().getManager().io.storage.userData.tipsDisabled.contains(onlinePlayer.getUniqueId().toString())) continue;
|
||||||
|
onlinePlayer.sendMessage(Text.getMessage(false, Text.Pallet.NEUTRAL,tip));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package me.trouper.armorsmp.server.systems;
|
package me.trouper.armorsmp.server.systems;
|
||||||
|
|
||||||
|
import me.trouper.armorsmp.ArmorSMP;
|
||||||
import me.trouper.armorsmp.data.io.IO;
|
import me.trouper.armorsmp.data.io.IO;
|
||||||
import me.trouper.armorsmp.data.io.Storage;
|
import me.trouper.armorsmp.data.io.Storage;
|
||||||
import me.trouper.armorsmp.data.Unique;
|
import me.trouper.armorsmp.data.Unique;
|
||||||
@@ -7,6 +8,8 @@ import org.bukkit.Bukkit;
|
|||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class UniquesBackend {
|
public class UniquesBackend {
|
||||||
|
|
||||||
private final Storage storage;
|
private final Storage storage;
|
||||||
@@ -15,20 +18,22 @@ public class UniquesBackend {
|
|||||||
storage = io.storage;
|
storage = io.storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateUniques(Player p) {
|
private void updateUniques() {
|
||||||
if (!storage.uniques.owners.containsValue(p.getUniqueId().toString())) return;
|
ArmorSMP.getInstance().getServer().getOnlinePlayers().forEach(this::updateUniques);
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
}
|
||||||
|
|
||||||
|
public void updateUniques(Player p) {
|
||||||
|
ArmorSMP.getInstance().getManager().io.storage.uniques.owners.forEach(((unique, id) -> {
|
||||||
|
if (id.equals(p.getUniqueId().toString())) {
|
||||||
|
if (!p.getInventory().contains(unique.getInGameItem())) p.getInventory().addItem(unique.getInGameItem());
|
||||||
|
} else {
|
||||||
|
p.getInventory().removeItemAnySlot(unique.getInGameItem());
|
||||||
}
|
}
|
||||||
storage.uniques.owners.forEach((unique,owner)->{
|
}));
|
||||||
if (unique.equals(Unique.MACE) || unique.equals(Unique.SWORD) || unique.equals(Unique.AXE) && owner.equals(p.getUniqueId().toString()) && !p.getInventory().contains(unique.getInGameItem())) {
|
|
||||||
p.getInventory().addItem(unique.getInGameItem());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void queueUpdate(OfflinePlayer target) {
|
public void queueUpdate(OfflinePlayer target) {
|
||||||
if (target.getPlayer() != null && target.isOnline()) updateUniques(target.getPlayer());
|
if (target.getPlayer() != null && target.isOnline()) updateUniques();
|
||||||
else storage.uniqueUpdateCache.add(target.getUniqueId().toString());
|
else storage.uniqueUpdateCache.add(target.getUniqueId().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,3 +19,7 @@ commands:
|
|||||||
aliases:
|
aliases:
|
||||||
- asmp
|
- asmp
|
||||||
- armor_smp
|
- armor_smp
|
||||||
|
ability:
|
||||||
|
description: Utilize unique abilities.
|
||||||
|
aliases:
|
||||||
|
- a
|
||||||
Reference in New Issue
Block a user