Skip to content

Commit c260d79

Browse files
cryptobenchclaude
andcommitted
Refactor command system into subcommands
- Extract subcommands from monolithic EasyClaimsCommand - Add subcommands directory structure - Improve ClaimStorage with better data handling - Update PlayerClaims with enhanced functionality - Refactor map rendering components Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent e0beb15 commit c260d79

24 files changed

Lines changed: 1287 additions & 774 deletions

src/main/java/com/easyclaims/EasyClaims.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ public void shutdown() {
241241
playtimeManager.shutdown();
242242
}
243243

244-
// Save all claim data
244+
// Shutdown claim storage (flushes pending saves and stops background thread)
245245
if (claimStorage != null) {
246-
claimStorage.saveAll();
246+
claimStorage.shutdown();
247247
}
248248
}
249249

src/main/java/com/easyclaims/EasyClaimsAccess.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,7 @@ public static UUID getClaimOwner(String worldName, int chunkX, int chunkZ) {
3535
System.out.println("[EasyClaimsAccess] ERROR: claimStorage is null!");
3636
return null;
3737
}
38-
UUID owner = claimStorage.getClaimOwner(worldName, chunkX, chunkZ);
39-
// Debug: log when we find a claim (first few only to avoid spam)
40-
if (owner != null) {
41-
System.out.println("[EasyClaimsAccess] Found claim at " + worldName + " " + chunkX + "," + chunkZ + " owner=" + owner);
42-
}
43-
return owner;
38+
return claimStorage.getClaimOwner(worldName, chunkX, chunkZ);
4439
}
4540

