Crossfire JXClient, Trunk
CfAnimations.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.map;
24 
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Map;
38 import java.util.Random;
39 import org.jetbrains.annotations.NotNull;
40 import org.jetbrains.annotations.Nullable;
41 
46 public class CfAnimations {
47 
51  @NotNull
52  private static final Object SYNC = new Object();
53 
57  @NotNull
58  private final ItemSet itemSet;
59 
63  @NotNull
64  private final FacesManager facesManager;
65 
69  @NotNull
70  private final Animations animations;
71 
75  @NotNull
76  private final Collection<Integer> unknownAnimations = new HashSet<>();
77 
82  @NotNull
83  private final Random random = new Random();
84 
88  @NotNull
89  @SuppressWarnings("FieldCanBeLocal")
91 
92  @Override
93  public void playerChanged(@Nullable final CfItem player) {
94  if (!tags.isEmpty()) {
95  System.err.println("Warning: player inventory is not empty when changing players");
96  for (final int tag : tags.values()) {
97  tagRemove(tag);
98  }
99  tags.clear();
100  }
101 
102  if (playerTag != -1) {
104  }
105  playerTag = player == null ? -1 : player.getTag();
106  if (playerTag != -1) {
108  }
109  }
110 
111  @Override
112  public void openContainerChanged(final int tag) {
113  }
114 
115  };
116 
120  @NotNull
121  @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
123 
124  @NotNull
125  @Override
126  public Object mapBegin() {
127  return SYNC;
128  }
129 
130  @Override
131  public void mapFace(@NotNull final Location location, final int faceNum) {
132  }
133 
134  @Override
135  public void mapEnd() {
136  }
137 
138  };
139 
143  private int mapWidth;
144 
148  private int mapHeight;
149 
153  @NotNull
154  private final AnimationMap mapAnimations = new AnimationMap();
155 
159  @NotNull
160  private final AnimationSet tagAnimations = new AnimationSet();
161 
166  @NotNull
167  private final Collection<AnimationState> animationStates = new HashSet<>();
168 
172  @NotNull
173  private final Map<Integer, AnimationState> syncAnimationStates = new HashMap<>();
174 
179  @NotNull
180  private final Collection<AnimationState> pendingTickUpdates = new ArrayList<>();
181 
185  @NotNull
187 
188  @Override
189  public void itemChanged(final int tag) {
190  }
191 
192  @Override
193  public void itemRemoved(final int tag) {
194  }
195 
196  @Override
197  public void inventoryAdded(final int tag, final int index, @NotNull final CfItem item) {
198  final int itemTag = item.getTag();
199  final int anim = item.getAnim();
200  final int animSpeed = item.getAnimSpeed();
201  if (anim != 0) {
202  final Animation animation = animations.get(anim&Map2.ANIM_MASK);
203  if (animation == null) {
204  if (unknownAnimations.add(anim&Map2.ANIM_MASK)) {
205  System.err.println("Unknown animation id "+(anim&Map2.ANIM_MASK)+", ignoring");
206  }
207  return;
208  }
209 
210  final Integer prevTag = tags.put(index, itemTag);
211  if (prevTag != null) {
212  tagRemove(prevTag);
213  }
214  tagAdd(itemTag, animation, (anim>>Map2.ANIM_TYPE_SHIFT)&Map2.ANIM_TYPE_MASK);
215  tagAnimations.updateSpeed(itemTag, animSpeed);
216  }
217  }
218 
219  @Override
220  public void inventoryRemoved(final int tag, final int index) {
221  final Integer prevTag = tags.remove(index);
222  if (prevTag == null) {
223  return;
224  }
225 
226  tagRemove(prevTag);
227  }
228 
229  };
230 
234  @NotNull
235  private final Map<Integer, Integer> tags = new HashMap<>();
236 
240  private int playerTag = -1;
241 
248  public CfAnimations(@NotNull final ItemSet itemSet, @NotNull final FacesManager facesManager, @NotNull final Animations animations) {
249  this.itemSet = itemSet;
250  this.facesManager = facesManager;
251  this.animations = animations;
252 
254  }
255 
260  public void setMapListener(@NotNull final CfAnimationsMapListener mapListener) {
261  this.mapListener = mapListener;
262  }
263 
267  public void mapClear() {
269  final Collection<AnimationState> tagAnimationStates = tagAnimations.getAllAnimationStates();
270  animationStates.retainAll(tagAnimationStates);
271  for (final AnimationState animationState : animationStates) {
272  animationState.freeAllLocations();
273  }
274  syncAnimationStates.values().retainAll(tagAnimationStates);
275  pendingTickUpdates.retainAll(tagAnimationStates);
276  }
277 
284  public void mapAdd(@NotNull final Location location, @NotNull final Animation animation, final int type) {
285  mapAnimations.add(location, add(animation, type));
286  }
287 
293  public void mapRemove(final int x, final int y) {
294  for (int layer = 0; layer < Map2.NUM_LAYERS; layer++) {
295  mapAnimations.remove(new Location(x, y, layer));
296  }
297  }
298 
303  public void mapRemove(@NotNull final Location location) {
304  mapAnimations.remove(location);
305  }
306 
312  public void mapUpdateSpeed(@NotNull final Location location, final int speed) {
313  mapAnimations.updateSpeed(location, speed);
314  }
315 
322  public void mapScroll(final int dx, final int dy) {
324  }
325 
331  public void mapSetSize(final int mapWidth, final int mapHeight) {
332  this.mapWidth = mapWidth;
333  this.mapHeight = mapHeight;
334  mapClear();
335  }
336 
341  public void tick(final int tickNo) {
342  for (AnimationState animationState : pendingTickUpdates) {
343  animationState.setTickNo(tickNo);
344  }
345  pendingTickUpdates.clear();
346  final Iterable<AnimationState> animationStatesToUpdate = new ArrayList<>(animationStates);
347  synchronized (mapListener.mapBegin()) {
348  for (AnimationState animationState : animationStatesToUpdate) {
349  animationState.updateTickNo(tickNo);
350  }
352  }
353  }
354 
361  private void tagAdd(final int tag, @NotNull final Animation animation, final int type) {
362  tagAnimations.add(tag, add(animation, type));
363  }
364 
369  private void tagRemove(final int tag) {
370  tagAnimations.remove(tag);
371  }
372 
379  @NotNull
380  private AnimationState add(@NotNull final Animation animation, final int type) {
381  assert 0 <= type && type < 4;
382 
383  final AnimationState animationState;
384  final boolean addToPendingTickUpdates;
385  switch (type) {
386  default: // invalid; treated as "normal"
387  case Map2.ANIM_NORMAL: // animation starts at index 0
388  animationState = new AnimationState(animation, 0, mapListener, itemSet, facesManager);
389  addToPendingTickUpdates = true;
390  break;
391 
392  case Map2.ANIM_RANDOM: // animation starts at random index
393  animationState = new AnimationState(animation, random.nextInt(animation.getFaces()), mapListener, itemSet, facesManager);
394  addToPendingTickUpdates = true;
395  break;
396 
397  case Map2.ANIM_SYNC: // animation is synchronized with other animations
398  final int animationId = animation.getAnimationId();
399  final AnimationState tmp = syncAnimationStates.get(animationId);
400  if (tmp == null) {
401  animationState = new AnimationState(animation, 0, mapListener, itemSet, facesManager);
402  syncAnimationStates.put(animationId, animationState);
403  addToPendingTickUpdates = true;
404  } else {
405  animationState = tmp;
406  addToPendingTickUpdates = false;
407  }
408  break;
409  }
410 
411  animationStates.add(animationState);
412  if (addToPendingTickUpdates) {
413  pendingTickUpdates.add(animationState);
414  }
415 
416  return animationState;
417  }
418 
419 }
com.realtime.crossfire.jxclient
com.realtime.crossfire.jxclient.map.CfAnimations.itemSet
final ItemSet itemSet
Definition: CfAnimations.java:58
com.realtime.crossfire.jxclient.map.AnimationMap.add
void add(@NotNull final Location location, @NotNull final AnimationState animationState)
Definition: AnimationMap.java:58
com.realtime.crossfire.jxclient.map.CfAnimations
Definition: CfAnimations.java:46
com.realtime.crossfire.jxclient.map.AnimationMap
Definition: AnimationMap.java:36
com.realtime.crossfire.jxclient.map.CfAnimations.mapRemove
void mapRemove(final int x, final int y)
Definition: CfAnimations.java:293
com.realtime.crossfire.jxclient.items.ItemSet.removeInventoryListener
void removeInventoryListener(final int tag, @NotNull final ItemListener listener)
Definition: ItemSet.java:121
com.realtime.crossfire.jxclient.animations.Animations.get
Animation get(final int animationId)
Definition: Animations.java:125
com.realtime.crossfire.jxclient.map.CfAnimations.mapClear
void mapClear()
Definition: CfAnimations.java:267
com.realtime.crossfire.jxclient.map.AnimationSet.add
void add(final int tag, @NotNull final AnimationState animationState)
Definition: AnimationSet.java:51
com.realtime.crossfire.jxclient.map.CfAnimationsMapListener.mapBegin
Object mapBegin()
com.realtime.crossfire.jxclient.map.CfAnimations.animations
final Animations animations
Definition: CfAnimations.java:70
com.realtime.crossfire.jxclient.items.ItemListener
Definition: ItemListener.java:32
com.realtime.crossfire.jxclient.map.CfAnimations.SYNC
static final Object SYNC
Definition: CfAnimations.java:52
com.realtime.crossfire.jxclient.map.CfAnimations.itemSetListener
final ItemSetListener itemSetListener
Definition: CfAnimations.java:90
com.realtime.crossfire.jxclient.map.CfAnimations.mapListener
CfAnimationsMapListener mapListener
Definition: CfAnimations.java:122
com.realtime.crossfire.jxclient.map.CfAnimations.mapScroll
void mapScroll(final int dx, final int dy)
Definition: CfAnimations.java:322
com.realtime.crossfire.jxclient.map.CfAnimations.playerInventoryListener
final ItemListener playerInventoryListener
Definition: CfAnimations.java:186
com.realtime.crossfire.jxclient.protocol.Map2.ANIM_NORMAL
int ANIM_NORMAL
Definition: Map2.java:119
com.realtime.crossfire.jxclient.map.CfAnimations.mapWidth
int mapWidth
Definition: CfAnimations.java:143
com.realtime.crossfire.jxclient.map.AnimationMap.scroll
void scroll(final int dx, final int dy, final int width, final int height)
Definition: AnimationMap.java:93
com.realtime.crossfire.jxclient.items.ItemSet
Definition: ItemSet.java:44
com.realtime.crossfire.jxclient.map.CfAnimations.tagAdd
void tagAdd(final int tag, @NotNull final Animation animation, final int type)
Definition: CfAnimations.java:361
com.realtime.crossfire.jxclient.map.AnimationSet.remove
void remove(final int tag)
Definition: AnimationSet.java:60
com.realtime.crossfire.jxclient.map.CfAnimations.mapAnimations
final AnimationMap mapAnimations
Definition: CfAnimations.java:154
com.realtime.crossfire.jxclient.map.AnimationSet.getAllAnimationStates
Collection< AnimationState > getAllAnimationStates()
Definition: AnimationSet.java:85
com.realtime.crossfire.jxclient.faces
Definition: AbstractFaceQueue.java:23
com.realtime.crossfire.jxclient.map.CfAnimations.random
final Random random
Definition: CfAnimations.java:83
com.realtime.crossfire.jxclient.protocol.Map2.ANIM_MASK
int ANIM_MASK
Definition: Map2.java:135
com.realtime.crossfire.jxclient.protocol
Definition: MagicMap.java:23
com.realtime.crossfire.jxclient.map.Location
Definition: Location.java:32
com.realtime.crossfire.jxclient.protocol.Map2.NUM_LAYERS
int NUM_LAYERS
Definition: Map2.java:34
com.realtime.crossfire.jxclient.map.AnimationMap.remove
void remove(@NotNull final Location location)
Definition: AnimationMap.java:67
com.realtime.crossfire.jxclient.map.CfAnimations.tagAnimations
final AnimationSet tagAnimations
Definition: CfAnimations.java:160
com.realtime.crossfire.jxclient.map.CfAnimations.mapHeight
int mapHeight
Definition: CfAnimations.java:148
com.realtime.crossfire.jxclient.animations
Definition: Animation.java:23
com.realtime.crossfire.jxclient.map.CfAnimations.tags
final Map< Integer, Integer > tags
Definition: CfAnimations.java:235
com.realtime.crossfire.jxclient.protocol.Map2.ANIM_SYNC
int ANIM_SYNC
Definition: Map2.java:130
com.realtime.crossfire.jxclient.map.CfAnimations.mapSetSize
void mapSetSize(final int mapWidth, final int mapHeight)
Definition: CfAnimations.java:331
com.realtime.crossfire.jxclient.protocol.Map2
Definition: Map2.java:29
com.realtime.crossfire.jxclient.items.CfItem
Definition: CfItem.java:37
com.realtime.crossfire.jxclient.map.CfAnimations.pendingTickUpdates
final Collection< AnimationState > pendingTickUpdates
Definition: CfAnimations.java:180
com.realtime.crossfire.jxclient.map.CfAnimations.syncAnimationStates
final Map< Integer, AnimationState > syncAnimationStates
Definition: CfAnimations.java:173
com.realtime.crossfire.jxclient.map.CfAnimations.unknownAnimations
final Collection< Integer > unknownAnimations
Definition: CfAnimations.java:76
com.realtime.crossfire.jxclient.map.AnimationSet
Definition: AnimationSet.java:36
com.realtime.crossfire.jxclient.map.CfAnimations.animationStates
final Collection< AnimationState > animationStates
Definition: CfAnimations.java:167
com.realtime.crossfire.jxclient.faces.FacesManager
Definition: FacesManager.java:40
com.realtime.crossfire.jxclient.map.AnimationMap.clear
void clear()
Definition: AnimationMap.java:48
com.realtime.crossfire
com.realtime.crossfire.jxclient.map.CfAnimations.setMapListener
void setMapListener(@NotNull final CfAnimationsMapListener mapListener)
Definition: CfAnimations.java:260
com.realtime.crossfire.jxclient.map.AnimationState
Definition: AnimationState.java:41
com.realtime
com.realtime.crossfire.jxclient.map.CfAnimations.add
AnimationState add(@NotNull final Animation animation, final int type)
Definition: CfAnimations.java:380
com.realtime.crossfire.jxclient.items.ItemSet.addInventoryListener
void addInventoryListener(final int tag, @NotNull final ItemListener listener)
Definition: ItemSet.java:112
com
com.realtime.crossfire.jxclient.items.ItemSet.addItemSetListener
void addItemSetListener(@NotNull final ItemSetListener listener)
Definition: ItemSet.java:95
com.realtime.crossfire.jxclient.map.CfAnimationsMapListener.mapEnd
void mapEnd()
com.realtime.crossfire.jxclient.animations.Animations
Definition: Animations.java:38
com.realtime.crossfire.jxclient.items
Definition: AbstractItemView.java:23
com.realtime.crossfire.jxclient.map.CfAnimations.tagRemove
void tagRemove(final int tag)
Definition: CfAnimations.java:369
com.realtime.crossfire.jxclient.protocol.Map2.ANIM_TYPE_MASK
int ANIM_TYPE_MASK
Definition: Map2.java:146
com.realtime.crossfire.jxclient.map.CfAnimations.CfAnimations
CfAnimations(@NotNull final ItemSet itemSet, @NotNull final FacesManager facesManager, @NotNull final Animations animations)
Definition: CfAnimations.java:248
com.realtime.crossfire.jxclient.map.CfAnimations.mapRemove
void mapRemove(@NotNull final Location location)
Definition: CfAnimations.java:303
com.realtime.crossfire.jxclient.animations.Animation
Definition: Animation.java:32
com.realtime.crossfire.jxclient.map.CfAnimationsMapListener
Definition: CfAnimationsMapListener.java:5
com.realtime.crossfire.jxclient.items.ItemSetListener
Definition: ItemSetListener.java:32
com.realtime.crossfire.jxclient.protocol.Map2.ANIM_TYPE_SHIFT
int ANIM_TYPE_SHIFT
Definition: Map2.java:140
com.realtime.crossfire.jxclient.map.CfAnimations.mapUpdateSpeed
void mapUpdateSpeed(@NotNull final Location location, final int speed)
Definition: CfAnimations.java:312
com.realtime.crossfire.jxclient.map.CfAnimations.playerTag
int playerTag
Definition: CfAnimations.java:240
com.realtime.crossfire.jxclient.map.CfAnimations.mapAdd
void mapAdd(@NotNull final Location location, @NotNull final Animation animation, final int type)
Definition: CfAnimations.java:284
com.realtime.crossfire.jxclient.protocol.Map2.ANIM_RANDOM
int ANIM_RANDOM
Definition: Map2.java:124
com.realtime.crossfire.jxclient.map.AnimationMap.updateSpeed
void updateSpeed(@NotNull final Location location, final int speed)
Definition: AnimationMap.java:76
com.realtime.crossfire.jxclient.map.CfAnimations.tick
void tick(final int tickNo)
Definition: CfAnimations.java:341
com.realtime.crossfire.jxclient.map.CfAnimations.facesManager
final FacesManager facesManager
Definition: CfAnimations.java:64
com.realtime.crossfire.jxclient.map.AnimationSet.updateSpeed
void updateSpeed(final int tag, final int speed)
Definition: AnimationSet.java:69