Crossfire JXClient, Trunk
SpellsManager.java
Go to the documentation of this file.
1 /*
2  * This file is part of JXClient, the Fullscreen Java Crossfire Client.
3  *
4  * JXClient is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * JXClient is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with JXClient; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * Copyright (C) 2005-2008 Yann Chachkoff
19  * Copyright (C) 2006-2017,2019-2023 Andreas Kirschbaum
20  * Copyright (C) 2010-2012,2014-2018,2020-2023 Nicolas Weeger
21  */
22 
23 package com.realtime.crossfire.jxclient.spells;
24 
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.Comparator;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.concurrent.CopyOnWriteArrayList;
40 import java.util.stream.Collectors;
41 import org.jetbrains.annotations.NotNull;
42 import org.jetbrains.annotations.Nullable;
43 
50 public class SpellsManager {
51 
55  public static final int UPD_SP_MANA = 1;
56 
60  public static final int UPD_SP_GRACE = 2;
61 
65  public static final int UPD_SP_DAMAGE = 4;
66 
70  @NotNull
71  private final List<Spell> spells = new CopyOnWriteArrayList<>();
72 
76  @NotNull
77  private final List<Spell> filteredSpells = new CopyOnWriteArrayList<>();
78 
83  private int skillFilter = -1;
84 
89  @NotNull
90  private final Map<String, Spell> unknownSpells = new HashMap<>();
91 
96  @NotNull
98 
103  @NotNull
104  private final Comparator<Spell> spellNameComparator = new SpellComparator();
105 
110  @NotNull
111  @SuppressWarnings("FieldCanBeLocal")
113 
114  @Override
115  public void start() {
116  // ignore
117  }
118 
119  @Override
120  public void metaserver() {
121  // ignore
122  }
123 
124  @Override
125  public void preConnecting(@NotNull final String serverInfo) {
126  // ignore
127  }
128 
129  @Override
130  public void connecting(@NotNull final String serverInfo) {
131  spells.clear();
132  spellSkills.clear();
133  filteredSpells.clear();
134  }
135 
136  @Override
137  public void connecting(@NotNull final ClientSocketState clientSocketState, @NotNull final String param) {
138  // ignore
139  }
140 
141  @Override
142  public void connected() {
143  // ignore
144  }
145 
146  @Override
147  public void connectFailed(@NotNull final String reason) {
148  // ignore
149  }
150 
151  };
152 
156  private final SkillSet skillSet;
157 
161  private final Stats stats;
162 
166  private final Skill skillAll = new Skill("All spell skills");
167 
171  private final List<Skill> spellSkills = new ArrayList<>();
172 
179  public SpellsManager(@NotNull final GuiStateManager guiStateManager, @NotNull final SkillSet skillSet, @NotNull final Stats stats) {
180  guiStateManager.addGuiStateListener(guiStateListener);
181  this.skillSet = skillSet;
182  this.stats = stats;
183  }
184 
189  public void addCrossfireSpellChangedListener(@NotNull final SpellsManagerListener listener) {
190  listeners.add(listener);
191  }
192 
197  public void removeCrossfireSpellChangedListener(@NotNull final SpellsManagerListener listener) {
198  listeners.remove(listener);
199  }
200 
216  public void addSpell(final int tag, final int level, final int castingTime, final int mana, final int grace, final int damage, final int skill, final int path, final int faceNum, @NotNull final String spellName, @NotNull final String message) {
217  final Spell key = new Spell(spellName, skillSet, stats);
218  key.setParameters(faceNum, tag, message, level, castingTime, mana, grace, damage, skill, path); // set spell path which is used in the comparator
219 
220  int index = Collections.binarySearch(spells, key, spellNameComparator);
221  final Spell spell;
222  if (index < 0) {
223  final Spell existingSpell;
224  synchronized (unknownSpells) {
225  existingSpell = unknownSpells.remove(spellName);
226  }
227  if (existingSpell == null) {
228  spell = key;
229  } else {
230  spell = existingSpell;
231  spell.setParameters(faceNum, tag, message, level, castingTime, mana, grace, damage, skill, path);
232  }
233  index = -index-1;
234  spells.add(index, spell);
235  } else {
236  spell = spells.get(index);
237  spell.setParameters(faceNum, tag, message, level, castingTime, mana, grace, damage, skill, path);
238  }
239 
240  rebuildSkills();
241  filterSpells();
242 
243  for (SpellsManagerListener listener : listeners) {
244  listener.spellAdded(index);
245  }
246  }
247 
256  public void updateSpell(final int flags, final int tag, final int mana, final int grace, final int damage) {
257  for (Spell spell : spells) {
258  if (spell.getTag() == tag) {
259  spell.updateParameters((flags&UPD_SP_MANA) != 0, mana, (flags&UPD_SP_GRACE) != 0, grace, (flags&UPD_SP_DAMAGE) != 0, damage);
260  break;
261  }
262  }
263  }
264 
269  public void deleteSpell(final int tag) {
270  int index = 0;
271  for (Spell spell : spells) {
272  if (spell.getTag() == tag) {
273  deleteSpellByIndex(index);
274  break;
275  }
276  index++;
277  }
278  rebuildSkills();
279  filterSpells();
280  }
281 
286  private void deleteSpellByIndex(final int index) {
287  final Spell spell = spells.remove(index);
288  synchronized (unknownSpells) {
289  unknownSpells.put(spell.getName(), spell);
290  }
291 
292  for (SpellsManagerListener listener : listeners) {
293  listener.spellRemoved(index);
294  }
295 
296  spell.setUnknown(true);
297 
298  rebuildSkills();
299  }
300 
306  @Nullable
307  public Spell getSpell(@NotNull final String spellName) {
308  for (Spell spell : spells) {
309  if (spell.getName().equals(spellName)) {
310  return spell;
311  }
312  }
313 
314  Spell result = null;
315  for (Spell spell : spells) {
316  if (spell.getName().startsWith(spellName)) {
317  //noinspection VariableNotUsedInsideIf
318  if (result != null) {
319  // prefix is not unique => pretend the spell does not exist
320  return null;
321  }
322  result = spell;
323  }
324  }
325 
326  return result;
327  }
328 
333  @NotNull
334  public Collection<Spell> getAllSpells() {
335  return Collections.unmodifiableList(filteredSpells);
336  }
337 
342  @NotNull
343  public Collection<Spell> getFilteredSpells() {
344  return Collections.unmodifiableList(filteredSpells);
345  }
346 
351  public int getFilteredSpellsCount() {
352  return filteredSpells.size();
353  }
354 
361  @Nullable
362  public Spell getFilteredSpell(final int index) {
363  try {
364  return filteredSpells.get(index);
365  } catch (final IndexOutOfBoundsException ignored) {
366  return null;
367  }
368  }
369 
375  public boolean displaysFace(final int faceNum) {
376  for (Spell spell : spells) {
377  if (spell.getFaceNum() == faceNum) {
378  return true;
379  }
380  }
381 
382  return false;
383  }
384 
388  public void selectCharacter() {
389  spells.clear();
390  filteredSpells.clear();
391  }
392 
397  public void filterSkill(final int index) {
398  if (index < 0 || index >= spellSkills.size()) {
399  return;
400  }
401 
402  final int id = skillSet.getSkillId(spellSkills.get(index).toString());
403 
404  if (skillFilter == id) {
405  return;
406  }
407 
408  skillFilter = id;
409  filterSpells();
410 
411  for (SpellsManagerListener listener : listeners) {
412  listener.spellAdded(0);
413  }
414  }
415 
419  private void filterSpells() {
420  filteredSpells.clear();
421  filteredSpells.addAll(spells.stream().filter(spell -> skillFilter == -1 || spell.getSkill() == skillFilter).collect(Collectors.toList()));
422  }
423 
427  private void rebuildSkills() {
428  spellSkills.clear();
429  for (Spell spell : spells) {
430  final Skill skill = skillSet.getSkill(spell.getSkill());
431  if (skill != null && !spellSkills.contains(skill)) {
432  spellSkills.add(skill);
433  }
434  }
435  spellSkills.sort(Comparator.comparing(Skill::toString));
436  spellSkills.add(0, skillAll);
437  }
438 
443  public int getSpellSkills() {
444  return spellSkills.size();
445  }
446 
452  @Nullable
453  public Skill getSpellSkill(final int index) {
454  return 0 <= index && index < spellSkills.size() ? spellSkills.get(index) : null;
455  }
456 
457 }
com.realtime.crossfire.jxclient
com.realtime.crossfire.jxclient.spells.SpellsManager.skillSet
final SkillSet skillSet
The SkillSet containing skills from the server.
Definition: SpellsManager.java:156
com.realtime.crossfire.jxclient.spells.SpellsManager.getSpellSkills
int getSpellSkills()
Returns the number of spell skills.
Definition: SpellsManager.java:443
com.realtime.crossfire.jxclient.spells.SpellsManager.getFilteredSpells
Collection< Spell > getFilteredSpells()
Returns all currently shown spells.
Definition: SpellsManager.java:343
com.realtime.crossfire.jxclient.spells.SpellsManager.filterSkill
void filterSkill(final int index)
Filters spells to display by the specified skill index.
Definition: SpellsManager.java:397
com.realtime.crossfire.jxclient.spells.SpellsManager.unknownSpells
final Map< String, Spell > unknownSpells
All unknown spells that have been referenced before.
Definition: SpellsManager.java:90
com.realtime.crossfire.jxclient.skills.Skill.toString
String toString()
Definition: Skill.java:145
com.realtime.crossfire.jxclient.spells.SpellsManager.UPD_SP_MANA
static final int UPD_SP_MANA
Flag for updspell command: mana is present.
Definition: SpellsManager.java:55
com.realtime.crossfire.jxclient.spells.SpellsManager.guiStateListener
final GuiStateListener guiStateListener
The GuiStateListener for detecting established or dropped connections.
Definition: SpellsManager.java:112
com.realtime.crossfire.jxclient.guistate.GuiStateListener
Interface for listeners interested gui state changes.
Definition: GuiStateListener.java:32
com.realtime.crossfire.jxclient.spells.SpellsManager.deleteSpellByIndex
void deleteSpellByIndex(final int index)
Deletes a spell by index into spells.
Definition: SpellsManager.java:286
com.realtime.crossfire.jxclient.spells.SpellsManager.addCrossfireSpellChangedListener
void addCrossfireSpellChangedListener(@NotNull final SpellsManagerListener listener)
Adds a SpellsManagerListener to notify about changes.
Definition: SpellsManager.java:189
com.realtime.crossfire.jxclient.spells.SpellsManager.selectCharacter
void selectCharacter()
A character name was sent to the server.
Definition: SpellsManager.java:388
com.realtime.crossfire.jxclient.util.EventListenerList2
A list of event listeners.
Definition: EventListenerList2.java:37
com.realtime.crossfire.jxclient.spells.SpellsManager
Manages all known spells.
Definition: SpellsManager.java:50
com.realtime.crossfire.jxclient.spells.SpellsManager.UPD_SP_DAMAGE
static final int UPD_SP_DAMAGE
Flag for updspell command: damage is present.
Definition: SpellsManager.java:65
com.realtime.crossfire.jxclient.spells.SpellsManager.getSpell
Spell getSpell(@NotNull final String spellName)
Returns a Spell instance by partial spell name.
Definition: SpellsManager.java:307
com.realtime.crossfire.jxclient.spells.SpellsManager.skillFilter
int skillFilter
Skill to filter spells by, as a skill id in SkillSet.
Definition: SpellsManager.java:83
com.realtime.crossfire.jxclient.spells.SpellsManager.getSpellSkill
Skill getSpellSkill(final int index)
Returns the specified spell skill.
Definition: SpellsManager.java:453
com.realtime.crossfire.jxclient.spells.SpellsManager.getFilteredSpellsCount
int getFilteredSpellsCount()
Returns the number of currently shown spells.
Definition: SpellsManager.java:351
com.realtime.crossfire.jxclient.spells.Spell
Describes a Crossfire spell.
Definition: Spell.java:37
com.realtime.crossfire.jxclient.spells.SpellsManager.filterSpells
void filterSpells()
Rebuilds the list of spells to display.
Definition: SpellsManager.java:419
com.realtime.crossfire.jxclient.guistate
Definition: ClientSocketState.java:23
com.realtime.crossfire.jxclient.spells.SpellsManager.SpellsManager
SpellsManager(@NotNull final GuiStateManager guiStateManager, @NotNull final SkillSet skillSet, @NotNull final Stats stats)
Creates a new instance.
Definition: SpellsManager.java:179
com.realtime.crossfire.jxclient.spells.SpellsManager.addSpell
void addSpell(final int tag, final int level, final int castingTime, final int mana, final int grace, final int damage, final int skill, final int path, final int faceNum, @NotNull final String spellName, @NotNull final String message)
Adds a new spell.
Definition: SpellsManager.java:216
com.realtime.crossfire.jxclient.spells.SpellsManager.updateSpell
void updateSpell(final int flags, final int tag, final int mana, final int grace, final int damage)
Updates spell information.
Definition: SpellsManager.java:256
com.realtime.crossfire.jxclient.spells.SpellsManagerListener
Interface for listeners interested in SpellsManager events.
Definition: SpellsManagerListener.java:31
com.realtime.crossfire.jxclient.skills
Definition: Skill.java:23
com.realtime.crossfire.jxclient.skills.Skill
One skill of the character.
Definition: Skill.java:35
com.realtime.crossfire.jxclient.guistate.GuiStateManager
Maintains the current GuiState.
Definition: GuiStateManager.java:34
com.realtime.crossfire.jxclient.spells.SpellsManager.deleteSpell
void deleteSpell(final int tag)
Deletes a spell.
Definition: SpellsManager.java:269
com.realtime.crossfire.jxclient.skills.SkillSet.getSkill
Skill getSkill(final int id)
Returns the given skill as a Skill object.
Definition: SkillSet.java:192
com.realtime.crossfire.jxclient.spells.Spell.setParameters
void setParameters(final int faceNum, final int tag, @NotNull final String message, final int level, final int castingTime, final int mana, final int grace, final int damage, final int skill, final int path)
Updates the spell's parameters.
Definition: Spell.java:251
com.realtime.crossfire.jxclient.stats.Stats
This is the representation of all the statistics of a player, like its speed or its experience.
Definition: Stats.java:44
com.realtime.crossfire.jxclient.spells.SpellsManager.removeCrossfireSpellChangedListener
void removeCrossfireSpellChangedListener(@NotNull final SpellsManagerListener listener)
Removes a SpellsManagerListener to notify about changes.
Definition: SpellsManager.java:197
com.realtime.crossfire.jxclient.util
Definition: Codec.java:23
com.realtime.crossfire.jxclient.skills.SkillSet.getSkillId
int getSkillId(final String name)
Get a skill identifier from the skill name.
Definition: SkillSet.java:202
com.realtime.crossfire.jxclient.spells.SpellComparator
A Comparator to compare Spell instances by spell path and name.
Definition: SpellComparator.java:34
com.realtime.crossfire.jxclient.spells.SpellsManager.displaysFace
boolean displaysFace(final int faceNum)
Returns whether any spell has the given face.
Definition: SpellsManager.java:375
com.realtime.crossfire.jxclient.spells.SpellsManager.UPD_SP_GRACE
static final int UPD_SP_GRACE
Flag for updspell command: grace is present.
Definition: SpellsManager.java:60
com.realtime.crossfire
com.realtime
com.realtime.crossfire.jxclient.spells.SpellsManager.filteredSpells
final List< Spell > filteredSpells
Spells currently exposed, based on the filter.
Definition: SpellsManager.java:77
com.realtime.crossfire.jxclient.spells.Spell.getName
String getName()
Returns the spell name.
Definition: Spell.java:198
com
com.realtime.crossfire.jxclient.spells.SpellsManager.skillAll
final Skill skillAll
Dummy skill for "all skills".
Definition: SpellsManager.java:166
com.realtime.crossfire.jxclient.spells.SpellsManager.spellNameComparator
final Comparator< Spell > spellNameComparator
A Comparator to compare Spell instances by spell path and name.
Definition: SpellsManager.java:104
com.realtime.crossfire.jxclient.spells.SpellsManager.spells
final List< Spell > spells
All known spells.
Definition: SpellsManager.java:71
com.realtime.crossfire.jxclient.guistate.ClientSocketState
Connection progress states of the Crossfire server connection.
Definition: ClientSocketState.java:30
com.realtime.crossfire.jxclient.spells.SpellsManager.rebuildSkills
void rebuildSkills()
Rebuilds the list of skills from the spells.
Definition: SpellsManager.java:427
com.realtime.crossfire.jxclient.spells.SpellsManager.getFilteredSpell
Spell getFilteredSpell(final int index)
Returns a Spell instance by index.
Definition: SpellsManager.java:362
com.realtime.crossfire.jxclient.skills.SkillSet
Maintain the set of skills as sent by the server.
Definition: SkillSet.java:39
com.realtime.crossfire.jxclient.spells.SpellsManager.stats
final Stats stats
The Stats for the player.
Definition: SpellsManager.java:161
com.realtime.crossfire.jxclient.spells.SpellsManager.spellSkills
final List< Skill > spellSkills
Skills used by the spell, including the "all" skill.
Definition: SpellsManager.java:171
com.realtime.crossfire.jxclient.spells.Spell.setUnknown
void setUnknown(final boolean unknown)
Marks this spell as known or unknown for the character.
Definition: Spell.java:231
com.realtime.crossfire.jxclient.spells.SpellsManager.getAllSpells
Collection< Spell > getAllSpells()
Returns all known spells.
Definition: SpellsManager.java:334
com.realtime.crossfire.jxclient.spells.SpellsManager.listeners
final EventListenerList2< SpellsManagerListener > listeners
The SpellsManagerListeners to notify about changes.
Definition: SpellsManager.java:97
com.realtime.crossfire.jxclient.stats
Definition: ActiveSkillWatcher.java:23