|
| 1 | +package com.easyclaims.commands.subcommands.admin; |
| 2 | + |
| 3 | +import com.hypixel.hytale.component.Ref; |
| 4 | +import com.hypixel.hytale.component.Store; |
| 5 | +import com.hypixel.hytale.server.core.Message; |
| 6 | +import com.hypixel.hytale.server.core.NameMatching; |
| 7 | +import com.hypixel.hytale.server.core.command.system.CommandContext; |
| 8 | +import com.hypixel.hytale.server.core.command.system.arguments.system.RequiredArg; |
| 9 | +import com.hypixel.hytale.server.core.command.system.arguments.types.ArgTypes; |
| 10 | +import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand; |
| 11 | +import com.hypixel.hytale.server.core.universe.PlayerRef; |
| 12 | +import com.hypixel.hytale.server.core.universe.Universe; |
| 13 | +import com.hypixel.hytale.server.core.universe.world.World; |
| 14 | +import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; |
| 15 | +import com.easyclaims.EasyClaims; |
| 16 | +import com.easyclaims.data.PlayerClaims; |
| 17 | +import com.easyclaims.data.PlaytimeData; |
| 18 | + |
| 19 | +import javax.annotation.Nonnull; |
| 20 | +import java.awt.Color; |
| 21 | +import java.util.UUID; |
| 22 | + |
| 23 | +/** |
| 24 | + * Shows detailed claim information for a player. |
| 25 | + * Works for online and offline players. |
| 26 | + * |
| 27 | + * Usage: /easyclaims admin info <player> |
| 28 | + * |
| 29 | + * Displays: |
| 30 | + * - Current claims / max claims |
| 31 | + * - Playtime hours |
| 32 | + * - Bonus claim slots (admin-granted) |
| 33 | + * - Bonus max claims (admin-granted) |
| 34 | + * - Unlimited claims status |
| 35 | + */ |
| 36 | +public class AdminInfoSubcommand extends AbstractPlayerCommand { |
| 37 | + private final EasyClaims plugin; |
| 38 | + private final RequiredArg<String> playerArg; |
| 39 | + |
| 40 | + private static final Color GREEN = new Color(85, 255, 85); |
| 41 | + private static final Color RED = new Color(255, 85, 85); |
| 42 | + private static final Color YELLOW = new Color(255, 255, 85); |
| 43 | + private static final Color GOLD = new Color(255, 170, 0); |
| 44 | + private static final Color GRAY = new Color(170, 170, 170); |
| 45 | + private static final Color AQUA = new Color(85, 255, 255); |
| 46 | + |
| 47 | + public AdminInfoSubcommand(EasyClaims plugin) { |
| 48 | + super("info", "View a player's claim statistics and bonuses"); |
| 49 | + this.plugin = plugin; |
| 50 | + this.playerArg = withRequiredArg("player", "Player name or UUID", ArgTypes.STRING); |
| 51 | + requirePermission("easyclaims.admin"); |
| 52 | + } |
| 53 | + |
| 54 | + @Override |
| 55 | + protected void execute(@Nonnull CommandContext ctx, |
| 56 | + @Nonnull Store<EntityStore> store, |
| 57 | + @Nonnull Ref<EntityStore> playerRef, |
| 58 | + @Nonnull PlayerRef playerData, |
| 59 | + @Nonnull World world) { |
| 60 | + String playerInput = playerArg.get(ctx); |
| 61 | + |
| 62 | + // Resolve player (online or offline) |
| 63 | + UUID targetId = null; |
| 64 | + String targetName = playerInput; |
| 65 | + boolean isOnline = false; |
| 66 | + |
| 67 | + // Try 1: Online player lookup by username |
| 68 | + PlayerRef targetPlayer = Universe.get().getPlayerByUsername(playerInput, NameMatching.EXACT_IGNORE_CASE); |
| 69 | + if (targetPlayer != null) { |
| 70 | + targetId = targetPlayer.getUuid(); |
| 71 | + targetName = targetPlayer.getUsername(); |
| 72 | + isOnline = true; |
| 73 | + } else { |
| 74 | + // Try 2: Parse as UUID (works for offline players) |
| 75 | + try { |
| 76 | + targetId = UUID.fromString(playerInput); |
| 77 | + String storedName = plugin.getClaimStorage().getPlayerName(targetId); |
| 78 | + if (storedName != null && !storedName.equals(targetId.toString().substring(0, 8))) { |
| 79 | + targetName = storedName; |
| 80 | + } |
| 81 | + } catch (IllegalArgumentException e) { |
| 82 | + // Try 3: Lookup by username in stored names |
| 83 | + targetId = plugin.getClaimStorage().getPlayerUUID(playerInput); |
| 84 | + if (targetId == null) { |
| 85 | + playerData.sendMessage(Message.raw("Player not found: " + playerInput).color(RED)); |
| 86 | + playerData.sendMessage(Message.raw("Use a UUID for players who have never claimed.").color(YELLOW)); |
| 87 | + return; |
| 88 | + } |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + // Get player data |
| 93 | + PlayerClaims claims = plugin.getClaimStorage().getPlayerClaims(targetId); |
| 94 | + PlaytimeData playtime = plugin.getPlaytimeStorage().getPlaytime(targetId); |
| 95 | + |
| 96 | + // Calculate stats |
| 97 | + int currentClaims = claims.getClaimCount(); |
| 98 | + int maxClaims = plugin.getClaimManager().getMaxClaims(targetId); |
| 99 | + double playtimeHours = playtime.getTotalHoursWithCurrentSession(); |
| 100 | + int bonusSlots = claims.getBonusClaimSlots(); |
| 101 | + int bonusMax = claims.getBonusMaxClaims(); |
| 102 | + boolean unlimited = claims.hasUnlimitedClaims(); |
| 103 | + |
| 104 | + // Server config values |
| 105 | + int serverStarting = plugin.getPluginConfig().getStartingClaims(); |
| 106 | + int serverMax = plugin.getPluginConfig().getMaxClaims(); |
| 107 | + double claimsPerHour = plugin.getPluginConfig().getClaimsPerHour(); |
| 108 | + |
| 109 | + // Calculate breakdown |
| 110 | + int fromPlaytime = (int) (playtimeHours * claimsPerHour); |
| 111 | + int baseMax = serverStarting + fromPlaytime; |
| 112 | + int cappedMax = Math.min(baseMax, serverMax + bonusMax); |
| 113 | + |
| 114 | + // Display header |
| 115 | + playerData.sendMessage(Message.raw("=== Claim Info: " + targetName + " ===").color(GOLD)); |
| 116 | + String status = isOnline ? " (online)" : " (offline)"; |
| 117 | + playerData.sendMessage(Message.raw("UUID: " + targetId.toString() + status).color(GRAY)); |
| 118 | + |
| 119 | + // Display claims |
| 120 | + String claimStatus = currentClaims + " / " + (unlimited ? "unlimited" : String.valueOf(maxClaims)); |
| 121 | + playerData.sendMessage(Message.raw("Claims: " + claimStatus).color(currentClaims >= maxClaims && !unlimited ? YELLOW : GREEN)); |
| 122 | + |
| 123 | + // Display playtime |
| 124 | + String playtimeStr = String.format("%.1f hours", playtimeHours); |
| 125 | + playerData.sendMessage(Message.raw("Playtime: " + playtimeStr).color(AQUA)); |
| 126 | + |
| 127 | + // Display max claims calculation breakdown |
| 128 | + playerData.sendMessage(Message.raw("--- Max Claims Breakdown ---").color(GRAY)); |
| 129 | + playerData.sendMessage(Message.raw(" Starting claims: " + serverStarting).color(GRAY)); |
| 130 | + playerData.sendMessage(Message.raw(" From playtime: +" + fromPlaytime + " (" + String.format("%.1f", playtimeHours) + "h x " + claimsPerHour + "/h)").color(GRAY)); |
| 131 | + playerData.sendMessage(Message.raw(" Base total: " + baseMax).color(GRAY)); |
| 132 | + |
| 133 | + if (!unlimited) { |
| 134 | + int effectiveCap = serverMax + bonusMax; |
| 135 | + playerData.sendMessage(Message.raw(" Cap: " + serverMax + " (server)" + (bonusMax > 0 ? " + " + bonusMax + " (bonus)" : "") + " = " + effectiveCap).color(GRAY)); |
| 136 | + playerData.sendMessage(Message.raw(" After cap: " + cappedMax).color(GRAY)); |
| 137 | + } |
| 138 | + |
| 139 | + // Display admin-granted bonuses |
| 140 | + playerData.sendMessage(Message.raw("--- Admin Bonuses ---").color(GOLD)); |
| 141 | + |
| 142 | + if (bonusSlots > 0) { |
| 143 | + playerData.sendMessage(Message.raw(" Bonus claim slots: +" + bonusSlots).color(GREEN)); |
| 144 | + } else { |
| 145 | + playerData.sendMessage(Message.raw(" Bonus claim slots: 0").color(GRAY)); |
| 146 | + } |
| 147 | + |
| 148 | + if (bonusMax > 0) { |
| 149 | + playerData.sendMessage(Message.raw(" Bonus max claims: +" + bonusMax).color(GREEN)); |
| 150 | + } else { |
| 151 | + playerData.sendMessage(Message.raw(" Bonus max claims: 0").color(GRAY)); |
| 152 | + } |
| 153 | + |
| 154 | + if (unlimited) { |
| 155 | + playerData.sendMessage(Message.raw(" Unlimited claims: YES").color(GOLD)); |
| 156 | + } else { |
| 157 | + playerData.sendMessage(Message.raw(" Unlimited claims: no").color(GRAY)); |
| 158 | + } |
| 159 | + |
| 160 | + // Final effective max |
| 161 | + if (!unlimited) { |
| 162 | + int effective = cappedMax + bonusSlots; |
| 163 | + playerData.sendMessage(Message.raw("Effective max: " + effective + " (" + cappedMax + " + " + bonusSlots + " bonus slots)").color(AQUA)); |
| 164 | + } |
| 165 | + } |
| 166 | +} |
0 commit comments