4641
/**

src/main/java/com/easyclaims/commands/EasyClaimsCommand.java

Lines changed: 29 additions & 722 deletions
Large diffs are not rendered by default.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.easyclaims.commands.subcommands;
2+
3+
import com.hypixel.hytale.component.Ref;
4+
import com.hypixel.hytale.component.Store;
5+
import com.hypixel.hytale.math.vector.Vector3d;
6+
import com.hypixel.hytale.server.core.Message;
7+
import com.hypixel.hytale.server.core.command.system.CommandContext;
8+
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
9+
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
10+
import com.hypixel.hytale.server.core.universe.PlayerRef;
11+
import com.hypixel.hytale.server.core.universe.world.World;
12+
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
13+
import com.hypixel.hytale.math.util.ChunkUtil;
14+
import com.easyclaims.EasyClaims;
15+
import com.easyclaims.managers.ClaimManager;
16+
17+
import javax.annotation.Nonnull;
18+
import java.awt.Color;
19+
import java.util.UUID;
20+
21+
public class ClaimSubcommand extends AbstractPlayerCommand {
22+
private final EasyClaims plugin;
23+
24+
private static final Color GREEN = new Color(85, 255, 85);
25+
private static final Color RED = new Color(255, 85, 85);
26+
private static final Color YELLOW = new Color(255, 255, 85);
27+
private static final Color GRAY = new Color(170, 170, 170);
28+
29+
public ClaimSubcommand(EasyClaims plugin) {
30+
super("claim", "Claim the chunk you're standing in");
31+
this.plugin = plugin;
32+
}
33+
34+
@Override
35+
protected void execute(@Nonnull CommandContext ctx,
36+
@Nonnull Store<EntityStore> store,
37+
@Nonnull Ref<EntityStore> playerRef,
38+
@Nonnull PlayerRef playerData,
39+
@Nonnull World world) {
40+
UUID playerId = playerData.getUuid();
41+
String worldName = world.getName();
42+
43+
TransformComponent transform = store.getComponent(playerRef, TransformComponent.getComponentType());
44+
Vector3d position = transform.getPosition();
45+
46+
int chunkX = ChunkUtil.chunkCoordinate((int) position.getX());
47+
int chunkZ = ChunkUtil.chunkCoordinate((int) position.getZ());
48+
49+
ClaimManager claimManager = plugin.getClaimManager();
50+
int currentClaims = claimManager.getPlayerClaims(playerId).getClaimCount();
51+
int maxClaims = claimManager.getMaxClaims(playerId);
52+
53+
ClaimManager.ClaimResult result = claimManager.claimChunk(playerId, worldName, position.getX(), position.getZ());
54+
55+
switch (result) {
56+
case SUCCESS:
57+
playerData.sendMessage(Message.raw("Claimed chunk [" + chunkX + ", " + chunkZ + "]").color(GREEN));
58+
playerData.sendMessage(Message.raw("Claims: " + (currentClaims + 1) + "/" + maxClaims).color(GRAY));
59+
plugin.refreshWorldMapChunk(worldName, chunkX, chunkZ);
60+
break;
61+
case ALREADY_OWN:
62+
playerData.sendMessage(Message.raw("You already own this chunk!").color(YELLOW));
63+
break;
64+
case CLAIMED_BY_OTHER:
65+
UUID owner = claimManager.getOwnerAt(worldName, position.getX(), position.getZ());
66+
String ownerName = owner != null ? plugin.getClaimStorage().getPlayerName(owner) : "Unknown";
67+
playerData.sendMessage(Message.raw("This chunk is claimed by " + ownerName).color(RED));
68+
break;
69+
case LIMIT_REACHED:
70+
playerData.sendMessage(Message.raw("Claim limit reached! (" + currentClaims + "/" + maxClaims + ")").color(RED));
71+
playerData.sendMessage(Message.raw("Play more to earn additional claims.").color(GRAY));
72+
break;
73+
case TOO_CLOSE_TO_OTHER_CLAIM:
74+
playerData.sendMessage(Message.raw("Cannot claim here - too close to another player's claim!").color(RED));
75+
int buffer = plugin.getPluginConfig().getClaimBufferSize();
76+
playerData.sendMessage(Message.raw("Claims must be at least " + buffer + " chunks away from other players.").color(GRAY));
77+
break;
78+
}
79+
}
80+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.easyclaims.commands.subcommands;
2+
3+
import com.hypixel.hytale.component.Ref;
4+
import com.hypixel.hytale.component.Store;
5+
import com.hypixel.hytale.math.vector.Vector3d;
6+
import com.hypixel.hytale.server.core.command.system.CommandContext;
7+
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
8+
import com.hypixel.hytale.server.core.entity.entities.Player;
9+
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
10+
import com.hypixel.hytale.server.core.universe.PlayerRef;
11+
import com.hypixel.hytale.server.core.universe.world.World;
12+
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
13+
import com.hypixel.hytale.math.util.ChunkUtil;
14+
import com.easyclaims.EasyClaims;
15+
import com.easyclaims.gui.ChunkVisualizerGui;
16+
17+
import javax.annotation.Nonnull;
18+
19+
public class GuiSubcommand extends AbstractPlayerCommand {
20+
private final EasyClaims plugin;
21+
22+
public GuiSubcommand(EasyClaims plugin) {
23+
super("gui", "Open the visual claim manager");
24+
this.plugin = plugin;
25+
addAliases("map");
26+
}
27+
28+
@Override
29+
protected void execute(@Nonnull CommandContext ctx,
30+
@Nonnull Store<EntityStore> store,
31+
@Nonnull Ref<EntityStore> playerRef,
32+
@Nonnull PlayerRef playerData,
33+
@Nonnull World world) {
34+
Player player = store.getComponent(playerRef, Player.getComponentType());
35+
if (player == null) return;
36+
37+
TransformComponent transform = store.getComponent(playerRef, TransformComponent.getComponentType());
38+
Vector3d position = transform.getPosition();
39+
40+
int chunkX = ChunkUtil.chunkCoordinate((int) position.getX());
41+
int chunkZ = ChunkUtil.chunkCoordinate((int) position.getZ());
42+
43+
world.execute(() -> {
44+
player.getPageManager().openCustomPage(playerRef, store,
45+
new ChunkVisualizerGui(
46+
playerData,
47+
world.getName(),
48+
chunkX,
49+
chunkZ,
50+
plugin.getClaimManager(),
51+
plugin.getClaimStorage(),
52+
false,
53+
(worldName) -> plugin.refreshWorldMap(worldName)
54+
)
55+
);
56+
});
57+
}
58+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.easyclaims.commands.subcommands;
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.command.system.CommandContext;
7+
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
8+
import com.hypixel.hytale.server.core.universe.PlayerRef;
9+
import com.hypixel.hytale.server.core.universe.world.World;
10+
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
11+
import com.easyclaims.EasyClaims;
12+
import com.easyclaims.data.Claim;
13+
import com.easyclaims.data.PlayerClaims;
14+
15+
import javax.annotation.Nonnull;
16+
import java.awt.Color;
17+
import java.util.List;
18+
19+
public class ListSubcommand extends AbstractPlayerCommand {
20+
private final EasyClaims plugin;
21+
22+
private static final Color GOLD = new Color(255, 170, 0);
23+
private static final Color YELLOW = new Color(255, 255, 85);
24+
private static final Color GRAY = new Color(170, 170, 170);
25+
private static final Color AQUA = new Color(85, 255, 255);
26+
27+
public ListSubcommand(EasyClaims plugin) {
28+
super("list", "List all your claimed chunks");
29+
this.plugin = plugin;
30+
addAliases("claims");
31+
}
32+
33+
@Override
34+
protected void execute(@Nonnull CommandContext ctx,
35+
@Nonnull Store<EntityStore> store,
36+
@Nonnull Ref<EntityStore> playerRef,
37+
@Nonnull PlayerRef playerData,
38+
@Nonnull World world) {
39+
PlayerClaims playerClaims = plugin.getClaimManager().getPlayerClaims(playerData.getUuid());
40+
List<Claim> claims = playerClaims.getClaims();
41+
42+
if (claims.isEmpty()) {
43+
playerData.sendMessage(Message.raw("You don't have any claims.").color(YELLOW));
44+
playerData.sendMessage(Message.raw("Use /easyclaims claim to claim land!").color(GRAY));
45+
return;
46+
}
47+
48+
int maxClaims = plugin.getClaimManager().getMaxClaims(playerData.getUuid());
49+
playerData.sendMessage(Message.raw("Your Claims (" + claims.size() + "/" + maxClaims + "):").color(GOLD));
50+
51+
for (Claim claim : claims) {
52+
String marker = claim.getWorld().equals(world.getName()) ? " (current world)" : "";
53+
playerData.sendMessage(Message.raw(" " + claim.getWorld() + " [" + claim.getChunkX() + ", " + claim.getChunkZ() + "]" + marker).color(AQUA));
54+
}
55+
}
56+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.easyclaims.commands.subcommands;
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.command.system.CommandContext;
7+
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
8+
import com.hypixel.hytale.server.core.universe.PlayerRef;
9+
import com.hypixel.hytale.server.core.universe.world.World;
10+
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
11+
import com.easyclaims.EasyClaims;
12+
import com.easyclaims.managers.ClaimManager;
13+
14+
import javax.annotation.Nonnull;
15+
import java.awt.Color;
16+
import java.util.UUID;
17+
18+
public class PlaytimeSubcommand extends AbstractPlayerCommand {
19+
private final EasyClaims plugin;
20+
21+
private static final Color GOLD = new Color(255, 170, 0);
22+
private static final Color GREEN = new Color(85, 255, 85);
23+
private static final Color YELLOW = new Color(255, 255, 85);
24+
private static final Color GRAY = new Color(170, 170, 170);
25+
private static final Color AQUA = new Color(85, 255, 255);
26+
27+
public PlaytimeSubcommand(EasyClaims plugin) {
28+
super("playtime", "Show your playtime and claim slots");
29+
this.plugin = plugin;
30+
addAliases("stats");
31+
}
32+
33+
@Override
34+
protected void execute(@Nonnull CommandContext ctx,
35+
@Nonnull Store<EntityStore> store,
36+
@Nonnull Ref<EntityStore> playerRef,
37+
@Nonnull PlayerRef playerData,
38+
@Nonnull World world) {
39+
UUID playerId = playerData.getUuid();
40+
ClaimManager claimManager = plugin.getClaimManager();
41+
42+
double hours = plugin.getPlaytimeManager().getTotalHours(playerId);
43+
int currentClaims = claimManager.getPlayerClaims(playerId).getClaimCount();
44+
int maxClaims = claimManager.getMaxClaims(playerId);
45+
46+
playerData.sendMessage(Message.raw("=== Your Stats ===").color(GOLD));
47+
playerData.sendMessage(Message.raw("Playtime: " + String.format("%.1f", hours) + " hours").color(AQUA));
48+
playerData.sendMessage(Message.raw("Claims: " + currentClaims + "/" + maxClaims + " used").color(AQUA));
49+
50+
if (currentClaims < maxClaims) {
51+
playerData.sendMessage(Message.raw("You can claim " + (maxClaims - currentClaims) + " more chunk(s)!").color(GREEN));
52+
} else {
53+
double hoursUntilNext = claimManager.getHoursUntilNextClaim(playerId);
54+
if (hoursUntilNext > 0) {
55+
playerData.sendMessage(Message.raw("Next claim slot in " + String.format("%.1f", hoursUntilNext) + " hours").color(GRAY));
56+
} else {
57+
playerData.sendMessage(Message.raw("Maximum claims reached!").color(YELLOW));
58+
}
59+
}
60+
}
61+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.easyclaims.commands.subcommands;
2+
3+
import com.hypixel.hytale.component.Ref;
4+
import com.hypixel.hytale.component.Store;
5+
import com.hypixel.hytale.server.core.command.system.CommandContext;
6+
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
7+
import com.hypixel.hytale.server.core.entity.entities.Player;
8+
import com.hypixel.hytale.server.core.universe.PlayerRef;
9+
import com.hypixel.hytale.server.core.universe.world.World;
10+
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
11+
import com.easyclaims.EasyClaims;
12+
import com.easyclaims.gui.ClaimSettingsGui;
13+
14+
import javax.annotation.Nonnull;
15+
16+
public class SettingsSubcommand extends AbstractPlayerCommand {
17+
private final EasyClaims plugin;
18+
19+
public SettingsSubcommand(EasyClaims plugin) {
20+
super("settings", "Manage your trusted players");
21+
this.plugin = plugin;
22+
}
23+
24+
@Override
25+
protected void execute(@Nonnull CommandContext ctx,
26+
@Nonnull Store<EntityStore> store,
27+
@Nonnull Ref<EntityStore> playerRef,
28+
@Nonnull PlayerRef playerData,
29+
@Nonnull World world) {
30+
Player player = store.getComponent(playerRef, Player.getComponentType());
31+
if (player == null) return;
32+
33+
world.execute(() -> {
34+
player.getPageManager().openCustomPage(playerRef, store,
35+
new ClaimSettingsGui(
36+
playerData,
37+
plugin.getClaimManager(),
38+
plugin.getPlaytimeManager(),
39+
(playerId) -> plugin.refreshPlayerClaimChunks(playerId)
40+
)
41+
);
42+
});
43+
}
44+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.easyclaims.commands.subcommands;
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.command.system.CommandContext;
7+
import com.hypixel.hytale.server.core.command.system.basecommands.AbstractPlayerCommand;
8+
import com.hypixel.hytale.server.core.universe.PlayerRef;
9+
import com.hypixel.hytale.server.core.universe.world.World;
10+
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
11+
import com.easyclaims.EasyClaims;
12+
import com.easyclaims.data.PlayerClaims;
13+
import com.easyclaims.data.TrustedPlayer;
14+
15+
import javax.annotation.Nonnull;
16+
import java.awt.Color;
17+
import java.util.Map;
18+
import java.util.UUID;
19+
20+
public class TrustListSubcommand extends AbstractPlayerCommand {
21+
private final EasyClaims plugin;
22+
23+
private static final Color GOLD = new Color(255, 170, 0);
24+
private static final Color YELLOW = new Color(255, 255, 85);
25+
private static final Color GRAY = new Color(170, 170, 170);
26+
27+
public TrustListSubcommand(EasyClaims plugin) {
28+
super("trustlist", "List all players you've trusted");
29+
this.plugin = plugin;
30+
}
31+
32+
@Override
33+
protected void execute(@Nonnull CommandContext ctx,
34+
@Nonnull Store<EntityStore> store,
35+
@Nonnull Ref<EntityStore> playerRef,
36+
@Nonnull PlayerRef playerData,
37+
@Nonnull World world) {
38+
PlayerClaims claims = plugin.getClaimManager().getPlayerClaims(playerData.getUuid());
39+
Map<UUID, TrustedPlayer> trustedPlayers = claims.getTrustedPlayersMap();
40+
41+
if (trustedPlayers.isEmpty()) {
42+
playerData.sendMessage(Message.raw("You haven't trusted anyone.").color(YELLOW));
43+
playerData.sendMessage(Message.raw("Use /easyclaims trust <player> [level]").color(GRAY));
44+
return;
45+
}
46+
47+
playerData.sendMessage(Message.raw("Trusted Players (" + trustedPlayers.size() + "):").color(GOLD));
48+
for (TrustedPlayer tp : trustedPlayers.values()) {
49+
playerData.sendMessage(Message.raw(" " + tp.getName() + " [" + tp.getLevel().getDescription() + "]").color(GRAY));
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)