77import java .util .Objects ;
88import java .util .UUID ;
99
10- /**
11- * Represents a scaling preset for a specific player.
12- * <p>
13- * Each preset contains:
14- * <ul>
15- * <li>An identifier (UUID or username)</li>
16- * <li>An optional friendly display name</li>
17- * <li>A scale factor for the player</li>
18- * <li>An enabled/disabled state</li>
19- * </ul>
20- * <p>
21- * Presets are immutable after creation, use {@link #copy()} to create modified versions.
22- */
2310public class PlayerPreset {
2411
2512 @ SerializedName ("identifier" )
26- public String identifier ; // Package-private for manager access
13+ public String identifier ;
2714
2815 @ SerializedName ("friendlyName" )
29- public String friendlyName ; // Package-private for manager access
16+ public String friendlyName ;
3017
3118 @ SerializedName ("scale" )
32- public float scale ; // Package-private for manager access
19+ public float scale ;
3320
3421 @ SerializedName ("enabled" )
35- public boolean enabled ; // Package-private for manager access
22+ public boolean enabled ;
3623
3724 /**
3825 * Creates a new player preset with validation.
3926 * @param identifier The player identifier (UUID or username)
4027 * @param friendlyName Optional display name (can be null)
4128 * @param scale The scale factor
42- * @throws IllegalArgumentException if identifier is invalid or scale is out of range
29+ * @throws IllegalArgumentException if scale is out of range
4330 */
4431 public PlayerPreset (String identifier , String friendlyName , float scale ) {
45- validateIdentifier (identifier );
46- validateScale (scale );
47-
48- this .identifier = identifier .trim ();
32+ // Allow empty identifier for draft presets
33+ // Validation will occur during save operation
34+ this .identifier = identifier != null ? identifier .trim () : "" ;
4935 this .friendlyName = (friendlyName != null && !friendlyName .trim ().isEmpty ())
5036 ? friendlyName .trim () : null ;
37+
38+ validateScale (scale );
5139 this .scale = ScaleConstants .clampScale (scale );
5240 this .enabled = true ;
5341 }
5442
55- // ===== Validation Helper Methods =====
43+ /**
44+ * Validates that this preset is ready to be saved.
45+ * @throws IllegalArgumentException if preset is invalid
46+ */
47+ public void validateForSave () {
48+ validateIdentifier (this .identifier );
49+ validateScale (this .scale );
50+ }
5651
5752 /**
58- * Validates and sets the scale value.
59- * @param scale The new scale value
60- * @throws IllegalArgumentException if scale is invalid
53+ * Checks if this preset is valid for saving.
54+ * @return true if valid, false otherwise
6155 */
56+ public boolean isValidForSave () {
57+ try {
58+ validateForSave ();
59+ return true ;
60+ } catch (IllegalArgumentException e ) {
61+ return false ;
62+ }
63+ }
64+
65+ // ===== Validation Helper Methods =====
66+
6267 public void setScaleValidated (float scale ) {
6368 validateScale (scale );
6469 this .scale = ScaleConstants .clampScale (scale );
6570 }
6671
67- /**
68- * Validates and sets the identifier.
69- * @param identifier The new identifier
70- * @throws IllegalArgumentException if identifier is invalid
71- */
7272 public void setIdentifierValidated (String identifier ) {
7373 validateIdentifier (identifier );
7474 this .identifier = identifier .trim ();
7575 }
7676
7777 // ===== Core Methods =====
7878
79- /**
80- * Creates a deep copy of this preset.
81- * @return A new PlayerPreset with identical values
82- */
8379 public PlayerPreset copy () {
8480 PlayerPreset copy = new PlayerPreset (this .identifier , this .friendlyName , this .scale );
8581 copy .enabled = this .enabled ;
8682 return copy ;
8783 }
8884
89- /**
90- * Returns the display name for this preset.
91- * Uses friendly name if available, otherwise falls back to identifier.
92- * @return The effective display name
93- */
9485 public String getEffectiveDisplayName () {
9586 return (friendlyName != null && !friendlyName .isEmpty ())
9687 ? friendlyName
9788 : identifier ;
9889 }
9990
100- /**
101- * Checks if this preset matches a given identifier (case-insensitive).
102- * Only returns true if the preset is enabled.
103- * @param id The identifier to check
104- * @return true if enabled and identifier matches
105- */
10691 public boolean matches (String id ) {
10792 return enabled && identifier .equalsIgnoreCase (id );
10893 }
10994
110- /**
111- * Checks if this preset matches a player by UUID or username.
112- * @param playerUUID The player's UUID
113- * @param playerName The player's name (can be null)
114- * @return true if enabled and matches either UUID or username
115- */
11695 public boolean matchesPlayer (UUID playerUUID , String playerName ) {
11796 if (!enabled || playerUUID == null ) {
11897 return false ;
11998 }
12099
121- // Check UUID match if identifier is a UUID
122100 if (isUUID ()) {
123101 try {
124102 return UUID .fromString (identifier ).equals (playerUUID );
@@ -127,32 +105,19 @@ public boolean matchesPlayer(UUID playerUUID, String playerName) {
127105 }
128106 }
129107
130- // Check username match (case insensitive)
131108 return playerName != null && identifier .equalsIgnoreCase (playerName );
132109 }
133110
134- /**
135- * Attempts to resolve this preset's identifier to a UUID.
136- * @return The resolved UUID, or null if resolution fails
137- */
138111 public UUID resolveToUUID () {
139112 return PlayerUUIDResolver .resolvePlayerUUID (this .identifier );
140113 }
141114
142115 // ===== Validation Methods =====
143116
144- /**
145- * Checks if the identifier is in UUID format.
146- * @return true if identifier matches UUID pattern
147- */
148117 public boolean isUUID () {
149118 return identifier != null && identifier .matches (ScaleConstants .UUID_REGEX );
150119 }
151120
152- /**
153- * Checks if the identifier is in username format.
154- * @return true if identifier matches username pattern
155- */
156121 public boolean isUsername () {
157122 return identifier != null && identifier .matches (ScaleConstants .USERNAME_REGEX );
158123 }
@@ -168,11 +133,6 @@ private void validateIdentifier(String identifier) {
168133 }
169134 }
170135
171- /**
172- * Validates that a scale value is within acceptable range.
173- * @param scale The scale value to validate
174- * @throws IllegalArgumentException if scale is invalid
175- */
176136 private void validateScale (float scale ) {
177137 if (!ScaleConstants .isValidScale (scale )) {
178138 throw new IllegalArgumentException (
0 commit comments