1 /* $Id$ */
2 /* The server side of the network stuff */
3 
4 /* The following is a direct excerpt from the netserver.c
5  * in the XPilot distribution.  Much of it is incorrect
6  * in MAngband's case, but most of it is still correct.
7  */
8 
9 
10 
11 /*
12  * This is the server side of the network connnection stuff.
13  *
14  * We try very hard to not let the game be disturbed by
15  * players logging in.  Therefore a new connection
16  * passes through several states before it is actively
17  * playing.
18  * First we make a new connection structure available
19  * with a new socket to listen on.  This socket port
20  * number is told to the client via the pack mechanism.
21  * In this state the client has to send a packet to this
22  * newly created socket with its name and playing parameters.
23  * If this succeeds the connection advances to its second state.
24  * In this second state the essential server configuration
25  * like the map and so on is transmitted to the client.
26  * If the client has acknowledged all this data then it
27  * advances to the third state, which is the
28  * ready-but-not-playing-yet state.  In this state the client
29  * has some time to do its final initializations, like mapping
30  * its user interface windows and so on.
31  * When the client is ready to accept frame updates and process
32  * keyboard events then it sends the start-play packet.
33  * This play packet advances the connection state into the
34  * actively-playing state.  A player structure is allocated and
35  * initialized and the other human players are told about this new player.
36  * The newly started client is told about the already playing players and
37  * play has begun.
38  * Apart from these four states there are also two intermediate states.
39  * These intermediate states are entered when the previous state
40  * has filled the reliable data buffer and the client has not
41  * acknowledged all the data yet that is in this reliable data buffer.
42  * They are so called output drain states.  Not doing anything else
43  * then waiting until the buffer is empty.
44  * The difference between these two intermediate states is tricky.
45  * The second intermediate state is entered after the
46  * ready-but-not-playing-yet state and before the actively-playing state.
47  * The difference being that in this second intermediate state the client
48  * is already considered an active player by the rest of the server
49  * but should not get frame updates yet until it has acknowledged its last
50  * reliable data.
51  *
52  * Communication between the server and the clients is only done
53  * using UDP datagrams.  The first client/serverized version of XPilot
54  * was using TCP only, but this was too unplayable across the Internet,
55  * because TCP is a data stream always sending the next byte.
56  * If a packet gets lost then the server has to wait for a
57  * timeout before a retransmission can occur.  This is too slow
58  * for a real-time program like this game, which is more interested
59  * in recent events than in sequenced/reliable events.
60  * Therefore UDP is now used which gives more network control to the
61  * program.
62  * Because some data is considered crucial, like the names of
63  * new players and so on, there also had to be a mechanism which
64  * enabled reliable data transmission.  Here this is done by creating
65  * a data stream which is piggybacked on top of the unreliable data
66  * packets.  The client acknowledges this reliable data by sending
67  * its byte position in the reliable data stream.  So if the client gets
68  * a new reliable data packet and it has not had this data before and
69  * there is also no data packet missing inbetween, then it advances
70  * its byte position and acknowledges this new position to the server.
71  * Otherwise it discards the packet and sends its old byte position
72  * to the server meaning that it detected a packet loss.
73  * The server maintains an acknowledgement timeout timer for each
74  * connection so that it can retransmit a reliable data packet
75  * if the acknowledgement timer expires.
76  */
77 
78 
79 
80 #define SERVER
81 
82 #include "angband.h"
83 #include "netserver.h"
84 
85 #include <sys/types.h>
86 #include <sys/stat.h>
87 #ifndef WINDOWS
88 #include <sys/wait.h>
89 #include <netinet/in.h>
90 #include <sys/socket.h>
91 #include <netdb.h>
92 #endif
93 #include <errno.h>
94 
95 
96 /* hack to prevent the floor tile bug on windows xp and windows 2003 machines */
97 //#define FLOORTILEBUG_WORKAROUND
98 
99 /* Message to send to client when kicking him out due to starvation while being idle */
100 //#define STARVING_AUTOKICK_MSG "starving auto-kick"
101 #define STARVING_AUTOKICK_MSG format("You were STARVING and idle for %ds, so the game kicked you to prevent death!", STARVE_KICK_TIMER)
102 
103 /* Sanity check of client input */
104 #define bad_dir(d)	((d)<0 || (d)>9)	/* used for non-targetting actions that require a direction */
105 //#define bad_dir1(d)	((d)<0 || (d)>9+1)	/* used for most targetting actions */
bad_dir1(int Ind,char * dir)106 static bool bad_dir1(int Ind, char *dir) {
107 	/* paranoia? */
108 	if (Ind == -1) return TRUE;
109 
110 	if (*dir < 0 || *dir > 11) return TRUE;
111 	if (*dir == 11) {
112 		if (target_okay(Ind)) *dir = 5;
113 	}
114 	else if (*dir == 10) {
115 		if (!target_okay(Ind)) return TRUE;
116 		*dir = 5;
117 	}
118 	return FALSE;
119 }
120 #define bad_dir2(d)	((d)<128 || (d)>137)	/* dir + 128; used for manual target positioning */
121 //#define bad_dir3(d)	((d)<-1 || (d)>9+1)	/* used for MKEY_SCHOOL activations */
bad_dir3(int Ind,char * dir)122 static bool bad_dir3(int Ind, char *dir) {
123 	/* paranoia? */
124 	if (Ind == -1) return TRUE;
125 
126 	if (*dir < -1 || *dir > 11) return TRUE;
127 	if (*dir == 11) {
128 		if (target_okay(Ind)) *dir = 5;
129 	}
130 	else if (*dir == 10) {
131 		if (!target_okay(Ind)) return TRUE;
132 		*dir = 5;
133 	}
134 	return FALSE;
135 }
136 
137 
138 
139 #if 0
140 static bool validstrings(char *nick, char *real, char *host);
141 #else
142 static bool validstring(char *nick);
143 #endif
144 void validatestring(char *string);
145 
146 connection_t	**Conn = NULL;
147 static int	max_connections = 0;
148 static setup_t	Setup;
149 static int	(*playing_receive[256])(int ind),
150 		(*login_receive[256])(int ind),
151 		(*drain_receive[256])(int ind);
152 int		login_in_progress;
153 static int	num_logins, num_logouts;
154 static long	Id;
155 int		NumPlayers, NumNonAdminPlayers;
156 
157 
158 pid_t		metapid = 0;
159 int		MetaSocket = -1;
160 
161 #ifdef NEW_SERVER_CONSOLE
162 int		ConsoleSocket = -1;
163 #endif
164 #ifdef SERVER_GWPORT
165 int		SGWSocket = -1;
166 #endif
167 #ifdef TOMENET_WORLDS
168 int		WorldSocket = -1;
169 #endif
170 
171 
showtime(void)172 char *showtime(void)
173 {
174 	time_t		now;
175 	struct tm	*tmp;
176 	static char	month_names[13][4] = {
177 				"Jan", "Feb", "Mar", "Apr", "May", "Jun",
178 				"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
179 				"Bug"
180 			};
181 	static char	buf[80];
182 	/* adding weekdays, basically just for p_printf() - C. Blue */
183 	static char	day_names[7][4] = {
184 				"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
185 			};
186 	time(&now);
187 	tmp = localtime(&now);
188 	sprintf(buf, "%02d %s (%s) %02d:%02d:%02d",
189 		tmp->tm_mday, month_names[tmp->tm_mon], day_names[tmp->tm_wday],
190 		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
191 	return buf;
192 }
193 
194 /* added for the BBS - C. Blue */
showdate(void)195 char *showdate(void)
196 {
197 	time_t		now;
198 	struct tm	*tmp;
199 	static char	buf[80];
200 	time(&now);
201 	tmp = localtime(&now);
202 	sprintf(buf, "%02d-%02d", tmp->tm_mon + 1, tmp->tm_mday);
203 	return buf;
204 }
205 
206 /* added for changing seasons via lua cron_24h() - C. Blue */
get_date(int * weekday,int * day,int * month,int * year)207 void get_date(int *weekday, int *day, int *month, int *year) {
208         time_t		now;
209         struct tm	*tmp;
210         time(&now);
211         tmp = localtime(&now);
212         *weekday = tmp->tm_wday;
213         *day = tmp->tm_mday;
214         *month = tmp->tm_mon + 1;
215 	*year = tmp->tm_year + 1900;
216 }
217 
add_banlist(char * account,char * ip_addy,char * hostname,int time,char * reason)218 void add_banlist(char *account, char *ip_addy, char *hostname, int time, char *reason) {
219 	struct combo_ban *ptr;
220 
221 	if (!time) return;
222 	if (!account && !ip_addy) return;
223 
224 	ptr = NEW(struct combo_ban);
225 	ptr->next = banlist;
226 
227 	ptr->time = time;
228 	if (reason) strcpy(ptr->reason, reason);
229 	else ptr->reason[0] = 0;
230 	if (hostname) {
231 		strncpy(ptr->hostname, hostname, MAX_CHARS);
232 		ptr->hostname[MAX_CHARS - 1] = 0;
233 	} else ptr->hostname[0] = 0;
234 
235 	if (reason) s_printf("Banned for %d minutes ('%s'):\n", time, reason);
236 	else s_printf("Banned for %d minutes:\n", time);
237 	if (account) {
238 		strcpy(ptr->acc, account);
239 		s_printf(" Connections for %s.\n", ptr->acc, time);
240 	} else ptr->acc[0] = 0;
241 	if (ip_addy) {
242 		strcpy(ptr->ip, ip_addy);
243 		s_printf(" Connections from %s.\n", ptr->ip, time);
244 	} else ptr->ip[0] = 0;
245 
246 	banlist = ptr;
247 }
248 
249 /*
250  * Initialize the function dispatch tables for the various client
251  * connection states.  Some states use the same table.
252  */
Init_receive(void)253 static void Init_receive(void)
254 {
255 	int i;
256 
257 	for (i = 0; i < 256; i++)
258 	{
259 		login_receive[i] = Receive_undefined;
260 		playing_receive[i] = Receive_undefined;
261 		drain_receive[i] = Receive_undefined;
262 	}
263 
264 	drain_receive[PKT_QUIT]			= Receive_quit;
265 //	drain_receive[PKT_ACK]			= Receive_ack;
266 	drain_receive[PKT_VERIFY]		= Receive_discard;
267 	drain_receive[PKT_PLAY]			= Receive_discard;
268 
269 	login_receive[PKT_PLAY]			= Receive_play;
270 	login_receive[PKT_QUIT]			= Receive_quit;
271 //	login_receive[PKT_ACK]			= Receive_ack;
272 	login_receive[PKT_VERIFY]		= Receive_discard;
273 	login_receive[PKT_LOGIN]		= Receive_login;
274 
275 //	playing_receive[PKT_ACK]		= Receive_ack;
276 	playing_receive[PKT_VERIFY]		= Receive_discard;
277 	playing_receive[PKT_QUIT]		= Receive_quit;
278 	playing_receive[PKT_PLAY]		= Receive_play;
279 	playing_receive[PKT_FILE]		= Receive_file;
280 
281 	playing_receive[PKT_KEEPALIVE]		= Receive_keepalive;
282 	playing_receive[PKT_WALK]		= Receive_walk;
283 	playing_receive[PKT_RUN]		= Receive_run;
284 	playing_receive[PKT_TUNNEL]		= Receive_tunnel;
285 	playing_receive[PKT_AIM_WAND]		= Receive_aim_wand;
286 	playing_receive[PKT_DROP]		= Receive_drop;
287 	playing_receive[PKT_FIRE]		= Receive_fire;
288 	playing_receive[PKT_STAND]		= Receive_stand;
289 	playing_receive[PKT_DESTROY]		= Receive_destroy;
290 	playing_receive[PKT_LOOK]		= Receive_look;
291 
292 	playing_receive[PKT_OPEN]		= Receive_open;
293 	playing_receive[PKT_QUAFF]		= Receive_quaff;
294 	playing_receive[PKT_READ]		= Receive_read;
295 	playing_receive[PKT_SEARCH]		= Receive_search;
296 	playing_receive[PKT_TAKE_OFF]		= Receive_take_off;
297 	playing_receive[PKT_TAKE_OFF_AMT]	= Receive_take_off_amt;
298 	playing_receive[PKT_USE]		= Receive_use;
299 	playing_receive[PKT_THROW]		= Receive_throw;
300 	playing_receive[PKT_WIELD]		= Receive_wield;
301 	playing_receive[PKT_OBSERVE]		= Receive_observe;
302 	playing_receive[PKT_ZAP]		= Receive_zap;
303 	playing_receive[PKT_ZAP_DIR]		= Receive_zap_dir;
304 	playing_receive[PKT_MIND]		= Receive_mind;
305 
306 	playing_receive[PKT_TARGET]		= Receive_target;
307 	playing_receive[PKT_TARGET_FRIENDLY]	= Receive_target_friendly;
308 	playing_receive[PKT_INSCRIBE]		= Receive_inscribe;
309 	playing_receive[PKT_UNINSCRIBE]		= Receive_uninscribe;
310 	playing_receive[PKT_AUTOINSCRIBE]	= Receive_autoinscribe;
311 	playing_receive[PKT_ACTIVATE]		= Receive_activate;
312 	playing_receive[PKT_ACTIVATE_DIR]	= Receive_activate_dir;
313 	playing_receive[PKT_BASH]		= Receive_bash;
314 	playing_receive[PKT_DISARM]		= Receive_disarm;
315 	playing_receive[PKT_EAT]		= Receive_eat;
316 	playing_receive[PKT_FILL]		= Receive_fill;
317 	playing_receive[PKT_LOCATE]		= Receive_locate;
318 	playing_receive[PKT_MAP]		= Receive_map;
319 	playing_receive[PKT_SEARCH_MODE]	= Receive_search_mode;
320 
321 	playing_receive[PKT_CLOSE]		= Receive_close;
322 //	playing_receive[PKT_GAIN]		= Receive_gain;
323 	playing_receive[PKT_DIRECTION]		= Receive_direction;
324 	playing_receive[PKT_GO_UP]		= Receive_go_up;
325 	playing_receive[PKT_GO_DOWN]		= Receive_go_down;
326 	playing_receive[PKT_MESSAGE]		= Receive_message;
327 	playing_receive[PKT_ITEM]		= Receive_item;
328 	playing_receive[PKT_SPELL]		= Receive_spell;
329 	playing_receive[PKT_PURCHASE]		= Receive_purchase;
330 	playing_receive[PKT_KING]		= Receive_King;
331 
332 	playing_receive[PKT_SELL]		= Receive_sell;
333 	playing_receive[PKT_STORE_LEAVE]	= Receive_store_leave;
334 	playing_receive[PKT_STORE_CONFIRM]	= Receive_store_confirm;
335 	playing_receive[PKT_DROP_GOLD]		= Receive_drop_gold;
336 	playing_receive[PKT_REDRAW]		= Receive_redraw;
337 	playing_receive[PKT_REST]		= Receive_rest;
338 	playing_receive[PKT_SPECIAL_LINE]	= Receive_special_line;
339 	playing_receive[PKT_PARTY]		= Receive_party;
340 	playing_receive[PKT_GHOST]		= Receive_ghost;
341 
342 	playing_receive[PKT_STEAL]		= Receive_steal;
343 	playing_receive[PKT_OPTIONS]		= Receive_options;
344 	playing_receive[PKT_SUICIDE]		= Receive_suicide;
345 	playing_receive[PKT_MASTER]		= Receive_master;
346 	playing_receive[PKT_HOUSE]		= Receive_admin_house;
347 
348 	playing_receive[PKT_AUTOPHASE]		= Receive_autophase;
349 	playing_receive[PKT_SCREEN_DIM]		= Receive_screen_dimensions;
350 
351 	playing_receive[PKT_CLEAR_BUFFER]	= Receive_clear_buffer;
352 	playing_receive[PKT_CLEAR_ACTIONS]	= Receive_clear_actions;
353 
354 	playing_receive[PKT_SPIKE]		= Receive_spike;
355 	playing_receive[PKT_GUILD]		= Receive_guild;
356 	playing_receive[PKT_GUILD_CFG]		= Receive_guild_config;
357 
358         playing_receive[PKT_SKILL_MOD]		= Receive_skill_mod;
359 	playing_receive[PKT_SKILL_DEV]		= Receive_skill_dev;
360         playing_receive[PKT_ACTIVATE_SKILL]	= Receive_activate_skill;
361 	playing_receive[PKT_RAW_KEY]		= Receive_raw_key;
362 	playing_receive[PKT_STORE_EXAMINE]	= Receive_store_examine;
363 	playing_receive[PKT_STORE_CMD]		= Receive_store_command;
364 	playing_receive[PKT_PING]		= Receive_ping;
365 
366 	/* New stuff for v4.4.1 or 4.4.0d (dual-wield & co) - C. Blue */
367 	playing_receive[PKT_SIP]		= Receive_sip;
368 	playing_receive[PKT_TELEKINESIS]	= Receive_telekinesis;
369 	playing_receive[PKT_BBS]		= Receive_BBS;
370 	playing_receive[PKT_WIELD2]		= Receive_wield2;
371 	playing_receive[PKT_CLOAK]		= Receive_cloak;
372 	playing_receive[PKT_INVENTORY_REV]	= Receive_inventory_revision;
373 	playing_receive[PKT_ACCOUNT_INFO]	= Receive_account_info;
374 	playing_receive[PKT_CHANGE_PASSWORD]	= Receive_change_password;
375 
376 	playing_receive[PKT_FORCE_STACK]	= Receive_force_stack;
377 
378 	playing_receive[PKT_REQUEST_KEY]	= Receive_request_key;
379 	playing_receive[PKT_REQUEST_NUM]	= Receive_request_num;
380 	playing_receive[PKT_REQUEST_STR]	= Receive_request_str;
381 	playing_receive[PKT_REQUEST_CFR]	= Receive_request_cfr;
382 }
383 
Init_setup(void)384 static int Init_setup(void) {
385 	int n = 0, i;
386 	char buf[1024];
387 	FILE *fp;
388 
389 	Setup.frames_per_second = cfg.fps;
390 	Setup.max_race = MAX_RACE;
391 #if 1
392   #ifdef ENABLE_MCRAFT
393 	Setup.max_class = MAX_CLASS;
394   #else
395 	Setup.max_class = MAX_CLASS - 1;
396   #endif
397 #else
398 	Setup.max_class = MAX_CLASS;
399 #endif
400 	Setup.max_trait = MAX_TRAIT;
401 
402 
403 	Setup.motd_len = 23 * 120; /*80;*/	/* colour codes extra */
404 	Setup.setup_size = sizeof(setup_t);
405 
406 	path_build(buf, 1024, ANGBAND_DIR_TEXT, "news.txt");
407 
408 	/* Open the news file */
409 	fp = my_fopen(buf, "r");
410 
411 	if (fp) {
412 		/* Dump the file into the buffer */
413 		while (0 == my_fgets(fp, buf, 1024, TRUE) && n < 23) {
414 			/* strncpy(&Setup.motd[n * 80], buf, 80); */
415 			strncpy(&Setup.motd[n * 120], buf, 120);
416 			n++;
417 		}
418 
419 		my_fclose(fp);
420 	}
421 
422 	/* MEGAHACK -- copy race/class names */
423 	/* XXX I know this ruins the meaning of Setup... sry	- Jir - */
424 	for (i = 0; i < MAX_RACE; i++) {
425 		if (!race_info[i].title) {
426 			Setup.max_race = i;
427 			break;
428 		}
429 //		strncpy(&Setup.race_title[i], race_info[i].title, 12);
430 //		Setup.race_choice[i] = race_info[i].choice;
431 		/* 1 for '\0', 4 for race_choice */
432 		Setup.setup_size += strlen(race_info[i].title) + 1 + 4 + 6;
433 	}
434 
435 	for (i = 0; i < MAX_CLASS; i++) {
436 		if (!class_info[i].title) {
437 			Setup.max_class = i;
438 			break;
439 		}
440 //		strncpy(&Setup.class_title[i], class_info[i].title, 12);
441 		Setup.setup_size += strlen(class_info[i].title) + 1 + 6;
442 	}
443 
444 	for (i = 0; i < MAX_TRAIT; i++) {
445 		if (!trait_info[i].title) {
446 			Setup.max_trait = i;
447 			break;
448 		}
449 		Setup.setup_size += strlen(trait_info[i].title) + 1 + 4;
450 	}
451 
452 	return 0;
453 }
454 
init_players()455 void init_players() {
456 	max_connections = MAX_SELECT_FD - 24; /* 999 connections at most */
457 	/* Last player is the DM Edit player ! */
458 	/* As no extra connection is required, */
459 	/* we need only allocate the player_type for it */
460 	C_MAKE(Players, max_connections+1, player_type *);
461 }
462 
463 
464 /*
465  * Talk to the metaserver.
466  *
467  * This function is called on startup, on death, and when the number of players
468  * in the game changes.
469  */
Report_to_meta(int flag)470 bool Report_to_meta(int flag)
471 {
472         /* Abort if the user doesn't want to report */
473 	if (!cfg.report_to_meta || cfg.runlevel < 4 || ((cfg.runlevel > 1023) && (cfg.runlevel < 2045))) {
474 		return FALSE;
475 	}
476 
477 	/* New implementation */
478 //	s_printf("Reporting to meta...\n");
479 	meta_report(flag);
480 	return TRUE;
481 }
482 
483 /* update tomenet.acc record structure to a new version - C. Blue
484    Done by opening 'tomenet.acc_old' and (over)writing 'tomenet.acc'. */
update_acc_file_version(void)485 static bool update_acc_file_version(void) {
486 	FILE *fp_old, *fp;
487 	struct account_old c_acc_old;
488 	struct account c_acc;
489         size_t retval;
490 	char buf[1024];
491 	int amt = 0, total = 0;
492 
493 	path_build(buf, 1024, ANGBAND_DIR_SAVE, "tomenet.acc_old");
494 	fp_old = fopen(buf, "rb");
495 	/* No updating to do?
496 	   Exit here, if no 'tomenet.acc_old' file exists: */
497 	if (!fp_old) return(FALSE);
498 
499 	s_printf("Initiating tomenet.acc update.. ");
500 
501 	path_build(buf, 1024, ANGBAND_DIR_SAVE, "tomenet.acc");
502 	fp = fopen(buf, "wb");
503 	if (!fp) {
504 		s_printf("failed opening tomenet.acc.\n");
505 		fclose(fp_old);
506 		return(FALSE);
507 	}
508 
509 	/* helper vars */
510 	char *ptr;
511 
512 	while (!feof(fp_old)) {
513 		retval = fread(&c_acc_old, sizeof(struct account_old), 1, fp_old);
514 		if (retval == 0) break; /* EOF reached, nothing read into c_acc - mikaelh */
515 		total++;
516 
517 		/* copy unchanged structure parts: */
518 		c_acc.id = c_acc_old.id;
519 		c_acc.flags = c_acc_old.flags;
520 		//strcpy(c_acc.name, c_acc_old.name);
521 		strcpy(c_acc.pass, c_acc_old.pass);
522 		c_acc.acc_laston = c_acc_old.acc_laston;
523 		c_acc.acc_laston_real = c_acc_old.acc_laston_real;
524 		c_acc.cheeze = c_acc_old.cheeze;
525 		c_acc.cheeze_self = c_acc_old.cheeze_self;
526 		c_acc.deed_event = c_acc_old.deed_event;
527 		c_acc.deed_achievement = c_acc_old.deed_achievement;
528 		c_acc.guild_id = c_acc_old.guild_id;
529 		c_acc.guild_dna = c_acc.guild_id ? guilds[c_acc.guild_id].dna : 0;
530 
531 		/* changes/additions - cumulative since 4.5.8a release time, to not break non-official servers: */
532 		//1: disallow spaces at the end of account names
533 		for (ptr = &c_acc_old.name[strlen(c_acc_old.name)]; ptr-- > c_acc_old.name; ) {
534 			if (*ptr == ' ') *ptr = '\0';
535 			else break;
536 		}
537 		strcpy(c_acc.name, c_acc_old.name);
538 		//2: add 'name_normalised'
539 		condense_name(c_acc.name_normalised, c_acc_old.name);
540 
541 		/* write it back */
542 		if (fwrite(&c_acc, sizeof(struct account), 1, fp) < 1)
543 			s_printf("failure: %s\n", feof(fp) ? "EOF" : strerror(ferror(fp)));
544 
545 		amt++;
546 	}
547 	s_printf("%d of %d records updated.\n", amt, total);
548 	fclose(fp);
549 	fclose(fp_old);
550 
551 	path_build(buf, 1024, ANGBAND_DIR_SAVE, "tomenet.acc_old");
552 	remove(buf);
553 
554 	return(TRUE);
555 }
556 
557 /* Purge deleted accounts from tomenet.acc file by rewriting it. */
purge_acc_file(void)558 bool purge_acc_file(void) {
559 	FILE *fp_old, *fp;
560 	struct account c_acc;
561         size_t retval;
562 	char buf[1024], buf2[1024];
563 	int amt = 0, total = 0;
564 
565 	s_printf("Initiating tomenet.acc purge.. ");
566 
567 	path_build(buf, 1024, ANGBAND_DIR_SAVE, "tomenet.acc");
568 	fp_old = fopen(buf, "rb");
569 	if (!fp_old) {
570 		s_printf("failed opening tomenet.acc.\n");
571 		fclose(fp_old);
572 		return(FALSE);
573 	}
574 
575 	path_build(buf2, 1024, ANGBAND_DIR_SAVE, "tomenet.acc_new");
576 	fp = fopen(buf2, "wb");
577 	if (!fp) {
578 		s_printf("failed opening tomenet.acc_new.\n");
579 		fclose(fp_old);
580 		return(FALSE);
581 	}
582 
583 	while (!feof(fp_old)) {
584 		retval = fread(&c_acc, sizeof(struct account), 1, fp_old);
585 		if (retval == 0) break; /* EOF reached, nothing read into c_acc - mikaelh */
586 		total++;
587 
588 		/* Purge all deleted accounts */
589 		if (c_acc.flags & ACC_DELD) {
590 			amt++;
591 			continue;
592 		}
593 
594 		/* write it back */
595 		if (fwrite(&c_acc, sizeof(struct account), 1, fp) < 1)
596 			s_printf("failure: %s\n", feof(fp) ? "EOF" : strerror(ferror(fp)));
597 	}
598 	s_printf("%d of %d records purged.\n", amt, total);
599 	fclose(fp);
600 	fclose(fp_old);
601 
602 	remove(buf);
603 	rename(buf2, buf);
604 
605 	return(TRUE);
606 }
607 
608 /*
609  * Initialize the connection structures.
610  */
Setup_net_server(void)611 int Setup_net_server(void)
612 {
613 	size_t size;
614 
615 	Init_receive();
616 
617 	if (Init_setup() == -1)
618 		return -1;
619 
620 	/*
621 	 * The number of connections is limited by the number of bases
622 	 * and the max number of possible file descriptors to use in
623 	 * the select(2) call minus those for stdin, stdout, stderr,
624 	 * the contact socket, and the socket for the resolver library routines.
625 	 */
626 
627 	size = max_connections * sizeof(*Conn);
628 	if ((Conn = (connection_t **) malloc(size)) == NULL)
629 		quit("Cannot allocate memory for connections");
630 
631 	memset(Conn, 0, size);
632 
633 	/* Tell the metaserver that we're starting up */
634 	s_printf("Report to metaserver\n");
635 	Report_to_meta(META_START);
636 
637 	s_printf("%s\n", longVersion);
638 	s_printf("Server is running version %04x\n", MY_VERSION);
639 	strcpy(serverStartupTime, showtime());
640 	s_printf("Current time is %s\n", serverStartupTime);
641 	time(&cfg.runtime);
642 	s_printf("Session startup turn is: %d\n", turn);
643 	session_turn = turn;
644 
645 	/* Check for updating account file structure to a new version */
646 	update_acc_file_version();
647 
648 	return 0;
649 }
650 
651 /* The contact socket */
652 static int Socket;
653 static sockbuf_t ibuf;
654 
655 /* The contact socket now uses TCP.  This breaks backwards
656  * compatibility, but is a good thing.
657  */
658 
setup_contact_socket(void)659 void setup_contact_socket(void)
660 {
661 	plog(format("Create TCP socket on port %d...", cfg.game_port));
662 	while ((Socket = CreateServerSocket(cfg.game_port)) == -1)
663 	{
664 #ifdef WINDOWS
665 		Sleep(1000);
666 #else
667 		sleep(1);
668 #endif
669 	}
670 	plog("Set Non-Blocking...");
671 	if (SetSocketNonBlocking(Socket, 1) == -1)
672 	{
673 		plog("Can't make contact socket non-blocking");
674 	}
675 #ifdef FD_CLOEXEC
676 	/* Make the socket close-on-exec if possible - mikaelh */
677 	if (fcntl(Socket, F_SETFD, FD_CLOEXEC) == -1)
678 	{
679 		plog("Can't make contact socket close-on-exec");
680 	}
681 #endif
682 	if (SetSocketNoDelay(Socket, 1) == -1)
683 	{
684 		plog("Can't set TCP_NODELAY on the socket");
685 	}
686 	if (SocketLinger(Socket) == -1)
687 	{
688 		plog("Couldn't set SO_LINGER on the socket");
689 	}
690 
691 	if (Sockbuf_init(&ibuf, Socket, SERVER_SEND_SIZE,
692 		SOCKBUF_READ | SOCKBUF_WRITE ) == -1)
693 	{
694 		quit("No memory for contact buffer");
695 	}
696 
697 	install_input(Contact, Socket, 0);
698 
699 #ifdef SERVER_CONSOLE
700 	/* Hack -- Install stdin an the "console" input */
701 	install_input(Console, 0, 0);
702 #endif
703 
704 #ifdef NEW_SERVER_CONSOLE
705 	if ((ConsoleSocket = CreateServerSocket(cfg.console_port)) == -1)
706 	{
707 		s_printf("Couldn't create console socket\n");
708 		return;
709 	}
710 #ifdef FD_CLOEXEC
711 	/* Make the socket close-on-exec if possible - mikaelh */
712 	if (fcntl(ConsoleSocket, F_SETFD, FD_CLOEXEC) == -1)
713 	{
714 		plog("Can't make console socket close-on-exec");
715 	}
716 #endif
717 	if (SocketLinger(ConsoleSocket) == -1)
718 	{
719 		plog("Couldn't set SO_LINGER on the console socket");
720 	}
721 
722 	if (!InitNewConsole(ConsoleSocket))
723 	{
724 		return;
725 	}
726 
727 	/* Install the new console socket */
728 	install_input(NewConsole, ConsoleSocket, 0);
729 #endif
730 #ifdef SERVER_GWPORT
731 	/* evileye testing only */
732 	if ((SGWSocket = CreateServerSocket(cfg.gw_port)) == -1)
733 	{
734 		s_printf("Couldn't create server gateway port\n");
735 		return;
736 	}
737 #ifdef FD_CLOEXEC
738 	/* Make the socket close-on-exec if possible - mikaelh */
739 	if (fcntl(SGWSocket, F_SETFD, FD_CLOEXEC) == -1)
740 	{
741 		plog("Can't make contact socket close-on-exec");
742 	}
743 #endif
744 #if 0
745 	if (SetSocketNonBlocking(SGWSocket, 1) == -1)
746 	{
747 		plog("Can't make GW socket non-blocking");
748 	}
749 #endif
750 
751 	/* Install the new gateway socket */
752 	install_input(SGWHit, SGWSocket, 0);
753 #endif
754 #ifdef TOMENET_WORLDS
755 	world_connect(-1);
756 #endif
757 }
758 
759 #ifdef TOMENET_WORLDS
world_connect(int Ind)760 void world_connect(int Ind) {
761 	/* evileye testing only */
762 	/* really, server should DIE if this happens */
763 	if (WorldSocket != -1) {
764 		if (Ind != -1) msg_print(Ind, "\377oAlready connected to the world server");
765 		return;
766 	}
767 
768 	block_timer();
769 	if ((WorldSocket = CreateClientSocket(cfg.wserver, 18360)) == -1) {
770 #ifdef WIN32
771 		s_printf("Unable to connect to world server %d\n", errno);
772 #else
773 		s_printf("Unable to connect to world server %d %d\n", errno, sl_errno);
774 #endif
775 		if (Ind != -1) msg_print(Ind, "\377rFailed to connect to the world server");
776 	} else {
777 		install_input(world_comm, WorldSocket, 0);
778 		if (Ind != -1) msg_print(Ind, "\377gSuccessfully connected to the world server");
779 	}
780 	allow_timer();
781 }
782 #endif
783 
Reply(char * host_addr,int fd)784 static int Reply(char *host_addr, int fd)
785 {
786 	int result;
787 
788 	// No silly redundancy with TCP
789 	if ((result = DgramWrite(fd, ibuf.buf, ibuf.len)) == -1)
790 	{
791 		GetSocketError(ibuf.sock);
792 	}
793 
794 	return result;
795 }
796 
797 
798 /* invite only */
player_allowed(char * name)799 static bool player_allowed(char *name) {
800 	FILE *sfp;
801 	char buffer[80];
802 	bool success = FALSE;
803 	/* Hack -- allow 'guest' account */
804 	/* if (!strcmp("Guest", name)) return TRUE; */
805 
806 	sfp = fopen("allowlist", "r");
807 	if (sfp == (FILE*)NULL)
808 		return TRUE;
809 	else {
810 		while (fgets(buffer, 80, sfp)) {
811 			/* allow for \n */
812 			if ((strlen(name) + 1) != strlen(buffer)) continue;
813 			if (!strncmp(buffer,name, strlen(name))) {
814 				success = TRUE;
815 				break;
816 			}
817 		}
818 		fclose(sfp);
819 	}
820 	return(success);
821 }
822 
823 /* blacklist of special nicknames unavailable to players (monster names, "insanity",..) - C. Blue */
forbidden_name(char * cname)824 static bool forbidden_name(char *cname) {
825 	FILE *sfp;
826 	char path_buf[1024];
827 	char buffer[80], name[80];
828 	bool success = FALSE;
829 	int i = 0;
830 
831 	/* All bad names must be specified in lower-case */
832 	do name[i] = tolower(cname[i]);
833 	while (cname[i++]);
834 
835 
836 	/* Hack -- allow 'guest' account */
837 	/* if (!strcmp("Guest", name)) return FALSE; */
838 
839 	/* Note: Character names always start upper-case, so some of these
840 	   aren't really needed on most file systems (semi-paranoia). */
841 	/* Hardcode some critically important ones */
842 	if (!strcmp(name, "server")) return TRUE; /* server save file is stored in same folder as player save files */
843 	if (!strcmp(name, "server.new")) return TRUE; /* server save file is stored in same folder as player save files */
844 	if (!strcmp(name, "server.old")) return TRUE; /* server save file is stored in same folder as player save files */
845 	if (!strncmp(name, "server", 6) && name[6] >= '0' && name[6] <= '9') return TRUE; /* prepare for multiple partial server save files */
846 	if (strstr(name, "guild") && strstr(name, ".data")) return TRUE; /* moved guild hall save files to save folder, from data folder */
847 	if (strlen(name) >= 5 && name[0] == 's' && name[1] == 'a' && name[2] == 'v' && name[3] == 'e' &&
848 	    name[4] >= '0' && name[4] <= '9') return TRUE; /* backup save file folders, save00..saveNN */
849 	if (!strcmp(name, "estate")) return TRUE; /* for new 'estate' folder that backs up houses. */
850 	if (!strcmp(name, "quests")) return TRUE; /* dedicated quest state server save file */
851 	if (!strcmp(name, "quests.new")) return TRUE; /* dedicated quest state server save file */
852 	if (!strcmp(name, "quests.old")) return TRUE; /* dedicated quest state server save file */
853 
854 	/* account file management */
855 	if (!strcmp(name, "tomenet.acc")) return TRUE;
856 	if (!strcmp(name, "tomenet.acc_old")) return TRUE;
857 	if (!strcmp(name, "accedit")) return TRUE;
858 
859 	if (!strncmp(name, "save", 4) && name[4] >= '0' && name[4] <= '9') return TRUE; /* paranoia - backup folders "saveX..." */
860 	if (!strncmp(name, "estate", 6)) return TRUE; /* paranoia - house contents backup folder for server resets */
861 
862 	/* special death causes */
863 	if (!strcmp(name, "insanity")) return TRUE;
864 	if (!strcmp(name, "divine wrath")) return TRUE;
865 #ifdef ENABLE_MAIA
866 	if (!strcmp(name, "indecisiveness")) return TRUE;
867 #endif
868 	if (!strcmp(name, "indetermination")) return TRUE;
869 
870 	/* Hardcode some not so important ones */
871 	if (!strcmp(name, "tbot")) return TRUE; /* Sandman's internal chat bot */
872 	if (!strcmp(name, "8ball")) return TRUE; /* Sandman's internal chat bot */
873 	/* For logging chat relayed from IRC */
874 	if (!strcmp(name, "irc")) return TRUE;
875 
876 
877 	path_build(path_buf, 1024, ANGBAND_DIR_CONFIG, "badnames.txt");
878 
879 	sfp = fopen(path_buf, "r");
880 	if (sfp == (FILE*) NULL)
881 		return FALSE;
882 	else {
883 		while (fgets(buffer, 80, sfp)) {
884 			/* allow for \n */
885 			if ((strlen(name) + 1) != strlen(buffer)) continue;
886 			if (!strncmp(buffer,name, strlen(name))) {
887 				success = TRUE;
888 				break;
889 			}
890 		}
891 		fclose(sfp);
892 	}
893 	return(success);
894 }
895 
Trim_name(char * nick_name)896 static void Trim_name(char *nick_name)
897 {
898 	char *ptr;
899 	/* spaces at the beginning are impossible thanks to Check_names */
900 	/* remove spaces at the end */
901 	for (ptr = &nick_name[strlen(nick_name)]; ptr-- > nick_name; ) {
902 		if (isspace(*ptr)) *ptr = '\0';
903 		else break;
904 	}
905 	/* remove special chars that are used for parsing purpose */
906 	for (ptr = &nick_name[strlen(nick_name)]; ptr-- > nick_name; ) {
907 		if (!((*ptr >= 'A' && *ptr <= 'Z') ||
908 		    (*ptr >= 'a' && *ptr <= 'z') ||
909 		    (*ptr >= '0' && *ptr <= '9') ||
910 		    strchr(" .,-'&_$%~#<>|", *ptr))) /* chars allowed for character name, */
911 			*ptr = '_'; /* but they become _ in savefile name */
912 	}
913 }
914 
915 /* verify that account, user, host name are valid,
916    and that we're resuming from the same IP address if we're resuming  */
Check_names(char * nick_name,char * real_name,char * host_name,char * addr,bool check_for_resume)917 static int Check_names(char *nick_name, char *real_name, char *host_name, char *addr, bool check_for_resume) {
918 	player_type *p_ptr = NULL;
919 	connection_t *connp = NULL;
920 	int i;
921 
922 	if (real_name[0] == 0 || host_name[0] == 0) return E_INVAL;
923 	if (nick_name[0] < 'A' || nick_name[0] > 'Z') return E_LETTER;
924 	if (strchr(nick_name, ':')) return E_INVAL;
925 
926 	if (check_for_resume) {
927 		for (i = 1; i < NumPlayers + 1; i++) {
928 			if (Players[i]->conn != NOT_CONNECTED ) {
929 				p_ptr = Players[i];
930 				/*
931 				 * FIXME: p_ptr->name is character name while nick_name is
932 				 * account name, so this check always fail.  Evileye? :)
933 				 */
934 				if (strcasecmp(p_ptr->name, nick_name) == 0) {
935 					/*plog(format("%s %s", Players[i]->name, nick_name));*/
936 
937 					/* The following code allows you to "override" an
938 					 * existing connection by connecting again  -Crimson */
939 
940 					/* XXX Hack -- since the password is not read until later, to
941 					 * authorize the "hijacking" of an existing connection,
942 					 * we check to see if the username and hostname are
943 					 * identical.  Note that it may be possobile to spoof this,
944 					 * kicking someone off.  This is a quick hack that should
945 					 * be replaced with proper password checking.
946 					 */
947 					/* XXX another Hack -- don't allow to resume connection if
948 					 * in 'character edit' mode		- Jir -
949 					 */
950 
951 					/* resume connection at this point is not compatible
952 					   with multicharacter accounts */
953 					if (!strcasecmp(p_ptr->realname, real_name) &&
954 					    //!strcasecmp(p_ptr->accountname, acc_name) &&  --not needed, can't access nick_name from different account
955 					    !strcasecmp(p_ptr->addr, addr) && cfg.runlevel != 1024) {
956 						printf("%s %s\n", p_ptr->realname, p_ptr->addr);
957 						Destroy_connection(p_ptr->conn, "resume connection");
958 					}
959 					else return E_IN_USE;
960 				}
961 
962 				/* All restrictions on the number of allowed players from one IP have
963 				 * been removed at this time. -APD
964 				 *
965 				 * Restored after the advent of Tcp/IP, becuase there is
966 				 * no longer any good reason to allow them.  --Crimson
967 
968 				if (!strcasecmp(Players[i]->realname, real_name) &&
969 				    !strcasecmp(Players[i]->addr, addr) &&
970 				    strcasecmp(Players[i]->realname, cfg_admin_wizard) &&
971 				    strcasecmp(Players[i]->realname, cfg_dungeon_master)) {
972 					return E_TWO_PLAYERS;
973 				}
974 				*/
975 			}
976 		}
977 		/* new, fix timing exploit that allows multi-login, part 1/2 (resuming) */
978 		for (i = 0; i < max_connections; i++) {
979 			connp = Conn[i];
980 			if (!connp || connp->state == CONN_FREE) continue;// != CONN_LOGIN
981 			if (!connp->c_name) continue;//hasn't chosen a character to login with yet?
982 			if (strcasecmp(connp->c_name, nick_name)) continue;
983 			//if (strcasecmp(connp->nick, acc_name)) continue;  --not needed, can't access nick_name from different account
984 			if (!strcasecmp(connp->real, real_name) &&
985 			    !strcasecmp(connp->addr, addr) && cfg.runlevel != 1024) {
986 				printf("%s %s\n", connp->real, connp->addr);
987 				Destroy_connection(i, "resume connection");
988 			}
989 			else return E_IN_USE;
990 		}
991 	}
992 
993 	return SUCCESS;
994 }
995 /* new, fix timing exploit that allows multi-login, part 2/2 (non-resuming) */
check_multi_exploit(char * acc,char * nick)996 bool check_multi_exploit(char *acc, char *nick) {
997 	connection_t *connp = NULL;
998 	int i;
999 
1000 	for (i = 0; i < max_connections; i++) {
1001 		connp = Conn[i];
1002 		if (!connp || connp->state == CONN_FREE) continue;// != CONN_LOGIN
1003 		if (!connp->c_name) continue;//hasn't chosen a character to login with yet?
1004 		if (!strcasecmp(connp->c_name, nick)) continue; //this case is instead handled by part 1/2: resume connection!
1005 		if (strcasecmp(connp->nick, acc)) continue;
1006 		s_printf("check_multi_exploit=TRUE\n");
1007 		return TRUE;
1008 	}
1009 	return FALSE;
1010 }
1011 
1012 #if 0
1013 static void Console(int fd, int arg)
1014 {
1015 	char buf[1024];
1016 	int i;
1017 
1018 	/* See what we got */
1019         /* this code added by thaler, 6/28/97 */
1020         fgets(buf, 1024, stdin);
1021         if (buf[ strlen(buf)-1 ] == '\n')
1022             buf[ strlen(buf)-1 ] = '\0';
1023 
1024 	for (i = 0; i < strlen(buf) && buf[i] != ' '; i++)
1025 	{
1026 		/* Capitalize each letter until we hit a space */
1027 		buf[i] = toupper(buf[i]);
1028 	}
1029 
1030 	/* Process our input */
1031 	if (!strncmp(buf, "HELLO", 5))
1032 		s_printf("Hello.  How are you?\n");
1033 
1034 	if (!strncmp(buf, "SHUTDOWN", 8))
1035 	{
1036 		shutdown_server();
1037 	}
1038 
1039 
1040 	if (!strncmp(buf, "STATUS", 6))
1041 	{
1042 		s_printf("There %s %d %s.\n", (NumPlayers != 1 ? "are" : "is"), NumPlayers, (NumPlayers != 1 ? "players" : "player"));
1043 
1044 		if (NumPlayers > 0)
1045 		{
1046 			s_printf("%s:\n", (NumPlayers > 1 ? "They are" : "He is"));
1047 			for (i = 1; i < NumPlayers + 1; i++)
1048 				s_printf("\t%s\n", Players[i]->name);
1049 		}
1050 	}
1051 
1052 	if (!strncmp(buf, "MESSAGE", 7))
1053 	{
1054 		/* Send message to all players */
1055 		for (i = 1; i <= NumPlayers; i++)
1056 			msg_format(i, "[Server Admin] %s", &buf[8]);
1057 
1058 		/* Acknowledge */
1059 		s_printf("Message sent.\n");
1060 	}
1061 
1062 	if (!strncmp(buf, "KELDON", 6))
1063 	{
1064 		/* Whatever I need at the moment */
1065 	}
1066 }
1067 #endif // if 0
1068 
Contact(int fd,int arg)1069 static void Contact(int fd, int arg) {
1070 	int bytes, login_port, newsock;
1071 	u16b version = 0;
1072 	unsigned magic;
1073 	unsigned short port;
1074 	char	ch,
1075 		real_name[MAX_CHARS],
1076 		nick_name[MAX_CHARS],
1077 		host_name[MAX_CHARS],
1078 		host_addr[24],
1079 		reply_to, status;
1080 	version_type version_ext;
1081 
1082 	/* Create a TCP socket for communication with whoever contacted us */
1083 	/* Hack -- check if this data has arrived on the contact socket or not.
1084 	 * If it has, then we have not created a connection with the client yet,
1085 	 * and so we must do so.
1086 	 */
1087 
1088 	if (fd == Socket) {
1089 		if ((newsock = SocketAccept(fd)) == -1)
1090 			quit("Couldn't accept game TCP connection.\n");
1091 		install_input(Contact, newsock, 2);
1092 		return;
1093 	}
1094 
1095 	/*
1096 	 * Someone connected to us, now try and decipher the message
1097 	 */
1098 	Sockbuf_clear(&ibuf);
1099 	if ((bytes = DgramReceiveAny(fd, ibuf.buf, ibuf.size)) <= 8) {
1100 		/* If 0 bytes have been sent than the client has probably closed
1101 		 * the connection
1102 		 */
1103 		if (bytes == 0) {
1104 	/* evileye - still in contact input, so close the socket here */
1105 	/* Dont tell me it is ugly. I know ;( */
1106 	/* Sched should do accepts and closes */
1107 			close(fd);
1108 	/*end evileye*/
1109 			remove_input(fd);
1110 		}
1111 		else if (bytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR) {
1112 			/* Clear the error condition for the contact socket */
1113 			GetSocketError(fd);
1114 		}
1115 		return;
1116 	}
1117 	ibuf.len = bytes;
1118 
1119 #ifdef WINDOWS
1120 	/* Get the IP address of the client, without using the broken DgramLastAddr() */
1121 	struct sockaddr_in sin;
1122 	int len = sizeof(sin);
1123 	if (getpeername(fd, (struct sockaddr *) &sin, &len) >= 0) {
1124 		u32b addr = ntohl(sin.sin_addr.s_addr);
1125 		strnfmt(host_addr, sizeof(host_addr), "%d.%d.%d.%d", (byte)(addr>>24),
1126 			(byte)(addr>>16), (byte)(addr>>8), (byte)addr);
1127 	}
1128 #else
1129 	strcpy(host_addr, DgramLastaddr(fd));
1130 	if (errno == ENOTCONN) {	/* will be "0.0.0.0" probably */
1131 		s_printf("Lost connection from unknown peer\n");
1132 		close(fd);
1133 		remove_input(fd);
1134 		return;
1135 	}
1136 #endif
1137 
1138 	/*if (Check_address(host_addr)) return;*/
1139 
1140 	if (Packet_scanf(&ibuf, "%u", &magic) <= 0) {
1141 		plog(format("Incompatible packet from %s", host_addr));
1142 		return;
1143 	}
1144 
1145 	if (Packet_scanf(&ibuf, "%s%hu%c", real_name, &port, &ch) <= 0) {
1146 		plog(format("Incomplete packet from %s", host_addr));
1147 		return;
1148 	}
1149 	reply_to = (ch & 0xFF);
1150 
1151 	port = DgramLastport(fd);
1152 
1153 	if (Packet_scanf(&ibuf, "%s%s%hu", nick_name, host_name, &version) <= 0) {
1154 		plog(format("Incomplete login from %s", host_addr));
1155 		return;
1156 	}
1157 	if (version == 0xFFFFU) {
1158 		/* Extended version support */
1159 		if (Packet_scanf(&ibuf, "%d%d%d%d%d%d", &version_ext.major, &version_ext.minor, &version_ext.patch, &version_ext.extra, &version_ext.branch, &version_ext.build) <= 0) {
1160 			plog(format("Incomplete extended version from %s", host_addr));
1161 			return;
1162 		}
1163 
1164 		/* Hack: Clients > 4.4.8.1.0.0 also send their binary type
1165 		   (OS they were compiled for), useful for MinGW weirdness
1166 		   in the future, like the LUA crash bug - C. Blue */
1167 		if (is_older_than(&version_ext, 4, 4, 9, 2, 0, 0)) {
1168 			version_ext.os = version_ext.build / 1000;
1169 			version_ext.build %= 1000;
1170 		} else {
1171 			/* Use millions as of 4.4.9.2 (449b) - mikaelh */
1172 			version_ext.os = version_ext.build / 1000000;
1173 			version_ext.build %= 1000000;
1174 		}
1175 	} else {
1176 		version_ext.major = version >> 12;
1177 		version_ext.minor = (version >> 8) & 0xF;
1178 		version_ext.patch = (version >> 4) & 0xF;
1179 		version_ext.extra = version & 0xF;
1180 		version_ext.branch = 0;
1181 		version_ext.build = 0;
1182 	}
1183 
1184 	//what does this stuff do?
1185 	nick_name[sizeof(nick_name) - 1] = '\0';
1186 	host_name[sizeof(host_name) - 1] = '\0';
1187 
1188 	/* server-side limit checks */
1189 	nick_name[ACCOUNTNAME_LEN - 1] = '\0';
1190 	real_name[REALNAME_LEN - 1] = '\0';
1191 	host_name[HOSTNAME_LEN - 1] = '\0';
1192 
1193 #if 1
1194 	s_printf("Received contact from %s:%d.\n", host_name, port);
1195 	s_printf("Address: %s.\n", host_addr);
1196 	s_printf("Info: real_name %s, port %hu, nick %s, host %s, version %hu\n", real_name, port, nick_name, host_name, version);
1197 #endif
1198 
1199 	/* Replace all weird chars - mikaelh */
1200 	validatestring(real_name);
1201 	validatestring(host_name);
1202 
1203 	status = Enter_player(real_name, nick_name, host_addr, host_name,
1204 				&version_ext, port, &login_port, fd);
1205 
1206 #if DEBUG_LEVEL > 0
1207 	if (status && status != E_NEED_INFO)
1208 		s_printf("%s: Connection refused(%d).. %s=%s@%s (%s/%d)\n", showtime(),
1209 				status, nick_name, real_name, host_name, host_addr, port);
1210 #endif	// DEBUG_LEVEL
1211 
1212 	Sockbuf_clear(&ibuf);
1213 
1214 	/* s_printf("Sending login port %d, status %d.\n", login_port, status); */
1215 
1216 	if (is_newer_than(&version_ext, 4, 4, 1, 5, 0, 0)) {
1217 		/* Hack - Send server version too - mikaelh */
1218 		Packet_printf(&ibuf, "%c%c%d%d", reply_to, status, login_port, CHAR_CREATION_FLAGS | 0x02);
1219 		Packet_printf(&ibuf, "%d%d%d%d%d%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_EXTRA, VERSION_BRANCH, VERSION_BUILD);
1220 	}
1221 	else {
1222 	        Packet_printf(&ibuf, "%c%c%d%d", reply_to, status, login_port, CHAR_CREATION_FLAGS);
1223 	}
1224 
1225 /* -- DGDGDGDG it would be NEAT to have classes sent to the cleint at conenciton, sadly Im too clumpsy at network code ..
1226         for (i = 0; i < MAX_CLASS; i++)
1227         {
1228                  Packet_printf(&ibuf, "%c%s", i, class_info[i].title);
1229         }
1230 */
1231 	Reply(host_addr, fd);
1232 }
1233 
Enter_player(char * real,char * nick,char * addr,char * host,version_type * version,int port,int * login_port,int fd)1234 static int Enter_player(char *real, char *nick, char *addr, char *host,
1235 				version_type *version, int port, int *login_port, int fd)
1236 {
1237 	//int status;
1238 
1239 	*login_port = 0;
1240 
1241 #if 0
1242 	if(!validstrings(nick, real, host))
1243 #else
1244 	/* Only check the account name for weird chars - mikaelh */
1245 	if(!validstring(nick))
1246 #endif
1247 		return E_INVAL;
1248 
1249 	if (NumPlayers >= max_connections)
1250 		return E_GAME_FULL;
1251 
1252 #if 0	/* This would pass in the account name rather than the
1253 	   player's character name. Also, we must *always* allow
1254 	   a second account login - it may be a subsequent resume.
1255 	   We can check duplicate account use on player entry
1256 	   (PKT_LOGIN) */
1257 	if ((status = Check_names(nick, real, host, addr, TRUE)) != SUCCESS)
1258 	{
1259 		/*s_printf("Check_names failed with result %d.\n", status);*/
1260 		return status;
1261 	}
1262 #endif
1263 
1264 #if 0
1265 	if (version < MY_VERSION)
1266 		return E_VERSION_OLD;
1267 	if (version > MY_VERSION)
1268 		return E_VERSION_UNKNOWN;
1269 #else
1270 	/* Extended version support */
1271 	if (is_older_than(version, MIN_VERSION_MAJOR, MIN_VERSION_MINOR, MIN_VERSION_PATCH, MIN_VERSION_EXTRA, 0, 0)) {
1272 		return E_VERSION_OLD;
1273 	} else if (is_newer_than(version, MAX_VERSION_MAJOR, MAX_VERSION_MINOR, MAX_VERSION_PATCH, MAX_VERSION_EXTRA, 0, INT_MAX)) {
1274 		return E_VERSION_UNKNOWN;
1275 	}
1276 #endif
1277 
1278 	if (!player_allowed(nick)) return E_INVITE;
1279 	if (in_banlist(nick, addr, NULL, NULL)) return(E_BANNED);
1280 
1281 	*login_port = Setup_connection(real, nick, addr, host, version, fd);
1282 	if (*login_port == -1) return E_SOCKET;
1283 
1284 	return SUCCESS;
1285 }
1286 
1287 
Conn_set_state(connection_t * connp,int state,int drain_state)1288 static void Conn_set_state(connection_t *connp, int state, int drain_state)
1289 {
1290 	static int num_conn_busy;
1291 	static int num_conn_playing;
1292 
1293 	if ((connp->state & (CONN_PLAYING | CONN_READY)) != 0)
1294 		num_conn_playing--;
1295 	else if (connp->state == CONN_FREE)
1296 		num_conn_busy++;
1297 
1298 	connp->state = state;
1299 	connp->drain_state = drain_state;
1300 	connp->start = turn;
1301 
1302 	if (connp->state == CONN_PLAYING)
1303 	{
1304 		num_conn_playing++;
1305 		connp->timeout = IDLE_TIMEOUT;
1306 	}
1307 	else if (connp->state == CONN_READY)
1308 	{
1309 		num_conn_playing++;
1310 		connp->timeout = READY_TIMEOUT;
1311 	}
1312 	else if (connp->state == CONN_LOGIN)
1313 		connp->timeout = LOGIN_TIMEOUT;
1314 	else if (connp->state == CONN_SETUP)
1315 		connp->timeout = SETUP_TIMEOUT;
1316 	else if (connp->state == CONN_LISTENING)
1317 		connp->timeout = LISTEN_TIMEOUT;
1318 	else if (connp->state == CONN_FREE)
1319 	{
1320 		num_conn_busy--;
1321 		connp->timeout = IDLE_TIMEOUT;
1322 	}
1323 	login_in_progress = num_conn_busy - num_conn_playing;
1324 }
1325 
1326 
1327 /*
1328  * Delete a player's information and save his game
1329  */
Delete_player(int Ind)1330 static void Delete_player(int Ind)
1331 {
1332 	player_type *p_ptr = Players[Ind];
1333 	int i;
1334 	inventory_change_type *inv_change;
1335 
1336 	/* terminate mindcrafter charm effect */
1337 	do_mstopcharm(Ind);
1338 
1339 	/* Be paranoid */
1340 	cave_type **zcave;
1341 	if ((zcave = getcave(&p_ptr->wpos)))
1342 	{
1343 		/* There's nobody on this space anymore */
1344 		zcave[p_ptr->py][p_ptr->px].m_idx = 0;
1345 
1346 		/* Forget his lite and viewing area */
1347 		forget_lite(Ind);
1348 		forget_view(Ind);
1349 
1350 		/* Show everyone his disappearance */
1351 		everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
1352 	}
1353 
1354 	/* If (s)he was in a game team, remove him/her - mikaelh */
1355 	if (p_ptr->team != 0)
1356 	{
1357 		teams[p_ptr->team - 1]--;
1358 		p_ptr->team = 0;
1359 	}
1360 
1361 	/* Also remove hostility if (s)he was blood bonded - mikaelh */
1362 	if (p_ptr->blood_bond)
1363 	{
1364 #if 0
1365 		remove_hostility(Ind, lookup_player_name(p_ptr->blood_bond));
1366 
1367 		i = find_player(p_ptr->blood_bond);
1368 		if (i)
1369 		{
1370 			remove_hostility(i, p_ptr->name);
1371 			Players[i]->blood_bond = 0;
1372 		}
1373 
1374 		p_ptr->blood_bond = 0;
1375 #else
1376 		player_list_type *pl_ptr, *tmp;
1377 		pl_ptr = p_ptr->blood_bond;
1378 
1379 		while (pl_ptr)
1380 		{
1381 			/* Remove hostility */
1382 			remove_hostility(Ind, lookup_player_name(pl_ptr->id));
1383 
1384 			i = find_player(pl_ptr->id);
1385 			if (i)
1386 			{
1387 				/* Remove hostility and blood bond from the other player */
1388 				remove_hostility(i, p_ptr->name);
1389 				remove_blood_bond(i, Ind);
1390 			}
1391 
1392 			tmp = pl_ptr;
1393 			pl_ptr = pl_ptr->next;
1394 			FREE(tmp, player_list_type);
1395 		}
1396 
1397 		/* The list is gone now */
1398 		p_ptr->blood_bond = NULL;
1399 #endif
1400 	}
1401 
1402 	/* Remove ignores - mikaelh */
1403 #if 0
1404 	if (p_ptr->ignore)
1405 	{
1406 		hostile_type *h_ptr, *tmp;
1407 
1408 		h_ptr = p_ptr->ignore;
1409 
1410 		while (h_ptr)
1411 		{
1412 			tmp = h_ptr;
1413 			h_ptr = h_ptr->next;
1414 			FREE(tmp, hostile_type);
1415 		}
1416 	}
1417 #else
1418 	/* Make use of the new player_list_free */
1419 	player_list_free(p_ptr->ignore);
1420 #endif
1421 
1422 	/* Remove him from everyone's afk_noticed if he was AFK */
1423 	if (p_ptr->afk)
1424 		for (i = 1; i <= NumPlayers; i++)
1425 			player_list_del(&Players[i]->afk_noticed, p_ptr->id);
1426 
1427 	/* Free afk_noticed - mikaelh */
1428 	player_list_free(p_ptr->afk_noticed);
1429 
1430 	/* Free inventory changes - mikaelh */
1431 	inv_change = p_ptr->inventory_changes;
1432 	while (inv_change) {
1433 		inventory_change_type *free_change = inv_change;
1434 		inv_change = inv_change->next;
1435 		KILL(free_change, inventory_change_type);
1436 	}
1437 	p_ptr->inventory_changes = NULL;
1438 
1439 	/* Try to save his character */
1440 	save_player(Ind);
1441 
1442 	/* If he was actively playing, tell everyone that he's left */
1443 	/* handle the cfg_secret_dungeon_master option */
1444 	if (p_ptr->alive && !p_ptr->death) {
1445 		if (!p_ptr->admin_dm || !cfg.secret_dungeon_master) {
1446 			cptr title = "";
1447 			if (p_ptr->total_winner) {
1448 				if (p_ptr->mode & (MODE_HARD | MODE_NO_GHOST)) {
1449 					title = (p_ptr->male)?"Emperor ":((!strcmp(p_ptr->name,"Tina"))?"Tiny ":"Empress ");
1450 				} else {
1451 					title = (p_ptr->male)?"King ":"Queen ";
1452 				}
1453 			}
1454 			if (p_ptr->admin_dm) title = (p_ptr->male)?"Dungeon Master ":"Dungeon Mistress ";
1455 			if (p_ptr->admin_wiz) title = "Dungeon Wizard ";
1456 
1457 #ifdef TOMENET_WORLDS /* idea: maybe use the 'quiet' flag as 'dungeon master' flag instead? */
1458 			world_player(p_ptr->id, p_ptr->name, FALSE, TRUE); /* last flag is 'quiet' mode -> no public msg */
1459 #endif
1460 
1461 			for (i = 1; i < NumPlayers + 1; i++)
1462 			{
1463 				if (Players[i]->conn == NOT_CONNECTED)
1464 					continue;
1465 
1466 				/* Don't tell him about himself */
1467 				if (i == Ind) continue;
1468 
1469 				/* Send a little message */
1470 				msg_format(i, "\374\377%c%s%s has left the game.", COLOUR_SERVER, title, p_ptr->name);
1471 			}
1472 #ifdef TOMENET_WORLDS
1473 			if (cfg.worldd_pleave) world_msg(format("\374\377%c%s%s has left the game.", COLOUR_SERVER, title, p_ptr->name));
1474 #endif
1475 		} else {
1476 			cptr title = "";
1477 			if (p_ptr->admin_dm) title = (p_ptr->male)?"Dungeon Master ":"Dungeon Mistress ";
1478 			if (p_ptr->admin_wiz) title = "Dungeon Wizard ";
1479 #if 0 /* Don't show admins in the list!! Reenable this when 'quiet' flag got reworked into 'dm' flag or sth. */
1480 #ifdef TOMENET_WORLDS
1481 			world_player(p_ptr->id, p_ptr->name, FALSE, TRUE); /* last flag is 'quiet' mode -> no public msg */
1482 #endif
1483 #endif
1484 			for (i = 1; i < NumPlayers + 1; i++) {
1485 				if (Players[i]->conn == NOT_CONNECTED)
1486 					continue;
1487 				if (!is_admin(Players[i]))
1488 					continue;
1489 
1490 				/* Don't tell him about himself */
1491 				if (i == Ind) continue;
1492 
1493 				/* Send a little message */
1494 				msg_format(i, "\374\377%c%s%s has left the game.", COLOUR_SERVER, title, p_ptr->name);
1495 				/* missing TOMENET_WORLDS relay here :/ (currently no way to send to 'foreign' admins only) - C. Blue */
1496 			}
1497 		}
1498 	}
1499 
1500 #ifdef AUCTION_SYSTEM
1501 	/* Save his/her money in the hash table */
1502 	clockin(Ind, 5);
1503 #endif
1504 
1505 	if (p_ptr->esp_link_type && p_ptr->esp_link) {
1506 		/* This is the last chance to get out!!! */
1507 		int Ind2 = find_player(p_ptr->esp_link);
1508 		if (Ind2) end_mind(Ind2, TRUE);
1509 	}
1510 
1511 
1512 	/* Swap entry number 'Ind' with the last one */
1513 	/* Also, update the "player_index" on the cave grids */
1514 	if (Ind != NumPlayers) {
1515 		cave_type **zcave;
1516 		worldpos *wpos = &Players[NumPlayers]->wpos;
1517 		p_ptr			= Players[NumPlayers];
1518 		if ((zcave = getcave(&p_ptr->wpos)))
1519 			zcave[p_ptr->py][p_ptr->px].m_idx = 0 - Ind;
1520 		Players[NumPlayers]	= Players[Ind];
1521 		Players[Ind]		= p_ptr;
1522 		cave_midx_debug(wpos, p_ptr->py, p_ptr->px, -Ind);
1523 		p_ptr			= Players[NumPlayers];
1524 	}
1525 
1526 	if (Conn[Players[Ind]->conn]->id != -1)
1527 		GetInd[Conn[Players[Ind]->conn]->id] = Ind;
1528 	if (Conn[Players[NumPlayers]->conn]->id != -1)
1529 		GetInd[Conn[Players[NumPlayers]->conn]->id] = NumPlayers;
1530 
1531 	Players[Ind]->Ind = Ind;
1532 
1533 	/* Recalculate player-player visibility */
1534 	update_players();
1535 
1536 	if (!is_admin(p_ptr)) NumNonAdminPlayers--;
1537 
1538 	if (p_ptr) {
1539 		if (p_ptr->inventory)
1540 			C_FREE(p_ptr->inventory, INVEN_TOTAL, object_type);
1541 		if (p_ptr->inventory_copy)
1542 			C_FREE(p_ptr->inventory_copy, INVEN_TOTAL, object_type);
1543 
1544 		KILL(Players[NumPlayers], player_type);
1545 	}
1546 
1547 	NumPlayers--;
1548 
1549 	/* Update Morgoth eventually if the player was on his level */
1550 	check_Morgoth(0);
1551 
1552 	/* Tell the metaserver about the loss of a player */
1553 	Report_to_meta(META_UPDATE);
1554 }
1555 
1556 
1557 /*
1558  * Cleanup a connection.  The client may not know yet that it is thrown out of
1559  * the game so we send it a quit packet if our connection to it has not already
1560  * closed.  If our connection to it has been closed, then connp->w.sock will
1561  * be set to -1.
1562  */
Destroy_connection(int ind,char * reason_orig)1563 bool Destroy_connection(int ind, char *reason_orig)
1564 {
1565 	connection_t	*connp = Conn[ind];
1566 	int		id, len, sock;
1567 	char		pkt[MAX_CHARS];
1568 	char		*reason;
1569 	int		i, player = 0;
1570 	char		traffic[50+1];
1571 	player_type	*p_ptr = NULL;
1572 
1573 	/* reason was probably made using format() which uses a static buffer so copy it - mikaelh */
1574 	reason = (char*)string_make(reason_orig);
1575 
1576 	kill_xfers(ind);	/* don't waste time sending to a dead
1577 				   connection ( or crash! ) */
1578 
1579 	if (!connp || connp->state == CONN_FREE) {
1580 		errno = 0;
1581 		plog(format("Cannot destroy empty connection (\"%s\")", reason));
1582 		string_free(reason);
1583 		return FALSE;
1584 	}
1585 
1586 	if (connp->id != -1) {
1587 		exec_lua(0, format("player_leaves(%d, %d, \"%/s\", \"%s\")", GetInd[connp->id], connp->id, connp->c_name, showtime()));
1588 
1589 		/* in case winners CAN hold arts as long as they don't leave the floor (default): */
1590 		//lua_strip_true_arts_from_present_player(GetInd[connp->id], int mode)
1591 	} else
1592 		exec_lua(0, format("player_leaves(%d, %d, \"%/s\", \"%s\")", 0, connp->id, connp->c_name, showtime()));
1593 
1594 	sock = connp->w.sock;
1595 	if (sock != -1) remove_input(sock);
1596 
1597 	strncpy(&pkt[1], reason, sizeof(pkt) - 3);
1598 	pkt[sizeof(pkt) - 2] = '\0';
1599 	pkt[0] = PKT_QUIT;
1600 	len = strlen(pkt) + 2;
1601 	pkt[len - 1] = PKT_END;
1602 	pkt[len] = '\0';
1603 	/*len++;*/
1604 
1605 	if (sock != -1) {
1606 #if 1	// sorry evileye, removing it causes SIGPIPE to the client
1607 
1608 		if (DgramWrite(sock, pkt, len) != len) {
1609 			GetSocketError(sock);
1610 //maybe remove this one too? Or have its error be cleared too? - C. Blue
1611 //    			DgramWrite(sock, pkt, len);
1612 		}
1613 #endif
1614 	}
1615 
1616 	if (connp->id != -1) {
1617 		player = GetInd[connp->id];
1618 		p_ptr = Players[player];
1619 	}
1620 	if (p_ptr) {
1621 		s_printf("%s: Goodbye %s(%s)=%s@%s (\"%s\") (Ind=%d,ind=%d;wpos=%d,%d,%d;xy=%d,%d)\n",
1622 		    showtime(),
1623 		    connp->c_name ? connp->c_name : "",
1624 		    connp->nick ? connp->nick : "",
1625 		    connp->real ? connp->real : "",
1626 		    connp->host ? connp->host : "",
1627 		    reason, player, ind,
1628 		    p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz,
1629 		    p_ptr->px, p_ptr->py);
1630 		clockin(player, 7); /* Remember his wpos -- should be redundant with clockin() call in dungeon.c:process_player_change_wpos() */
1631 	} else
1632 		s_printf("%s: Goodbye %s(%s)=%s@%s (\"%s\") (Ind=%d,ind=%d;wpos=-,-,-;xy=-,-)\n",
1633 		    showtime(),
1634 		    connp->c_name ? connp->c_name : "",
1635 		    connp->nick ? connp->nick : "",
1636 		    connp->real ? connp->real : "",
1637 		    connp->host ? connp->host : "",
1638 		    reason, player, ind);
1639 
1640 	Conn_set_state(connp, CONN_FREE, CONN_FREE);
1641 
1642 	if (connp->id != -1) {
1643 		id = connp->id;
1644 		connp->id = -1;
1645 	/*
1646 		Players[GetInd[id]]->conn = NOT_CONNECTED;
1647 	*/
1648 		Delete_player(GetInd[id]);
1649 	}
1650 
1651 	exec_lua(0, format("player_has_left(%d, %d, \"%/s\", \"%s\")", player, connp->id, connp->c_name, showtime()));
1652 	if (NumPlayers == 0) exec_lua(0, format("last_player_has_left(%d, %d, \"%/s\", \"%s\")", player, connp->id, connp->c_name, showtime()));
1653 	strcpy(traffic, "");
1654 	for (i = 1; (i <= NumPlayers) && (i < 50); i++)
1655 		if (!(i % 5)) strcat(traffic, "* "); else strcat(traffic, "*");
1656 	p_printf("%s -  %03d  %s\n", showtime(), NumPlayers, traffic);
1657 
1658 	if (connp->real != NULL) free(connp->real);
1659 	if (connp->nick != NULL) free(connp->nick);
1660 	if (connp->addr != NULL) free(connp->addr);
1661 	if (connp->host != NULL) free(connp->host);
1662 	if (connp->c_name != NULL) free(connp->c_name);
1663 	Sockbuf_cleanup(&connp->w);
1664 	Sockbuf_cleanup(&connp->r);
1665 	Sockbuf_cleanup(&connp->c);
1666 	Sockbuf_cleanup(&connp->q);
1667 	memset(connp, 0, sizeof(*connp));
1668 
1669 	/* Free the connection_t structure - mikaelh */
1670 	KILL(Conn[ind], connection_t);
1671 	connp = NULL;
1672 
1673 	num_logouts++;
1674 
1675 	if (sock != -1) DgramClose(sock);
1676 
1677 	string_free(reason);
1678 
1679 	return TRUE;
1680 }
1681 
Check_connection(char * real,char * nick,char * addr)1682 int Check_connection(char *real, char *nick, char *addr)
1683 {
1684 	int i;
1685 	connection_t *connp;
1686 
1687 	for (i = 0; i < max_connections; i++)
1688 	{
1689 		connp = Conn[i];
1690 		if (connp && connp->state == CONN_LISTENING)
1691 			if (strcasecmp(connp->nick, nick) == 0)
1692 			{
1693 				if (!strcmp(real, connp->real)
1694 					&& !strcmp(addr, connp->addr))
1695 						return connp->my_port;
1696 				return -1;
1697 			}
1698 	}
1699 	return -1;
1700 }
1701 
1702 
1703 /*
1704  * A client has requested a playing connection with this server.
1705  * See if we have room for one more player and if his name is not
1706  * already in use by some other player.  Because the confirmation
1707  * may get lost we are willing to send it another time if the
1708  * client connection is still in the CONN_LISTENING state.
1709  */
Setup_connection(char * real,char * nick,char * addr,char * host,version_type * version,int fd)1710 int Setup_connection(char *real, char *nick, char *addr, char *host,
1711 			version_type *version, int fd)
1712 {
1713 	int i, free_conn_index = max_connections, my_port, sock;
1714 	connection_t *connp;
1715 
1716 	for (i = 0; i < max_connections; i++)
1717 	{
1718 		connp = Conn[i];
1719 		if (!connp || connp->state == CONN_FREE)
1720 		{
1721 			if (free_conn_index == max_connections)
1722 				free_conn_index = i;
1723 			continue;
1724 		}
1725 
1726 		/* Do not deny access here, or we cannot *ever*
1727 		   resume or allow multiple connections from
1728 		   a single account. */
1729 #if 0
1730 		if (strcasecmp(connp->nick, nick) == 0)
1731 		{
1732 			if (connp->state == CONN_LISTENING
1733 				&& strcmp(real, connp->real) == 0
1734 				&& version == connp->version)
1735 					return connp->my_port;
1736 			else return -1;
1737 		}
1738 #endif
1739 	}
1740 
1741 	if (free_conn_index >= max_connections)
1742 	{
1743 		s_printf("Full house for %s(%s)@%s\n", real, nick, host);
1744 		return -1;
1745 	}
1746 
1747 	/* Allocate the connection_t structure - mikaelh */
1748 	MAKE(Conn[free_conn_index], connection_t);
1749 
1750 	connp = Conn[free_conn_index];
1751 
1752 	if (connp == NULL)
1753 	{
1754 		plog("Not enough memory for connection");
1755 		Destroy_connection(free_conn_index, "Server is out of memory.");
1756 		return -1;
1757 	}
1758 
1759 	// A TCP connection already exists with the client, use it.
1760 	sock = fd;
1761 
1762 	if ((my_port = GetPortNum(sock)) == 0)
1763 	{
1764 		plog("Cannot get port from socket");
1765 		DgramClose(sock);
1766 		return -1;
1767 	}
1768 	if (SetSocketNonBlocking(sock, 1) == -1)
1769 	{
1770 		plog("Cannot make client socket non-blocking");
1771 		DgramClose(sock);
1772 		return -1;
1773 	}
1774 	if (SocketLinger(sock) == -1)
1775 	{
1776 		plog("Couldn't set SO_LINGER on the socket");
1777 	}
1778 	if (SetSocketReceiveBufferSize(sock, SERVER_RECV_SIZE + 256) == -1)
1779 		plog(format("Cannot set receive buffer size to %d", SERVER_RECV_SIZE + 256));
1780 	if (SetSocketSendBufferSize(sock, SERVER_SEND_SIZE + 256) == -1)
1781 		plog(format("Cannot set send buffer size to %d", SERVER_SEND_SIZE + 256));
1782 
1783 	Sockbuf_init(&connp->w, sock, SERVER_SEND_SIZE, SOCKBUF_WRITE);
1784 	Sockbuf_init(&connp->r, sock, SERVER_RECV_SIZE, SOCKBUF_WRITE | SOCKBUF_READ);
1785 	Sockbuf_init(&connp->c, -1, MAX_SOCKBUF_SIZE, SOCKBUF_WRITE | SOCKBUF_READ | SOCKBUF_LOCK);
1786 	Sockbuf_init(&connp->q, -1, MAX_SOCKBUF_SIZE, SOCKBUF_WRITE | SOCKBUF_READ | SOCKBUF_LOCK);
1787 
1788 	connp->my_port = my_port;
1789 	connp->real = strdup(real);
1790 	connp->nick = strdup(nick);
1791 	connp->addr = strdup(addr);
1792 	connp->host = strdup(host);
1793 #if 0
1794 	connp->version = version;
1795 #else
1796 	/* Extended version support */
1797 	memcpy(&connp->version, version, sizeof(version_type));
1798 #endif
1799 	connp->start = turn;
1800 	connp->magic = rand() + my_port + sock + turn;
1801 	connp->id = -1;
1802 	connp->timeout = LISTEN_TIMEOUT;
1803 /* - not used - mikaelh
1804 	connp->reliable_offset = 0;
1805 	connp->reliable_unsent = 0;
1806 	connp->last_send_loops = 0;
1807 	connp->retransmit_at_loop = 0;
1808 	connp->rtt_retransmit = DEFAULT_RETRANSMIT;
1809 	connp->rtt_smoothed = 0;
1810 	connp->rtt_dev = 0;
1811 	connp->rtt_timeouts = 0;
1812 */
1813 	connp->acks = 0;
1814 	connp->setup = 0;
1815 	connp->password_verified = FALSE;
1816 	Conn_set_state(connp, CONN_LISTENING, CONN_FREE);
1817 	if (connp->w.buf == NULL || connp->r.buf == NULL || connp->c.buf == NULL
1818 		|| connp->q.buf == NULL || connp->real == NULL || connp->nick == NULL
1819 		|| connp->addr == NULL || connp->host == NULL)
1820 	{
1821 		plog("Not enough memory for connection");
1822 		Destroy_connection(free_conn_index, "Server is out of memory.");
1823 		return -1;
1824 	}
1825 
1826 	// Remove the contact input handler
1827 	remove_input(sock);
1828 	// Install the game input handler
1829 	install_input(Handle_input, sock, free_conn_index);
1830 
1831 	return my_port;
1832 }
1833 
Handle_setup(int ind)1834 static int Handle_setup(int ind)
1835 {
1836 	connection_t *connp = Conn[ind];
1837 	char *buf;
1838 	int n, len, i, j;
1839 	char b1, b2, b3, b4, b5, b6;
1840 
1841 	if (connp->state != CONN_SETUP) {
1842 		Destroy_connection(ind, "not setup");
1843 		return -1;
1844 	}
1845 
1846 	if (connp->setup == 0) {
1847 		if (is_newer_than(&connp->version, 4, 4, 5, 10, 0, 0))
1848 			n = Packet_printf(&connp->c, "%d%hd%c%c%c%d",
1849 			    Setup.motd_len, Setup.frames_per_second, Setup.max_race, Setup.max_class, Setup.max_trait, Setup.setup_size);
1850 		else
1851 			n = Packet_printf(&connp->c, "%d%hd%c%c%d",
1852 			    Setup.motd_len, Setup.frames_per_second, Setup.max_race, Setup.max_class, Setup.setup_size);
1853 
1854 		if (n <= 0) {
1855 			Destroy_connection(ind, "Setup 0 write error");
1856 			return -1;
1857 		}
1858 
1859 		for (i = 0; i < Setup.max_race; i++) {
1860 //			Packet_printf(&ibuf, "%c%s", i, class_info[i].title);
1861 			b1 = race_info[i].r_adj[0]+50;
1862 			b2 = race_info[i].r_adj[1]+50;
1863 			b3 = race_info[i].r_adj[2]+50;
1864 			b4 = race_info[i].r_adj[3]+50;
1865 			b5 = race_info[i].r_adj[4]+50;
1866 			b6 = race_info[i].r_adj[5]+50;
1867 			Packet_printf(&connp->c, "%c%c%c%c%c%c%s%d", b1, b2, b3, b4, b5, b6, race_info[i].title, race_info[i].choice);
1868 		}
1869 
1870 		for (i = 0; i < Setup.max_class; i++) {
1871 //			Packet_printf(&ibuf, "%c%s", i, class_info[i].title);
1872 			b1 = class_info[i].c_adj[0]+50;
1873 			b2 = class_info[i].c_adj[1]+50;
1874 			b3 = class_info[i].c_adj[2]+50;
1875 			b4 = class_info[i].c_adj[3]+50;
1876 			b5 = class_info[i].c_adj[4]+50;
1877 			b6 = class_info[i].c_adj[5]+50;
1878 			Packet_printf(&connp->c, "%c%c%c%c%c%c%s", b1, b2, b3, b4, b5, b6, class_info[i].title);
1879 			if (is_newer_than(&connp->version, 4, 4, 3, 1, 0, 0))
1880 				for (j = 0; j < 6; j++)
1881 					Packet_printf(&connp->c, "%c", class_info[i].min_recommend[j]);
1882 		}
1883 
1884 		if (is_newer_than(&connp->version, 4, 4, 5, 10, 0, 0))
1885 		for (i = 0; i < Setup.max_trait; i++)
1886 			Packet_printf(&connp->c, "%s%d", trait_info[i].title, trait_info[i].choice);
1887 
1888 		connp->setup = (char *) &Setup.motd[0] - (char *) &Setup;
1889 		connp->setup = 0;
1890 	}
1891 	/* else if (connp->setup < Setup.setup_size) */
1892 	else if (connp->setup < Setup.motd_len) {
1893 		if (connp->c.len > 0) {
1894 			/* If there is still unacked reliable data test for acks. */
1895 			Handle_input(-1, ind);
1896 			if (connp->state == CONN_FREE)
1897 				return -1;
1898 		}
1899 	}
1900 	/* if (connp->setup < Setup.setup_size) */
1901 	if (connp->setup < Setup.motd_len) {
1902 		len = MIN(connp->c.size, 4096) - connp->c.len;
1903 		if (len <= 0) {
1904 			/* Wait for acknowledgement of previously transmitted data. */
1905 			return 0;
1906 		}
1907 	/*
1908 		if (len > Setup.setup_size - connp->setup)
1909 			len = Setup.setup_size - connp->setup;
1910 	*/
1911 
1912 		if (len>Setup.motd_len-connp->setup) {
1913 			len = Setup.motd_len - connp->setup;
1914 			len = Setup.motd_len;
1915 		}
1916 
1917 	/*	buf = (char *) &Setup; */
1918 		buf = (char *) &Setup.motd[0];
1919 		if (Sockbuf_write(&connp->c, &buf[connp->setup], len) != len) {
1920 			Destroy_connection(ind, "sockbuf write setup error");
1921 			return -1;
1922 		}
1923 		connp->setup += len;
1924 		if (len >= 512)
1925 			connp->start += (len * cfg.fps) / (8 * 512) + 1;
1926 	}
1927 
1928 	/* if (connp->setup >= Setup.setup_size) */
1929 	if (connp->setup >= Setup.motd_len)
1930 		//Conn_set_state(connp, CONN_DRAIN, CONN_LOGIN);
1931 		Conn_set_state(connp, CONN_LOGIN, CONN_LOGIN);
1932 
1933 	return 0;
1934 }
1935 
1936 /*
1937  * No spaces/strange characters in the account name,
1938  * real name or hostname.
1939  */
1940 #if 0
1941 static bool validstrings(char *nick, char *real, char *host) {
1942 	int i;
1943 	int rval = 1;
1944 
1945 	for (i = 0; nick[i]; i++) {
1946 		if (nick[i] < 32 || nick[i] > 'z') {
1947 			nick[i] = '\0';
1948 			rval = 0;
1949 		}
1950 	}
1951 	for (i = 0; real[i]; i++) {
1952 		if (real[i] < 32 || real[i] > 'z') {
1953 			real[i] = '\0';
1954 			rval = 0;
1955 		}
1956 	}
1957 	for (i = 0; host[i]; i++) {
1958 		if (host[i] < 32 || host[i] > 'z') {
1959 			host[i] = '\0';
1960 			rval = 0;
1961 		}
1962 	}
1963 	return(rval);
1964 }
1965 #else
validstring(char * nick)1966 static bool validstring(char *nick) {
1967 	int i, rval = 1;
1968 
1969 	for (i = 0; nick[i]; i++) {
1970 		if (nick[i] < 32 || nick[i] > 'z') {
1971 			nick[i] = '\0';
1972 			rval = 0;
1973 		}
1974 	}
1975 
1976 	return(rval);
1977 }
1978 #endif
1979 
1980 /*
1981  * Replace all weird chars with underscores
1982  * Alternate to validstrings() - mikaelh
1983  */
validatestring(char * string)1984 void validatestring(char *string) {
1985 	int i;
1986 
1987 	for (i = 0; string[i]; i++) {
1988 		if (string[i] < 32 || string[i] > 'z') {
1989 			string[i] = '_';
1990 		}
1991 	}
1992 }
1993 
1994 /*
1995  * Handle a connection that is in the listening state.
1996  */
Handle_listening(int ind)1997 static int Handle_listening(int ind)
1998 {
1999 	connection_t *connp = Conn[ind];
2000 	unsigned char type;
2001 	int  n, oldlen;
2002 	char nick[MAX_CHARS], real[MAX_CHARS], pass[MAX_CHARS];
2003 	version_type *version = &connp->version;
2004 
2005 	if (connp->state != CONN_LISTENING)
2006 	{
2007 		Destroy_connection(ind, "not listening");
2008 		return -1;
2009 	}
2010 	errno = 0;
2011 
2012 	/* Some data has arrived on the socket.  Read this data into r.buf.
2013 	 */
2014 	oldlen = connp->r.len;
2015 	n = Sockbuf_read(&connp->r);
2016 	if (n - oldlen <= 0)
2017 	{
2018 		if (n == 0)
2019 		{
2020 			/* Hack -- set sock to -1 so destroy connection doesn't
2021 			 * try to inform the client about its destruction
2022 			 */
2023 			remove_input(connp->w.sock);
2024 			connp->w.sock = -1;
2025 			Destroy_connection(ind, "TCP connection closed");
2026 		}
2027 		/* It's already Dead, Jim.
2028 		else
2029 			Destroy_connection(ind, "read first packet error");
2030 		*/
2031 		return -1;
2032 	}
2033 	connp->his_port = DgramLastport(connp->r.sock);
2034 
2035 	/* Do a sanity check and read in the some basic player information. */
2036 	/* XXX reason messages here are not transmitted to the client!	- Jir - */
2037 	if (connp->r.ptr[0] != PKT_VERIFY)
2038 	{
2039 		Send_reply(ind, PKT_VERIFY, PKT_FAILURE);
2040 		Send_reliable(ind);
2041 		Destroy_connection(ind, "not connecting");
2042 		return -1;
2043 	}
2044 
2045 	if ((n = Packet_scanf(&connp->r, "%c%s%s%s", &type, real, nick, pass)) <= 0)
2046 	{
2047 		Send_reply(ind, PKT_VERIFY, PKT_FAILURE);
2048 		Send_reliable(ind);
2049 		Destroy_connection(ind, "verify broken");
2050 		return -1;
2051 	}
2052 
2053 	/*
2054 	 * It's quite doubtful if it's 2654 bytes, since MAX_R_IDX and MAX_K_IDX
2055 	 * etc are much bigger than before;  however, let's follow the saying
2056 	 * 'Never touch what works' ;)		- Jir -
2057 	 */
2058 
2059 	/* Log the players connection */
2060 	s_printf("%s: Welcome %s=%s@%s (%s/%d) (NP=%d,ind=%d)", showtime(), connp->nick,
2061 		connp->real, connp->host, connp->addr, connp->his_port, NumPlayers, ind);
2062 #if 0
2063 	if (connp->version != MY_VERSION)
2064 		s_printf(" (version %04x)", connp->version);
2065 #else
2066 	/* Extended version support */
2067 	s_printf(" (version %d.%d.%d.%d branch %d build %d, os %d)", version->major, version->minor, version->patch, version->extra, version->branch, version->build, version->os);
2068 #endif
2069 	s_printf("\n");
2070 
2071 	if (strcmp(real, connp->real))
2072 	{
2073 		s_printf("Client verified incorrectly (%s, %s)(%s, %s)\n",
2074 			real, nick, connp->real, connp->nick);
2075 		Send_reply(ind, PKT_VERIFY, PKT_FAILURE);
2076 		Send_reliable(ind);
2077 		Destroy_connection(ind, "verify incorrect");
2078 		return -1;
2079 	}
2080 
2081 	/* Set his character info */
2082 	connp->pass = strdup(pass);
2083 
2084 	Sockbuf_clear(&connp->w);
2085 	if (Send_reply(ind, PKT_VERIFY, PKT_SUCCESS) == -1
2086 		|| Packet_printf(&connp->c, "%c%u", PKT_MAGIC, connp->magic) <= 0
2087 		|| Send_reliable(ind) <= 0)
2088 	{
2089 		Destroy_connection(ind, "confirm failed");
2090 		return -1;
2091 	}
2092 
2093 	Conn_set_state(connp, CONN_SETUP, CONN_SETUP);
2094 
2095 	return -1;
2096 }
2097 
2098 /*
2099  * Sync the named options from the array of options.
2100  *
2101  * This is a crappy way of doing things....
2102  */
2103 /* see client_opts */
sync_options(int Ind,bool * options)2104 static void sync_options(int Ind, bool *options) {
2105 	player_type *p_ptr = Players[Ind];
2106 
2107 	bool tmp;
2108 	int i;
2109 
2110 	/* Do the dirty work */
2111     if (is_older_than(&p_ptr->version, 4, 5, 8, 2, 0, 0)) {
2112 	p_ptr->rogue_like_commands = options[0];
2113 
2114 	if (is_older_than(&p_ptr->version, 4, 4, 8, 7, 0, 0)) /* which effectively means < 4.4.9 */
2115 		p_ptr->warn_unique_credit = FALSE;
2116 	else
2117 		p_ptr->warn_unique_credit = options[1];
2118 
2119 	if (is_older_than(&p_ptr->version, 4, 4, 8, 2, 0, 0))
2120 		p_ptr->newbie_hints = TRUE;
2121 	else {
2122 		tmp = p_ptr->newbie_hints;
2123 		p_ptr->newbie_hints = options[3];
2124 
2125 		/* disable some or all newbie hints */
2126 		if (!p_ptr->newbie_hints) disable_specific_warnings(p_ptr);
2127 		else if (!tmp) msg_print(Ind, "\374\377yEnabling newbie hints requires you to exit and log in again.");
2128 	}
2129 
2130 	p_ptr->use_old_target = options[4];
2131 	p_ptr->always_pickup = options[5];
2132 	p_ptr->stack_force_notes = options[8];
2133 	p_ptr->stack_force_costs = options[9];
2134 	if (!is_newer_than(&p_ptr->version, 4, 5, 2, 0, 0, 0))
2135 		p_ptr->font_map_solid_walls = FALSE;
2136 	else {
2137 		tmp = p_ptr->font_map_solid_walls;
2138 		if ((p_ptr->font_map_solid_walls = options[13]) != tmp) p_ptr->redraw |= PR_MAP;
2139 	}
2140 	p_ptr->find_ignore_stairs = options[16];
2141 	p_ptr->find_ignore_doors = options[17];
2142 	p_ptr->find_cut = options[18];
2143 	p_ptr->find_examine = options[19];
2144 	p_ptr->disturb_move = options[20];
2145 	p_ptr->disturb_near = options[21];
2146 	p_ptr->disturb_panel = options[22];
2147 	p_ptr->disturb_state = options[23];
2148 	p_ptr->disturb_minor = options[24];
2149 	p_ptr->disturb_other = options[25];
2150 	p_ptr->alert_hitpoints = options[26];
2151 	p_ptr->alert_afk_dam = options[27];
2152 	p_ptr->auto_afk = options[28];
2153 	p_ptr->newb_suicide = options[29];
2154 	p_ptr->stack_allow_items = options[30];
2155 	p_ptr->stack_allow_wands = options[31];
2156 
2157 	tmp = p_ptr->view_perma_grids;
2158 	if ((p_ptr->view_perma_grids = options[34]) != tmp) p_ptr->redraw |= PR_MAP;
2159 	tmp = p_ptr->view_torch_grids;
2160 	if ((p_ptr->view_torch_grids = options[35]) != tmp) p_ptr->redraw |= PR_MAP;
2161 	tmp = p_ptr->view_reduce_lite;
2162 	if ((p_ptr->view_reduce_lite = options[44]) != tmp) p_ptr->redraw |= PR_MAP;
2163 	tmp = p_ptr->view_reduce_view;
2164 	if ((p_ptr->view_reduce_view = options[45]) != tmp) p_ptr->redraw |= PR_MAP;
2165 
2166 	p_ptr->safe_float = options[46];
2167 
2168 	if (is_older_than(&p_ptr->version, 4, 4, 8, 4, 0, 0))
2169 		p_ptr->censor_swearing = TRUE;
2170 	else
2171 		p_ptr->censor_swearing = options[53];
2172 
2173 	if (!is_newer_than(&p_ptr->version, 4, 5, 2, 0, 0, 0))
2174 		p_ptr->view_animated_lite = FALSE;
2175 	else {
2176 		tmp = p_ptr->view_animated_lite;
2177 		if ((p_ptr->view_animated_lite = options[52]) != tmp) p_ptr->redraw |= PR_MAP;
2178 	}
2179 	if (is_older_than(&p_ptr->version, 4, 5, 2, 0, 0, 0))
2180 		p_ptr->view_shade_walls = options[57];
2181 	else {
2182 		tmp = p_ptr->view_shade_walls;
2183 		if ((p_ptr->view_shade_walls = options[55]) != tmp) p_ptr->redraw |= PR_MAP;
2184 	}
2185 	tmp = p_ptr->view_lamp_floor;
2186 	if ((p_ptr->view_lamp_floor = options[56]) != tmp) p_ptr->redraw |= PR_MAP;
2187 	tmp = p_ptr->view_shade_floor;
2188 	if ((p_ptr->view_shade_floor = options[57]) != tmp) p_ptr->redraw |= PR_MAP;
2189 	tmp = p_ptr->wall_lighting;
2190 	if ((p_ptr->wall_lighting = options[58]) != tmp) p_ptr->redraw |= PR_MAP;
2191 	tmp = p_ptr->floor_lighting;
2192 	if ((p_ptr->floor_lighting = options[59]) != tmp) p_ptr->redraw |= PR_MAP;
2193 
2194 	p_ptr->easy_open = options[60];
2195 	p_ptr->easy_disarm = options[61];
2196 	p_ptr->easy_tunnel = options[62];
2197 //	p_ptr->auto_destroy = options[63];
2198 	p_ptr->clear_inscr = options[63];
2199 	p_ptr->auto_inscribe = options[64];
2200 	if (!is_newer_than(&p_ptr->version, 4, 5, 7, 2, 0, 0)) {
2201 		p_ptr->taciturn_messages = options[65];
2202 		p_ptr->last_words = options[66];
2203 	} else {
2204 		bool vlf = p_ptr->view_lite_extra;
2205 		p_ptr->last_words = TRUE;
2206 		p_ptr->taciturn_messages = options[66];
2207 		p_ptr->view_lite_extra = options[65];
2208 		if (vlf != p_ptr->view_lite_extra) p_ptr->redraw |= PR_MAP;
2209 	}
2210 
2211 	p_ptr->limit_chat = options[67];
2212 
2213 	tmp = p_ptr->depth_in_feet;
2214 	if ((p_ptr->depth_in_feet = options[7]) != tmp)
2215 		p_ptr->redraw |= PR_DEPTH;
2216 
2217 	p_ptr->auto_target = options[69];
2218 	p_ptr->autooff_retaliator = options[70];
2219 	p_ptr->wide_scroll_margin = options[71];
2220 	p_ptr->always_repeat = options[6];
2221 	p_ptr->fail_no_melee = options[72];
2222 
2223 	/* in case we toggled linear_stats: */
2224 	p_ptr->redraw |= (PR_STATS);
2225 
2226 	tmp = p_ptr->short_item_names;
2227 	if ((p_ptr->short_item_names = options[77]) != tmp) {
2228 		/* update inventory */
2229 		for (i = 0; i < INVEN_WIELD; i++)
2230 			WIPE(&p_ptr->inventory_copy[i], object_type);
2231 		p_ptr->window |= PW_INVEN;
2232 	}
2233 
2234 	// bool speak_unique;
2235 
2236 	p_ptr->uniques_alive = options[32];
2237 	p_ptr->overview_startup = options[33];
2238 	p_ptr->page_on_privmsg = options[40];
2239 	p_ptr->page_on_afk_privmsg = options[41];
2240 	p_ptr->auto_untag = options[42];
2241 	/* hack: if client doesn't know player_list options yet then assume full list (old) */
2242 	if (is_older_than(&p_ptr->version, 4, 4, 7, 1, 0, 0)) {
2243 		p_ptr->player_list = FALSE;
2244 		p_ptr->player_list2 = FALSE;
2245 	} else {
2246 		p_ptr->player_list = options[50];
2247 		p_ptr->player_list2 = options[51];
2248 	}
2249 	p_ptr->half_sfx_attack = options[86];
2250 	p_ptr->cut_sfx_attack = options[87];
2251 
2252 	if (is_older_than(&p_ptr->version, 4, 5, 5, 0, 0, 1)) {
2253 		p_ptr->sfx_combat = TRUE;
2254 		p_ptr->sfx_magicattack = TRUE;
2255 		p_ptr->sfx_defense = TRUE;
2256 		p_ptr->sfx_monsterattack = TRUE;
2257 		p_ptr->sfx_shriek = TRUE;
2258 		p_ptr->sfx_store = FALSE;
2259 		p_ptr->sfx_house_quiet = TRUE;
2260 		p_ptr->sfx_house = TRUE;
2261 		p_ptr->no_weather = FALSE;
2262 		p_ptr->hilite_player = FALSE;
2263 		p_ptr->alert_mana = FALSE;
2264 
2265 		p_ptr->alert_offpanel_dam = FALSE;
2266 		p_ptr->idle_starve_kick = TRUE;
2267 		p_ptr->view_lamp_walls = p_ptr->view_lamp_floor;//was the same option so far, now split up
2268 	} else {
2269 		bool sfx_house_quiet = p_ptr->sfx_house_quiet, sfx_house = p_ptr->sfx_house;
2270 		p_ptr->sfx_combat = !options[47];
2271 		p_ptr->sfx_magicattack = !options[48];
2272 		p_ptr->sfx_defense = !options[49];
2273 		p_ptr->sfx_monsterattack = !options[93];
2274 		p_ptr->sfx_shriek = !options[94];
2275 		p_ptr->sfx_store = !options[96];
2276 		p_ptr->sfx_house_quiet = options[97];
2277 		p_ptr->sfx_house = !options[98];
2278 		if (p_ptr->sfx_house != sfx_house || p_ptr->sfx_house_quiet != sfx_house_quiet) {
2279 			if (p_ptr->grid_house) {
2280 				if (!p_ptr->sfx_house) Send_sfx_volume(Ind, 0, 0);
2281 				else if (p_ptr->sfx_house_quiet) Send_sfx_volume(Ind, p_ptr->sound_ambient == SFX_AMBIENT_FIREPLACE ? 100 : GRID_SFX_REDUCTION, GRID_SFX_REDUCTION);
2282 				else Send_sfx_volume(Ind, 100, 100);
2283 			}
2284 		}
2285 #ifdef CLIENT_SIDE_WEATHER
2286 		if (options[99] && !p_ptr->no_weather) {
2287 			/* update his client-side weather */
2288 			player_weather(Ind, TRUE, TRUE, TRUE);
2289 			p_ptr->no_weather = TRUE;
2290 		} else p_ptr->no_weather = options[99];
2291 #endif
2292 		p_ptr->hilite_player = options[100];
2293 		if (p_ptr->pclass == CLASS_WARRIOR || p_ptr->pclass == CLASS_ARCHER) p_ptr->alert_mana = FALSE;
2294 		else p_ptr->alert_mana = options[101];
2295 		p_ptr->exp_bar = options[103];//just for tracking this feature's popularity =P
2296 		p_ptr->consistent_players = options[104];
2297 		p_ptr->flash_self = options[105] ? 0 : -1;
2298 
2299 		if (is_older_than(&p_ptr->version, 4, 5, 8, 2, 0, 0)) {
2300 			p_ptr->alert_offpanel_dam = FALSE;
2301 			p_ptr->idle_starve_kick = TRUE;
2302 			p_ptr->view_lamp_walls = p_ptr->view_lamp_floor;//was the same option so far, now split up
2303 		} else {
2304 			p_ptr->alert_offpanel_dam = options[106];
2305 			p_ptr->idle_starve_kick = options[107];
2306 			tmp = p_ptr->view_lamp_walls;
2307 			if ((p_ptr->view_lamp_walls = options[3]) != tmp) p_ptr->redraw |= PR_MAP;
2308 		}
2309 	}
2310     } else { /* 4.5.8.2+ (after 4.5.8a release) */
2311 	bool vlf = p_ptr->view_lite_extra;
2312 	bool sfx_house_quiet = p_ptr->sfx_house_quiet, sfx_house = p_ptr->sfx_house;
2313 
2314 	/* unmutable options :D */
2315 	p_ptr->last_words = TRUE;
2316 
2317 	//page 1
2318 
2319 	p_ptr->rogue_like_commands = options[0];
2320 	tmp = p_ptr->newbie_hints;
2321 	p_ptr->newbie_hints = options[1];
2322 	/* disable some or all newbie hints */
2323 	if (!p_ptr->newbie_hints) disable_specific_warnings(p_ptr);
2324 	else if (!tmp) msg_print(Ind, "\374\377yEnabling newbie hints requires you to exit and log in again.");
2325 	p_ptr->censor_swearing = options[2];
2326 
2327 	p_ptr->page_on_privmsg = options[5];
2328 	p_ptr->page_on_afk_privmsg = options[6];
2329 
2330 	tmp = p_ptr->font_map_solid_walls;
2331 	if ((p_ptr->font_map_solid_walls = options[8]) != tmp) p_ptr->redraw |= PR_MAP;
2332 	tmp = p_ptr->view_animated_lite;
2333 	if ((p_ptr->view_animated_lite = options[9]) != tmp) p_ptr->redraw |= PR_MAP;
2334 
2335 	tmp = p_ptr->wall_lighting;
2336 	if ((p_ptr->wall_lighting = options[10]) != tmp) p_ptr->redraw |= PR_MAP;
2337 	tmp = p_ptr->view_lamp_walls;
2338 	if ((p_ptr->view_lamp_walls = options[11]) != tmp) p_ptr->redraw |= PR_MAP;
2339 	tmp = p_ptr->view_shade_walls;
2340 	if ((p_ptr->view_shade_walls = options[12]) != tmp) p_ptr->redraw |= PR_MAP;
2341 
2342 	tmp = p_ptr->floor_lighting;
2343 	if ((p_ptr->floor_lighting = options[13]) != tmp) p_ptr->redraw |= PR_MAP;
2344 	tmp = p_ptr->view_lamp_floor;
2345 	if ((p_ptr->view_lamp_floor = options[14]) != tmp) p_ptr->redraw |= PR_MAP;
2346 	tmp = p_ptr->view_shade_floor;
2347 	if ((p_ptr->view_shade_floor = options[15]) != tmp) p_ptr->redraw |= PR_MAP;
2348 	p_ptr->view_lite_extra = options[16];
2349 	if (vlf != p_ptr->view_lite_extra) p_ptr->redraw |= PR_MAP;
2350 
2351 	p_ptr->alert_hitpoints = options[17];
2352 	if (p_ptr->pclass == CLASS_WARRIOR || p_ptr->pclass == CLASS_ARCHER) p_ptr->alert_mana = FALSE;
2353 	else p_ptr->alert_mana = options[18];
2354 	p_ptr->alert_afk_dam = options[19];
2355 	p_ptr->alert_offpanel_dam = options[20];
2356 	p_ptr->exp_bar = options[21];//just for tracking this feature's popularity =P
2357 
2358 	//page 2
2359 
2360 	p_ptr->uniques_alive = options[22];
2361 	p_ptr->warn_unique_credit = options[23];
2362 	p_ptr->limit_chat = options[24];
2363 	p_ptr->no_afk_msg = options[25];
2364 	p_ptr->overview_startup = options[26];
2365 
2366 	/* in case we toggled linear_stats: */
2367 	p_ptr->redraw |= (PR_STATS);
2368 	//..other client-side only stuff..
2369 
2370 	tmp = p_ptr->depth_in_feet;
2371 	if ((p_ptr->depth_in_feet = options[31]) != tmp) p_ptr->redraw |= PR_DEPTH;
2372 	p_ptr->newb_suicide = options[32];
2373 
2374 	tmp = p_ptr->short_item_names;
2375 	if ((p_ptr->short_item_names = options[36]) != tmp) {
2376 		/* update inventory */
2377 		for (i = 0; i < INVEN_WIELD; i++)
2378 			WIPE(&p_ptr->inventory_copy[i], object_type);
2379 		p_ptr->window |= PW_INVEN;
2380 	}
2381 
2382 	p_ptr->taciturn_messages = options[39];
2383 
2384 #ifdef CLIENT_SIDE_WEATHER
2385 	if (options[41] && !p_ptr->no_weather) {
2386 		/* update his client-side weather */
2387 		player_weather(Ind, TRUE, TRUE, TRUE);
2388 		p_ptr->no_weather = TRUE;
2389 	} else p_ptr->no_weather = options[41];
2390 #endif
2391 	p_ptr->player_list = options[42];
2392 	p_ptr->player_list2 = options[43];
2393 
2394 	//page 3
2395 
2396 	p_ptr->flash_self = options[44] ? 0 : -1;
2397 	p_ptr->hilite_player = options[45];
2398 	p_ptr->consistent_players = options[46];
2399 
2400 	//page 4
2401 
2402 	p_ptr->auto_afk = options[50];
2403 	p_ptr->idle_starve_kick = options[51];
2404 	p_ptr->safe_float = options[52];
2405 
2406 //	p_ptr->auto_destroy = options[];
2407 	p_ptr->auto_untag = options[54];
2408 	p_ptr->clear_inscr = options[55];
2409 	p_ptr->auto_inscribe = options[56];
2410 	p_ptr->stack_force_notes = options[57];
2411 	p_ptr->stack_force_costs = options[58];
2412 	p_ptr->stack_allow_items = options[59];
2413 	p_ptr->stack_allow_wands = options[60];
2414 
2415 	p_ptr->always_repeat = options[62];
2416 	p_ptr->always_pickup = options[63];
2417 	p_ptr->use_old_target = options[64];
2418 	p_ptr->autooff_retaliator = options[65];
2419 	p_ptr->fail_no_melee = options[66];
2420 	p_ptr->wide_scroll_margin = options[67];
2421 	p_ptr->auto_target = options[68];
2422 
2423 	//page 5
2424 
2425 	p_ptr->find_ignore_stairs = options[71];
2426 	p_ptr->find_ignore_doors = options[72];
2427 	p_ptr->find_cut = options[73];
2428 	p_ptr->find_examine = options[74];
2429 	p_ptr->disturb_move = options[75];
2430 	p_ptr->disturb_near = options[76];
2431 	p_ptr->disturb_panel = options[77];
2432 	p_ptr->disturb_state = options[78];
2433 	p_ptr->disturb_minor = options[79];
2434 	p_ptr->disturb_other = options[80];
2435 	tmp = p_ptr->view_perma_grids;
2436 	if ((p_ptr->view_perma_grids = options[81]) != tmp) p_ptr->redraw |= PR_MAP;
2437 	tmp = p_ptr->view_torch_grids;
2438 	if ((p_ptr->view_torch_grids = options[82]) != tmp) p_ptr->redraw |= PR_MAP;
2439 	tmp = p_ptr->view_reduce_lite;
2440 	if ((p_ptr->view_reduce_lite = options[83]) != tmp) p_ptr->redraw |= PR_MAP;
2441 	tmp = p_ptr->view_reduce_view;
2442 	if ((p_ptr->view_reduce_view = options[84]) != tmp) p_ptr->redraw |= PR_MAP;
2443 	p_ptr->easy_open = options[85];
2444 	p_ptr->easy_disarm = options[86];
2445 	p_ptr->easy_tunnel = options[87];
2446 
2447 	//page 6
2448 
2449 	// bool speak_unique;
2450 	p_ptr->sfx_combat = !options[93];
2451 	p_ptr->sfx_magicattack = !options[94];
2452 	p_ptr->sfx_defense = !options[95];
2453 	p_ptr->half_sfx_attack = options[96];
2454 	p_ptr->cut_sfx_attack = options[97];
2455 	p_ptr->sfx_monsterattack = !options[103];
2456 	p_ptr->sfx_shriek = !options[104];
2457 	p_ptr->sfx_store = !options[105];
2458 	p_ptr->sfx_house_quiet = options[106];
2459 	p_ptr->sfx_house = !options[107];
2460 
2461 	if (p_ptr->sfx_house != sfx_house ||
2462 	    p_ptr->sfx_house_quiet != sfx_house_quiet) {
2463 		if (p_ptr->grid_house) {
2464 			if (!p_ptr->sfx_house) Send_sfx_volume(Ind, 0, 0);
2465 			else if (p_ptr->sfx_house_quiet) Send_sfx_volume(Ind, p_ptr->sound_ambient == SFX_AMBIENT_FIREPLACE ? 100 : GRID_SFX_REDUCTION, GRID_SFX_REDUCTION);
2466 			else Send_sfx_volume(Ind, 100, 100);
2467 		}
2468 	}
2469     }
2470 }
2471 
2472 /*
2473  * A client has requested to start active play.
2474  * See if we can allocate a player structure for it
2475  * and if this succeeds update the player information
2476  * to all connected players.
2477  */
Handle_login(int ind)2478 static int Handle_login(int ind)
2479 {
2480 	connection_t *connp = Conn[ind];
2481 	player_type *p_ptr = NULL;
2482 	object_type forge, *o_ptr = &forge;
2483 	int i, j;
2484 	bool options[OPT_MAX], greeting;
2485 	char namebuf1[80], namebuf2[80], o_name[ONAME_LEN];
2486 	cptr title = "";
2487 	char traffic[50+1];
2488 	bool newly_created_msg = FALSE;
2489 
2490 	if (Id >= MAX_ID) {
2491 		errno = 0;
2492 		plog(format("Id too big (%d)", Id));
2493 		return -1;
2494 	}
2495 
2496 	/* This will cause problems for account/char with same name */
2497 #if 0
2498 	for (i = 1; i < NumPlayers + 1; i++) {
2499 		if (strcasecmp(Players[i]->name, connp->nick) == 0) {
2500 			errno = 0;
2501 			plog(format("Name already in use %s", connp->nick));
2502 			return -1;
2503 		}
2504 	}
2505 #endif
2506 
2507 	if (!player_birth(NumPlayers + 1, ind, connp)) {
2508 		/* Failed, connection destroyed */
2509 		Destroy_connection(ind, "not login");
2510 		return -1;
2511 	}
2512 	p_ptr = Players[NumPlayers + 1];
2513 	p_ptr->Ind = NumPlayers + 1;
2514 	strcpy(p_ptr->realname, connp->real);
2515 	strncpy(p_ptr->hostname, connp->host, 25); /* cap ridiculously long hostnames - C. Blue */
2516 	strcpy(p_ptr->accountname, connp->nick);
2517 	strcpy(p_ptr->addr, connp->addr);
2518 	p_ptr->version = connp->version; /* this actually copies the extended version structure */
2519 	p_ptr->v_unknown = is_newer_than(&p_ptr->version, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_EXTRA, VERSION_BRANCH, !VERSION_BUILD ? 1 : VERSION_BUILD); /* +1: account for 'test' client! */
2520 	p_ptr->v_test_latest = is_same_as(&p_ptr->version, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_EXTRA, VERSION_BRANCH, !VERSION_BUILD ? 1 : VERSION_BUILD);
2521 	p_ptr->v_test = !p_ptr->v_unknown && is_newer_than(&p_ptr->version, VERSION_MAJOR_LATEST, VERSION_MINOR_LATEST, VERSION_PATCH_LATEST, VERSION_EXTRA_LATEST, VERSION_BRANCH_LATEST, VERSION_BUILD_LATEST);
2522 	p_ptr->v_outdated = !is_newer_than(&p_ptr->version, VERSION_MAJOR_OUTDATED, VERSION_MINOR_OUTDATED, VERSION_PATCH_OUTDATED, VERSION_EXTRA_OUTDATED, VERSION_BRANCH_OUTDATED, VERSION_BUILD_OUTDATED);
2523 	p_ptr->v_latest = is_same_as(&p_ptr->version, VERSION_MAJOR_LATEST, VERSION_MINOR_LATEST, VERSION_PATCH_LATEST, VERSION_EXTRA_LATEST, VERSION_BRANCH_LATEST, VERSION_BUILD_LATEST);
2524 	p_ptr->audio_sfx = connp->audio_sfx;
2525 	p_ptr->audio_mus = connp->audio_mus;
2526 
2527 	/* Copy the client preferences to the player struct */
2528 	for (i = 0; i < OPT_MAX; i++)
2529 		options[i] = connp->Client_setup.options[i];
2530 
2531 	for (i = 0; i < TV_MAX; i++) {
2532 		int j;
2533 
2534 		if (!connp->Client_setup.u_attr[i] &&
2535 		    !connp->Client_setup.u_char[i])
2536 			continue;
2537 
2538 		/* XXX not max_k_idx, since client doesn't know the value */
2539 		for (j = 0; j < MAX_K_IDX; j++) {
2540 			if (k_info[j].tval == i) {
2541 				p_ptr->d_attr[j] = connp->Client_setup.u_attr[i];
2542 				p_ptr->d_char[j] = connp->Client_setup.u_char[i];
2543 			}
2544 		}
2545 	}
2546 
2547 	for (i = 0; i < MAX_F_IDX; i++) {
2548 /* Hacking the no-floor bug for loth/bree tower/gondo city -C. Blue */
2549 		p_ptr->f_attr[i] = connp->Client_setup.f_attr[i];
2550 		p_ptr->f_char[i] = connp->Client_setup.f_char[i];
2551 #ifndef FLOORTILEBUG_WORKAROUND
2552 		if (!p_ptr->f_attr[i]) p_ptr->f_attr[i] = f_info[i].z_attr;
2553 		if (!p_ptr->f_char[i]
2554 		    || p_ptr->f_char[i] == 31) /* workaround for people who are still using old font-win.prf files with floor tile /31 mapping glitch */
2555 			p_ptr->f_char[i] = f_info[i].z_char;
2556 #else		/*now all tiles are bright white and never dimmed.*/
2557 		p_ptr->f_attr[i] = f_info[i].z_attr;
2558 		p_ptr->f_char[i] = f_info[i].z_char;
2559 #endif
2560 		/* local, hacked copy: for font_map_solid_walls */
2561 		p_ptr->f_char_solid[i] = f_info[i].z_char;
2562 		p_ptr->f_attr_solid[i] = f_info[i].z_attr;
2563 
2564 	}
2565 	/* modify solid walls of local copy for font_map_solid_walls */
2566 	if (p_ptr->version.os == OS_WIN32) {
2567 		p_ptr->f_char_solid[50] = 127; //magma, 8
2568 		p_ptr->f_char_solid[52] = 127;
2569 		p_ptr->f_char_solid[51] = 127; //quartz, 9
2570 		p_ptr->f_attr_solid[51] = 9;
2571 		p_ptr->f_char_solid[53] = 127;
2572 		p_ptr->f_attr_solid[53] = 9;
2573 
2574 		p_ptr->f_char_solid[54] = 1; //specialty: magma with treasure (diamond ascii)
2575 		p_ptr->f_char_solid[55] = 1; //specialty: quartz with treasure (diamond ascii)
2576 
2577 		p_ptr->f_char_solid[56] = 127; //granite, 2
2578 		p_ptr->f_char_solid[57] = 127;
2579 		p_ptr->f_char_solid[58] = 127;
2580 		p_ptr->f_char_solid[59] = 127; //perma vaults, 1
2581 		p_ptr->f_char_solid[60] = 127;
2582 		p_ptr->f_char_solid[61] = 127;
2583 		p_ptr->f_char_solid[62] = 127;
2584 		p_ptr->f_char_solid[63] = 127;
2585 		p_ptr->f_char_solid[26] = 127; //perma houses, 1
2586 		p_ptr->f_char_solid[28] = 127;
2587 		p_ptr->f_char_solid[75] = 127;
2588 		p_ptr->f_char_solid[76] = 127;
2589 		p_ptr->f_char_solid[77] = 127;
2590 		p_ptr->f_char_solid[78] = 127;
2591 		p_ptr->f_char_solid[95] = 127; //ice wall
2592 		p_ptr->f_char_solid[98] = 127; //sand wall
2593 		p_ptr->f_char_solid[99] = 127;
2594 
2595 		p_ptr->f_char_solid[100] = 1; //specialty: sand wall with treasure (diamond ascii)
2596 
2597 		p_ptr->f_char_solid[177] = 127;
2598 		p_ptr->f_char_solid[188] = 127;
2599 		p_ptr->f_char_solid[189] = 127;
2600 		p_ptr->f_char_solid[190] = 127; //house roofs, 11
2601 		p_ptr->f_char_solid[191] = 127;
2602 		p_ptr->f_char_solid[193] = 127; //house roofs, 4
2603 		p_ptr->f_char_solid[194] = 127;
2604 	} else {
2605 		/* assume OS_X11 -- does this work on OSX/GCU too? */
2606 		p_ptr->f_char_solid[50] = 2; //magma, 8
2607 		p_ptr->f_char_solid[52] = 2;
2608 		p_ptr->f_char_solid[51] = 2; //quartz, 9
2609 		p_ptr->f_attr_solid[51] = 9;
2610 		p_ptr->f_char_solid[53] = 2;
2611 		p_ptr->f_attr_solid[53] = 9;
2612 
2613 		p_ptr->f_char_solid[54] = 1; //specialty: magma with treasure (diamond ascii)
2614 		p_ptr->f_char_solid[55] = 1; //specialty: quartz with treasure (diamond ascii)
2615 
2616 		p_ptr->f_char_solid[56] = 2; //granite, 2
2617 		p_ptr->f_char_solid[57] = 2;
2618 		p_ptr->f_char_solid[58] = 2;
2619 		p_ptr->f_char_solid[59] = 2; //perma vaults, 1
2620 		p_ptr->f_char_solid[60] = 2;
2621 		p_ptr->f_char_solid[61] = 2;
2622 		p_ptr->f_char_solid[62] = 2;
2623 		p_ptr->f_char_solid[63] = 2;
2624 		p_ptr->f_char_solid[26] = 2; //perma houses, 1
2625 		p_ptr->f_char_solid[28] = 2;
2626 		p_ptr->f_char_solid[75] = 2;
2627 		p_ptr->f_char_solid[76] = 2;
2628 		p_ptr->f_char_solid[77] = 2;
2629 		p_ptr->f_char_solid[78] = 2;
2630 		p_ptr->f_char_solid[95] = 2; //ice walls
2631 		p_ptr->f_char_solid[98] = 2; //sand wall
2632 		p_ptr->f_char_solid[99] = 2;
2633 
2634 		p_ptr->f_char_solid[100] = 1; //specialty: sand wall with treasure (diamond ascii)
2635 
2636 		p_ptr->f_char_solid[177] = 2;
2637 		p_ptr->f_char_solid[188] = 2;
2638 		p_ptr->f_char_solid[189] = 2;
2639 		p_ptr->f_char_solid[190] = 2; //house roofs, 11
2640 		p_ptr->f_char_solid[191] = 2;
2641 		p_ptr->f_char_solid[193] = 2; //house roofs, 4
2642 		p_ptr->f_char_solid[194] = 2;
2643 	}
2644 
2645 	for (i = 0; i < MAX_K_IDX; i++) {
2646 		p_ptr->k_attr[i] = connp->Client_setup.k_attr[i];
2647 		p_ptr->k_char[i] = connp->Client_setup.k_char[i];
2648 
2649 		if (!p_ptr->k_attr[i]) p_ptr->k_attr[i] = k_info[i].x_attr;
2650 		if (!p_ptr->k_char[i]) p_ptr->k_char[i] = k_info[i].x_char;
2651 
2652 #if 1
2653 		if (!p_ptr->d_attr[i]) p_ptr->d_attr[i] = k_info[i].d_attr;
2654 		if (!p_ptr->d_char[i]) p_ptr->d_char[i] = k_info[i].d_char;
2655 #else
2656 		if (!p_ptr->k_attr[i]) p_ptr->d_attr[i] = k_info[i].d_attr;
2657 		if (!p_ptr->k_char[i]) p_ptr->d_char[i] = k_info[i].d_char;
2658 #endif	// 0
2659 	}
2660 
2661 	/* Hack -- acquire a flag for ego-monsters	- Jir - */
2662 	p_ptr->use_r_gfx = FALSE;
2663 
2664 	for (i = 0; i < MAX_R_IDX; i++) {
2665 		p_ptr->r_attr[i] = connp->Client_setup.r_attr[i];
2666 		p_ptr->r_char[i] = connp->Client_setup.r_char[i];
2667 
2668 		if (!p_ptr->r_attr[i]) p_ptr->r_attr[i] = r_info[i].x_attr;
2669 		else p_ptr->use_r_gfx = TRUE;
2670 
2671 		if (!p_ptr->r_char[i]) p_ptr->r_char[i] = r_info[i].x_char;
2672 		else p_ptr->use_r_gfx = TRUE;
2673 	}
2674 
2675 	sync_options(NumPlayers + 1, options);
2676 
2677 	GetInd[Id] = NumPlayers + 1;
2678 
2679 	NumPlayers++;
2680 	if (!is_admin(p_ptr)) NumNonAdminPlayers++;
2681 	if (NumNonAdminPlayers > MaxSimultaneousPlayers) {
2682 		MaxSimultaneousPlayers = NumPlayers;
2683 		if (MaxSimultaneousPlayers > 15) s_printf("SimultaneousPlayers (above 15): %d\n", MaxSimultaneousPlayers);
2684 	}
2685 	connp->id = Id++;
2686 
2687 	//Conn_set_state(connp, CONN_READY, CONN_PLAYING);
2688 	Conn_set_state(connp, CONN_PLAYING, CONN_PLAYING);
2689 
2690 	if (Send_reply(ind, PKT_PLAY, PKT_SUCCESS) <= 0) {
2691 		plog("Cannot send play reply");
2692 		return -1;
2693 	}
2694 
2695 	/* Send party/guild information */
2696 	Send_party(NumPlayers, FALSE, FALSE);
2697 	/* Guild timed out meanwhile? (Leaderless for too long) */
2698 	if (p_ptr->guild &&
2699 	    (!guilds[p_ptr->guild].members || guilds[p_ptr->guild].dna != p_ptr->guild_dna)) {
2700 		p_ptr->guild = 0;
2701 		clockin(NumPlayers, 3);
2702 	}
2703 	Send_guild(NumPlayers, FALSE, FALSE);
2704 	Send_guild_config(p_ptr->guild);
2705 
2706 	/* Hack -- terminate the data stream sent to the client */
2707 	if (Packet_printf(&connp->c, "%c", PKT_END) <= 0) {
2708 		Destroy_connection(p_ptr->conn, "write error");
2709 		return -1;
2710 	}
2711 
2712 	if (Send_reliable(ind) == -1) {
2713 		Destroy_connection(ind, "Couldn't send reliable data");
2714 		return -1;
2715 	}
2716 
2717 	num_logins++;
2718 
2719 	save_server_info();
2720 
2721 	/* Execute custom script if player joins the server */
2722 	if (first_player_joined) {
2723 		first_player_joined = FALSE;
2724 		exec_lua(NumPlayers, format("first_player_has_joined(%d, %d, \"%/s\", \"%s\")", NumPlayers, p_ptr->id, p_ptr->name, showtime()));
2725 	}
2726 	if (NumPlayers == 1) exec_lua(NumPlayers, format("player_has_joined_empty_server(%d, %d, \"%/s\", \"%s\")", NumPlayers, p_ptr->id, p_ptr->name, showtime()));
2727 	exec_lua(NumPlayers, format("player_has_joined(%d, %d, \"%/s\", \"%s\")", NumPlayers, p_ptr->id, p_ptr->name, showtime()));
2728 	strcpy(traffic, "");
2729 	for (i = 1; (i <= NumPlayers) && (i < 50); i++)
2730 		if (!(i % 5)) strcat(traffic, "* "); else strcat(traffic, "*");
2731 	p_printf("%s +  %03d  %s\n", showtime(), NumPlayers, traffic);
2732 
2733 	/* Initialize his mimic spells. - C. Blue
2734 	   Note: This is actually done earlier in time via calc_body_bonus(),
2735 	   but at that point, the connection is not yet ready to receive spell info. */
2736 	calc_body_spells(NumPlayers);
2737 
2738 	/* check pending notes to this player -C. Blue */
2739 	for (i = 0; i < MAX_ADMINNOTES; i++) {
2740 		if (strcmp(admin_note[i], "")) {
2741 			msg_format(NumPlayers, "\377sMotD: %s", admin_note[i]);
2742 		}
2743 	}
2744 	for (i = 0; i < MAX_NOTES; i++) {
2745 		strcpy(namebuf1, priv_note_target[i]);
2746 		strcpy(namebuf2, connp->nick);
2747 		j = 0; while(namebuf1[j]) { namebuf1[j] = tolower(namebuf1[j]); j++; }
2748 		j = 0; while(namebuf2[j]) { namebuf2[j] = tolower(namebuf2[j]); j++; }
2749 //		if (!strcmp(priv_note_target[i], p_ptr->name)) { /* <- sent to a character name */
2750 //		if (!strcmp(priv_note_target[i], connp->nick)) { /* <- sent to an account name */
2751 		if (!strcmp(namebuf1, namebuf2)) { /* <- sent to an account name, case-independant */
2752 			msg_format(NumPlayers, "\374\377RNote from %s: %s", priv_note_sender[i], priv_note[i]);
2753 			strcpy(priv_note_sender[i], "");
2754 			strcpy(priv_note_target[i], "");
2755 			strcpy(priv_note[i], "");
2756 		}
2757 	}
2758 	if (p_ptr->party) for (i = 0; i < MAX_PARTYNOTES; i++) {
2759 		if (!strcmp(party_note_target[i], parties[p_ptr->party].name)) {
2760 			if (strcmp(party_note[i], ""))
2761 				msg_format(NumPlayers, "\374\377bParty Note: %s", party_note[i]);
2762 			break;
2763 		}
2764 	}
2765 	if (p_ptr->guild) for (i = 0; i < MAX_GUILDNOTES; i++) {
2766 		if (!strcmp(guild_note_target[i], guilds[p_ptr->guild].name)) {
2767 			if (strcmp(guild_note[i], ""))
2768 				msg_format(NumPlayers, "\374\377bGuild Note: %s", guild_note[i]);
2769 			break;
2770 		}
2771 	}
2772 	if (server_warning[0]) msg_format(NumPlayers, "\374\377R*** Note: %s ***", server_warning);
2773 
2774 	/* Warn the player if some of his/her characters are about to expire */
2775 	account_checkexpiry(NumPlayers);
2776 
2777 #ifndef ARCADE_SERVER
2778 	/* Brand-new players get super-short instructions presented here: */
2779 	greeting = !(acc_get_flags(p_ptr->accountname) & ACC_GREETED);
2780 	if (p_ptr->inval || greeting) {
2781 		s_printf("GREETING: %s\n", p_ptr->name);
2782 
2783 		/* no bloody noob ever seems to read this how2run thingy.. (p_ptr->warning_welcome) */
2784 		msg_print(NumPlayers, "\374\377y ");
2785 		msg_print(NumPlayers, "\374\377y   ***  Welcome to Tomenet! You can chat with \377R:\377y key. Say hello :)  ***");
2786 		msg_print(NumPlayers, "\374\377y      To run fast, use \377oSHIFT+direction\377y keys (\377oNUMLOCK\377y must be OFF)");
2787 		if (p_ptr->warning_wield == 0)
2788 			msg_print(NumPlayers, "\374\377y      Before you move out, press \377ow\377y to equip your weapon and armour!");
2789 		else
2790 			msg_print(NumPlayers, "\374\377y      Before you move out, press \377ow\377y to equip your starting items!");
2791 		msg_print(NumPlayers, "\374\377y ");
2792 //		msg_print(NumPlayers, "\377RTurn off \377oNUMLOCK\377R and hit \377oSHIFT+numkeys\377R to run (move quickly).");
2793 //		msg_print(NumPlayers, "\377RHit '\377o?\377R' key for help. Hit '\377o:\377R' to chat. Hit '\377o@\377R' to see who is online.");
2794 //		msg_print(NumPlayers, "\377R<< Welcome to TomeNET! >>");
2795 
2796 		/* Play audio greeting too! - C. Blue */
2797 		if (greeting) { /* only the very 1st time, might become annoying */
2798 			s_printf("GREETING_AUDIO: %s\n", p_ptr->name);
2799 			sound(NumPlayers, "greeting", NULL, SFX_TYPE_MISC, FALSE);
2800 
2801 			acc_set_flags(p_ptr->accountname, ACC_GREETED, TRUE);
2802 		}
2803 	}
2804 	/* Notify all online admins about an invalid player having joined, so they may validate him */
2805 	if (p_ptr->inval) for (i = 1; i < NumPlayers + 1; i++) {
2806 		if (Players[i]->conn == NOT_CONNECTED) continue;
2807 		if (!is_admin(Players[i])) continue;
2808 		msg_format(i, "\374\377R(Admin) Invalid account \"%s\", host: \"%s\"", p_ptr->accountname, p_ptr->hostname);
2809 		if (!Players[i]->paging) Players[i]->paging = 2;
2810 	}
2811 
2812 	/* warning_rest only occurs once per account */
2813 	if (acc_get_flags(p_ptr->accountname) & ACC_WARN_REST) p_ptr->warning_rest = 3;
2814 #else
2815 	/* no greeting */
2816 	greeting = FALSE;
2817 
2818 	/* auto-validate */
2819 	if (acc_get_flags(p_ptr->accountname) & ACC_TRIAL)
2820 		validate(p_ptr->accountname);
2821 #endif
2822 
2823 #if 1
2824 	/* Give a more visible message about outdated client usage - C. Blue */
2825 	if (!is_newer_than(&p_ptr->version, VERSION_MAJOR_OUTDATED, VERSION_MINOR_OUTDATED, VERSION_PATCH_OUTDATED, VERSION_EXTRA_OUTDATED, VERSION_BRANCH_OUTDATED, VERSION_BUILD_OUTDATED)) {
2826 		msg_print(NumPlayers, "\374\377y --- Your client is outdated! Get newest one from www.tomenet.eu ---");
2827 	} else if (is_older_than(&p_ptr->version, VERSION_MAJOR_LATEST, VERSION_MINOR_LATEST, VERSION_PATCH_LATEST, VERSION_EXTRA_LATEST, VERSION_BRANCH_LATEST, VERSION_BUILD_LATEST)) {
2828 		msg_print(NumPlayers, "\374\377D --- Your client is NOT the latest version, it's not 'outdated' though. ---");
2829 	}
2830 #endif
2831 #if 0
2832 	if (p_ptr->audio_mus == 49) /* problem: cannot take into account if the player purposefully removed some songs */
2833 		msg_print(NumPlayers, "\374\377D --- Your music pack is outdated. ---");
2834 	else if (p_ptr->audio_mus == 55 || p_ptr->audio_mus == 56) /* problem: cannot take into account if the player purposefully removed some songs */
2835 		msg_print(NumPlayers, "\374\377D --- Your music pack is outdated. ---");
2836 #else
2837 	/* In 4.5.7 we can now distinguish (client-side) between disabled and unavailable audio */
2838 	if (p_ptr->audio_sfx > 3 && p_ptr->audio_sfx < __audio_sfx_max) msg_print(NumPlayers, "\374\377D --- Warning: Your sound pack is outdated! ---");
2839 	if (p_ptr->audio_mus && p_ptr->audio_mus < __audio_mus_max) msg_print(NumPlayers, "\374\377D --- Warning: Your music pack is outdated! ---");
2840 #endif
2841 
2842 	/* Admin messages */
2843 	if (p_ptr->admin_dm)
2844 		switch (cfg.runlevel) {
2845 		case 2051:
2846 			msg_print(NumPlayers, "\377y* XtremelyLow-server-shutdown command pending *");
2847 			break;
2848 		case 2048:
2849 			msg_print(NumPlayers, "\377y* Empty-server-shutdown command pending *");
2850 			break;
2851 		case 2047:
2852 			msg_print(NumPlayers, "\377y* Low-server-shutdown command pending *");
2853 			break;
2854 		case 2046:
2855 			msg_print(NumPlayers, "\377y* VeryLow-server-shutdown command pending *");
2856 			break;
2857 		case 2045:
2858 			msg_print(NumPlayers, "\377y* None-server-shutdown command pending *");
2859 			break;
2860 		case 2044:
2861 			msg_print(NumPlayers, "\377y* ActiveVeryLow-server-shutdown command pending *");
2862 			break;
2863 		case 2043:
2864 			msg_print(NumPlayers, "\377y* Recall-server-shutdown command pending *");
2865 			break;
2866 		case 2042:
2867 			msg_print(NumPlayers, "\377y* Recall-server-termination command pending *");
2868 			break;
2869 		}
2870 
2871 	if (cfg.runlevel == 2043 || cfg.runlevel == 2042) {
2872 		if (shutdown_recall_timer >= 120)
2873 			msg_format(NumPlayers, "\374\377I*** \377RServer shutdown in %d minutes (auto-recall). \377I***", shutdown_recall_timer / 60);
2874 		else
2875 			msg_format(NumPlayers, "\374\377I*** \377RServer shutdown in %d seconds (auto-recall). \377I***", shutdown_recall_timer);
2876 	}
2877 
2878 	if (p_ptr->xorder_id) {
2879 		for (i = 0; i < MAX_XORDERS; i++) {
2880 			if (xorders[i].id == p_ptr->xorder_id) {
2881 				msg_format(NumPlayers, "\377oYour order to exterminate \377y%d \377g%s\377o (level %d) is still valid.",
2882 				    p_ptr->xorder_num, r_name + r_info[xorders[i].type].name, r_info[xorders[i].type].level);
2883 				break;
2884 			}
2885 		}
2886 	}
2887 
2888 	if(!(p_ptr->mode & MODE_NO_GHOST) &&
2889 	    !(p_ptr->mode & MODE_EVERLASTING) &&
2890 	    !(p_ptr->mode & MODE_PVP) &&
2891 	    !cfg.no_ghost && cfg.lifes)
2892 	{
2893 #if 0
2894 		/* if total_winner char was loaded from old save game that
2895 		   didn't reduce his/her lifes to 1 on winning, do that now: */
2896 		if (p_ptr->total_winner && (p_ptr->lives > 1+1)) {
2897 			msg_print(NumPlayers, "\377yTake care! As a winner, you have no more resurrections left!");
2898 			p_ptr->lives = 1+1;
2899 		}
2900 #endif
2901 		if (p_ptr->lives-1 == 1)
2902     			msg_print(NumPlayers, "\377GYou have no more resurrections left!");
2903 	        else
2904 			msg_format(NumPlayers, "\377GYou have %d resurrections left.", p_ptr->lives-1-1);
2905 	}
2906 
2907 	/* for PvP mode chars */
2908 	if (p_ptr->free_mimic) msg_format(NumPlayers, "\377GYou have %d free mimicry transformation left.", p_ptr->free_mimic);
2909 
2910 	/* receive previously buffered global-event-contender-deed from other character of her/his account */
2911 	for (i = 0; i < MAX_CONTENDER_BUFFERS; i++) {
2912 		if (ge_contender_buffer_ID[i] == p_ptr->account) {
2913 			ge_contender_buffer_ID[i] = 0;
2914 			i = lookup_kind(TV_PARCHMENT, ge_contender_buffer_deed[i]);
2915 			invcopy(o_ptr, i);
2916 			o_ptr->number = 1;
2917 			object_aware(NumPlayers, o_ptr);
2918 			object_known(o_ptr);
2919 			o_ptr->discount = 0;
2920 			o_ptr->level = 0;
2921 			o_ptr->ident |= ID_MENTAL;
2922 			inven_carry(NumPlayers, o_ptr);
2923 			msg_print(NumPlayers, "\377GAs a former contender in an event, you have received a deed!");
2924 		}
2925 	}
2926 	/* receive previously buffered achievement deed (pvp) from other character of her/his account */
2927 	for (i = 0; i < MAX_ACHIEVEMENT_BUFFERS; i++) {
2928 		if (achievement_buffer_ID[i] == p_ptr->account) {
2929 			switch (achievement_buffer_deed[i]) {
2930 			case SV_DEED_PVP_MAX: /* this one is transferrable to non-pvp char */
2931 				break;
2932 			case SV_DEED_PVP_MID:
2933 			case SV_DEED_PVP_MASS:
2934 				if (!(p_ptr->mode & MODE_PVP)) continue;
2935 				break;
2936 			}
2937 			achievement_buffer_ID[i] = 0;
2938 			i = lookup_kind(TV_PARCHMENT, achievement_buffer_deed[i]);
2939 			invcopy(o_ptr, i);
2940 			o_ptr->number = 1;
2941 			object_aware(NumPlayers, o_ptr);
2942 			object_known(o_ptr);
2943 			o_ptr->discount = 0;
2944 			o_ptr->level = 0;
2945 			o_ptr->ident |= ID_MENTAL;
2946 			inven_carry(NumPlayers, o_ptr);
2947 			msg_print(NumPlayers, "\377GFor your achievements, you have received a deed!");
2948 		}
2949 	}
2950 
2951 	/* Sold something in his player store while he wasn't logged on? */
2952 	if (acc_get_flags(p_ptr->accountname) & ACC_WARN_SALE) {
2953 		acc_set_flags(p_ptr->accountname, ACC_WARN_SALE, FALSE);
2954 		msg_print(NumPlayers, "\374\377yA store of yours has sold something meanwhile!");
2955 	}
2956 
2957 #if 1 /* hm, too much spam? - but usually you'd get this notification anyway, if logged in a bit earlier.. */
2958 #define GE_FINAL_ANNOUNCEMENT 300 /* keep consistent with xtra1.c */
2959 	for (i = 0; i < MAX_GLOBAL_EVENTS; i++)
2960 		if ((global_event[i].getype != GE_NONE) && (global_event[i].hidden == FALSE || is_admin(p_ptr))) {
2961 			int time_left = global_event[i].announcement_time - ((turn - global_event[i].start_turn) / cfg.fps);
2962 			/* Event is not in announcement phase anymore? */
2963 			if (time_left <= 0) continue;
2964 			/* Final announcement has not yet been made? */
2965 			if (global_event[i].announcement_time * cfg.fps -
2966 			    (turn - global_event[i].start_turn - global_event[i].paused_turns) //<- 'elapsed_time'
2967 			    >= GE_FINAL_ANNOUNCEMENT * cfg.fps)
2968 				continue;
2969  #if 0
2970 			msg_format(Ind, "  \377U%d\377W) '%s' recruits for %d more minutes.",
2971 			    i + 1, global_event[i].title, (global_event[i].announcement_time - ((turn - global_event[i].start_turn) / cfg.fps)) / 60);
2972  #else
2973 			if (time_left >= 120) msg_format(NumPlayers, "\374\377W[%s (\377U%d\377W) starts in %d minutes]", global_event[i].title, i + 1, time_left / 60);
2974 			else msg_format(NumPlayers, "\374\377W[%s (%d) starts in %d seconds!]", global_event[i].title, i + 1, time_left);
2975  #endif
2976 		}
2977 #endif
2978 
2979 	/* display some warnings if an item will severely conflict with Martial Arts skill */
2980 	if (get_skill(p_ptr, SKILL_MARTIAL_ARTS)) {
2981 		bool warn_takeoff = FALSE;
2982 
2983 		if (!p_ptr->warning_ma_weapon &&
2984 		    (p_ptr->inventory[INVEN_WIELD].k_idx ||
2985 		    is_weapon(p_ptr->inventory[INVEN_ARM].tval) || /* for dual-wielders */
2986 #ifndef ENABLE_MA_BOOMERANG
2987 		    p_ptr->inventory[INVEN_BOW].k_idx)) {
2988 #else
2989 		    p_ptr->inventory[INVEN_BOW].tval == TV_BOW)) {
2990 #endif
2991 #ifndef ENABLE_MA_BOOMERANG
2992 			msg_print(NumPlayers, "\374\377RWarning: Using any sort of weapon renders Martial Arts skill effectless.");
2993 #else
2994 			msg_print(NumPlayers, "\374\377RWarning: Using any melee weapon or bow renders Martial Arts skill effectless.");
2995 #endif
2996 			warn_takeoff = TRUE;
2997 
2998 			/* might find esp-weapon at non-low levels, so stop spamming this warning then */
2999 			if (p_ptr->lev >= 15) p_ptr->warning_ma_weapon = 1;
3000 		}
3001 		if (!p_ptr->warning_ma_shield &&
3002 		    p_ptr->inventory[INVEN_ARM].k_idx) {
3003 			msg_print(NumPlayers, "\374\377RWarning: Using a shield will prevent Martial Arts combat styles.");
3004 			warn_takeoff = TRUE;
3005 
3006 			/* might find esp-shield at non-low levels, so stop spamming this warning then */
3007 			if (p_ptr->lev >= 15) p_ptr->warning_ma_shield = 1;
3008 		}
3009 		if (warn_takeoff) msg_print(NumPlayers, "\374\377R         Press 't' key to take off your weapons or shield.");
3010 	}
3011 
3012 	/* automatically re-add him to the guild of his last character? */
3013 	namebuf1[0] = '\0'; //abuse namebuf1
3014 	if ((i = acc_get_guild(p_ptr->accountname))) {
3015 #if 1
3016 		if (p_ptr->newly_created) {
3017 #else /* add char if it's level 1 */
3018 		if (p_ptr->lev == 1) {
3019 #endif
3020 			/* within time limit [20 minutes]? */
3021 			time_t now = time(&now);
3022 #if 0 /* add char if it's within 20 min */
3023 			if (now - lookup_player_laston(p_ptr->id) <= 60 * 20 && /* always true, since char was newly created! gotta use acc_laston or just ignore */
3024 #else
3025 			if (
3026 #endif
3027 			    guilds[i].members /* guild still exists? */
3028 			    && guilds[i].dna == acc_get_guild_dna(p_ptr->accountname)) { /* and is still the SAME guild? */
3029 				/* auto-re-add him to the guild */
3030 				if (guild_auto_add(NumPlayers, i, namebuf1)) {
3031 					/* also restore his 'adder' status if he was one */
3032 					if ((acc_get_flags(p_ptr->accountname) & ACC_GUILD_ADDER)) {
3033 #ifdef GUILD_ADDERS_LIST
3034 						/* check for vacant adder slot */
3035 						for (i = 0; i < 5; i++)
3036 							if (guilds[p_ptr->guild].adder[i][0] == '\0') break;
3037 						/* success? */
3038 						if (i != 5) {
3039 							strcpy(guilds[p_ptr->guild].adder[i], p_ptr->name);
3040 							p_ptr->guild_flags |= PGF_ADDER;
3041 						}
3042 					}
3043 #else
3044 						p_ptr->guild_flags |= PGF_ADDER;
3045 					}
3046 #endif
3047 				}
3048 			}
3049 		}
3050 		acc_set_guild(p_ptr->accountname, 0);
3051 		acc_set_flags(p_ptr->accountname, ACC_GUILD_ADDER, FALSE);
3052 	}
3053 
3054 #ifdef GUILD_ADDERS_LIST
3055 	/* Erase his PGF_ADDER flag if he's been removed from the adder list. */
3056 	if ((p_ptr->guild_flags & PGF_ADDER)) {
3057 		for (i = 0; i < 5; i++)
3058 			if (streq(guilds[p_ptr->guild].adder[i], p_ptr->name)) break;
3059 		if (i == 5) {
3060 			p_ptr->guild_flags &= ~PGF_ADDER;
3061 			msg_format(NumPlayers, "\374\377%cYour authorization to add others to the guild has been \377rretracted\377%c.", COLOUR_CHAT_GUILD, COLOUR_CHAT_GUILD);
3062 		}
3063 	}
3064 #endif
3065 
3066 	if (p_ptr->IDDC_logscum) msg_print(NumPlayers, "\377RThis floor has become stale, take a staircase to move on!");
3067 
3068 	/* some one-time hints and other stuff after char creation in player_birth() */
3069 	if (p_ptr->newly_created) {
3070 		p_ptr->newly_created = FALSE;
3071 
3072 		/* hints */
3073 		newly_created_msg = TRUE;
3074 		if (p_ptr->mode & MODE_PVP) {
3075 			msg_print(NumPlayers, "\377yType \"/pvp\" into chat to enter the pvp arena, and again to leave it.");
3076 
3077 			if (p_ptr->inval) {
3078 				msg_print(NumPlayers, "\374\377RNOTE: 'PvP mode' is a special type of gameplay. NOT recommended for beginners!");
3079 				msg_print(NumPlayers, "\374\377R      If you didn't choose PvP mode on purpose, press \377oSHIFT+q\377R to start over.");
3080 			}
3081 		}
3082 
3083 		/* pre-know certain special items without need for ID */
3084 #ifdef PLAYER_STORES
3085 		p_ptr->obj_aware[lookup_kind(TV_SCROLL, SV_SCROLL_CHEQUE)] = TRUE;
3086 #endif
3087 #ifdef NEW_WILDERNESS_MAP_SCROLLS
3088 		p_ptr->obj_aware[lookup_kind(TV_SCROLL, SV_SCROLL_WILDERNESS_MAP)] = TRUE;
3089 #endif
3090 	}
3091 
3092 #ifdef ENABLE_DRACONIAN_TRAITS
3093         if (p_ptr->prace == RACE_DRACONIAN && !p_ptr->ptrait) {
3094 		msg_print(NumPlayers, "\377oDraconians now have specific 'traits'. You do not have one yet!");
3095 		msg_print(NumPlayers, "\377o Press '\377R:\377o' key to chat and enter the command   \377R/trait\377o  to get one.");
3096         }
3097 #endif
3098 
3099 #ifdef FLUENT_ARTIFACT_RESETS
3100 	for (i = 0; i < INVEN_TOTAL; i++) {
3101 		if (!p_ptr->inventory[i].k_idx) continue;
3102 		j = p_ptr->inventory[i].name1;
3103 		if (!j || j == ART_RANDART) continue;
3104 		if (!(p_ptr->inventory[i].ident & ID_MENTAL)) continue;
3105 		if (a_info[j].timeout <= 0 || a_info[j].timeout > FLUENT_ARTIFACT_WARNING || cfg.persistent_artifacts) continue;
3106 		object_desc(NumPlayers, o_name, &p_ptr->inventory[i], TRUE, 128);
3107 		msg_format(NumPlayers, "\374\377RYour %s will vanish soon!", o_name);
3108 	}
3109 	if (p_ptr->fluent_artifact_reset == TRUE) {
3110 		msg_print(NumPlayers, "\374\377ROne or more true artifacts have bidden you farewell!");
3111 		p_ptr->fluent_artifact_reset = FALSE;
3112 	}
3113 #endif
3114 
3115 	/* Check Morgoth, if player had saved a level where he was generated */
3116 	check_Morgoth(NumPlayers);
3117 
3118 	/* Initialise his temporary quest helper information */
3119 	quest_check_player_location(NumPlayers);
3120 
3121 #if defined(DUNGEON_VISIT_BONUS) || defined(ALLOW_NR_CROSS_PARTIES) || defined(ALLOW_NR_CROSS_ITEMS)
3122 	wpcopy(&Players[NumPlayers]->wpos_old, &p_ptr->wpos);
3123 #endif
3124 
3125 #ifdef CLIENT_SIDE_WEATHER
3126 	/* update his client-side weather */
3127 	player_weather(NumPlayers, TRUE, TRUE, TRUE);
3128 #endif
3129 
3130 #ifdef AUCTION_SYSTEM
3131 	auction_player_joined(NumPlayers);
3132 #endif
3133 
3134 #ifdef USE_SOUND_2010
3135 	/* Initialize his background music */
3136 	p_ptr->music_current = -1; //hack-init: since 0 is used too..
3137 	p_ptr->musicalt_current = -1;
3138 	p_ptr->sound_ambient = -1; //hack-init: since 0 is used too..
3139 	p_ptr->music_monster = -1; //hack-init: since 0 is used too.. (boss-specific music)
3140 
3141 	/* Keep music quiet for a moment to allow player to hear the introduction speech? */
3142 	if (greeting && p_ptr->audio_mus > 0 && p_ptr->audio_sfx >= 2) /* speech is event #2 in unmodified sounds.cfg */
3143 		p_ptr->music_start = 20; /* wait for this # of turns until starting the music */
3144 	else
3145 		handle_music(NumPlayers); /* start music normally (instantly) */
3146 
3147 	/* Don't skip the first attack sfx (in case player enabled half_sfx_attack or cut_sfx_attack) */
3148 	p_ptr->count_cut_sfx_attack = 500;
3149 #endif
3150 
3151 	/* Note: p_ptr->sound_ambient must be initialised to -1 before calling this. */
3152 	grid_affects_player(NumPlayers);
3153 
3154 #ifdef USE_SOUND_2010
3155 	/* Note: This must come after grid_affects_players() has been called initially. */
3156 	handle_ambient_sfx(NumPlayers, &(getcave(&p_ptr->wpos)[p_ptr->py][p_ptr->px]), &p_ptr->wpos, FALSE);
3157 #endif
3158 
3159 	/* Initialize the client's unique list;
3160 	it will become further updated each time he kills another unique */
3161 	for (i = 0; i < MAX_R_IDX; i++)
3162 		if (r_info[i].flags1 & RF1_UNIQUE)
3163 			Send_unique_monster(NumPlayers, i);
3164 
3165 #if 0 /* not here, but below instead. Or admins will be shown in the list! */
3166  #ifdef TOMENET_WORLDS
3167 	world_player(p_ptr->id, p_ptr->name, TRUE, TRUE); /* last flag is 'quiet' mode -> no public msg */
3168  #endif
3169 #endif
3170 
3171 
3172 	/* Prepare title for possibly telling others about our new player (or admin) */
3173 	title = "";
3174 	if (p_ptr->admin_dm) title = (p_ptr->male) ? "Dungeon Master " : "Dungeon Mistress ";
3175 	else if (p_ptr->admin_wiz) title = "Dungeon Wizard ";
3176 	else if (p_ptr->total_winner) {
3177 		if (p_ptr->mode & (MODE_HARD | MODE_NO_GHOST)) {
3178 			title = (p_ptr->male)?"Emperor ":((!strcmp(p_ptr->name,"Tina"))?"Tiny ":"Empress ");
3179 		} else {
3180 			title = (p_ptr->male) ? "King " : "Queen ";
3181 		}
3182 	}
3183 
3184 	/* Handle the cfg_secret_dungeon_master option: Only tell other admins. */
3185 	if (p_ptr->admin_dm && (cfg.secret_dungeon_master)) {
3186 		/* Tell other secret dungeon masters about our new player */
3187 		for (i = 1; i < NumPlayers; i++) {
3188 			if (Players[i]->conn == NOT_CONNECTED) continue;
3189 			if (!is_admin(Players[i])) continue;
3190 
3191 			if (newly_created_msg) {
3192 				if (p_ptr->fruit_bat)
3193 					msg_format(i, "\374\377%c%s%s flaps %s wings into the world.", COLOUR_SERVER, title, p_ptr->name, (p_ptr->male?"his":"her"));
3194 				else
3195 					msg_format(i, "\374\377%c%s%s sets foot into the world.", COLOUR_SERVER, title, p_ptr->name);
3196 			} else
3197 				msg_format(i, "\374\377%c%s%s has entered the game.", COLOUR_SERVER, title, p_ptr->name);
3198 			if (namebuf1[0] && Players[i]->guild == p_ptr->guild) msg_print(i, namebuf1);
3199 		}
3200 		return 0;
3201 	}
3202 
3203 #ifdef TOMENET_WORLDS
3204 	world_player(p_ptr->id, p_ptr->name, TRUE, TRUE); /* last flag is 'quiet' mode -> no public msg */
3205 #endif
3206 
3207 	/* Tell everyone about our new player */
3208 	for (i = 1; i < NumPlayers; i++) {
3209 		if (Players[i]->conn == NOT_CONNECTED) continue;
3210 		if (newly_created_msg) {
3211 			if (p_ptr->fruit_bat)
3212 				msg_format(i, "\374\377%c%s%s flaps %s wings into the world.", COLOUR_SERVER, title, p_ptr->name, (p_ptr->male?"his":"her"));
3213 			else
3214 				msg_format(i, "\374\377%c%s%s sets foot into the world.", COLOUR_SERVER, title, p_ptr->name);
3215 		} else
3216 			msg_format(i, "\374\377%c%s%s has entered the game.", COLOUR_SERVER, title, p_ptr->name);
3217 
3218 		/* print notification message about guild-auto-add now */
3219 		if (namebuf1[0] && Players[i]->guild == p_ptr->guild) msg_print(i, namebuf1);
3220 	}
3221 
3222 #ifdef TOMENET_WORLDS
3223 	if (cfg.worldd_pjoin) {
3224 		if (newly_created_msg) {
3225 			if (p_ptr->fruit_bat)
3226 				world_msg(format("\374\377%c%s%s flaps %s wings into the world.", COLOUR_SERVER, title, p_ptr->name, (p_ptr->male?"his":"her")));
3227 			else
3228 				world_msg(format("\374\377%c%s%s sets foot into the world.", COLOUR_SERVER, title, p_ptr->name));
3229 		} else
3230 			world_msg(format("\374\377%c%s%s has entered the game.", COLOUR_SERVER, title, p_ptr->name));
3231 	}
3232 #endif
3233 
3234 	/* Tell the meta server about the new player */
3235 	Report_to_meta(META_UPDATE);
3236 
3237 	return 0;
3238 }
3239 
3240 /* wrapper function for local 'Conn' - C. Blue */
3241 int is_inactive(int Ind) {
3242 	if (Conn[Players[Ind]->conn]->inactive_keepalive)
3243 		return (Conn[Players[Ind]->conn]->inactive_keepalive);
3244 	else
3245 		return (Conn[Players[Ind]->conn]->inactive_ping / 2);
3246 }
3247 
3248 /* Actually execute commands from the client command queue */
3249 void process_pending_commands(int ind)
3250 {
3251 	connection_t *connp = Conn[ind];
3252 	player_type *p_ptr = NULL;
3253 	int player = -1, type, result, (**receive_tbl)(int ind) = playing_receive, old_energy = 0;
3254 	int num_players_start = NumPlayers; // Hack to see if we have quit in this function
3255 
3256 	// Hack -- take any pending commands from the command que connp->q
3257 	// and move them to connp->r, where the Receive functions get their
3258 	// data from.
3259 	Sockbuf_clear(&connp->r);
3260 	if (connp->q.len > 0)
3261 	{
3262 		if (Sockbuf_write(&connp->r, connp->q.ptr, connp->q.len) != connp->q.len)
3263 		{
3264 			errno = 0;
3265 			Destroy_connection(ind, "Can't copy queued data to buffer");
3266 			return;
3267 		}
3268 		//connp->q.ptr += connp->q.len;
3269 		//Sockbuf_advance(&connp->q, connp->q.ptr - connp->q.buf);
3270 		Sockbuf_clear(&connp->q);
3271 	}
3272 
3273 	// If we have no commands to execute return
3274 	if (connp->r.len <= 0)
3275 		return;
3276 
3277 	// Get the player pointer
3278 	if (connp->id != -1)
3279 	{
3280 		player = GetInd[connp->id];
3281 		p_ptr = Players[player];
3282 	}
3283 	// Hack -- if our player id has not been set then assume that Receive_play
3284 	// should be called.
3285 	else
3286 	{
3287 		Receive_play(ind);
3288 		return;
3289 	}
3290 
3291 	// Attempt to execute every pending command. Any command that fails due
3292 	// to lack of energy will be put into the queue for next turn by the
3293 	// respective receive function.
3294 
3295 	//while ( (p_ptr->energy >= level_speed(p_ptr->dun_depth)) &&
3296 	//while ( (connp->state == CONN_PLAYING ? p_ptr->energy >= level_speed(p_ptr->dun_depth) : 1) &&
3297 	//while ( (connp->state == CONN_PLAYING ? p_ptr->energy >= level_speed(p_ptr->dun_depth) : 1) &&
3298 	while ((connp->r.ptr < connp->r.buf + connp->r.len))
3299 	{
3300 		char *foo = connp->r.ptr;
3301 		type = (connp->r.ptr[0] & 0xFF);
3302 		if (type != PKT_KEEPALIVE && type != PKT_PING)
3303 		{
3304 			connp->inactive_keepalive = 0;
3305 			connp->inactive_ping = 0;
3306 			if (connp->id != -1) p_ptr->idle = 0;
3307 		}
3308 		result = (*receive_tbl[type])(ind);
3309 
3310 		/* Check that the player wasn't disconnected - mikaelh */
3311 		if (!Conn[ind]) {
3312 			return;
3313 		}
3314 
3315 		/* See 'p_ptr->requires_energy' below in 'result == 0' clause. */
3316 		if (p_ptr != NULL && p_ptr->conn != NOT_CONNECTED)
3317 			p_ptr->requires_energy = (result == 0);
3318 
3319 		/* Check whether the socket buffer has advanced */
3320 		if (connp->r.ptr == foo) {
3321 			/* Return code 0 means that there wasn't enough data in the socket buffer */
3322 			if (result == 0) {
3323 				/* Move the remaining data to the queue buffer - mikaelh */
3324 				int len = connp->r.len - (connp->r.ptr - connp->r.buf);
3325 				if (Sockbuf_write(&connp->q, connp->r.ptr, len) != len)
3326 				{
3327 					errno = 0;
3328 					Destroy_connection(ind, "Can't copy data to queue");
3329 					return;
3330 				}
3331 			}
3332 
3333 			/* Clear the buffer to avoid getting stuck in a loop */
3334 			Sockbuf_clear(&connp->r);
3335 			break;
3336 		}
3337 		if (connp->state == CONN_PLAYING)
3338 		{
3339 			connp->start = turn;
3340 		}
3341 		if (result == -1) {
3342 			return;
3343 		}
3344 
3345 		// We didn't have enough energy to execute an important command.
3346 		if (result == 0) {
3347 			/* New: Since fire-till-kill is now allowed to begin at <= 1
3348 			   energy (see dungeon.c, process_player_end()), we need this
3349 			   to avoid getting 'locked up' in shooting_till_kill. - C. Blue */
3350 			//done above already	p_ptr->requires_energy = TRUE;
3351 
3352 			/* Hack -- if we tried to do something while resting, wake us up.
3353 			 */
3354 			if (p_ptr->resting) disturb(player, 0, 0);
3355 
3356 			/* If we didn't have enough energy to execute this
3357 			 * command, in order to ensure that our important
3358 			 * commands execute in the proper order, stop
3359 			 * processing any commands that require energy. We
3360 			 * assume that any commands that don't require energy
3361 			 * (such as quitting, or talking) should be executed
3362 			 * ASAP.
3363 			 */
3364 			/* Mega-Hack -- save our old energy and set our energy
3365 			 * to 0.  This will allow us to execute "out of game"
3366 			 * actions such as talking while we wait for enough
3367 			 * energy to execute our next queued in game action.
3368 			 */
3369 			if (p_ptr->energy) {
3370 				old_energy = p_ptr->energy;
3371 				p_ptr->energy = 0;
3372 			}
3373 		}
3374 
3375 		/* Queue all remaining packets now */
3376 		if (result == 3)
3377 		{
3378 			int len = connp->r.len - (connp->r.ptr - connp->r.buf);
3379 			if (Sockbuf_write(&connp->q, connp->r.ptr, len) != len)
3380 			{
3381 				errno = 0;
3382 				Destroy_connection(ind, "Can't copy data to queue");
3383 				return;
3384 			}
3385 			Sockbuf_clear(&connp->r);
3386 
3387 			break;
3388 		}
3389 	}
3390 	/* Restore our energy if neccecary. */
3391 
3392 	/* Make sure that the player structure hasn't been deallocated in this
3393 	 * time due to a quit request.  Hack -- to do this we check if the number
3394 	 * of players has changed while this loop has been executing.  This would be
3395 	 * a BAD thing to do if we ever went multithreaded.
3396 	 */
3397 	if (NumPlayers == num_players_start)
3398 		if (!p_ptr->energy) p_ptr->energy = old_energy;
3399 }
3400 
3401 /*
3402  * Process a client packet.
3403  * The client may be in one of several states,
3404  * therefore we use function dispatch tables for easy processing.
3405  * Some functions may process requests from clients being
3406  * in different states.
3407  * The behavior of this function has been changed somewhat.  New commands are now
3408  * put into a command queue, where they will be executed later.
3409  */
3410 void Handle_input(int fd, int arg)
3411 {
3412 	int ind = arg, player = -1, old_numplayers = NumPlayers;
3413 	connection_t *connp = Conn[ind];
3414 	player_type *p_ptr = NULL;
3415 	//int type, result, (**receive_tbl)(int ind);
3416 	//int (**receive_tbl)(int ind);
3417 
3418 	/* Check that the pointer is valid - mikaelh */
3419 	if (!connp) return;
3420 
3421 	if (connp->state & (CONN_PLAYING | CONN_READY))
3422 		;//receive_tbl = &playing_receive[0];
3423 	else if (connp->state & (CONN_LOGIN/* | CONN_SETUP */))
3424 #if 0
3425 		receive_tbl = &login_receive[0];
3426 #else
3427 	{
3428 		//receive_tbl = &login_receive[0];
3429 		Receive_play(ind);
3430 		return;
3431 	}
3432 #endif
3433 	else if (connp->state & (CONN_DRAIN/* | CONN_SETUP */))
3434 		;//receive_tbl = &drain_receive[0];
3435 	else if (connp->state == CONN_LISTENING) {
3436 		Handle_listening(ind);
3437 		return;
3438 	} else if (connp->state == CONN_SETUP) {
3439 		Handle_setup(ind);
3440 		return;
3441 	} else {
3442 		if (connp->state != CONN_FREE)
3443 			Destroy_connection(ind, "not input");
3444 		return;
3445 	}
3446 
3447 #if 0
3448 	/* Clear connp->r, which will be our new queue */
3449 	Sockbuf_clear(&connp->r);
3450 
3451 	/* Put any old commands at the beginning of the new queue we are reading into */
3452 	if (connp->q.len > 0) {
3453 		if (connp->r.ptr > connp->r.buf)
3454 			Sockbuf_advance(&connp->r, connp->r.ptr - connp->r.buf);
3455 		if (Sockbuf_write(&connp->r, connp->q.ptr, connp->q.len) != connp->q.len) {
3456 			errno = 0;
3457 			Destroy_connection(ind, "Can't copy queued data to buffer");
3458 			return;
3459 		}
3460 
3461 		connp->q.ptr += connp->q.len;
3462 		Sockbuf_advance(&connp->q, connp->q.ptr - connp->q.buf);
3463 	}
3464 	Sockbuf_clear(&connp->q);
3465 #endif
3466 
3467 	if (connp->id != -1) {
3468 		player = GetInd[connp->id];
3469 		p_ptr = Players[player];
3470 	}
3471 
3472 	/* Mega-Hack */
3473 	if (p_ptr && p_ptr->new_level_flag) return;
3474 
3475 	// Reset the buffer we are reading into
3476 	Sockbuf_clear(&connp->r);
3477 
3478 	// Read in the data
3479 	if (Sockbuf_read(&connp->r) <= 0) {
3480 		// Check to make sure that an EAGAIN error didn't occur.  Sometimes on
3481 		// Linux when receiving a lot of traffic EAGAIN will occur on recv and
3482 		// Sockbuf_read will return 0.
3483 		if (errno != EAGAIN) {
3484 			// If this happens, the the client has probably closed his TCP connection.
3485 			do_quit(ind, 0);
3486 		}
3487 
3488 		//Destroy_connection(ind, "input error");
3489 		return;
3490 	}
3491 
3492 	// Add this new data to the command queue
3493 	if (Sockbuf_write(&connp->q, connp->r.ptr, connp->r.len) != connp->r.len) {
3494 		errno = 0;
3495 		Destroy_connection(ind, "Can't copy queued data to buffer");
3496 		return;
3497 	}
3498 
3499 	// Execute any new commands immediately if possible
3500 	// Don't process commands when marked for death - mikaelh
3501 	if (!p_ptr || !p_ptr->death) process_pending_commands(ind);
3502 
3503 	/* Check that the player wasn't disconnected - mikaelh */
3504 	if (!Conn[ind]) return;
3505 
3506 	/* Experimental hack -- to reduce perceived latency, flush our network
3507 	 * info right now so the player sees the results of his actions as soon
3508 	 * as possobile.  Everyone else will see him move at most one game turn
3509 	 * later, which is usually < 100 ms.
3510 	 */
3511 
3512 	/* Hack -- don't update the player info if the number of players since
3513 	 * the beginning of this function call has changed, which might indicate
3514 	 * that our player has left the game.
3515 	 */
3516 	if ((old_numplayers == NumPlayers) && (connp->state == CONN_PLAYING)) {
3517 		// Update the players display if neccecary and possobile
3518 		if (p_ptr) {
3519 			/* Notice stuff */
3520 			if (p_ptr->notice) notice_stuff(player);
3521 
3522 			/* Update stuff */
3523 			if (p_ptr->update) update_stuff(player);
3524 
3525 			/* Redraw stuff */
3526 			if (p_ptr->redraw) redraw_stuff(player);
3527 
3528 			/* Window stuff */
3529 			if (p_ptr->window) window_stuff(player);
3530 		}
3531 	}
3532 
3533 	if (connp->c.len > 0) {
3534 		if (Packet_printf(&connp->c, "%c", PKT_END) <= 0) {
3535 			Destroy_connection(ind, "write error");
3536 			return;
3537 		}
3538 		Send_reliable(ind);
3539 	}
3540 
3541 //	Sockbuf_clear(&connp->r);
3542 }
3543 
3544 // This function is used for sending data to clients who do not yet have
3545 // Player structures allocated, and for timing out players who have been
3546 // idle for a while.
3547 int Net_input(void)
3548 {
3549 	int i, ind, num_reliable = 0, input_reliable[MAX_SELECT_FD];
3550 	connection_t *connp;
3551 	char msg[MSG_LEN];
3552 
3553 	for (i = 0; i < max_connections; i++)
3554 	{
3555 		connp = Conn[i];
3556 
3557 		if (!connp || connp->state == CONN_FREE)
3558 			continue;
3559 		if (connp->timeout && (connp->start + connp->timeout * cfg.fps < turn))
3560 		{
3561 			if (connp->state & (CONN_PLAYING | CONN_READY))
3562 			{
3563 /*				sprintf(msg, "%s mysteriously disappeared!",
3564 					connp->nick);
3565 				Set_message(msg); */
3566 			}
3567 			sprintf(msg, "timeout %02x", connp->state);
3568 			Destroy_connection(i, msg);
3569 
3570 #if 0
3571 			/* Very VERY bad hack :/ - C. Blue */
3572 	                save_game_panic();
3573 #endif
3574 
3575 			continue;
3576 		}
3577 
3578 		// Make sure that the player we are looking at is not already in the
3579 		// game.  If he is already in the game then we will send him data
3580 		// in the function Net_input.
3581 		if (connp->id != -1) continue;
3582 
3583 /*		if (connp->r.len > 0)
3584 			Sockbuf_clear(&connp->r); */
3585 
3586 #if 0
3587 		if (connp->state != CONN_PLAYING)
3588 		{
3589 #endif
3590 			input_reliable[num_reliable++] = i;
3591 			if (connp->state == CONN_SETUP )
3592 			{
3593 				Handle_setup(i);
3594 				continue;
3595 			}
3596 #if 0
3597 		}
3598 #endif
3599 	}
3600 
3601 	/* Do GW timeout checks */
3602 	SGWTimeout();
3603 
3604 	for (i = 0; i < num_reliable; i++)
3605 	{
3606 		ind = input_reliable[i];
3607 		connp = Conn[ind];
3608 		if (connp->state & (CONN_DRAIN | CONN_READY | CONN_SETUP
3609 			| CONN_LOGIN | CONN_PLAYING))
3610 		{
3611 			if (connp->c.len > 0)
3612 				if (Send_reliable(ind) == -1)
3613 					continue;
3614 		}
3615 	}
3616 
3617 	if (num_logins | num_logouts)
3618 		num_logins = num_logouts = 0;
3619 
3620 	return login_in_progress;
3621 }
3622 
3623 int Net_output(void)
3624 {
3625 	int	i;
3626 	connection_t *connp;
3627 	player_type *p_ptr = NULL;
3628 
3629 	for (i = 1; i <= NumPlayers; i++)
3630 	{
3631 		p_ptr = Players[i];
3632 
3633 		if (p_ptr->conn == NOT_CONNECTED) continue;
3634 
3635 		if (p_ptr->new_level_flag) continue;
3636 
3637 		connp = Conn[p_ptr->conn];
3638 
3639 		/* XXX XXX XXX Mega-Hack -- Redraw player's spot every time */
3640 		/* This keeps the network connection "active" even if nothing is */
3641 		/* happening -- KLJ */
3642 		/* This has been changed to happen less often, operating at close to 3
3643 		 * times a second to keep the BGP routing tables happy.
3644 		 * I had originally changed this to about once every 2 seconds,
3645 		 * but apparently it was doing bad things, as the inactivity in the UDP
3646 		 * stream was causing us to loose priority in the routing tables.
3647 		 * Thanks to Crimson for explaining this. -APD
3648 		 */
3649 
3650 		/* to keep a good UDP connection, send data that requests a response
3651 		 * every 1/4 of a second
3652 		 */
3653 
3654 		/* Hack -- add the index to our turn, so we don't send all the players
3655 		 * reliable data simultaniously.  This should hopefully "spread out"
3656 		 * the incoming data a little so it doesn't all happen in a semi-
3657 		 * synchronized way.
3658 		 */
3659 
3660 		/*
3661 		   Can't coment this out, it updates things like food
3662 		    and stores.
3663 		   Still have to worry about routing with TCP :)
3664 		   -- Crimson
3665 		   --- But STill buggy, so off for now.
3666 		if (!((turn + i) % 8))
3667 		{
3668 			lite_spot(i, p_ptr->py, p_ptr->px);
3669 		}
3670 		*/
3671 
3672 		/* otherwise, send normal data if there is any */
3673 		//else
3674 		//{
3675 	//		  Tell the client that this is the end
3676 	//
3677 	//		If we have any data to send to the client, terminate it
3678 	//		and send it to the client.
3679 			if (connp->c.len > 0)
3680 			{
3681 				if (Packet_printf(&connp->c, "%c", PKT_END) <= 0)
3682 				{
3683 					Destroy_connection(p_ptr->conn, "write error");
3684 					continue;
3685 				}
3686 				Send_reliable(p_ptr->conn);
3687 			}
3688 			// Flush the output buffers
3689 		//	if (Sockbuf_flush(&connp->w) == -1)
3690 		//		return -1;
3691 		//}
3692 
3693 		//Sockbuf_clear(&connp->w);
3694 	}
3695 
3696 	/* Every fifteen seconds, update the info sent to the metaserver */
3697 	if (!(turn % (15 * cfg.fps)))
3698 		Report_to_meta(META_UPDATE);
3699 
3700 	return 1;
3701 }
3702 
3703 int Net_output1(int Ind)
3704 {
3705 	connection_t *connp;
3706 	player_type *p_ptr = NULL;
3707 
3708 	p_ptr = Players[Ind];
3709 	if (p_ptr->conn == NOT_CONNECTED) return 0;
3710 	if (p_ptr->new_level_flag) return 2;
3711 	connp = Conn[p_ptr->conn];
3712 
3713 	if (connp->c.len > 0)
3714 	{
3715 		if (Packet_printf(&connp->c, "%c", PKT_END) <= 0) {
3716 			Destroy_connection(p_ptr->conn, "write error");
3717 			return 3;
3718 		} else {
3719 			Send_reliable(p_ptr->conn);
3720 		}
3721 	}
3722 	return 1;
3723 }
3724 
3725 /*
3726  * Send a reply to a special client request.
3727  * Not used consistently everywhere.
3728  * It could be used to setup some form of reliable
3729  * communication from the client to the server.
3730  */
3731 int Send_reply(int ind, int replyto, int result)
3732 {
3733 	connection_t *connp = Conn[ind];
3734 	int n;
3735 
3736 	n = Packet_printf(&connp->c, "%c%c%c", PKT_REPLY, replyto, result);
3737 	if (n == -1)
3738 	{
3739 		Destroy_connection(ind, "write error");
3740 		return -1;
3741 	}
3742 
3743 	return n;
3744 }
3745 
3746 int Send_leave(int ind, int id)
3747 {
3748 	connection_t *connp = Conn[ind];
3749 
3750 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
3751 	{
3752 		errno = 0;
3753 		plog(format("Connection not ready for leave info (%d,%d)",
3754 			connp->state, connp->id));
3755 		return 0;
3756 	}
3757 	return Packet_printf(&connp->c, "%c%hd", PKT_LEAVE, id);
3758 }
3759 
3760 // Actually quit. This was seperated as a hack to allow us to
3761 // "quit" when a quit packet has not been received, such as when
3762 // our TCP connection is severed.  The tellclient argument
3763 // specifies whether or not we should try to send data to the
3764 // client informing it about the quit event.
3765 void do_quit(int ind, bool tellclient)
3766 {
3767 	int player = -1;
3768 	player_type *p_ptr = NULL;
3769 	connection_t * connp = Conn[ind];
3770 
3771 	if (connp->id != -1) {
3772 		player = GetInd[connp->id];
3773 		p_ptr = Players[player];
3774 	}
3775 	if (!tellclient) {
3776 		/* Close the socket */
3777 		close(connp->w.sock);
3778 
3779 		/* No more packets from a player who is quitting */
3780 		remove_input(connp->w.sock);
3781 
3782 		/* Disable all output and input to and from this player */
3783 		connp->w.sock = -1;
3784 	}
3785 
3786 	/* If we are close to the center of town, exit quickly. */
3787 	if (connp->id == -1 ||
3788 	    isdungeontown(&p_ptr->wpos) ||
3789 	    (istownarea(&p_ptr->wpos, MAX_TOWNAREA) && !(sector00separation && in_sector00(&p_ptr->wpos)))) {
3790 		Destroy_connection(ind, "client quit");
3791 	}
3792 	// Otherwise wait for the timeout
3793 	else exec_lua(NumPlayers, format("player_leaves_timeout(%d, %d, \"%/s\", \"%s\")", NumPlayers, p_ptr->id, p_ptr->name, showtime()));
3794 }
3795 
3796 
3797 static int Receive_quit(int ind) {
3798 	int n;
3799 	connection_t *connp = Conn[ind];
3800 	char ch;
3801 
3802 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) != 1) {
3803 		errno = 0;
3804 		Destroy_connection(ind, "receive error in quit");
3805 		return -1;
3806 	}
3807 
3808 	do_quit(ind, 0);
3809 
3810 	return 1;
3811 }
3812 
3813 static int Receive_login(int ind) {
3814 	connection_t *connp = Conn[ind], *connp2 = NULL;
3815 	//unsigned char ch;
3816 	int i, n, res;
3817 	char choice[MAX_CHARS], loc[MAX_CHARS];
3818 	struct account *l_acc;
3819 	struct worldpos wpos;
3820 
3821 	n = Sockbuf_read(&connp->r);
3822 	if (n == 0 && !(errno == EAGAIN || errno == EWOULDBLOCK)) {
3823 		/* avoid SIGPIPE in zero read - it was closed */
3824 		close(connp->w.sock);
3825 		remove_input(connp->w.sock);
3826 		connp->w.sock = -1;
3827 		Destroy_connection(ind, "disconnect in login");
3828 		return(-1);
3829 	}
3830 
3831 	if ((n = Packet_scanf(&connp->r, "%s", choice)) != 1) {
3832 		errno = 0;
3833 		printf("%d\n", n);
3834 		plog("Failed reading login packet");
3835 		Destroy_connection(ind, "receive error in login");
3836 		return -1;
3837 	}
3838 
3839 	if (strlen(choice) == 0) { /* we have entered an account name */
3840 		u32b p_id;
3841 		bool censor_swearing_tmp = censor_swearing;
3842 		char tmp_name[ACCOUNTNAME_LEN], tmp_name2[ACCOUNTNAME_LEN];
3843 		char tmp_name_wide[MAX_CHARS_WIDE];
3844 		struct account *acc;
3845 
3846 		/* security check: a bugged client might try to send the character name, but allows an 'empty' name!
3847 		   Here, the server would think that 'choice' being empty is signaling a different login stage.
3848 		   However, if the client was really trying to send an (empty) character name, at least connp->pass
3849 		   would be 0x0 at this point, causing the server to segfault! - C. Blue */
3850 		if (!connp->pass ||//<-important check
3851 		    !connp->nick || !connp->real || !connp->host || !connp->addr) {//<-just paranoia checks
3852 			Destroy_connection(ind, "Unexpected login error. Please contact an administrator.");
3853 			return(-1);
3854 		}
3855 
3856 		/* remove disallowed chars and spaces at the end */
3857 		Trim_name(connp->nick);
3858 
3859 		/* Check if player tries to create an account of the same name as
3860 		   an already existing character - give an error message.
3861 		   (Mostly for new feat 'privmsg to account name' - C. Blue) */
3862 		if ((p_id = lookup_player_id(connp->nick))) { /* character name identical to this account name already exists? */
3863 			/* That character doesn't belong to our account? Forbid creating an account of this name then. */
3864 			if (lookup_accountname(p_id) && //<- avoid panic save if tomenet.acc file has been deleted for some reason. NOTE: Missing tomenet.acc still causes *problems*, so don't do that.
3865 			    strcmp(lookup_accountname(p_id), connp->nick)) {
3866 				/* However, if our account already exists then allow it to continue existing. */
3867 				if (!(acc = Admin_GetAccount(connp->nick))) {
3868 					Destroy_connection(ind, "Name already in use.");
3869 					Sockbuf_flush(&connp->w);
3870 					return(0);
3871 				}
3872 				KILL(acc, struct account);
3873 			}
3874 		}
3875 
3876 		/* check if player tries to use one of the temporarily reserved character names as this account name */
3877 		for (i = 0; i < MAX_RESERVED_NAMES; i++) {
3878 			if (!reserved_name_character[i][0]) break;
3879 
3880 			/* new: also for 'similar' names that don't belong to us */
3881 			condense_name(tmp_name, reserved_name_character[i]);
3882 			condense_name(tmp_name2, connp->nick);
3883 			if (!strcmp(tmp_name, tmp_name2) &&
3884 			    strcmp(reserved_name_account[i], connp->nick)) {
3885 				Destroy_connection(ind, "Name already in use.");
3886 				return(-0);
3887 			}
3888 
3889 			if (strcmp(reserved_name_character[i], connp->nick)) continue;
3890 
3891 			if (!strcmp(reserved_name_account[i], connp->nick)) {
3892 				reserved_name_character[i][0] = '\0'; //clear reservation
3893 				break;
3894 			}
3895 
3896 			Destroy_connection(ind, "Name already in use.");
3897 			return(-0);
3898 		}
3899 
3900 		/* Check if a too similar name already exists --
3901 		   must be called before GetAccount() is called, because that function
3902 		   imprints the condensed name onto a newly created account.
3903 		   Don't prevent already existing accounts from logging in though. */
3904 		if (!(acc = Admin_GetAccount(connp->nick)) && lookup_similar_account(connp->nick, NULL)) {
3905 			Destroy_connection(ind, "A too similar name is already in use. Check lower/upper case.");
3906 			return -1;
3907 		}
3908 		KILL(acc, struct account);
3909 
3910 		if (!connp->nick[0]) {
3911 			Destroy_connection(ind, "You need to enter an account name and password!");
3912 			return -1;
3913 		}
3914 		if (!connp->pass[0]) {
3915 			Destroy_connection(ind, "You must enter a password too!");
3916 			return -1;
3917 		}
3918 
3919 		if ((res = Check_names(connp->nick, connp->real, connp->host, connp->addr, FALSE)) != SUCCESS) {
3920 			if (res == E_LETTER)
3921 				Destroy_connection(ind, "Your accountname must start on a letter (A-Z).");
3922 			else
3923 				Destroy_connection(ind, "Your accountname, username or hostname contains invalid characters");
3924 			return(-1);
3925 		}
3926 
3927 		/* Check for forbidden names (swearing).
3928 		   Note: This overrides 'censor_swearing' and is always on! */
3929 		censor_swearing = censor_swearing_identity;
3930 		/* Check account name for swearing.. */
3931 		strcpy(tmp_name, connp->nick);
3932 		if (handle_censor(tmp_name)) {
3933 			censor_swearing = censor_swearing_tmp;
3934 			Destroy_connection(ind, "This account name is not available. Please choose a different name.");
3935 			return(-1);
3936 		}
3937 #if 1		/* Check hostname too for swearing? */
3938 		strcpy(tmp_name_wide, connp->host);
3939 		if (handle_censor(tmp_name_wide)) {
3940 			censor_swearing = censor_swearing_tmp;
3941 			Destroy_connection(ind, format("Your host name is '%s' which is deemed offensive. Please change it.", connp->host));
3942 			return(-1);
3943 		}
3944 #endif
3945 		/* (Note: since 'real' name is always replaced by "PLAYER", we don't need to check that one for swearing.) */
3946 		/* Switch back to normal swearing checking. */
3947 		censor_swearing = censor_swearing_tmp;
3948 
3949 		/* Password obfuscation introduced in pre-4.4.1a client or 4.4.1.1 */
3950 		if (connp->pass && is_newer_than(&connp->version, 4, 4, 1, 0, 0, 0)) {
3951 			/* Use memfrob for the password - mikaelh */
3952 			my_memfrob(connp->pass, strlen(connp->pass));
3953 		}
3954 
3955 		if (connp->pass && (l_acc = GetAccount(connp->nick, connp->pass, FALSE))) {
3956 			int *id_list;
3957 			byte tmpm;
3958 			char colour_sequence[3];
3959 			/* server flags to tell the client more about us - just informational purpose: */
3960 			u32b sflags3 = 0x0, sflags2 = 0x0, sflags1 = 0x0, sflags0 = 0x0;
3961 			/* flag array 0: server type flags
3962 			   flag array 1: features offered by server/client mode (special screen layout for showing party stats maybe (TODO//unused))
3963 			   flag array 2: temporary lua testing flags for experimental features
3964 			   flag array 3: unused
3965 			*/
3966 
3967 			/* Set server type flags */
3968 #ifdef RPG_SERVER
3969 			sflags0 |= SFLG0_RPG;
3970 			if (l_acc->flags & ACC_ADMIN) sflags0 |= SFLG0_RPG_ADMIN; /* Allow multiple chars per account for admins! */
3971 #endif
3972 #ifdef FUN_SERVER
3973 			sflags0 |= SFLG0_FUN;
3974 #endif
3975 #ifdef PARTY_SERVER
3976 			sflags0 |= SFLG0_PARTY;
3977 #endif
3978 #ifdef ARCADE_SERVER
3979 			sflags0 |= SFLG0_ARCADE;
3980 #endif
3981 #ifdef TEST_SERVER
3982 			sflags0 |= SFLG0_TEST;
3983 #endif
3984 #ifndef RPG_SERVER	/* not implemented for RPG SERVER atm */
3985  #ifdef ALLOW_DED_IDDC_MODE
3986 			sflags0 |= SFLG0_DED_IDDC;
3987  #endif
3988  #ifdef ALLOW_DED_PVP_MODE
3989 			sflags0 |= SFLG0_DED_PVP;
3990  #endif
3991 #endif
3992 #ifdef NO_PK
3993 			sflags0 |= SFLG0_NO_PK;
3994 #endif
3995 
3996 			/* Set available-feature / client mode flags */
3997 #ifdef BIG_MAP
3998 			sflags1 |= SFLG1_BIG_MAP;
3999 #endif
4000 
4001 #ifdef NEW_SHIELDS_NO_AC
4002 			sflags1 |= SFLG1_NEW_SHIELDS_NO_AC;
4003 #endif
4004 
4005 			/* Set temporary flags */
4006 			sflags2 = sflags_TEMP;
4007 
4008 			/* Set XXX flags */
4009 
4010 			/* Send all flags! */
4011 			Packet_printf(&connp->c, "%c%d%d%d%d", PKT_SERVERDETAILS, sflags3, sflags2, sflags1, sflags0);
4012 
4013 			connp->password_verified = TRUE;
4014 			free(connp->pass);
4015 			connp->pass = NULL;
4016 			n = player_id_list(&id_list, l_acc->id);
4017 			/* Display all account characters here */
4018 			for (i = 0; i < n; i++) {
4019 				u16b ptype = lookup_player_type(id_list[i]);
4020 
4021 				/* do not change protocol here */
4022 				tmpm = lookup_player_mode(id_list[i]);
4023 				if (tmpm & MODE_EVERLASTING) strcpy(colour_sequence, "\377B");
4024 				else if (tmpm & MODE_PVP) strcpy(colour_sequence, format("\377%c", COLOUR_MODE_PVP));
4025 				else if (tmpm & MODE_NO_GHOST) strcpy(colour_sequence, "\377D");
4026 				else if (tmpm & MODE_HARD) strcpy(colour_sequence, "\377s");
4027 				else strcpy(colour_sequence, "\377W");
4028 
4029 				/* look up character's current location */
4030 				wpos = lookup_player_wpos(id_list[i]);
4031 				/* note: we don't receive options yet, so we don't know about 'depth_in_feet' */
4032 				//sprintf(loc, "On lv %d in (%d,%d)", wpos.wz, wpos.wx, wpos.wy);
4033 				//sprintf(loc, "on %dft in (%d,%d)", wpos.wz * 50, wpos.wx, wpos.wy);//..so we just assume 'ft' notation
4034 				sprintf(loc, "in (%d,%d) on %dft", wpos.wx, wpos.wy, wpos.wz * 50);//..so we just assume 'ft' notation
4035 
4036 				if (is_newer_than(&connp->version, 4, 5, 7, 0, 0, 0))
4037 					Packet_printf(&connp->c, "%c%hd%s%s%hd%hd%hd%s", PKT_LOGIN, tmpm, colour_sequence, lookup_player_name(id_list[i]), lookup_player_level(id_list[i]), ptype&0xff , ptype>>8, loc);
4038 				else if (is_newer_than(&connp->version, 4, 4, 9, 2, 0, 0))
4039 					Packet_printf(&connp->c, "%c%hd%s%s%hd%hd%hd", PKT_LOGIN, tmpm, colour_sequence, lookup_player_name(id_list[i]), lookup_player_level(id_list[i]), ptype&0xff , ptype>>8);
4040 				else
4041 					Packet_printf(&connp->c, "%c%s%s%hd%hd%hd", PKT_LOGIN, colour_sequence, lookup_player_name(id_list[i]), lookup_player_level(id_list[i]), ptype&0xff , ptype>>8);
4042 			}
4043 			if (is_newer_than(&connp->version, 4, 5, 7, 0, 0, 0))
4044 				Packet_printf(&connp->c, "%c%hd%s%s%hd%hd%hd%s", PKT_LOGIN, 0, "", "", 0, 0 , 0, "");
4045 			else if (is_newer_than(&connp->version, 4, 4, 9, 2, 0, 0))
4046 				Packet_printf(&connp->c, "%c%hd%s%s%hd%hd%hd", PKT_LOGIN, 0, "", "", 0, 0, 0);
4047 			else
4048 				Packet_printf(&connp->c, "%c%s%s%hd%hd%hd", PKT_LOGIN, "", "", 0, 0, 0);
4049 			if (n) C_KILL(id_list, n, int);
4050 			KILL(l_acc, struct account);
4051 		}
4052 		else{
4053 			/* fail login here */
4054 			Destroy_connection(ind, "Wrong password or name already in use.");
4055 		}
4056 		Sockbuf_flush(&connp->w);
4057 		return(0);
4058 
4059 	} else if (connp->password_verified) { /* we have entered a character name */
4060 		int check_account_reason = 0;
4061 		bool censor_swearing_tmp = censor_swearing, took_reservation = FALSE;
4062 		char tmp_name[CHARACTERNAME_LEN];
4063 
4064 #if 0
4065 		/* just in case - some places can't handle a longer name and a valid client shouldn't supply a name this long anyway - mikaelh */
4066 		choice[NAME_LEN - 1] = '\0';
4067 #else
4068 		choice[CHARACTERNAME_LEN - 1] = '\0';
4069 #endif
4070 
4071 		/* Prevent EXPLOIT (adding a SPACE to foreign charname) */
4072 		s_printf("Player %s chooses character '%s' (strlen=%d)\n", connp->nick, choice, strlen(choice));
4073 		Trim_name(choice);
4074 
4075 		/* If already exists, change capitalization to match */
4076 		if (fix_player_case(choice)) s_printf("Name capitalization: -> '%s'\n", choice);
4077 
4078 		/* Check for forbidden names (technical/lore reasons) */
4079 		if (forbidden_name(choice)) {
4080 //			Packet_printf(&connp->c, "%c", E_INVAL);
4081 			Destroy_connection(ind, "Forbidden character name. Please choose a different name.");
4082 			return(-1);
4083 		}
4084 
4085 		/* Check for forbidden names (swearing).
4086 		   Note: This overrides 'censor_swearing' and is always on! */
4087 		censor_swearing = censor_swearing_identity;
4088 		strcpy(tmp_name, choice);
4089 		if (handle_censor(tmp_name)) {
4090 			censor_swearing = censor_swearing_tmp;
4091 			Destroy_connection(ind, "This character name is not available. Please choose a different name.");
4092 			return(-1);
4093 		}
4094 		censor_swearing = censor_swearing_tmp;
4095 
4096 		/* check if player tries to use one of the temporarily reserved character names */
4097 		for (i = 0; i < MAX_RESERVED_NAMES; i++) {
4098 			if (!reserved_name_character[i][0]) break;
4099 			if (strcasecmp(reserved_name_character[i], choice)) continue;
4100 
4101 			if (!strcmp(reserved_name_account[i], connp->nick)) {
4102 				reserved_name_character[i][0] = '\0'; //clear reservation
4103 				took_reservation = TRUE;
4104 				break;
4105 			}
4106 
4107 			Destroy_connection(ind, "Name already in use by another player.");
4108 			return(-1);
4109 		}
4110 
4111 		/* Check if a too similar account name already exists.
4112 		   Only for characters that don't exist yet and would be newly created. */
4113 		if (!lookup_player_id(choice) && lookup_similar_account(choice, connp->nick)
4114 		    /* exception! reserved character names have priority.
4115 		       Otherwise someone could create an account meanwhile to block this player's reincarnation.
4116 		       Ok, far-fetched paranoia, but still >_>.. */
4117 		    && !took_reservation) {
4118 			Destroy_connection(ind, "A too similar name exists. Please choose a different name.");
4119 			return -1;
4120 		}
4121 
4122 		/* at this point, we are authorised as the owner
4123 		   of the account. any valid name will be
4124 		   allowed. */
4125 		/* i realise it should return different value depending
4126 		   on reason - evileye */
4127 		check_account_reason = check_account(connp->nick, choice);
4128 		//s_printf("success = %d\n", check_account_reason);
4129 		switch (check_account_reason) {
4130 		case 0: //NOT OK
4131 			/* fail login here */
4132 			Destroy_connection(ind, "Name already in use by another player.");
4133 			return(-1);
4134 		case 1:	//OK
4135 			break;
4136 		case -1: //NOT OK: Max 1 char (RPG)
4137 			/* fail login here */
4138 			Destroy_connection(ind, "Only one character per account is allowed.");
4139 			return(-1);
4140 		case -2: //NOT OK
4141 			/* fail login here */
4142 			Destroy_connection(ind, "Multiple logins on the same account aren't allowed.");
4143 			return(-1);
4144 		case -3: /* Out of character slots! */
4145 			Destroy_connection(ind, "Character amount limit reached.");
4146 			return(-1);
4147 		case -4: /* Force creation of MODE_DED_PVP character */
4148 			connp->sex = MODE_DED_PVP;
4149 			break;
4150 		case -5: /* Force creation of MODE_DED_IDDC or MODE_DED_PVP character */
4151 			connp->sex = MODE_DED_IDDC;
4152 			break;
4153 		case -6:
4154 			/*hack: marker for both possibilities. We will decide when we see the user's actual choice later. */
4155 			connp->sex = MODE_DED_PVP | MODE_DED_IDDC;
4156 			break;
4157 		case -7: /* like 1, and allow non-forced creation of slot-exclusive chars */
4158 			connp->sex = MODE_DED_PVP_OK | MODE_DED_IDDC_OK;
4159 			break;
4160 		case -8: /* like 1, and allow non-forced creation of iddc-slot-exclusive char */
4161 			connp->sex = MODE_DED_IDDC_OK;
4162 			break;
4163 		case -9: /* like 1, and allow non-forced creation of pvp-slot-exclusive char */
4164 			connp->sex = MODE_DED_PVP_OK;
4165 			break;
4166 		default:
4167 			Destroy_connection(ind, "unknown error");
4168 			return -1;
4169 		}
4170 
4171 		/* Check that no one else is creating a char with the same name - mikaelh */
4172 		for (i = 0; i < max_connections; i++) {
4173 			connp2 = Conn[i];
4174 			if (!connp2 || connp2->state == CONN_FREE) continue;
4175 			if (connp2->c_name && !strcasecmp(connp2->c_name, choice) &&
4176 			    strcasecmp(connp2->nick, connp->nick)) { /* check that it's a different account, too */
4177 				/* Fail login */
4178 				Destroy_connection(ind, "Character name already in use.");
4179 				s_printf("(Prevented simultaneous creation of same character.)\n");
4180 				return(-1);
4181 			}
4182 		}
4183 
4184 		/* Validate names/resume in proper place */
4185 		if ((res = Check_names(choice, connp->real, connp->host, connp->addr, TRUE))) {
4186 			/* connp->real is _always_ 'PLAYER' - connp->nick is the account name, choice the c_name */
4187 			/* fail login here */
4188 			if (res == E_LETTER)
4189 				Destroy_connection(ind, "Your charactername must start on a letter (A-Z).");
4190 			else if (res == E_INVAL)
4191 				Destroy_connection(ind, "Your charactername contains invalid characters"); //user+host names have already been checked previously (on account login)
4192 			else
4193 				Destroy_connection(ind, "Security violation");
4194 			return(-1);
4195 		}
4196 		Packet_printf(&connp->c, "%c", lookup_player_id(choice) ? SUCCESS : E_NEED_INFO);
4197 		connp->c_name = strdup(choice);
4198 	} else {
4199 		/* fail login due to missing password */
4200 		s_printf("EXPLOIT: Missing password of player %s.\n", connp->nick);
4201 		Destroy_connection(ind, "Missing password");
4202 		return(-1);
4203 	}
4204 	if (connp->setup >= Setup.setup_size)
4205 		Conn_set_state(connp, CONN_LOGIN, CONN_LOGIN);
4206 	return(0);
4207 }
4208 
4209 #define RECEIVE_PLAY_SIZE (2*6+OPT_MAX+2*(TV_MAX+MAX_F_IDX_COMPAT+MAX_K_IDX_COMPAT+MAX_R_IDX_COMPAT))
4210 #define RECEIVE_PLAY_SIZE_OPTMAXCOMPAT (2*6+OPT_MAX_COMPAT+2*(TV_MAX+MAX_F_IDX_COMPAT+MAX_K_IDX_COMPAT+MAX_R_IDX_COMPAT))
4211 #define RECEIVE_PLAY_SIZE_OPTMAXOLD (2*6+OPT_MAX_OLD+2*(TV_MAX+MAX_F_IDX_COMPAT+MAX_K_IDX_COMPAT+MAX_R_IDX_COMPAT))
4212 //#define STRICT_RECEIVE_PLAY
4213 static int Receive_play(int ind) {
4214 	connection_t *connp = Conn[ind];
4215 	unsigned char ch;
4216 	int i, n;
4217 	s16b sex, race, class, trait = 0;
4218         short int sfx = -1, mus = -1;
4219 
4220 	/* XXX */
4221 	n = Sockbuf_read(&connp->r);
4222 	if (n == 0 && !(errno == EAGAIN || errno == EWOULDBLOCK)) {
4223 		/* avoid SIGPIPE in zero read */
4224 		close(connp->w.sock);
4225 		remove_input(connp->w.sock);
4226 		connp->w.sock = -1;
4227 		Destroy_connection(ind, "disconnect in play");
4228 		return(-1);
4229 	}
4230 
4231 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) != 1) {
4232 		errno = 0;
4233 		plog("Cannot receive play packet");
4234 		Destroy_connection(ind, "receive error in play");
4235 		return -1;
4236 	}
4237 
4238 	/* Do not tell me how much this sucks. I didn't do the design
4239 	   evileye */
4240 	if (ch == PKT_LOGIN) {
4241 		Receive_login(ind);
4242 		return(0);
4243 	}
4244 	if (ch != PKT_PLAY) {
4245 	  //		errno = 0;
4246 #if DEBUG_LEVEL > 1
4247 #if DEBUG_LEVEL < 3
4248 		if (ch != PKT_KEEPALIVE)
4249 #endif	// DEBUG_LEVEL(2)
4250 			plog(format("Packet is not of play type (%d)", ch));
4251 #endif	// DEBUG_LEVEL(1)
4252 	  //Destroy_connection(ind, "not play");
4253 	  //return -1;
4254 	  return 0;
4255 	}
4256 //	else
4257 	{
4258 		if (is_newer_than(&connp->version, 4, 4, 5, 10, 0, 0)) {
4259 			if ((n = Packet_scanf(&connp->r, "%hd%hd%hd%hd%hd%hd", &sex, &race, &class, &trait, &sfx, &mus)) <= 0) {
4260 				errno = 0;
4261 				plog("Play packet is broken");
4262 				Destroy_connection(ind, "receive error 2 in play");
4263 				return -1;
4264 			}
4265 		} else {
4266 			if ((n = Packet_scanf(&connp->r, "%hd%hd%hd", &sex, &race, &class)) <= 0) {
4267 				errno = 0;
4268 				plog("Play packet is broken");
4269 				Destroy_connection(ind, "receive error 2 in play");
4270 				return -1;
4271 			}
4272 		}
4273 
4274 		/* hacks for forcibly dedicated characters */
4275 		if ((connp->sex & MODE_DED_PVP) &&
4276 		    (connp->sex & MODE_DED_IDDC)) { //allow both, depending on what the user wants:
4277 			if (sex & MODE_PVP) {
4278 				sex &= ~(MODE_EVERLASTING | MODE_NO_GHOST | MODE_HARD | MODE_DED_IDDC);
4279 				sex |= MODE_DED_PVP;
4280 			} else {
4281 				sex &= ~MODE_DED_PVP;
4282 				sex |= MODE_DED_IDDC;
4283 			}
4284 		}
4285 		else if (connp->sex & MODE_DED_PVP) {
4286 			sex &= ~(MODE_EVERLASTING | MODE_NO_GHOST | MODE_HARD | MODE_DED_IDDC);
4287 			sex |= MODE_DED_PVP | MODE_PVP;
4288 		}
4289 		else if (connp->sex & MODE_DED_IDDC) {
4290 			sex &= ~(MODE_PVP | MODE_DED_PVP);
4291 			sex |= MODE_DED_IDDC;
4292 		}
4293 
4294 		/* hack for willingly dedicated characters */
4295 		if (!(connp->sex & (MODE_DED_PVP | MODE_DED_IDDC))) {//not forced..
4296 			if (sex & MODE_DED_PVP) { //..but wants to be dedicated pvp. Check if that's not allowed.
4297 				if (!(connp->sex & MODE_DED_PVP_OK)) sex &= ~MODE_DED_PVP;
4298 				if (!(sex & MODE_PVP)) sex &= ~MODE_DED_PVP;
4299 			}
4300 			if (sex & MODE_DED_IDDC) { //..but wants to be dedicated iddc. Check if that's not allowed.
4301 				if (!(connp->sex & MODE_DED_IDDC_OK)) sex &= ~MODE_DED_IDDC;
4302 				if (sex & MODE_PVP) sex &= ~MODE_DED_IDDC;
4303 			}
4304 		}
4305 
4306 		/* Dedicated IDDC characters are always no-ghost */
4307 		if (sex & MODE_DED_IDDC) {
4308 			sex &= ~MODE_EVERLASTING;
4309 			sex |= MODE_NO_GHOST;
4310 		}
4311 
4312 		if (sex & MODE_DED_PVP) sex |= MODE_PVP;
4313 
4314 		/* Set his character info */
4315 		connp->sex = sex;
4316 		connp->race = race;
4317 		connp->class = class;
4318 		connp->trait = trait;
4319 
4320 //		if (2654 > connp->r.len - (connp->r.ptr - connp->r.buf))
4321 		if ((is_newer_than(&connp->version, 4, 5, 8, 1, 0, 1) ? RECEIVE_PLAY_SIZE :
4322 		    (is_newer_than(&connp->version, 4, 5, 5, 0, 0, 0) ? RECEIVE_PLAY_SIZE_OPTMAXCOMPAT : RECEIVE_PLAY_SIZE_OPTMAXOLD))
4323 		    > connp->r.len - (connp->r.ptr - connp->r.buf)) {
4324 #if DEBUG_LEVEL > 2
4325 			plog(format("Play packet is not large enough yet (%d)",
4326 			    connp->r.len - (connp->r.ptr - connp->r.buf)));
4327 #endif	// DEBUG_LEVEL
4328 			connp->r.ptr = connp->r.buf;
4329 			return 1;
4330 		}
4331 
4332 #if DEBUG_LEVEL > 2
4333 			plog(format("Play packet is now large enough (%d)",
4334 			    connp->r.len - (connp->r.ptr - connp->r.buf)));
4335 #endif	// DEBUG_LEVEL
4336 
4337 #if 1	// moved from Handle_listening
4338 		/* Read the stat order */
4339 		for (i = 0; i < 6; i++) {
4340 			n = Packet_scanf(&connp->r, "%hd", &connp->stat_order[i]);
4341 			if (n <= 0) {
4342 				Destroy_connection(ind, "Misread stat order");
4343 				return -1;
4344 			}
4345 		}
4346 
4347 #if 0
4348 		/* Read class extra */
4349 		n = Packet_scanf(&connp->r, "%hd", &connp->class_extra);
4350 		if (n <= 0) {
4351 			Destroy_connection(ind, "Misread class extra");
4352 			return -1;
4353 		}
4354 #endif	// 0
4355 
4356 		/* Read the options */
4357 		if (is_newer_than(&connp->version, 4, 5, 8, 1, 0, 1)) {
4358 			for (i = 0; i < OPT_MAX; i++) {
4359 				n = Packet_scanf(&connp->r, "%c", &connp->Client_setup.options[i]);
4360 				if (n <= 0) {
4361 					Destroy_connection(ind, "Misread options");
4362 					return -1;
4363 				}
4364 			}
4365 		} else if (is_newer_than(&connp->version, 4, 5, 5, 0, 0, 0)) {
4366 			for (i = 0; i < OPT_MAX_COMPAT; i++) {
4367 				n = Packet_scanf(&connp->r, "%c", &connp->Client_setup.options[i]);
4368 				if (n <= 0) {
4369 					Destroy_connection(ind, "Misread options");
4370 					return -1;
4371 				}
4372 			}
4373 		} else {
4374 			for (i = 0; i < OPT_MAX_OLD; i++) {
4375 				n = Packet_scanf(&connp->r, "%c", &connp->Client_setup.options[i]);
4376 				if (n <= 0) {
4377 					Destroy_connection(ind, "Misread options");
4378 					return -1;
4379 				}
4380 			}
4381 		}
4382 
4383 		/* Read screen dimensions */
4384 		if (is_newer_than(&connp->version, 4, 4, 9, 1, 0, 1)) {
4385 			n = Packet_scanf(&connp->r, "%d%d", &connp->Client_setup.screen_wid, &connp->Client_setup.screen_hgt);
4386 			if (n <= 0) {
4387 				Destroy_connection(ind, "Misread dimensions");
4388 				return -1;
4389 			}
4390 
4391 			/* fix limits */
4392 #ifdef BIG_MAP
4393 			if (connp->Client_setup.screen_wid > MAX_SCREEN_WID) connp->Client_setup.screen_wid = MAX_SCREEN_WID;
4394 			if (connp->Client_setup.screen_wid < MIN_SCREEN_WID) connp->Client_setup.screen_wid = MIN_SCREEN_WID;
4395 			if (connp->Client_setup.screen_hgt > MAX_SCREEN_HGT) connp->Client_setup.screen_hgt = MAX_SCREEN_HGT;
4396 			if (connp->Client_setup.screen_hgt < MIN_SCREEN_HGT) connp->Client_setup.screen_hgt = MIN_SCREEN_HGT;
4397 			/* for now until resolved: avoid dimensions whose half values aren't divisors of MAX_WID/HGT */
4398 			if (MAX_WID % (connp->Client_setup.screen_wid / 2)) connp->Client_setup.screen_wid = SCREEN_WID;
4399 			if (MAX_HGT % (connp->Client_setup.screen_hgt / 2)) connp->Client_setup.screen_hgt = SCREEN_HGT;
4400 #else
4401 			connp->Client_setup.screen_wid = SCREEN_WID;
4402 			connp->Client_setup.screen_hgt = SCREEN_HGT;
4403 #endif
4404 		} else {
4405 			connp->Client_setup.screen_wid = SCREEN_WID;
4406 			connp->Client_setup.screen_hgt = SCREEN_HGT;
4407 		}
4408 
4409 		/* Read the "unknown" char/attrs */
4410 		for (i = 0; i < TV_MAX; i++) {
4411 			n = Packet_scanf(&connp->r, "%c%c", &connp->Client_setup.u_attr[i], &connp->Client_setup.u_char[i]);
4412 			if (n <= 0) {
4413 #ifdef STRICT_RECEIVE_PLAY
4414 				Destroy_connection(ind, "Misread unknown redefinitions");
4415 				return -1;
4416 #else
4417 				break;
4418 #endif
4419 			}
4420 		}
4421 
4422 		/* Read the "feature" char/attrs */
4423 		for (i = 0; i < MAX_F_IDX_COMPAT; i++) {
4424 			n = Packet_scanf(&connp->r, "%c%c", &connp->Client_setup.f_attr[i], &connp->Client_setup.f_char[i]);
4425 			if (n <= 0) {
4426 #ifdef STRICT_RECEIVE_PLAY
4427 				Destroy_connection(ind, "Misread feature redefinitions");
4428 				return -1;
4429 #else
4430 				break;
4431 #endif
4432 			}
4433 		}
4434 
4435 		/* Read the "object" char/attrs */
4436 		for (i = 0; i < MAX_K_IDX_COMPAT; i++) {
4437 			n = Packet_scanf(&connp->r, "%c%c", &connp->Client_setup.k_attr[i], &connp->Client_setup.k_char[i]);
4438 			if (n <= 0) {
4439 #ifdef STRICT_RECEIVE_PLAY
4440 				Destroy_connection(ind, "Misread object redefinitions");
4441 				return -1;
4442 #else
4443 				break;
4444 #endif
4445 			}
4446 		}
4447 
4448 		/* Read the "monster" char/attrs */
4449 		for (i = 0; i < MAX_R_IDX_COMPAT; i++) {
4450 			n = Packet_scanf(&connp->r, "%c%c", &connp->Client_setup.r_attr[i], &connp->Client_setup.r_char[i]);
4451 			if (n <= 0) {
4452 #ifdef STRICT_RECEIVE_PLAY
4453 				Destroy_connection(ind, "Misread monster redefinitions");
4454 				return -1;
4455 #else
4456 				break;
4457 #endif
4458 			}
4459 		}
4460 #endif	// 0
4461 	}
4462 	if (connp->state != CONN_LOGIN) {
4463 		if (connp->state != CONN_PLAYING) {
4464 			if (connp->state == CONN_READY) {
4465 				connp->r.ptr = connp->r.buf + connp->r.len;
4466 				return 0;
4467 			}
4468 			errno = 0;
4469 			plog(format("Connection not in login state (%02x)", connp->state));
4470 			Destroy_connection(ind, "not login");
4471 			return -1;
4472 		}
4473 		//if (Send_reliable_old(ind) == -1)
4474 		if (Send_reliable(ind) == -1)
4475 			return -1;
4476 		return 0;
4477 	}
4478 
4479 	s_printf("AUDIO: %s features %hd, %hd.\n", connp->nick, sfx, mus);
4480 	connp->audio_sfx = (short int)sfx;
4481 	connp->audio_mus = (short int)mus;
4482 
4483 	Sockbuf_clear(&connp->w);
4484 	if (Handle_login(ind) == -1) {
4485 		/* The connection has already been destroyed */
4486 		return -1;
4487 	}
4488 
4489 	return 2;
4490 }
4491 
4492 /* Head of file transfer system receive */
4493 /* DO NOT TOUCH - work in progress */
4494 static int Receive_file(int ind) {
4495 	char command, ch;
4496 	char fname[MAX_CHARS];	/* possible filename */
4497 	int x;	/* return value/ack */
4498 	unsigned short fnum;	/* unique SENDER side file number */
4499 	unsigned short len;
4500 	u32b csum;
4501 	int n;
4502 	connection_t *connp = Conn[ind];
4503 	player_type *p_ptr = NULL;
4504 	int Ind;
4505 
4506 	Ind = GetInd[connp->id];
4507 	p_ptr = Players[Ind];
4508 	n = Packet_scanf(&connp->r, "%c%c%hd", &ch, &command, &fnum);
4509 	if (n == 3) {
4510 		switch (command) {
4511 			case PKT_FILE_INIT:
4512 				/* Admin to do this only !!! */
4513 				Packet_scanf(&connp->r, "%s", fname);
4514 				if (!is_admin(p_ptr)) {
4515 					msg_print(Ind, "\377rFile transfer refused");
4516 					x = 0;
4517 				} else {
4518 					msg_print(Ind, "\377gAttempting file transfer");
4519 					x = local_file_init(ind, fnum, fname);
4520 				}
4521 				break;
4522 			case PKT_FILE_DATA:
4523 				Packet_scanf(&connp->r, "%hd", &len);
4524 				x = local_file_write(ind, fnum, len);
4525 				break;
4526 			case PKT_FILE_END:
4527 				x = local_file_close(ind, fnum);
4528 				msg_format(Ind, "\377oFile transfer %s.", x? "successful":"failed");
4529 				break;
4530 			case PKT_FILE_CHECK:
4531 				/* Admin to do this only !!! */
4532 				Packet_scanf(&connp->r, "%s", fname);
4533 				if (!is_admin(p_ptr)) {
4534 					msg_print(Ind, "\377rFile check refused");
4535 					x = 0;
4536 				} else {
4537 					msg_print(Ind, "\377yChecking file");
4538 					x = local_file_check(fname, &csum);
4539 					Packet_printf(&connp->w, "%c%c%hd%d", PKT_FILE, PKT_FILE_SUM, fnum, csum);
4540 					return(1);
4541 				}
4542 				break;
4543 			case PKT_FILE_SUM:
4544 				Packet_scanf(&connp->r, "%d", &csum);
4545 				check_return(ind, fnum, csum, Ind);
4546 
4547 				/* for 4.4.8.1.0.0 LUA update crash bug */
4548 				if (p_ptr->warning_lua_count == 0 && p_ptr->warning_lua_update == 1
4549 				    /* don't give him messages if he can't help it */
4550 				    && !p_ptr->v_latest) {
4551 					msg_print(Ind, "\377RWarning: Due to a bug in client 4.4.8 it cannot update LUA files.");
4552 					msg_print(Ind, "\377R         If you play spell-casting characters please update your client!");
4553 				}
4554 
4555 				return(1);
4556 				break;
4557 			case PKT_FILE_ACK:
4558 				local_file_ack(ind, fnum);
4559 				return(1);
4560 				break;
4561 			case PKT_FILE_ERR:
4562 				local_file_err(ind, fnum);
4563 				/* continue the send/terminate */
4564 				return(1);
4565 				break;
4566 			default:
4567 				printf("unknown file transfer packet\n");
4568 				x = 0;
4569 		}
4570 		Packet_printf(&connp->c, "%c%c%hd", PKT_FILE, x?PKT_FILE_ACK:PKT_FILE_ERR, fnum);
4571 	}
4572 	return(1);
4573 }
4574 
4575 int Receive_file_data(int ind, unsigned short len, char *buffer) {
4576 	connection_t *connp = Conn[ind];
4577 	memcpy(buffer, connp->r.ptr, len);
4578 	connp->r.ptr += len;
4579 	return(1);
4580 }
4581 
4582 int Send_file_check(int ind, unsigned short id, char *fname) {
4583 	connection_t *connp = Conn[ind];
4584 	Packet_printf(&connp->c, "%c%c%hd%s", PKT_FILE, PKT_FILE_CHECK, id, fname);
4585 	return(1);
4586 }
4587 
4588 int Send_file_init(int ind, unsigned short id, char *fname) {
4589 	connection_t *connp = Conn[ind];
4590 	Packet_printf(&connp->c, "%c%c%hd%s", PKT_FILE, PKT_FILE_INIT, id, fname);
4591 	return(1);
4592 }
4593 
4594 int Send_file_data(int ind, unsigned short id, char *buf, unsigned short len) {
4595 	connection_t *connp = Conn[ind];
4596 	Packet_printf(&connp->c, "%c%c%hd%hd", PKT_FILE, PKT_FILE_DATA, id, len);
4597 	if (Sockbuf_write(&connp->c, buf, len) != len) {
4598 		printf("failed sending file data\n");
4599 	}
4600 	return(1);
4601 }
4602 
4603 int Send_file_end(int ind, unsigned short id) {
4604 	connection_t *connp = Conn[ind];
4605 	Packet_printf(&connp->c, "%c%c%hd", PKT_FILE, PKT_FILE_END, id);
4606 	return(1);
4607 }
4608 
4609 int Send_reliable(int ind)
4610 {
4611 	connection_t *connp = Conn[ind];
4612 	int num_written;
4613 
4614 	/* Hack -- make sure we have a valid socket to write to.  -1 is used to
4615 	 * specify a player that has disconnected but is still "in game".
4616 	 */
4617 	if (connp->w.sock == -1) return 0;
4618 
4619 	if (Sockbuf_write(&connp->w, connp->c.buf, connp->c.len) != connp->c.len)
4620 	{
4621 		plog("Cannot write reliable data");
4622 		Destroy_connection(ind, "write error");
4623 		return -1;
4624 	}
4625 	if ((num_written = Sockbuf_flush(&connp->w)) < connp->w.len)
4626 	{
4627 		plog(format("Cannot flush reliable data (%d)", num_written));
4628 		Destroy_connection(ind, "flush error");
4629 
4630 #if 0
4631 		/* Very bad hack :/ - C. Blue */
4632 		save_game_panic();
4633 #endif
4634 
4635 		return -1;
4636 	}
4637 	Sockbuf_clear(&connp->c);
4638 	return num_written;
4639 }
4640 
4641 #if 0 /* old UDP networking stuff - mikaelh */
4642 int Send_reliable_old(int ind)
4643 {
4644 	connection_t *connp = Conn[ind];
4645 	char *read_buf;
4646 	int i, n, len, todo, max_todo, rel_off;
4647 	const int max_packet_size = MAX_RELIABLE_DATA_PACKET_SIZE,
4648 		min_send_size = 1;
4649 
4650 	if (connp->c.len <= 0 || connp->last_send_loops == turn) {
4651 		connp->last_send_loops = turn;
4652 		return 0;
4653 	}
4654 	read_buf = connp->c.buf;
4655 	max_todo = connp->c.len;
4656 	rel_off = connp->reliable_offset;
4657 	if (connp->w.len > 0) {
4658 		if (connp->w.len >= max_packet_size - min_send_size)
4659 			return 0;
4660 		if (max_todo > max_packet_size - connp->w.len)
4661 			max_todo = max_packet_size - connp->w.len;
4662 	}
4663 	if (connp->retransmit_at_loop > turn)
4664 	{
4665 		if (max_todo <= connp->reliable_unsent - connp->reliable_offset
4666 			+ min_send_size || connp->w.len == 0)
4667 			return 0;
4668 	}
4669 	else if (connp->retransmit_at_loop != 0)
4670 		connp->acks >>= 1;
4671 
4672 	todo = max_todo;
4673 
4674 	for (i = 0; i <= connp->acks && todo > 0; i++)
4675 	{
4676 		len = (todo > max_packet_size) ? max_packet_size : todo;
4677 		if (Packet_printf(&connp->w, "%c%hd%d%d%d", PKT_RELIABLE,
4678 			len, rel_off, turn, max_todo) <= 0
4679 			|| Sockbuf_write(&connp->w, read_buf, len) != len)
4680 		{
4681 			plog("Cannot write reliable data");
4682 			Destroy_connection(ind, "write error");
4683 			return -1;
4684 		}
4685 
4686 		if ((n = Sockbuf_flush(&connp->w)) < len)
4687 		{
4688 			if (n == 0 && (errno == EWOULDBLOCK
4689 				|| errno == EAGAIN))
4690 			{
4691 				connp->acks = 0;
4692 				break;
4693 			}
4694 			else
4695 			{
4696 				plog(format("Cannot flush reliable data (%d)", n));
4697 				Destroy_connection(ind, "flush error");
4698 				return -1;
4699 			}
4700 		}
4701 
4702 		todo -= len;
4703 		rel_off += len;
4704 		read_buf += len;
4705 	}
4706 
4707 	Sockbuf_clear(&connp->w);
4708 
4709 	connp->last_send_loops = turn;
4710 
4711 	if (max_todo - todo <= 0)
4712 		return 0;
4713 
4714 	if (connp->rtt_retransmit > MAX_RETRANSMIT)
4715 		connp->rtt_retransmit = MAX_RETRANSMIT;
4716 	if (connp->retransmit_at_loop <= turn)
4717 	{
4718 		connp->retransmit_at_loop = turn + connp->rtt_retransmit;
4719 		connp->rtt_retransmit <<= 1;
4720 		connp->rtt_timeouts++;
4721 	}
4722 	else connp->retransmit_at_loop = turn + connp->rtt_retransmit;
4723 
4724 	if (rel_off > connp->reliable_unsent)
4725 		connp->reliable_unsent = rel_off;
4726 
4727 	return (max_todo - todo);
4728 }
4729 #endif
4730 
4731 #if 0 /* old UDP networking stuff - mikaelh */
4732 static int Receive_ack(int ind)
4733 {
4734 	connection_t *connp = Conn[ind];
4735 	int n;
4736 	unsigned char ch;
4737 	int rel, rtt, diff, delta, rel_loops;
4738 
4739 	if ((n = Packet_scanf(&connp->r, "%c%d%d", &ch, &rel, &rel_loops))
4740 		<= 0)
4741 	{
4742 		errno = 0;
4743 		plog(format("Cannot read ack packet (%d)", n));
4744 		Destroy_connection(ind, "read error");
4745 		return -1;
4746 	}
4747 	if (ch != PKT_ACK)
4748 	{
4749 		errno = 0;
4750 		plog(format("Not an ack packet (%d)", ch));
4751 		Destroy_connection(ind, "not ack");
4752 		return -1;
4753 	}
4754 	rtt = turn - rel_loops;
4755 	if (rtt > 0 && rtt <= MAX_RTT)
4756 	{
4757 		if (connp->rtt_smoothed == 0)
4758 			connp->rtt_smoothed = rtt << 3;
4759 		delta = rtt - (connp->rtt_smoothed >> 3);
4760 		connp->rtt_smoothed += delta;
4761 		if (delta < 0)
4762 			delta = -delta;
4763 		connp->rtt_dev += delta - (connp->rtt_dev >> 2);
4764 		connp->rtt_retransmit = ((connp->rtt_smoothed >> 2)
4765 			+ connp->rtt_dev) >> 1;
4766 		if (connp->rtt_retransmit < MIN_RETRANSMIT)
4767 			connp->rtt_retransmit = MIN_RETRANSMIT;
4768 	}
4769 	diff = rel - connp->reliable_offset;
4770 	if (diff > connp->c.len)
4771 	{
4772 		errno = 0;
4773 		plog(format("Bad ack (diff=%d,cru=%d,c=%d,len=%d)",
4774 			diff, rel, connp->reliable_offset, connp->c.len));
4775 		Destroy_connection(ind, "bad ack");
4776 		return -1;
4777 	}
4778 	else if (diff <= 0)
4779 		return 1;
4780 	Sockbuf_advance(&connp->c, (int) diff);
4781 	connp->reliable_offset += diff;
4782 	if ((n = ((diff + 512 - 1) / 512)) > connp->acks)
4783 		connp->acks = n;
4784 	else
4785 		connp->acks++;
4786 	if (connp->reliable_offset >= connp->reliable_unsent)
4787 	{
4788 		connp->retransmit_at_loop = 0;
4789 		if (connp->state == CONN_DRAIN)
4790 			Conn_set_state(connp, connp->drain_state, connp->drain_state);
4791 	}
4792 	if (connp->state == CONN_READY
4793 		&& (connp->c.len <= 0
4794 		|| (connp->c.buf[0] != PKT_REPLY
4795 			&& connp->c.buf[0] != PKT_PLAY
4796 			&& connp->c.buf[0] != PKT_SUCCESS
4797 			&& connp->c.buf[0] != PKT_FAILURE)))
4798 		Conn_set_state(connp, connp->drain_state, connp->drain_state);
4799 
4800 	connp->rtt_timeouts = 0;
4801 
4802 	/*printf("Received ack to data sent at %d.\n", rel_loops);*/
4803 
4804 	return 1;
4805 }
4806 #endif
4807 
4808 static int Receive_discard(int ind)
4809 {
4810 	connection_t *connp = Conn[ind];
4811 
4812 	errno = 0;
4813 	plog(format("Discarding packet %d while in state %02x",
4814 		connp->r.ptr[0], connp->state));
4815 	connp->r.ptr = connp->r.buf + connp->r.len;
4816 
4817 	return 0;
4818 }
4819 
4820 static int Receive_undefined(int ind)
4821 {
4822 	connection_t *connp = Conn[ind];
4823 
4824 	errno = 0;
4825 	plog(format("Unknown packet type (%d,%02x)", connp->r.ptr[0], connp->state));
4826 
4827 	/* Dont destroy connection. Ignore the invalid packet */
4828 	/*Destroy_connection(ind, "undefined packet");*/
4829 
4830 	/* Discard everything - mikaelh */
4831 	connp->r.ptr = connp->r.buf + connp->r.len;
4832 
4833 	return -1;	/* Crash if not (evil) */
4834 	/*return 0;*/
4835 }
4836 
4837 int Send_plusses(int ind, int tohit, int todam, int hr, int dr, int hm, int dm)
4838 {
4839 	connection_t *connp = Conn[Players[ind]->conn], *connp2;
4840 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[ind];*/
4841 
4842 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
4843 	{
4844 		errno = 0;
4845 		plog(format("Connection not ready for plusses (%d.%d.%d)",
4846 			ind, connp->state, connp->id));
4847 		return 0;
4848 	}
4849 
4850 	if (get_esp_link(ind, LINKF_MISC, &p_ptr2)) {
4851 		connp2 = Conn[p_ptr2->conn];
4852 		Packet_printf(&connp2->c, "%c%hd%hd%hd%hd%hd%hd", PKT_PLUSSES, tohit, todam, hr, dr, hm, dm);
4853 	}
4854 
4855         return Packet_printf(&connp->c, "%c%hd%hd%hd%hd%hd%hd", PKT_PLUSSES, tohit, todam, hr, dr, hm, dm);
4856 }
4857 
4858 
4859 int Send_ac(int ind, int base, int plus)
4860 {
4861 	connection_t *connp = Conn[Players[ind]->conn], *connp2;
4862 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[ind];*/
4863 
4864 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
4865 	{
4866 		errno = 0;
4867 		plog(format("Connection not ready for ac (%d.%d.%d)",
4868 			ind, connp->state, connp->id));
4869 		return 0;
4870 	}
4871 	if (get_esp_link(ind, LINKF_MISC, &p_ptr2)) {
4872 		connp2 = Conn[p_ptr2->conn];
4873 		Packet_printf(&connp2->c, "%c%hd%hd", PKT_AC, base, plus);
4874 	}
4875 	return Packet_printf(&connp->c, "%c%hd%hd", PKT_AC, base, plus);
4876 }
4877 
4878 int Send_experience(int Ind, int lev, s32b max, s32b cur, s32b adv, s32b adv_prev) {
4879 	connection_t *connp = Conn[Players[Ind]->conn];
4880 
4881 
4882 	int Ind2;
4883 	connection_t *connp2;
4884 	player_type *p_ptr2 = NULL;
4885 
4886 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
4887 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2))) {
4888 		connp2 = Conn[p_ptr2->conn];
4889 		if (is_newer_than(&Players[Ind2]->version, 4, 5, 6, 0, 0, 1))
4890 			/* hack: add marker to 'lev' to allow keeping track of exp_frac during level 1 exp'ing phase */
4891 			Packet_printf(&connp2->c, "%c%hu%hu%hu%d%d%d%d", PKT_EXPERIENCE, lev + (Players[Ind]->exp_frac >= 5000 ? 1000 : 0), Players[Ind]->max_lev, Players[Ind]->max_plv, max, cur, adv, adv_prev);
4892 		else if (is_newer_than(&Players[Ind2]->version, 4, 4, 1, 3, 0, 0))
4893 			Packet_printf(&connp2->c, "%c%hu%hu%hu%d%d%d", PKT_EXPERIENCE, lev, Players[Ind]->max_lev, Players[Ind]->max_plv, max, cur, adv);
4894 		else
4895 			Packet_printf(&connp2->c, "%c%hu%d%d%d", PKT_EXPERIENCE, lev, max, cur, adv);
4896 	}
4897 
4898 
4899 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
4900 		errno = 0;
4901 		plog(format("Connection not ready for experience (%d.%d.%d)",
4902 			Ind, connp->state, connp->id));
4903 		return 0;
4904 	}
4905 
4906 	if (is_newer_than(&Players[Ind]->version, 4, 5, 6, 0, 0, 1))
4907 		/* hack: add marker to 'lev' to allow keeping track of exp_frac during level 1 exp'ing phase */
4908 		return Packet_printf(&connp->c, "%c%hu%hu%hu%d%d%d%d", PKT_EXPERIENCE, lev + (Players[Ind]->exp_frac >= 5000 ? 1000 : 0), Players[Ind]->max_lev, Players[Ind]->max_plv, max, cur, adv, adv_prev);
4909 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 1, 3, 0, 0))
4910 		return Packet_printf(&connp->c, "%c%hu%hu%hu%d%d%d", PKT_EXPERIENCE, lev, Players[Ind]->max_lev, Players[Ind]->max_plv, max, cur, adv);
4911 	else
4912 		return Packet_printf(&connp->c, "%c%hu%d%d%d", PKT_EXPERIENCE, lev, max, cur, adv);
4913 }
4914 
4915 #if 0
4916 int Send_skill_init(int Ind, int type, int i)
4917 #else
4918 int Send_skill_init(int Ind, u16b i)
4919 #endif
4920 {
4921 	connection_t *connp = Conn[Players[Ind]->conn];
4922 
4923 	char *tmp;
4924 	int mkey;
4925 
4926 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
4927 	{
4928 		errno = 0;
4929 		plog(format("Connection not ready for skill init (%d.%d.%d)",
4930 			Ind, connp->state, connp->id));
4931 		return 0;
4932 	}
4933 
4934 	tmp = s_info[i].action_desc ? s_text + s_info[i].action_desc : "";
4935 	mkey = s_info[i].action_mkey;
4936 
4937 	/* hack for fighting/shooting techniques */
4938 	if (mkey == MKEY_MELEE && Players[Ind]->melee_techniques == 0x0000) mkey = 0;
4939 	if (mkey == MKEY_RANGED && Players[Ind]->ranged_techniques == 0x0000) mkey = 0;
4940 
4941 	/* Note: %hd is 2 bytes - use this for x16b.
4942 	   We can use %c for bytes. */
4943 	return( Packet_printf(&connp->c, "%c%hd%hd%hd%hd%d%c%S%S%S",
4944 		PKT_SKILL_INIT, i,
4945 		s_info[i].father, s_info[i].order, mkey,
4946 		s_info[i].flags1, s_info[i].tval, s_name+s_info[i].name,
4947 		s_text+s_info[i].desc, tmp ? tmp : "" ) );
4948 
4949 }
4950 
4951 int Send_skill_points(int Ind) {
4952 	connection_t *connp = Conn[Players[Ind]->conn];
4953 	player_type *p_ptr = Players[Ind];
4954 
4955 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
4956 	{
4957 		errno = 0;
4958 		plog(format("Connection not ready for skill mod (%d.%d.%d)",
4959 			Ind, connp->state, connp->id));
4960 		return 0;
4961 	}
4962         return Packet_printf(&connp->c, "%c%d", PKT_SKILL_PTS, p_ptr->skill_points);
4963 }
4964 
4965 /* i is skill index, keep means if we want the client to keep his 'deflated?' state */
4966 int Send_skill_info(int Ind, int i, bool keep)
4967 {
4968 	connection_t *connp = Conn[Players[Ind]->conn];
4969 	player_type *p_ptr = Players[Ind];
4970 	int mkey;
4971 
4972 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
4973 	{
4974 		errno = 0;
4975 		plog(format("Connection not ready for skill mod (%d.%d.%d)",
4976 			Ind, connp->state, connp->id));
4977 		return 0;
4978 	}
4979 
4980 	mkey = s_info[i].action_mkey;
4981 	/* hack for fighting/shooting techniques */
4982 	if (mkey == MKEY_MELEE && Players[Ind]->melee_techniques == 0x0000) mkey = 0;
4983 	if (mkey == MKEY_RANGED && Players[Ind]->ranged_techniques == 0x0000) mkey = 0;
4984 
4985 #ifndef ENABLE_DRACONIAN_TRAITS
4986 	if (mkey == MKEY_BREATH) mkey = 0;
4987 #endif
4988 
4989 	if (!is_newer_than(&connp->version, 4, 4, 1, 2, 0, 0))
4990 	        return Packet_printf(&connp->c, "%c%d%d%d%d%d", PKT_SKILL_MOD, i, p_ptr->s_info[i].value, p_ptr->s_info[i].mod, p_ptr->s_info[i].dev, p_ptr->s_info[i].flags1 & SKF1_HIDDEN);
4991 	else if (!is_newer_than(&connp->version, 4, 4, 1, 7, 0, 0)) {
4992 	        return Packet_printf(&connp->c, "%c%d%d%d%d%d%d", PKT_SKILL_MOD, i, p_ptr->s_info[i].value, p_ptr->s_info[i].mod, p_ptr->s_info[i].dev, p_ptr->s_info[i].flags1 & SKF1_HIDDEN, mkey);
4993 	} else if (!is_newer_than(&connp->version, 4, 4, 4, 1, 0, 0)) {
4994 	        return Packet_printf(&connp->c, "%c%d%d%d%d%d%d%d", PKT_SKILL_MOD, i, p_ptr->s_info[i].value, p_ptr->s_info[i].mod, p_ptr->s_info[i].dev, p_ptr->s_info[i].flags1 & SKF1_HIDDEN, mkey, p_ptr->s_info[i].flags1 & SKF1_DUMMY);
4995 	} else if (!is_newer_than(&connp->version, 4, 4, 6, 2, 0, 0)) {
4996 	        return Packet_printf(&connp->c, "%c%d%d%d%d%c%d", PKT_SKILL_MOD, i, p_ptr->s_info[i].value, p_ptr->s_info[i].mod, p_ptr->s_info[i].dev, p_ptr->s_info[i].flags1, mkey);
4997 	} else {
4998 	        return Packet_printf(&connp->c, "%c%d%d%d%d%c%d", PKT_SKILL_MOD, i, p_ptr->s_info[i].value, p_ptr->s_info[i].mod, keep ? -1 : (p_ptr->s_info[i].dev ? 1 : 0), p_ptr->s_info[i].flags1, mkey);
4999 	}
5000 }
5001 
5002 int Send_gold(int Ind, s32b au, s32b balance)
5003 {
5004 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5005 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5006 
5007 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5008 	{
5009 		errno = 0;
5010 		plog(format("Connection not ready for gold (%d.%d.%d)",
5011 			Ind, connp->state, connp->id));
5012 		return 0;
5013 	}
5014 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5015 		connp2 = Conn[p_ptr2->conn];
5016 		Packet_printf(&connp2->c, "%c%d%d", PKT_GOLD, au, balance);
5017 	}
5018 	return Packet_printf(&connp->c, "%c%d%d", PKT_GOLD, au, balance);
5019 }
5020 
5021 #if 0	// well, it's easily cracked by client
5022 int Send_sanity(int Ind, int msane, int csane)
5023 {
5024 #ifdef SHOW_SANITY
5025 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5026 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5027 //	printf("sanity send!\n");
5028 
5029 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5030 	{
5031 		errno = 0;
5032 		plog(format("Connection not ready for hp (%d.%d.%d)",
5033 			Ind, connp->state, connp->id));
5034 		return 0;
5035 	}
5036 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5037 		connp2 = Conn[p_ptr2->conn];
5038 		Packet_printf(&connp2->c, "%c%hd%hd", PKT_SANITY, msane, csane);
5039 	}
5040 	return Packet_printf(&connp->c, "%c%hd%hd", PKT_SANITY, msane, csane);
5041 #endif	// SHOW_SANITY
5042 }
5043 #else	// 0
5044 int Send_sanity(int Ind, byte attr, cptr msg)
5045 {
5046 #ifdef SHOW_SANITY
5047 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5048 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5049 //	printf("sanity send!\n");
5050 
5051 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5052 	{
5053 		errno = 0;
5054 		plog(format("Connection not ready for hp (%d.%d.%d)",
5055 			Ind, connp->state, connp->id));
5056 		return 0;
5057 	}
5058 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5059 		connp2 = Conn[p_ptr2->conn];
5060 		Packet_printf(&connp2->c, "%c%c%s", PKT_SANITY, attr, msg);
5061 	}
5062 	return Packet_printf(&connp->c, "%c%c%s", PKT_SANITY, attr, msg);
5063 #endif	// SHOW_SANITY
5064 }
5065 #endif	// 0
5066 
5067 int Send_hp(int Ind, int mhp, int chp)
5068 {
5069 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5070 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5071 
5072 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5073 	{
5074 		errno = 0;
5075 		plog(format("Connection not ready for hp (%d.%d.%d)",
5076 			Ind, connp->state, connp->id));
5077 		return 0;
5078 	}
5079 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5080 		connp2 = Conn[p_ptr2->conn];
5081 		Packet_printf(&connp2->c, "%c%hd%hd", PKT_HP, mhp, chp);
5082 	}
5083 	return Packet_printf(&connp->c, "%c%hd%hd", PKT_HP, mhp, chp);
5084 }
5085 
5086 int Send_sp(int Ind, int msp, int csp)
5087 {
5088 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5089 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
5090 
5091 #if 1 /* can we use mana at all? */
5092 	if (is_newer_than(&p_ptr->version, 4, 4, 1, 3, 0, 0) &&
5093 	    (p_ptr->pclass == CLASS_WARRIOR || p_ptr->pclass == CLASS_ARCHER)) {
5094 		msp = -9999;
5095 		csp = -9999;
5096 	}
5097 #endif
5098 
5099 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5100 	{
5101 		errno = 0;
5102 		plog(format("Connection not ready for sp (%d.%d.%d)",
5103 			Ind, connp->state, connp->id));
5104 		return 0;
5105 	}
5106 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5107 		connp2 = Conn[p_ptr2->conn];
5108 		Packet_printf(&connp2->c, "%c%hd%hd", PKT_SP, msp, csp);
5109 	}
5110 	return Packet_printf(&connp->c, "%c%hd%hd", PKT_SP, msp, csp);
5111 }
5112 
5113 int Send_stamina(int Ind, int mst, int cst) {
5114 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
5115 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5116 
5117 #ifndef ENABLE_TECHNIQUES
5118  #ifdef ENABLE_DRACONIAN_TRAITS
5119 	/* may breathe elements for stamina */
5120 	if (p_ptr->race != RACE_DRACONIAN)
5121  #endif
5122 	return(0); /* disabled until client can handle it */
5123 #endif
5124 
5125 	if (!is_newer_than(&connp->version, 4, 4, 1, 2, 0, 0)) return(0);
5126 
5127 	/* can we use stamina at all? */
5128 	if (is_newer_than(&p_ptr->version, 4, 4, 1, 3, 0, 0) &&
5129 	    (p_ptr->pclass == CLASS_MAGE || p_ptr->pclass == CLASS_PRIEST ||
5130 	    p_ptr->pclass == CLASS_SHAMAN)
5131 #ifdef ENABLE_DRACONIAN_TRAITS
5132 	    /* may breathe elements for stamina */
5133 	    && p_ptr->prace != RACE_DRACONIAN
5134 #endif
5135 	    ) {
5136 		mst = -9999;
5137 		cst = -9999;
5138 	}
5139 
5140 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5141 		errno = 0;
5142 		plog(format("Connection not ready for hp (%d.%d.%d)",
5143 			Ind, connp->state, connp->id));
5144 		return 0;
5145 	}
5146 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5147 		connp2 = Conn[p_ptr2->conn];
5148 		Packet_printf(&connp2->c, "%c%hd%hd", PKT_STAMINA, mst, cst);
5149 	}
5150 	return Packet_printf(&connp->c, "%c%hd%hd", PKT_STAMINA, mst, cst);
5151 }
5152 
5153 int Send_char_info(int Ind, int race, int class, int trait, int sex, int mode, cptr name) {
5154 	connection_t *connp = Conn[Players[Ind]->conn];
5155 
5156 #ifndef ENABLE_DRACONIAN_TRAITS
5157 	if (race == RACE_DRACONIAN) trait = 0;
5158 #endif
5159 
5160 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5161 		errno = 0;
5162 		plog(format("Connection not ready for char info (%d.%d.%d)",
5163 			Ind, connp->state, connp->id));
5164 		return 0;
5165 	}
5166 
5167 	if (is_newer_than(&connp->version, 4, 5, 2, 0, 0, 0)) {
5168 		return Packet_printf(&connp->c, "%c%hd%hd%hd%hd%hd%s", PKT_CHAR_INFO, race, class, trait, sex, mode, name);
5169 	} else if (is_newer_than(&connp->version, 4, 4, 5, 10, 0, 0)) {
5170 		return Packet_printf(&connp->c, "%c%hd%hd%hd%hd%hd", PKT_CHAR_INFO, race, class, trait, sex, mode);
5171 	} else {
5172 		return Packet_printf(&connp->c, "%c%hd%hd%hd%hd", PKT_CHAR_INFO, race, class, sex, mode);
5173 	}
5174 }
5175 
5176 int Send_various(int Ind, int hgt, int wgt, int age, int sc, cptr body)
5177 {
5178 	connection_t *connp = Conn[Players[Ind]->conn];
5179 
5180 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5181 	{
5182 		errno = 0;
5183 		plog(format("Connection not ready for various (%d.%d.%d)",
5184 			Ind, connp->state, connp->id));
5185 		return 0;
5186 	}
5187 	return Packet_printf(&connp->c, "%c%hu%hu%hu%hu%s", PKT_VARIOUS, hgt, wgt, age, sc, body);
5188 }
5189 
5190 int Send_stat(int Ind, int stat, int max, int cur, int s_ind, int max_base)
5191 {
5192 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5193 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5194 
5195 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5196 	{
5197 		errno = 0;
5198 		plog(format("Connection not ready for stat (%d.%d.%d)",
5199 			Ind, connp->state, connp->id));
5200 		return 0;
5201 	}
5202 
5203 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5204 		connp2 = Conn[p_ptr2->conn];
5205 		Packet_printf(&connp2->c, "%c%c%hd%hd%hd%hd", PKT_STAT, stat, max, cur, s_ind, max_base);
5206 	}
5207 
5208 	return Packet_printf(&connp->c, "%c%c%hd%hd%hd%hd", PKT_STAT, stat, max, cur, s_ind, max_base);
5209 }
5210 
5211 int Send_history(int Ind, int line, cptr hist)
5212 {
5213 	connection_t *connp = Conn[Players[Ind]->conn];
5214 
5215 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5216 	{
5217 		errno = 0;
5218 		plog(format("Connection not ready for history (%d.%d.%d)",
5219 			Ind, connp->state, connp->id));
5220 		return 0;
5221 	}
5222 	return Packet_printf(&connp->c, "%c%hu%s", PKT_HISTORY, line, hist);
5223 }
5224 
5225 /* XXX 'pval' is sent only when the item is TV_BOOK (same with Send_equip)
5226  * otherwise you can use badly-cracked client :)	- Jir -
5227  */
5228 int Send_inven(int Ind, char pos, byte attr, int wgt, object_type *o_ptr, cptr name) {
5229 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5230 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5231 	char uses_dir = 0; /* flag whether a rod requires a direction for zapping or not */
5232 
5233 	/* Mark rods that require a direction */
5234 	if (o_ptr->tval == TV_ROD && rod_requires_direction(Ind, o_ptr))
5235 		uses_dir = 1;
5236 
5237 	/* Mark activatable items that require a direction */
5238 	if (activation_requires_direction(o_ptr)
5239 //appearently not for A'able items >_>	    || !object_aware_p(Ind, o_ptr))
5240 	    ) {
5241 		uses_dir = 1;
5242 	}
5243 
5244 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5245 		errno = 0;
5246 		plog(format("Connection not ready for inven (%d.%d.%d)",
5247 		    Ind, connp->state, connp->id));
5248 		return 0;
5249 	}
5250 
5251 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5252 		connp2 = Conn[p_ptr2->conn];
5253 		if (is_newer_than(&p_ptr2->version, 4, 5, 2, 0, 0, 0))
5254 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%hd%c%I", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, object_known_p(Ind, o_ptr) ? o_ptr->name1 : 0, uses_dir, name);
5255 		else if (is_newer_than(&p_ptr2->version, 4, 4, 5, 10, 0, 0))
5256 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%c%I", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, uses_dir, name);
5257 		else if (is_newer_than(&p_ptr2->version, 4, 4, 4, 2, 0, 0))
5258 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%I", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5259 		else
5260 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%s", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5261 	}
5262 
5263 	if (is_newer_than(&Players[Ind]->version, 4, 5, 2, 0, 0, 0))
5264 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%hd%c%I", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, object_known_p(Ind, o_ptr) ? o_ptr->name1 : 0, uses_dir, name);
5265 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 5, 10, 0, 0))
5266 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%c%I", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, uses_dir, name);
5267 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 4, 2, 0, 0))
5268 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%I", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5269 	else
5270 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%s", PKT_INVEN, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5271 }
5272 
5273 int Send_inven_wide(int Ind, char pos, byte attr, int wgt, object_type *o_ptr, cptr name) {
5274 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5275 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5276 
5277 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5278 		errno = 0;
5279 		plog(format("Connection not ready for inven (%d.%d.%d)",
5280 			Ind, connp->state, connp->id));
5281 		return 0;
5282 	}
5283 
5284 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5285 		connp2 = Conn[p_ptr2->conn];
5286 		if (is_newer_than(&p_ptr2->version, 4, 5, 2, 0, 0, 0))
5287 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%hd%c%c%c%c%c%c%c%c%c%I", PKT_INVEN_WIDE, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval,
5288 			    o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, object_known_p(Ind, o_ptr) ? o_ptr->name1 : 0,
5289 			    o_ptr->xtra1, o_ptr->xtra2, o_ptr->xtra3, o_ptr->xtra4, o_ptr->xtra5, o_ptr->xtra6, o_ptr->xtra7, o_ptr->xtra8, o_ptr->xtra9, name);
5290 		else if (is_newer_than(&p_ptr2->version, 4, 4, 4, 2, 0, 0))
5291 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%c%c%c%c%c%c%c%c%c%I", PKT_INVEN_WIDE, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0,
5292 			    o_ptr->xtra1, o_ptr->xtra2, o_ptr->xtra3, o_ptr->xtra4, o_ptr->xtra5, o_ptr->xtra6, o_ptr->xtra7, o_ptr->xtra8, o_ptr->xtra9, name);
5293 		else
5294 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%c%c%c%c%c%c%c%c%c%s", PKT_INVEN_WIDE, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0,
5295 			    o_ptr->xtra1, o_ptr->xtra2, o_ptr->xtra3, o_ptr->xtra4, o_ptr->xtra5, o_ptr->xtra6, o_ptr->xtra7, o_ptr->xtra8, o_ptr->xtra9, name);
5296 	}
5297 
5298 	if (is_newer_than(&Players[Ind]->version, 4, 5, 2, 0, 0, 0))
5299 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%hd%c%c%c%c%c%c%c%c%c%I", PKT_INVEN_WIDE, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval,
5300 		    o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, object_known_p(Ind, o_ptr) ? o_ptr->name1 : 0,
5301 		    o_ptr->xtra1, o_ptr->xtra2, o_ptr->xtra3, o_ptr->xtra4, o_ptr->xtra5, o_ptr->xtra6, o_ptr->xtra7, o_ptr->xtra8, o_ptr->xtra9, name);
5302 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 4, 2, 0, 0))
5303 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%c%c%c%c%c%c%c%c%c%I", PKT_INVEN_WIDE, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0,
5304 		    o_ptr->xtra1, o_ptr->xtra2, o_ptr->xtra3, o_ptr->xtra4, o_ptr->xtra5, o_ptr->xtra6, o_ptr->xtra7, o_ptr->xtra8, o_ptr->xtra9, name);
5305 	else
5306 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%c%c%c%c%c%c%c%c%c%s", PKT_INVEN_WIDE, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0,
5307 		    o_ptr->xtra1, o_ptr->xtra2, o_ptr->xtra3, o_ptr->xtra4, o_ptr->xtra5, o_ptr->xtra6, o_ptr->xtra7, o_ptr->xtra8, o_ptr->xtra9, name);
5308 }
5309 
5310 //int Send_equip(int Ind, char pos, byte attr, int wgt, byte tval, cptr name)
5311 int Send_equip(int Ind, char pos, byte attr, int wgt, object_type *o_ptr, cptr name) {
5312 	char uses_dir = 0;
5313 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5314 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5315 	int slot = INVEN_WIELD + pos - 'a';
5316 
5317 	/* Mark activatable items that require a direction */
5318 	if (activation_requires_direction(o_ptr)
5319 //appearently not for A'able items >_>	    || !object_aware_p(Ind, o_ptr))
5320 	    ) {
5321 		uses_dir = 1;
5322 	}
5323 
5324 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5325 		errno = 0;
5326 		plog(format("Connection not ready for equip (%d.%d.%d)",
5327 			Ind, connp->state, connp->id));
5328 		return 0;
5329 	}
5330 
5331 	/* for characters in forms that cannot use full equipment */
5332 	if (!item_tester_hook_wear(Ind, slot)) {
5333 		attr = TERM_L_DARK;
5334 		name = "(unavailable)";
5335 	}
5336 	/* hack: display INVEN_ARM slot as unavailable for 2-h weapons */
5337 	else if (slot == INVEN_ARM && Players[Ind]->inventory[INVEN_WIELD].k_idx && (k_info[Players[Ind]->inventory[INVEN_WIELD].k_idx].flags4 & TR4_MUST2H)) {
5338 		attr = TERM_L_DARK;
5339 		//name = "(occupied)";
5340 		name = "-";
5341 	}
5342 
5343 
5344 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5345 		connp2 = Conn[p_ptr2->conn];
5346 		if (is_newer_than(&p_ptr2->version, 4, 5, 2, 0, 0, 0))
5347 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%hd%c%I", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval,
5348 			    o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, object_known_p(Ind, o_ptr) ? o_ptr->name1 : 0, uses_dir, name);
5349 		else if (is_newer_than(&p_ptr2->version, 4, 4, 5, 10, 0, 0))
5350 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%c%I", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, uses_dir, name);
5351 		else if (is_newer_than(&p_ptr2->version, 4, 4, 4, 2, 0, 0))
5352 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%I", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5353 		else
5354 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%s", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5355 	}
5356 
5357 	if (is_newer_than(&Players[Ind]->version, 4, 5, 2, 0, 0, 0))
5358 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%hd%c%I", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval,
5359 		    o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, object_known_p(Ind, o_ptr) ? o_ptr->name1 : 0, uses_dir, name);
5360 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 5, 10, 0, 0))
5361 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%c%I", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, uses_dir, name);
5362 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 4, 2, 0, 0))
5363 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%I", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5364 	else
5365 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%s", PKT_EQUIP, pos, attr, wgt, o_ptr->number, o_ptr->tval, o_ptr->sval, o_ptr->tval == TV_BOOK ? o_ptr->pval : 0, name);
5366 }
5367 
5368 int Send_equip_availability(int Ind, int slot) {
5369 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5370 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5371 
5372 	char pos = 'a' + slot - INVEN_WIELD;
5373 	cptr name = "(nothing)";
5374 	byte attr = TERM_WHITE;
5375 
5376 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5377 		errno = 0;
5378 		plog(format("Connection not ready for equip (%d.%d.%d)",
5379 			Ind, connp->state, connp->id));
5380 		return 0;
5381 	}
5382 
5383 	if (!item_tester_hook_wear(Ind, slot)) {
5384 		attr = TERM_L_DARK;
5385 		name = "(unavailable)";
5386 	}
5387 	/* hack: 2-h weapon disables INVEN_ARM slot */
5388 	else if (slot == INVEN_ARM && Players[Ind]->inventory[INVEN_WIELD].k_idx && (k_info[Players[Ind]->inventory[INVEN_WIELD].k_idx].flags4 & TR4_MUST2H)) {
5389 		attr = TERM_L_DARK;
5390 		//name = "(occupied)";
5391 		name = "-";
5392 	}
5393 
5394 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5395 		connp2 = Conn[p_ptr2->conn];
5396 		if (is_newer_than(&p_ptr2->version, 4, 5, 2, 0, 0, 0))
5397 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%hd%c%I", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, 0, 0, name);
5398 		else if (is_newer_than(&p_ptr2->version, 4, 4, 5, 10, 0, 0))
5399 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%c%I", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, 0, name);
5400 		else if (is_newer_than(&p_ptr2->version, 4, 4, 4, 2, 0, 0))
5401 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%I", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, name);
5402 		else
5403 			Packet_printf(&connp2->c, "%c%c%c%hu%hd%c%c%hd%s", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, name);
5404 	}
5405 
5406 	if (is_newer_than(&Players[Ind]->version, 4, 5, 2, 0, 0, 0))
5407 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%hd%c%I", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, 0, 0, name);
5408 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 5, 10, 0, 0))
5409 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%c%I", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, 0, name);
5410 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 4, 2, 0, 0))
5411 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%I", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, name);
5412 	else
5413 		return Packet_printf(&connp->c, "%c%c%c%hu%hd%c%c%hd%s", PKT_EQUIP, pos, attr, 0, 0, 0, 0, 0, name);
5414 }
5415 
5416 int Send_title(int Ind, cptr title) {
5417 	connection_t *connp = Conn[Players[Ind]->conn];
5418 
5419 
5420 	int Ind2;
5421 	connection_t *connp2;
5422 	player_type *p_ptr2 = NULL;
5423 
5424 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
5425 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2))) {
5426 		connp2 = Conn[p_ptr2->conn];
5427 		Packet_printf(&connp2->c, "%c%s", PKT_TITLE, title);
5428 	}
5429 
5430 
5431 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5432 		errno = 0;
5433 		plog(format("Connection not ready for title (%d.%d.%d)",
5434 			Ind, connp->state, connp->id));
5435 		return 0;
5436 	}
5437 	return Packet_printf(&connp->c, "%c%s", PKT_TITLE, title);
5438 }
5439 
5440 int Send_extra_status(int Ind, cptr status)
5441 {
5442 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5443 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5444 
5445 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5446 	{
5447 		errno = 0;
5448 		plog(format("Connection not ready for extra status (%d.%d.%d)",
5449 			Ind, connp->state, connp->id));
5450 		return 0;
5451 	}
5452 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5453 		connp2 = Conn[p_ptr2->conn];
5454 		Packet_printf(&connp2->c, "%c%s", PKT_EXTRA_STATUS, status);
5455 	}
5456 	return Packet_printf(&connp->c, "%c%s", PKT_EXTRA_STATUS, status);
5457 }
5458 
5459 int Send_depth(int Ind, struct worldpos *wpos) {
5460 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5461 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
5462 	bool ville = istown(wpos) && !isdungeontown(wpos); /* -> print name (TRUE) or a depth value (FALSE)? */
5463 	cptr desc = "", loc_name = "";
5464 	dungeon_type *d_ptr = NULL;
5465 	int colour, colour_sector = TERM_L_GREEN, Ind2;
5466 	cave_type **zcave;
5467 	bool no_tele = FALSE;
5468 	int dlev = getlevel(wpos);
5469 	if ((zcave = getcave(&p_ptr->wpos))) no_tele = (zcave[p_ptr->py][p_ptr->px].info & CAVE_STCK) != 0;
5470 
5471 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
5472 
5473 	if (wpos->wz > 0) d_ptr = wild_info[wpos->wy][wpos->wx].tower;
5474 	else if (wpos->wz < 0) d_ptr = wild_info[wpos->wy][wpos->wx].dungeon;
5475 	if (d_ptr) loc_name = get_dun_name(wpos->wx, wpos->wy, (wpos->wz > 0), d_ptr, 0, TRUE);
5476 
5477 	/* XXX this kinda thing should be done *before* calling Send_*
5478 	 * in general, of course..	- Jir - */
5479 	if (ville) {
5480 		int i;
5481 		for (i = 0; i < numtowns; i++) {
5482 			if (town[i].x == wpos->wx && town[i].y == wpos->wy) {
5483 				desc = town_profile[town[i].type].name;
5484 				break;
5485 			}
5486 		}
5487 	}
5488 
5489 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5490 		errno = 0;
5491 		plog(format("Connection not ready for depth (%d.%d.%d)",
5492 			Ind, connp->state, connp->id));
5493 		return 0;
5494 	}
5495 
5496 	/* Hack for Valinor */
5497 	if (in_valinor(wpos)) {
5498 		ville = TRUE;
5499 		desc = "Valinor";
5500 	}
5501 	/* Hack for PvP Arena */
5502 	else if (wpos->wx == WPOS_PVPARENA_X && wpos->wy == WPOS_PVPARENA_Y && wpos->wz == WPOS_PVPARENA_Z) {
5503 		ville = TRUE;
5504 		desc = "Arena";
5505 	}
5506 #if 0
5507 	/* Hack for Arena Monster Challenge */
5508 	else if (wpos->wx == WPOS_ARENA_X && wpos->wy == WPOS_ARENA_Y && wpos->wz == WPOS_ARENA_Z) {
5509 		ville = TRUE;
5510 		desc = "Arena";
5511 	}
5512 #endif
5513 #ifdef IRONDEEPDIVE_FIXED_TOWNS
5514 	/* Hack for Ironman Deep Dive Challenge static dungeons */
5515 	else if (is_fixed_irondeepdive_town(wpos, dlev)) {
5516 		if (dlev == 40) {
5517 			ville = TRUE;
5518 			desc = "Menegroth";
5519 		} else if (dlev == 80) {
5520 			ville = TRUE;
5521 			desc = "Nargothrond";
5522 		}
5523 	}
5524 #endif
5525 	else if (sector00separation) {
5526 		/* Hack for Dungeon Keeper  */
5527 		if (wpos->wx == WPOS_SECTOR00_X && wpos->wy == WPOS_SECTOR00_Y && wpos->wz == WPOS_SECTOR00_Z
5528 		    && (sector00flags2 & LF2_INDOORS)) {
5529 			ville = TRUE;
5530 			desc = "Old Dungeon";
5531 		}
5532 		/* Hack for Highlander */
5533 		else if (wpos->wx == WPOS_HIGHLANDER_X && wpos->wy == WPOS_HIGHLANDER_Y && wpos->wz == WPOS_HIGHLANDER_Z) {
5534 			ville = TRUE;
5535 			desc = "Highlands";
5536 		}
5537 		/* Hack for Highlander (dungeon) */
5538 		else if (wpos->wx == WPOS_HIGHLANDER_DUN_X && wpos->wy == WPOS_HIGHLANDER_DUN_Y && wpos->wz * WPOS_HIGHLANDER_DUN_Z > 0) {
5539 			ville = TRUE;
5540 			desc = "Underground";
5541 		}
5542 	}
5543 
5544 	if (desc[0]) loc_name = desc;
5545 
5546 	if (is_newer_than(&p_ptr->version, 4, 4, 1, 5, 0, 0)) {
5547 		/* pending recall? */
5548 		if (p_ptr->word_recall) colour = TERM_ORANGE;
5549 		/* use as indicator for pvp_prevent_tele, actually */
5550 		else if ((p_ptr->mode & MODE_PVP) && p_ptr->pvp_prevent_tele) colour = TERM_RED;
5551 		/* use indicator asterisk instead in newer versions */
5552 		else if ((!is_newer_than(&p_ptr->version, 4, 5, 6, 0, 0, 1) || ville) &&
5553 		    /* able to get extra level feeling on next floor? */
5554 		    TURNS_FOR_EXTRA_FEELING && p_ptr->turns_on_floor >= TURNS_FOR_EXTRA_FEELING)
5555 			colour = TERM_L_BLUE;
5556 		/* in a town? ignore town level */
5557 		else if (ville) colour = TERM_WHITE;
5558 		/* way too low to get good exp? */
5559 		else if (dlev < det_req_level(p_ptr->lev) - 5) colour = TERM_L_DARK;
5560 		/* too low to get 100% exp? */
5561 		else if (dlev < det_req_level(p_ptr->lev)) colour = TERM_YELLOW;
5562 		/* normal exp depth or deeper (default) */
5563 		else colour = TERM_WHITE;
5564 	} else {
5565 		colour = p_ptr->word_recall;
5566 	}
5567 	/* able to get extra level feeling on next floor? */
5568 	if (is_newer_than(&p_ptr->version, 4, 5, 6, 0, 0, 1) && !ville &&
5569 	    TURNS_FOR_EXTRA_FEELING && p_ptr->turns_on_floor >= TURNS_FOR_EXTRA_FEELING)
5570 		desc = "*";
5571 
5572 
5573 	if (is_newer_than(&p_ptr->version, 4, 4, 1, 6, 0, 0) && no_tele) {
5574 		Send_cut(Ind, 0); /* hack: clear the field shared between cut and depth */
5575 		colour_sector = TERM_L_DARK;
5576 	}
5577 
5578 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2))) {
5579 		connp2 = Conn[p_ptr2->conn];
5580 		if (is_newer_than(&p_ptr2->version, 4, 5, 9, 0, 0, 0)) {
5581 			if (no_tele) Send_cut(Ind2, 0); /* hack: clear the field shared between cut and depth */
5582 			Packet_printf(&connp2->c, "%c%hu%hu%hu%c%c%c%s%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, ville, colour, colour_sector, desc, loc_name);
5583 		} else if (is_newer_than(&p_ptr2->version, 4, 4, 1, 6, 0, 0)) {
5584 			if (no_tele) Send_cut(Ind2, 0); /* hack: clear the field shared between cut and depth */
5585 			Packet_printf(&connp2->c, "%c%hu%hu%hu%c%c%c%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, ville, colour, colour_sector, desc);
5586 		} else {
5587 			Packet_printf(&connp2->c, "%c%hu%hu%hu%c%hu%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, ville, colour, desc);
5588 		}
5589 	}
5590 
5591 	if (is_newer_than(&p_ptr->version, 4, 5, 9, 0, 0, 0)) {
5592 		return Packet_printf(&connp->c, "%c%hu%hu%hu%c%c%c%s%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, ville, colour, colour_sector, desc, loc_name);
5593 	} else if (is_newer_than(&p_ptr->version, 4, 4, 1, 6, 0, 0)) {
5594 		return Packet_printf(&connp->c, "%c%hu%hu%hu%c%c%c%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, ville, colour, colour_sector, desc);
5595 	} else {
5596 		return Packet_printf(&connp->c, "%c%hu%hu%hu%c%hu%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, ville, colour, desc);
5597 	}
5598 }
5599 
5600 /* (added for Valinor, but now just unused except for debugging purpose: /testdisplay in slash.c)
5601    This allows determining whether we're in a (fake) 'town' or not, and also
5602    the exact (fake) town's name that will be displayed to the player. */
5603 int Send_depth_hack(int Ind, struct worldpos *wpos, bool town, cptr desc)
5604 {
5605 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5606 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
5607 	int colour, colour2, colour_sector = TERM_L_GREEN, colour2_sector = TERM_L_GREEN, Ind2;
5608 	cave_type **zcave;
5609 	bool no_tele = FALSE;
5610 	if ((zcave = getcave(&p_ptr->wpos))) no_tele = (zcave[p_ptr->py][p_ptr->px].info & CAVE_STCK) != 0;
5611 
5612 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5613 	{
5614 		errno = 0;
5615 		plog(format("Connection not ready for depth (%d.%d.%d)",
5616 			Ind, connp->state, connp->id));
5617 		return 0;
5618 	}
5619 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
5620 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2))) {
5621 		connp2 = Conn[p_ptr2->conn];
5622 
5623 		if (is_newer_than(&p_ptr2->version, 4, 4, 1, 5, 0, 0)) {
5624 			/* pending recall? */
5625 			if (p_ptr2->word_recall) colour2 = TERM_ORANGE;
5626 			/* able to get extra level feeling on next floor? */
5627 			else if (TURNS_FOR_EXTRA_FEELING && (p_ptr2->turns_on_floor >= TURNS_FOR_EXTRA_FEELING)) colour2 = TERM_L_BLUE;
5628 			/* in a town? ignore town level */
5629 			else if (town) colour2 = TERM_WHITE;
5630 			/* way too low to get good exp? */
5631 			else if (getlevel(wpos) < det_req_level(p_ptr2->lev) - 5) colour2 = TERM_L_DARK;
5632 			/* too low to get 100% exp? */
5633 			else if (getlevel(wpos) < det_req_level(p_ptr2->lev)) colour2 = TERM_YELLOW;
5634 			/* normal exp depth or deeper (default) */
5635 			else colour2 = TERM_WHITE;
5636 		} else {
5637 			colour2 = p_ptr2->word_recall;
5638 		}
5639 
5640 		if (is_newer_than(&p_ptr2->version, 4, 4, 1, 6, 0, 0)) {
5641 			if (no_tele) {
5642 				Send_cut(Ind2, 0); /* hack: clear the field shared between cut and depth */
5643 				colour2_sector = TERM_L_DARK;
5644 			}
5645 			Packet_printf(&connp2->c, "%c%hu%hu%hu%c%c%c%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, town, colour2, colour2_sector, desc);
5646 		} else {
5647 			Packet_printf(&connp2->c, "%c%hu%hu%hu%c%hu%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, town, colour2, desc);
5648 		}
5649 	}
5650 
5651 	if (is_newer_than(&p_ptr->version, 4, 4, 1, 5, 0, 0)) {
5652 		/* pending recall? */
5653 		if (p_ptr->word_recall) colour = TERM_ORANGE;
5654 		/* able to get extra level feeling on next floor? */
5655 		else if (TURNS_FOR_EXTRA_FEELING && (p_ptr->turns_on_floor >= TURNS_FOR_EXTRA_FEELING)) colour = TERM_L_BLUE;
5656 		/* in a town? ignore town level */
5657 		else if (town) colour = TERM_WHITE;
5658 		/* way too low to get good exp? */
5659 		else if (getlevel(wpos) < det_req_level(p_ptr->lev) - 5) colour = TERM_L_DARK;
5660 		/* too low to get 100% exp? */
5661 		else if (getlevel(wpos) < det_req_level(p_ptr->lev)) colour = TERM_YELLOW;
5662 		/* normal exp depth or deeper (default) */
5663 		else colour = TERM_WHITE;
5664 	} else {
5665 		colour = p_ptr->word_recall;
5666 	}
5667 
5668 	if (is_newer_than(&p_ptr->version, 4, 4, 1, 6, 0, 0)) {
5669 		if (no_tele) {
5670 			Send_cut(Ind, 0); /* hack: clear the field shared between cut and depth */
5671 			colour_sector = TERM_L_DARK;
5672 		}
5673 		return Packet_printf(&connp->c, "%c%hu%hu%hu%c%c%c%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, town, colour, colour_sector, desc);
5674 	} else {
5675 		return Packet_printf(&connp->c, "%c%hu%hu%hu%c%hu%s", PKT_DEPTH, wpos->wx, wpos->wy, wpos->wz, town, p_ptr->word_recall, desc);
5676 	}
5677 }
5678 
5679 int Send_food(int Ind, int food)
5680 {
5681 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5682 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5683 
5684 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5685 	{
5686 		errno = 0;
5687 		plog(format("Connection not ready for food (%d.%d.%d)",
5688 			Ind, connp->state, connp->id));
5689 		return 0;
5690 	}
5691 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5692 		connp2 = Conn[p_ptr2->conn];
5693 		Packet_printf(&connp2->c, "%c%hu", PKT_FOOD, food);
5694 	}
5695 	return Packet_printf(&connp->c, "%c%hu", PKT_FOOD, food);
5696 }
5697 
5698 int Send_blind(int Ind, bool blind)
5699 {
5700 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5701 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5702 
5703 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5704 	{
5705 		errno = 0;
5706 		plog(format("Connection not ready for blind (%d.%d.%d)",
5707 			Ind, connp->state, connp->id));
5708 		return 0;
5709 	}
5710 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5711 		connp2 = Conn[p_ptr2->conn];
5712 		Packet_printf(&connp2->c, "%c%c", PKT_BLIND, blind);
5713 	}
5714 	return Packet_printf(&connp->c, "%c%c", PKT_BLIND, blind);
5715 }
5716 
5717 int Send_confused(int Ind, bool confused)
5718 {
5719 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5720 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5721 
5722 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5723 	{
5724 		errno = 0;
5725 		plog(format("Connection not ready for confusion (%d.%d.%d)",
5726 			Ind, connp->state, connp->id));
5727 		return 0;
5728 	}
5729 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5730 		connp2 = Conn[p_ptr2->conn];
5731 		Packet_printf(&connp2->c, "%c%c", PKT_CONFUSED, confused);
5732 	}
5733 	return Packet_printf(&connp->c, "%c%c", PKT_CONFUSED, confused);
5734 }
5735 
5736 int Send_fear(int Ind, bool fear)
5737 {
5738 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5739 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5740 
5741 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5742 	{
5743 		errno = 0;
5744 		plog(format("Connection not ready for fear (%d.%d.%d)",
5745 			Ind, connp->state, connp->id));
5746 		return 0;
5747 	}
5748 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5749 		connp2 = Conn[p_ptr2->conn];
5750 		Packet_printf(&connp2->c, "%c%c", PKT_FEAR, fear);
5751 	}
5752 	return Packet_printf(&connp->c, "%c%c", PKT_FEAR, fear);
5753 }
5754 
5755 int Send_poison(int Ind, bool poisoned)
5756 {
5757 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5758 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5759 
5760 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5761 	{
5762 		errno = 0;
5763 		plog(format("Connection not ready for poison (%d.%d.%d)",
5764 			Ind, connp->state, connp->id));
5765 		return 0;
5766 	}
5767 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5768 		connp2 = Conn[p_ptr2->conn];
5769 		Packet_printf(&connp2->c, "%c%c", PKT_POISON, poisoned);
5770 	}
5771 	return Packet_printf(&connp->c, "%c%c", PKT_POISON, poisoned);
5772 }
5773 
5774 int Send_state(int Ind, bool paralyzed, bool searching, bool resting)
5775 {
5776 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5777 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
5778 
5779 	/* give 'knocked out' priority over paralysis;
5780 	   give stun priority over search/rest */
5781 	if (is_newer_than(&connp->version, 4, 4, 2, 0, 0, 0) &&
5782 	    (p_ptr->stun > 100 || (!paralyzed && p_ptr->stun))) return 0;
5783 
5784 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5785 	{
5786 		errno = 0;
5787 		plog(format("Connection not ready for state (%d.%d.%d)",
5788 			Ind, connp->state, connp->id));
5789 		return 0;
5790 	}
5791 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5792 		connp2 = Conn[p_ptr2->conn];
5793 		Packet_printf(&connp2->c, "%c%hu%hu%hu", PKT_STATE, paralyzed, searching, resting);
5794 	}
5795 	return Packet_printf(&connp->c, "%c%hu%hu%hu", PKT_STATE, paralyzed, searching, resting);
5796 }
5797 
5798 int Send_speed(int Ind, int speed)
5799 {
5800 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5801 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5802 
5803 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5804 	{
5805 		errno = 0;
5806 		plog(format("Connection not ready for speed (%d.%d.%d)",
5807 			Ind, connp->state, connp->id));
5808 		return 0;
5809 	}
5810 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5811 		connp2 = Conn[p_ptr2->conn];
5812 		Packet_printf(&connp2->c, "%c%hd", PKT_SPEED, speed);
5813 	}
5814 	return Packet_printf(&connp->c, "%c%hd", PKT_SPEED, speed);
5815 }
5816 
5817 int Send_study(int Ind, bool study)
5818 {
5819 	connection_t *connp = Conn[Players[Ind]->conn];
5820 
5821 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5822 	{
5823 		errno = 0;
5824 		plog(format("Connection not ready for study (%d.%d.%d)",
5825 			Ind, connp->state, connp->id));
5826 		return 0;
5827 	}
5828 	return Packet_printf(&connp->c, "%c%c", PKT_STUDY, study);
5829 }
5830 
5831 int Send_bpr(int Ind, byte bpr, byte attr)
5832 {
5833 	int Ind2;
5834 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5835 	player_type *p_ptr2 = NULL;
5836 
5837 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
5838 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2))) {
5839 		connp2 = Conn[p_ptr2->conn];
5840 		Packet_printf(&connp2->c, "%c%c%c", PKT_BPR, bpr, attr);
5841 	}
5842 
5843 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
5844 		errno = 0;
5845 		plog(format("Connection not ready for bpr (%d.%d.%d)",
5846 			Ind, connp->state, connp->id));
5847 		return 0;
5848 	}
5849 	return Packet_printf(&connp->c, "%c%c%c", PKT_BPR, bpr, attr);
5850 }
5851 
5852 int Send_cut(int Ind, int cut)
5853 {
5854 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5855 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5856 
5857 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5858 	{
5859 		errno = 0;
5860 		plog(format("Connection not ready for cut (%d.%d.%d)",
5861 			Ind, connp->state, connp->id));
5862 		return 0;
5863 	}
5864 
5865 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5866 		connp2 = Conn[p_ptr2->conn];
5867 		Packet_printf(&connp2->c, "%c%hu", PKT_CUT, cut);
5868 	}
5869 	return Packet_printf(&connp->c, "%c%hu", PKT_CUT, cut);
5870 }
5871 
5872 int Send_stun(int Ind, int stun)
5873 {
5874 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5875 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
5876 
5877 	/* give 'knocked out' priority over paralysis */
5878 	if (is_newer_than(&connp->version, 4, 4, 2, 0, 0, 0) &&
5879 	    p_ptr->paralyzed && p_ptr->stun <= 100) return 0;
5880 
5881 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5882 	{
5883 		errno = 0;
5884 		plog(format("Connection not ready for stun (%d.%d.%d)",
5885 			Ind, connp->state, connp->id));
5886 		return 0;
5887 	}
5888 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5889 		connp2 = Conn[p_ptr2->conn];
5890 		Packet_printf(&connp2->c, "%c%hu", PKT_STUN, stun);
5891 	}
5892 	return Packet_printf(&connp->c, "%c%hu", PKT_STUN, stun);
5893 }
5894 
5895 int Send_direction(int Ind)
5896 {
5897 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
5898 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
5899 
5900 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5901 	{
5902 		errno = 0;
5903 		plog(format("Connection not ready for direction (%d.%d.%d)",
5904 			Ind, connp->state, connp->id));
5905 		return FALSE;
5906 	}
5907 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
5908 		connp2 = Conn[p_ptr2->conn];
5909 		return Packet_printf(&connp2->c, "%c", PKT_DIRECTION);
5910 	}
5911 	return Packet_printf(&connp->c, "%c", PKT_DIRECTION);
5912 }
5913 
5914 static bool hack_message = FALSE;
5915 
5916 int Send_message(int Ind, cptr msg)
5917 {
5918 	connection_t *connp = Conn[Players[Ind]->conn];
5919 	player_type *p_ptr = Players[Ind];
5920 	char buf[80 +80]; // for +80 see below, at 'Clip end of msg'..
5921 
5922 	if (msg == NULL)
5923 		return 1;
5924 
5925 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5926 	{
5927 		errno = 0;
5928 		plog(format("Connection not ready for message (%d.%d.%d)",
5929 			Ind, connp->state, connp->id));
5930 		return 0;
5931 	}
5932 
5933 	/* Clip end of msg if too long */
5934 // Taking this out for now, since it's ONLY called from msg_print in util.c,
5935 // which already performs checks - C. Blue
5936 // (otherwise, lines with colour codes might be crippled here :| )
5937 //	strncpy(buf, msg, 78);
5938 //	buf[78] = '\0';
5939 	strncpy(buf, msg, 158);
5940 	buf[158] = '\0';
5941 
5942 	if ((!hack_message) && p_ptr->esp_link_type && p_ptr->esp_link && (p_ptr->esp_link_flags & LINKF_MISC))
5943 	  {
5944 	    int Ind2 = find_player(p_ptr->esp_link);
5945 	    player_type *p_ptr2;
5946 	    connection_t *connp2;
5947 
5948 	    if (!Ind2) {
5949 	      hack_message = TRUE;
5950 	      end_mind(Ind, TRUE);
5951 	      hack_message = FALSE;
5952 	    }
5953 	    else
5954 	      {
5955 		p_ptr2 = Players[Ind2];
5956 		connp2 = Conn[p_ptr2->conn];
5957 
5958 		if (!BIT(connp2->state, CONN_PLAYING | CONN_READY))
5959 		  {
5960 		    plog(format("Connection not ready for message (%d.%d.%d)",
5961 				Ind, connp2->state, connp2->id));
5962 		  }
5963 		else Packet_printf(&connp2->c, "%c%S", PKT_MESSAGE, buf);
5964 	      }
5965 	  }
5966 	return Packet_printf(&connp->c, "%c%S", PKT_MESSAGE, buf);
5967 }
5968 
5969 int Send_char(int Ind, int x, int y, byte a, char c)
5970 {
5971         player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
5972 
5973 	if (!BIT(Conn[Players[Ind]->conn]->state, CONN_PLAYING | CONN_READY))
5974 		return 0;
5975 
5976 	if (p_ptr->esp_link_flags & LINKF_VIEW_DEDICATED) return 0;
5977 
5978 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
5979 		if (BIT(Conn[p_ptr2->conn]->state, CONN_PLAYING | CONN_READY))
5980 			Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c%c%c%c", PKT_CHAR, x, y, a, c);
5981 	}
5982 
5983 	return Packet_printf(&Conn[p_ptr->conn]->c, "%c%c%c%c%c", PKT_CHAR, x, y, a, c);
5984 }
5985 
5986 int Send_spell_info(int Ind, int realm, int book, int i, cptr out_val)
5987 {
5988 	connection_t *connp = Conn[Players[Ind]->conn];
5989 	player_type *p_ptr = Players[Ind];
5990 
5991 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
5992 	{
5993 		errno = 0;
5994 		plog(format("Connection not ready for spell info (%d.%d.%d)",
5995 			Ind, connp->state, connp->id));
5996 		return 0;
5997 	}
5998 	return Packet_printf(&connp->c, "%c%d%d%d%hu%hu%hu%s", PKT_SPELL_INFO, p_ptr->innate_spells[0], p_ptr->innate_spells[1], p_ptr->innate_spells[2], realm, book, i, out_val);
5999 }
6000 
6001 /* Implementing fighting/shooting techniques, but maybe using a lua 'school' file would be better instead - C. Blue */
6002 int Send_technique_info(int Ind)
6003 {
6004 #ifndef ENABLE_TECHNIQUES
6005 	return(0); /* disabled until client can handle it */
6006 #endif
6007 	connection_t *connp = Conn[Players[Ind]->conn];
6008 	if (!is_newer_than(&connp->version, 4, 4, 1, 2, 0, 0)) return(0);
6009 
6010 	player_type *p_ptr = Players[Ind];
6011 
6012 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6013 	{
6014 		errno = 0;
6015 		plog(format("Connection not ready for techniques info (%d.%d.%d)",
6016 			Ind, connp->state, connp->id));
6017 		return 0;
6018 	}
6019 	return Packet_printf(&connp->c, "%c%d%d", PKT_TECHNIQUE_INFO, p_ptr->melee_techniques, p_ptr->ranged_techniques);
6020 }
6021 
6022 int Send_item_request(int Ind, signed char tester_hook) { //paranoia @ 'signed' char =-p
6023 	connection_t *connp = Conn[Players[Ind]->conn];
6024 #if 0
6025 	connection_t *connp2;
6026 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6027 #endif
6028 
6029 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6030 		errno = 0;
6031 		plog(format("Connection not ready for item request (%d.%d.%d)",
6032 		    Ind, connp->state, connp->id));
6033 		return 0;
6034 	}
6035 
6036 #if 0 /* what is this needed for, actually? */
6037 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
6038 		connp2 = Conn[p_ptr2->conn];
6039 		if (is_newer_than(&p_ptr2->version, 4, 5, 2, 0, 0, 0))
6040 			Packet_printf(&connp2->c, "%c%c", PKT_ITEM, tester_hook);
6041 		else
6042 			Packet_printf(&connp2->c, "%c", PKT_ITEM);
6043 	}
6044 #endif
6045 
6046 	if (is_newer_than(&Players[Ind]->version, 4, 5, 2, 0, 0, 0))
6047 		return Packet_printf(&connp->c, "%c%c", PKT_ITEM, tester_hook);
6048 	else
6049 		return Packet_printf(&connp->c, "%c", PKT_ITEM);
6050 }
6051 
6052 /* for DISCRETE_SPELL_SYSTEM: DSS_EXPANDED_SCROLLS */
6053 int Send_spell_request(int Ind, int item) {
6054 	connection_t *connp = Conn[Players[Ind]->conn];
6055 
6056 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6057 		errno = 0;
6058 		plog(format("Connection not ready for spell request (%d.%d.%d)",
6059 		    Ind, connp->state, connp->id));
6060 		return 0;
6061 	}
6062 
6063 	return Packet_printf(&connp->c, "%c%d", PKT_SPELL, item);
6064 }
6065 
6066 int Send_flush(int Ind)
6067 {
6068 	connection_t *connp = Conn[Players[Ind]->conn];
6069 	//player_type *p_ptr = Players[Ind];
6070 
6071 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6072 	{
6073 		errno = 0;
6074 		plog(format("Connection not ready for flush (%d.%d.%d)",
6075 			Ind, connp->state, connp->id));
6076 		return 0;
6077 	}
6078 	return Packet_printf(&connp->c, "%c", PKT_FLUSH);
6079 }
6080 
6081 /*
6082  * As an attempt to lower bandwidth requirements, each line is run length
6083  * encoded.  Non-encoded grids are sent as normal, but if a grid is
6084  * repeated at least twice, then bit 0x40 of the attribute is set, and
6085  * the next byte contains the number of repetitions of the previous grid.
6086  */
6087 int Send_line_info(int Ind, int y)
6088 {
6089 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
6090 	connection_t *connp = Conn[p_ptr->conn];
6091 	int x, x1, n;
6092 	char c;
6093 	byte a;
6094 	int Ind2 = 0;
6095 #ifdef EXTENDED_TERM_COLOURS
6096 	bool old_colours = is_older_than(&p_ptr->version, 4, 5, 1, 2, 0, 0);
6097 	int a_c;
6098 #endif
6099 
6100 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6101 	{
6102 		errno = 0;
6103 		plog(format("Connection not ready for line info (%d.%d.%d)",
6104 			Ind, connp->state, connp->id));
6105 		return 0;
6106 	}
6107 
6108 	if (p_ptr->esp_link_flags & LINKF_VIEW_DEDICATED) return 0; /* bad hack for shortcut */
6109 //	if (p_ptr->esp_link && p_ptr->esp_link_type && (p_ptr->esp_link_flags & LINKF_VIEW_DEDICATED)) return 0;
6110 
6111 	Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2);
6112 
6113 	/* Put a header on the packet */
6114 	Packet_printf(&connp->c, "%c%hd", PKT_LINE_INFO, y);
6115 	if (Ind2) Packet_printf(&(Conn[p_ptr2->conn]->c), "%c%hd", PKT_LINE_INFO, y);
6116 
6117 	/* Each column */
6118 	for (x = 0; x < 80; x++)
6119 	{
6120 		/* Obtain the char/attr pair */
6121 		c = p_ptr->scr_info[y][x].c;
6122 		a = p_ptr->scr_info[y][x].a;
6123 
6124 #ifdef EXTENDED_TERM_COLOURS
6125 		if (old_colours) {
6126 		    a_c = a & ~(TERM_BNW | TERM_PVP);
6127 		    if (a_c == 29 || a_c == 30 || a_c >= 32)
6128 			a = TERM_WHITE; /* use white to indicate that client needs updating */
6129 		}
6130 #endif
6131 
6132 		/* Start looking here */
6133 		x1 = x + 1;
6134 
6135 		/* Start with count of 1 */
6136 		n = 1;
6137 
6138 		/* Count repetitions of this grid */
6139 		while (p_ptr->scr_info[y][x1].c == c &&
6140 			p_ptr->scr_info[y][x1].a == a && x1 < 80) //TODO (EXTENDED_TERM_COLOURS): the scr_info.a should also be changed to TERM_WHITE if client is old, but it doesn't matter.
6141 		{
6142 			/* Increment count and column */
6143 			n++;
6144 			x1++;
6145 		}
6146 
6147 		/* RLE if there at least 2 similar grids in a row */
6148 		if (n >= 2)
6149 		{
6150 			/* 4.4.3.1 clients support new RLE */
6151 			if (is_newer_than(&connp->version, 4, 4, 3, 0, 0, 5))
6152 			{
6153 				/* New RLE */
6154 				Packet_printf(&connp->c, "%c%c%c%c", c, 0xFF, a, n);
6155 			}
6156 			else
6157 			{
6158 				/* Old RLE */
6159 				Packet_printf(&connp->c, "%c%c%c", c, a | 0x40, n);
6160 			}
6161 
6162 			if (Ind2)
6163 			{
6164 				/* 4.4.3.1 clients support new RLE */
6165 				if (is_newer_than(&Conn[p_ptr2->conn]->version, 4, 4, 3, 0, 0, 5))
6166 				{
6167 					/* New RLE */
6168 					Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c%c%c", c, 0xFF, a, n);
6169 				}
6170 				else {
6171 					/* Old RLE */
6172 					Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c%c", c, a | 0x40, n);
6173 				}
6174 			}
6175 
6176 			/* Start again after the run */
6177 			x = x1 - 1;
6178 		}
6179 		else
6180 		{
6181 			/* Normal, single grid */
6182 			if (!is_newer_than(&connp->version, 4, 4, 3, 0, 0, 5)) {
6183 				/* Remove 0x40 (TERM_PVP) if the client is old */
6184 				Packet_printf(&connp->c, "%c%c", c, a & ~0xC0);
6185 			}
6186 			else
6187 			{
6188 				if (a == 0xFF)
6189 				{
6190 					/* Use RLE format as an escape sequence for 0xFF as attr */
6191 					Packet_printf(&connp->c, "%c%c%c%c", c, 0xFF, a, 1);
6192 				}
6193 				else
6194 				{
6195 					/* Normal output */
6196 					Packet_printf(&connp->c, "%c%c", c, a);
6197 				}
6198 			}
6199 
6200 			if (Ind2)
6201 			{
6202 				if (!is_newer_than(&Conn[p_ptr2->conn]->version, 4, 4, 3, 0, 0, 5)) {
6203 					/* Remove 0x40 (TERM_PVP) if the client is old */
6204 					Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c", c, a & ~0xC0);
6205 				}
6206 				else
6207 				{
6208 					if (a == 0xFF)
6209 					{
6210 						/* Use RLE format as an escape sequence for 0xFF as attr */
6211 						Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c%c%c", c, 0xFF, a, 1);
6212 					}
6213 					else
6214 					{
6215 						/* Normal output */
6216 						Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c", c, a);
6217 					}
6218 				}
6219 			}
6220 		}
6221 	}
6222 
6223 	/* Hack -- Prevent buffer overruns by flushing after each line sent */
6224 	/* Send_reliable(Players[Ind]->conn); */
6225 
6226 	return 1;
6227 }
6228 
6229 int Send_mini_map(int Ind, int y, byte *sa, char *sc)
6230 {
6231 	player_type *p_ptr = Players[Ind];
6232 	connection_t *connp = Conn[p_ptr->conn];
6233 	int x, x1, n;
6234 	char c;
6235 	byte a;
6236 
6237 	int Ind2 = 0;
6238 	player_type *p_ptr2 = NULL;
6239 	connection_t *connp2 = NULL;
6240 
6241 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6242 	{
6243 		errno = 0;
6244 		plog(format("Connection not ready for minimap (%d.%d.%d)",
6245 			Ind, connp->state, connp->id));
6246 		return 0;
6247 	}
6248 
6249 	if (p_ptr->esp_link_flags & LINKF_VIEW_DEDICATED) return 0;
6250 
6251 	/* Sending this packet to a mind-linked person is bad - mikaelh */
6252 #if 0
6253 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2)))
6254 		connp2 = Conn[p_ptr2->conn];
6255 #endif
6256 
6257 	/* Packet header */
6258 	Packet_printf(&connp->c, "%c%hd", PKT_MINI_MAP, y);
6259      	if (Ind2) Packet_printf(&connp2->c, "%c%hd", PKT_MINI_MAP, y);
6260 
6261 	/* Each column */
6262 	for (x = 0; x < 80; x++)
6263 	{
6264 		/* Obtain the char/attr pair */
6265 		c = sc[x];
6266 		a = sa[x];
6267 
6268 		/* Start looking here */
6269 		x1 = x + 1;
6270 
6271 		/* Start with count of 1 */
6272 		n = 1;
6273 
6274 		/* Count repetitions of this grid */
6275 		while (x1 < 80 && sc[x1] == c && sa[x1] == a)
6276 		{
6277 			/* Increment count and column */
6278 			n++;
6279 			x1++;
6280 		}
6281 
6282 		/* RLE if there at least 2 similar grids in a row */
6283 		if (n >= 2)
6284 		{
6285 			/* 4.4.3.1 clients support new RLE */
6286 			if (is_newer_than(&connp->version, 4, 4, 3, 0, 0, 5))
6287 			{
6288 				/* New RLE */
6289 				Packet_printf(&connp->c, "%c%c%c%c", c, 0xFF, a, n);
6290 			}
6291 			else
6292 			{
6293 				/* Old RLE */
6294 				Packet_printf(&connp->c, "%c%c%c", c, a | 0x40, n);
6295 			}
6296 
6297 			if (Ind2)
6298 			{
6299 				/* 4.4.3.1 clients support new RLE */
6300 				if (is_newer_than(&Conn[p_ptr2->conn]->version, 4, 4, 3, 0, 0, 5))
6301 				{
6302 					/* New RLE */
6303 					Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c%c%c", c, 0xFF, a, n);
6304 				}
6305 				else {
6306 					/* Old RLE */
6307 					Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c%c", c, a | 0x40, n);
6308 				}
6309 			}
6310 
6311 			/* Start again after the run */
6312 			x = x1 - 1;
6313 		}
6314 		else
6315 		{
6316 			/* Normal, single grid */
6317 			if (!is_newer_than(&connp->version, 4, 4, 3, 0, 0, 5)) {
6318 				/* Remove 0x40 (TERM_PVP) if the client is old */
6319 				Packet_printf(&connp->c, "%c%c", c, a & ~0xD0);
6320 			}
6321 			else
6322 			{
6323 				if (a == 0xFF)
6324 				{
6325 					/* Use RLE format as an escape sequence for 0xFF as attr */
6326 					Packet_printf(&connp->c, "%c%c%c%c", c, 0xFF, a, 1);
6327 				}
6328 				else
6329 				{
6330 					/* Normal output */
6331 					Packet_printf(&connp->c, "%c%c", c, a);
6332 				}
6333 			}
6334 
6335 			if (Ind2)
6336 			{
6337 				if (!is_newer_than(&Conn[p_ptr2->conn]->version, 4, 4, 3, 0, 0, 5)) {
6338 					/* Remove 0x40 (TERM_PVP) if the client is old */
6339 					Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c", c, a & ~0xD0);
6340 				}
6341 				else
6342 				{
6343 					if (a == 0xFF)
6344 					{
6345 						/* Use RLE format as an escape sequence for 0xFF as attr */
6346 						Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c%c%c", c, 0xFF, a, 1);
6347 					}
6348 					else
6349 					{
6350 						/* Normal output */
6351 						Packet_printf(&Conn[p_ptr2->conn]->c, "%c%c", c, a);
6352 					}
6353 				}
6354 			}
6355 		}
6356 	}
6357 
6358 	/* Hack -- Prevent buffer overruns by flushing after each line sent */
6359 	/* Send_reliable(Players[Ind]->conn); */
6360 
6361 	return 1;
6362 }
6363 
6364 int Send_mini_map_pos(int Ind, int x, int y, byte a, char c) {
6365 	player_type *p_ptr = Players[Ind];
6366 	connection_t *connp = Conn[p_ptr->conn];
6367 	short int xs = (short int)x, ys = (short int)y; //note: this isn't required, can just use x and y instead
6368 
6369 	//int Ind2 = 0;
6370 	//player_type *p_ptr2 = NULL;
6371 	//connection_t *connp2 = NULL;
6372 
6373 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6374 		errno = 0;
6375 		plog(format("Connection not ready for minimap_pos (%d.%d.%d)",
6376 			Ind, connp->state, connp->id));
6377 		return 0;
6378 	}
6379 
6380 	if (p_ptr->esp_link_flags & LINKF_VIEW_DEDICATED) return 0;
6381 
6382 	/* Sending this packet to a mind-linked person is bad - mikaelh */
6383 #if 0
6384 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2)))
6385 		connp2 = Conn[p_ptr2->conn];
6386 #endif
6387 
6388 	/* Packet header */
6389 	if (is_newer_than(&p_ptr->version, 4, 5, 5, 0, 0, 0)) Packet_printf(&connp->c, "%c%hd%hd%c%c", PKT_MINI_MAP_POS, xs, ys, a, c);
6390 	//if (Ind2 && is_newer_than(&p_ptr2->version, 4, 5, 5, 0, 0, 0)) Packet_printf(&connp2->c, "%c%hd%hd%c%c", PKT_MINI_MAP_POS, xs, ys, a, c);
6391 
6392 	return 1;
6393 }
6394 
6395 //int Send_store(int Ind, char pos, byte attr, int wgt, int number, int price, cptr name)
6396 int Send_store(int Ind, char pos, byte attr, int wgt, int number, int price, cptr name, char tval, char sval, s16b pval)
6397 {
6398 	connection_t *connp = Conn[Players[Ind]->conn];
6399 #ifdef MINDLINK_STORE
6400 	connection_t *connp2;
6401 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6402 
6403 #endif
6404 
6405 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6406 	{
6407 		errno = 0;
6408 		plog(format("Connection not ready for store item (%d.%d.%d)",
6409 			Ind, connp->state, connp->id));
6410 		return 0;
6411 	}
6412 
6413 	/* don't segfault old clients which use STORE_INVEN_MAX = 48 */
6414 	if (pos >= 48 && is_older_than(&Players[Ind]->version, 4, 4, 9, 0, 0, 0)) return 0;
6415 
6416 	/* Hack -- send pval only if it's School book */
6417 	if (tval != TV_BOOK) pval = 0;
6418 
6419 #ifdef MINDLINK_STORE
6420 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6421 		connp2 = Conn[p_ptr2->conn];
6422 		if (is_newer_than(&p_ptr2->version, 4, 4, 7, 0, 0, 0))
6423 			Packet_printf(&connp2->c, "%c%c%c%hd%hd%d%S%c%c%hd", PKT_STORE, pos, attr, wgt, number, price, name, tval, sval, pval);
6424 		else
6425 			Packet_printf(&connp2->c, "%c%c%c%hd%hd%d%s%c%c%hd", PKT_STORE, pos, attr, wgt, number, price, name, tval, sval, pval);
6426 	}
6427 #endif
6428 
6429 	if (is_newer_than(&Players[Ind]->version, 4, 4, 7, 0, 0, 0))
6430 		return Packet_printf(&connp->c, "%c%c%c%hd%hd%d%S%c%c%hd", PKT_STORE, pos, attr, wgt, number, price, name, tval, sval, pval);
6431 	else
6432 		return Packet_printf(&connp->c, "%c%c%c%hd%hd%d%s%c%c%hd", PKT_STORE, pos, attr, wgt, number, price, name, tval, sval, pval);
6433 }
6434 
6435 /* Send_store() variant for custom spellbooks */
6436 int Send_store_wide(int Ind, char pos, byte attr, int wgt, int number, int price, cptr name, char tval, char sval, s16b pval,
6437     byte xtra1, byte xtra2, byte xtra3, byte xtra4, byte xtra5, byte xtra6, byte xtra7, byte xtra8, byte xtra9)
6438 {
6439 	connection_t *connp = Conn[Players[Ind]->conn];
6440 #ifdef MINDLINK_STORE
6441 	connection_t *connp2;
6442 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6443 
6444 #endif
6445 
6446 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6447 	{
6448 		errno = 0;
6449 		plog(format("Connection not ready for store item (%d.%d.%d)",
6450 			Ind, connp->state, connp->id));
6451 		return 0;
6452 	}
6453 
6454 	/* don't segfault old clients which use STORE_INVEN_MAX = 48 */
6455 	if (pos >= 48 && is_older_than(&Players[Ind]->version, 4, 4, 9, 0, 0, 0)) return 0;
6456 
6457 	/* Hack -- send pval only if it's School book */
6458 	if (tval != TV_BOOK) pval = 0;
6459 
6460 #ifdef MINDLINK_STORE
6461 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6462 		connp2 = Conn[p_ptr2->conn];
6463 		if (is_newer_than(&p_ptr2->version, 4, 4, 7, 0, 0, 0))
6464 			Packet_printf(&connp2->c, "%c%c%c%hd%hd%d%S%c%c%hd%c%c%c%c%c%c%c%c%c", PKT_STORE_WIDE, pos, attr, wgt, number, price, name, tval, sval, pval, xtra1, xtra2, xtra3, xtra4, xtra5, xtra6, xtra7, xtra8, xtra9);
6465 		else
6466 			Packet_printf(&connp2->c, "%c%c%c%hd%hd%d%s%c%c%hd%c%c%c%c%c%c%c%c%c", PKT_STORE_WIDE, pos, attr, wgt, number, price, name, tval, sval, pval, xtra1, xtra2, xtra3, xtra4, xtra5, xtra6, xtra7, xtra8, xtra9);
6467 	}
6468 #endif
6469 
6470 	if (is_newer_than(&Players[Ind]->version, 4, 4, 7, 0, 0, 0))
6471 		return Packet_printf(&connp->c, "%c%c%c%hd%hd%d%S%c%c%hd%c%c%c%c%c%c%c%c%c", PKT_STORE_WIDE, pos, attr, wgt, number, price, name, tval, sval, pval, xtra1, xtra2, xtra3, xtra4, xtra5, xtra6, xtra7, xtra8, xtra9);
6472 	else
6473 		return Packet_printf(&connp->c, "%c%c%c%hd%hd%d%s%c%c%hd%c%c%c%c%c%c%c%c%c", PKT_STORE_WIDE, pos, attr, wgt, number, price, name, tval, sval, pval, xtra1, xtra2, xtra3, xtra4, xtra5, xtra6, xtra7, xtra8, xtra9);
6474 }
6475 
6476 /* For new non-shop stores (SPECIAL flag) - C. Blue */
6477 int Send_store_special_str(int Ind, char line, char col, char attr, char *str) {
6478 	connection_t *connp = Conn[Players[Ind]->conn];
6479 #ifdef MINDLINK_STORE
6480 	connection_t *connp2;
6481 	player_type *p_ptr2 = NULL;
6482 #endif
6483 
6484 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return 0;
6485 
6486 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6487 		errno = 0;
6488 		plog(format("Connection not ready for store item (%d.%d.%d)",
6489 		    Ind, connp->state, connp->id));
6490 		return 0;
6491 	}
6492 
6493 #ifdef MINDLINK_STORE
6494 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6495 		connp2 = Conn[p_ptr2->conn];
6496 		if (is_newer_than(&connp2->version, 4, 4, 6, 1, 0, 0))
6497 			Packet_printf(&connp2->c, "%c%c%c%c%s", PKT_STORE_SPECIAL_STR, line, col, attr, str);
6498 	}
6499 #endif
6500 
6501 	return Packet_printf(&connp->c, "%c%c%c%c%s", PKT_STORE_SPECIAL_STR, line, col, attr, str);
6502 }
6503 
6504 /* For new non-shop stores (SPECIAL flag) - C. Blue */
6505 int Send_store_special_char(int Ind, char line, char col, char attr, char c) {
6506 	connection_t *connp = Conn[Players[Ind]->conn];
6507 #ifdef MINDLINK_STORE
6508 	connection_t *connp2;
6509 	player_type *p_ptr2 = NULL;
6510 #endif
6511 
6512 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return 0;
6513 
6514 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6515 		errno = 0;
6516 		plog(format("Connection not ready for store item (%d.%d.%d)",
6517 		    Ind, connp->state, connp->id));
6518 		return 0;
6519 	}
6520 
6521 #ifdef MINDLINK_STORE
6522 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6523 		connp2 = Conn[p_ptr2->conn];
6524 		if (is_newer_than(&connp2->version, 4, 4, 6, 1, 0, 0))
6525 			Packet_printf(&connp2->c, "%c%c%c%c%c", PKT_STORE_SPECIAL_CHAR, line, col, attr, c);
6526 	}
6527 #endif
6528 
6529 	return Packet_printf(&connp->c, "%c%c%c%c%c", PKT_STORE_SPECIAL_CHAR, line, col, attr, c);
6530 }
6531 
6532 /* For new non-shop stores (SPECIAL flag) - C. Blue */
6533 int Send_store_special_clr(int Ind, char line_start, char line_end) {
6534 	connection_t *connp = Conn[Players[Ind]->conn];
6535 #ifdef MINDLINK_STORE
6536 	connection_t *connp2;
6537 	player_type *p_ptr2 = NULL;
6538 #endif
6539 
6540 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return 0;
6541 
6542 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6543 		errno = 0;
6544 		plog(format("Connection not ready for store item (%d.%d.%d)",
6545 		    Ind, connp->state, connp->id));
6546 		return 0;
6547 	}
6548 
6549 #ifdef MINDLINK_STORE
6550 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6551 		connp2 = Conn[p_ptr2->conn];
6552 		if (is_newer_than(&connp2->version, 4, 4, 6, 1, 0, 0))
6553 			Packet_printf(&connp2->c, "%c%c%c", PKT_STORE_SPECIAL_CLR, line_start, line_end);
6554 	}
6555 #endif
6556 
6557 	return Packet_printf(&connp->c, "%c%c%c", PKT_STORE_SPECIAL_CLR, line_start, line_end);
6558 }
6559 
6560 /*
6561  * This function is supposed to handle 'store actions' too,
6562  * like 'buy' 'identify' 'heal' 'bid to an auction'		- Jir -
6563  */
6564 int Send_store_info(int Ind, int num, cptr store, cptr owner, int items, int purse, byte attr, char c)
6565 {
6566 	connection_t *connp = Conn[Players[Ind]->conn];
6567 #ifdef MINDLINK_STORE
6568 	connection_t *connp2;
6569 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6570 #endif
6571 
6572 	/* don't segfault old clients which use STORE_INVEN_MAX = 48 */
6573 	if (is_older_than(&Players[Ind]->version, 4, 4, 9, 0, 0, 0)) {
6574 		if (items > 48) items = 48;
6575 		if ((num == STORE_HOME || num == STORE_HOME_DUN)
6576 		    && purse > 48) purse = 48;
6577 	}
6578 
6579 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6580 	{
6581 		errno = 0;
6582 		plog(format("Connection not ready for store info (%d.%d.%d)",
6583 		    Ind, connp->state, connp->id));
6584 		return 0;
6585 	}
6586 
6587 #ifdef MINDLINK_STORE
6588 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6589 		connp2 = Conn[p_ptr2->conn];
6590 		if (is_newer_than(&connp2->version, 4, 4, 4, 0, 0, 0)) {
6591 			Packet_printf(&connp2->c, "%c%hd%s%s%hd%d%c%c", PKT_STORE_INFO, num, store, owner, items, purse, attr, c);
6592 		} else {
6593 			Packet_printf(&connp2->c, "%c%hd%s%s%hd%d", PKT_STORE_INFO, num, store, owner, items, purse);
6594 		}
6595 	}
6596 #endif
6597 
6598 	if (is_newer_than(&connp->version, 4, 4, 4, 0, 0, 0)) {
6599 		return Packet_printf(&connp->c, "%c%hd%s%s%hd%d%c%c", PKT_STORE_INFO, num, store, owner, items, purse, attr, c);
6600 	} else {
6601 		return Packet_printf(&connp->c, "%c%hd%s%s%hd%d", PKT_STORE_INFO, num, store, owner, items, purse);
6602 	}
6603 }
6604 
6605 int Send_store_action(int Ind, char pos, u16b bact, u16b action, cptr name, char attr, char letter, s16b cost, byte flag)
6606 {
6607 	connection_t *connp = Conn[Players[Ind]->conn];
6608 #ifdef MINDLINK_STORE
6609 	connection_t *connp2;
6610 	player_type *p_ptr = Players[Ind], *p_ptr2;
6611 #endif
6612 
6613 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6614 	{
6615 		errno = 0;
6616 		plog(format("Connection not ready for store info (%d.%d.%d)",
6617 		    Ind, connp->state, connp->id));
6618 		return 0;
6619 	}
6620 
6621 #ifdef MINDLINK_STORE
6622 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6623 		connp2 = Conn[p_ptr2->conn];
6624 		Packet_printf(&connp2->c, "%c%c%hd%hd%s%c%c%hd%c", PKT_BACT, pos, bact, action, name, attr, letter, cost, flag);
6625 	}
6626 #endif
6627 
6628 	return Packet_printf(&connp->c, "%c%c%hd%hd%s%c%c%hd%c", PKT_BACT, pos, bact, action, name, attr, letter, cost, flag);
6629 }
6630 
6631 int Send_store_sell(int Ind, int price)
6632 {
6633 	connection_t *connp = Conn[Players[Ind]->conn];
6634 #ifdef MINDLINK_STORE
6635 	connection_t *connp2;
6636 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6637 #endif
6638 
6639 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6640 	{
6641 		errno = 0;
6642 		plog(format("Connection not ready for sell price (%d.%d.%d)",
6643 		    Ind, connp->state, connp->id));
6644 		return 0;
6645 	}
6646 
6647 #ifdef MINDLINK_STORE
6648 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6649 		connp2 = Conn[p_ptr2->conn];
6650 		Packet_printf(&connp2->c, "%c%d", PKT_SELL, price);
6651 	}
6652 #endif
6653 
6654 	return Packet_printf(&connp->c, "%c%d", PKT_SELL, price);
6655 }
6656 
6657 int Send_store_kick(int Ind)
6658 {
6659 	connection_t *connp = Conn[Players[Ind]->conn];
6660 #ifdef MINDLINK_STORE
6661 	connection_t *connp2;
6662 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6663 #endif
6664 
6665 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6666 	{
6667 		errno = 0;
6668 		plog(format("Connection not ready for store_kick (%d.%d.%d)",
6669 			Ind, connp->state, connp->id));
6670 		return 0;
6671 	}
6672 
6673 #ifdef MINDLINK_STORE
6674 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) {
6675 		connp2 = Conn[p_ptr2->conn];
6676 		Packet_printf(&connp2->c, "%c", PKT_STORE_LEAVE);
6677 	}
6678 #endif
6679 
6680 	return Packet_printf(&connp->c, "%c", PKT_STORE_LEAVE);
6681 }
6682 
6683 int Send_target_info(int Ind, int x, int y, cptr str)
6684 {
6685 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
6686 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6687 	char buf[80];
6688 
6689 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
6690 	{
6691 		errno = 0;
6692 		plog(format("Connection not ready for target info (%d.%d.%d)",
6693 			Ind, connp->state, connp->id));
6694 		return 0;
6695 	}
6696 
6697 	/* Copy */
6698 	strncpy(buf, str, 80 - 1);
6699 	/* Paranoia -- Add null */
6700 	buf[80 - 1] = '\0';
6701 
6702 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
6703 		connp2 = Conn[p_ptr2->conn];
6704 		Packet_printf(&connp2->c, "%c%c%c%s", PKT_TARGET_INFO, x, y, buf);
6705 	}
6706 	return Packet_printf(&connp->c, "%c%c%c%s", PKT_TARGET_INFO, x, y, buf);
6707 }
6708 /* type is for client-side, regarding efficiency options;
6709    vol is the relative volume, if it stems from a source nearby instead of concerning the player directly;
6710    player_id is the player it actually concerns; - C. Blue */
6711 int Send_sound(int Ind, int sound, int alternative, int type, int vol, s32b player_id) {
6712 	connection_t *connp = Conn[Players[Ind]->conn];
6713 
6714 	/* Mind-linked to someone? Send him our sound too! */
6715 	player_type *p_ptr2 = NULL;
6716 	connection_t *connp2 = NULL;
6717 	/* If we're the target, we still hear our own sounds! */
6718 //	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) ;//nothing
6719 	/* Get target player */
6720 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) connp2 = Conn[p_ptr2->conn];
6721 	/* Send same info to target player, if available */
6722 	if (connp2) {
6723 		if (is_newer_than(&connp2->version, 4, 4, 5, 3, 0, 0))
6724 			Packet_printf(&connp2->c, "%c%d%d%d%d%d", PKT_SOUND, sound, alternative, type, vol, player_id);
6725 		else if (is_newer_than(&connp2->version, 4, 4, 5, 1, 0, 0))
6726 			Packet_printf(&connp2->c, "%c%d%d%d", PKT_SOUND, sound, alternative, type);
6727 		else if (is_newer_than(&connp2->version, 4, 4, 5, 0, 0, 0))
6728 			Packet_printf(&connp2->c, "%c%d%d", PKT_SOUND, sound, alternative);
6729 		else
6730 			Packet_printf(&connp2->c, "%c%c", PKT_SOUND, sound);
6731 	}
6732 
6733 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6734 		errno = 0;
6735 		plog(format("Connection not ready for sound (%d.%d.%d)",
6736 			Ind, connp->state, connp->id));
6737 		return 0;
6738 	}
6739 
6740 //	if (is_admin(Players[Ind])) s_printf("USE_SOUND_2010: sound %d (alt %d) sent to player %s (%d).\n", sound, alternative, Players[Ind]->name, Ind);//debug
6741 
6742 	if (is_newer_than(&connp->version, 4, 4, 5, 3, 0, 0)) {
6743 		return Packet_printf(&connp->c, "%c%d%d%d%d%d", PKT_SOUND, sound, alternative, type, vol, player_id);
6744 	} else if (is_newer_than(&connp->version, 4, 4, 5, 1, 0, 0)) {
6745 		return Packet_printf(&connp->c, "%c%d%d%d", PKT_SOUND, sound, alternative, type);
6746 	} else if (is_newer_than(&connp->version, 4, 4, 4, 5, 0, 0)) {
6747 		return Packet_printf(&connp->c, "%c%d%d", PKT_SOUND, sound, alternative);
6748 	} else {
6749 		return Packet_printf(&connp->c, "%c%c", PKT_SOUND, sound);
6750 	}
6751 }
6752 
6753 #ifdef USE_SOUND_2010
6754 int Send_music(int Ind, int music, int musicalt) {
6755 	connection_t *connp = Conn[Players[Ind]->conn];
6756 
6757 	/* Mind-linked to someone? Send him our music too! */
6758 	player_type *p_ptr2 = NULL;
6759 	connection_t *connp2 = NULL;
6760 	/* If we're the target, we won't hear our own music */
6761 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
6762 	/* Get target player */
6763 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) connp2 = Conn[p_ptr2->conn];
6764 	/* Send same info to target player, if available */
6765 	if (connp2) {
6766 		if (p_ptr2->music_current != music) {
6767 			p_ptr2->music_current = music;
6768 			p_ptr2->musicalt_current = musicalt;
6769 			if (is_newer_than(&connp2->version, 4, 5, 6, 0, 0, 1))
6770 				Packet_printf(&connp2->c, "%c%c%c", PKT_MUSIC, music, musicalt);
6771 			else if (is_newer_than(&connp2->version, 4, 4, 4, 5, 0, 0))
6772 				Packet_printf(&connp2->c, "%c%c", PKT_MUSIC, music);
6773 		}
6774 	}
6775 
6776 	if (Players[Ind]->music_current == music) return(-1);
6777 	Players[Ind]->music_current = music;
6778 	Players[Ind]->musicalt_current = musicalt;
6779 
6780 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6781 		errno = 0;
6782 		plog(format("Connection not ready for music (%d.%d.%d)",
6783 			Ind, connp->state, connp->id));
6784 		return 0;
6785 	}
6786 
6787 	if (is_newer_than(&connp->version, 4, 5, 6, 0, 0, 1))
6788 		return Packet_printf(&connp->c, "%c%c%c", PKT_MUSIC, music, musicalt);
6789 	else if (!is_newer_than(&connp->version, 4, 4, 4, 5, 0, 0))
6790 		return(-1);
6791 //	s_printf("USE_SOUND_2010: music %d sent to player %s (%d).\n", music, Players[Ind]->name, Ind);//debug
6792 	return Packet_printf(&connp->c, "%c%c", PKT_MUSIC, music);
6793 }
6794 int Send_sfx_ambient(int Ind, int sfx_ambient, bool smooth) {
6795 	connection_t *connp = Conn[Players[Ind]->conn];
6796 
6797 
6798 	/* translate: ambient sfx index -> sound index */
6799 	int i = -1;
6800 	cptr name = NULL;
6801 
6802 	//-1: smooth (poor with WoR, otherwise great), -2: sudden (needed for WoR/staircases)
6803 	switch (sfx_ambient) {
6804 	case SFX_AMBIENT_NONE:		i = (smooth ? -1 : -2); break;
6805 	case SFX_AMBIENT_FIREPLACE:	name = "ambient_fireplace"; break;
6806 	case SFX_AMBIENT_SHORE:		name = "ambient_shore"; break;
6807 	case SFX_AMBIENT_LAKE:		name = "ambient_lake"; break;
6808 	}
6809 
6810 	if (name) for (i = 0; i < SOUND_MAX_2010; i++) {
6811 		if (!audio_sfx[i][0]) {
6812 			i = -2;
6813 			break;
6814 		}
6815 		if (!strcmp(audio_sfx[i], name)) break;
6816 	}
6817 	/* paranoia */
6818 	if (i == SOUND_MAX_2010) i = -2;
6819 
6820 	/* Mind-linked to someone? Send him our sound too! */
6821 	player_type *p_ptr2 = NULL;
6822 	connection_t *connp2 = NULL;
6823 	/* If we're the target, we won't hear our own sfx */
6824 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
6825 	/* Get target player */
6826 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) connp2 = Conn[p_ptr2->conn];
6827 	/* Send same info to target player, if available */
6828 	if (connp2) {
6829 		if (p_ptr2->sound_ambient != sfx_ambient) {
6830 			p_ptr2->sound_ambient = sfx_ambient;
6831 			if (is_newer_than(&connp2->version, 4, 5, 4, 0, 0, 0))
6832 				Packet_printf(&connp2->c, "%c%d", PKT_SFX_AMBIENT, i);
6833 		}
6834 	}
6835 
6836 	if (Players[Ind]->sound_ambient == sfx_ambient) return(-1);
6837 	Players[Ind]->sound_ambient = sfx_ambient;
6838 
6839 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6840 		errno = 0;
6841 		plog(format("Connection not ready for ambient sfx (%d.%d.%d)",
6842 			Ind, connp->state, connp->id));
6843 		return 0;
6844 	}
6845 
6846 	if (!is_newer_than(&connp->version, 4, 5, 4, 0, 0, 0)) return(-1);
6847 	//s_printf("USE_SOUND_2010: ambient sfx %d sent to player %s (%d).\n", i, Players[Ind]->name, Ind);//debug
6848 	return Packet_printf(&connp->c, "%c%d", PKT_SFX_AMBIENT, i);
6849 }
6850 int Send_sfx_volume(int Ind, char sfx_ambient_vol, char sfx_weather_vol) {
6851 	connection_t *connp = Conn[Players[Ind]->conn];
6852 	/* Mind-linked to someone? Send him our sound too! */
6853 	player_type *p_ptr2 = NULL;
6854 	connection_t *connp2 = NULL;
6855 
6856 	/* If we're the target, we won't hear our own sfx */
6857 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
6858 	/* Get target player */
6859 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) connp2 = Conn[p_ptr2->conn];
6860 	/* Send same info to target player, if available */
6861 	if (connp2 && is_newer_than(&connp2->version, 4, 5, 5, 0, 0, 0))
6862 		Packet_printf(&connp2->c, "%c%c%c", PKT_SFX_VOLUME, sfx_ambient_vol, sfx_weather_vol);
6863 
6864 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6865 		errno = 0;
6866 		plog(format("Connection not ready for ambient sfx (%d.%d.%d)",
6867 			Ind, connp->state, connp->id));
6868 		return 0;
6869 	}
6870 
6871 	if (!is_newer_than(&connp->version, 4, 5, 5, 0, 0, 0)) return(-1);
6872 	//s_printf("USE_SOUND_2010: ambient sfx %d sent to player %s (%d).\n", i, Players[Ind]->name, Ind);//debug
6873 	return Packet_printf(&connp->c, "%c%c%c", PKT_SFX_VOLUME, sfx_ambient_vol, sfx_weather_vol);
6874 }
6875 #endif
6876 
6877 int Send_boni_col(int Ind, boni_col c) {
6878 	connection_t *connp = Conn[Players[Ind]->conn];
6879 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6880 		errno = 0;
6881 		plog(format("Connection not ready for boni_col (%d.%d.%d)",
6882 			Ind, connp->state, connp->id));
6883 		return 0;
6884 	}
6885 
6886 	if (!is_newer_than(&connp->version, 4, 5, 3, 2, 0, 0)) return(-1);
6887 	if (is_newer_than(&connp->version, 4, 5, 9, 0, 0, 0)) {
6888 		return Packet_printf(&connp->c, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", PKT_BONI_COL, //1+22+13+2 bytes in total
6889 		c.i, c.spd, c.slth, c.srch, c.infr, c.lite, c.dig, c.blow, c.crit, c.shot,
6890 		c.migh, c.mxhp, c.mxmp, c.luck, c.pstr, c.pint, c.pwis, c.pdex, c.pcon, c.pchr, c.amfi, c.sigl,
6891 		c.cb[0], c.cb[1], c.cb[2], c.cb[3], c.cb[4], c.cb[5], c.cb[6], c.cb[7], c.cb[8], c.cb[9],
6892 		c.cb[10], c.cb[11], c.cb[12], c.color, c.symbol);
6893 	} else { //send old info to old players
6894 		return Packet_printf(&connp->c, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", PKT_BONI_COL, //1+20+13+2 bytes in total
6895 		c.i, c.spd, c.slth, c.srch, c.infr, c.lite, c.dig, c.blow, c.crit, c.shot,
6896 		c.migh, c.mxhp, c.mxmp, c.luck, c.pstr, c.pint, c.pwis, c.pdex, c.pcon, c.pchr,
6897 		c.cb[0], c.cb[1], c.cb[2], c.cb[3], c.cb[4], c.cb[5], c.cb[6], c.cb[7], c.cb[8], c.cb[9],
6898 		c.cb[10], c.cb[11], c.cb[12], c.color, c.symbol);
6899 	}
6900 }
6901 
6902 int Send_beep(int Ind) {
6903 	connection_t *connp = Conn[Players[Ind]->conn];
6904 
6905 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6906 		errno = 0;
6907 		plog(format("Connection not ready for beep (page) (%d.%d.%d)",
6908 			Ind, connp->state, connp->id));
6909 		return 0;
6910 	}
6911 
6912 	return Packet_printf(&connp->c, "%c", PKT_BEEP);
6913 }
6914 
6915 int Send_warning_beep(int Ind)
6916 {
6917 	connection_t *connp = Conn[Players[Ind]->conn];
6918 
6919 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6920 		errno = 0;
6921 		plog(format("Connection not ready for beep (warning) (%d.%d.%d)",
6922 			Ind, connp->state, connp->id));
6923 		return 0;
6924 	}
6925 
6926 	if (is_newer_than(&Players[Ind]->version, 4, 5, 2, 0, 0, 0))
6927 		return Packet_printf(&connp->c, "%c", PKT_WARNING_BEEP);
6928 	else
6929 		return Packet_printf(&connp->c, "%c", PKT_BEEP);
6930 }
6931 
6932 int Send_AFK(int Ind, byte afk)
6933 {
6934 	connection_t *connp = Conn[Players[Ind]->conn];
6935 //	player_type *p_ptr = Players[Ind];
6936 
6937 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6938 		errno = 0;
6939 		plog(format("Connection not ready for AFK (%d.%d.%d)",
6940 			Ind, connp->state, connp->id));
6941 		return 0;
6942 	}
6943 	return Packet_printf(&connp->c, "%c%c", PKT_AFK, afk);
6944 }
6945 
6946 int Send_encumberment(int Ind, byte cumber_armor, byte awkward_armor, byte cumber_glove, byte heavy_wield, byte heavy_shield, byte heavy_shoot,
6947     byte icky_wield, byte awkward_wield, byte easy_wield, byte cumber_weight, byte monk_heavyarmor, byte rogue_heavyarmor, byte awkward_shoot,
6948     byte heavy_swim) {
6949 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
6950 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
6951 
6952 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6953 		errno = 0;
6954 		plog(format("Connection not ready for encumberment (%d.%d.%d)",
6955 			Ind, connp->state, connp->id));
6956 		return 0;
6957 	}
6958 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
6959 		connp2 = Conn[p_ptr2->conn];
6960 		if (!is_newer_than(&connp2->version, 4, 4, 2, 0, 0, 0)) {
6961 			Packet_printf(&connp2->c, "%c%c%c%c%c%c%c%c%c%c%c%c%c", PKT_ENCUMBERMENT, cumber_armor, awkward_armor, cumber_glove, heavy_wield, heavy_shield, heavy_shoot,
6962                                 icky_wield, awkward_wield, easy_wield, cumber_weight, monk_heavyarmor, awkward_shoot);
6963                 } else {
6964 			Packet_printf(&connp2->c, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c", PKT_ENCUMBERMENT, cumber_armor, awkward_armor, cumber_glove, heavy_wield, heavy_shield, heavy_shoot,
6965                                 icky_wield, awkward_wield, easy_wield, cumber_weight, monk_heavyarmor, rogue_heavyarmor, awkward_shoot);
6966                 }
6967 	}
6968 	if (!is_newer_than(&connp->version, 4, 4, 2, 0, 0, 0)) {
6969 		return Packet_printf(&connp->c, "%c%c%c%c%c%c%c%c%c%c%c%c%c", PKT_ENCUMBERMENT, cumber_armor, awkward_armor, cumber_glove, heavy_wield, heavy_shield, heavy_shoot,
6970 	                icky_wield, awkward_wield, easy_wield, cumber_weight, monk_heavyarmor, awkward_shoot);
6971         } else {
6972 		return Packet_printf(&connp->c, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c", PKT_ENCUMBERMENT, cumber_armor, awkward_armor, cumber_glove, heavy_wield, heavy_shield, heavy_shoot,
6973 	                icky_wield, awkward_wield, easy_wield, cumber_weight, monk_heavyarmor, rogue_heavyarmor, awkward_shoot);
6974         }
6975 }
6976 
6977 
6978 int Send_special_line(int Ind, s32b max, s32b line, byte attr, cptr buf) {
6979 	connection_t *connp = Conn[Players[Ind]->conn];
6980 	char temp[ONAME_LEN - 3], xattr = 'w', temp2[ONAME_LEN];
6981 
6982 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
6983 		errno = 0;
6984 		plog(format("Connection not ready for special line (%d.%d.%d)",
6985 		    Ind, connp->state, connp->id));
6986 		return 0;
6987 	}
6988 
6989 	switch (attr) {
6990 	case TERM_DARK:		xattr = 'd';break;
6991 	case TERM_RED:		xattr = 'r';break;
6992 	case TERM_L_DARK:	xattr = 'D';break;
6993 	case TERM_L_RED:	xattr = 'R';break;
6994 	case TERM_WHITE:	xattr = 'w';break;
6995 	case TERM_GREEN:	xattr = 'g';break;
6996 	case TERM_L_WHITE:	xattr = 'W';break;
6997 	case TERM_L_GREEN:	xattr = 'G';break;
6998 	case TERM_SLATE:	xattr = 's';break;
6999 	case TERM_BLUE:		xattr = 'b';break;
7000 	case TERM_VIOLET:	xattr = 'v';break;
7001 	case TERM_L_BLUE:	xattr = 'B';break;
7002 	case TERM_ORANGE:	xattr = 'o';break;
7003 	case TERM_UMBER:	xattr = 'u';break;
7004 	case TERM_YELLOW:	xattr = 'y';break;
7005 	case TERM_L_UMBER:	xattr = 'U';break;
7006 	case TERM_MULTI:	xattr = 'm';break;
7007 	case TERM_POIS:		xattr = 'p';break;
7008 	case TERM_FIRE:		xattr = 'f';break;
7009 	case TERM_COLD:		xattr = 'c';break;
7010 	case TERM_ACID:		xattr = 'a';break;
7011 	case TERM_ELEC:		xattr = 'e';break;
7012 	case TERM_LITE:		xattr = 'L';break;
7013 	case TERM_HALF:		xattr = 'h';break;
7014 	case TERM_CONF:		xattr = 'C';break;
7015 	case TERM_SOUN:		xattr = 'S';break;
7016 	case TERM_SHAR:		xattr = 'H';break;
7017 	case TERM_DARKNESS:	xattr = 'A';break;
7018 	case TERM_SHIELDM:	xattr = 'M';break;
7019 	case TERM_SHIELDI:	xattr = 'I';break;
7020 	//TODO: implement/watch client version for EXTENDED_TERM_COLOURS
7021 	}
7022 
7023 	strncpy(temp, buf, ONAME_LEN - 4);
7024 	temp[ONAME_LEN - 4] = '\0';
7025 
7026 	strcpy(temp2, "\377");
7027 	temp2[1] = xattr; temp2[2] = '\0';
7028 
7029 #if 0 /* default (no colour codes conversion) */
7030 	strcat(temp2, temp);
7031 #else /* allow colour code shortcut - C. Blue */
7032  #if 0 /* '{' = colour, '{{' = normal */
7033 	{
7034 		char *t = temp, *t2 = temp2 + 2;
7035 		while (*t) {
7036 			if (*t != '{') *t2++ = *t++;
7037 			else {
7038 				/* double '{' ? */
7039 				if (*(t + 1) == '{') {
7040 					*t2++ = *t++;
7041 				}
7042 				/* single '{' ? -> becomes colour code */
7043 				else {
7044 					*t2++ = '\377';
7045 				}
7046 				t++;
7047 			}
7048 		}
7049 		*t2 = 0;
7050 	}
7051  #endif
7052  #if 1 /* '\{' = colour, '{' = normal */
7053 	{
7054 		char *t = temp, *t2 = temp2 + 2;
7055 		while (*t) {
7056 			if (*t != '\\') *t2++ = *t++;
7057 			else {
7058 				/* double code ? -> colour */
7059 				if (*(t + 1) == '{') {
7060 					*t2++ = '\377';
7061 					t += 2;
7062 				}
7063 				/* single '{' ? keep */
7064 				else *t2++ = *t++;
7065 			}
7066 		}
7067 		*t2 = 0;
7068 	}
7069  #endif
7070 #endif
7071 
7072 	if (is_newer_than(&Players[Ind]->version, 4, 4, 7, 0, 0, 0))
7073 		return Packet_printf(&connp->c, "%c%d%d%c%I", PKT_SPECIAL_LINE, max, line, attr, temp2);
7074 	else if (is_newer_than(&Players[Ind]->version, 4, 4, 6, 1, 0, 0))
7075 		return Packet_printf(&connp->c, "%c%hd%hd%c%I", PKT_SPECIAL_LINE, max, line, attr, temp2);
7076 	else {
7077 		/* Cut it off so old clients can handle it, ouch */
7078 		temp2[79] = 0;
7079 		return Packet_printf(&connp->c, "%c%d%d%c%s", PKT_SPECIAL_LINE, max, line, attr, temp2);
7080 	}
7081 }
7082 
7083 int Send_floor(int Ind, char tval)
7084 {
7085 	connection_t *connp = Conn[Players[Ind]->conn];
7086 
7087 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
7088 	{
7089 		errno = 0;
7090 		plog(format("Connection not ready for floor item (%d.%d.%d)",
7091 			Ind, connp->state, connp->id));
7092 		return 0;
7093 	}
7094 
7095 	return Packet_printf(&connp->c, "%c%c", PKT_FLOOR, tval);
7096 }
7097 
7098 int Send_pickup_check(int Ind, cptr buf)
7099 {
7100 	connection_t *connp = Conn[Players[Ind]->conn];
7101 
7102 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
7103 	{
7104 		errno = 0;
7105 		plog(format("Connection not ready for pickup check (%d.%d.%d)",
7106 			Ind, connp->state, connp->id));
7107 		return 0;
7108 	}
7109 
7110 	return Packet_printf(&connp->c, "%c%s", PKT_PICKUP_CHECK, buf);
7111 }
7112 
7113 /* adding ultimate quick and dirty hack here so geraldo can play his 19th lvl char
7114    with the 80 character party name......
7115    -APD-
7116 */
7117 
7118 int Send_party(int Ind, bool leave, bool clear) {
7119 	int i;
7120 	party_type *pa_ptr = &parties[Players[Ind]->party];
7121 	char bufn[90], bufm[20], bufo[50], buf[10];
7122 	char bufn_compat[90], bufm_compat[20], bufo_compat[50];
7123 
7124 	/* prepare data for outdated clients */
7125 	if (pa_ptr->mode == PA_IRONTEAM)
7126 		snprintf(bufn_compat, 90, "Party (Iron Team): %s", pa_ptr->name);
7127 	else
7128 		snprintf(bufn_compat, 90, "Party  : %s", pa_ptr->name);
7129 	strcpy(bufm_compat, "Members: ");
7130 	snprintf(buf, 10, "%d", pa_ptr->members);
7131 	strcat(bufm_compat, buf);
7132 	strcpy(bufo_compat, "Owner  : ");
7133 	strcat(bufo_compat, pa_ptr->owner);
7134 
7135 	/* We're just sending that we aren't in a party? */
7136 	if (Players[Ind]->party == 0) {
7137 		connection_t *connp = Conn[Players[Ind]->conn];
7138 		if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7139 			errno = 0;
7140 			plog(format("Connection nor ready for party info (%d.%d.%d)",
7141 				Ind, connp->state, connp->id));
7142 			return 0;
7143 		}
7144 		if (!is_newer_than(&Players[Ind]->version, 4, 4, 7, 0, 0, 0)) {
7145 			Packet_printf(&connp->c, "%c%s%s%s", PKT_PARTY, bufn_compat, "Members: - ", "Owner  : - ");
7146 		} else {
7147 			Packet_printf(&connp->c, "%c%s%s%s", PKT_PARTY, "", "", "");
7148 		}
7149 		return 1;
7150 	}
7151 
7152 	/* prepare data for clients */
7153 	if (pa_ptr->mode == PA_IRONTEAM)
7154 		snprintf(bufn, 90, "Iron Team: '\377%c%s\377w'", COLOUR_CHAT_PARTY, pa_ptr->name);
7155 	else
7156 		snprintf(bufn, 90, "Party: '\377%c%s\377w'", COLOUR_CHAT_PARTY, pa_ptr->name);
7157 	snprintf(buf, 10, "%d", pa_ptr->members);
7158 	strcpy(bufm, buf);
7159 	if (pa_ptr->members == 1) strcat(bufm, " member");
7160 	else strcat(bufm, " members");
7161 	strcpy(bufo, "owner: ");
7162 	strcat(bufo, pa_ptr->owner);
7163 
7164 	/* scan party members and send info */
7165 	for (i = 1; i <= NumPlayers; i++) {
7166 		player_type *p_ptr = Players[i];
7167 		connection_t *connp = Conn[p_ptr->conn];
7168 
7169 		if (p_ptr->party != Players[Ind]->party) continue;
7170 		if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7171 			errno = 0;
7172 			plog(format("Connection nor ready for party info (%d.%d.%d)",
7173 				i, connp->state, connp->id));
7174 			continue;
7175 		}
7176 
7177 		if (!is_newer_than(&p_ptr->version, 4, 4, 7, 0, 0, 0)) {
7178 			Packet_printf(&connp->c, "%c%s%s%s", PKT_PARTY, bufn_compat, bufm_compat, bufo_compat);
7179 		} else {
7180 			if (!clear && (!leave || i != Ind)) {
7181 				Packet_printf(&connp->c, "%c%s%s%s", PKT_PARTY, bufn, bufm, bufo);
7182 			} else {
7183 				Packet_printf(&connp->c, "%c%s%s%s", PKT_PARTY, "", "", "");
7184 			}
7185 		}
7186 	}
7187 
7188 	return 1;
7189 }
7190 
7191 int Send_guild(int Ind, bool leave, bool clear) {
7192 	int i;
7193 	guild_type *g_ptr = &guilds[Players[Ind]->guild];
7194 	char bufn[90], bufm[20], bufo[50], buf[10];
7195 
7196 	/* We're just sending that we aren't in a guild? */
7197 	if (Players[Ind]->guild == 0) {
7198 		connection_t *connp = Conn[Players[Ind]->conn];
7199 		if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7200 			errno = 0;
7201 			plog(format("Connection nor ready for guild info (%d.%d.%d)",
7202 				Ind, connp->state, connp->id));
7203 			return 0;
7204 		}
7205 		Packet_printf(&connp->c, "%c%s%s%s", PKT_GUILD, "", "", "");
7206 		return 1;
7207 	}
7208 
7209 	/* prepare data for clients */
7210 	snprintf(bufn, 90, "Guild: '\377%c%s\377w'", COLOUR_CHAT_GUILD, g_ptr->name);
7211 	snprintf(buf, 10, "%d", g_ptr->members);
7212 	strcpy(bufm, buf);
7213 	if (g_ptr->members == 1) strcat(bufm, " member");
7214 	else strcat(bufm, " members");
7215 	if (lookup_player_name(g_ptr->master)) {
7216 		strcpy(bufo, "master: ");
7217 		strcat(bufo, lookup_player_name(g_ptr->master));
7218 	} else {
7219 		strcpy(bufo, "master: <leaderless>");
7220 	}
7221 
7222 	/* scan party members and send info */
7223 	for (i = 1; i <= NumPlayers; i++) {
7224 		player_type *p_ptr = Players[i];
7225 		connection_t *connp = Conn[p_ptr->conn];
7226 
7227 		if (!is_newer_than(&p_ptr->version, 4, 4, 7, 0, 0, 0)) continue;
7228 		if (p_ptr->guild != Players[Ind]->guild) continue;
7229 		if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7230 			errno = 0;
7231 			plog(format("Connection nor ready for guild info (%d.%d.%d)",
7232 				i, connp->state, connp->id));
7233 			continue;
7234 		}
7235 
7236 		if (!clear && (!leave || i != Ind)) {
7237 			Packet_printf(&connp->c, "%c%s%s%s", PKT_GUILD, bufn, bufm, bufo);
7238 		} else {
7239 			Packet_printf(&connp->c, "%c%s%s%s", PKT_GUILD, "", "", "");
7240 		}
7241 	}
7242 
7243 	return 1;
7244 }
7245 
7246 int Send_guild_config(int id) {
7247 	int i, j;
7248 	guild_type *g_ptr = &guilds[id];
7249 	int master;
7250 	int ghwx = -1, ghwy = 0, ghx, ghy, ghpos = -1;
7251 
7252 	/* guild hall location */
7253 	if (g_ptr->h_idx) {
7254 		ghwx = houses[g_ptr->h_idx - 1].wpos.wx;
7255 		ghwy = houses[g_ptr->h_idx - 1].wpos.wy;
7256 		ghx = houses[g_ptr->h_idx - 1].x;
7257 		ghy = houses[g_ptr->h_idx - 1].y;
7258 
7259 		if (ghy < MAX_HGT / 3) ghpos = 0;
7260 		else if (ghy < 2 * MAX_HGT / 3) ghpos = 1;
7261 		else ghpos = 2;
7262 		if (ghx < MAX_WID / 3) ghpos += 0;
7263 		else if (ghx < 2 * MAX_WID / 3) ghpos += 4;
7264 		else ghpos += 8;
7265 	}
7266 #ifndef ENABLE_GUILD_HALL
7267 	else ghwx = -2;
7268 #endif
7269 
7270 	/* scan party members and send info */
7271 	for (i = 1; i <= NumPlayers; i++) {
7272 		player_type *p_ptr = Players[i];
7273 		connection_t *connp = Conn[p_ptr->conn];
7274 
7275 		if (!is_newer_than(&p_ptr->version, 4, 5, 2, 0, 0, 0)) continue;
7276 		if (p_ptr->guild != id) continue;
7277 		if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7278 			errno = 0;
7279 			plog(format("Connection nor ready for guild info (%d.%d.%d)",
7280 				i, connp->state, connp->id));
7281 			continue;
7282 		}
7283 
7284 		if (g_ptr->master == p_ptr->id) master = 1;
7285 		else master = 0;
7286 
7287 		Packet_printf(&connp->c, "%c%d%d%d%d%d%d%d", PKT_GUILD_CFG, master, g_ptr->flags, g_ptr->minlev, 5, ghwx, ghwy, ghpos);
7288 		for (j = 0; j < 5; j++) Packet_printf(&connp->c, "%s", g_ptr->adder[j]);
7289 	}
7290 
7291 	return 1;
7292 }
7293 
7294 int Send_special_other(int Ind) {
7295 	connection_t *connp = Conn[Players[Ind]->conn];
7296 
7297 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7298 		errno = 0;
7299 		plog(format("Connection not ready for special other (%d.%d.%d)",
7300 			Ind, connp->state, connp->id));
7301 		return 0;
7302 	}
7303 
7304 	return Packet_printf(&connp->c, "%c", PKT_SPECIAL_OTHER);
7305 }
7306 
7307 int Send_skills(int Ind) {
7308 	player_type *p_ptr = Players[Ind];
7309 	connection_t *connp = Conn[p_ptr->conn];
7310 	s16b skills[12];
7311 	int i, tmp = 0;
7312 	object_type *o_ptr;
7313 
7314 	/* Fighting skill */
7315 	o_ptr = &p_ptr->inventory[INVEN_WIELD];
7316 	tmp = o_ptr->to_h;
7317 	/* dual-wield? */
7318 #if 0 /* hmm seemed a bit glitchy? replacing below.. */
7319 	o_ptr = &p_ptr->inventory[INVEN_ARM];
7320 	if (o_ptr->k_idx && o_ptr->tval != TV_SHIELD) tmp += o_ptr->to_h;
7321 	/* average? */
7322 	if (p_ptr->dual_wield) tmp /= 2;
7323 #else
7324 	if (p_ptr->dual_wield && p_ptr->dual_mode) {
7325 		o_ptr = &p_ptr->inventory[INVEN_ARM];
7326 		tmp += o_ptr->to_h;
7327 		/* average */
7328 		tmp /= 2;
7329 	}
7330 #endif
7331 
7332 #if 1 /* since Fighting and Bows/Throws have other effects, don't confuse players with this weird sum */
7333 	tmp += p_ptr->to_h + p_ptr->to_h_melee;
7334 	skills[0] = p_ptr->skill_thn + (tmp * BTH_PLUS_ADJ);
7335 
7336 	/* Shooting skill */
7337 	o_ptr = &p_ptr->inventory[INVEN_BOW];
7338 	tmp = p_ptr->to_h + o_ptr->to_h + p_ptr->to_h_ranged;
7339 	skills[1] = p_ptr->skill_thb + (tmp * BTH_PLUS_ADJ);
7340 #else /* looks silly for a warrior who has maxed skills yet is only "good" or something */
7341 	skills[0] = p_ptr->skill_thn;
7342 	skills[1] = p_ptr->skill_thb;
7343 #endif
7344 
7345 	/* Basic abilities */
7346 	skills[2] = p_ptr->skill_sav;
7347 	skills[3] = p_ptr->skill_stl;
7348 	skills[4] = p_ptr->skill_fos;
7349 	skills[5] = p_ptr->skill_srh;
7350 	skills[6] = p_ptr->skill_dis;
7351 	skills[7] = p_ptr->skill_dev;
7352 
7353 	/* Number of blows */
7354 	skills[8] = p_ptr->num_blow;
7355 	skills[9] = p_ptr->num_fire;
7356 	skills[10] = p_ptr->num_spell;
7357 
7358 	/* Infravision */
7359 	skills[11] = p_ptr->see_infra;
7360 
7361 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7362 		errno = 0;
7363 		plog(format("Connection not ready for skills (%d.%d.%d)",
7364 			Ind, connp->state, connp->id));
7365 		return 0;
7366 	}
7367 
7368 	Packet_printf(&connp->c, "%c", PKT_SKILLS);
7369 
7370 	for (i = 0; i < 12; i++) Packet_printf(&connp->c, "%hd", skills[i]);
7371 
7372 	return 1;
7373 }
7374 
7375 
7376 int Send_pause(int Ind) {
7377 	connection_t *connp = Conn[Players[Ind]->conn];
7378 
7379 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7380 		errno = 0;
7381 		plog(format("Connection not ready for skills (%d.%d.%d)",
7382 			Ind, connp->state, connp->id));
7383 		return 0;
7384 	}
7385 
7386 	return Packet_printf(&connp->c, "%c", PKT_PAUSE);
7387 }
7388 
7389 
7390 
7391 int Send_monster_health(int Ind, int num, byte attr) {
7392 	connection_t *connp = Conn[Players[Ind]->conn], *connp2;
7393 	player_type *p_ptr2 = NULL; /*, *p_ptr = Players[Ind];*/
7394 
7395 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7396 		errno = 0;
7397 		plog(format("Connection not ready for monster health bar (%d.%d.%d)",
7398 			Ind, connp->state, connp->id));
7399 		return 0;
7400 	}
7401 	if (get_esp_link(Ind, LINKF_MISC, &p_ptr2)) {
7402 		connp2 = Conn[p_ptr2->conn];
7403 		Packet_printf(&connp2->c, "%c%c%c", PKT_MONSTER_HEALTH, num, attr);
7404 	}
7405 
7406 	return Packet_printf(&connp->c, "%c%c%c", PKT_MONSTER_HEALTH, num, attr);
7407 }
7408 
7409 /* Always display oneself as '@' for easier visibility,
7410    instead of number or minus sign (when dead)? */
7411 #define CHARDUMP_VIS_HACK
7412 int Send_chardump(int Ind, cptr tag) {
7413 	player_type *p_ptr = Players[Ind];
7414 	connection_t *connp = Conn[p_ptr->conn];
7415 	int thp;
7416 
7417 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7418 		errno = 0;
7419 		plog(format("Connection not ready for chardump (%d.%d.%d)",
7420 			Ind, connp->state, connp->id));
7421 		return 0;
7422 	}
7423 
7424 #if 0 /* This works, but won't help non-death char dumps that are taken manually */
7425 	/* hack: Quickly update the client's unique list first */
7426 	for (i = 0; i < MAX_R_IDX; i++)
7427 		if (r_info[i].flags1 & RF1_UNIQUE)
7428 			Send_unique_monster(Ind, i);
7429 #endif
7430 
7431 #ifdef CHARDUMP_VIS_HACK
7432 	/* hack: display own symbol as '@' for this chardump, for easier recognising */
7433 	thp = p_ptr->chp;
7434  #if 0
7435 	if (p_ptr->chp < 0) /* only for death dumps? */
7436  #endif
7437 		p_ptr->chp = p_ptr->mhp;
7438 	lite_spot(Ind, p_ptr->py, p_ptr->px);
7439 #endif
7440 
7441 	if (!is_newer_than(&connp->version, 4, 4, 2, 0, 0, 0) ||
7442 	    MY_VERSION <= (4 << 12 | 4 << 8 | 2 << 4 | 0))
7443 		return Packet_printf(&connp->c, "%c", PKT_CHARDUMP);
7444 	else
7445 		return Packet_printf(&connp->c, "%c%s", PKT_CHARDUMP, tag);
7446 
7447 #ifdef CHARDUMP_VIS_HACK
7448 	/* unhack '@' */
7449 	p_ptr->chp = thp;
7450 	lite_spot(Ind, p_ptr->py, p_ptr->px);
7451 #endif
7452 }
7453 
7454 int Send_unique_monster(int Ind, int r_idx) {
7455 	connection_t *connp = Conn[Players[Ind]->conn];
7456 	player_type *p_ptr = Players[Ind];
7457 
7458 	if (!is_newer_than(&connp->version, 4, 4, 1, 7, 0, 0)) return(0);
7459 
7460 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
7461 	{
7462 		errno = 0;
7463 		plog(format("Connection not ready for unique monster (%d.%d.%d)",
7464 			Ind, connp->state, connp->id));
7465 		return 0;
7466 	}
7467 	return Packet_printf(&connp->c, "%c%d%d%s", PKT_UNIQUE_MONSTER, r_info[r_idx].u_idx, p_ptr->r_killed[r_idx], r_name + r_info[r_idx].name);
7468 }
7469 
7470 int Send_weather(int Ind, int weather_type, int weather_wind, int weather_gen_speed, int weather_intensity, int weather_speed, bool update_clouds, bool revoke_clouds) {
7471 	int n, i, c;
7472 	int cx1, cy1, cx2, cy2;
7473 
7474 	/* Note: This is NOT the client-side limit, but rather the current
7475 	   server-side limit how many clouds we want to transmit to the client. */
7476 	const int cloud_limit = 10;
7477 
7478 	connection_t *connp = Conn[Players[Ind]->conn];
7479 
7480 	/* Mind-linked to someone? Send him our weather */
7481 	player_type *p_ptr2 = NULL;
7482 	connection_t *connp2 = NULL;
7483 	/* If we're the target, we won't see our own weather */
7484 	if (Players[Ind]->esp_link_flags & LINKF_VIEW_DEDICATED) return(0);
7485 	/* Get target player */
7486 	if (get_esp_link(Ind, LINKF_VIEW, &p_ptr2)) connp2 = Conn[p_ptr2->conn];
7487 
7488 
7489 	wilderness_type *w_ptr = &wild_info[Players[Ind]->wpos.wy][Players[Ind]->wpos.wx];
7490 
7491 	if (!is_newer_than(&connp->version, 4, 4, 2, 0, 0, 0)) return(0);
7492 
7493 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY))
7494 	{
7495 		errno = 0;
7496 		plog(format("Connection not ready for weather (%d.%d.%d)",
7497 			Ind, connp->state, connp->id));
7498 		return 0;
7499 	}
7500 
7501 	/* hack: tell client to disable all clouds */
7502 	if (revoke_clouds) c = -1;
7503 	/* tell client to expect clouds */
7504 //	else if (update_clouds) c = w_ptr->clouds_to_update;
7505 	else if (update_clouds) c = cloud_limit;
7506 	else c = 0;
7507 	/* fix limit! (or crash/bug results on client-side,
7508 	   since it tries to read ALL clouds (despite discarding
7509 	   those which are too much) and hence tries to read more
7510 	   packets than we are actually sending, corrupting itself) */
7511 //redundant, see above
7512 //	if (c > cloud_limit) c = cloud_limit;
7513 #ifdef TEST_SERVER
7514 if (weather_type > 0) s_printf("weather_type: %d\n", weather_type);
7515 #endif
7516 	n = Packet_printf(&connp->c, "%c%d%d%d%d%d%d%d%d", PKT_WEATHER,
7517 	    weather_type, weather_wind, weather_gen_speed, weather_intensity, weather_speed,
7518 	    Players[Ind]->panel_col_prt, Players[Ind]->panel_row_prt, c);
7519 	if (connp2) Packet_printf(&connp2->c, "%c%d%d%d%d%d%d%d%d", PKT_WEATHER,
7520 	    weather_type, weather_wind, weather_gen_speed, weather_intensity, weather_speed,
7521 	    Players[Ind]->panel_col_prt, Players[Ind]->panel_row_prt, c);
7522 
7523 #ifdef TEST_SERVER
7524 #if 0
7525 s_printf("clouds_to_update %d (%d)\n", c, w_ptr->clouds_to_update);
7526 #endif
7527 #endif
7528 
7529 	/* re-send all clouds that have 'updated' flag set */
7530 	if (c > 0) {
7531 		for (i = 0; i < cloud_limit; i++) {
7532 #if 0 /* unfinished//also, make it visible to all players, so if0 here - see "/jokeweather" instead */
7533 			/* fun stuff ;) abuse the last cloud for this */
7534 			if (Players[Ind]->joke_weather && (i == cloud_limit - 1)) {
7535 				n = Packet_printf(&connp->c, "%d%d%d%d%d%d%d%d", i,
7536 				    Players[Ind]->px - 1, Players[Ind]->py,
7537 				    Players[Ind]->px + 1, Players[Ind]->py,
7538 				    7, 0, 0);
7539 				continue;
7540 			}
7541 #endif
7542 
7543 //			if (w_ptr->cloud_updated[i]) {
7544 //s_printf("cloud_updated %d\n", i);
7545 
7546 //DEBUGGING... (local should be correct, but that's not all yet..)
7547 #if 0 /* send global cloud coordinates, same as the server uses? */
7548 				n = Packet_printf(&connp->c, "%d%d%d%d%d%d%d%d",
7549 				    i, w_ptr->cloud_x1[i], w_ptr->cloud_y1[i], w_ptr->cloud_x2[i], w_ptr->cloud_y2[i],
7550 				    w_ptr->cloud_dsum[i], w_ptr->cloud_xm100[i], w_ptr->cloud_ym100[i]);
7551 #else /* send local cloud coordinates especially for client-side? */
7552 				/* convert global cloud coordinates (server-side)
7553 				   to local coordinates for the client, who only
7554 				   has to pay attention to one sector at a time
7555 				   (ie the one the player is currently in): */
7556 				cx1 = w_ptr->cloud_x1[i] - Players[Ind]->wpos.wx * MAX_WID;
7557 				cy1 = w_ptr->cloud_y1[i] - Players[Ind]->wpos.wy * MAX_HGT;
7558 				cx2 = w_ptr->cloud_x2[i] - Players[Ind]->wpos.wx * MAX_WID;
7559 				cy2 = w_ptr->cloud_y2[i] - Players[Ind]->wpos.wy * MAX_HGT;
7560 				/* hack: 'disable' a cloud slot */
7561 				if (w_ptr->cloud_x1[i] == -9999) cx1 = -9999;
7562 
7563 #ifdef TEST_SERVER
7564 #if 0
7565 s_printf("sending local cloud %d (%d,%d - %d,%d)\n", i, cx1, cy1, cx2, cy2);
7566 #endif
7567 #endif
7568 
7569 				n = Packet_printf(&connp->c, "%d%d%d%d%d%d%d%d",
7570 				    i, cx1, cy1, cx2, cy2,
7571 				    w_ptr->cloud_dsum[i], w_ptr->cloud_xm100[i], w_ptr->cloud_ym100[i]);
7572 				if (connp2) Packet_printf(&connp2->c, "%d%d%d%d%d%d%d%d",
7573 				    i, cx1, cy1, cx2, cy2,
7574 				    w_ptr->cloud_dsum[i], w_ptr->cloud_xm100[i], w_ptr->cloud_ym100[i]);
7575 #endif
7576 //			}
7577 		}
7578 	}
7579 
7580 	return n;
7581 }
7582 
7583 int Send_inventory_revision(int Ind) {
7584 	connection_t *connp = Conn[Players[Ind]->conn];
7585 	player_type *p_ptr = Players[Ind];
7586 
7587 	if (!is_newer_than(&connp->version, 4, 4, 2, 1, 0, 0)) return(0);
7588 
7589 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7590 		errno = 0;
7591 		plog(format("Connection not ready for inventory revision (%d.%d.%d)",
7592 			Ind, connp->state, connp->id));
7593 		return 0;
7594 	}
7595 
7596 	return Packet_printf(&connp->c, "%c%d", PKT_INVENTORY_REV, p_ptr->inventory_revision);
7597 }
7598 
7599 int Send_account_info(int Ind) {
7600 	connection_t *connp = Conn[Players[Ind]->conn];
7601 	struct account *l_acc;
7602 	u32b acc_flags = 0;
7603 
7604 	if (!is_newer_than(&connp->version, 4, 4, 2, 2, 0, 0)) return(0);
7605 
7606 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7607 		errno = 0;
7608 		plog(format("Connection not ready for account info (%d.%d.%d)",
7609 			Ind, connp->state, connp->id));
7610 		return 0;
7611 	}
7612 
7613 	l_acc = GetAccount(connp->nick, NULL, FALSE);
7614 	if (l_acc)
7615 	{
7616 		acc_flags = l_acc->flags;
7617 		KILL(l_acc, struct account);
7618 	}
7619 
7620 	return Packet_printf(&connp->c, "%c%hd", PKT_ACCOUNT_INFO, acc_flags);
7621 }
7622 
7623 int Send_request_key(int Ind, int id, char *prompt) {
7624 	connection_t *connp = Conn[Players[Ind]->conn];
7625 
7626 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return(0);
7627 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7628 		errno = 0;
7629 		plog(format("Connection not ready for request_key (%d.%d.%d)",
7630 		    Ind, connp->state, connp->id));
7631 		return 0;
7632 	}
7633 
7634 	Players[Ind]->request_id = id;
7635 	Players[Ind]->request_type = RTYPE_KEY;
7636 	return Packet_printf(&connp->c, "%c%d%s", PKT_REQUEST_KEY, id, prompt);
7637 }
7638 int Send_request_num(int Ind, int id, char *prompt, int std) {
7639 	connection_t *connp = Conn[Players[Ind]->conn];
7640 
7641 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return(0);
7642 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7643 		errno = 0;
7644 		plog(format("Connection not ready for request_num (%d.%d.%d)",
7645 		    Ind, connp->state, connp->id));
7646 		return 0;
7647 	}
7648 
7649 	Players[Ind]->request_id = id;
7650 	Players[Ind]->request_type = RTYPE_NUM;
7651 	return Packet_printf(&connp->c, "%c%d%s%d", PKT_REQUEST_NUM, id, prompt, std);
7652 }
7653 void Send_delayed_request_str(int Ind, int id, char *prompt, char *std) {
7654 	player_type *p_ptr = Players[Ind];
7655 
7656 	p_ptr->delay_str = cfg.fps / 2;//delay (turns)
7657 	p_ptr->delay_str_id = id;
7658 	strcpy(p_ptr->delay_str_prompt, prompt);
7659 	strcpy(p_ptr->delay_str_std, std);
7660 }
7661 int Send_request_str(int Ind, int id, char *prompt, char *std) {
7662 	connection_t *connp = Conn[Players[Ind]->conn];
7663 
7664 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return(0);
7665 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7666 		errno = 0;
7667 		plog(format("Connection not ready for request_str (%d.%d.%d)",
7668 		    Ind, connp->state, connp->id));
7669 		return 0;
7670 	}
7671 
7672 	Players[Ind]->request_id = id;
7673 	Players[Ind]->request_type = RTYPE_STR;
7674 	return Packet_printf(&connp->c, "%c%d%s%s", PKT_REQUEST_STR, id, prompt, std);
7675 }
7676 void Send_delayed_request_cfr(int Ind, int id, char *prompt, bool default_yes) {
7677 	player_type *p_ptr = Players[Ind];
7678 
7679 	p_ptr->delay_cfr = cfg.fps / 2;//delay (turns)
7680 	p_ptr->delay_cfr_id = id;
7681 	strcpy(p_ptr->delay_cfr_prompt, prompt);
7682 	p_ptr->delay_cfr_default_yes = default_yes;
7683 }
7684 int Send_request_cfr(int Ind, int id, char *prompt, bool default_yes) {
7685 	connection_t *connp = Conn[Players[Ind]->conn];
7686 
7687 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return(0);
7688 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7689 		errno = 0;
7690 		plog(format("Connection not ready for request_cfr (%d.%d.%d)",
7691 		    Ind, connp->state, connp->id));
7692 		return 0;
7693 	}
7694 
7695 	Players[Ind]->request_id = id;
7696 	Players[Ind]->request_type = RTYPE_CFR;
7697 	if (is_newer_than(&connp->version, 4, 5, 6, 0, 0, 1))
7698 		return Packet_printf(&connp->c, "%c%d%s%c", PKT_REQUEST_CFR, id, prompt, default_yes ? 1 : 0);
7699 	else
7700 		return Packet_printf(&connp->c, "%c%d%s", PKT_REQUEST_CFR, id, prompt);
7701 }
7702 /* NOTE: Should be followed by a p_ptr->request_id = RID_NONE to clean up. */
7703 int Send_request_abort(int Ind) {
7704 	connection_t *connp = Conn[Players[Ind]->conn];
7705 
7706 	if (!is_newer_than(&connp->version, 4, 4, 6, 1, 0, 0)) return(0);
7707 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7708 		errno = 0;
7709 		plog(format("Connection not ready for request_abort (%d.%d.%d)",
7710 		    Ind, connp->state, connp->id));
7711 		return 0;
7712 	}
7713 
7714 	return Packet_printf(&connp->c, "%c", PKT_REQUEST_ABORT);
7715 }
7716 
7717 int Send_apply_auto_insc(int Ind, int slot) {
7718 	connection_t *connp = Conn[Players[Ind]->conn];
7719 
7720 	if (!is_newer_than(&connp->version, 4, 5, 5, 0, 0, 0)) return(0);
7721 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
7722 		errno = 0;
7723 		plog(format("Connection not ready for request_apply_auto_insc (%d.%d.%d)",
7724 		    Ind, connp->state, connp->id));
7725 		return 0;
7726 	}
7727 
7728 	return Packet_printf(&connp->c, "%c%c", PKT_AUTOINSCRIBE, (char)slot);
7729 }
7730 
7731 /*
7732  * Return codes for the "Receive_XXX" functions are as follows:
7733  *
7734  * -1 --> Some error occured
7735  *  0 --> The action was queued (not enough energy)
7736  *  1 --> The action was ignored (not enough energy)
7737  *  2 --> The action completed successfully
7738  *  3 --> The action has been queued and is blocking further actions that need to be queued
7739  *
7740  *  Every code except for 1 will cause the input handler to stop
7741  *  processing actions.
7742  */
7743 
7744 // This does absolutly nothing other than keep our connection active.
7745 static int Receive_keepalive(int ind) {
7746 	int n, Ind;
7747 	connection_t *connp = Conn[ind];
7748 	char ch;
7749 	player_type *p_ptr;
7750 
7751 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
7752 		if (n == -1) Destroy_connection(ind, "read error");
7753 		return n;
7754 	}
7755 
7756 	/* If client has not been hacked, this should set AFK after 1 minute
7757 	   of no activity. */
7758 
7759 	connp->inactive_keepalive++;
7760 
7761 	if (connp->id != -1) {
7762 		Ind = GetInd[connp->id];
7763 		p_ptr = Players[Ind];
7764 
7765 		p_ptr->idle += 2;
7766 		p_ptr->idle_char += 2;
7767 
7768 		/* Kick a starving player */
7769 		if (p_ptr->idle_starve_kick && p_ptr->food < PY_FOOD_WEAK && connp->inactive_keepalive > STARVE_KICK_TIMER / 2) {
7770 			Destroy_connection(ind, STARVING_AUTOKICK_MSG);
7771 			return 2;
7772 		}
7773 
7774 		else if (!p_ptr->afk && p_ptr->auto_afk && connp->inactive_keepalive > AUTO_AFK_TIMER / 2) { /* dont oscillate ;) */
7775 			/* auto AFK timer (>1 min) */
7776 //			if (!p_ptr->resting) toggle_afk(Ind, ""); /* resting can take quite long sometimes */
7777 			toggle_afk(Ind, "");
7778 		}
7779 	}
7780 
7781 	return 2;
7782 }
7783 
7784 static int Receive_walk(int ind)
7785 {
7786 	connection_t *connp = Conn[ind];
7787 	player_type *p_ptr = NULL;
7788 	char ch, dir;
7789 	int n, player = -1;
7790 
7791 	if (connp->id != -1) {
7792 		player = GetInd[connp->id];
7793 		use_esp_link(&player, LINKF_MOV);
7794 		p_ptr = Players[player];
7795 	}
7796 	else player = 0;
7797 
7798 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
7799 		if (n == -1) Destroy_connection(ind, "read error");
7800 		return n;
7801 	}
7802 
7803 	/* Sanity check */
7804 	if (bad_dir(dir)) return 1;
7805 
7806 
7807 	/* bugged here if !p_ptr */
7808 
7809 	/* Disturb if running or resting */
7810 	if (p_ptr->running || p_ptr->resting) {
7811 		disturb(player, 0, 0);
7812 #if 0 /* disabled, because this would prevent 'walking/running out of fire-till-kill/auto-ret' which is a bit annoying: \
7813          it'd actually first just do disturb() here, so the player would have to attempt a second time to run/walk, after that. - C. Blue */
7814 		return 1;
7815 #endif
7816 	}
7817 
7818 	if (p_ptr->command_rep) p_ptr->command_rep = -1;
7819 
7820 	if (player && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
7821 		if (p_ptr->warning_run < 3) {
7822 			p_ptr->warning_run_steps++;
7823 			/* Give a warning after first 10 walked steps, then every 50 walked steps. */
7824 			if (p_ptr->warning_run_steps == 60) p_ptr->warning_run_steps = 10;
7825 			if (p_ptr->warning_run_steps == 10) {
7826 				msg_print(player, "\374\377oHINT: You can run swiftly by holding the \377RSHIFT\377o key when pressing a direction!");
7827 				msg_print(player, "\374\377o      To use this, the \377RNUMLOCK\377o key (labelled 'Num') must be turned off,");
7828 				msg_print(player, "\374\377o      and no awake monster must be in your line-of-sight (except in Bree).");
7829 				s_printf("warning_run_steps: %s\n", p_ptr->name);
7830 			}
7831 		}
7832 		do_cmd_walk(player, dir, p_ptr->always_pickup);
7833 		return 2;
7834 	} else {
7835 		// Otherwise discared the walk request.
7836 		//if (!connp->q.len && p_ptr->autoattack)
7837 		// If we have no commands queued, then queue our walk request.
7838 		// Note that ch might equal PKT_RUN, since Receive_run will
7839 		// sometimes call this function.
7840 		if (connp->q.len < 2) {
7841 			Packet_printf(&connp->q, "%c%c", PKT_WALK, dir);
7842 			return 0;
7843 		} else {
7844 			// If we have a walk command queued at the end of the queue,
7845 			// then replace it with this queue request.
7846 			if (connp->q.buf[connp->q.len - 2] == PKT_WALK) {
7847 				connp->q.len -= 2;
7848 				Packet_printf(&connp->q, "%c%c", PKT_WALK, dir);
7849 				return 0;
7850 			}
7851 		}
7852 	}
7853 
7854 	return 1;
7855 }
7856 
7857 static int Receive_run(int ind) {
7858 	connection_t *connp = Conn[ind];
7859 	player_type *p_ptr = NULL;
7860 	char ch;
7861 	int i, n, player = -1;
7862 	char dir;
7863 	dun_level *l_ptr = NULL;
7864 
7865 	if (connp->id != -1) {
7866 		player = GetInd[connp->id];
7867 		use_esp_link(&player, LINKF_MOV);
7868 		p_ptr = Players[player];
7869 		l_ptr = getfloor(&p_ptr->wpos);
7870 	}
7871 
7872 	/* paranoia? */
7873 //	if (player == -1) return;
7874 
7875 	if (p_ptr->command_rep) p_ptr->command_rep = -1;
7876 
7877 	/* If not the dungeon master, who can always run */
7878 	if (!p_ptr->admin_dm) {
7879 		monster_race *r_ptr;
7880 
7881 		if ((p_ptr->global_event_temp & PEVF_NO_RUN_00)) return Receive_walk(ind);
7882 		if (l_ptr && (l_ptr->flags2 & LF2_NO_RUN)) return Receive_walk(ind);
7883 		if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_RUN)) return Receive_walk(ind);
7884 
7885 		/* check for status impairments (lack of light is checked in run_test()) */
7886 		if (p_ptr->confused || p_ptr->blind)
7887 			return Receive_walk(ind);
7888 
7889 		/* Check for monsters in sight */
7890 		for (i = 0; i < m_max; i++) {
7891 			/* Check this monster */
7892 			if (p_ptr->mon_los[i] && !m_list[i].csleep && !m_list[i].special
7893 			    /* not for Bree townies, Santa, Halloween townies, Target dummy */
7894 			    && !((r_ptr = race_inf(&m_list[i]))->flags8 & RF8_ALLOW_RUNNING)) {
7895 				// Treat this as a walk request
7896 				// Hack -- send the same connp->r "arguments" to Receive_walk
7897 				if (p_ptr->warning_run_monlos == 0) {
7898 					p_ptr->warning_run_monlos = 1;
7899 					msg_print(player, "\374\377yNote: You cannot initiate running while you are within line-of-sight");
7900 					msg_print(player, "\374\377y      of an awake monster. The town of Bree is excepted from this.");
7901 					s_printf("warning_run_monlos: %s\n", p_ptr->name);
7902 				}
7903 				return Receive_walk(ind);
7904 			}
7905 		}
7906 
7907 #ifdef HOSTILITY_ABORTS_RUNNING
7908 		/* Check for hostile players. They should be treated as a disturbance.
7909 		 * Should lessen the unfair advantage melee have in PVP */
7910 		for (i = 1; i <= NumPlayers; i++) {
7911 			if (i == player) continue;
7912 			if (check_hostile(player, i)) {
7913 				if (target_able(player, 0 - i)) { /* target_able takes in midx usually */
7914 					return Receive_walk(ind);
7915 				}
7916 			}
7917 		}
7918 #endif
7919 	}
7920 
7921 #if 0 /* with new fire-till-kill/auto-ret code that accepts <= 100% energy, and accordingly the new \
7922     p_ptr->requires_energy flag, this stuff should no longer be required and hence obsolete. - C. Blue */
7923 	/* hack to fix 'movelock' bug, which occurs if a player tries to RUN away from a
7924 	   monster while he's currently auto-retaliating. (WALKING away instead of
7925 	   trying to run works by the way.)
7926 	   It doesn't matter if auto-retaliation is done by melee weaponry, shooting, or by spellcasting.
7927 	   The bug results in the player being unable to move until he clears the buffer with ')' key or
7928 	   (even while attacking) inscribes his item to stop auto-retaliating.
7929 	   So this fix checks for adjacent monsters and, if found, changes the run command to a walk
7930 	   command.
7931 	   Note that the bug ONLY happens if the player is auto-retaliating. Manual attacks are fine.
7932 	   The fix also makes kind of sense, since players can't run anyways while seeing a monster that's
7933 	   awake. And any monster that's auto-retaliated (if not a 'pseudo monster' which rensembles an
7934 	   inanimate object) should definitely be awake.
7935 	   Better solutions (that also fix the 'double energy' players have after performing no action
7936 	   for a turn and NEED for running) might take its place in the future. - C. Blue */
7937 //if (p_ptr->auto_retaliating) s_printf("auto-retal\n");
7938 //else s_printf("not a-r\n");
7939 //	if (!p_ptr->admin_dm && p_ptr->auto_retaliating) {
7940 	if (p_ptr->auto_retaliating || p_ptr->shooting_till_kill)
7941 		return Receive_walk(ind);
7942 #endif
7943 
7944 
7945 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
7946 		if (n == -1)
7947 			Destroy_connection(ind, "read error");
7948 		return n;
7949 	}
7950 
7951 	/* Sanity check */
7952 	if (bad_dir(dir)) return 1;
7953 
7954 	/* Disturb if we want to change directions */
7955 	//if (dir != p_ptr->find_current) disturb(player, 0, 0);
7956 
7957 	/* Hack -- Fix the running in '5' bug */
7958 	if (dir == 5) return 1;
7959 
7960 #if 0
7961 	/* Only process the run command if we are not already running in
7962 	 * the direction requested.
7963 	 */
7964 	if (player && (!p_ptr->running || (dir != p_ptr->find_current)))
7965 #endif
7966 	{
7967 		// If we don't want to queue the command, return now.
7968 		if ((n = do_cmd_run(player, dir)) == 2) {
7969 			return 2;
7970 		}
7971 		// If do_cmd_run returns a 0, then there wasn't enough energy
7972 		// to execute the run command.  Queue the run command if desired.
7973 		else if (n == 0) {
7974 			// Only buffer a run request if we have no previous commands
7975 			// buffered, and it is a new direction or we aren't already
7976 			// running.
7977 #if 0 /* changed so we can 'run' out of fire-till-kill'ing, even if we got there while we were already running - C. Blue */
7978 			if (((!connp->q.len) && (dir != p_ptr->find_current)) || (!p_ptr->running)) {
7979 #else
7980 			if (!connp->q.len) {
7981 #endif
7982 				Packet_printf(&connp->q, "%c%c", ch, dir);
7983 				return 0;
7984 			}
7985 		}
7986 	}
7987 
7988 	return 1;
7989 }
7990 
7991 int fake_Receive_tunnel(int Ind, int dir) {
7992 	player_type *p_ptr = Players[Ind];
7993 	connection_t *connp = Conn[p_ptr->conn];
7994 
7995 	/* all this is temp just to make it work */
7996 	if (p_ptr->command_rep == -1) {
7997 		p_ptr->command_rep = 0;
7998 		return 0;
7999 	}
8000 
8001 	/* please redesign ALL of this out of higher level */
8002 	if (p_ptr->command_rep != PKT_TUNNEL) p_ptr->command_rep = -1;
8003 
8004 	if (p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8005 		do_cmd_tunnel(Ind, dir, FALSE);
8006 		if (p_ptr->command_rep) Packet_printf(&connp->q, "%c%c", PKT_TUNNEL, dir);
8007 
8008 		return 2;
8009 	}
8010 
8011 	Packet_printf(&connp->q, "%c%c", PKT_TUNNEL, dir);
8012 	return 0;
8013 }
8014 
8015 static int Receive_tunnel(int ind)
8016 {
8017 	connection_t *connp = Conn[ind];
8018 	player_type *p_ptr = NULL;
8019 	char ch, dir;
8020 	int n, player = -1;
8021 
8022 	if (connp->id != -1)
8023 	{
8024 		player = GetInd[connp->id];
8025 		use_esp_link(&player, LINKF_MOV);
8026 		p_ptr = Players[player];
8027 	}
8028 
8029 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0)
8030 	{
8031 		if (n == -1)
8032 			Destroy_connection(ind, "read error");
8033 		return n;
8034 	}
8035 
8036 	if (!p_ptr) return 1;
8037 
8038 	/* Sanity check */
8039 	if (bad_dir(dir)) return 1;
8040 
8041 	/* all this is temp just to make it work */
8042 	if (p_ptr->command_rep == -1) {
8043 		p_ptr->command_rep = 0;
8044 		return 0;
8045 	}
8046 
8047 	/* please redesign ALL of this out of higher level */
8048 	if (p_ptr->command_rep != PKT_TUNNEL) p_ptr->command_rep = -1;
8049 
8050 	if (p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8051 		do_cmd_tunnel(player, dir, FALSE);
8052 		if (p_ptr->command_rep) Packet_printf(&connp->q, "%c%c", ch, dir);
8053 
8054 		return 2;
8055 	}
8056 
8057 	Packet_printf(&connp->q, "%c%c", ch, dir);
8058 	return 0;
8059 }
8060 
8061 static int Receive_aim_wand(int ind)
8062 {
8063 	connection_t *connp = Conn[ind];
8064 	player_type *p_ptr = NULL;
8065 	char ch, dir;
8066 	s16b item;
8067 	int n, player = -1;
8068 
8069 	if (connp->id != -1) {
8070 		player = GetInd[connp->id];
8071 		use_esp_link(&player, LINKF_OBJ);
8072 		p_ptr = Players[player];
8073 	}
8074 
8075 	if ((n = Packet_scanf(&connp->r, "%c%hd%c", &ch, &item, &dir)) <= 0) {
8076 		if (n == -1) Destroy_connection(ind, "read error");
8077 		return n;
8078 	}
8079 
8080 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8081 		/* Sanity check - mikaelh */
8082 		if (item >= INVEN_TOTAL) return 1;
8083 		if (bad_dir1(player, &dir)) return 1;
8084 
8085 		item = replay_inven_changes(player, item);
8086 		if (item == 0xFF) {
8087 			msg_print(player, "Command failed because item is gone.");
8088 			return 1;
8089 		}
8090 
8091 		do_cmd_aim_wand(player, item, dir);
8092 		return 2;
8093 	} else if (p_ptr) {
8094 		Packet_printf(&connp->q, "%c%hd%c", ch, item, dir);
8095 		return 0;
8096 	}
8097 
8098 	return 1;
8099 }
8100 
8101 static int Receive_drop(int ind)
8102 {
8103 	connection_t *connp = Conn[ind];
8104 	player_type *p_ptr = NULL;
8105 	char ch;
8106 	int n, player = -1;
8107 	s16b item, amt;
8108 
8109 	if (connp->id != -1)
8110 	{
8111 		player = GetInd[connp->id];
8112 		use_esp_link(&player, LINKF_OBJ);
8113 		p_ptr = Players[player];
8114 	}
8115 
8116 	if ((n = Packet_scanf(&connp->r, "%c%hd%hd", &ch, &item, &amt)) <= 0)
8117 	{
8118 		if (n == -1)
8119 			Destroy_connection(ind, "read error");
8120 		return n;
8121 	}
8122 
8123 	/* Sanity check - mikaelh */
8124 	if (item >= INVEN_TOTAL)
8125 		return 1;
8126 
8127 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
8128 	{
8129 		item = replay_inven_changes(player, item);
8130 		if (item == 0xFF)
8131 		{
8132 			msg_print(player, "Command failed because item is gone.");
8133 			return 1;
8134 		}
8135 
8136 		do_cmd_drop(player, item, amt);
8137 		return 2;
8138 	}
8139 	else if (p_ptr)
8140 	{
8141 		Packet_printf(&connp->q, "%c%hd%hd", ch, item, amt);
8142 		return 0;
8143 	}
8144 
8145 	return 1;
8146 }
8147 
8148 static int Receive_fire(int ind)
8149 {
8150 	connection_t *connp = Conn[ind];
8151 	player_type *p_ptr = NULL;
8152 	char ch, dir = 5;
8153 	int n, player = -1;
8154 	//s16b item;
8155 
8156 	if (connp->id != -1) {
8157 		player = GetInd[connp->id];
8158 		use_esp_link(&player, LINKF_OBJ);
8159 		p_ptr = Players[player];
8160 	}
8161 
8162 //	if ((n = Packet_scanf(&connp->r, "%c%c%hd", &ch, &dir, &item)) <= 0)
8163 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
8164 		if (n == -1)
8165 			Destroy_connection(ind, "read error");
8166 		return n;
8167 	}
8168 
8169 	/* Check confusion */
8170 	if (p_ptr->confused) {
8171 		/* Change firing direction */
8172 		/* no targetted shooting anymore while confused! */
8173 		dir = randint(8);
8174 		if (dir >= 5) dir++;
8175 	}
8176 
8177 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos) / p_ptr->num_fire) {
8178 		/* Sanity check */
8179 		if (bad_dir1(player, &dir)) return 1;
8180 
8181 		if (p_ptr->shoot_till_kill && dir == 5) p_ptr->shooty_till_kill = TRUE;
8182 //		do_cmd_fire(player, dir, item);
8183 		do_cmd_fire(player, dir);
8184 		if (!(p_ptr->shoot_till_kill && dir == 5 && !p_ptr->shooting_till_kill)) {
8185 			if (p_ptr->ranged_double) do_cmd_fire(player, dir);
8186 		}
8187 		p_ptr->shooty_till_kill = FALSE;
8188 		return 2;
8189 	} else if (p_ptr) {
8190 //		Packet_printf(&connp->q, "%c%c%hd", ch, dir, item);
8191 		Packet_printf(&connp->q, "%c%c", ch, dir);
8192 		return 0;
8193 	}
8194 
8195 	return 1;
8196 }
8197 
8198 static int Receive_observe(int ind)
8199 {
8200 	connection_t *connp = Conn[ind];
8201 	player_type *p_ptr = NULL;
8202 
8203 	char ch;
8204 
8205 	s16b item;
8206 
8207 	int n, player = -1;
8208 
8209 	if (connp->id != -1)
8210 	{
8211 		player = GetInd[connp->id];
8212 		p_ptr = Players[player];
8213 	}
8214 
8215 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
8216 	{
8217 		if (n == -1)
8218 			Destroy_connection(ind, "read error");
8219 		return n;
8220 	}
8221 
8222 	/* Sanity check - mikaelh */
8223 	if (item >= INVEN_TOTAL)
8224 		return 1;
8225 
8226 	if (p_ptr)
8227 		do_cmd_observe(player, item);
8228 
8229 	return 1;
8230 }
8231 
8232 static int Receive_stand(int ind)
8233 {
8234 	connection_t *connp = Conn[ind];
8235 	player_type *p_ptr = NULL;
8236 	char ch;
8237 	int n, player = -1;
8238 
8239 	if (connp->id != -1) {
8240 		player = GetInd[connp->id];
8241 		use_esp_link(&player, LINKF_MOV);
8242 		p_ptr = Players[player];
8243 	}
8244 
8245 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
8246 		if (n == -1) Destroy_connection(ind, "read error");
8247 		return n;
8248 	}
8249 
8250 //	if (p_ptr) { 		/* disallow picking up items while paralyzed: */
8251 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8252 		do_cmd_stay(player, 1);
8253 		return 2;
8254 	} else if (p_ptr) {
8255 		Packet_printf(&connp->q, "%c", ch);
8256 		return 0;
8257 	}
8258 
8259 	return -1;
8260 }
8261 
8262 static int Receive_destroy(int ind)
8263 {
8264 	connection_t *connp = Conn[ind];
8265 	player_type *p_ptr = NULL;
8266 	char ch;
8267 	s16b item, amt;
8268 	int n, player = -1;
8269 
8270 	if (connp->id != -1)
8271 	{
8272 		player = GetInd[connp->id];
8273 		use_esp_link(&player, LINKF_OBJ);
8274 		p_ptr = Players[player];
8275 	}
8276 
8277 	if ((n = Packet_scanf(&connp->r, "%c%hd%hd", &ch, &item, &amt)) <= 0)
8278 	{
8279 		if (n == -1)
8280 			Destroy_connection(ind, "read error");
8281 		return n;
8282 	}
8283 
8284 	/* Sanity check - mikaelh */
8285 	if (item >= INVEN_TOTAL)
8286 		return 1;
8287 
8288 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8289 		item = replay_inven_changes(player, item);
8290 		if (item == 0xFF) {
8291 			msg_print(player, "Command failed because item is gone.");
8292 			return 1;
8293 		}
8294 
8295 		do_cmd_destroy(player, item, amt);
8296 		return 2;
8297 	} else if (p_ptr) {
8298 		Packet_printf(&connp->q, "%c%hd%hd", ch, item, amt);
8299 		return 0;
8300 	}
8301 
8302 	return 1;
8303 }
8304 
8305 static int Receive_look(int ind)
8306 {
8307 	connection_t *connp = Conn[ind];
8308 	player_type *p_ptr = NULL;
8309 	char ch;
8310 	s16b dir;
8311 	int n, player = -1;
8312 
8313 	if (connp->id != -1) {
8314 		player = GetInd[connp->id];
8315 		use_esp_link(&player, LINKF_OBJ);
8316 		p_ptr = Players[player];
8317 	}
8318 
8319 	if (is_older_than(&p_ptr->version, 4, 4, 9, 4, 0, 0)) {
8320 		char old_dir;
8321 		if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &old_dir)) <= 0) {
8322 			if (n == -1) Destroy_connection(ind, "read error");
8323 			return n;
8324 		}
8325 		dir = old_dir;
8326 	} else { /* for 'p' feature (manual ground-targetting) */
8327 		if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &dir)) <= 0) {
8328 			if (n == -1) Destroy_connection(ind, "read error");
8329 			return n;
8330 		}
8331 	}
8332 
8333 	/* Sanity check */
8334 	if (bad_dir(dir) && bad_dir2(dir)) return 1;
8335 
8336 	if (p_ptr) {
8337 		do_cmd_look(player, dir);
8338 	}
8339 
8340 	return 1;
8341 }
8342 
8343 /*
8344  * Possibly, most of Receive_* functions can be bandled into one function
8345  * like this; that'll make the client *MUCH* more generic.		- Jir -
8346  */
8347 static int Receive_activate_skill(int ind) {
8348 	connection_t *connp = Conn[ind];
8349 	player_type *p_ptr = NULL;
8350 	char ch, mkey, dir;
8351 	int n, player = -1, old = -1;
8352 	s16b book, spell, item, aux;
8353 
8354 	if (connp->id != -1) {
8355 		player = GetInd[connp->id];
8356 		old = player;
8357 		use_esp_link(&player, LINKF_OBJ);
8358 		p_ptr = Players[player];
8359 	}
8360 
8361 	if ((n = Packet_scanf(&connp->r, "%c%c%hd%hd%c%hd%hd", &ch, &mkey, &book, &spell, &dir, &item, &aux)) <= 0) {
8362 		if (n == -1) Destroy_connection(ind, "read error");
8363 		return n;
8364 	}
8365 
8366 	/* Not by class nor by item; by skill */
8367 	if (p_ptr &&
8368 	    (p_ptr->energy >= level_speed(&p_ptr->wpos) ||
8369 	    /* some abilities don't require energy: */
8370 	    mkey == MKEY_DODGE || mkey == MKEY_PARRYBLOCK ||
8371 	    mkey == MKEY_SHOOT_TILL_KILL || mkey == MKEY_DUAL_MODE)) {
8372 		/* Sanity check - mikaelh */
8373 		if (item >= INVEN_TOTAL) return 1;
8374 		if (bad_dir3(player, &dir)) return 1;
8375 
8376 
8377 		p_ptr->current_char = (old == player) ? TRUE : FALSE;
8378 
8379 		if (p_ptr->ghost && !is_admin(p_ptr)) {
8380 			msg_print(player, "\377oYou need your body to use a skill.");
8381 			return 2;
8382 		}
8383 
8384 #if 0
8385 		/* Break goi/manashield */
8386 		if (mkey != MKEY_DODGE) { // it's not real 'activation'
8387 			if (p_ptr->invuln) set_invuln(player, 0);
8388 			if (p_ptr->tim_manashield) set_tim_manashield(player, 0);
8389 		}
8390 #endif
8391 
8392 		switch (mkey) {
8393 		case MKEY_MIMICRY:
8394 			if (get_skill(p_ptr, SKILL_MIMIC)) {
8395 				if (spell == 20000 && dir) {
8396 					switch (dir) {
8397 					case 1:
8398 						switch (p_ptr->mimic_immunity) {
8399 						case 0:
8400 							msg_print(player, "\377WCurrently you don't have any preferred form immunity.");
8401 							break;
8402 						case 1:
8403 							msg_print(player, "\377WYour current immunity preference is \377blightning.");
8404 							break;
8405 						case 2:
8406 							msg_print(player, "\377WYour current immunity preference is \377wfrost.");
8407 							break;
8408 						case 3:
8409 							msg_print(player, "\377WYour current immunity preference is \377sacid.");
8410 							break;
8411 						case 4:
8412 							msg_print(player, "\377WYour current immunity preference is \377rfire.");
8413 							break;
8414 						case 5:
8415 							msg_print(player, "\377WYour current immunity preference is \377gpoison.");
8416 							break;
8417 						case 6:
8418 							msg_print(player, "\377WYour current immunity preference is \377Bwater.");
8419 							break;
8420 						}
8421 						break;
8422 					case 2:
8423 						p_ptr->mimic_immunity = 0;
8424 						msg_print(player, "\377WYou no longer have any preferred form immunity.");
8425 						break;
8426 					case 3:
8427 						p_ptr->mimic_immunity = 1;
8428 						msg_print(player, "\377WPreferred form immunity is now \377blightning.");
8429 						if (p_ptr->body_monster &&
8430 						    (r_info[p_ptr->body_monster].flags3 & RF3_IM_ELEC))
8431 							calc_boni(player);
8432 						break;
8433 					case 4:
8434 						p_ptr->mimic_immunity = 2;
8435 						msg_print(player, "\377WPreferred form immunity is now \377wfrost.");
8436 						if (p_ptr->body_monster &&
8437 						    (r_info[p_ptr->body_monster].flags3 & RF3_IM_COLD))
8438 							calc_boni(player);
8439 						break;
8440 					case 5:
8441 						p_ptr->mimic_immunity = 3;
8442 						msg_print(player, "\377WPreferred form immunity is now \377sacid.");
8443 						if (p_ptr->body_monster &&
8444 						    (r_info[p_ptr->body_monster].flags3 & RF3_IM_ACID))
8445 							calc_boni(player);
8446 						break;
8447 					case 6:
8448 						p_ptr->mimic_immunity = 4;
8449 						msg_print(player, "\377WPreferred form immunity is now \377rfire.");
8450 						if (p_ptr->body_monster &&
8451 						    (r_info[p_ptr->body_monster].flags3 & RF3_IM_FIRE))
8452 							calc_boni(player);
8453 						break;
8454 					case 7:
8455 						p_ptr->mimic_immunity = 5;
8456 						msg_print(player, "\377WPreferred form immunity is now \377gpoison.");
8457 						if (p_ptr->body_monster &&
8458 						    (r_info[p_ptr->body_monster].flags3 & RF3_IM_POIS))
8459 							calc_boni(player);
8460 						break;
8461 					case 8:
8462 						p_ptr->mimic_immunity = 6;
8463 						msg_print(player, "\377WPreferred form immunity is now \377Bwater.");
8464 						if (p_ptr->body_monster &&
8465 						    (r_info[p_ptr->body_monster].flags9 & RF9_IM_WATER))
8466 							calc_boni(player);
8467 						break;
8468 					default:
8469 						msg_print(player, "\377yThat immunity does not exist.");
8470 						break;
8471 					}
8472 					return 2;
8473 				}
8474 				if (p_ptr->shoot_till_kill && dir == 5) p_ptr->shooty_till_kill = TRUE;
8475 				do_cmd_mimic(player, spell, dir);
8476 				p_ptr->shooty_till_kill = FALSE;
8477 			}
8478 			break;
8479 
8480 		case MKEY_DODGE:
8481 			use_ability_blade(player);
8482 			break;
8483 		case MKEY_FLETCHERY:
8484 			do_cmd_fletchery(player);
8485 			break;
8486 #ifdef ENABLE_STANCES
8487 		case MKEY_STANCE:
8488 			do_cmd_stance(player, book);
8489 			break;
8490 #endif
8491 #ifdef ENABLE_NEW_MELEE
8492 		case MKEY_PARRYBLOCK:
8493 			check_parryblock(player);
8494 			break;
8495 #endif
8496 		case MKEY_TRAP:
8497 			do_cmd_set_trap(player, book, spell);
8498 			break;
8499 		case MKEY_SCHOOL:
8500 			book = replay_inven_changes(player, book);
8501 			if (book == 0xFF) {
8502 				msg_print(player, "Command failed because item is gone.");
8503 				return 1;
8504 			}
8505 			item = replay_inven_changes(player, item);
8506 			if (item == 0xFF) {
8507 				msg_print(player, "Command failed because item is gone.");
8508 				return 1;
8509 			}
8510 
8511 			/* Sanity check #2 */
8512 			if (dir == -1) dir = 5;
8513 
8514 			if (p_ptr->shoot_till_kill && dir == 5) p_ptr->shooty_till_kill = TRUE;
8515 			cast_school_spell(player, book, spell, dir, item, aux);
8516 			p_ptr->shooty_till_kill = FALSE;
8517 			break;
8518 
8519 		case MKEY_RCRAFT:
8520 			/* Sanity check #2 */
8521 			if (dir == -1) dir = 5;
8522 
8523 			if (p_ptr->shoot_till_kill && dir == 5) p_ptr->shooty_till_kill = TRUE;
8524 			(void)cast_rune_spell(player, dir, (u16b)book, (u16b)spell, (u16b)item, 0);
8525 			p_ptr->shooty_till_kill = FALSE;
8526 			break;
8527 
8528 		case MKEY_AURA_FEAR:
8529 			toggle_aura(player, 0);
8530 			break;
8531 		case MKEY_AURA_SHIVER:
8532 			toggle_aura(player, 1);
8533 			break;
8534 		case MKEY_AURA_DEATH:
8535 			toggle_aura(player, 2);
8536 			break;
8537 
8538 		case MKEY_MELEE:
8539 			do_cmd_melee_technique(player, spell);
8540 			break;
8541 		case MKEY_RANGED:
8542 			do_cmd_ranged_technique(player, spell);
8543 			break;
8544 		case MKEY_SHOOT_TILL_KILL:
8545 			toggle_shoot_till_kill(player);
8546 			break;
8547 #ifdef DUAL_WIELD
8548 		case MKEY_DUAL_MODE:
8549 			toggle_dual_mode(player);
8550 			break;
8551 #endif
8552 		case MKEY_BREATH:
8553 			/* Sanity check #2 */
8554 			if (dir == -1) dir = 5;
8555 
8556 			//do_cmd_breathe(player);
8557 			do_cmd_breathe_aux(player, dir);
8558 			break;
8559 		}
8560 		return 2;
8561 	} else if (p_ptr) {
8562 		p_ptr->current_spell = -1;
8563 		p_ptr->current_mind = -1;
8564 		Packet_printf(&connp->q, "%c%c%hd%hd%c%hd%hd", ch, mkey, book, spell, dir, item, aux);
8565 		return 0;
8566 	}
8567 
8568 
8569 	return 1;
8570 }
8571 
8572 static int Receive_open(int ind)
8573 {
8574 	connection_t *connp = Conn[ind];
8575 	player_type *p_ptr = NULL;
8576 	char ch, dir;
8577 	int n, player = -1;
8578 
8579 	if (connp->id != -1) {
8580 		player = GetInd[connp->id];
8581 		use_esp_link(&player, LINKF_OBJ);
8582 		p_ptr = Players[player];
8583 	}
8584 
8585 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
8586 		if (n == -1)
8587 			Destroy_connection(ind, "read error");
8588 		return n;
8589 	}
8590 
8591 	/* Sanity check */
8592 	if (bad_dir(dir)) return 1;
8593 
8594 	/* all this is temp just to make it work */
8595 	if (p_ptr->command_rep == -1) {
8596 		p_ptr->command_rep = 0;
8597 		return 0;
8598 	}
8599 	if (p_ptr && p_ptr->command_rep != PKT_OPEN)
8600 		p_ptr->command_rep = -1;
8601 
8602 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8603 		do_cmd_open(player, dir);
8604 		if (p_ptr->command_rep) Packet_printf(&connp->q, "%c%c", ch, dir);
8605 		return 2;
8606 	} else if (p_ptr) {
8607 		Packet_printf(&connp->q, "%c%c", ch, dir);
8608 		return 0;
8609 	}
8610 
8611 	return 1;
8612 }
8613 
8614 static int Receive_mind(int ind)
8615 {
8616 	connection_t *connp = Conn[ind];
8617 	char ch;
8618 	int n, player = 0;
8619 
8620 	if (connp->id != -1) player = GetInd[connp->id];
8621 
8622 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
8623 		if (n == -1) Destroy_connection(ind, "read error");
8624 		return n;
8625 	}
8626 
8627 	if (player) {
8628 		change_mind(player, TRUE);
8629 		return 2;
8630 	}
8631 	return 1;
8632 }
8633 
8634 static int Receive_ghost(int ind)
8635 {
8636 	connection_t *connp = Conn[ind];
8637 	player_type *p_ptr = NULL;
8638 
8639 	char ch;
8640 
8641 	int n, player = -1;
8642 
8643 	s16b ability;
8644 
8645 	if (connp->id != -1)
8646 	{
8647 		player = GetInd[connp->id];
8648 		p_ptr = Players[player];
8649 	}
8650 
8651 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &ability)) <= 0)
8652 	{
8653 		if (n == -1)
8654 			Destroy_connection(ind, "read error");
8655 		return n;
8656 	}
8657 
8658 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
8659 	{
8660 		do_cmd_ghost_power(player, ability);
8661 		return 2;
8662 	}
8663 	else if (p_ptr)
8664 	{
8665 		Packet_printf(&connp->q, "%c%hd", ch, ability);
8666 		return 0;
8667 	}
8668 
8669 	return 1;
8670 }
8671 
8672 static int Receive_quaff(int ind)
8673 {
8674 	connection_t *connp = Conn[ind];
8675 	player_type *p_ptr = NULL;
8676 	char ch;
8677 	s16b item;
8678 	int n, player = -1;
8679 
8680 	if (connp->id != -1)
8681 	{
8682 		player = GetInd[connp->id];
8683 		use_esp_link(&player, LINKF_OBJ);
8684 		p_ptr = Players[player];
8685 	}
8686 
8687 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
8688 	{
8689 		if (n == -1)
8690 			Destroy_connection(ind, "read error");
8691 		return n;
8692 	}
8693 
8694 	/* Sanity check - mikaelh */
8695 	if (item >= INVEN_TOTAL)
8696 		return 1;
8697 
8698 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
8699 	{
8700 		item = replay_inven_changes(player, item);
8701 		if (item == 0xFF)
8702 		{
8703 			msg_print(player, "Command failed because item is gone.");
8704 			return 1;
8705 		}
8706 
8707 		do_cmd_quaff_potion(player, item);
8708 		return 2;
8709 	}
8710 	else if (p_ptr)
8711 	{
8712 		Packet_printf(&connp->q, "%c%hd", ch, item);
8713 		return 0;
8714 	}
8715 
8716 	return 1;
8717 }
8718 
8719 static int Receive_read(int ind)
8720 {
8721 	connection_t *connp = Conn[ind];
8722 	player_type *p_ptr = NULL;
8723 	char ch;
8724 	s16b item;
8725 	int n, player = -1;
8726 
8727 	if (connp->id != -1)
8728 	{
8729 		player = GetInd[connp->id];
8730 		use_esp_link(&player, LINKF_OBJ);
8731 		p_ptr = Players[player];
8732 	}
8733 
8734 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
8735 	{
8736 		if (n == -1)
8737 			Destroy_connection(ind, "read error");
8738 		return n;
8739 	}
8740 
8741 	/* Sanity check - mikaelh */
8742 	if (item >= INVEN_TOTAL)
8743 		return 1;
8744 
8745 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
8746 	{
8747 		item = replay_inven_changes(player, item);
8748 		if (item == 0xFF)
8749 		{
8750 			msg_print(player, "Command failed because item is gone.");
8751 			return 1;
8752 		}
8753 
8754 		do_cmd_read_scroll(player, item);
8755 		return 2;
8756 	}
8757 	else if (p_ptr)
8758 	{
8759 		Packet_printf(&connp->q, "%c%hd", ch, item);
8760 		return 0;
8761 	}
8762 
8763 	return 1;
8764 }
8765 
8766 static int Receive_search(int ind)
8767 {
8768 	connection_t *connp = Conn[ind];
8769 	player_type *p_ptr = NULL;
8770 	char ch;
8771 	int n, player = -1;
8772 
8773 	if (connp->id != -1) {
8774 		player = GetInd[connp->id];
8775 		use_esp_link(&player, LINKF_MOV);
8776 		p_ptr = Players[player];
8777 	}
8778 
8779 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
8780 		if (n == -1)
8781 			Destroy_connection(ind, "read error");
8782 		return n;
8783 	}
8784 
8785 	/* all this is temp just to make it work */
8786 	if (p_ptr->command_rep == -1) {
8787 		p_ptr->command_rep = 0;
8788 		return(0);
8789 	}
8790 	if (p_ptr && p_ptr->command_rep != PKT_SEARCH) {
8791 		p_ptr->command_rep = -1;
8792 	}
8793 
8794 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8795 		do_cmd_search(player);
8796 		if (p_ptr->command_rep) Packet_printf(&connp->q, "%c", ch);
8797 		return 2;
8798 	} else if (p_ptr) {
8799 		Packet_printf(&connp->q, "%c", ch);
8800 		return 0;
8801 	}
8802 
8803 	return 1;
8804 }
8805 
8806 static int Receive_take_off(int ind)
8807 {
8808 	connection_t *connp = Conn[ind];
8809 	player_type *p_ptr = NULL;
8810 	char ch;
8811 	s16b item;
8812 	int n, player = -1;
8813 
8814 	if (connp->id != -1) {
8815 		player = GetInd[connp->id];
8816 		use_esp_link(&player, LINKF_OBJ);
8817 		p_ptr = Players[player];
8818 	}
8819 
8820 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0) {
8821 		if (n == -1) Destroy_connection(ind, "read error");
8822 		return n;
8823 	}
8824 
8825 	/* Sanity check - mikaelh */
8826 	if (item >= INVEN_TOTAL)
8827 		return 1;
8828 
8829 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
8830 	{
8831 		item = replay_inven_changes(player, item);
8832 		if (item == 0xFF)
8833 		{
8834 			msg_print(player, "Command failed because item is gone.");
8835 			return 1;
8836 		}
8837 
8838 		do_cmd_takeoff(player, item, 255);
8839 		return 2;
8840 	}
8841 	else if (p_ptr)
8842 	{
8843 		Packet_printf(&connp->q, "%c%hd", ch, item);
8844 		return 0;
8845 	}
8846 
8847 	return 1;
8848 }
8849 
8850 static int Receive_take_off_amt(int ind)
8851 {
8852 	connection_t *connp = Conn[ind];
8853 	player_type *p_ptr = NULL;
8854 	char ch;
8855 	s16b item, amt;
8856 	int n, player = -1;
8857 
8858 	if (connp->id != -1)
8859 	{
8860 		player = GetInd[connp->id];
8861 		use_esp_link(&player, LINKF_OBJ);
8862 		p_ptr = Players[player];
8863 	}
8864 
8865 	if ((n = Packet_scanf(&connp->r, "%c%hd%hd", &ch, &item, &amt)) <= 0)
8866 	{
8867 		if (n == -1)
8868 			Destroy_connection(ind, "read error");
8869 		return n;
8870 	}
8871 
8872 	/* Sanity check - mikaelh */
8873 	if (item >= INVEN_TOTAL)
8874 		return 1;
8875 
8876 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
8877 	{
8878 		item = replay_inven_changes(player, item);
8879 		if (item == 0xFF)
8880 		{
8881 			msg_print(player, "Command failed because item is gone.");
8882 			return 1;
8883 		}
8884 
8885 		do_cmd_takeoff(player, item, amt);
8886 		return 2;
8887 	}
8888 	else if (p_ptr)
8889 	{
8890 		Packet_printf(&connp->q, "%c%hd%hd", ch, item, amt);
8891 		return 0;
8892 	}
8893 
8894 	return 1;
8895 }
8896 
8897 static int Receive_use(int ind)
8898 {
8899 	connection_t *connp = Conn[ind];
8900 	player_type *p_ptr = NULL;
8901 	char ch;
8902 	s16b item;
8903 	int n, player = -1;
8904 
8905 	if (connp->id != -1)
8906 	{
8907 		player = GetInd[connp->id];
8908 		use_esp_link(&player, LINKF_OBJ);
8909 		p_ptr = Players[player];
8910 	}
8911 
8912 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
8913 	{
8914 		if (n == -1)
8915 			Destroy_connection(ind, "read error");
8916 		return n;
8917 	}
8918 
8919 	/* Sanity check - mikaelh */
8920 	if (item >= INVEN_TOTAL)
8921 		return 1;
8922 
8923 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
8924 	{
8925 		item = replay_inven_changes(player, item);
8926 		if (item == 0xFF)
8927 		{
8928 			msg_print(player, "Command failed because item is gone.");
8929 			return 1;
8930 		}
8931 
8932 		do_cmd_use_staff(player, item);
8933 		return 2;
8934 	}
8935 	else if (p_ptr)
8936 	{
8937 		Packet_printf(&connp->q, "%c%hd", ch, item);
8938 		return 0;
8939 	}
8940 
8941 	return 1;
8942 }
8943 
8944 static int Receive_throw(int ind)
8945 {
8946 	connection_t *connp = Conn[ind];
8947 	player_type *p_ptr = NULL;
8948 	char ch, dir;
8949 	int n, player = -1;
8950 	s16b item;
8951 
8952 	if (connp->id != -1) {
8953 		player = GetInd[connp->id];
8954 		use_esp_link(&player, LINKF_OBJ);
8955 		p_ptr = Players[player];
8956 	}
8957 
8958 	if ((n = Packet_scanf(&connp->r, "%c%c%hd", &ch, &dir, &item)) <= 0) {
8959 		if (n == -1)
8960 			Destroy_connection(ind, "read error");
8961 		return n;
8962 	}
8963 
8964 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
8965 		/* Sanity check - mikaelh */
8966 		if (item >= INVEN_TOTAL) return 1;
8967 		if (bad_dir1(player, &dir)) return 1;
8968 
8969 		item = replay_inven_changes(player, item);
8970 		if (item == 0xFF) {
8971 			msg_print(player, "Command failed because item is gone.");
8972 			return 1;
8973 		}
8974 
8975 		do_cmd_throw(player, dir, item, 0);
8976 		return 2;
8977 	} else if (p_ptr) {
8978 		Packet_printf(&connp->q, "%c%c%hd", ch, dir, item);
8979 		return 0;
8980 	}
8981 
8982 	return 1;
8983 }
8984 
8985 static int Receive_wield(int ind)
8986 {
8987 	connection_t *connp = Conn[ind];
8988 	player_type *p_ptr = NULL;
8989 	char ch;
8990 	s16b item;
8991 	int n, player = -1;
8992 
8993 	if (connp->id != -1)
8994 	{
8995 		player = GetInd[connp->id];
8996 		use_esp_link(&player, LINKF_OBJ);
8997 		p_ptr = Players[player];
8998 	}
8999 
9000 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
9001 	{
9002 		if (n == -1)
9003 			Destroy_connection(ind, "read error");
9004 		return n;
9005 	}
9006 
9007 	/* Sanity check - mikaelh */
9008 	if (item >= INVEN_TOTAL) return 1;
9009 
9010 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
9011 	{
9012 		item = replay_inven_changes(player, item);
9013 		if (item == 0xFF)
9014 		{
9015 			msg_print(player, "Command failed because item is gone.");
9016 			return 1;
9017 		}
9018 
9019 		do_cmd_wield(player, item, 0x0);
9020 		return 2;
9021 	}
9022 	else if (p_ptr)
9023 	{
9024 		Packet_printf(&connp->q, "%c%hd", ch, item);
9025 		return 0;
9026 	}
9027 
9028 	return 1;
9029 }
9030 
9031 static int Receive_zap(int ind)
9032 {
9033 	connection_t *connp = Conn[ind];
9034 	player_type *p_ptr = NULL;
9035 	char ch;
9036 	s16b item;
9037 	int n, player = -1;
9038 
9039 	if (connp->id != -1)
9040 	{
9041 		player = GetInd[connp->id];
9042 		use_esp_link(&player, LINKF_OBJ);
9043 		p_ptr = Players[player];
9044 	}
9045 
9046 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
9047 	{
9048 		if (n == -1)
9049 			Destroy_connection(ind, "read error");
9050 		return n;
9051 	}
9052 
9053 	/* Sanity check - mikaelh */
9054 	if (item >= INVEN_TOTAL)
9055 		return 1;
9056 
9057 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
9058 	{
9059 		item = replay_inven_changes(player, item);
9060 		if (item == 0xFF)
9061 		{
9062 			msg_print(player, "Command failed because item is gone.");
9063 			return 1;
9064 		}
9065 
9066 		do_cmd_zap_rod(player, item, 0);
9067 		return 2;
9068 	}
9069 	else if (p_ptr)
9070 	{
9071 		Packet_printf(&connp->q, "%c%hd", ch, item);
9072 		return 0;
9073 	}
9074 
9075 	return 1;
9076 }
9077 
9078 static int Receive_zap_dir(int ind)
9079 {
9080 	connection_t *connp = Conn[ind];
9081 	player_type *p_ptr = NULL;
9082 	char ch, dir;
9083 	s16b item;
9084 	int n, player = -1;
9085 
9086 	if (connp->id != -1) {
9087 		player = GetInd[connp->id];
9088 		use_esp_link(&player, LINKF_OBJ);
9089 		p_ptr = Players[player];
9090 	}
9091 
9092 	if ((n = Packet_scanf(&connp->r, "%c%hd%c", &ch, &item, &dir)) <= 0) {
9093 		if (n == -1)
9094 			Destroy_connection(ind, "read error");
9095 		return n;
9096 	}
9097 
9098 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9099 		/* Sanity check - mikaelh */
9100 		if (item >= INVEN_TOTAL) return 1;
9101 		if (bad_dir1(player, &dir)) return 1;
9102 
9103 		item = replay_inven_changes(player, item);
9104 		if (item == 0xFF) {
9105 			msg_print(player, "Command failed because item is gone.");
9106 			return 1;
9107 		}
9108 
9109 		do_cmd_zap_rod(player, item, dir);
9110 		return 2;
9111 	} else if (p_ptr) {
9112 		Packet_printf(&connp->q, "%c%hd%c", ch, item, dir);
9113 		return 0;
9114 	}
9115 
9116 	return 1;
9117 }
9118 
9119 static int Receive_target(int ind)
9120 {
9121 	connection_t *connp = Conn[ind];
9122 	player_type *p_ptr = NULL;
9123 	char ch;
9124 	s16b dir;
9125 	int n, player = -1;
9126 
9127 	if (connp->id != -1)
9128 	{
9129 		player = GetInd[connp->id];
9130 		use_esp_link(&player, LINKF_OBJ);
9131 		p_ptr = Players[player];
9132 	}
9133 
9134 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &dir)) <= 0)
9135 	{
9136 		if (n == -1)
9137 			Destroy_connection(ind, "read error");
9138 		return n;
9139 	}
9140 
9141 	/* Sanity check */
9142 	if (bad_dir(dir) && bad_dir2(dir)) return 1;
9143 
9144 	if (p_ptr)
9145 		do_cmd_target(player, dir);
9146 
9147 	return 1;
9148 }
9149 
9150 static int Receive_target_friendly(int ind)
9151 {
9152 	connection_t *connp = Conn[ind];
9153 	player_type *p_ptr = NULL;
9154 
9155 	char ch;
9156 
9157 	s16b dir;
9158 	int n, player = -1;
9159 
9160 	if (connp->id != -1)
9161 	{
9162 		player = GetInd[connp->id];
9163 		use_esp_link(&player, LINKF_OBJ);
9164 		p_ptr = Players[player];
9165 	}
9166 
9167 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &dir)) <= 0)
9168 	{
9169 		if (n == -1)
9170 			Destroy_connection(ind, "read error");
9171 		return n;
9172 	}
9173 
9174 	/* Sanity check */
9175 	if (bad_dir(dir) && bad_dir2(dir)) return 1;
9176 
9177 	if (p_ptr)
9178 		do_cmd_target_friendly(player, dir);
9179 
9180 	return 1;
9181 }
9182 
9183 
9184 static int Receive_inscribe(int ind)
9185 {
9186 	connection_t *connp = Conn[ind];
9187 	player_type *p_ptr = NULL;
9188 	char ch;
9189 	int n, player = -1;
9190 	s16b item;
9191 	char inscription[MAX_CHARS];
9192 
9193 	if (connp->id != -1)
9194 	{
9195 		player = GetInd[connp->id];
9196 		use_esp_link(&player, LINKF_OBJ);
9197 		p_ptr = Players[player];
9198 	}
9199 
9200 	if ((n = Packet_scanf(&connp->r, "%c%hd%s", &ch, &item, inscription)) <= 0)
9201 	{
9202 		if (n == -1)
9203 			Destroy_connection(ind, "read error");
9204 		return n;
9205 	}
9206 	/* paranoia? */
9207 	inscription[MAX_CHARS - 1] = '\0';
9208 
9209 	/* Sanity check - mikaelh */
9210 	if (item >= INVEN_TOTAL)
9211 		return 1;
9212 
9213 	if (p_ptr)
9214 	{
9215 		item = replay_inven_changes(player, item);
9216 		if (item == 0xFF)
9217 		{
9218 			msg_print(player, "Command failed because item is gone.");
9219 			return 1;
9220 		}
9221 
9222 		do_cmd_inscribe(player, item, inscription);
9223 	}
9224 
9225 	return 1;
9226 }
9227 
9228 static int Receive_uninscribe(int ind)
9229 {
9230 	connection_t *connp = Conn[ind];
9231 	char ch;
9232 	int n, player = -1;
9233 	s16b item;
9234 	player_type *p_ptr = NULL;
9235 
9236 	if (connp->id != -1)
9237 	{
9238 		player = GetInd[connp->id];
9239 		use_esp_link(&player, LINKF_OBJ);
9240 		p_ptr = Players[player];
9241 	}
9242 
9243 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
9244 	{
9245 		if (n == -1)
9246 			Destroy_connection(ind, "read error");
9247 		return n;
9248 	}
9249 
9250 	/* Sanity check - mikaelh */
9251 	if (item >= INVEN_TOTAL)
9252 		return 1;
9253 
9254 	if (p_ptr)
9255 	{
9256 		item = replay_inven_changes(player, item);
9257 		if (item == 0xFF)
9258 		{
9259 			msg_print(player, "Command failed because item is gone.");
9260 			return 1;
9261 		}
9262 
9263 		do_cmd_uninscribe(player, item);
9264 	}
9265 
9266 	return 1;
9267 }
9268 
9269 static int Receive_autoinscribe(int ind) {
9270 	connection_t *connp = Conn[ind];
9271 	char ch;
9272 	int n, player = -1;
9273 	s16b item;
9274 	player_type *p_ptr = NULL;
9275 
9276 	if (connp->id != -1) {
9277 		player = GetInd[connp->id];
9278 		use_esp_link(&player, LINKF_OBJ);
9279 		p_ptr = Players[player];
9280 	}
9281 
9282 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0) {
9283 		if (n == -1) Destroy_connection(ind, "read error");
9284 		return n;
9285 	}
9286 
9287 	/* Sanity check - mikaelh */
9288 	if (item >= INVEN_TOTAL) return 1;
9289 
9290 	if (p_ptr) {
9291 		item = replay_inven_changes(player, item);
9292 		if (item == 0xFF) {
9293 			msg_print(player, "Command failed because item is gone.");
9294 			return 1;
9295 		}
9296 
9297 		auto_inscribe(player, &(p_ptr->inventory[item]), TRUE);
9298 		p_ptr->window |= PW_INVEN;
9299 	}
9300 
9301 	return 1;
9302 }
9303 
9304 static int Receive_activate(int ind)
9305 {
9306 	connection_t *connp = Conn[ind];
9307 	player_type *p_ptr = NULL;
9308 	char ch;
9309 	s16b item;
9310 	int n, player = -1;
9311 
9312 	if (connp->id != -1)
9313 	{
9314 		player = GetInd[connp->id];
9315 		use_esp_link(&player, LINKF_OBJ);
9316 		p_ptr = Players[player];
9317 	}
9318 
9319 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
9320 	{
9321 		if (n == -1)
9322 			Destroy_connection(ind, "read error");
9323 		return n;
9324 	}
9325 
9326 	/* Sanity check - mikaelh */
9327 	if (item >= INVEN_TOTAL)
9328 		return 1;
9329 
9330 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
9331 	{
9332 		item = replay_inven_changes(player, item);
9333 		if (item == 0xFF)
9334 		{
9335 			msg_print(player, "Command failed because item is gone.");
9336 			return 1;
9337 		}
9338 
9339 		do_cmd_activate(player, item, 0);
9340 		return 2;
9341 	}
9342 	else if (p_ptr)
9343 	{
9344 		Packet_printf(&connp->q, "%c%hd", ch, item);
9345 		return 0;
9346 	}
9347 
9348 	return 1;
9349 }
9350 
9351 static int Receive_activate_dir(int ind)
9352 {
9353 	connection_t *connp = Conn[ind];
9354 	player_type *p_ptr = NULL;
9355 	char ch, dir;
9356 	s16b item;
9357 	int n, player = -1;
9358 
9359 	if (connp->id != -1) {
9360 		player = GetInd[connp->id];
9361 		use_esp_link(&player, LINKF_OBJ);
9362 		p_ptr = Players[player];
9363 	}
9364 
9365 	if ((n = Packet_scanf(&connp->r, "%c%hd%c", &ch, &item, &dir)) <= 0) {
9366 		if (n == -1) Destroy_connection(ind, "read error");
9367 		return n;
9368 	}
9369 
9370 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9371 		/* Sanity check - mikaelh */
9372 		if (item >= INVEN_TOTAL) return 1;
9373 		if (bad_dir1(player, &dir)) return 1;
9374 
9375 		item = replay_inven_changes(player, item);
9376 		if (item == 0xFF) {
9377 			msg_print(player, "Command failed because item is gone.");
9378 			return 1;
9379 		}
9380 
9381 		do_cmd_activate(player, item, dir);
9382 		return 2;
9383 	} else if (p_ptr) {
9384 		Packet_printf(&connp->q, "%c%hd%c", ch, item, dir);
9385 		return 0;
9386 	}
9387 
9388 	return 1;
9389 }
9390 
9391 static int Receive_bash(int ind)
9392 {
9393 	connection_t *connp = Conn[ind];
9394 	player_type *p_ptr = NULL;
9395 	char ch, dir;
9396 	int n, player = -1;
9397 
9398 	if (connp->id != -1) {
9399 		player = GetInd[connp->id];
9400 		use_esp_link(&player, LINKF_MOV);
9401 		p_ptr = Players[player];
9402 	}
9403 
9404 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
9405 		if (n == -1) Destroy_connection(ind, "read error");
9406 		return n;
9407 	}
9408 
9409 	/* Sanity check */
9410 	if (bad_dir(dir)) return 1;
9411 
9412 	/* all this is temp just to make it work */
9413 	if (p_ptr->command_rep == -1) {
9414 		p_ptr->command_rep = 0;
9415 		return(0);
9416 	}
9417 
9418 	if (p_ptr && p_ptr->command_rep != PKT_BASH) {
9419 		p_ptr->command_rep = -1;
9420 	}
9421 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9422 		do_cmd_bash(player, dir);
9423 		if (p_ptr->command_rep) Packet_printf(&connp->q, "%c%c", ch, dir);
9424 		return 2;
9425 	} else if (p_ptr) {
9426 		Packet_printf(&connp->q, "%c%c", ch, dir);
9427 		return 0;
9428 	}
9429 
9430 	return 1;
9431 }
9432 
9433 static int Receive_disarm(int ind)
9434 {
9435 	connection_t *connp = Conn[ind];
9436 	player_type *p_ptr = NULL;
9437 	char ch, dir;
9438 	int n, player = -1;
9439 
9440 	if (connp->id != -1) {
9441 		player = GetInd[connp->id];
9442 		use_esp_link(&player, LINKF_MOV);
9443 		p_ptr = Players[player];
9444 	}
9445 
9446 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
9447 		if (n == -1) Destroy_connection(ind, "read error");
9448 		return n;
9449 	}
9450 
9451 	/* Sanity check */
9452 	if (bad_dir(dir)) return 1;
9453 
9454 	/* all this is temp just to make it work */
9455 	if (p_ptr->command_rep == -1) {
9456 		p_ptr->command_rep = 0;
9457 		return(0);
9458 	}
9459 	if (p_ptr && p_ptr->command_rep != PKT_DISARM) p_ptr->command_rep = -1;
9460 
9461 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9462 		do_cmd_disarm(player, dir);
9463 		if (p_ptr->command_rep) Packet_printf(&connp->q, "%c%c", ch, dir);
9464 		return 2;
9465 	} else if (p_ptr) {
9466 		Packet_printf(&connp->q, "%c%c", ch, dir);
9467 		return 0;
9468 	}
9469 	return 1;
9470 }
9471 
9472 static int Receive_eat(int ind)
9473 {
9474 	connection_t *connp = Conn[ind];
9475 	player_type *p_ptr = NULL;
9476 	char ch;
9477 	s16b item;
9478 	int n, player = -1;
9479 
9480 	if (connp->id != -1) {
9481 		player = GetInd[connp->id];
9482 		use_esp_link(&player, LINKF_OBJ);
9483 		p_ptr = Players[player];
9484 	}
9485 
9486 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0) {
9487 		if (n == -1) Destroy_connection(ind, "read error");
9488 		return n;
9489 	}
9490 
9491 	/* Sanity check - mikaelh */
9492 	if (item >= INVEN_TOTAL)
9493 		return 1;
9494 
9495 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9496 		item = replay_inven_changes(player, item);
9497 		if (item == 0xFF) {
9498 			msg_print(player, "Command failed because item is gone.");
9499 			return 1;
9500 		}
9501 
9502 		do_cmd_eat_food(player, item);
9503 		return 2;
9504 	} else if (p_ptr) {
9505 		Packet_printf(&connp->q, "%c%hd", ch, item);
9506 		return 0;
9507 	}
9508 	return 1;
9509 }
9510 
9511 static int Receive_fill(int ind)
9512 {
9513 	connection_t *connp = Conn[ind];
9514 	player_type *p_ptr = NULL;
9515 	char ch;
9516 	s16b item;
9517 	int n, player = -1;
9518 
9519 	if (connp->id != -1) {
9520 		player = GetInd[connp->id];
9521 		use_esp_link(&player, LINKF_OBJ);
9522 		p_ptr = Players[player];
9523 	}
9524 
9525 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0) {
9526 		if (n == -1) Destroy_connection(ind, "read error");
9527 		return n;
9528 	}
9529 
9530 	/* Sanity check - mikaelh */
9531 	if (item >= INVEN_TOTAL)
9532 		return 1;
9533 
9534 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9535 		item = replay_inven_changes(player, item);
9536 		if (item == 0xFF) {
9537 			msg_print(player, "Command failed because item is gone.");
9538 			return 1;
9539 		}
9540 		do_cmd_refill(player, item);
9541 		return 2;
9542 	} else if (p_ptr) {
9543 		Packet_printf(&connp->q, "%c%hd", ch, item);
9544 		return 0;
9545 	}
9546 	return 1;
9547 }
9548 
9549 static int Receive_locate(int ind)
9550 {
9551 	connection_t *connp = Conn[ind];
9552 	player_type *p_ptr = NULL;
9553 	char ch, dir;
9554 	int n, player = -1;
9555 
9556 	if (connp->id != -1) {
9557 		player = GetInd[connp->id];
9558 		use_esp_link(&player, LINKF_MOV);
9559 		p_ptr = Players[player];
9560 	}
9561 
9562 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
9563 		if (n == -1) Destroy_connection(ind, "read error");
9564 		return n;
9565 	}
9566 
9567 	/* Sanity check */
9568 	if (bad_dir(dir)) return 1;
9569 
9570 	if (p_ptr) {
9571 #if 0 /* too much slowdown of the game play ~~ */
9572 		if (!is_admin(p_ptr) && p_ptr->redraw_cooldown) {
9573 			Packet_printf(&connp->q, "%c%c", ch, dir);
9574 			return 0;
9575 		}
9576 		/* have a small cooldown, albeit less than like from CTRL+R'ing directly */
9577 		p_ptr->redraw_cooldown = 1;
9578 #endif
9579 		do_cmd_locate(player, dir);
9580 	}
9581 
9582 	return 1;
9583 }
9584 
9585 static int Receive_map(int ind)
9586 {
9587 	connection_t *connp = Conn[ind];
9588 	char ch, mode;
9589 	int n, player = -1;
9590 	player_type *p_ptr = NULL;
9591 
9592 	if (connp->id != -1) {
9593 		player = GetInd[connp->id];
9594 		use_esp_link(&player, LINKF_OBJ);
9595 		p_ptr = Players[player];
9596 	}
9597 
9598 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &mode)) <= 0) {
9599 		if (n == -1) Destroy_connection(ind, "read error");
9600 		return n;
9601 	}
9602 
9603 	if (p_ptr) do_cmd_view_map(player, mode);
9604 	return 1;
9605 }
9606 
9607 static int Receive_search_mode(int ind)
9608 {
9609 	connection_t *connp = Conn[ind];
9610 	char ch;
9611 	int n, player = -1;
9612 	player_type *p_ptr = NULL;
9613 
9614 	if (connp->id != -1) {
9615 		player = GetInd[connp->id];
9616 		use_esp_link(&player, LINKF_OBJ);
9617 		p_ptr = Players[player];
9618 	}
9619 
9620 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
9621 		if (n == -1) Destroy_connection(ind, "read error");
9622 		return n;
9623 	}
9624 
9625 	if (p_ptr) do_cmd_toggle_search(player);
9626 	return 1;
9627 }
9628 
9629 static int Receive_close(int ind)
9630 {
9631 	connection_t *connp = Conn[ind];
9632 	player_type *p_ptr = NULL;
9633 	char ch, dir;
9634 	int n, player = -1;
9635 
9636 	if (connp->id != -1) {
9637 		player = GetInd[connp->id];
9638 		use_esp_link(&player, LINKF_OBJ);
9639 		p_ptr = Players[player];
9640 	}
9641 
9642 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
9643 		if (n == -1) Destroy_connection(ind, "read error");
9644 		return n;
9645 	}
9646 
9647 	/* Sanity check */
9648 	if (bad_dir(dir)) return 1;
9649 
9650 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9651 		do_cmd_close(player, dir);
9652 		return 2;
9653 	} else if (p_ptr) {
9654 		Packet_printf(&connp->q, "%c%c", ch, dir);
9655 		return 0;
9656 	}
9657 	return 1;
9658 }
9659 
9660 static int Receive_skill_mod(int ind)
9661 {
9662 	connection_t *connp = Conn[ind];
9663 	player_type *p_ptr = NULL;
9664 	char ch;
9665 	s32b i;
9666 	int n, player = -1;
9667 
9668 	if (connp->id != -1) {
9669 		player = GetInd[connp->id];
9670 		p_ptr = Players[player];
9671 	}
9672 
9673 	if ((n = Packet_scanf(&connp->r, "%c%d", &ch, &i)) <= 0) {
9674 		if (n == -1) Destroy_connection(ind, "read error");
9675 		return n;
9676 	}
9677 
9678 	if (p_ptr) increase_skill(player, i, FALSE);
9679 	return 1;
9680 }
9681 
9682 static int Receive_skill_dev(int ind) {
9683 	connection_t *connp = Conn[ind];
9684 	player_type *p_ptr = NULL;
9685 	char ch;
9686 	s32b i;
9687 	bool dev;
9688 	int n, player = -1;
9689 
9690 	if (connp->id != -1) {
9691 		player = GetInd[connp->id];
9692 		p_ptr = Players[player];
9693 	}
9694 
9695 	if ((n = Packet_scanf(&connp->r, "%c%d%c", &ch, &i, &dev)) <= 0) {
9696 		if (n == -1) Destroy_connection(ind, "read error");
9697 		return n;
9698 	}
9699 
9700 	if (p_ptr) {
9701 		if (i == -1) {
9702 			/* do it for whole skill tree? */
9703 			for (i = 0; i < MAX_SKILLS; i++) {
9704 				p_ptr->s_info[i].dev = (dev == 0 ? FALSE : TRUE);
9705 			}
9706 		} else {
9707 			/* only do it for one skill */
9708 			p_ptr->s_info[i].dev = (dev == 0 ? FALSE : TRUE);
9709 		}
9710 	}
9711 	return 1;
9712 }
9713 
9714 static int Receive_go_up(int ind)
9715 {
9716 	connection_t *connp = Conn[ind];
9717 	player_type *p_ptr = NULL;
9718 	char ch;
9719 	int n, player = -1;
9720 
9721 	if (connp->id != -1) {
9722 		player = GetInd[connp->id];
9723 		use_esp_link(&player, LINKF_OBJ);
9724 		p_ptr = Players[player];
9725 	}
9726 
9727 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
9728 		if (n == -1) Destroy_connection(ind, "read error");
9729 		return n;
9730 	}
9731 
9732 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9733 		do_cmd_go_up(player);
9734 		return 2;
9735 	} else if (p_ptr) {
9736 		Packet_printf(&connp->q, "%c", ch);
9737 		return 0;
9738 	}
9739 	return 1;
9740 }
9741 
9742 static int Receive_go_down(int ind)
9743 {
9744 	connection_t *connp = Conn[ind];
9745 	player_type *p_ptr = NULL;
9746 	char ch;
9747 	int n, player = -1;
9748 
9749 	if (connp->id != -1) {
9750 		player = GetInd[connp->id];
9751 		use_esp_link(&player, LINKF_OBJ);
9752 		p_ptr = Players[player];
9753 	}
9754 
9755 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
9756 		if (n == -1) Destroy_connection(ind, "read error");
9757 		return n;
9758 	}
9759 
9760 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
9761 		do_cmd_go_down(player);
9762 		return 2;
9763 	} else if (p_ptr) {
9764 		Packet_printf(&connp->q, "%c", ch);
9765 		return 0;
9766 	}
9767 	return 1;
9768 }
9769 
9770 
9771 static int Receive_direction(int ind)
9772 {
9773 	connection_t *connp = Conn[ind];
9774 	char ch, dir;
9775 	int n, player = -1;
9776 	player_type *p_ptr = NULL;
9777 
9778 	if (connp->id != -1) {
9779 		player = GetInd[connp->id];
9780 		use_esp_link(&player, LINKF_OBJ);
9781 		p_ptr = Players[player];
9782 	}
9783 	else player = 0;
9784 
9785 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
9786 		if (n == -1) Destroy_connection(ind, "read error");
9787 		return n;
9788 	}
9789 
9790 	/* Sanity check */
9791 	if (bad_dir1(player, &dir)) return 1;
9792 
9793 	if (p_ptr) Handle_direction(player, dir);
9794 
9795 	return 1;
9796 }
9797 
9798 static int Receive_item(int ind)
9799 {
9800 	connection_t *connp = Conn[ind];
9801 	char ch;
9802 	s16b item;
9803 	int n, player = -1;
9804 	player_type *p_ptr = NULL;
9805 
9806 	if (connp->id != -1) {
9807 		player = GetInd[connp->id];
9808 		use_esp_link(&player, LINKF_OBJ);
9809 		p_ptr = Players[player];
9810 	}
9811 	else player = 0;
9812 
9813 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0) {
9814 		if (n == -1) Destroy_connection(ind, "read error");
9815 		return n;
9816 	}
9817 
9818 	/* Sanity check - mikaelh */
9819 	if (item >= INVEN_TOTAL)
9820 		return 1;
9821 
9822 	if (p_ptr) {
9823 		item = replay_inven_changes(player, item);
9824 		if (item == 0xFF) {
9825 			msg_print(player, "Command failed because item is gone.");
9826 			return 1;
9827 		}
9828 		Handle_item(player, item);
9829 	}
9830 	return 1;
9831 }
9832 
9833 /* for DISCRETE_SPELL_SYSTEM: DSS_EXPANDED_SCROLLS */
9834 static int Receive_spell(int ind) {
9835 	connection_t *connp = Conn[ind];
9836 	char ch;
9837 	s16b item, spell;
9838 	int n, player = -1;
9839 	player_type *p_ptr = NULL;
9840 
9841 	if (connp->id != -1) {
9842 		player = GetInd[connp->id];
9843 		use_esp_link(&player, LINKF_OBJ);
9844 		p_ptr = Players[player];
9845 	}
9846 	else player = 0;
9847 
9848 	if ((n = Packet_scanf(&connp->r, "%c%hd%hd", &ch, &item, &spell)) <= 0) {
9849 		if (n == -1) Destroy_connection(ind, "read error");
9850 		return n;
9851 	}
9852 
9853 	/* Sanity check - mikaelh */
9854 	if (item >= INVEN_TOTAL)
9855 		return 1;
9856 	if (spell > max_spells) return 1;
9857 
9858 	if (p_ptr) {
9859 		item = replay_inven_changes(player, item);
9860 		if (item == 0xFF) {
9861 			msg_print(player, "Command failed because item is gone.");
9862 			return 1;
9863 		}
9864 		//Handle_item(player, item);
9865 		//TODO: finish tome_creation_aux() here
9866 	}
9867 	return 1;
9868 }
9869 
9870 
9871 static int Receive_message(int ind)
9872 {
9873 	connection_t *connp = Conn[ind];
9874 	char ch, buf[MSG_LEN];
9875 	int n, player = -1;
9876 	if (connp->id != -1) player = GetInd[connp->id];
9877 	else player = 0;
9878 
9879 	if ((n = Packet_scanf(&connp->r, "%c%S", &ch, buf)) <= 0) {
9880 		if (n == -1) Destroy_connection(ind, "read error");
9881 		return n;
9882 	}
9883 
9884 	/* A message longer than 159 characters will certainly cause problems - mikaelh
9885 	   (Changed it to MSG_LEN - C. Blue) */
9886 	buf[MSG_LEN - 1] = '\0';
9887 	player_talk(player, buf);
9888 	return 1;
9889 }
9890 
9891 static int Receive_admin_house(int ind) {
9892 	connection_t *connp = Conn[ind];
9893 	char ch;
9894 	s16b dir;
9895 	int n,player = -1;
9896 	char buf[MAX_CHARS];
9897 
9898 	if (connp->id != -1) {
9899 		player = GetInd[connp->id];
9900 //		use_esp_link(&player, LINKF_OBJ);
9901 	}
9902 	else player = 0;
9903 
9904 	if ((n = Packet_scanf(&connp->r, "%c%hd%s", &ch, &dir, buf)) <= 0) {
9905 		if (n == -1) Destroy_connection(ind, "read error");
9906 		return n;
9907 	}
9908 
9909 	/* Sanity check */
9910 	if (bad_dir(dir)) return 1;
9911 
9912 	house_admin(player, dir, buf);
9913 	return(1);
9914 }
9915 
9916 static int Receive_purchase(int ind)
9917 {
9918 	connection_t *connp = Conn[ind];
9919 	player_type *p_ptr = NULL;
9920 
9921 	char ch;
9922 	int n, player = -1;
9923 	s16b item, amt;
9924 
9925 	if (connp->id != -1) {
9926 		player = GetInd[connp->id];
9927 //		use_esp_link(&player, LINKF_OBJ);
9928 		p_ptr = Players[player];
9929 	}
9930 	else player = 0;
9931 
9932 	if ((n = Packet_scanf(&connp->r, "%c%hd%hd", &ch, &item, &amt)) <= 0) {
9933 		if (n == -1) Destroy_connection(ind, "read error");
9934 		return n;
9935 	}
9936 
9937 	if (player && p_ptr->store_num != -1)
9938 		store_purchase(player, item, amt);
9939 	else if (p_ptr)
9940 		do_cmd_purchase_house(player, item);
9941 
9942 	return 1;
9943 }
9944 
9945 static int Receive_sell(int ind)
9946 {
9947 	connection_t *connp = Conn[ind];
9948 
9949 	char ch;
9950 	int n, player = -1;
9951 	s16b item, amt;
9952 
9953 	if (connp->id != -1) {
9954 		player = GetInd[connp->id];
9955 //		use_esp_link(&player, LINKF_OBJ);
9956 	}
9957 	else player = 0;
9958 
9959 	if ((n = Packet_scanf(&connp->r, "%c%hd%hd", &ch, &item, &amt)) <= 0) {
9960 		if (n == -1) Destroy_connection(ind, "read error");
9961 		return n;
9962 	}
9963 
9964 	if (player) store_sell(player, item, amt);
9965 
9966 	return 1;
9967 }
9968 
9969 static int Receive_store_leave(int ind)
9970 {
9971 	connection_t *connp = Conn[ind];
9972 #ifdef MINDLINK_STORE
9973 	connection_t *connp2;
9974 #endif
9975 	player_type *p_ptr = NULL;
9976 
9977 	char ch;
9978 	int n, player = -1;
9979 
9980 	if (connp->id != -1) {
9981 		player = GetInd[connp->id];
9982 //		use_esp_link(&player, LINKF_OBJ);
9983 		p_ptr = Players[player];
9984 #ifdef MINDLINK_STORE
9985 		if (get_esp_link(GetInd[connp->id], LINKF_OBJ, &p_ptr)) {
9986 		        connp2 = Conn[p_ptr->conn];
9987 		        Packet_printf(&connp2->c, "%c", PKT_STORE_LEAVE); /* not working */
9988 		}
9989 #endif
9990 	} else player = 0;
9991 
9992 	if (player) p_ptr = Players[player];
9993 
9994 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
9995 		if (n == -1) Destroy_connection(ind, "read error");
9996 		return n;
9997 	}
9998 
9999 	if (!player) return -1;
10000 
10001         /* Update stuff */
10002         p_ptr->update |= (PU_VIEW | PU_LITE);
10003         p_ptr->update |= (PU_MONSTERS);
10004 
10005         /* Redraw stuff */
10006         p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA);
10007 
10008         /* Window stuff */
10009         p_ptr->window |= (PW_OVERHEAD);
10010 
10011 	/* Update store info */
10012 	if (p_ptr->store_num != -1) {
10013 #ifdef PLAYER_STORES
10014 		/* Player stores aren't entered such as normal stores,
10015 		   instead, the customer just stays in front of it. */
10016 		if (p_ptr->store_num > -2)
10017 #endif
10018 		/* Hack -- don't stand in the way */
10019 		teleport_player_force(player, 1);
10020 
10021 		handle_store_leave(player);
10022 	}
10023 
10024 #if 0
10025  #if 0
10026 	/* hack -- update night/day in wilderness levels */
10027 	/* XXX it's not so good place to do such things -
10028 	 * prolly we'll need PU_SUN or sth.		- Jir - */
10029 	if (!p_ptr->wpos.wz) {
10030 		if (IS_DAY) world_surface_day(&p_ptr->wpos);
10031 		else world_surface_night(&p_ptr->wpos);
10032 	}
10033  #else
10034 	if (!p_ptr->wpos.wz) {
10035 		if (IS_DAY) player_day(player);
10036 		else player_night(player);
10037 	}
10038  #endif
10039 #endif
10040 
10041 	return 1;
10042 }
10043 
10044 static int Receive_store_confirm(int ind) {
10045 	connection_t *connp = Conn[ind];
10046 	char ch;
10047 	int n, player = -1;
10048 
10049 	if (connp->id != -1) {
10050 		player = GetInd[connp->id];
10051 //		use_esp_link(&player, LINKF_OBJ);
10052 	}
10053 	else player = 0;
10054 
10055 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
10056 		if (n == -1) Destroy_connection(ind, "read error");
10057 		return n;
10058 	}
10059 
10060 	if (!player) return -1;
10061 
10062 	store_confirm(player);
10063 	return 1;
10064 }
10065 
10066 /* Store code should be written to allow more kinds of actions in general..
10067  */
10068 static int Receive_store_examine(int ind)
10069 {
10070 	connection_t *connp = Conn[ind];
10071 	player_type *p_ptr = NULL;
10072 
10073 	char ch;
10074 	int n, player = -1;
10075 	s16b item;
10076 
10077 	if (connp->id != -1) {
10078 		player = GetInd[connp->id];
10079 //		use_esp_link(&player, LINKF_OBJ);
10080 		p_ptr = Players[player];
10081 	}
10082 	else player = 0;
10083 
10084 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0) {
10085 		if (n == -1) Destroy_connection(ind, "read error");
10086 		return n;
10087 	}
10088 
10089 	if (player && p_ptr->store_num != -1)
10090 		store_examine(player, item);
10091 
10092 	return 1;
10093 }
10094 
10095 static int Receive_store_command(int ind)
10096 {
10097 	connection_t *connp = Conn[ind];
10098 	player_type *p_ptr = NULL;
10099 
10100 	char ch;
10101 	int n, player = 0, gold;
10102 	u16b action;
10103 	s16b item, item2, amt;
10104 
10105 	if (connp->id != -1) {
10106 		player = GetInd[connp->id];
10107 //		use_esp_link(&player, LINKF_OBJ);
10108 		p_ptr = Players[player];
10109 	}
10110 	else player = 0;
10111 
10112 	if ((n = Packet_scanf(&connp->r, "%c%hd%hd%hd%hd%d", &ch, &action, &item, &item2, &amt, &gold)) <= 0) {
10113 		if (n == -1) Destroy_connection(ind, "read error");
10114 		return n;
10115 	}
10116 
10117 	if (player && p_ptr->store_num != -1)
10118 		store_exec_command(player, action, item, item2, amt, gold);
10119 
10120 	return 1;
10121 }
10122 
10123 static int Receive_drop_gold(int ind)
10124 {
10125 	connection_t *connp = Conn[ind];
10126 	player_type *p_ptr = NULL;
10127 	char ch;
10128 	int n, player = -1;
10129 	s32b amt;
10130 
10131 	if (connp->id != -1) {
10132 		player = GetInd[connp->id];
10133 //		use_esp_link(&player, LINKF_OBJ);
10134 		p_ptr = Players[player];
10135 	}
10136 
10137 	if ((n = Packet_scanf(&connp->r, "%c%d", &ch, &amt)) <= 0) {
10138 		if (n == -1) Destroy_connection(ind, "read error");
10139 		return n;
10140 	}
10141 
10142 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
10143 		do_cmd_drop_gold(player, amt);
10144 		return 2;
10145 	} else if (p_ptr) {
10146 		Packet_printf(&connp->q, "%c%d", ch, amt);
10147 		return 0;
10148 	}
10149 	return 1;
10150 }
10151 
10152 static int Receive_steal(int ind)
10153 {
10154 	connection_t *connp = Conn[ind];
10155 	player_type *p_ptr = NULL;
10156 	char ch, dir;
10157 	int n, player = -1;
10158 
10159 	if (connp->id != -1) {
10160 		player = GetInd[connp->id];
10161 //		use_esp_link(&player, LINKF_OBJ);
10162 		p_ptr = Players[player];
10163 	}
10164 
10165 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
10166 		if (n == -1) Destroy_connection(ind, "read error");
10167 		return n;
10168 	}
10169 
10170 	/* Sanity check */
10171 	if (bad_dir(dir)) return 1;
10172 
10173 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
10174 		do_cmd_steal(player, dir);
10175 		return 2;
10176 	} else if (p_ptr) {
10177 		Packet_printf(&connp->q, "%c%c", ch, dir);
10178 		return 0;
10179 	}
10180 	return 1;
10181 }
10182 
10183 
10184 static int Receive_King(int ind)
10185 {
10186 	connection_t *connp = Conn[ind];
10187 	player_type *p_ptr = NULL;
10188 
10189 	byte type;
10190 	char ch;
10191 
10192 	int n, player = -1;
10193 
10194 	if (connp->id != -1) {
10195 		player = GetInd[connp->id];
10196 //		use_esp_link(&player, LINKF_OBJ);
10197 		p_ptr = Players[player];
10198 	}
10199 
10200 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &type)) <= 0) {
10201 		if (n == -1) Destroy_connection(ind, "read error");
10202 		return n;
10203 	}
10204 
10205 	if (p_ptr) {
10206 		switch(type) {
10207 #if 0 /* DGDGDGDG -- Cause fucking up of levels */
10208 			case KING_OWN:
10209 				do_cmd_own(player);
10210 				break;
10211 #endif
10212 		}
10213 		return 2;
10214 	} else if (p_ptr) {
10215 		Packet_printf(&connp->q, "%c%c", ch, type);
10216 		return 0;
10217 	}
10218 	return 1;
10219 }
10220 
10221 static int Receive_redraw(int ind)
10222 {
10223 	connection_t *connp = Conn[ind];
10224 	player_type *p_ptr = NULL;
10225 	int player = -1, n;
10226 	char ch, mode;
10227 
10228 	if (connp->id != -1) {
10229 		player = GetInd[connp->id];
10230 		p_ptr = Players[player];
10231 
10232 		if (p_ptr->esp_link_type && p_ptr->esp_link) {
10233 			int Ind2 = find_player(p_ptr->esp_link);
10234 
10235 			if (!Ind2)
10236 				end_mind(ind, TRUE);
10237 			else {
10238 				if (Players[Ind2]->esp_link_flags & LINKF_VIEW) {
10239 					player = Ind2;
10240 					p_ptr = Players[Ind2];
10241 				}
10242 			}
10243 		}
10244 	}
10245 	else player = 0;
10246 
10247 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &mode)) <= 0) {
10248 		if (n == -1) Destroy_connection(ind, "read error");
10249 		return n;
10250 	}
10251 
10252 	if (player && !p_ptr->redraw_cooldown) {
10253 		if (!is_admin(p_ptr)) p_ptr->redraw_cooldown = 3;
10254 
10255 //		p_ptr->store_num = -1;
10256 		p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
10257 		p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
10258 		p_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP | PU_SANITY);
10259 
10260 		/* Do 'Heavy' redraw if requested.
10261 		 * TODO: One might wish to add more detailed modes
10262 		 */
10263 		if (mode) {
10264 			/* Tell the server to redraw the player's display */
10265 			p_ptr->redraw |= PR_MAP | PR_EXTRA | PR_BASIC | PR_HISTORY | PR_VARIOUS | PR_STATE;
10266 			p_ptr->redraw |= PR_PLUSSES;
10267 			if (is_older_than(&p_ptr->version, 4, 4, 8, 5, 0, 0)) p_ptr->redraw |= PR_STUDY;
10268 
10269 			/* Update his view, light, bonuses, and torch radius */
10270 #ifdef ORIG_SKILL_EVIL	/* not to be defined */
10271 			p_ptr->update |= (PU_VIEW | PU_LITE | PU_BONUS | PU_TORCH | PU_DISTANCE
10272 					| PU_SKILL_INFO | PU_SKILL_MOD);
10273 #else
10274 			p_ptr->update |= (PU_VIEW | PU_LITE | PU_BONUS | PU_TORCH | PU_DISTANCE );
10275 #endif
10276 			p_ptr->update |= (PU_MANA | PU_HP | PU_SANITY);
10277 
10278 			/* Update his inventory, equipment, and spell info */
10279 			p_ptr->window |= (PW_INVEN | PW_EQUIP);
10280 		}
10281 	}
10282 
10283 	return 1;
10284 }
10285 
10286 static int Receive_rest(int ind)
10287 {
10288 	connection_t *connp = Conn[ind];
10289 	player_type *p_ptr = NULL;
10290 	int player = -1, n;
10291 	char ch;
10292 
10293 	if (connp->id != -1) {
10294 		player = GetInd[connp->id];
10295 		use_esp_link(&player, LINKF_MOV);
10296 		p_ptr = Players[player];
10297 	}
10298 	else player = 0;
10299 
10300 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
10301 		if (n == -1) Destroy_connection(ind, "read error");
10302 		return n;
10303 	}
10304 
10305 	if (player) {
10306 		cave_type **zcave;
10307 
10308 		/* If we are already resting, cancel the rest. */
10309 		/* Waking up takes no energy, although we will still be drowsy... */
10310 		if (p_ptr->resting) {
10311 			disturb(player, 0, 0);
10312 			return 2;
10313 		}
10314 
10315 		/* Don't rest if we are poisoned or at max hit points and max spell points
10316 		   and max stamina */
10317 		if ((p_ptr->poisoned) || (p_ptr->cut) || (p_ptr->sun_burn) ||
10318 		    ((p_ptr->chp == p_ptr->mhp) &&
10319 		    (p_ptr->csp == p_ptr->msp) &&
10320 		    (p_ptr->cst == p_ptr->mst)
10321 		    && !(p_ptr->prace == RACE_ENT && p_ptr->food < PY_FOOD_FULL)
10322 		    ))
10323 			return 2;
10324 
10325 		if (!(zcave = getcave(&p_ptr->wpos))) return 2;
10326 
10327 #if 0 /* why? don't see a reason atm */
10328 		/* Can't rest on a Void Jumpgate -- too dangerous */
10329 		if (zcave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN) {
10330 			msg_print(player, "Resting on a Void Jumpgate is too dangerous!");
10331 			return 2;
10332 		}
10333 #endif
10334 
10335 		/* Resting takes a lot of energy! */
10336 		if ((p_ptr->energy) >= (level_speed(&p_ptr->wpos) * 2) - 1) {
10337 			/* Set flag */
10338 			p_ptr->resting = TRUE;
10339 			p_ptr->warning_rest = 3;
10340 
10341 			/* Make sure we aren't running */
10342 			p_ptr->running = FALSE;
10343 			break_shadow_running(player);
10344 			stop_precision(player);
10345 			stop_shooting_till_kill(player);
10346 
10347 			/* Take a lot of energy to enter "rest mode" */
10348 			p_ptr->energy -= (level_speed(&p_ptr->wpos) * 2) - 1;
10349 
10350 			/* Redraw */
10351 			p_ptr->redraw |= (PR_STATE);
10352 			return 2;
10353 		}
10354 		/* If we don't have enough energy to rest, disturb us (to stop
10355 		 * us from running) and queue the command.
10356 		 */
10357 		else
10358 		{
10359 			disturb(player, 0, 0);
10360 			Packet_printf(&connp->q, "%c", ch);
10361 			return 0;
10362 		}
10363 	}
10364 
10365 	return 1;
10366 }
10367 
10368 void Handle_clear_buffer(int Ind)
10369 {
10370 	player_type *p_ptr = Players[Ind];
10371 	connection_t *connp = Conn[p_ptr->conn];
10372 
10373 	/* Clear the buffer */
10374 
10375 	/* No energy commands are placed in 'q' */
10376 	Sockbuf_clear(&connp->q);
10377 
10378 	/* New commands are in 'r' - clear this and its gone. */
10379 	/* Sockbuf_clear(&connp->r); */
10380 
10381 	/* Clear 'current spell' */
10382 	p_ptr->current_spell = -1;
10383 }
10384 
10385 static void Handle_clear_actions(int Ind) {
10386 	player_type *p_ptr = Players[Ind];
10387 
10388 	/* Stop ranged auto-retaliation (fire-till-kill) */
10389 	p_ptr->shooting_till_kill = FALSE;
10390 
10391 	/* Stop automatically executed repeated actions */
10392 	p_ptr->command_rep = 0;
10393 #ifdef ENABLE_XID_SPELL
10394 	p_ptr->current_item = -1; //unnecessary?
10395 #endif
10396 
10397 	/* Stop preparing shooting techniques */
10398 	stop_precision(Ind);
10399 	if (p_ptr->ranged_flare) {
10400 		msg_print(Ind, "You dispose of the flare missile.");
10401 		p_ptr->ranged_flare = FALSE;
10402 	}
10403 	if (p_ptr->ranged_barrage) {
10404 		msg_print(Ind, "You cancel preparations for barrage.");
10405 		p_ptr->ranged_barrage = FALSE;
10406 	}
10407 
10408 	/* Stop resting */
10409 	disturb(Ind, 0, 0);
10410 }
10411 
10412 static int Receive_clear_buffer(int ind) {
10413 	connection_t *connp = Conn[ind];
10414 	int player = -1, n;
10415 	char ch;
10416 
10417 	if (connp->id != -1) {
10418 		player = GetInd[connp->id];
10419 //		use_esp_link(&player, LINKF_OBJ);
10420 	}
10421 	else player = 0;
10422 
10423 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
10424 		if (n == -1) Destroy_connection(ind, "read error");
10425 		return n;
10426 	}
10427 
10428 	if (player) Handle_clear_buffer(player);
10429 
10430 	return 1;
10431 }
10432 
10433 static int Receive_clear_actions(int ind) {
10434 	connection_t *connp = Conn[ind];
10435 	int player = -1, n;
10436 	char ch;
10437 
10438 	if (connp->id != -1) {
10439 		player = GetInd[connp->id];
10440 //		use_esp_link(&player, LINKF_OBJ);
10441 	}
10442 	else player = 0;
10443 
10444 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
10445 		if (n == -1) Destroy_connection(ind, "read error");
10446 		return n;
10447 	}
10448 
10449 	if (player) Handle_clear_actions(player);
10450 
10451 	return 1;
10452 }
10453 
10454 static int Receive_special_line(int ind)
10455 {
10456 	connection_t *connp = Conn[ind];
10457 	int player = -1, n;
10458 	char ch, type;
10459 	s32b line;
10460 
10461 	if (connp->id != -1) player = GetInd[connp->id];
10462 		else player = 0;
10463 
10464 	if (is_newer_than(&connp->version, 4, 4, 7, 0, 0, 0)) {
10465 		if ((n = Packet_scanf(&connp->r, "%c%c%d", &ch, &type, &line)) <= 0) {
10466 			if (n == -1)
10467 				Destroy_connection(ind, "read error");
10468 			return n;
10469 		}
10470 	} else {
10471 		s16b old_line;
10472 		if ((n = Packet_scanf(&connp->r, "%c%c%hd", &ch, &type, &old_line)) <= 0) {
10473 			if (n == -1)
10474 				Destroy_connection(ind, "read error");
10475 			return n;
10476 		}
10477 		line = old_line;
10478 	}
10479 
10480 	if (player) {
10481 		char kludge[2] = "", minlev = 0;
10482 		/* abuse 'line' to encode both, type and minlev (for monster knowledge) */
10483 		minlev = line / 100000;
10484 		line = line % 100000;
10485 		kludge[0] = (char) line;
10486 		kludge[1] = '\0';
10487 		switch (type) {
10488 		case SPECIAL_FILE_NONE:
10489 			Players[player]->special_file_type = FALSE;
10490 			/* Remove the file */
10491 /*			if (!strcmp(Players[player]->infofile,
10492 						Players[player]->cur_file))	*/
10493 				fd_kill(Players[player]->infofile);
10494 			break;
10495 		case SPECIAL_FILE_UNIQUE:
10496 			do_cmd_check_uniques(player, line);
10497 			break;
10498 		case SPECIAL_FILE_ARTIFACT:
10499 			do_cmd_check_artifacts(player, line);
10500 			break;
10501 		case SPECIAL_FILE_PLAYER:
10502 			do_cmd_check_players(player, line);
10503 			break;
10504 		case SPECIAL_FILE_PLAYER_EQUIP:
10505 			do_cmd_check_player_equip(player, line);
10506 			break;
10507 		case SPECIAL_FILE_OTHER:
10508 			do_cmd_check_other(player, line);
10509 			break;
10510 		case SPECIAL_FILE_SCORES:
10511 			display_scores(player, line);
10512 			break;
10513 		case SPECIAL_FILE_HELP:
10514 			do_cmd_help(player, line);
10515 			break;
10516 		/* Obsolete, just left for compatibility (DELETEME) */
10517 		case SPECIAL_FILE_LOG:
10518 			if (is_admin(Players[player]))
10519 				do_cmd_view_rfe(player, "tomenet.log", line);
10520 			break;
10521 		case SPECIAL_FILE_RFE:
10522 			if (is_admin(Players[player]) || cfg.public_rfe)
10523 				do_cmd_view_rfe(player, "tomenet.rfe", line);
10524 			break;
10525 		case SPECIAL_FILE_MOTD2:
10526 			show_motd2(player);
10527 			break;
10528 		/*
10529 		 * Hack -- those special files actually use do_cmd_check_other
10530 		 * XXX redesign it
10531 		 */
10532 		case SPECIAL_FILE_SERVER_SETTING:
10533 			do_cmd_check_server_settings(player);
10534 			break;
10535 		case SPECIAL_FILE_MONSTER:
10536 			do_cmd_show_monster_killed_letter(player, kludge, minlev);
10537  			break;
10538 		case SPECIAL_FILE_OBJECT:
10539 			do_cmd_show_known_item_letter(player, kludge);
10540  			break;
10541 		case SPECIAL_FILE_HOUSE:
10542 			do_cmd_show_houses(player, FALSE, FALSE);
10543  			break;
10544 		case SPECIAL_FILE_TRAP:
10545 			do_cmd_knowledge_traps(player);
10546  			break;
10547 		case SPECIAL_FILE_RECALL:
10548 			do_cmd_knowledge_dungeons(player);
10549  			break;
10550 		}
10551 	}
10552 
10553 	return 1;
10554 }
10555 
10556 static int Receive_options(int ind) {
10557 	connection_t *connp = Conn[ind];
10558 	int player = -1, i, n;
10559 	char ch;
10560 
10561 	if (connp->id != -1) {
10562 		player = GetInd[connp->id];
10563 	} else {
10564 		player = 0;
10565 	}
10566 
10567 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
10568 		if (n == -1) Destroy_connection(ind, "read error");
10569 		return n;
10570 	}
10571 
10572 	if (player) {
10573 		bool options[OPT_MAX];
10574 
10575 		if (is_newer_than(&connp->version, 4, 5, 8, 1, 0, 1)) {
10576 			for (i = 0; i < OPT_MAX; i++) {
10577 				n = Packet_scanf(&connp->r, "%c", &options[i]);
10578 				if (n <= 0) {
10579 					Destroy_connection(ind, "read error");
10580 					return n;
10581 				}
10582 			}
10583 		} else if (is_newer_than(&connp->version, 4, 5, 5, 0, 0, 0)) {
10584 			for (i = 0; i < OPT_MAX_COMPAT; i++) {
10585 				n = Packet_scanf(&connp->r, "%c", &options[i]);
10586 				if (n <= 0) {
10587 					Destroy_connection(ind, "read error");
10588 					return n;
10589 				}
10590 			}
10591 		} else {
10592 			for (i = 0; i < OPT_MAX_OLD; i++) {
10593 				n = Packet_scanf(&connp->r, "%c", &options[i]);
10594 				if (n <= 0) {
10595 					Destroy_connection(ind, "read error");
10596 					return n;
10597 				}
10598 			}
10599 		}
10600 
10601 		/* Sync named options */
10602 		sync_options(player, options);
10603 	}
10604 
10605 	return 1;
10606 }
10607 
10608 static int Receive_screen_dimensions(int ind) {
10609 	connection_t *connp = Conn[ind];
10610 	player_type *p_ptr = NULL;
10611 	int player = -1, n;
10612 	char ch;
10613 
10614 	if (connp->id != -1) {
10615 		player = GetInd[connp->id];
10616 		p_ptr = Players[player];
10617 	} else {
10618 		player = 0;
10619 		p_ptr = NULL;
10620 	}
10621 
10622 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
10623 		if (n == -1) Destroy_connection(ind, "read error");
10624 		return n;
10625 	}
10626 
10627 	if (player) {
10628 		n = Packet_scanf(&connp->r, "%d%d", &p_ptr->screen_wid, &p_ptr->screen_hgt);
10629 		if (n <= 0) {
10630 			Destroy_connection(ind, "read error");
10631 			return n;
10632 		}
10633 #ifndef BIG_MAP
10634 		return 1;
10635 #endif
10636 
10637 
10638 		/* fix limits */
10639 #ifdef BIG_MAP
10640 		if (p_ptr->screen_wid > MAX_SCREEN_WID) p_ptr->screen_wid = MAX_SCREEN_WID;
10641 		if (p_ptr->screen_wid < MIN_SCREEN_WID) p_ptr->screen_wid = MIN_SCREEN_WID;
10642 		if (p_ptr->screen_hgt > MAX_SCREEN_HGT) p_ptr->screen_hgt = MAX_SCREEN_HGT;
10643 		if (p_ptr->screen_hgt < MIN_SCREEN_HGT) p_ptr->screen_hgt = MIN_SCREEN_HGT;
10644 		/* for now until resolved: avoid dimensions whose half values aren't divisors of MAX_WID/HGT */
10645 		if (MAX_WID % (p_ptr->screen_wid / 2)) p_ptr->screen_wid = SCREEN_WID;
10646 		if (MAX_HGT % (p_ptr->screen_hgt / 2)) p_ptr->screen_hgt = SCREEN_HGT;
10647 #else
10648                 p_ptr->screen_wid = SCREEN_WID;
10649                 p_ptr->screen_hgt = SCREEN_HGT;
10650 #endif
10651 
10652 		connp->Client_setup.screen_wid = p_ptr->screen_wid;
10653 		connp->Client_setup.screen_hgt = p_ptr->screen_hgt;
10654 
10655 
10656 	        /* Recalculate panel */
10657 
10658 	        if (p_ptr->wpos.wz) {
10659 			dun_level *l_ptr = getfloor(&p_ptr->wpos);
10660 	                p_ptr->max_panel_rows = MAX_PANEL_ROWS_L;
10661 	                p_ptr->max_panel_cols = MAX_PANEL_COLS_L;
10662 
10663 	        } else {
10664 	                p_ptr->max_panel_rows = MAX_PANEL_ROWS;
10665                         p_ptr->max_panel_cols = MAX_PANEL_COLS;
10666                 }
10667 #ifdef BIG_MAP
10668                 if (p_ptr->max_panel_rows < 0) p_ptr->max_panel_rows = 0;
10669                 if (p_ptr->max_panel_cols < 0) p_ptr->max_panel_cols = 0;
10670 #endif
10671 
10672 	        p_ptr->panel_row = ((p_ptr->py - p_ptr->screen_hgt / 4) / (p_ptr->screen_hgt / 2));
10673 	        if (p_ptr->panel_row > p_ptr->max_panel_rows) p_ptr->panel_row = p_ptr->max_panel_rows;
10674 	        else if (p_ptr->panel_row < 0) p_ptr->panel_row = 0;
10675 
10676 	        p_ptr->panel_col = ((p_ptr->px - p_ptr->screen_wid / 4) / (p_ptr->screen_wid / 2));
10677 	        if (p_ptr->panel_col > p_ptr->max_panel_cols) p_ptr->panel_col = p_ptr->max_panel_cols;
10678 	        else if (p_ptr->panel_col < 0) p_ptr->panel_col = 0;
10679 
10680 #ifdef ALERT_OFFPANEL_DAM
10681 		/* For alert-beeps on damage: Reset remembered panel */
10682 		p_ptr->panel_row_old = p_ptr->panel_row;
10683 		p_ptr->panel_col_old = p_ptr->panel_col;
10684 #endif
10685 
10686                 panel_bounds(player);
10687 
10688 
10689 		/* Heavy redraw (just to make sure) */
10690 
10691 		p_ptr->redraw |= PR_MAP | PR_EXTRA | PR_BASIC | PR_HISTORY | PR_VARIOUS | PR_STATE | PR_PLUSSES;
10692 		if (is_older_than(&p_ptr->version, 4, 4, 8, 5, 0, 0)) p_ptr->redraw |= PR_STUDY;
10693 
10694 #ifdef ORIG_SKILL_EVIL	/* not to be defined */
10695 		p_ptr->update |= (PU_LITE | PU_TORCH | PU_DISTANCE | PU_SKILL_INFO | PU_SKILL_MOD);
10696 #else
10697 		p_ptr->update |= (PU_LITE | PU_TORCH | PU_DISTANCE );
10698 #endif
10699 		p_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP | PU_SANITY);
10700 		p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
10701 	}
10702 
10703 	return 1;
10704 }
10705 
10706 static int Receive_suicide(int ind)
10707 {
10708 	connection_t *connp = Conn[ind];
10709 	int player = -1, n;
10710 	char ch;
10711 	char extra1 = 1, extra2 = 4;
10712 
10713 	if (connp->id != -1)
10714 		player = GetInd[connp->id];
10715 	else player = 0;
10716 
10717 	/* Newer clients send couple of extra bytes to prevent accidental
10718 	 * suicides due to network mishaps. - mikaelh */
10719 	if (is_newer_than(&connp->version, 4, 4, 2, 3, 0, 0)) {
10720 		if ((n = Packet_scanf(&connp->r, "%c%c%c", &ch, &extra1, &extra2)) <= 0)
10721 		{
10722 			if (n == -1)
10723 				Destroy_connection(ind, "read error");
10724 			return n;
10725 		}
10726 	}
10727 	else
10728 	{
10729 		if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0)
10730 		{
10731 			if (n == -1)
10732 				Destroy_connection(ind, "read error");
10733 			return n;
10734 		}
10735 	}
10736 
10737 	if (extra1 != 1 || extra2 != 4)
10738 	{
10739 		/* Invalid suicide command detected, clear the buffer now */
10740 		Sockbuf_clear(&connp->r);
10741 		return 1;
10742 	}
10743 
10744 	/* Commit suicide */
10745 	do_cmd_suicide(player);
10746 
10747 	return 1;
10748 }
10749 
10750 static int Receive_party(int ind) {
10751 	connection_t *connp = Conn[ind];
10752 	int player = -1, n;
10753 	char ch, buf[MAX_CHARS];
10754 	s16b command;
10755 
10756 	if (connp->id != -1) player = GetInd[connp->id];
10757 		else return 1;
10758 
10759 	if ((n = Packet_scanf(&connp->r, "%c%hd%s", &ch, &command, buf)) <= 0) {
10760 		if (n == -1) Destroy_connection(ind, "read error");
10761 		return n;
10762 	}
10763 
10764 	/* sanitize input - C. Blue */
10765 	if (strlen(buf) > 40) *(buf + 40) = 0;
10766 	for (n = 0; n < (int)strlen(buf); n++)
10767 		if (*(buf + n) < 32) *(buf + n) = '_';
10768 
10769 	switch (command) {
10770 	case PARTY_CREATE:
10771 		party_create(player, buf);
10772 		break;
10773 	case PARTY_CREATE_IRONTEAM:
10774 		party_create_ironteam(player, buf);
10775 		break;
10776 	case PARTY_ADD:
10777 		if (!Players[player]->party) party_add_self(player, buf);
10778 		else party_add(player, buf);
10779 		break;
10780 	case PARTY_DELETE:
10781 		party_remove(player, buf);
10782 		break;
10783 	case PARTY_REMOVE_ME:
10784 		party_leave(player, TRUE);
10785 		break;
10786 	case PARTY_HOSTILE:
10787 		add_hostility(player, buf, TRUE);
10788 		break;
10789 	case PARTY_PEACE:
10790 		remove_hostility(player, buf);
10791 		break;
10792 	}
10793 
10794 	return 1;
10795 }
10796 
10797 static int Receive_guild(int ind) {
10798 	connection_t *connp = Conn[ind];
10799 	int player = -1, n;
10800 	char ch, buf[MAX_CHARS];
10801 	s16b command;
10802 	player_type *p_ptr = NULL;
10803 
10804 	if (connp->id != -1) {
10805 		player = GetInd[connp->id];
10806 		p_ptr = Players[player];
10807 	}
10808 	else return 1;
10809 
10810 	if ((n = Packet_scanf(&connp->r, "%c%hd%s", &ch, &command, buf)) <= 0) {
10811 		if (n == -1) Destroy_connection(ind, "read error");
10812 		return n;
10813 	}
10814 
10815 	switch (command) {
10816 	case GUILD_CREATE:
10817 		strcpy(p_ptr->cur_file_title, buf);//hack: abuse cur_file_title
10818 		Send_request_cfr(player, RID_GUILD_CREATE, format("Creating a guild costs %d Au. Are you sure?", GUILD_PRICE), FALSE);
10819 		break;
10820 	case GUILD_ADD:
10821 		if (!p_ptr->guild) guild_add_self(player, buf);
10822 		else guild_add(player, buf);
10823 		break;
10824 	case GUILD_DELETE:
10825 		guild_remove(player, buf);
10826 		break;
10827 	case GUILD_REMOVE_ME:
10828 		guild_leave(player, TRUE);
10829 		break;
10830 	}
10831 
10832 	return 1;
10833 }
10834 
10835 static int Receive_guild_config(int ind) {
10836 	connection_t *connp = Conn[ind];
10837 	int player = 0, n, j;
10838 	char ch, adder[MAX_CHARS];
10839 	int command;
10840 	u32b flags;
10841 	guild_type *guild;
10842 	player_type *p_ptr, *q_ptr;
10843 
10844 	if (connp->id != -1) player = GetInd[connp->id];
10845 	if ((n = Packet_scanf(&connp->r, "%c%d%d%s", &ch, &command, &flags, adder)) <= 0) {
10846 		if (n == -1) Destroy_connection(ind, "read error");
10847 		return n;
10848 	}
10849 	if (!player) return 1;
10850 	p_ptr = Players[player];
10851 
10852 	/* Must be a guild master */
10853 	if (!p_ptr->guild) {
10854 		s_printf("GUILDCFG_EXPLOIT: (noguild) %s(%s) - %d, %d, %s\n", p_ptr->name, p_ptr->accountname, command, flags, adder);
10855 		return 1;
10856 	}
10857 	guild = &guilds[p_ptr->guild];
10858 	if (guild->master != p_ptr->id) {
10859 		s_printf("GUILDCFG_EXPLOIT: (nomaster) %s(%s) - %d, %d, %s\n", p_ptr->name, p_ptr->accountname, command, flags, adder);
10860 		return 1;
10861 	}
10862 
10863 	switch (command) {
10864 	case 0: /* set flags */
10865 		guild->flags = flags;
10866 		break;
10867 	case 1: /* set minlev */
10868                 // if (flags < 0) flags = 0; // always false because flags is unsigned
10869                 if (flags > 100) flags = 100;
10870                 //msg_format(player, "Minimum level required to join the guild so far was %d..", guild->minlev);
10871 		guild->minlev = flags;
10872                 //msg_format(player, "..and has now been set to %d.", guild->minlev);
10873 		break;
10874 	case 2: /* set/remove adder */
10875 		if (!adder[0]) break;
10876 		adder[0] = toupper(adder[0]); /* be helpful */
10877                 n = name_lookup_loose(player, adder, FALSE, FALSE);
10878                 if (!n) {
10879 #ifdef GUILD_ADDERS_LIST
10880                         /* Handle de-authorization */
10881                         for (j = 0; j < 5; j++) if (streq(guild->adder[j], adder)) break;
10882                         if (j == 5) {
10883                                 msg_print(player, "Player must be online to become an adder.");
10884                                 return 1;
10885                         }
10886                         if (streq(p_ptr->name, adder)) {
10887                                 msg_print(player, "As guild master you can always add others.");
10888                                 return 1;
10889                         }
10890                         guild->adder[j][0] = '\0';
10891                         msg_format(player, "Player \377r%s\377w is no longer authorized to add others.", adder);
10892                         break;
10893 #else
10894                         msg_print(player, "Player not online.");
10895                         return 1;
10896 #endif
10897                 }
10898                 if (n == player) {
10899                         msg_print(player, "As guild master you can always add others.");
10900                         return 1;
10901                 }
10902                 q_ptr = Players[n];
10903                 if (q_ptr->guild != p_ptr->guild) {
10904                         msg_print(player, "That player is not in your guild.");
10905                         return 1;
10906                 }
10907 
10908                 if ((q_ptr->guild_flags & PGF_ADDER)) {
10909 #ifdef GUILD_ADDERS_LIST
10910                         for (j = 0; j < 5; j++) if (streq(guild->adder[j], q_ptr->name)) {
10911                                 guild->adder[j][0] = '\0';
10912                                 break;
10913                         }
10914 #endif
10915 
10916                         q_ptr->guild_flags &= ~PGF_ADDER;
10917                         //msg_format(player, "Player \377r%s\377w is no longer authorized to add others.", q_ptr->name);
10918                         msg_format(n, "\374\377%cGuild master %s \377rretracted\377%c your authorization to add others.", COLOUR_CHAT_GUILD, p_ptr->name, COLOUR_CHAT_GUILD);
10919                 } else {
10920 #ifdef GUILD_ADDERS_LIST
10921                         /* look if we have less than 5 adders still */
10922                         for (j = 0; j < 5; j++) if (guild->adder[j][0] == '\0') break; /* found a vacant slot? */
10923                         if (j == 5) {
10924                                 msg_print(player, "You cannot designate more than 5 adders.");
10925                                 return 1;
10926                         }
10927                         strcpy(guild->adder[j], q_ptr->name);
10928 #endif
10929 
10930                         q_ptr->guild_flags |= PGF_ADDER;
10931                         //msg_format(player, "Player \377G%s\377w is now authorized to add other players.", q_ptr->name);
10932                         msg_format(n, "\374\377%cGuild master %s \377Gauthorized\377%c you to add other players.", COLOUR_CHAT_GUILD, p_ptr->name, COLOUR_CHAT_GUILD);
10933                         if (!(guild->flags & GFLG_ALLOW_ADDERS)) {
10934                     		//spam msg_print(player, "Note that currently the guild configuration prevents 'adders'!");
10935                                 //msg_print(player, "However, note that currently the guild configuration still prevent this!");
10936 				//msg_print(player, "To toggle the corresponding flag, use '/guild_cfg adders' command.");
10937                         }
10938                 }
10939 		break;
10940 	}
10941 
10942 	Send_guild_config(p_ptr->guild);
10943 	return 1;
10944 }
10945 
10946 void Handle_direction(int Ind, int dir) {
10947 	player_type *p_ptr = Players[Ind];//, *p_ptr2 = NULL;
10948 	//int Ind2;
10949 //s_printf("hd dir,current_spell,current_realm=%d,%d,%d\n", dir, p_ptr->current_spell, p_ptr->current_realm);
10950 
10951 	/* New '+' feat in 4.4.6.2 */
10952 	if (dir == 11) { /* repeat forever, if we keep pressing '+', yay.. */
10953 		get_aim_dir(Ind);
10954 		return;
10955 	}
10956 
10957 	if (!dir) {
10958 		p_ptr->current_char = 0;
10959 		p_ptr->current_spell = -1;
10960 		p_ptr->current_mind = -1;
10961 		p_ptr->current_rod = -1;
10962 		p_ptr->current_activation = -1;
10963 		p_ptr->current_rcraft = -1;
10964 		p_ptr->current_wand = -1;
10965 		p_ptr->current_item = -1;
10966 		p_ptr->current_book = -1;
10967 		p_ptr->current_aux = -1;
10968 		p_ptr->current_realm = -1;
10969 		p_ptr->current_fire = -1;
10970 		p_ptr->current_throw = -1;
10971 		p_ptr->current_breath = 0;
10972 		return;
10973 	}
10974 
10975 	//Ind2 = get_esp_link(Ind, LINKF_MISC, &p_ptr2);
10976 
10977 	if (p_ptr->current_spell != -1) {
10978 //		if (p_ptr->current_realm == REALM_GHOST)
10979 		if (p_ptr->ghost)
10980 			do_cmd_ghost_power_aux(Ind, dir);
10981 		else if (p_ptr->current_realm == REALM_MIMIC)
10982 			do_mimic_power_aux(Ind, dir);
10983 		else if (p_ptr->current_realm == REALM_SCHOOL)
10984 			cast_school_spell(Ind, p_ptr->current_book, p_ptr->current_spell,
10985 			    dir, p_ptr->current_item, p_ptr->current_aux);
10986 		else p_ptr->current_spell = -1;
10987 	}
10988 	else if (p_ptr->current_rcraft != -1)
10989 		(void)cast_rune_spell(Ind, dir, p_ptr->current_rcraft_e_flags, p_ptr->current_rcraft_m_flags, 0, 0);
10990        	else if (p_ptr->current_rod != -1)
10991 		do_cmd_zap_rod_dir(Ind, dir);
10992 	else if (p_ptr->current_activation != -1)
10993 		do_cmd_activate_dir(Ind, dir);
10994 	else if (p_ptr->current_wand != -1)
10995 		do_cmd_aim_wand(Ind, p_ptr->current_wand, dir);
10996 	else if (p_ptr->current_fire != -1)
10997 		do_cmd_fire(Ind, dir);
10998 	else if (p_ptr->current_throw != -1)
10999 		do_cmd_throw(Ind, dir, p_ptr->current_throw, 0);
11000 	else if (p_ptr->current_breath != 0)
11001 		do_cmd_breathe_aux(Ind, dir);
11002 }
11003 
11004 void Handle_item(int Ind, int item) {
11005 	player_type *p_ptr = Players[Ind];
11006 	int i;
11007 
11008 	if ((p_ptr->current_enchant_h > 0) || (p_ptr->current_enchant_d > 0) ||
11009              (p_ptr->current_enchant_a > 0)) {
11010 		enchant_spell_aux(Ind, item, p_ptr->current_enchant_h,
11011 			p_ptr->current_enchant_d, p_ptr->current_enchant_a,
11012 			p_ptr->current_enchant_flag);
11013 	} else if (p_ptr->current_identify) {
11014 		ident_spell_aux(Ind, item);
11015 	} else if (p_ptr->current_star_identify) {
11016 		identify_fully_item(Ind, item);
11017 	} else if (p_ptr->current_recharge) {
11018 		recharge_aux(Ind, item, p_ptr->current_recharge);
11019 	} else if (p_ptr->current_artifact) {
11020 		create_artifact_aux(Ind, item);
11021 	} else if (p_ptr->current_telekinesis != NULL) {
11022 		telekinesis_aux(Ind, item);
11023 	} else if (p_ptr->current_curse != 0) {
11024 		curse_spell_aux(Ind, item);
11025 	} else if (p_ptr->current_tome_creation) {
11026 		/* swap-hack: activating a custom tome uses up
11027 		   the TARGET item, not the tome, of course */
11028 		i = p_ptr->using_up_item;
11029 		p_ptr->using_up_item = item;
11030 		tome_creation_aux(Ind, i);
11031 	} else if (p_ptr->current_rune) {
11032 		rune_combine_aux(Ind, item);
11033 	}
11034 
11035 	/* to be safe, clean up; just in case our item was used up */
11036 	for (i = 0; i < INVEN_PACK; i++) inven_item_optimize(Ind, i);
11037 }
11038 
11039 /* Is it a king and on his land ? */
11040 bool player_is_king(int Ind) {
11041 	player_type *p_ptr = Players[Ind];
11042 
11043 	return FALSE;
11044 
11045 	if (p_ptr->total_winner && ((inarea(&p_ptr->own1, &p_ptr->wpos)) || (inarea(&p_ptr->own2, &p_ptr->wpos))))
11046 		return TRUE;
11047 
11048 	/* Assume false */
11049 	return FALSE;
11050 }
11051 
11052 /* receive a dungeon master command */
11053 static int Receive_master(int ind) {
11054 	connection_t *connp = Conn[ind];
11055 	int player = -1, n;
11056 	char ch, buf[MAX_CHARS];
11057 	s16b command;
11058 
11059 	if (connp->id != -1) player = GetInd[connp->id];
11060 		else player = 0;
11061 
11062 	/* Make sure this came from the dungeon master.  Note that it may be
11063 	 * possible to spoof this, so probably in the future more advanced
11064 	 * authentication schemes will be neccecary. -APD
11065 	 */
11066 
11067 	/* Is this necessary here? Maybe (evileye) */
11068 	if (!admin_p(player) &&
11069 	    !player_is_king(player) && !guild_build(player)) {
11070 		/* Hack -- clear the receive and queue buffers since we won't be
11071 		 * reading in the dungeon master parameters that were sent.
11072 		 */
11073 		Sockbuf_clear(&connp->r);
11074 		Sockbuf_clear(&connp->c);
11075 		return 2;
11076 	}
11077 
11078 	if ((n = Packet_scanf(&connp->r, "%c%hd%s", &ch, &command, buf)) <= 0) {
11079 		if (n == -1) Destroy_connection(ind, "read error");
11080 		return n;
11081 	}
11082 
11083 	if (player) {
11084 		switch (command) {
11085 			case MASTER_LEVEL:
11086 				master_level(player, buf);
11087 				break;
11088 			case MASTER_BUILD:
11089 				master_build(player, buf);
11090 				break;
11091 			case MASTER_SUMMON:
11092 				master_summon(player, buf);
11093 				break;
11094 			case MASTER_GENERATE:
11095 				master_generate(player, buf);
11096 				break;
11097 			case MASTER_PLAYER:
11098 				master_player(player, buf);
11099 				break;
11100 			case MASTER_SCRIPTS:
11101 				master_script_exec(player, buf);
11102 				break;
11103 			case MASTER_SCRIPTB:
11104 				master_script_begin(buf + 1, *buf);
11105 				break;
11106 			case MASTER_SCRIPTE:
11107 				master_script_end();
11108 				break;
11109 			case MASTER_SCRIPTL:
11110 				master_script_line(buf);
11111 				break;
11112 		}
11113 	}
11114 
11115 	return 2;
11116 }
11117 
11118 /* automatic phase command, will try to phase door
11119  * in the best way possobile.
11120  *
11121  * This function should probably be improved a lot, I am just
11122  * doing a basic version for now.
11123  */
11124 
11125 static int Receive_autophase(int ind) {
11126 	player_type *p_ptr = NULL;
11127 	connection_t *connp = Conn[ind];
11128 	object_type *o_ptr;
11129 	int player = -1, n;
11130 
11131 	if (connp->id != -1) player = GetInd[connp->id];
11132 		else player = 0;
11133 
11134 	/* a valid player was found, try to do the autophase */
11135 	if (player) {
11136 		p_ptr = Players[player];
11137 		/* first, check the inventory for phase scrolls */
11138 		/* check every item of his inventory */
11139 		for (n = 0; n < INVEN_PACK; n++) {
11140 			o_ptr = &p_ptr->inventory[n];
11141 			if ((o_ptr->tval == TV_SCROLL) && (o_ptr->sval == SV_SCROLL_PHASE_DOOR)) {
11142 				/* found a phase scroll, read it! */
11143 				do_cmd_read_scroll(player, n);
11144 				return 1;
11145 			}
11146 		}
11147 	}
11148 
11149 	/* Failure!  We are in trouble... */
11150 
11151 	return -1;
11152 }
11153 
11154 void end_mind(int Ind, bool update) {
11155 //	int Ind2;
11156 	player_type *p_ptr = Players[Ind];//, *p_ptr2;
11157 
11158 #if 0 /* end_mind() is called by get_esp_link() ! -> infinite recursion in a rare case */
11159 	if ((Ind2 = get_esp_link(Ind, LINKF_VIEW, &p_ptr2))) p_ptr2->update |= PU_MUSIC;
11160 #endif
11161 	if (p_ptr->esp_link_flags & LINKF_VIEW_DEDICATED) p_ptr->update |= PU_MUSIC;
11162 
11163 #if 1 /* in addition, end link on viewee's side -- at least if it's a hidden link, for now */
11164 	if (p_ptr->esp_link_type &&
11165 	    p_ptr->esp_link &&
11166 	    (p_ptr->esp_link_flags & LINKF_HIDDEN)) { //add LINKF_VIEW too?
11167 		int Ind2 = find_player(p_ptr->esp_link);
11168 		if (Ind2) {
11169 			player_type *p2_ptr = Players[Ind2];
11170 
11171 			if (!(p2_ptr->esp_link_flags & LINKF_HIDDEN)) msg_print(Ind2, "\377REnding mind link.");
11172 
11173 			p2_ptr->esp_link = 0;
11174 			p2_ptr->esp_link_type = 0;
11175 			//p2_ptr->esp_link_flags = 0;
11176 			p2_ptr->esp_link_flags &= ~(LINKF_VIEW | LINKF_HIDDEN);
11177 			p2_ptr->esp_link_end = 0; //obsolete? (not saved anyway)
11178 		}
11179 	}
11180 #endif
11181 
11182 	/* end link on viewer's side */
11183 	if (!(p_ptr->esp_link_flags & LINKF_HIDDEN)) msg_print(Ind, "\377REnding mind link.");
11184 	p_ptr->esp_link = 0;
11185 	p_ptr->esp_link_type = 0;
11186 	p_ptr->esp_link_flags = 0;
11187 	if (update) {
11188 		p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
11189 		p_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
11190 		p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
11191 	}
11192 }
11193 
11194 static int Receive_spike(int ind) {
11195 	connection_t *connp = Conn[ind];
11196 	player_type *p_ptr = NULL;
11197 	char ch, dir;
11198 	int n, player = -1;
11199 
11200 	if (connp->id != -1) {
11201 		player = GetInd[connp->id];
11202 		use_esp_link(&player, LINKF_OBJ);
11203 		p_ptr = Players[player];
11204 	}
11205 
11206 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &dir)) <= 0) {
11207 		if (n == -1) Destroy_connection(ind, "read error");
11208 		return n;
11209 	}
11210 
11211 	/* Sanity check */
11212 	if (bad_dir(dir)) return 1;
11213 
11214 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
11215 		do_cmd_spike(player, dir);
11216 		return 2;
11217 	} else if (p_ptr) {
11218 		Packet_printf(&connp->q, "%c%c", ch, dir);
11219 		return 0;
11220 	}
11221 
11222 	return 1;
11223 }
11224 
11225 /*
11226  * Lazy way to add a new command	- Jir -
11227  */
11228 static int Receive_raw_key(int ind)
11229 {
11230 	connection_t *connp = Conn[ind];
11231 	player_type *p_ptr = NULL;
11232 
11233 	char ch, key;
11234 	int n, player = -1;
11235 
11236 	if (connp->id != -1)
11237 	{
11238 		player = GetInd[connp->id];
11239 //		use_esp_link(&player, LINKF_OBJ); /* might be bad, depending on actual command */
11240 		p_ptr = Players[player];
11241 	}
11242 
11243 	if ((n = Packet_scanf(&connp->r, "%c%c", &ch, &key)) <= 0)
11244 	{
11245 		if (n == -1)
11246 			Destroy_connection(ind, "read error");
11247 		return n;
11248 	}
11249 
11250 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos))
11251 	{
11252 		if (p_ptr->store_num != -1)
11253 		{
11254 			switch (key)
11255 			{
11256 				default:
11257 					msg_format(player, "'%c' key does not work in this building.", key);
11258 					break;
11259 			}
11260 		}
11261 		else
11262 		{
11263 			switch (key)
11264 			{
11265 #if 0 /* all in client 4.4.1 or 4.4.0d now! #if 0 this when released */
11266 				/* Drink from a fountain (test passed:) */
11267 				case '_':
11268 					do_cmd_drink_fountain(player);
11269 					break;
11270 				/* Open/close mind to receive items via telekinesis */
11271 				case 'p':
11272 					/* But we can also use this for telekinesis! - C. Blue
11273 					   (mostly to avoid PK exploits */
11274 					if (p_ptr->esp_link_flags & LINKF_TELEKIN) {
11275 						msg_print(player, "\377RYou stop concentrating on telekinesis.");
11276 						p_ptr->esp_link_flags &= ~LINKF_TELEKIN;
11277 					} else {
11278 						msg_print(player, "\377RYou concentrate on telekinesis!");
11279 						p_ptr->esp_link_flags |= LINKF_TELEKIN;
11280 					}
11281 					break;
11282 				case '!':
11283 					/* Look at in-game bbs - C. Blue */
11284 					msg_print(player, "\377wBulletin board (type '/bbs <text>' in chat to write something) :");
11285 					censor_message = TRUE;
11286 					for (n = 0; n < BBS_LINES; n++)
11287 						if (strcmp(bbs_line[n], "")) {
11288 							censor_length = strlen(bbs_line[i]) + bbs_line[i] - strchr(bbs_line[i], ':') - 4;
11289 							msg_format(player, "\377s %s", bbs_line[n]);
11290 							bbs_empty = FALSE;
11291 						}
11292 					censor_message = FALSE;
11293 					if (bbs_empty) msg_print(player, "\377s <nothing has been written on the board so far>");
11294 					break;
11295 //					return 1; /* consume no energy/don't disturb character (resting mode) */
11296 #else
11297 				case '_':
11298 				case '!':
11299 				case 'p':
11300 					msg_print(player, "\377RYour client is outdated (probably version 4.4.0).");
11301 					msg_print(player, "\377RPlease download latest client from www.tomenet.eu");
11302 					break;
11303 #endif
11304 				default:
11305 					msg_format(player, "'%c' key is currently not used.  Hit '?' for help.", key);
11306 					break;
11307 			}
11308 		}
11309 		return 2;
11310 	}
11311 	else if (p_ptr)
11312 	{
11313 		Packet_printf(&connp->q, "%c%c", ch, key);
11314 		return 0;
11315 	}
11316 
11317 	return 1;
11318 }
11319 
11320 /* Reply to ping packets - mikaelh */
11321 static int Receive_ping(int ind) {
11322 	connection_t *connp = Conn[ind];
11323 	char ch, pong, buf[MSG_LEN];
11324 	int n, id, tim, utim, Ind;
11325 	player_type *p_ptr;
11326 
11327 	if ((n = Packet_scanf(&connp->r, "%c%c%d%d%d%S", &ch, &pong, &id, &tim, &utim, &buf)) <= 0) {
11328 		if (n == -1) Destroy_connection(ind, "read error");
11329 		return n;
11330 	}
11331 
11332 	if (!pong) {
11333 		connp->inactive_ping++;
11334 
11335 		if (connp->id != -1) {
11336 			Ind = GetInd[connp->id];
11337 			p_ptr = Players[Ind];
11338 
11339 			p_ptr->idle++;
11340 			p_ptr->idle_char++;
11341 
11342 #if (MAX_PING_RECVS_LOGGED > 0)
11343 			/* Get the exact time and save it */
11344 			p_ptr->pings_received_head = (p_ptr->pings_received_head + 1) % MAX_PING_RECVS_LOGGED;
11345 			gettimeofday(&p_ptr->pings_received[(int) p_ptr->pings_received_head], NULL);
11346 #endif
11347 
11348 			/* Kick a starving player */
11349 			if (p_ptr->idle_starve_kick && p_ptr->food < PY_FOOD_WEAK && connp->inactive_ping > STARVE_KICK_TIMER) {
11350 				Destroy_connection(ind, STARVING_AUTOKICK_MSG);
11351 				return 2;
11352 			}
11353 
11354 			else if (!p_ptr->afk && p_ptr->auto_afk && connp->inactive_ping > AUTO_AFK_TIMER) { /* dont oscillate ;) */
11355 				/* auto AFK timer (>1 min) */
11356 //				if (!p_ptr->resting) toggle_afk(Ind, ""); /* resting can take quite long sometimes */
11357 				toggle_afk(Ind, "");
11358 			}
11359 		}
11360 
11361 		if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) {
11362 			errno = 0;
11363 			plog(format("Connection not ready for pong (%d.%d.%d)",
11364 				ind, connp->state, connp->id));
11365 			return 1;
11366 		}
11367 
11368 		pong = 1;
11369 
11370 		Packet_printf(&connp->c, "%c%c%d%d%d%S", PKT_PING, pong, id, tim, utim, buf);
11371 	}
11372 
11373 	return 2;
11374 }
11375 
11376 static int Receive_sip(int ind) {
11377 	connection_t *connp = Conn[ind];
11378 	player_type *p_ptr = NULL;
11379 	char ch;
11380 	int n, player = -1;
11381 
11382 	if (connp->id != -1)
11383 	{
11384 		player = GetInd[connp->id];
11385 		use_esp_link(&player, LINKF_OBJ);
11386 		p_ptr = Players[player];
11387 	}
11388 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
11389 		if (n == -1) Destroy_connection(ind, "read error");
11390 		return n;
11391 	}
11392 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
11393 		do_cmd_drink_fountain(player);
11394 		return 2;
11395 	} else if (p_ptr) {
11396 		Packet_printf(&connp->q, "%c", ch);
11397 		return 0;
11398 	}
11399 	return 1;
11400 }
11401 
11402 
11403 static int Receive_telekinesis(int ind) {
11404 #if 1 /* taken over by Receive_mind() now, that mindcrafters got fusion */
11405 	return Receive_mind(ind);
11406 #else
11407 	connection_t *connp = Conn[ind];
11408 	player_type *p_ptr = NULL;
11409 	char ch;
11410 	int n, player = -1;
11411 
11412 	if (connp->id != -1)
11413 	{
11414 		player = GetInd[connp->id];
11415 		use_esp_link(&player, LINKF_OBJ);
11416 		p_ptr = Players[player];
11417 	}
11418 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
11419 		if (n == -1) Destroy_connection(ind, "read error");
11420 		return n;
11421 	}
11422 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
11423 		/* Open/close mind to receive items via telekinesis */
11424 		/* But we can also use this for telekinesis! - C. Blue
11425 		   (mostly to avoid PK exploits */
11426 		if (p_ptr->esp_link_flags & LINKF_TELEKIN) {
11427 			msg_print(player, "\377yYou stop concentrating on telekinesis.");
11428 			p_ptr->esp_link_flags &= ~LINKF_TELEKIN;
11429 		} else {
11430 			msg_print(player, "\377RYou concentrate on telekinesis!");
11431 			p_ptr->esp_link_flags |= LINKF_TELEKIN;
11432 		}
11433 		return 2;
11434 	} else if (p_ptr) {
11435 		Packet_printf(&connp->q, "%c", ch);
11436 		return 0;
11437 	}
11438 	return 1;
11439 #endif
11440 }
11441 
11442 static int Receive_BBS(int ind) {
11443 	connection_t *connp = Conn[ind];
11444 	player_type *p_ptr = NULL;
11445 	char ch;
11446 	int n, player = -1;
11447 	bool bbs_empty = TRUE;
11448 
11449 	if (connp->id != -1)
11450 	{
11451 		player = GetInd[connp->id];
11452 		p_ptr = Players[player];
11453 	}
11454 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
11455 		if (n == -1) Destroy_connection(ind, "read error");
11456 		return n;
11457 	}
11458 	if (p_ptr) {
11459 		/* Look at in-game bbs - C. Blue */
11460 		msg_print(player, "\377sBulletin board (type '/bbs <text>' in chat to write something):");
11461 		censor_message = TRUE;
11462 		for (n = 0; n < BBS_LINES; n++)
11463 			if (strcmp(bbs_line[n], "")) {
11464 				censor_length = strlen(bbs_line[n]) + bbs_line[n] - strchr(bbs_line[n], ':') - 4;
11465 				msg_format(player, "\377s %s", bbs_line[n]);
11466 				bbs_empty = FALSE;
11467 			}
11468 		censor_message = FALSE;
11469 		if (bbs_empty) msg_print(player, "\377s <nothing has been written on the board so far>");
11470 		return 2; /* consume no energy/don't disturb character (resting mode) */
11471 	} else if (p_ptr) {
11472 		Packet_printf(&connp->q, "%c", ch);
11473 		return 0;
11474 	}
11475 	return 1;
11476 }
11477 
11478 static int Receive_wield2(int ind) {
11479 	connection_t *connp = Conn[ind];
11480 	player_type *p_ptr = NULL;
11481 
11482 	char ch;
11483 	s16b item;
11484 	int n, player = -1;
11485 
11486 	if (connp->id != -1) {
11487 		player = GetInd[connp->id];
11488 		use_esp_link(&player, LINKF_OBJ);
11489 		p_ptr = Players[player];
11490 	}
11491 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0) {
11492 		if (n == -1) Destroy_connection(ind, "read error");
11493 		return n;
11494 	}
11495 
11496 	/* Sanity check - mikaelh */
11497 	if (item >= INVEN_TOTAL)
11498 		return 1;
11499 
11500 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
11501 		item = replay_inven_changes(player, item);
11502 		if (item == 0xFF)
11503 		{
11504 			msg_print(player, "Command failed because item is gone.");
11505 			return 1;
11506 		}
11507 
11508 		do_cmd_wield(player, item, 0x2);
11509 		return 2;
11510 	} else if (p_ptr) {
11511 		Packet_printf(&connp->q, "%c%hd", ch, item);
11512 		return 0;
11513 	}
11514 	return 1;
11515 }
11516 
11517 static int Receive_cloak(int ind) {
11518 	connection_t *connp = Conn[ind];
11519 	player_type *p_ptr = NULL;
11520 	char ch;
11521 	int n, player = -1;
11522 
11523 	if (connp->id != -1)
11524 	{
11525 		player = GetInd[connp->id];
11526 		use_esp_link(&player, LINKF_OBJ);
11527 		p_ptr = Players[player];
11528 	}
11529 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
11530 		if (n == -1) Destroy_connection(ind, "read error");
11531 		return n;
11532 	}
11533 	if (p_ptr && p_ptr->energy >= level_speed(&p_ptr->wpos)) {
11534 		do_cmd_cloak(player);
11535 		return 2;
11536 	} else if (p_ptr) {
11537 		Packet_printf(&connp->q, "%c", ch);
11538 		return 0;
11539 	}
11540 	return 1;
11541 }
11542 
11543 void change_mind(int Ind, bool open_or_close) {
11544 	int Ind2;
11545 	player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
11546 	bool d = TRUE;
11547 
11548 	/* 'hidden link' is unaffected by 'passive' change_mind() calls */
11549 	if ((p_ptr->esp_link_flags & LINKF_HIDDEN) && !open_or_close) return;
11550 
11551 	if ((Ind2 = get_esp_link(Ind, 0x0, &p_ptr2)) &&
11552 	    !(p_ptr->esp_link_flags & LINKF_HIDDEN)) {
11553 		if (p_ptr->esp_link_type == LINK_DOMINATED) {
11554 			if (!p_ptr->esp_link_end) {
11555 				p_ptr->esp_link_end = rand_int(6) + 15;
11556 			} else {
11557 				/* can't stabilize link while on different floors! */
11558 				if (!inarea(&p_ptr->wpos, &p_ptr2->wpos)) return;
11559 
11560 				p_ptr->esp_link_end = 0;
11561 				d = FALSE;
11562 			}
11563 		}
11564 		if (p_ptr2->esp_link_type == LINK_DOMINATED) {
11565 			if (!p_ptr2->esp_link_end) {
11566 				p_ptr2->esp_link_end = rand_int(6) + 15;
11567 			} else {
11568 				/* can't stabilize link while on different floors! */
11569 				if (!inarea(&p_ptr->wpos, &p_ptr2->wpos)) return;
11570 
11571 				p_ptr2->esp_link_end = 0;
11572 				d = FALSE;
11573 			}
11574 		}
11575 
11576 		if (d) {
11577 			if (!(p_ptr->esp_link_flags & LINKF_HIDDEN)) {
11578 				msg_format(Ind, "\377RThe mind link with %s begins to break.", p_ptr2->name);
11579 				msg_format(Ind2, "\377RThe mind link with %s begins to break.", p_ptr->name);
11580 			}
11581 		} else {
11582 			if (!(p_ptr->esp_link_flags & LINKF_HIDDEN)) {
11583 				msg_format(Ind, "\377yThe mind link with %s stabilizes.", p_ptr2->name);
11584 				msg_format(Ind2, "\377yThe mind link with %s stabilizes.", p_ptr->name);
11585 			}
11586 		}
11587 	} else {
11588 		if (p_ptr->esp_link_flags & LINKF_OPEN) {
11589 			msg_print(Ind, "\377yYou close your mind.");
11590 			p_ptr->esp_link_flags &= ~(LINKF_OPEN | LINKF_TELEKIN);
11591 		} else {
11592 			msg_print(Ind, "\377RYou open your mind..");
11593 			p_ptr->esp_link_flags |= (LINKF_OPEN | LINKF_TELEKIN);
11594 		}
11595 	}
11596 }
11597 
11598 static int Receive_inventory_revision(int ind) {
11599 	connection_t *connp = Conn[ind];
11600 	player_type *p_ptr = NULL;
11601 	char ch;
11602 	int n, player = -1;
11603 	int revision;
11604 
11605 	if (connp->id != -1)
11606 	{
11607 		player = GetInd[connp->id];
11608 		p_ptr = Players[player];
11609 	}
11610 	if ((n = Packet_scanf(&connp->r, "%c%d", &ch, &revision)) <= 0) {
11611 		if (n == -1) Destroy_connection(ind, "read error");
11612 		return n;
11613 	}
11614 	if (p_ptr) {
11615 		if (connp->q.len) {
11616 			/* There are some queued packets, block any further
11617 			 * packets until the queue is empty
11618 			 */
11619 			Packet_printf(&connp->q, "%c%d", ch, revision);
11620 			return 3; /* special return code */
11621 		} else {
11622 			inven_confirm_revision(player, revision);
11623 			return 2;
11624 		}
11625 	} else if (p_ptr) {
11626 		Packet_printf(&connp->q, "%c%d", ch, revision);
11627 		return 0;
11628 	}
11629 	return 1;
11630 }
11631 
11632 static int Receive_account_info(int ind) {
11633 	connection_t *connp = Conn[ind];
11634 	char ch;
11635 	int n, player = -1;
11636 
11637 	if (connp->id != -1)
11638 	{
11639 		player = GetInd[connp->id];
11640 	}
11641 	if ((n = Packet_scanf(&connp->r, "%c", &ch)) <= 0) {
11642 		if (n == -1) Destroy_connection(ind, "read error");
11643 		return n;
11644 	}
11645 
11646 	if (player > 0) {
11647 		Send_account_info(player);
11648 	}
11649 
11650 	return 1;
11651 }
11652 
11653 static int Receive_change_password(int ind) {
11654 	connection_t *connp = Conn[ind];
11655 	char ch;
11656 	int n, player = -1;
11657 	char old_pass[MAX_CHARS], new_pass[MAX_CHARS];
11658 
11659 	if (connp->id != -1)
11660 	{
11661 		player = GetInd[connp->id];
11662 	}
11663 	if ((n = Packet_scanf(&connp->r, "%c%s%s", &ch, old_pass, new_pass)) <= 0) {
11664 		if (n == -1) Destroy_connection(ind, "read error");
11665 		return n;
11666 	}
11667 
11668 	if (player > 0) {
11669 		/* Obfuscation */
11670 		my_memfrob(old_pass, strlen(old_pass));
11671 		my_memfrob(new_pass, strlen(new_pass));
11672 
11673 		account_change_password(player, old_pass, new_pass);
11674 
11675 		/* Wipe the passwords from memory */
11676 		memset(old_pass, 0, MAX_CHARS);
11677 		memset(new_pass, 0, MAX_CHARS);
11678 	}
11679 
11680 	return 1;
11681 }
11682 
11683 static int Receive_force_stack(int ind) {
11684 	connection_t *connp = Conn[ind];
11685 	char ch;
11686 	int n, player = -1;
11687 	s16b item;
11688 	player_type *p_ptr = NULL;
11689 
11690 	if (connp->id != -1)
11691 	{
11692 		player = GetInd[connp->id];
11693 		use_esp_link(&player, LINKF_OBJ);
11694 		p_ptr = Players[player];
11695 	}
11696 
11697 	if ((n = Packet_scanf(&connp->r, "%c%hd", &ch, &item)) <= 0)
11698 	{
11699 		if (n == -1)
11700 			Destroy_connection(ind, "read error");
11701 		return n;
11702 	}
11703 
11704 	/* Sanity check - mikaelh */
11705 	if (item >= INVEN_PACK)
11706 		return 1;
11707 
11708 	if (p_ptr) {
11709 		item = replay_inven_changes(player, item);
11710 		if (item == 0xFF)
11711 		{
11712 			msg_print(player, "Command failed because item is gone.");
11713 			return 1;
11714 		}
11715 
11716 		do_cmd_force_stack(player, item);
11717 	}
11718 
11719 	return 1;
11720 }
11721 
11722 static int Receive_request_key(int ind) {
11723 	connection_t *connp = Conn[ind];
11724 	player_type *p_ptr = NULL;
11725 
11726 	char ch, key;
11727 	int n, id, player = -1;
11728 	if (connp->id != -1) {
11729 		player = GetInd[connp->id];
11730 //		use_esp_link(&player, LINKF_OBJ);
11731 		p_ptr = Players[player];
11732 	}
11733 
11734 	if ((n = Packet_scanf(&connp->r, "%c%d%c", &ch, &id, &key)) <= 0) {
11735 		if (n == -1) Destroy_connection(ind, "read error");
11736 		return n;
11737 	}
11738 	if (!p_ptr) return 1;
11739 
11740 	handle_request_return_key(player, id, key);
11741 	return 2;
11742 }
11743 static int Receive_request_num(int ind) {
11744 	connection_t *connp = Conn[ind];
11745 	player_type *p_ptr = NULL;
11746 
11747 	char ch;
11748 	int n, id, player = -1, num;
11749 	if (connp->id != -1) {
11750 		player = GetInd[connp->id];
11751 //		use_esp_link(&player, LINKF_OBJ);
11752 		p_ptr = Players[player];
11753 	}
11754 
11755 	if ((n = Packet_scanf(&connp->r, "%c%d%d", &ch, &id, &num)) <= 0) {
11756 		if (n == -1) Destroy_connection(ind, "read error");
11757 		return n;
11758 	}
11759 	if (!p_ptr) return 1;
11760 
11761 	handle_request_return_num(player, id, num);
11762 	return 2;
11763 }
11764 static int Receive_request_str(int ind) {
11765 	connection_t *connp = Conn[ind];
11766 	player_type *p_ptr = NULL;
11767 
11768 	char ch, str[MSG_LEN];
11769 	int n, id, player = -1;
11770 	if (connp->id != -1) {
11771 		player = GetInd[connp->id];
11772 //		use_esp_link(&player, LINKF_OBJ);
11773 		p_ptr = Players[player];
11774 	}
11775 
11776 	if ((n = Packet_scanf(&connp->r, "%c%d%s", &ch, &id, str)) <= 0) {
11777 		if (n == -1) Destroy_connection(ind, "read error");
11778 		return n;
11779 	}
11780 	if (!p_ptr) return 1;
11781 
11782 	handle_request_return_str(player, id, str);
11783 	return 2;
11784 }
11785 static int Receive_request_cfr(int ind) {
11786 	connection_t *connp = Conn[ind];
11787 	player_type *p_ptr = NULL;
11788 
11789 	char ch;
11790 	int n, id, player = -1, cfr;
11791 	if (connp->id != -1) {
11792 		player = GetInd[connp->id];
11793 //		use_esp_link(&player, LINKF_OBJ);
11794 		p_ptr = Players[player];
11795 	}
11796 
11797 	if ((n = Packet_scanf(&connp->r, "%c%d%d", &ch, &id, &cfr)) <= 0) {
11798 		if (n == -1) Destroy_connection(ind, "read error");
11799 		return n;
11800 	}
11801 	if (!p_ptr) return 1;
11802 
11803 	handle_request_return_cfr(player, id, (cfr != 0));
11804 	return 2;
11805 }
11806 
11807 
11808 /* return some connection data for improved log handling - C. Blue */
11809 char *get_conn_userhost(int ind) {
11810 	return(format("%s@%s", Conn[ind]->real, Conn[ind]->host));
11811 }
11812 
11813 char *get_player_ip(int Ind) {
11814 	return(Conn[Players[Ind]->conn]->addr);
11815 }
11816 
11817 bool get_conn_state_ok(int Ind) {
11818 	connection_t *connp = Conn[Players[Ind]->conn];
11819 	if (!BIT(connp->state, CONN_PLAYING | CONN_READY)) return FALSE;
11820 	return TRUE;
11821 }
11822 
11823 sockbuf_t *get_conn_q(int Ind) {
11824 	return &Conn[Players[Ind]->conn]->q;
11825 }
11826