Crossfire JXClient, Trunk  R20561
AskfaceFaceQueue.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-2011 Andreas Kirschbaum.
20  */
21 
22 package com.realtime.crossfire.jxclient.faces;
23 
24 import java.nio.ByteBuffer;
25 import java.util.HashMap;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.Map;
29 import javax.swing.ImageIcon;
30 import org.jetbrains.annotations.NotNull;
31 
37 public class AskfaceFaceQueue extends AbstractFaceQueue {
38 
44  private static final int CONCURRENT_ASKFACE_COMMANDS = 8;
45 
49  @NotNull
50  private final Object sync = new Object();
51 
55  @NotNull
56  private final AskfaceQueue askfaceQueue;
57 
63  @NotNull
64  private final Map<Integer, Face> pendingAskfaces = new HashMap<>();
65 
70  @NotNull
71  private final Map<Integer, Face> pendingFaces = new HashMap<>();
72 
76  @NotNull
77  private final List<Face> pendingFacesQueue = new LinkedList<>();
78 
83  public AskfaceFaceQueue(@NotNull final AskfaceQueue askfaceQueue) {
84  this.askfaceQueue = askfaceQueue;
85  }
86 
90  @Override
91  public void reset() {
92  synchronized (sync) {
93  pendingAskfaces.clear();
94  pendingFaces.clear();
95  pendingFacesQueue.clear();
96  }
97  }
98 
102  @Override
103  public void loadFace(@NotNull final Face face) {
104  final int faceNum = face.getFaceNum();
105  if (faceNum <= 0 || faceNum > 65535) {
106  fireFaceFailed(face);
107  return;
108  }
109 
110  final Integer faceObject = faceNum;
111  synchronized (sync) {
112  if (pendingFaces.put(faceObject, face) != null) {
113  // move image to front of queue
114  pendingFacesQueue.remove(face);
115  pendingFacesQueue.add(0, face);
116  return;
117  }
118  pendingFacesQueue.add(0, face);
119 
120  sendAskface();
121  }
122  }
123 
127  private void sendAskface() {
128  for (final Face face : pendingFacesQueue) {
129  if (pendingAskfaces.size() >= CONCURRENT_ASKFACE_COMMANDS) {
130  break;
131  }
132 
133  final int faceNum = face.getFaceNum();
134  if (pendingAskfaces.put(faceNum, face) == null) {
135  askfaceQueue.sendAskface(faceNum);
136  }
137  }
138  }
139 
147  public void faceReceived(final int faceNum, final int faceSetNum, @NotNull final ByteBuffer packet) {
148  final Integer faceObject = faceNum;
149  synchronized (sync) {
150  final Face face = pendingAskfaces.remove(faceObject);
151  if (face == null) {
152  System.err.println("received unexpected image for face "+faceNum);
153  } else {
154  if (pendingFaces.remove(faceObject) != face) {
155  assert false;
156  }
157  if (!pendingFacesQueue.remove(face)) {
158  assert false;
159  }
160 
161  final byte[] data = new byte[packet.remaining()];
162  packet.get(data);
163  processFaceData(face, data);
164  }
165  sendAskface();
166  }
167  }
168 
174  private void processFaceData(@NotNull final Face face, @NotNull final byte[] data) {
175  final ImageIcon originalImageIcon;
176  try {
177  originalImageIcon = new ImageIcon(data);
178  } catch (final IllegalArgumentException ex) {
179  System.err.println("Invalid .png data for face "+face+": "+ex.getMessage());
180  return;
181  }
182 
183  if (originalImageIcon.getIconWidth() <= 0 || originalImageIcon.getIconHeight() <= 0) {
184  fireFaceFailed(face);
185  return;
186  }
187 
188  fireFaceLoaded(face, FaceImagesUtils.newFaceImages(originalImageIcon));
189  }
190 
191 }
static FaceImages newFaceImages(@NotNull final ImageIcon originalImageIcon)
Creates a new FaceImages instance from an "original" face; the "scaled" and "magic map" sized images ...
final Map< Integer, Face > pendingFaces
Face numbers for which an "askface" command should be sent.
Utility class for creating FaceImages instances.
void faceReceived(final int faceNum, final int faceSetNum, @NotNull final ByteBuffer packet)
Notifies the askface manager that image information have been received from the server.
final Map< Integer, Face > pendingAskfaces
Face numbers for which "askface" commands have been sent without having received a response from the ...
Interface for classes that allow sending "askface" commands.
void fireFaceLoaded(@NotNull final Face face, @NotNull final FaceImages faceImages)
Notify all listener with FaceImages).
Abstract base class for classes implementing FaceQueue.
final Object sync
The object use for synchronization.
void fireFaceFailed(@NotNull final Face face)
Notify all listener with FaceQueueListener#faceFailed(Face).
void sendAskface(int faceNum)
Sends an "askface" command.
void sendAskface()
Sends some pending "askface" commands.
void reset()
Reset the processing: forget about pending faces.This function is called whenever the server socket b...
A FaceQueue requesting faces by "askface" commands sent to the Crossfire server.
final AskfaceQueue askfaceQueue
The connection to use.
static final int CONCURRENT_ASKFACE_COMMANDS
The maximum number of concurrently sent "askface" commands.
AskfaceFaceQueue(@NotNull final AskfaceQueue askfaceQueue)
Creates a new instance.
void loadFace(@NotNull final Face face)
Request a face.Must eventually call either FaceQueueListener#faceLoaded(Face, FaceImages) or FaceQueu...
final List< Face > pendingFacesQueue
The same elements as pendingFaces in query order.
void processFaceData(@NotNull final Face face, @NotNull final byte[] data)
Processes face information received from the server.