ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/socket/image.C
Revision: 1.56
Committed: Tue May 6 16:55:26 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_6, rel-2_7, rel-2_72, rel-2_73, rel-2_71, rel-2_54, rel-2_55, rel-2_56, rel-2_61
Changes since 1.55: +1 -1 lines
Log Message:
update copyright

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     * Client tells us what type of faces it wants. Also sets
44     * the caching attribute.
45     *
46     */
47 root 1.3 void
48 root 1.13 SetFaceMode (char *buf, int len, client *ns)
49 elmex 1.1 {
50 root 1.3 int mask = (atoi (buf) & CF_FACE_CACHE), mode = (atoi (buf) & ~CF_FACE_CACHE);
51 elmex 1.1
52 root 1.3 if (mode == CF_FACE_NONE)
53 root 1.7 ns->facecache = 1;
54 root 1.3 else if (mode != CF_FACE_PNG)
55 root 1.14 ns->send_packet_printf ("drawinfo %d %s", NDI_RED, "Warning - send unsupported face mode. Will use Png");
56 root 1.7
57 root 1.3 if (mask)
58 root 1.7 ns->facecache = 1;
59 elmex 1.1 }
60    
61     /**
62 root 1.43 * client requested an image. send it rate-limited
63     * before flushing.
64 elmex 1.1 */
65 root 1.3 void
66 root 1.43 AskFaceCmd (char *buf, int len, client *ns)
67 elmex 1.1 {
68 root 1.43 int idx = 0, pri = 0;
69    
70     sscanf (buf, "%d %d", &idx, &pri);
71    
72 root 1.51 //TODO: somehow fetch default priority from send_fx here
73    
74 root 1.43 const facedata *d = face_data (idx, ns->faceset);
75    
76     if (!d)
77     return; // doh
78    
79     client::ixsend ix;
80    
81     ix.pri = pri;
82     ix.idx = idx;
83     ix.ofs = d->data.size ();
84    
85 root 1.46 auto (pos, ns->ixface.end ());
86    
87     if (ns->fxix < 2)
88     {
89     // gcfclient does not support prioritising, older cfplus versions
90     // do not support interleaved transfers.
91     if (!ns->ixface.empty ())
92     pos = ns->ixface.end () - 1;
93     }
94     else
95     {
96     // the by far most common case will be to insert
97     // near the end, so little looping.
98     while (pos != ns->ixface.begin ())
99     {
100     --pos;
101    
102     // sort within 2k bins, to slightly prefer smaller images
103     if (pri > pos->pri || (pri == pos->pri && (ix.ofs >> 11) <= (pos->ofs >> 11)))
104     {
105     ++pos;
106     break;
107     }
108     }
109     }
110    
111     ns->ixface.insert (pos, ix);
112 root 1.45
113     #if 0
114 root 1.46 for (auto (i, ns->ixface.begin ()); i != ns->ixface.end (); ++i)
115     fprintf (stderr, "<%d,%d> ", i->pri, i->ofs);
116     fprintf (stderr, "\n");
117 root 1.45 #endif
118 root 1.43 }
119    
120     /**
121     * Tells client the picture it has to use
122     * to smooth a picture number given as argument.
123     */
124     void
125     AskSmooth (char *buf, int len, client *ns)
126     {
127 root 1.50 ns->send_face (atoi (buf), -100);
128 root 1.43 ns->flush_fx ();
129 elmex 1.1 }
130    
131 root 1.24 // how lame
132     static void print_facename (packet &sl, const facedata &d)
133     {
134 root 1.25 for (int i = 0; i < CHKSUM_SIZE; ++i)
135     sl.printf ("%02x", d.chksum [i]);
136 root 1.24 }
137    
138 root 1.32 // gcfclient uses the server-provided checksum for comparison, but always
139     // writes a broken checksum to its cache file, so we have to provide
140     // gcfclient with the same broken (and useless) checksum just to have it
141     // cache the image despite its bugs.
142 root 1.26 static uint32 gcfclient_checksum (const facedata *d)
143     {
144     uint32 csum = 0;
145    
146     for (std::string::const_iterator i = d->data.begin ();
147     i != d->data.end ();
148     ++i)
149     {
150     csum = rotate_right (csum);
151     csum += *(uint8 *)&*i;
152     }
153    
154     return csum;
155     }
156    
157 elmex 1.1 /**
158     * Sends a face to a client if they are in pixmap mode
159     * nothing gets sent in bitmap mode.
160     * If nocache is true (nonzero), ignore the cache setting from the client -
161     * this is needed for the askface, in which we really do want to send the
162     * face (and askface is the only place that should be setting it). Otherwise,
163     * we look at the facecache, and if set, send the image name.
164     */
165 root 1.3 void
166 root 1.50 client::send_face (faceidx facenum, int pri)
167 elmex 1.1 {
168 root 1.28 // never send face 0. ever. it does not exist.
169     if (!facenum)
170     return;
171    
172 root 1.50 faceinfo *f = face_info (facenum);
173 root 1.28
174 root 1.50 if (!f)
175 root 1.3 {
176 root 1.54 LOG (llevError | logBacktrace, "client::send_face (%d) out of bounds??\n", facenum);
177 root 1.3 return;
178     }
179    
180 root 1.50 // refuse to send non-image faces
181     if (!fx_want [f->type])
182     return;
183 root 1.49
184 root 1.50 if (faces_sent [facenum])
185 root 1.48 return;
186    
187 root 1.50 faces_sent[facenum] = true;
188 root 1.32
189 root 1.38 // if for some reason we let a client without face caching connect,
190     // we better support that decision here and implement it.
191 root 1.33 if (!facecache)
192 root 1.38 return send_image (facenum);
193 root 1.33
194 root 1.39 if (fxix)
195     {
196     fxface.push_back (facenum);
197     return;
198     }
199    
200 root 1.50 const facedata *d = f->data (faceset);
201    
202 root 1.8 packet sl;
203 root 1.3
204 root 1.32 if (force_face0)
205     sl << "face " << uint16 (facenum);
206     else if (image2)
207     sl << "face2 " << uint16 (facenum) << uint8 (0) << uint32 (force_bad_checksum ? gcfclient_checksum (d) : 0);
208     else
209     sl << "face1 " << uint16 (facenum) << uint32 (force_bad_checksum ? gcfclient_checksum (d) : 0);
210    
211     // how lame
212     print_facename (sl, *d);
213     send_packet (sl);
214    
215 root 1.40 if (EMI_smooth)
216 root 1.3 {
217 root 1.40 if (f->smooth)
218     {
219     send_face (f->smooth);
220    
221     packet sl ("smooth");
222 root 1.30
223 root 1.40 sl << uint16 (facenum)
224     << uint16 (f->smooth);
225 root 1.31
226 root 1.40 send_packet (sl);
227     }
228 root 1.32 }
229     }
230    
231 root 1.39 void client::flush_fx ()
232     {
233     while (!fxface.empty ())
234     {
235 root 1.40 packet fx ("fx");
236     packet sx ("sx");
237 root 1.50 int type = 0;
238 root 1.39
239     do
240     {
241     faceidx facenum = fxface.back (); fxface.pop_back ();
242    
243 root 1.50 if (const faceinfo *f = face_info (facenum))
244     {
245     if (f->type != type)
246     {
247     type = f->type;
248    
249     fx << ber32 (0)
250     << uint8 (1) << uint8 (type);
251     }
252    
253     const facedata *d = f->data (faceset);
254 root 1.39
255 root 1.40 fx << ber32 (facenum)
256 root 1.39 << data8 (d->chksum, CHKSUM_SIZE);
257    
258 root 1.40 if (smoothing)
259     {
260     faceinfo *f = face_info (facenum);
261    
262     if (f->smooth)
263     {
264 root 1.50 send_face (f->smooth, -110);
265    
266 root 1.40 sx << ber32 (facenum)
267     << ber32 (f->smooth)
268     << ber32 (f->smoothlevel);
269     }
270     }
271 root 1.39 }
272     }
273 root 1.40 while (!fxface.empty ()
274 root 1.50 && fx.room () > ber32::size + CHKSUM_SIZE + 1 + 3 /* type switch */
275 root 1.40 && sx.room () > ber32::size * 3);
276 root 1.39
277 root 1.40 send_packet (fx);
278     if (sx.length () > 3) send_packet (sx);
279 root 1.39 }
280     }
281    
282 root 1.32 void
283     client::send_image (faceidx facenum)
284     {
285     // never send face 0. ever. it does not exist.
286     if (!facenum)
287     return;
288 root 1.31
289 root 1.32 const facedata *d = face_data (facenum, faceset);
290 root 1.30
291 root 1.43 faces_sent[facenum] = true;
292    
293 root 1.32 if (!d)
294     {
295     LOG (llevError, "client::send_image (%d) out of bounds??\n", facenum);
296     return;
297     }
298 root 1.43
299 root 1.36 if (force_image_newmap)
300     force_newmap = true;
301    
302 root 1.32 packet sl;
303 root 1.30
304 root 1.32 sl << (image2 ? "image2 " : "image ")
305     << uint32 (facenum);
306 root 1.6
307 root 1.32 if (image2)
308     sl << uint8 (0);
309 root 1.6
310 root 1.32 sl << uint32 (d->data.size ())
311     << data (d->data.data (), d->data.size ());
312 root 1.31
313 root 1.32 send_packet (sl);
314 root 1.28 }
315    
316     // send all faces of this object to the client
317     // this uses more bandwidth initially, but makes
318     // animations look much smoother, and every client
319     // is supposed to do client-side caching anyways.
320     void
321     client::send_faces (object *ob)
322     {
323 root 1.50 send_face (ob->face, 10);
324 root 1.28
325     if (ob->animation_id)
326     {
327     animation &anim = animations [ob->animation_id];
328    
329     for (int i = 0; i < anim.num_animations; i++)
330 root 1.50 send_face (anim.faces [i], -10);
331 root 1.28 }
332     }
333    
334     /**
335     * Need to send an animation sequence to the client.
336     * We will send appropriate face commands to the client if we haven't
337     * sent them the face yet (this can become quite costly in terms of
338     * how much we are sending - on the other hand, this should only happen
339     * when the player logs in and picks stuff up.
340     */
341     void
342     client::send_animation (short anim_num)
343     {
344     /* Do some checking on the anim_num we got. Note that the animations
345     * are added in contigous order, so if the number is in the valid
346     * range, it must be a valid animation.
347     */
348 root 1.41 if (anim_num < 0 || anim_num >= animations.size ())
349 root 1.28 {
350     LOG (llevError, "esrv_send_anim (%d) out of bounds??\n", anim_num);
351     return;
352     }
353    
354     packet sl ("anim");
355    
356     sl << uint16 (anim_num)
357     << uint16 (0); /* flags - not used right now */
358    
359     /* Build up the list of faces. Also, send any information (ie, the
360     * the face itself) down to the client.
361     */
362     for (int i = 0; i < animations[anim_num].num_animations; i++)
363     {
364 root 1.50 send_face (animations[anim_num].faces[i], -20);
365 root 1.28 sl << uint16 (animations[anim_num].faces[i]); /* flags - not used right now */
366 elmex 1.1 }
367 root 1.6
368 root 1.28 send_packet (sl);
369    
370     anims_sent[anim_num] = 1;
371 elmex 1.1 }
372    
373     /**
374     * Sends the number of images, checksum of the face file,
375     * and the image_info file information. See the doc/Developers/protocol
376     * if you want further detail.
377     */
378 root 1.3 void
379 root 1.15 send_image_info (client *ns, char *params)
380 elmex 1.1 {
381 root 1.8 packet sl;
382 elmex 1.1
383 root 1.24 //TODO: second parameter is a checksum, but it makes no sense in this current framework
384     sl.printf ("replyinfo image_info\n%d\n%u\n", MAX_FACES, 0);
385 root 1.6
386 root 1.24 sl << "0:base:standard:0:32x32:none:The old 32x32 faceset.\n";
387 elmex 1.1
388 root 1.11 ns->send_packet (sl);
389 elmex 1.1 }
390    
391     /**
392     * Sends requested face information.
393     * \param ns socket to send to
394     * \param params contains first and last index of face
395     *
396     * For each image in [start..stop] sends
397     * - checksum
398     * - name
399     */
400 root 1.3 void
401 root 1.15 send_image_sums (client *ns, char *params)
402 elmex 1.1 {
403 root 1.3 int start, stop;
404 pippijn 1.22 char *cp;
405 root 1.3
406 root 1.8 packet sl;
407 root 1.3
408     start = atoi (params);
409     for (cp = params; *cp != '\0'; cp++)
410     if (*cp == ' ')
411     break;
412    
413     stop = atoi (cp);
414 root 1.24 if (stop < start || *cp == '\0' || (stop - start) > 1000 || stop >= MAX_FACES)
415 root 1.3 {
416 root 1.7 sl.printf ("replyinfo image_sums %d %d", start, stop);
417     ns->send_packet (sl);
418     sl.reset ();
419 root 1.3 return;
420     }
421    
422 root 1.6 sl.printf ("replyinfo image_sums %d %d ", start, stop);
423 root 1.3
424 root 1.24 for (int i = start; i <= stop && i < faces.size (); i++)
425 root 1.53 if (const faceinfo *f = face_info (i))
426     if (ns->fx_want [f->type])
427     {
428     ns->faces_sent[i] = true;
429    
430     const facedata *d = f->data (ns->faceset);
431    
432     if (sl.room () < 2 + 4 + 1 + d->data.size () + 1)
433     break;
434    
435     sl << uint16 (i)
436     << uint32 (0) // checksum
437     << uint8 (ns->faceset);
438 root 1.23
439 root 1.53 print_facename (sl, *d); sl << uint8 (0);
440     }
441 root 1.6
442 root 1.3 /* It would make more sense to catch this pre-emptively in the code above.
443     * however, if this really happens, we probably just want to cut down the
444     * size to less than 1000, since that is what we claim the protocol would
445     * support.
446     */
447 root 1.23 //TODO: taken care of above, should simply abort or make sure the above code is correct
448 root 1.52 if (sl.length () > MAXSOCKBUF)
449 root 1.3 {
450 root 1.9 LOG (llevError, "send_image_send: buffer overrun, %d > %d\n", sl.length (), MAXSOCKBUF);
451 root 1.3 abort ();
452 elmex 1.1 }
453 root 1.6
454 root 1.11 ns->send_packet (sl);
455 elmex 1.1 }
456 root 1.6