ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/client.h
Revision: 1.37
Committed: Wed Mar 14 04:12:28 2007 UTC (17 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.36: +2 -2 lines
Log Message:
- rewrote more face handling code
- automatically send smooth faces, as the client will need them anyways
  and it makes little sense to wait for the client to axk for it. of course,
  gcfclient suffers from weird ordering problems again.
- UP_OBJ_FACE was often abused in situations where other things changed,
  updated lots of spaces, probably more to be done.
- update_smooth became so small that inlining it actually clarified
  the code. similar for update_space, which is not inlined for other reasons.
- faces were not initialised properly
- add versioncheck for face data
- rewrite invisibility handling a bit: god finger etc. now makes you blink,
  blinking routine has changed to be less annoying and more useful while
  still indicating invisibleness.

File Contents

# Content
1 /*
2 * 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
25 #ifndef CLIENT_H
26 #define CLIENT_H
27
28 #include <deque>
29 #include <bitset>
30 #include <tr1/unordered_set>
31
32 // (possibly) max. number of objects "per page" in the ground container
33 #define FLOORBOX_PAGESIZE 50
34
35 struct MapCell
36 {
37 UUID player; // this is, unfortunately, very wasteful of memory space, but pretty bandwidth-efficient
38 int count; /* This is really darkness in the map1 command */
39 faceidx faces[MAP_LAYERS];
40 unsigned char stat_hp; // health of something in this space, or 0
41 unsigned char flags;
42 uint8_t smooth[MAP_LAYERS];
43 };
44
45 #define MAX_CLIENT_X MAP_CLIENT_X
46 #define MAX_CLIENT_Y MAP_CLIENT_Y
47
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 #define MAXANIMNUM 10000
55
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 /* The following is the setup for a ring buffer for storing output
74 * 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 // 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 // a handler for a specific type of packet
95 enum {
96 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 };
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 ~command ()
117 {
118 sfree<char> (data, datalen + 1);
119 }
120 };
121
122 struct refitem
123 {
124 object_ptr op;
125 };
126
127 // 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 struct client_container : vector< refitem, slice_allocator<refitem> >
132 {
133 client *ns;
134 enum { CC_NONE, CC_INVENTORY, CC_MAPSPACE, CC_CONTAINER } type;
135
136 bool item_changed; // one of the items in here possibly changed
137
138 // for mapspace and container
139 int x, y;
140 maptile *map;
141
142 // for container
143 object *env;
144
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 };
158
159 /* how many times we are allowed to give the wrong password before being kicked. */
160 #define MAX_PASSWORD_FAILURES 5
161
162 INTERFACE_CLASS (client) // should become player when newsocket is a baseclass of player
163 struct client : zero_initialised, attachable
164 {
165 int ACC (RW, fd);
166 unsigned int inbuf_len; // number of bytes valid in inbuf
167 statsinfo stats;
168 int ACC (RO, active);
169
170 Buffer outputbuffer;
171
172 char *ACC (RW, host); /* Which host it is connected from (ip address) */
173 uint8 ACC (RW, state); /* Input state of the player (name, password, etc */
174
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
188 bool ACC (RW, afk); /* player is afk */
189 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 bool ACC (RW, plugincmd); /* CF+ extend the protocol through a plug-in */
194 bool ACC (RW, mapinfocmd); /* CF+ return map info and send map change info */
195 bool ACC (RW, extcmd); /* CF+ call into extensions/plugins */
196 bool ACC (RW, extmap); /* CF+ extend map comamnd with extra data */
197 bool ACC (RW, buggy_mapscroll); /* CF+ client crashes on large mapscrolls */
198 bool ACC (RW, force_face0); /* CF+ client workaround for buggy checksum calculation in gcfclient */
199 bool ACC (RW, force_bad_checksum); /* CF+ client workaround for buggy checksum calculation in gcfclient */
200 bool ACC (RW, darkness); /* True if client wants darkness information */
201 bool ACC (RW, image2); /* Client wants image2/face2 commands */
202 bool ACC (RW, update_look); /* If true, we need to send the look window */
203 bool ACC (RW, has_readable_type); /* If true client accept additional text information */
204 /* used to arrange text in books, scrolls, or scripted dialogs */
205 bool ACC (RW, monitor_spells); /* Client wishes to be informed when their spell list changes */
206 bool ACC (RW, ext_mapinfos); /* If true client accepts additional info on maps */
207 /* Below are flags for extedend infos to pass to client
208 * with S->C mapextended command */
209 bool ACC (RW, EMI_smooth); /* Send smooth in extendmapinfos */
210
211 uint32 ACC (RW, supported_readables); /* each bit is a readable supported by client */
212 uint32 ACC (RW, cs_version), ACC (RW, sc_version); /* versions of the client */
213 enum MapMode mapmode; /* Type of map commands the client wants. */
214 uint16 ACC (RW, look_position); /* start of drawing of look window */
215 uint8 ACC (RW, mapx), ACC (RW, mapy); /* How large a map the client wants */
216 uint8 ACC (RW, itemcmd); /* What version of the 'item' protocol command to use */
217
218 maptile *ACC (RW, current_map); // CF+ last/current player map
219 region *ACC (RW, current_region); // CF+ last/current player region
220 int ACC (RW, current_x), ACC (RW, current_y); // CF+ last/current map position
221 char ACC (RW, version)[64]; // CF+ client name/version
222 uint8 ACC (RW, faceset); // CF+ selected faceset
223
224 player_ptr ACC (RO, pl);
225
226 int ACC (RW, rtt), ACC (RW, rttvar); /* round-trip time and -variance, if known */
227
228 void do_destroy ();
229 void gather_callbacks (AV *&callbacks, event_type event) const;
230
231 iow socket_ev; void socket_cb (iow &w, int got);
232 iw cmd_ev; void cmd_cb (iw &w);
233 client_container cc_inv, cc_other;
234
235 std::deque< command, slice_allocator<command> > cmd_queue;
236
237 // large structures at the end please
238 struct Map lastmap;
239 std::bitset<MAXANIMNUM> anims_sent;
240 std::bitset<MAX_FACES> faces_sent;
241
242 // if we get an incomplete packet, this is used to hold the data.
243 // we add 2 byte for the header, one for the trailing 0 byte
244 uint8 inbuf[MAXSOCKBUF + 2 + 1];
245
246 bool may_execute (const packet_type *pkt) const;
247 void execute (const packet_type *pkt, char *data, int datalen);
248
249 void queue_command (packet_type *handler, char *data, int datalen);
250 MTH bool handle_command ();
251 // resets movement state
252 MTH void reset_state ();
253 // resets variable data used to send stat diffs
254 MTH void reset_stats ();
255
256 MTH bool handle_packet ();
257 int next_packet (); // returns length of packet or 0
258 void skip_packet (int len); // we have processed the packet, skip it
259
260 MTH void flush ();
261 MTH void write_outputbuffer ();
262 void send (void *buf_, int len);
263
264 void send_packet (const char *buf);
265 void send_packet (const char *buf, int len);
266 void send_packet_printf (const char *format, ...);
267 void send_packet (packet &sl);
268
269 void send_drawinfo (const char *msg, int flags = NDI_BLACK);
270 MTH void send_face (faceidx facenum, bool nocache = false);
271 MTH void send_faces (object *ob);
272 MTH void send_animation (short anim_num);
273
274 // called when something under the player changes
275 MTH void floorbox_update () { update_look = 1; }
276 // called when the player has been moved
277 MTH void floorbox_reset () { look_position = 0; floorbox_update (); }
278
279 MTH static client *create (int fd, const char *peername);
280
281 protected:
282 client (int fd, const char *from_ip);
283 ~client ();
284 };
285
286 #define CLIENT_SUPPORT_READABLES(__sockPtr,__type)\
287 ( ((__type)>0) &&\
288 ((__sockPtr)->has_readable_type) && \
289 ((__sockPtr)->supported_readables & (1<<(__type))) )
290
291 /* Constants in the form EMI_ is for extended map infos.
292 * Even if the client select the additionnal infos it wants
293 * on the map, there may exist cases where this whole info
294 * is not given in one buch but in separate bunches. This
295 * is done performance reasons (imagine some info related to
296 * a visible object and another info related to a 4 square
297 * width and height area). At the begin of an extended info packet
298 * is a bit field. A bit is activated for each extended info
299 * present in the data
300 */
301
302 /* Meanings:
303 * EMI_NOREDRAW Take extended infos into account but don't redraw,
304 * some additionnal datas will follow in a new packet
305 * EMI_SMOOTH Datas about smoothing
306 */
307 #define EMI_NOREDRAW 0x01
308 #define EMI_SMOOTH 0x02
309
310 /* this last one says the bitfield continue un next byte
311 * There may be several on contiguous bytes. So there is 7
312 * actual bits used per byte, and the number of bytes
313 * is not fixed in protocol
314 */
315 #define EMI_HASMOREBITS 0x80
316
317 #define FACE_TYPES 1
318 #define PNG_FACE_INDEX 0
319
320 #define VERSION_CS 1023 /* version >= 1023 understand setup cmd */
321 #define VERSION_SC 1026
322 //#define VERSION_SC 1027 // requestinfo image_info and image_sums, makes extending faces on the fly impossible
323 #define VERSION_INFO "Crossfire+ Server"
324
325 typedef object_vector<client, &client::active> sockvec;
326
327 extern sockvec clients;
328
329 #define for_all_clients(var) \
330 for (int _i = 0; _i < clients.size (); ++_i) \
331 declvar (client *, var, clients [_i])
332
333 #endif
334