Testing begins! Made armor updating not transfer unique enchantments, added functionality from command TODO.

Unique transfers when picked up now, need to implement drop notifications.
This commit is contained in:
thetrouper
2025-03-27 01:48:02 -05:00
parent 352c77449b
commit d54f340e2d
28 changed files with 494 additions and 193 deletions

Binary file not shown.

View File

@@ -6,3 +6,16 @@ prefix: ArmorSMP
load: STARTUP
authors: [ obvWolf ]
description: Kill Based Armor Upgrading
commands:
trust:
description: Make your friends immune to your abilities.
usage: "<add|remove|list> <target>"
aliases:
- t
armorsmp:
permission: op
description: Root command for giving items, everything is handled though alias labels.
usage: "/asmp usage"
aliases:
- asmp
- armor_smp

View File

@@ -10,15 +10,20 @@ public final class ArmorSMP extends JavaPlugin {
private Manager manager;
@Override
public void onEnable() {
getLogger().info("Initializing PDK");
PDK.init(this);
public void onLoad() {
getLogger().info("Instantiating Plugin");
instance = this;
getLogger().info("Initializing Manager");
manager = new Manager().init();
manager = new Manager();
}
@Override
public void onEnable() {
getLogger().info("Initializing PDK");
PDK.init(this);
manager.init();
}
@Override

View File

@@ -2,6 +2,7 @@ package me.trouper.armorsmp.data;
import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.utils.Verbose;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
@@ -18,90 +19,110 @@ public enum ArmorTier {
ItemBuilder.create()
.material(Material.LEATHER_HELMET)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.LEATHER_CHESTPLATE)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.LEATHER_LEGGINGS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.LEATHER_BOOTS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build()
),
CHAINMAIL(2,
ItemBuilder.create()
.material(Material.CHAINMAIL_HELMET)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.CHAINMAIL_CHESTPLATE)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.CHAINMAIL_LEGGINGS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.CHAINMAIL_BOOTS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build()
),
GOLD(3,
ItemBuilder.create()
.material(Material.GOLDEN_HELMET)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.GOLDEN_CHESTPLATE)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.GOLDEN_LEGGINGS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.GOLDEN_BOOTS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build()
),
IRON(4,
ItemBuilder.create()
.material(Material.IRON_HELMET)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.IRON_CHESTPLATE)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.IRON_LEGGINGS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.IRON_BOOTS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build()
),
DIAMOND(5,
ItemBuilder.create()
.material(Material.DIAMOND_HELMET)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.DIAMOND_CHESTPLATE)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.DIAMOND_LEGGINGS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build(),
ItemBuilder.create()
.material(Material.DIAMOND_BOOTS)
.enchant(Enchantment.BINDING_CURSE, 1)
.unbreakable(true)
.build()
);
@@ -120,10 +141,14 @@ public enum ArmorTier {
}
public static ArmorTier getTier(int numeric) {
Verbose.send("Getting tier for numeric %s",numeric);
for (ArmorTier value : values()) {
if (value.getNumeric() == numeric) return value;
if (value.getNumeric() < 1) return NONE;
if (value.getNumeric() > 5) return DIAMOND;
if (value.getNumeric() == numeric) {
Verbose.send("Matched %s to %s",numeric, value);
return value;
}
if (value.getNumeric() < 0) throw new IllegalArgumentException("Armor tier must be a value 0-5");
if (value.getNumeric() > 5) throw new IllegalArgumentException("Armor tier must be a value 0-5");
}
return NONE;
}

View File

@@ -19,15 +19,16 @@ public class Storage implements JsonSerializable<Storage> {
public UserData userData = new UserData();
public Uniques uniques = new Uniques();
public Map<String,Boolean> updateCache = new ConcurrentHashMap<>();
public Map<String,Boolean> armorUpdateCache = new ConcurrentHashMap<>();
public Set<String> uniqueUpdateCache = new HashSet<>();
public class Uniques {
public Map<Unique, String> owners = new HashMap<>();
public Map<Unique, String> owners = new ConcurrentHashMap<>();
}
public class UserData {
public Set<String> tipsDisabled = new HashSet<>();
public Map<String, ArmorTier> playerTiers = new HashMap<>();
public Map<String, ArmorTier> playerTiers = new ConcurrentHashMap<>();
public Map<String, Set<String>> playerTrust = new HashMap<>();
}
}

View File

