ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/client.h
Revision: 1.41
Committed: Fri Mar 16 02:37:54 2007 UTC (17 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.40: +1 -0 lines
Log Message:
- implement yet another bug workaround for gcfclient. its rather sad.

when bg scrubbing, the server sends images in advance, about twice per second.

then receiving a new image, gcfclient destroys the imventory and rebuilds it
(the widgets). this makes using it rather hard, as twice per seconds all widgets
go away and are replaced by new ones, so mouse clicks, if not fast enough, will
be ignored, making the client rather hard to use.

soo.... only to background sending for cfplus, which needs it least.

File Contents

# User Rev Content
1 root 1.1 /*
2 pippijn 1.26 * CrossFire, A Multiplayer game for the X Window System
3     *
4     * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5     * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (C) 1992 Frank Tore Johansen
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * 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     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21     *
22     * The author can be reached via e-mail to crossfire@schmorp.de
23     */
24 root 1.1
25     #ifndef CLIENT_H
26     #define CLIENT_H
27    
28 root 1.4 #include <deque>
29 root 1.7 #include <bitset>
30 root 1.13 #include <tr1/unordered_set>
31 root 1.1
32 root 1.4 // (possibly) max. number of objects "per page" in the ground container
33 root 1.11 #define FLOORBOX_PAGESIZE 50
34 root 1.1
35     struct MapCell
36     {
37     UUID player; // this is, unfortunately, very wasteful of memory space, but pretty bandwidth-efficient
38 root 1.37 int count; /* This is really darkness in the map1 command */
39 root 1.32 faceidx faces[MAP_LAYERS];
40 root 1.36 unsigned char stat_hp; // health of something in this space, or 0
41 root 1.1 unsigned char flags;
42 root 1.37 uint8_t smooth[MAP_LAYERS];
43 root 1.1 };
44    
45 root 1.33 #define MAX_CLIENT_X MAP_CLIENT_X
46     #define MAX_CLIENT_Y MAP_CLIENT_Y
47 root 1.1
48     struct Map
49     {
50     struct MapCell cells[MAX_CLIENT_X][MAX_CLIENT_Y];
51     };
52    
53     /* True max is 16383 given current map compaction method */
54 root 1.33 #define MAXANIMNUM 10000
55 root 1.1
56     struct statsinfo
57     {
58     char *range, *title;
59     };
60    
61     /* This contains basic information on the socket structure. status is its
62     * current state. we set up our on buffers for sending/receiving, so we can
63     * handle some higher level functions. fd is the actual file descriptor we
64     * are using.
65     */
66    
67     /* Only one map mode can actually be used, so lets make it a switch
68     * instead of having a bunch of different fields that needed to
69     * get toggled.
70     */
71     enum MapMode { Map0Cmd = 0, Map1Cmd = 1, Map1aCmd = 2 };
72    
73 root 1.13 /* The following is the setup for a ring buffer for storing output
74 root 1.1 * data that the OS can't handle right away.
75     */
76     struct Buffer
77     {
78     char data[SOCKETBUFSIZE];
79     int start;
80     int len;
81     };
82    
83 root 1.15 // states the socket can be in
84     enum {
85     ST_DEAD, // socket is dead
86     ST_SETUP, // initial handshake / setup / login
87     ST_PLAYING, // logged in an playing
88     ST_CUSTOM, // waiting for custom reply
89    
90     ST_CHANGE_CLASS,
91     ST_GET_PARTY_PASSWORD,
92     };
93    
94 root 1.4 // a handler for a specific type of packet
95     enum {
96 root 1.28 PF_PLAYER = 0x01, // must have valid player / will by synchronised
97     PF_PLAYING = 0x02, // must be in playing state
98     PF_COMMAND0 = 0x04, // command starts at offset 0
99     PF_COMMAND6 = 0x08, // command starts at offset 6
100 root 1.4 };
101    
102     struct packet_type
103     {
104     const char *name;
105     void *cb;
106     int flags;
107     };
108    
109     struct command
110     {
111     tstamp stamp;
112     const packet_type *handler;
113     char *data;
114     int datalen;
115    
116 root 1.6 ~command ()
117 root 1.4 {
118 root 1.8 sfree<char> (data, datalen + 1);
119 root 1.4 }
120     };
121    
122 root 1.13 struct refitem
123     {
124     object_ptr op;
125     };
126    
127 root 1.12 // this represents a container on the client side.
128     // right now, there are only ever two of them:
129     // the inventory and the floor/open container
130     //TODO: unused as of yet
131 root 1.13 struct client_container : vector< refitem, slice_allocator<refitem> >
132 root 1.12 {
133 root 1.13 client *ns;
134 root 1.12 enum { CC_NONE, CC_INVENTORY, CC_MAPSPACE, CC_CONTAINER } type;
135    
136 root 1.13 bool item_changed; // one of the items in here possibly changed
137    
138 root 1.12 // for mapspace and container
139 root 1.13 int x, y;
140 root 1.12 maptile *map;
141    
142     // for container
143     object *env;
144 root 1.13
145     client_container (client *ns)
146     : ns (ns), type (CC_NONE) { }
147    
148     tag_t tag () const;
149    
150     inline iterator merge_item (iterator i, object *op);
151    
152     void clear ();
153     void update ();
154    
155     void set_mapspace (maptile *map, int x, int y);
156     void set_container (object *env);
157 root 1.12 };
158    
159 root 1.1 /* how many times we are allowed to give the wrong password before being kicked. */
160     #define MAX_PASSWORD_FAILURES 5
161    
162 root 1.21 INTERFACE_CLASS (client) // should become player when newsocket is a baseclass of player
163     struct client : zero_initialised, attachable
164 root 1.1 {
165     int ACC (RW, fd);
166 root 1.10 unsigned int inbuf_len; // number of bytes valid in inbuf
167 root 1.20 statsinfo stats;
168 root 1.24 int ACC (RO, active);
169 root 1.12
170 root 1.15 Buffer outputbuffer;
171 root 1.10
172     char *ACC (RW, host); /* Which host it is connected from (ip address) */
173 root 1.15 uint8 ACC (RW, state); /* Input state of the player (name, password, etc */
174 root 1.25
175     sint8 ACC (RW, last_level); /* Last level we sent to client */
176     uint16 ACC (RW, last_flags); /* fire/run on flags for last tick */
177     float ACC (RW, last_weapon_sp); /* if diff than weapon_sp, update client */
178     sint32 ACC (RW, last_weight); /* Last weight as sent to client; -1 means do not send weight */
179     sint32 ACC (RW, last_weight_limit); /* Last weight limit transmitted to client */
180     uint32 ACC (RW, last_path_attuned); /* Last spell attunment sent to client */
181     uint32 ACC (RW, last_path_repelled); /* Last spell repelled sent to client */
182     uint32 ACC (RW, last_path_denied); /* Last spell denied sent to client */
183     living ACC (RO, last_stats); /* Last stats as sent to client */
184     float ACC (RW, last_speed); /* Last speed as sent to client */
185     sint16 ACC (RW, last_resist[NROFATTACKS]);/* last resist values sent to client */
186     sint64 ACC (RW, last_skill_exp[NUM_SKILLS]);/* shadow register. if != exp. obj update client */
187 root 1.10
188 root 1.20 bool ACC (RW, afk); /* player is afk */
189 root 1.10 bool ACC (RW, facecache); /* If true, client is caching images */
190     bool ACC (RW, sent_scroll);
191     bool ACC (RW, sound); /* does the client want sound */
192     bool ACC (RW, newmapcmd); /* Send newmap command when entering new map SMACFIGGEN */
193 root 1.40 bool ACC (RW, plugincmd); // extend the protocol through a plug-in */
194     bool ACC (RW, mapinfocmd); // return map info and send map change info
195     bool ACC (RW, extcmd); // call into extensions/plugins
196     bool ACC (RW, extmap); // extend map comamnd with extra data
197     bool ACC (RW, buggy_mapscroll); // client crashes on large mapscrolls
198     bool ACC (RW, force_face0); // client workaround for buggy checksum calculation in gcfclient
199     bool ACC (RW, force_bad_checksum); // client workaround for buggy checksum calculation in gcfclient
200     bool ACC (RW, force_image_newmap); // client workaround for client not redrawing map on image upload
201 root 1.41 bool ACC (RW, enable_bg_scrub); // client workaround, gcfclient becomes unusable if you send it images
202 root 1.10 bool ACC (RW, darkness); /* True if client wants darkness information */
203     bool ACC (RW, image2); /* Client wants image2/face2 commands */
204     bool ACC (RW, update_look); /* If true, we need to send the look window */
205     bool ACC (RW, has_readable_type); /* If true client accept additional text information */
206     /* used to arrange text in books, scrolls, or scripted dialogs */
207     bool ACC (RW, monitor_spells); /* Client wishes to be informed when their spell list changes */
208     bool ACC (RW, ext_mapinfos); /* If true client accepts additional info on maps */
209     /* Below are flags for extedend infos to pass to client
210     * with S->C mapextended command */
211     bool ACC (RW, EMI_smooth); /* Send smooth in extendmapinfos */
212 root 1.1
213 root 1.40 bool ACC (RW, force_newmap); // force a newmap before next map update
214 root 1.1 uint32 ACC (RW, supported_readables); /* each bit is a readable supported by client */
215     uint32 ACC (RW, cs_version), ACC (RW, sc_version); /* versions of the client */
216     enum MapMode mapmode; /* Type of map commands the client wants. */
217     uint16 ACC (RW, look_position); /* start of drawing of look window */
218     uint8 ACC (RW, mapx), ACC (RW, mapy); /* How large a map the client wants */
219     uint8 ACC (RW, itemcmd); /* What version of the 'item' protocol command to use */
220    
221     maptile *ACC (RW, current_map); // CF+ last/current player map
222 root 1.29 region *ACC (RW, current_region); // CF+ last/current player region
223 root 1.1 int ACC (RW, current_x), ACC (RW, current_y); // CF+ last/current map position
224 root 1.10 char ACC (RW, version)[64]; // CF+ client name/version
225 root 1.32 uint8 ACC (RW, faceset); // CF+ selected faceset
226 root 1.1
227 root 1.18 player_ptr ACC (RO, pl);
228 root 1.1
229 root 1.38 int ACC (RW, rtt), ACC (RW, rttvar); /* round-trip time and -variance, if known */
230    
231     int ACC (RW, max_rate); // max. # of bytes to send per tick
232 root 1.39 faceidx ACC (RW, scrub_idx); // which face to send next
233     int ACC (RW, bg_scrub); // how many ticks till the next background face send
234 root 1.38 std::vector<faceidx> askface; // which faces have been requested by the client
235 root 1.1
236 root 1.21 void do_destroy ();
237     void gather_callbacks (AV *&callbacks, event_type event) const;
238 root 1.4
239 pippijn 1.30 iow socket_ev; void socket_cb (iow &w, int got);
240 root 1.4 iw cmd_ev; void cmd_cb (iw &w);
241 pippijn 1.30 client_container cc_inv, cc_other;
242 root 1.1
243 root 1.4 std::deque< command, slice_allocator<command> > cmd_queue;
244    
245 root 1.14 // large structures at the end please
246     struct Map lastmap;
247     std::bitset<MAXANIMNUM> anims_sent;
248 root 1.36 std::bitset<MAX_FACES> faces_sent;
249    
250 root 1.14 // if we get an incomplete packet, this is used to hold the data.
251     // we add 2 byte for the header, one for the trailing 0 byte
252     uint8 inbuf[MAXSOCKBUF + 2 + 1];
253    
254 root 1.4 bool may_execute (const packet_type *pkt) const;
255     void execute (const packet_type *pkt, char *data, int datalen);
256    
257     void queue_command (packet_type *handler, char *data, int datalen);
258 root 1.22 MTH bool handle_command ();
259 root 1.14 // resets movement state
260 root 1.22 MTH void reset_state ();
261 root 1.25 // resets variable data used to send stat diffs
262     MTH void reset_stats ();
263 root 1.1
264 root 1.22 MTH bool handle_packet ();
265 root 1.4 int next_packet (); // returns length of packet or 0
266 root 1.1 void skip_packet (int len); // we have processed the packet, skip it
267    
268 root 1.22 MTH void flush ();
269     MTH void write_outputbuffer ();
270 root 1.38 MTH int outputbuffer_len () const { return outputbuffer.len; }
271 root 1.1 void send (void *buf_, int len);
272    
273     void send_packet (const char *buf);
274     void send_packet (const char *buf, int len);
275 root 1.4 void send_packet_printf (const char *format, ...);
276 root 1.1 void send_packet (packet &sl);
277 root 1.7
278 root 1.35 void send_drawinfo (const char *msg, int flags = NDI_BLACK);
279 root 1.38 MTH void send_face (faceidx facenum);
280     MTH void send_image (faceidx facenum);
281 root 1.35 MTH void send_faces (object *ob);
282     MTH void send_animation (short anim_num);
283    
284 root 1.10 // called when something under the player changes
285 root 1.22 MTH void floorbox_update () { update_look = 1; }
286 root 1.10 // called when the player has been moved
287 root 1.22 MTH void floorbox_reset () { look_position = 0; floorbox_update (); }
288    
289 root 1.39 MTH void tick (); // called every server tick to do housekeeping etc.
290    
291 root 1.22 MTH static client *create (int fd, const char *peername);
292 root 1.10
293 root 1.22 protected:
294     client (int fd, const char *from_ip);
295     ~client ();
296 root 1.1 };
297    
298     #define CLIENT_SUPPORT_READABLES(__sockPtr,__type)\
299     ( ((__type)>0) &&\
300     ((__sockPtr)->has_readable_type) && \
301     ((__sockPtr)->supported_readables & (1<<(__type))) )
302    
303     /* Constants in the form EMI_ is for extended map infos.
304     * Even if the client select the additionnal infos it wants
305     * on the map, there may exist cases where this whole info
306     * is not given in one buch but in separate bunches. This
307     * is done performance reasons (imagine some info related to
308     * a visible object and another info related to a 4 square
309     * width and height area). At the begin of an extended info packet
310     * is a bit field. A bit is activated for each extended info
311     * present in the data
312     */
313    
314     /* Meanings:
315     * EMI_NOREDRAW Take extended infos into account but don't redraw,
316     * some additionnal datas will follow in a new packet
317     * EMI_SMOOTH Datas about smoothing
318     */
319     #define EMI_NOREDRAW 0x01
320     #define EMI_SMOOTH 0x02
321    
322     /* this last one says the bitfield continue un next byte
323     * There may be several on contiguous bytes. So there is 7
324     * actual bits used per byte, and the number of bytes
325     * is not fixed in protocol
326     */
327     #define EMI_HASMOREBITS 0x80
328    
329     #define FACE_TYPES 1
330     #define PNG_FACE_INDEX 0
331    
332     #define VERSION_CS 1023 /* version >= 1023 understand setup cmd */
333 root 1.31 #define VERSION_SC 1026
334     //#define VERSION_SC 1027 // requestinfo image_info and image_sums, makes extending faces on the fly impossible
335 root 1.1 #define VERSION_INFO "Crossfire+ Server"
336    
337 root 1.24 typedef object_vector<client, &client::active> sockvec;
338 root 1.1
339     extern sockvec clients;
340 root 1.24
341     #define for_all_clients(var) \
342     for (int _i = 0; _i < clients.size (); ++_i) \
343     declvar (client *, var, clients [_i])
344    
345 root 1.1 #endif
346