Skip to content

Commit d37662b

Browse files
committed
Refactoring
1 parent 7cf381c commit d37662b

File tree

4 files changed

+283
-93
lines changed

4 files changed

+283
-93
lines changed

src/main/java/io/luna/game/model/mob/Skill.java

Lines changed: 133 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,32 @@
1414
import static com.google.common.base.Preconditions.checkArgument;
1515

1616
/**
17-
* A model representing a skill within a skill set.
17+
* Represents a single skill within a {@link SkillSet}, tracking both the <b>static</b> (experience-based) level and
18+
* the <b>dynamic</b> (temporarily modified) level.
19+
*
20+
* <h2>Static vs dynamic levels</h2>
21+
* <ul>
22+
* <li><b>Static level</b> – the level derived from total {@link #experience}. This is what players “really” are,
23+
* and is recalculated via {@link SkillSet#levelForExperience(int)}. This value is cached in {@link #staticLevel}
24+
* and invalidated whenever experience changes.</li>
25+
* <li><b>Dynamic level</b> – the current, temporary level shown/used by game logic when boosts or drains apply
26+
* (potions, prayers, debuffs, etc). This is stored in {@link #level} and may differ from the static level.</li>
27+
* </ul>
28+
*
29+
* <h2>Events and restoration</h2>
30+
* <ul>
31+
* <li>Whenever experience or the dynamic level changes, a {@link SkillChangeEvent} may be posted if the owning
32+
* {@link SkillSet} is configured to fire events (see {@link SkillSet#isFiringEvents()}).</li>
33+
* <li>If the dynamic level changes away from the static level, a {@link SkillRestorationTask} may be scheduled
34+
* to gradually restore skills back toward their static level (see {@link SkillSet#isRestoring()}).</li>
35+
* </ul>
1836
*
1937
* @author lare96
2038
*/
2139
public final class Skill {
2240

2341
/**
24-
* An immutable list of the names of all skills.
42+
* Ordered, immutable list of all skill names. The index into this list is the skill identifier.
2543
*/
2644
public static final ImmutableList<String> NAMES = ImmutableList.of(
2745
"Attack", "Defence", "Strength", "Hitpoints", "Ranged", "Prayer", "Magic",
@@ -30,17 +48,23 @@ public final class Skill {
3048
);
3149

3250
/**
33-
* The combat skill identifiers.
51+
* The range of skill identifiers considered in combat level calculations.
3452
*/
3553
public static final Range<Integer> COMBAT_IDS = Range.closed(0, 6);
3654

3755
/**
38-
* An immutable map of names to identifiers.
56+
* Maps skill name -> skill identifier.
57+
* <p>
58+
* Built from {@link #NAMES} in the static initializer.
59+
* </p>
3960
*/
4061
public static final ImmutableMap<String, Integer> NAME_TO_ID;
4162

4263
/**
43-
* An immutable list of all identifiers.
64+
* Immutable list of all skill identifiers.
65+
* <p>
66+
* This is effectively {@code 0..NAMES.size()-1} but derived from {@link #NAME_TO_ID} for convenience.
67+
* </p>
4468
*/
4569
public static final ImmutableList<Integer> IDS;
4670

@@ -150,30 +174,36 @@ public final class Skill {
150174
public static final int RUNECRAFTING = 20;
151175

152176
/**
153-
* Retrieves the name of a skill by its identifier.
177+
* Retrieves the skill name for {@code id}.
154178
*
155-
* @param id The identifier.
179+
* @param id The skill identifier (0-based).
156180
* @return The skill name.
181+
* @throws IndexOutOfBoundsException if {@code id} is not a valid skill identifier.
157182
*/
158183
public static String getName(int id) {
159184
return NAMES.get(id);
160185
}
161186

162187
/**
163-
* Retrieves the identifier of a skill by its name.
188+
* Retrieves the skill identifier for {@code name}, or {@code -1} if none were found.
189+
* <p>
190+
* Matching is exact and case-sensitive.
191+
* </p>
164192
*
165-
* @param name The skill name.
166-
* @return The identifier.
193+
* @param name The skill name (must match an entry in {@link #NAMES}).
194+
* @return The skill identifier, {@code -1} if none were found.
195+
* @throws NullPointerException if {@code name} is {@code null}.
167196
*/
168197
public static int getId(String name) {
169-
return NAME_TO_ID.get(name);
198+
Integer id = NAME_TO_ID.get(name);
199+
return id == null ? -1 : id;
170200
}
171201

172202
/**
173-
* Determines if a skill is a factor in combat level calculations.
203+
* Determines whether {@code id} is a combat skill.
174204
*
175205
* @param id The skill identifier.
176-
* @return {@code true} if the identifier is a combat skill.
206+
* @return {@code true} if {@code id} is in {@link #COMBAT_IDS}.
177207
*/
178208
public static boolean isCombatSkill(int id) {
179209
return COMBAT_IDS.contains(id);
@@ -187,35 +217,50 @@ public static boolean isCombatSkill(int id) {
187217
}
188218

189219
/**
190-
* The skill set.
220+
* The owning skill set.
191221
*/
192222
private transient final SkillSet set;
193223

194224
/**
195-
* The skill identifier.
225+
* The skill identifier (0-based index into {@link #NAMES}).
196226
*/
197227
private transient final int id;
198228

199229
/**
200-
* The static (experience based) skill level. Cached to avoid potentially expensive {@link SkillSet#levelForExperience(int)} calls.
230+
* Cached static (experience-based) level.
231+
* <p>
232+
* This is computed lazily from {@link #experience} and cached to avoid repeated {@link SkillSet#levelForExperience(int)}
233+
* calls. It is invalidated by setting {@code staticLevel = -1} whenever experience changes.
234+
* </p>
201235
*/
202236
private transient int staticLevel = -1;
203237

204238
/**
205-
* The dynamic skill level.
239+
* The dynamic (temporarily modified) level.
240+
* <p>
241+
* This may be higher or lower than the static level due to buffs/drains. Restoration may move this back
242+
* toward {@link #getStaticLevel()} over time.
243+
* </p>
206244
*/
207245
private int level = 1;
208246

209247
/**
210-
* The attained experience.
248+
* Total accumulated experience for this skill.
249+
* <p>
250+
* Bounded to {@code [0, SkillSet.MAXIMUM_EXPERIENCE]} by {@link #setExperience(double)}.
251+
* </p>
211252
*/
212253
private double experience;
213254

214255
/**
215256
* Creates a new {@link Skill}.
257+
* <p>
258+
* Hitpoints starts at level 10 with 1300 experience (classic RuneScape default), while other skills start at
259+
* level 1 with 0 experience.
260+
* </p>
216261
*
217262
* @param id The skill identifier.
218-
* @param set The skill set.
263+
* @param set The owning skill set.
219264
*/
220265
public Skill(int id, SkillSet set) {
221266
this.id = id;
@@ -233,11 +278,18 @@ public String toString() {
233278
}
234279

235280
/**
236-
* Restores depleted or buffed skills.
281+
* Schedules restoration if the dynamic level differs from the static level and restoration is enabled.
282+
* <p>
283+
* This method is intentionally conservative: it only schedules restoration when:
284+
* </p>
285+
* <ul>
286+
* <li>The {@link SkillSet} is not currently restoring ({@link SkillSet#isRestoring()} is {@code false}).</li>
287+
* <li>The dynamic {@link #level} differs from {@link #staticLevel}.</li>
288+
* </ul>
237289
*/
238290
private void restoreSkills() {
239291
if (!set.isRestoring()) {
240-
if (level != staticLevel) {
292+
if (level != getStaticLevel()) {
241293
var world = set.getMob().getWorld();
242294
world.schedule(new SkillRestorationTask(set));
243295
}
@@ -246,8 +298,13 @@ private void restoreSkills() {
246298

247299
/**
248300
* Adds experience to this skill.
301+
* <p>
302+
* For non-bot mobs, experience is multiplied by the configured game experience multiplier. Bots receive experience
303+
* at a fixed multiplier of {@code 1.0} (no bonus).
304+
* </p>
249305
*
250-
* @param amount The amount of experience to add.
306+
* @param amount The raw amount of experience to add.
307+
* @throws IllegalArgumentException if {@code amount <= 0}.
251308
*/
252309
public void addExperience(double amount) {
253310
checkArgument(amount > 0, "amount <= 0");
@@ -256,11 +313,14 @@ public void addExperience(double amount) {
256313
}
257314

258315
/**
259-
* Notifies plugins of any level or experience changes.
316+
* Posts a {@link SkillChangeEvent} to plugins if event firing is enabled.
317+
* <p>
318+
* The event includes the previous values so listeners can compute deltas or react to level-ups.
319+
* </p>
260320
*
261-
* @param oldExperience The old experience amount.
262-
* @param oldStaticLevel The old static level.
263-
* @param oldLevel The old dynamic level.
321+
* @param oldExperience The previous experience value.
322+
* @param oldStaticLevel The previous static level.
323+
* @param oldLevel The previous dynamic level.
264324
*/
265325
private void notifyListeners(double oldExperience, int oldStaticLevel, int oldLevel) {
266326
if (set.isFiringEvents()) {
@@ -271,21 +331,30 @@ private void notifyListeners(double oldExperience, int oldStaticLevel, int oldLe
271331
}
272332

273333
/**
274-
* @return The name of this skill.
334+
* Returns the name of this skill.
335+
*
336+
* @return The skill name (from {@link #NAMES}).
275337
*/
276338
public String getName() {
277339
return NAMES.get(id);
278340
}
279341

280342
/**
343+
* Returns the identifier of this skill.
344+
*
281345
* @return The skill identifier.
282346
*/
283347
public int getId() {
284348
return id;
285349
}
286350

287351
/**
288-
* @return The static (experience based) skill level.
352+
* Returns the static (experience-based) skill level.
353+
* <p>
354+
* This is computed lazily and cached. The cache is invalidated whenever experience changes.
355+
* </p>
356+
*
357+
* @return The experience-based level.
289358
*/
290359
public int getStaticLevel() {
291360
if (staticLevel == -1) {
@@ -295,22 +364,33 @@ public int getStaticLevel() {
295364
return staticLevel;
296365
}
297366

367+
/**
368+
* Sets the static (experience-based) level by converting the desired level into experience.
369+
*
370+
* @param level The target static level.
371+
*/
298372
public void setStaticLevel(int level) {
299373
setExperience(SkillSet.experienceForLevel(level));
300-
374+
staticLevel = level;
301375
}
302376

303377
/**
304-
* @return The dynamic skill level.
378+
* Returns the dynamic (temporarily modified) skill level.
379+
*
380+
* @return The current dynamic level.
305381
*/
306382
public int getLevel() {
307383
return level;
308384
}
309385

310386
/**
311-
* Sets the dynamic skill level.
387+
* Sets the dynamic (temporarily modified) skill level.
388+
* <p>
389+
* The level is clamped to a minimum of {@code 0}. If the value does not change, no events are fired and restoration
390+
* is not scheduled.
391+
* </p>
312392
*
313-
* @param newLevel The new level.
393+
* @param newLevel The new dynamic level.
314394
*/
315395
public void setLevel(int newLevel) {
316396
if (newLevel < 0) {
@@ -329,10 +409,14 @@ public void setLevel(int newLevel) {
329409

330410
/**
331411
* Increases the dynamic skill level by {@code amount}.
412+
* <p>
413+
* If {@code exceedStaticLevel} is {@code false}, the result is capped at {@link #getStaticLevel()}.
414+
* If {@code exceedStaticLevel} is {@code true}, the result is capped at {@code getStaticLevel() + amount}.
415+
* </p>
332416
*
333417
* @param amount The amount to increase by.
334-
* @param exceedStaticLevel If the bound should be set higher than the static level, or at the
335-
* static level.
418+
* @param exceedStaticLevel If {@code true}, allow the boost above the static level (up to {@code static + amount});
419+
* otherwise cap at the static level.
336420
*/
337421
public void addLevels(int amount, boolean exceedStaticLevel) {
338422
int bound = exceedStaticLevel ? getStaticLevel() + amount : getStaticLevel();
@@ -344,6 +428,11 @@ public void addLevels(int amount, boolean exceedStaticLevel) {
344428

345429
/**
346430
* Decreases the dynamic skill level by {@code amount}.
431+
* <p>
432+
* The result is clamped to a minimum of {@code 0}.
433+
* </p>
434+
*
435+
* @param amount The amount to remove.
347436
*/
348437
public void removeLevels(int amount) {
349438
int newAmount = getLevel() - amount;
@@ -352,14 +441,22 @@ public void removeLevels(int amount) {
352441
}
353442

354443
/**
355-
* @return The attained experience.
444+
* Returns total accumulated experience.
445+
*
446+
* @return The experience value.
356447
*/
357448
public double getExperience() {
358449
return experience;
359450
}
360451

361452
/**
362-
* Sets the attained experience.
453+
* Sets total accumulated experience for this skill.
454+
* <p>
455+
* The value is clamped into {@code [0, SkillSet.MAXIMUM_EXPERIENCE]}. If the value does not change, nothing happens.
456+
* </p>
457+
* <p>
458+
* If the value changes, the cached static level is invalidated and listeners may be notified.
459+
* </p>
363460
*
364461
* @param newExperience The new experience value.
365462
*/

0 commit comments

Comments
 (0)