@@ -19,8 +19,8 @@ public enum Unique {
.enchant(Enchantment.RESPIRATION,3)
.enchant(Enchantment.AQUA_AFFINITY,1)
.customModelData(2)
.build()
),
.build(),
"Netherite Helmet"),
CHESTPLATE(ItemBuilder.create()
.material(Material.NETHERITE_CHESTPLATE)
.lore(Text.legacyColor("&bAbilities:"))
@@ -32,8 +32,8 @@ public enum Unique {
.enchant(Enchantment.UNBREAKING,3)
.enchant(Enchantment.MENDING,1)
.customModelData(3)
.build()
),
.build(),
"Dragon Egg"),
LEGGINGS(ItemBuilder.create()
.material(Material.NETHERITE_LEGGINGS)
.lore(Text.legacyColor("&bAbilities:"))
@@ -45,8 +45,8 @@ public enum Unique {
.enchant(Enchantment.MENDING,1)
.enchant(Enchantment.SWIFT_SNEAK,3)
.customModelData(4)
.build()
),
.build(),
"Netherite Leggings"),
BOOTS(ItemBuilder.create()
.material(Material.NETHERITE_BOOTS)
.lore(Text.legacyColor("&bAbilities:"))
@@ -60,27 +60,27 @@ public enum Unique {
.enchant(Enchantment.FEATHER_FALLING,4)
.enchant(Enchantment.DEPTH_STRIDER,3)
.customModelData(5)
.build()
),
.build(),
"Netherite Boots"),
MACE(ItemBuilder.create()
.material(Material.MACE)
.lore(Text.legacyColor("&bAbilities:"))
.lore(Text.legacyColor("&3| &7Speed 1"))
.enchant(Enchantment.UNBREAKING,1)
.enchant(Enchantment.UNBREAKING,3)
.enchant(Enchantment.WIND_BURST,2)
.enchant(Enchantment.DENSITY,3)
.enchant(Enchantment.MENDING,1)
.customModelData(6)
.build()
),
.build(),
"Mace"),
SWORD(ItemBuilder.create()
.material(Material.NETHERITE_SWORD)
.enchant(Enchantment.UNBREAKING,3)
.enchant(Enchantment.MENDING,1)
.enchant(Enchantment.SHARPNESS,5)
.customModelData(7)
.build()
),
.build(),
"Netherite Sword"),
AXE(ItemBuilder.create()
.material(Material.NETHERITE_AXE)
.enchant(Enchantment.UNBREAKING,3)
@@ -88,39 +88,37 @@ public enum Unique {
.enchant(Enchantment.SHARPNESS,5)
.enchant(Enchantment.EFFICIENCY,5)
.customModelData(8)
.build()
),
PICKAXE(ItemBuilder.create()
.material(Material.NETHERITE_PICKAXE)
.enchant(Enchantment.UNBREAKING,3)
.enchant(Enchantment.MENDING,1)
.enchant(Enchantment.EFFICIENCY,5)
.customModelData(9)
.build()
),
SHOVEL(ItemBuilder.create()
.material(Material.NETHERITE_SHOVEL)
.enchant(Enchantment.UNBREAKING,3)
.enchant(Enchantment.MENDING,1)
.enchant(Enchantment.EFFICIENCY,5)
.customModelData(10)
.build()
),
HOE(ItemBuilder.create()
.material(Material.NETHERITE_HOE)
.enchant(Enchantment.UNBREAKING,3)
.enchant(Enchantment.MENDING,1)
.enchant(Enchantment.EFFICIENCY,5)
.customModelData(11)
.build()
);
private ItemStack inGame;
.build(),
"Netherite Axe");
Unique(ItemStack inGame) {
private final ItemStack inGame;
private final String canonical;
Unique(ItemStack inGame, String canonical) {
this.inGame = inGame;
this.canonical = canonical;
}
public ItemStack getInGameItem() {
return inGame;
}
public static boolean isUnique(ItemStack i) {
for (Unique value : values()) {
if (value.getInGameItem().isSimilar(i)) return true;
}
return false;
}
public static Unique matchUnique(ItemStack i) {
Unique match = null;
for (Unique value : values()) {
if (value.getInGameItem().isSimilar(i)) match = value;
}
return match;
}
public String getCanonical() {
return canonical;
}
}

View File

