ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/socket/image.C
Revision: 1.59
Committed: Thu Sep 17 01:57:31 2009 UTC (14 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.58: +1 -1 lines
Log Message:
just a simplification

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.55 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.42 *
4 root 1.56 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.42 * Copyright (©) 2001,2007 Mark Wedel
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7     *
8 root 1.55 * Deliantra is free software: you can redistribute it and/or modify
9 root 1.44 * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 root 1.42 *
13 root 1.44 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 root 1.42 *
18 root 1.44 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.42 *
21 root 1.55 * The authors can be reached via e-mail to <support@deliantra.net>
22 root 1.17 */
23 elmex 1.1
24     /** \file
25     * Image related communication
26     *
27     * \date 2003-12-02
28     *
29     * This file deals with the image related communication to the
30     * client. I've located all the functions in this file - this
31     * localizes it more, and means that we don't need to declare
32     * things like all the structures as globals.
33     */
34    
35     #include <global.h>
36     #include <sproto.h>
37    
38 root 1.20 #include "crc.h"
39    
40 elmex 1.1 #define MAX_IMAGE_SIZE 10000
41    
42     /**
43 root 1.43 * client requested an image. send it rate-limited
44     * before flushing.
45 elmex 1.1 */
46 root 1.3 void
47 root 1.43 AskFaceCmd (char *buf, int len, client *ns)
48 elmex 1.1 {
49 root 1.43 int idx = 0, pri = 0;
50    
51     sscanf (buf, "%d %d", &idx, &pri);
52    
53 root 1.51 //TODO: somehow fetch default priority from send_fx here
54    
55 root 1.43 const facedata *d = face_data (idx, ns->faceset);
56    
57     if (!d)
58     return; // doh
59    
60     client::ixsend ix;
61    
62     ix.pri = pri;
63     ix.idx = idx;
64     ix.ofs = d->data.size ();
65    
66 root 1.46 auto (pos, ns->ixface.end ());
67    
68 root 1.58 // the by far most common case will be to insert
69     // near the end, so little looping.
70     while (pos != ns->ixface.begin ())
71 root 1.46 {
72 root 1.58 --pos;
73    
74     // sort within 2k bins, to slightly prefer smaller images
75     if (pri > pos->pri || (pri == pos->pri && (ix.ofs >> 11) <= (pos->ofs >> 11)))
76 root 1.46 {
77 root 1.58 ++pos;
78     break;
79 root 1.46 }
80     }
81    
82     ns->ixface.insert (pos, ix);
83 root 1.45
84     #if 0
85 root 1.46 for (auto (i, ns->ixface.begin ()); i != ns->ixface.end (); ++i)
86     fprintf (stderr, "<%d,%d> ", i->pri, i->ofs);
87     fprintf (stderr, "\n");
88 root 1.45 #endif
89 root 1.43 }
90    
91     /**
92 elmex 1.1 * Sends a face to a client if they are in pixmap mode
93     * nothing gets sent in bitmap mode.
94     * If nocache is true (nonzero), ignore the cache setting from the client -
95     * this is needed for the askface, in which we really do want to send the
96     * face (and askface is the only place that should be setting it). Otherwise,
97     * we look at the facecache, and if set, send the image name.
98     */
99 root 1.3 void
100 root 1.50 client::send_face (faceidx facenum, int pri)
101 elmex 1.1 {
102 root 1.28 // never send face 0. ever. it does not exist.
103     if (!facenum)
104     return;
105    
106 root 1.50 faceinfo *f = face_info (facenum);
107 root 1.28
108 root 1.50 if (!f)
109 root 1.3 {
110 root 1.54 LOG (llevError | logBacktrace, "client::send_face (%d) out of bounds??\n", facenum);
111 root 1.3 return;
112     }
113    
114 root 1.50 // refuse to send non-image faces
115     if (!fx_want [f->type])
116     return;
117 root 1.49
118 root 1.50 if (faces_sent [facenum])
119 root 1.48 return;
120    
121 root 1.50 faces_sent[facenum] = true;
122 root 1.32
123 root 1.58 fxface.push_back (facenum);
124 root 1.32 }
125    
126 root 1.39 void client::flush_fx ()
127     {
128     while (!fxface.empty ())
129     {
130 root 1.40 packet fx ("fx");
131     packet sx ("sx");
132 root 1.50 int type = 0;
133 root 1.39
134     do
135     {
136     faceidx facenum = fxface.back (); fxface.pop_back ();
137    
138 root 1.50 if (const faceinfo *f = face_info (facenum))
139     {
140     if (f->type != type)
141     {
142     type = f->type;
143    
144     fx << ber32 (0)
145     << uint8 (1) << uint8 (type);
146     }
147    
148     const facedata *d = f->data (faceset);
149 root 1.39
150 root 1.40 fx << ber32 (facenum)
151 root 1.39 << data8 (d->chksum, CHKSUM_SIZE);
152    
153 root 1.40 if (smoothing)
154     {
155     faceinfo *f = face_info (facenum);
156    
157     if (f->smooth)
158     {
159 root 1.50 send_face (f->smooth, -110);
160    
161 root 1.40 sx << ber32 (facenum)
162     << ber32 (f->smooth)
163     << ber32 (f->smoothlevel);
164     }
165     }
166 root 1.39 }
167     }
168 root 1.40 while (!fxface.empty ()
169 root 1.50 && fx.room () > ber32::size + CHKSUM_SIZE + 1 + 3 /* type switch */
170 root 1.40 && sx.room () > ber32::size * 3);
171 root 1.39
172 root 1.40 send_packet (fx);
173     if (sx.length () > 3) send_packet (sx);
174 root 1.39 }
175     }
176    
177 root 1.28 // send all faces of this object to the client
178     // this uses more bandwidth initially, but makes
179     // animations look much smoother, and every client
180     // is supposed to do client-side caching anyways.
181     void
182     client::send_faces (object *ob)
183     {
184 root 1.50 send_face (ob->face, 10);
185 root 1.28
186     if (ob->animation_id)
187     {
188 root 1.59 const animation &anim = ob->anim ();
189 root 1.28
190     for (int i = 0; i < anim.num_animations; i++)
191 root 1.50 send_face (anim.faces [i], -10);
192 root 1.28 }
193     }
194    
195     /**
196     * Need to send an animation sequence to the client.
197     * We will send appropriate face commands to the client if we haven't
198     * sent them the face yet (this can become quite costly in terms of
199     * how much we are sending - on the other hand, this should only happen
200     * when the player logs in and picks stuff up.
201     */
202     void
203     client::send_animation (short anim_num)
204     {
205     /* Do some checking on the anim_num we got. Note that the animations
206     * are added in contigous order, so if the number is in the valid
207     * range, it must be a valid animation.
208     */
209 root 1.41 if (anim_num < 0 || anim_num >= animations.size ())
210 root 1.28 {
211     LOG (llevError, "esrv_send_anim (%d) out of bounds??\n", anim_num);
212     return;
213     }
214    
215     packet sl ("anim");
216    
217     sl << uint16 (anim_num)
218     << uint16 (0); /* flags - not used right now */
219    
220     /* Build up the list of faces. Also, send any information (ie, the
221     * the face itself) down to the client.
222     */
223     for (int i = 0; i < animations[anim_num].num_animations; i++)
224     {
225 root 1.50 send_face (animations[anim_num].faces[i], -20);
226 root 1.28 sl << uint16 (animations[anim_num].faces[i]); /* flags - not used right now */
227 elmex 1.1 }
228 root 1.6
229 root 1.28 send_packet (sl);
230    
231     anims_sent[anim_num] = 1;
232 elmex 1.1 }
233    
234     /**
235     * Sends the number of images, checksum of the face file,
236     * and the image_info file information. See the doc/Developers/protocol
237     * if you want further detail.
238     */
239 root 1.3 void
240 root 1.15 send_image_info (client *ns, char *params)
241 elmex 1.1 {
242 root 1.8 packet sl;
243 elmex 1.1
244 root 1.24 //TODO: second parameter is a checksum, but it makes no sense in this current framework
245     sl.printf ("replyinfo image_info\n%d\n%u\n", MAX_FACES, 0);
246 root 1.6
247 root 1.24 sl << "0:base:standard:0:32x32:none:The old 32x32 faceset.\n";
248 elmex 1.1
249 root 1.11 ns->send_packet (sl);
250 elmex 1.1 }
251    
252     /**
253     * Sends requested face information.
254     * \param ns socket to send to
255     * \param params contains first and last index of face
256     *
257     * For each image in [start..stop] sends
258     * - checksum
259     * - name
260     */
261 root 1.3 void
262 root 1.15 send_image_sums (client *ns, char *params)
263 elmex 1.1 {
264 root 1.3 int start, stop;
265 pippijn 1.22 char *cp;
266 root 1.3
267 root 1.8 packet sl;
268 root 1.3
269     start = atoi (params);
270     for (cp = params; *cp != '\0'; cp++)
271     if (*cp == ' ')
272     break;
273    
274     stop = atoi (cp);
275 root 1.24 if (stop < start || *cp == '\0' || (stop - start) > 1000 || stop >= MAX_FACES)
276 root 1.3 {
277 root 1.7 sl.printf ("replyinfo image_sums %d %d", start, stop);
278     ns->send_packet (sl);
279     sl.reset ();
280 root 1.3 return;
281     }
282    
283 root 1.6 sl.printf ("replyinfo image_sums %d %d ", start, stop);
284 root 1.3
285 root 1.24 for (int i = start; i <= stop && i < faces.size (); i++)
286 root 1.53 if (const faceinfo *f = face_info (i))
287     if (ns->fx_want [f->type])
288     {
289     ns->faces_sent[i] = true;
290    
291     const facedata *d = f->data (ns->faceset);
292    
293     if (sl.room () < 2 + 4 + 1 + d->data.size () + 1)
294     break;
295    
296     sl << uint16 (i)
297     << uint32 (0) // checksum
298     << uint8 (ns->faceset);
299 root 1.23
300 root 1.58 for (int i = 0; i < CHKSUM_SIZE; ++i)
301     sl.printf ("%02x", d->chksum [i]);
302    
303     sl << uint8 (0);
304 root 1.53 }
305 root 1.6
306 root 1.3 /* It would make more sense to catch this pre-emptively in the code above.
307     * however, if this really happens, we probably just want to cut down the
308     * size to less than 1000, since that is what we claim the protocol would
309     * support.
310     */
311 root 1.23 //TODO: taken care of above, should simply abort or make sure the above code is correct
312 root 1.52 if (sl.length () > MAXSOCKBUF)
313 root 1.3 {
314 root 1.9 LOG (llevError, "send_image_send: buffer overrun, %d > %d\n", sl.length (), MAXSOCKBUF);
315 root 1.3 abort ();
316 elmex 1.1 }
317 root 1.6
318 root 1.11 ns->send_packet (sl);
319 elmex 1.1 }
320 root 1.6