@@ -5,54 +5,49 @@ import me.trouper.armorsmp.data.IO;
import me.trouper.armorsmp.server.commands.AdminCommand;
import me.trouper.armorsmp.server.commands.TrustCommand;
import me.trouper.armorsmp.server.crafting.ArmorUpgrade;
import me.trouper.armorsmp.server.events.CraftEvent;
import me.trouper.armorsmp.server.events.*;
import me.trouper.armorsmp.server.systems.ArmorBackend;
import me.trouper.armorsmp.server.systems.TrustBackend;
import me.trouper.armorsmp.server.systems.UniquesBackend;
public class Manager {
// My systems
public IO io;
public ArmorBackend armor;
public TrustBackend trust;
// Commands
public AdminCommand adminCommand;
public TrustCommand trustCommand;
// Events
public CraftEvent craftEvent;
public UniquesBackend uniques;
public Manager() {
io = new IO(); // IO must come as the first.
armor = new ArmorBackend();
trust = new TrustBackend();
io = new IO();
adminCommand = new AdminCommand();
trustCommand = new TrustCommand();
craftEvent = new CraftEvent();
armor = new ArmorBackend(io);
trust = new TrustBackend(io);
uniques = new UniquesBackend(io);
}
public Manager init() {
public void init() {
ArmorSMP.getInstance().getLogger().info("Loading all IO Files");
io.loadAll();
registerCommands();
registerEvents();
registerCrafting();
return this;
}
private void registerEvents() {
ArmorSMP.getInstance().getLogger().info("Registering Events");
craftEvent.register();
new CraftEvents().register();
new DeathEvents().register();
new JoinEvent().register();
new UpgradeRedeemEvent().register();
new PickUpEvent().register();
}
private void registerCommands() {
ArmorSMP.getInstance().getLogger().info("Registering Commands");
adminCommand.register();
trustCommand.register();
new AdminCommand().register();
new TrustCommand().register();
}
private void registerCrafting() {

View File

@@ -7,6 +7,7 @@ import io.github.itzispyder.pdk.commands.Permission;
import io.github.itzispyder.pdk.commands.completions.CompletionBuilder;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.ArmorTier;
import me.trouper.armorsmp.data.Config;
import me.trouper.armorsmp.data.Unique;
import me.trouper.armorsmp.server.crafting.ArmorUpgrade;
import me.trouper.armorsmp.utils.Text;
@@ -66,7 +67,7 @@ public class AdminCommand implements CustomCommand {
}
Player target = Bukkit.getPlayer(args.get(2).toString());
if (target == null) {
Text.sendError(sender, "Player not found or offline.");
Text.sendError(sender, "Player not found online.");
return;
}
@@ -74,42 +75,29 @@ public class AdminCommand implements CustomCommand {
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Given and Upgrader to {0}",target.getName());
}
case "netherite" -> {
case "unique" -> {
if (args.getSize() < 4) {
Text.sendError(sender, "Usage: /armorsmp give netherite <piece> <player>");
Text.sendError(sender, "Usage: /armorsmp give unique <piece> <player>");
return;
}
final Unique piece = args.get(2).toEnum(Unique.class);
if (piece == null) {
Text.sendMessage(false, Text.Pallet.ERROR,sender,"Error: {0} is not a valid Netherite piece.",args.get(2).toString());
Text.sendMessage(false, Text.Pallet.ERROR,sender,"Error: {0} is not a valid unique piece.",args.get(2).toString());
return;
}
Player target = Bukkit.getPlayer(args.get(3).toString());
OfflinePlayer target = Bukkit.getPlayer(args.get(3).toString());
if (target == null) {
Text.sendError(sender, "Player not found or offline.");
Text.sendError(sender, "Player not found online or offline.");
return;
}
// TODO: Handle netherite stuff
ArmorSMP.getInstance().getManager().uniques.setOwner(piece,target);
ArmorSMP.getInstance().getManager().armor.queueUpdate(target,true);
ArmorSMP.getInstance().getManager().uniques.queueUpdate(target);
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Given {0} to {1}",piece.name().toLowerCase(), target.getName());
}
case "mace" -> {
if (args.getSize() < 3) {
Text.sendError(sender, "Usage: /armorsmp give mace <player>");
return;
}
Player target = Bukkit.getPlayer(args.get(2).toString());
if (target == null) {
Text.sendError(sender, "Player not found or offline.");
return;
}
// TODO: handle Mace stuff
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Given {0} to {1}","mace",target.getName());
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Set the owner of unique {0} to {1}.",piece.getCanonical(), target.getName());
}
default -> Text.sendError(sender, "Invalid give type! Valid types: upgrader, netherite, mace");
}
@@ -119,25 +107,54 @@ public class AdminCommand implements CustomCommand {
Text.sendError(sender, "Usage: /armorsmp toggle <end|nether|mace>");
return;
}
final String feature = args.get(1).toString().toLowerCase();
// TODO: toggles
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Toggled the {0}",feature);
Config config = ArmorSMP.getInstance().getManager().io.config;
String feature = args.get(1).toString().toLowerCase();
boolean result = false;
switch (feature) {
case "end" -> {
config.endEnabled = result = !config.endEnabled;
config.save();
feature = "The End";
}
case "nether" -> {
config.netherEnabled = result = !config.netherEnabled;
config.save();
feature = "The Nether";
}
case "mace" -> {
config.maceCraftingEnabled = result = !config.maceCraftingEnabled;
config.save();
feature = "Mace Crafting";
}
case "debug" -> {
config.debugMode = result = !config.debugMode;
config.save();
feature = "Debug Mode";
}
}
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Toggled {0} {1}.",feature,result ? "on" : "off");
}
case "reset" -> {
if (args.getSize() < 2 || !args.get(1).toString().equalsIgnoreCase("mace")) {
Text.sendError(sender, "Usage: /armorsmp reset mace");
return;
}
// TODO: mace reset
ArmorSMP.getInstance().getManager().io.storage.uniques.owners.remove(Unique.MACE);
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Reset Mace");
}
case "remove" -> {
final String type = args.get(1).toString().toLowerCase();
switch (type) {
case "netherite" -> {
case "unique" -> {
if (args.getSize() < 4) {
Text.sendError(sender, "Usage: /armorsmp remove <piece> <player>");
Text.sendError(sender, "Usage: /armorsmp remove unique <piece> <player>");
return;
}
final Unique piece = args.get(2).toEnum(Unique.class);
@@ -148,8 +165,11 @@ public class AdminCommand implements CustomCommand {
return;
}
// TODO: armor removal
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Removed {0} from {1}", piece.name().toLowerCase(), target.getName());
ArmorSMP.getInstance().getManager().io.storage.uniques.owners.remove(piece);
ArmorSMP.getInstance().getManager().armor.queueUpdate(target,true);
ArmorSMP.getInstance().getManager().uniques.queueUpdate(target);
Text.sendMessage(false, Text.Pallet.SUCCESS, sender, "Removed {0} from {1}", piece.getCanonical(), target.getName());
}
default -> Text.sendError(sender, "Invalid give type! Valid types: netherite");
}
@@ -167,21 +187,19 @@ public class AdminCommand implements CustomCommand {
b.arg("give")
.then(b.arg("upgrader")
.then(b.argOnlinePlayers()))
.then(b.arg("netherite")
.then(b.arg("unique")
.then(b.argEnum(Unique.class)
.then(b.argOnlinePlayers())))
.then(b.arg("mace")
.then(b.argOnlinePlayers()))
).then(
b.arg("reset")
.then(b.arg("mace"))
).then(
b.arg("remove")
.then(b.arg("netherite")
.then(b.arg("unique")
.then(b.argEnum(Unique.class)
.then(b.argOnlinePlayers())))
).then(b.arg("toggle")
.then(b.arg("end","nether","mace")));
.then(b.arg("end","nether","mace","debug")));
}

View File

@@ -61,6 +61,10 @@ public class TrustCommand implements CustomCommand {
Text.sendError(sender, "Player not found online or offline.");
return;
}
if (trustee.getUniqueId().equals(((Player) sender).getUniqueId())) {
Text.sendError(sender, "You do not want to un-trust yourself. It will break the code ;-;");
return;
}
if (ArmorSMP.getInstance().getManager().trust.removeTrust((Player) sender,trustee.getUniqueId())) {
Text.sendMessage(true, Text.Pallet.SUCCESS,sender,"Successfully un-trusted {0}.",target);

View File

@@ -9,9 +9,10 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.PrepareSmithingEvent;
import org.bukkit.inventory.ItemStack;
public class CraftEvent implements CustomListener {
public class CraftEvents implements CustomListener {
@EventHandler
public void onCraft(CraftItemEvent e) {
@@ -24,9 +25,16 @@ public class CraftEvent implements CustomListener {
if (result.getType().equals(Material.MACE)) {
if (!ArmorSMP.getInstance().getManager().io.config.maceCraftingEnabled) {
e.setCancelled(true);
p.closeInventory();
Text.sendWarning(p,"You are not allowed to craft {0}. Mace crafting is disabled.",name);
return;
}
if (ArmorSMP.getInstance().getManager().io.storage.uniques.owners.containsKey(Unique.MACE)) {
e.setCancelled(true);
p.closeInventory();
Text.sendWarning(p,"You are not allowed to craft {0}. It has already been crafted.",name);
return;
}
result.addEnchantments(Unique.MACE.getInGameItem().getEnchantments());
@@ -36,16 +44,7 @@ public class CraftEvent implements CustomListener {
return;
}
if (!name.contains("HELMET")
&& !name.contains("CHESTPLATE")
&& !name.contains("LEGGINGS")
&& !name.contains("BOOTS")
&& !name.contains("NETHERITE_SWORD")
&& !name.contains("NETHERITE_PICKAXE")
&& !name.contains("NETHERITE_AXE")
&& !name.contains("NETHERITE_SHOVEL")
&& !name.contains("NETHERITE_HOE")
) return;
if (isUnique(result)) return;
Verbose.send("%s Attempted to craft a disabled item.", p.getName());
@@ -53,4 +52,15 @@ public class CraftEvent implements CustomListener {
p.closeInventory();
Text.sendWarning(p,"You are not allowed to craft {0}.",name);
}
private boolean isUnique(ItemStack item) {
return isUnique(item.getType());
}
private boolean isUnique(Material m) {
for (Unique unique : Unique.values()) {
if (unique.getInGameItem().getType().equals(m)) return true;
}
return false;
}
}

View File

@@ -1,21 +0,0 @@
package me.trouper.armorsmp.server.events;
import io.github.itzispyder.pdk.events.CustomListener;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.ArmorTier;
import me.trouper.armorsmp.server.crafting.ArmorUpgrade;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.PlayerDeathEvent;
public class DeathEvent implements CustomListener {
@EventHandler
public void onDeath(PlayerDeathEvent e) {
Player p = e.getEntity();
final ArmorTier tier = ArmorSMP.getInstance().getManager().armor.getTier(p);
if (tier.equals(ArmorTier.NONE)) return;
if (ArmorSMP.getInstance().getManager().armor.downTier(p)) {
e.getDrops().add(ArmorUpgrade.ARMOR_UGPRADE);
}
}
}

View File

@@ -0,0 +1,45 @@
package me.trouper.armorsmp.server.events;
import io.github.itzispyder.pdk.events.CustomListener;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.ArmorTier;
import me.trouper.armorsmp.server.crafting.ArmorUpgrade;
import me.trouper.armorsmp.utils.Text;
import me.trouper.armorsmp.utils.Verbose;
import me.trouper.armorsmp.utils.WorldUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.ItemStack;
public class DeathEvents implements CustomListener {
@EventHandler
public void onDeath(PlayerDeathEvent e) {
Player p = e.getEntity();
final ArmorTier tier = ArmorSMP.getInstance().getManager().armor.getTier(p);
Verbose.send("Handling death event for %s, their tier is %s",p.getName(),tier);
e.getDrops().removeIf(WorldUtils::isDroppable);
if (tier.equals(ArmorTier.NONE)) {
Verbose.send("Tier was none");
Text.sendMessage(true, Text.Pallet.INFO,p,"You have died! Since you were at tier {0}, you didn't drop an Armor Upgrader.",tier);
return;
}
if (ArmorSMP.getInstance().getManager().armor.downTier(p)) {
Verbose.send("They have been down-tiered");
e.getDrops().add(ArmorUpgrade.ARMOR_UGPRADE);
e.deathMessage(Text.getMessage(false, Text.Pallet.INFO,"{0} has died, and dropped an {1}!", LegacyComponentSerializer.legacyAmpersand().serialize(p.name()),"Armor Upgrader"));
}
ArmorSMP.getInstance().getManager().armor.dropUniqueArmor(p);
ArmorSMP.getInstance().getManager().uniques.dropUniqueItems(p);
}
@EventHandler
public void onRespawn(PlayerRespawnEvent e) {
ArmorSMP.getInstance().getManager().armor.queueUpdate(e.getPlayer(),false);
}
}

View File

@@ -2,15 +2,43 @@ package me.trouper.armorsmp.server.events;
import io.github.itzispyder.pdk.events.CustomListener;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.ArmorTier;
import me.trouper.armorsmp.utils.Verbose;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class JoinEvent implements CustomListener {
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
if (ArmorSMP.getInstance().getManager().io.storage.updateCache.containsKey(e.getPlayer().getUniqueId().toString())) {
ArmorSMP.getInstance().getManager().armor.updateArmor(p,ArmorSMP.getInstance().getManager().io.storage.updateCache.get(p.getUniqueId().toString()));
ArmorSMP.getInstance().getManager().io.storage.updateCache.remove(p.getUniqueId().toString());
initPlayer(p);
handleUpdates(p);
}
private void initPlayer(Player p) {
ArmorSMP.getInstance().getManager().io.storage.userData.playerTiers.putIfAbsent(p.getUniqueId().toString(), ArmorTier.NONE);
ArmorSMP.getInstance().getManager().io.storage.userData.playerTrust.putIfAbsent(p.getUniqueId().toString(), new HashSet<>(Set.of(p.getUniqueId().toString())));
}
private void handleUpdates(Player p) {
Verbose.send("Checking for updates needed on %s",p.getName());
final Map<String, Boolean> armorCache = ArmorSMP.getInstance().getManager().io.storage.armorUpdateCache;
if (armorCache.containsKey(p.getUniqueId().toString()) || !ArmorSMP.getInstance().getManager().armor.verifyArmor(p)) {
Verbose.send("Updating armor");
ArmorSMP.getInstance().getManager().armor.queueUpdate(p,armorCache.get(p.getUniqueId().toString()));
ArmorSMP.getInstance().getManager().io.storage.armorUpdateCache.remove(p.getUniqueId().toString());
}
final Set<String> uniquesCache = ArmorSMP.getInstance().getManager().io.storage.uniqueUpdateCache;
if (uniquesCache.contains(p.getUniqueId().toString())) {
Verbose.send("Updating uniques");
ArmorSMP.getInstance().getManager().uniques.queueUpdate(p);
ArmorSMP.getInstance().getManager().io.storage.uniqueUpdateCache.remove(p.getUniqueId().toString());
}
}
}

View File

@@ -0,0 +1,32 @@
package me.trouper.armorsmp.server.events;
import io.github.itzispyder.pdk.events.CustomListener;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.Unique;
import me.trouper.armorsmp.utils.Text;
import me.trouper.armorsmp.utils.WorldUtils;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.inventory.ItemStack;
public class PickUpEvent implements CustomListener {
@EventHandler
public void onItemPickUp(EntityPickupItemEvent e) {
if (!(e.getEntity() instanceof Player p)) return;
ItemStack i = e.getItem().getItemStack();
if (!Unique.isUnique(i)) return;
Unique match = Unique.matchUnique(i);
ArmorSMP.getInstance().getManager().uniques.setOwner(match,p);
Text.sendMessage(true, Text.Pallet.INFO,p,"Congratulations! You have picked up the unique {0}. There is only one of each in the whole server!",match.getCanonical());
ArmorSMP.getInstance().getServer().broadcast(Text.getMessage(false, Text.Pallet.INFO,"GG, {0}! They are the new owner of the unique {1}",p.getName(),match.getCanonical()));
if (WorldUtils.isArmor(match.getInGameItem())) {
p.getInventory().remove(i);
ArmorSMP.getInstance().getManager().armor.queueUpdate(p,true);
}
}
}

View File

@@ -6,18 +6,21 @@ import me.trouper.armorsmp.data.ArmorTier;
import me.trouper.armorsmp.server.crafting.ArmorUpgrade;
import me.trouper.armorsmp.utils.Text;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
public class UpgradeRedeemEvent implements CustomListener {
@EventHandler
public void onClick(PlayerInteractEvent e) {
Player p = e.getPlayer();
ItemStack holding = e.getItem();
final ArmorTier tier = ArmorSMP.getInstance().getManager().armor.getTier(p);
if (holding == null || holding.isEmpty()) return;
if (!holding.equals(ArmorUpgrade.ARMOR_UGPRADE)) return;
if (!holding.isSimilar(ArmorUpgrade.ARMOR_UGPRADE)) return;
final ArmorTier tier = ArmorSMP.getInstance().getManager().armor.getTier(p);
if (ArmorSMP.getInstance().getManager().armor.upTier(p)) {
holding.setAmount(holding.getAmount() - 1);

View File

@@ -2,6 +2,7 @@ package me.trouper.armorsmp.server.systems;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.ArmorTier;
import me.trouper.armorsmp.data.IO;
import me.trouper.armorsmp.data.Storage;
import me.trouper.armorsmp.data.Unique;
import me.trouper.armorsmp.utils.Verbose;
@@ -11,14 +12,15 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
public class ArmorBackend {
private final Storage storage;
public ArmorBackend() {
storage = ArmorSMP.getInstance().getManager().io.storage;
public ArmorBackend(IO io) {
storage = io.storage;
}
public boolean shouldTransferEnchants(OfflinePlayer target, ArmorTier request) {
@@ -33,52 +35,80 @@ public class ArmorBackend {
public void setTier(OfflinePlayer target, ArmorTier tier, boolean transferEnchants) {
Verbose.send("Setting tier of %s to %s",target.getName(),tier);
storage.userData.playerTiers.put(target.getUniqueId().toString(),tier);
if (target.getPlayer() != null && target.isOnline()) updateArmor(target.getPlayer(), transferEnchants);
else storage.updateCache.put(target.getUniqueId().toString(),transferEnchants);
storage.save();
queueUpdate(target,transferEnchants);
}
public boolean downTier(OfflinePlayer target) {
final int numeric = storage.userData.playerTiers.get(target.getUniqueId().toString()).getNumeric();
int numeric = storage.userData.playerTiers.get(target.getUniqueId().toString()).getNumeric();
Verbose.send("Downgrading %s, current numeric: %s",target.getName(),numeric);
if (numeric < 0) return false;
numeric--;
ArmorTier tier = ArmorTier.getTier(numeric);
Verbose.send("New numeric is %s, tier: %s",numeric,tier);
setTier(target,ArmorTier.getTier(numeric - 1),true);
return false;
setTier(target,tier,true);
return true;
}
public boolean upTier(OfflinePlayer target) {
final int numeric = storage.userData.playerTiers.get(target.getUniqueId().toString()).getNumeric();
int numeric = storage.userData.playerTiers.get(target.getUniqueId().toString()).getNumeric();
Verbose.send("Upgrading %s, current numeric: %s",target.getName(),numeric);
if (numeric > 4) return false;
numeric++;
ArmorTier tier = ArmorTier.getTier(numeric);
Verbose.send("New numeric is %s, tier: %s",numeric,tier);
setTier(target,ArmorTier.getTier(numeric + 1),false);
setTier(target,tier,true);
return true;
}
public ArmorTier getTier(OfflinePlayer target) {
Verbose.send("Getting tier of %s", target.getName());
return storage.userData.playerTiers.getOrDefault(target.getUniqueId().toString(),ArmorTier.NONE);
ArmorTier tier = storage.userData.playerTiers.getOrDefault(target.getUniqueId().toString(),ArmorTier.NONE);
Verbose.send("Got tier of %s: %s", target.getName(),tier);
return tier;
}
public boolean verifyArmor(Player p) {
PlayerInventory e = p.getInventory();
final ArmorTier tier = getTier(p);
public boolean verifyArmor(Player target) {
Verbose.send("Verifying armor of %s", target.getName());
PlayerInventory e = target.getInventory();
final ArmorTier tier = getTier(target);
final Material correctHelmet = tier.getHelmet().getType();
final Material correctChestplate = tier.getChestplate().getType();
final Material correctLeggings = tier.getLeggings().getType();
final Material correctBoots = tier.getBoots().getType();
Verbose.send("""
Correct Gear:
%s
%s
%s
%s
""", correctHelmet,correctChestplate,correctLeggings,correctBoots
);
final Material helmet = e.getHelmet() == null ? Material.AIR : e.getHelmet().getType() == Material.NETHERITE_HELMET ? correctHelmet : e.getHelmet().getType();
final Material chestplate = e.getChestplate() == null ? Material.AIR : e.getChestplate().getType() == Material.NETHERITE_CHESTPLATE ? correctChestplate : e.getChestplate().getType();
final Material leggings = e.getLeggings() == null ? Material.AIR : e.getLeggings().getType() == Material.NETHERITE_LEGGINGS ? correctLeggings : e.getLeggings().getType();
final Material boots = e.getBoots() == null ? Material.AIR : e.getBoots().getType() == Material.NETHERITE_BOOTS ? correctBoots : e.getBoots().getType();
Verbose.send("""
Equipped Gear:
%s
%s
%s
%s
""", helmet,chestplate,leggings,boots
);
return helmet.equals(correctHelmet) && chestplate.equals(correctChestplate) && leggings.equals(correctLeggings) && boots.equals(correctBoots);
}
public void updateArmor(Player p, boolean transferEnchants) {
PlayerInventory e = p.getInventory();
final ArmorTier tier = getTier(p);
private void updateArmor(Player target, boolean transferEnchants) {
Verbose.send("Updating the armor of %s",target.getName());
PlayerInventory e = target.getInventory();
final ArmorTier tier = getTier(target);
Verbose.send("Tier is %s",tier);
final ItemStack helmet = e.getHelmet();
final ItemStack chestplate = e.getChestplate();
@@ -90,6 +120,9 @@ public class ArmorBackend {
e.setChestplate(new ItemStack(Material.AIR));
e.setLeggings(new ItemStack(Material.AIR));
e.setBoots(new ItemStack(Material.AIR));
updateUniqueArmor(target);
Verbose.send("Returning to prevent NPE");
return;
}
@@ -100,28 +133,61 @@ public class ArmorBackend {
if (transferEnchants) {
if (helmet != null) updatedHelmet.get().addEnchantments(helmet.getEnchantments());
if (chestplate != null) updatedChestplate.get().addEnchantments(chestplate.getEnchantments());
if (leggings != null) updatedLeggings.get().addEnchantments(leggings.getEnchantments());
if (boots != null) updatedBoots.get().addEnchantments(boots.getEnchantments());
}
if (storage.uniques.owners.containsValue(p.getUniqueId().toString())) {
storage.uniques.owners.forEach((unique,owner)->{
if (owner.equals(p.getUniqueId().toString())) {
if (unique.equals(Unique.HELMET)) updatedHelmet.set(unique.getInGameItem());
if (unique.equals(Unique.CHESTPLATE)) updatedChestplate.set(unique.getInGameItem());
if (unique.equals(Unique.LEGGINGS)) updatedLeggings.set(unique.getInGameItem());
if (unique.equals(Unique.BOOTS)) updatedBoots.set(unique.getInGameItem());
}
});
Verbose.send("Transfering enchants...");
if (helmet != null && !helmet.getType().name().contains("NETHERITE")) updatedHelmet.get().addEnchantments(helmet.getEnchantments());
if (chestplate != null && !chestplate.getType().name().contains("NETHERITE")) updatedChestplate.get().addEnchantments(chestplate.getEnchantments());
if (leggings != null && !leggings.getType().name().contains("NETHERITE")) updatedLeggings.get().addEnchantments(leggings.getEnchantments());
if (boots != null && !boots.getType().name().contains("NETHERITE")) updatedBoots.get().addEnchantments(boots.getEnchantments());
}
Verbose.send("Setting items...");
e.setHelmet(updatedHelmet.get());
e.setChestplate(updatedChestplate.get());
e.setLeggings(updatedLeggings.get());
e.setBoots(updatedBoots.get());
updateUniqueArmor(target);
Verbose.send("Update complete!");
}
private void updateUniqueArmor(Player target) {
PlayerInventory e = target.getInventory();
Verbose.send("Handling their unique armor...");
if (storage.uniques.owners.containsValue(target.getUniqueId().toString())) {
storage.uniques.owners.forEach((unique,owner)->{
if (owner.equals(target.getUniqueId().toString())) {
Verbose.send("They have the unique %s",unique);
if (unique.equals(Unique.HELMET)) e.setHelmet(unique.getInGameItem());
if (unique.equals(Unique.CHESTPLATE)) e.setChestplate(unique.getInGameItem());
if (unique.equals(Unique.LEGGINGS)) e.setLeggings(unique.getInGameItem());
if (unique.equals(Unique.BOOTS)) e.setBoots(unique.getInGameItem());
}
});
}
}
public void queueUpdate(OfflinePlayer target, boolean transferEnchants) {
Verbose.send("Queueing update for %s",target.getName());
if (target.getPlayer() != null && target.isOnline()) updateArmor(target.getPlayer(), transferEnchants);
else storage.armorUpdateCache.put(target.getUniqueId().toString(),transferEnchants);
}
public void dropUniqueArmor(Player target) {
final Map<Unique, String> uniques = storage.uniques.owners;
if (!uniques.containsValue(target.getUniqueId().toString())) return;
uniques.forEach((unique,owner)->{
if (owner.equals(target.getUniqueId().toString())) {
if (unique.equals(Unique.HELMET)
|| unique.equals(Unique.CHESTPLATE)
|| unique.equals(Unique.LEGGINGS)
|| unique.equals(Unique.BOOTS)
) {
storage.uniques.owners.remove(unique);
//target.getLocation().getWorld().dropItem(target.getLocation(),unique.getInGameItem());
}
}
});
}
}

View File

@@ -1,6 +1,7 @@
package me.trouper.armorsmp.server.systems;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.IO;
import me.trouper.armorsmp.data.Storage;
import org.bukkit.entity.Player;
@@ -11,8 +12,8 @@ import java.util.UUID;
public class TrustBackend {
private final Storage storage;
public TrustBackend() {
storage = ArmorSMP.getInstance().getManager().io.storage;
public TrustBackend(IO io) {
storage = io.storage;
}
public boolean addTrust(Player truster, UUID trustee) {

View File

@@ -0,0 +1,45 @@
package me.trouper.armorsmp.server.systems;
import me.trouper.armorsmp.ArmorSMP;
import me.trouper.armorsmp.data.IO;
import me.trouper.armorsmp.data.Storage;
import me.trouper.armorsmp.data.Unique;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
public class UniquesBackend {
private final Storage storage;
public UniquesBackend(IO io) {
storage = io.storage;
}
private void updateUniques(Player p) {
if (!storage.uniques.owners.containsValue(p.getUniqueId().toString())) return;
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) {
if (target.getPlayer() != null && target.isOnline()) updateUniques(target.getPlayer());
else storage.uniqueUpdateCache.add(target.getUniqueId().toString());
}
public void setOwner(Unique u, OfflinePlayer p) {
storage.uniques.owners.put(u,p.getUniqueId().toString());
queueUpdate(p);
}
public void dropUniqueItems(Player p) {
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())) {
storage.uniques.owners.remove(unique);
}
});
}
}

View File

@@ -52,11 +52,15 @@ public class Text {
} else {
allowTip = false;
}
Component message = getMessage(text, allowTip);
Component message = getMessage(allowTip,text);
sender.sendMessage(message);
}
public static Component getMessage(String text, boolean addFancyTip) {
public static Component getMessage(boolean addFancyTip, Pallet pallet, String text, Object... args) {
return getMessage(addFancyTip,formatArgs(pallet,text,args));
}
public static Component getMessage(boolean addFancyTip, String text) {
if (ArmorSMP.getInstance().getManager().io.config.fancyAlerts) {
return formatFancyMessage(text, addFancyTip);
} else {

View File

@@ -27,11 +27,11 @@ public class Verbose {
}
String formattedMessage = message.formatted(args);
String log = "[Sentinel] [DEBUG ^ %s] [%s]: %s".formatted(backtrace, callerInfo, formattedMessage);
String log = "[DEBUG ^ %s] [%s]: %s".formatted(backtrace, callerInfo, formattedMessage);
ArmorSMP.getInstance().getLogger().info(log);
for (Player operator : Bukkit.getOnlinePlayers()) {
if (operator.isOp()) operator.sendMessage("§d§lSentinel §7[§bDEBUG ^ %s§7] §7[§e%s§7] §8» §7%s"
if (operator.isOp()) operator.sendMessage("§d§lArmorSMP §7[§bDEBUG ^ %s§7] §7[§e%s§7] §8» §7%s"
.formatted(backtrace, callerInfo, formattedMessage));
}
}
@@ -57,11 +57,11 @@ public class Verbose {
}
String formattedMessage = message.formatted(args);
String log = "[Sentinel] [DEBUG] [%s]: %s".formatted(callerInfo, formattedMessage);
String log = "[DEBUG] [%s]: %s".formatted(callerInfo, formattedMessage);
ArmorSMP.getInstance().getLogger().info(log);
for (Player operator : Bukkit.getOnlinePlayers()) {
if (operator.isOp()) operator.sendMessage("§d§lSentinel §7[§bDEBUG§7] §7[§e%s§7] §8» §7%s"
if (operator.isOp()) operator.sendMessage("§d§lArmorSMP §7[§bDEBUG§7] §7[§e%s§7] §8» §7%s"
.formatted(callerInfo, formattedMessage));
}
}

View File

@@ -0,0 +1,29 @@
package me.trouper.armorsmp.utils;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public class WorldUtils {
public static boolean isDroppable(ItemStack i) {
return isArmor(i) && !isUnique(i);
}
public static boolean isArmor(ItemStack i) {
Material m = i.getType();
String n = m.name();
return n.contains("HELMET")
|| n.contains("CHESTPLATE")
|| n.contains("LEGGINGS")
|| n.contains("BOOTS");
}
public static boolean isUnique(ItemStack i) {
Material m = i.getType();
String n = m.name();
return n.contains("NETHERITE")
|| n.contains("MACE")
|| n.contains("NETHERITE_SWORD")
|| n.contains("NETHERITE_AXE");
}
}