From: Holger Schemel Date: Fri, 9 Oct 1998 23:10:36 +0000 (+0200) Subject: rnd-19981010-1 X-Git-Tag: 1.2.0^2~62 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=1cacebfb41c20889c904155001a5b88ace962348;p=rocksndiamonds.git rnd-19981010-1 --- diff --git a/src/Makefile b/src/Makefile index a6ce59b4..a4f45718 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,7 @@ # PROGNAME = rocksndiamonds -SERVNAME = rnd_server +# SERVNAME = rnd_server RM = rm -f CC = gcc @@ -68,7 +68,8 @@ SRCS = main.c \ gif.c \ send.c \ new.c \ - network.c + network.c \ + netserv.c OBJS = main.o \ init.o \ @@ -89,15 +90,17 @@ OBJS = main.o \ gif.o \ send.o \ new.o \ - network.o + network.o \ + netserv.o -all: $(PROGNAME) $(SERVNAME) +# all: $(PROGNAME) $(SERVNAME) +all: $(PROGNAME) $(PROGNAME): $(OBJS) $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $(PROGNAME) -$(SERVNAME): $(SERVNAME).c - $(CC) $(CFLAGS) $(SERVNAME).c $(LIBS) -o $(SERVNAME) +# $(SERVNAME): $(SERVNAME).c +# $(CC) $(CFLAGS) $(SERVNAME).c $(LIBS) -o $(SERVNAME) .c.o: $(CC) $(CFLAGS) -c $*.c diff --git a/src/init.c b/src/init.c index 76ff5941..ecafc3b8 100644 --- a/src/init.c +++ b/src/init.c @@ -115,7 +115,7 @@ void InitSound() { int i; - if (sound_status==SOUND_OFF) + if (sound_status == SOUND_OFF) return; #ifndef MSDOS @@ -126,7 +126,7 @@ void InitSound() return; } - if ((sound_device=open(sound_device_name,O_WRONLY))<0) + if ((sound_device = open(sound_device_name,O_WRONLY))<0) { Error(ERR_RETURN, "cannot open sound device - no sounds"); sound_status = SOUND_OFF; @@ -134,7 +134,7 @@ void InitSound() } close(sound_device); - sound_status=SOUND_AVAILABLE; + sound_status = SOUND_AVAILABLE; #ifdef VOXWARE sound_loops_allowed = TRUE; @@ -145,7 +145,7 @@ void InitSound() sound_loops_on = TRUE; #endif - for(i=0;i + * + * Started: 10 Oct 1996 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. See the file COPYING for details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netserv.h" + + + +extern int verbose; + +extern void copydown(char *, char *, int); +extern void fatal(char *); + + + +static int clients = 0; +static int bots = 0; +static int onceonly = 0; +static int timetoplay = 0; +static int is_daemon = 0; +static int level = 5; +static int mode = -1; +static int paused = 0; + +struct user +{ + int fd; + unsigned char nick[16]; + unsigned char number; + struct user *next, *nextvictim; + char active; + char introduced; + unsigned char readbuf[MAX_BUFFER_SIZE]; + int nread; + unsigned char writbuf[MAX_BUFFER_SIZE]; + int nwrite; + char playing; + char isbot; + int lines; + unsigned int games; + unsigned char action; + int action_received; +}; + +static struct user *user0 = NULL; + +#define NEXT(u) ((u)->next ? (u)->next : user0) + +static struct sockaddr_in saddr; +static int lfd; +static unsigned char realbuf[512], *buf = realbuf + 4; + +static int interrupt; +static int tcp = -1; + +static unsigned long frame_counter = 0; + +static fd_set fds; + +void syserr(char *s) +{ + if (!is_daemon) + fprintf(stderr, "fatal: %s failed.\n", s); + exit(1); +} + +void addtobuffer(struct user *u, unsigned char *b, int len) +{ + if (u->nwrite + len >= MAX_BUFFER_SIZE) + fatal("Internal error: send buffer overflow"); + memcpy(u->writbuf + u->nwrite, b, len); + u->nwrite += len; +} + +void flushuser(struct user *u) +{ + if (u->nwrite) + { + write(u->fd, u->writbuf, u->nwrite); + u->nwrite = 0; + } +} + +void broadcast(struct user *except, int len, int activeonly) +{ + struct user *u; + + realbuf[0] = realbuf[1] = realbuf[2] = 0; + realbuf[3] = (unsigned char)len; + for (u=user0; u; u=u->next) + if (u != except && (u->active || !activeonly) && u->introduced) + addtobuffer(u, realbuf, 4 + len); +} + +void sendtoone(struct user *to, int len) +{ + realbuf[0] = realbuf[1] = realbuf[2] = 0; + realbuf[3] = (unsigned char)len; + addtobuffer(to, realbuf, 4 + len); +} + +void dropuser(struct user *u) +{ + struct user *v, *w; + + if (verbose) + printf("RND_SERVER: dropping client %d (%s)\n", u->number, u->nick); + + if (u == user0) + user0 = u->next; + else + { + for (v=user0; v; v=v->next) + { + if (v->next && v->next == u) + { + v->next = u->next; + break; + } + } + } + close(u->fd); + + if (u->introduced) + { + buf[0] = u->number; + buf[1] = OP_PLAYER_DISCONNECTED; + broadcast(u, 2, 0); + } + + for (v=user0; v; v=v->next) + { + if (v->nextvictim == u) + { + for (w=NEXT(v); w!=v; w=NEXT(w)) + { + if (w->active && w->playing) + { + v->nextvictim = w; + break; + } + } + if (v->nextvictim == u) + v->nextvictim = NULL; + } + } + + if (u->isbot) + bots--; + + free(u); + clients--; + + if (onceonly && clients == bots) + { + if (verbose) + { + printf("RND_SERVER: no clients left\n"); + printf("RND_SERVER: aborting\n"); + } + exit(0); + } + + if (clients == 0) + { + mode = -1; + level = 5; + timetoplay = 0; + } +} + +void do_play() +{ + struct user *v, *w; + + for (w=user0; w; w=w->next) + { + if (w->introduced) + { + w->active = 1; + w->playing = 1; + w->lines = 0; + w->nextvictim = NULL; + for (v=NEXT(w); v!=w; v=NEXT(v)) + { + if (v->introduced) + { + w->nextvictim = v; + break; + } + } + } + } + + /* + if (paused) + { + paused = 0; + buf[1] = OP_CONT; + broadcast(NULL, 2, 0); + } + buf[1] = OP_START_PLAYING; + broadcast(NULL, 2, 0); + */ + + /* reset frame counter */ + frame_counter = 0; + + /* reset player actions */ + for (v=user0; v; v=v->next) + { + v->action = 0; + v->action_received = 0; + } + + broadcast(NULL, 10 + strlen(&buf[10])+1, 0); + +} + +void new_connect(int fd) +{ + struct user *u, *v; + unsigned char nxn; + + u = malloc(sizeof (struct user)); + if (!u) + fatal("Out of memory"); + u->fd = fd; + u->nick[0] = 0; + u->next = user0; + u->nextvictim = NULL; + u->active = 0; + u->nread = 0; + u->nwrite = 0; + u->playing = 0; + u->isbot = 0; + u->introduced = 0; + u->games = 0; + u->action = 0; + u->action_received = 0; + + user0 = u; + + nxn = 1; + +again: + v = u->next; + while(v) + { + if (v->number == nxn) + { + nxn++; + goto again; + } + v = v->next; + } + + u->number = nxn; + if (verbose) + printf("RND_SERVER: client %d connecting from %s\n", nxn, inet_ntoa(saddr.sin_addr)); + clients++; + + buf[0] = 0; + buf[1] = OP_YOUR_NUMBER; + buf[2] = u->number; + sendtoone(u, 3); +} + +void NetworkServer(int port, int onceonly) +{ + int i, sl, on; + struct user *u, *v, *w; + int mfd; + int r; + unsigned int len; + struct protoent *tcpproto; + struct timeval tv; + int is_daemon = 0; + +#ifndef NeXT + struct sigaction sact; +#endif + + if (port == 0) + port = DEFAULTPORT; + + if ((tcpproto = getprotobyname("tcp")) != NULL) + tcp = tcpproto->p_proto; + +#ifdef NeXT + signal(SIGPIPE, SIG_IGN); +#else + sact.sa_handler = SIG_IGN; + sigemptyset(&sact.sa_mask); + sact.sa_flags = 0; + sigaction(SIGPIPE, &sact, NULL); +#endif + + + lfd = socket(PF_INET, SOCK_STREAM, 0); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_port = htons(port); + + if (lfd < 0) + syserr("socket"); + on = 1; + + setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int)); + if (bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) + syserr("bind"); + + listen(lfd, 5); + + if (is_daemon) + { + /* become a daemon, breaking all ties with the controlling terminal */ + verbose = 0; + for (i=0; i<255; i++) + { + if (i != lfd) + close(i); + } + if (fork()) + exit(0); + setsid(); + if (fork()) + exit(0); + chdir("/"); + /* open a fake stdin, stdout, stderr, just in case */ + open("/dev/null", O_RDONLY); + open("/dev/null", O_WRONLY); + open("/dev/null", O_WRONLY); + } + + if (verbose) + { + printf("rocksndiamonds network server: started up, listening on port %d\n", + port); + printf("rocksndiamonds network server: using protocol version %d.%d.%d\n", + PROT_VERS_1, PROT_VERS_2, PROT_VERS_3); + } + + while(1) + { + interrupt = 0; + + if (timetoplay && time(NULL) >= timetoplay) + { + buf[0] = 0; + do_play(); + if (verbose) + printf("RND_SERVER: everyone lost... restarting game\n"); + timetoplay = 0; + } + + for (u=user0; u; u=u->next) + flushuser(u); + + FD_ZERO(&fds); + mfd = lfd; + u = user0; + while (u) + { + FD_SET(u->fd, &fds); + if (u->fd > mfd) + mfd = u->fd; + u = u->next; + } + FD_SET(lfd, &fds); + tv.tv_sec = 0; + tv.tv_usec = 500000; + if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0) + if (errno != EINTR) + syserr("select"); + else continue; + + if (sl < 0) + continue; + + if (clients > 0 && clients == bots) + { + if (verbose) + printf("RND_SERVER: only bots left... dropping all bots\n"); + while (user0) + dropuser(user0); + continue; + } + + if (sl == 0) + continue; + + if (FD_ISSET(lfd, &fds)) + { + int newfd, slen; + + slen = sizeof(saddr); + newfd = accept(lfd, (struct sockaddr *)&saddr, &slen); + if (newfd < 0) + { + if (errno != EINTR) + syserr("accept"); + } + else + { + if (tcp != -1) + { + on = 1; + setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int)); + } + new_connect(newfd); + } + continue; + } + + u = user0; + + do + { + if (FD_ISSET(u->fd, &fds)) + { + r = read(u->fd, u->readbuf + u->nread, MAX_BUFFER_SIZE - u->nread); + if (r <= 0) + { + if (verbose) + printf("RND_SERVER: EOF from client %d (%s)\n", u->number, u->nick); + dropuser(u); + interrupt = 1; + break; + } + u->nread += r; + while (u->nread >= 4 && u->nread >= 4 + u->readbuf[3]) + { + len = u->readbuf[3]; + if (u->readbuf[0] || u->readbuf[1] || u->readbuf[2]) + { + if (verbose) + printf("RND_SERVER: crap from client %d (%s)\n", u->number, u->nick); + write(u->fd, "\033]50;kanji24\007\033#8\033(0", 19); + dropuser(u); + interrupt = 1; + break; + } + memcpy(buf, &u->readbuf[4], len); + u->nread -= 4 + len; + copydown(u->readbuf, u->readbuf + 4 + len, u->nread); + + buf[0] = u->number; + if (!u->introduced && buf[1] != OP_NICKNAME) + { + if (verbose) + printf("RND_SERVER: !(client %d)->introduced && buf[1]==%d (expected OP_NICKNAME)\n", buf[0], buf[1]); + + dropuser(u); + interrupt = 1; + break; + } + + switch(buf[1]) + { + case OP_NICKNAME: + if (len>16) + len=16; + memcpy(u->nick, &buf[2], len-2); + u->nick[len-2] = 0; + for (i=0; inick[i] < ' ' || + (u->nick[i] > 0x7e && u->nick[i] <= 0xa0)) + { + u->nick[i] = 0; + break; + } + } + + if (!u->introduced) + { + buf[0] = u->number; + buf[1] = OP_PLAYER_CONNECTED; + broadcast(u, 2, 0); + } + + if (verbose) + printf("RND_SERVER: client %d calls itself \"%s\"\n", u->number, u->nick); + buf[1] = OP_NICKNAME; + broadcast(u, len, 0); + + if (!u->introduced) + { + for (v=user0; v; v=v->next) + { + if (v != u && v->introduced) + { + buf[0] = v->number; + buf[1] = OP_PLAYER_CONNECTED; + buf[2] = (v->games >> 8); + buf[3] = (v->games & 0xff); + sendtoone(u, 4); + buf[1] = OP_NICKNAME; + memcpy(&buf[2], v->nick, 14); + sendtoone(u, 2+strlen(v->nick)); + } + } + if (level != 5) + { + buf[0] = 0; + buf[1] = OP_LEVEL; + buf[2] = level; + sendtoone(u, 3); + } + if (mode >= 0) + { + buf[1] = OP_MODE; + buf[2] = mode; + sendtoone(u, 3); + } + } + + u->introduced = 1; + break; + + case OP_KILL: + for (v=user0; v; v=v->next) + { + if (v->number == buf[2]) + break; + } + if (v) + { + if (v->isbot) + { + if (verbose) + printf("RND_SERVER: client %d (%s) kills bot %d (%s)\n", u->number, u->nick, v->number, v->nick); + + dropuser(v); + interrupt = 1; + break; + } + else + { + if (verbose) + printf("RND_SERVER: client %d (%s) attempting to kill non-bot %d (%s)\n", u->number, u->nick, v->number, v->nick); + } + } + break; + + case OP_START_PLAYING: + if (verbose) + printf("RND_SERVER: client %d (%s) starts game [level %d from levedir %d (%s)]\n", + u->number, u->nick, + (buf[2] << 8) + buf[3], + (buf[4] << 8) + buf[5], + &buf[6]); + timetoplay = 0; + do_play(); + break; + + case OP_MOVE_FIGURE: + { + int actions_complete = 1; + int last_client_nr = 0; + + /* store player action */ + for (v=user0; v; v=v->next) + { + if (v->number == u->number) + { + v->action = buf[2]; + v->action_received = 1; + } + } + + /* check if server received action from each player */ + for (v=user0; v; v=v->next) + { + if (!v->action_received) + { + actions_complete = 0; + break; + } + } + + if (!actions_complete) + break; + + /* broadcast actions of all players to all players */ + for (v=user0; v; v=v->next) + { + buf[6 + v->number-1] = v->action; + v->action = 0; + v->action_received = 0; + + if (v->number > last_client_nr) + last_client_nr = v->number; + } + + buf[2] = (unsigned char)((frame_counter >> 24) & 0xff); + buf[3] = (unsigned char)((frame_counter >> 16) & 0xff); + buf[4] = (unsigned char)((frame_counter >> 8) & 0xff); + buf[5] = (unsigned char)((frame_counter >> 0) & 0xff); + + broadcast(NULL, 6 + last_client_nr, 0); + + frame_counter++; + + /* + if (verbose) + printf("RND_SERVER: frame %d: client %d (%s) moves player [0x%02x]\n", + frame_counter, + u->number, u->nick, buf[2]); + */ + + break; + } + + case OP_MODE: + mode = buf[2]; + if (verbose) + printf("RND_SERVER: client %d (%s) sets mode %d (%s)\n", u->number, u->nick, buf[2], buf[2] == 0 ? "normal" : (buf[2] == 1 ? "fun" : "unknown")); + broadcast(NULL, 3, 0); + break; + + case OP_PAUSE: + if (verbose) + printf("RND_SERVER: client %d (%s) pauses game\n", u->number, u->nick); + broadcast(NULL, 2, 0); + paused = 1; + break; + + case OP_CONT: + if (verbose) + printf("RND_SERVER: client %d (%s) continues game\n", u->number, u->nick); + broadcast(NULL, 2, 0); + paused = 0; + break; + + case OP_BOT: + if (!u->isbot) + bots++; + u->isbot = 1; + if (verbose) + printf("RND_SERVER: client %d (%s) declares itself to be a bot\n", u->number, u->nick); + break; + + case OP_LEVEL: + level = buf[2]; + if (verbose) + printf("RND_SERVER: client %d (%s) sets level %d\n", u->number, u->nick, buf[2]); + broadcast(NULL, 3, 0); + break; + + case OP_LOST: + { + struct user *won = NULL; + + if (verbose) + printf("RND_SERVER: client %d (%s) has lost\n", u->number, u->nick); + u->playing = 0; + broadcast(u, 2, 1); + i = 0; + for (v=user0; v; v=v->next) + { + if (v->nextvictim == u) + { + for (w=NEXT(v); w!=v; w=NEXT(w)) + { + if (w->active && w->playing) + { + v->nextvictim = w; + break; + } + } + if (v->nextvictim == u) + v->nextvictim = NULL; + } + } + for (v=user0; v; v=v->next) + { + if (v->playing) + { + i++; + won = v; + } + } + if (i == 1) + { + buf[0] = won->number; + buf[1] = OP_WON; + won->games++; + broadcast(NULL, 2, 0); + } + else if (i == 0) + { + buf[0] = u->number; + buf[1] = OP_WON; + u->games++; + broadcast(NULL, 2, 0); + } + if (i < 2 && clients > 1) + timetoplay = time(NULL) + 4; + } + break; + + case OP_ZERO: + broadcast(NULL, 2, 0); + if (verbose) + printf("RND_SERVER: client %d (%s) resets the game counters\n", u->number, u->nick); + for (v=user0; v; v=v->next) + v->games = 0; + break; + + case OP_CLEAR: + case OP_GROW: + broadcast(u, 2, 1); + break; + + case OP_MSG: + buf[len] = '\0'; + if (verbose) + printf("RND_SERVER: client %d (%s) sends message: %s\n", u->number, u->nick, &buf[2]); + broadcast(u, len, 0); + break; + + case OP_NUMBER_WANTED: + { + int nr_wanted = buf[2]; + int nr_is_free = 1; + + if (verbose) + printf("RND_SERVER: client %d (%s) wants to switch to # %d\n", + u->number, u->nick, nr_wanted); + + for (v=user0; v; v=v->next) + { + if (v->number == nr_wanted) + { + nr_is_free = 0; + break; + } + } + + if (verbose) + { + if (nr_is_free) + printf("RND_SERVER: client %d (%s) switches to # %d\n", + u->number, u->nick, nr_wanted); + else if (u->number == nr_wanted) + printf("RND_SERVER: client %d (%s) still has # %d\n", + u->number, u->nick, nr_wanted); + else + printf("RND_SERVER: client %d (%s) cannot switch (client %d still exists)\n", + u->number, u->nick, nr_wanted); + } + + if (nr_is_free) + u->number = nr_wanted; + + buf[0] = 0; + buf[1] = OP_NUMBER_WANTED; + buf[2] = nr_wanted; + buf[3] = u->number; + sendtoone(u, 4); + break; + } + + case OP_PROTOCOL_VERSION: + if (len != 5 || buf[2] != PROT_VERS_1 || buf[3] != PROT_VERS_2) + { + if (verbose) + printf("RND_SERVER: client %d (%s) has wrong protocol version %d.%d.%d\n", u->number, u->nick, buf[2], buf[3], buf[4]); + + buf[0] = 0; + buf[1] = OP_BADVERS; + buf[2] = PROT_VERS_1; + buf[3] = PROT_VERS_2; + buf[4] = PROT_VERS_3; + sendtoone(u, 5); + flushuser(u); + + dropuser(u); + interrupt = 1; + } + else + { + if (verbose) + printf("RND_SERVER: client %d (%s) uses protocol version %d.%d.%d\n", u->number, u->nick, buf[2], buf[3], buf[4]); + } + break; + + case OP_LINES: + if (len != 3) + { + if (verbose) + printf("RND_SERVER: client %d (%s) sends crap for an OP_LINES\n", u->number, u->nick); + + dropuser(u); + interrupt = 1; + break; + } + if (u->nextvictim) + { + if (verbose) + printf("RND_SERVER: client %d (%s) sends %d %s to client %d (%s)\n", u->number, u->nick, (int)buf[2], buf[2] == 1 ? "line" : "lines", u->nextvictim->number, u->nextvictim->nick); + sendtoone(u->nextvictim, 3); + buf[3] = u->nextvictim->number; + buf[1] = OP_LINESTO; + broadcast(u->nextvictim, 4, 1); + for (v=NEXT(u->nextvictim); v!=u->nextvictim; v=NEXT(v)) + { + if (v->active && v != u && v->playing) + { + u->nextvictim = v; + break; + } + } + } + else if (verbose) + printf("RND_SERVER: client %d (%s) makes %d %s but has no victim\n", u->number, u->nick, (int)buf[2], buf[2] == 1 ? "line" : "lines"); + break; + + default: + if (verbose) + printf("RND_SERVER: opcode %d from client %d (%s) not understood\n", buf[0], u->number, u->nick); + } + } + } + + if (u && !interrupt) + u = u->next; + } + while (u && !interrupt); + } +} diff --git a/src/netserv.h b/src/netserv.h new file mode 100644 index 00000000..537b3002 --- /dev/null +++ b/src/netserv.h @@ -0,0 +1,55 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* (c) 1995-98 Artsoft Entertainment * +* Holger Schemel * +* Oststrasse 11a * +* 33604 Bielefeld * +* phone: ++49 +521 290471 * +* email: aeglos@valinor.owl.de * +*----------------------------------------------------------* +* netserv.h * +***********************************************************/ + +#ifndef NETSERV_H +#define NETSERV_H + +#define DEFAULTPORT 19504 + +#define PROT_VERS_1 1 +#define PROT_VERS_2 2 +#define PROT_VERS_3 0 + +#define OP_PROTOCOL_VERSION 1 +#define OP_BAD_PROTOCOL_VERSION 2 +#define OP_PLAYER_CONNECTED 3 +#define OP_PLAYER_DISCONNECTED 4 +#define OP_YOUR_NUMBER 5 +#define OP_NUMBER_WANTED 6 +#define OP_NICKNAME 7 +#define OP_START_PLAYING 8 +#define OP_MOVE_FIGURE 9 + +#define OP_LOST 10 +#define OP_GONE 11 +#define OP_CLEAR 12 +#define OP_LINES 13 +#define OP_GROW 14 +#define OP_MODE 15 +#define OP_LEVEL 16 +#define OP_BOT 17 +#define OP_KILL 18 +#define OP_PAUSE 19 +#define OP_CONT 20 +#define OP_BADVERS 21 +#define OP_MSG 22 +#define OP_YOUARE 23 +#define OP_LINESTO 24 +#define OP_WON 25 +#define OP_ZERO 26 + +#define MAX_BUFFER_SIZE 4096 + +void NetworkServer(int, int); + +#endif diff --git a/src/network.c b/src/network.c index a88d55f6..bb4ea67e 100644 --- a/src/network.c +++ b/src/network.c @@ -26,45 +26,13 @@ #include #include "network.h" +#include "netserv.h" #include "game.h" #include "tape.h" #include "files.h" #include "tools.h" #include "misc.h" -int norestart = 0; -int nospeedup = 0; - -#define DEFAULTPORT 19503 - -#define PROT_VERS_1 1 -#define PROT_VERS_2 0 -#define PROT_VERS_3 1 - -#define OP_NICK 1 -#define OP_PLAY 2 -#define OP_MOVE 3 -#define OP_NRWANTED 4 -#define OP_LOST 5 -#define OP_GONE 6 -#define OP_CLEAR 7 -#define OP_NEW 8 -#define OP_LINES 9 -#define OP_GROW 10 -#define OP_MODE 11 -#define OP_LEVEL 12 -#define OP_BOT 13 -#define OP_KILL 14 -#define OP_PAUSE 15 -#define OP_CONT 16 -#define OP_VERSION 17 -#define OP_BADVERS 18 -#define OP_MSG 19 -#define OP_YOUARE 20 -#define OP_LINESTO 21 -#define OP_WON 22 -#define OP_ZERO 23 - #define MAXNICKLEN 14 struct user @@ -83,20 +51,11 @@ struct user me = /* server stuff */ -#define BUFLEN 4096 - int sfd; -unsigned char realbuf[512], readbuf[BUFLEN], writbuf[BUFLEN]; +unsigned char realbuf[512], readbuf[MAX_BUFFER_SIZE], writbuf[MAX_BUFFER_SIZE]; unsigned char *buf = realbuf + 4; int nread = 0, nwrite = 0; -/* like memcpy, but guaranteed to handle overlap when s <= t */ -void copydown(char *s, char *t, int n) -{ - for (; n; n--) - *(s++) = *(t++); -} - void sysmsg(char *s) { if (verbose) @@ -106,12 +65,6 @@ void sysmsg(char *s) } } -void fatal(char *s) -{ - fprintf(stderr, "%s.\n", s); - exit(1); -} - void *mmalloc(int n) { void *r; @@ -146,7 +99,7 @@ void sendbuf(int len) realbuf[0] = realbuf[1] = realbuf[2] = 0; realbuf[3] = (unsigned char)len; buf[0] = 0; - if (nwrite + 4 + len >= BUFLEN) + if (nwrite + 4 + len >= MAX_BUFFER_SIZE) fatal("Internal error: send buffer overflow"); memcpy(writbuf + nwrite, realbuf, 4 + len); nwrite += 4 + len; @@ -186,42 +139,24 @@ char *get_user_name(unsigned char c) return("no name"); } -void startserver() +void InitNetworkServer(int port) { - char *options[2]; - int n = 0; - - options[0] = options[1] = NULL; - if (verbose) - options[n++] = "-v"; - if (nospeedup) - options[n++] = "-nospeedup"; - switch (fork()) { case 0: - execlp( -#ifdef XTRISPATH - XTRISPATH "/rnd_server", -#else - "rnd_server", -#endif - "rnd_server", "-once", options[0], options[1], NULL); - - fprintf(stderr, "Can't start server '%s'.\n", -#ifdef XTRISPATH - XTRISPATH "/rnd_server" -#else - "rnd_server" -#endif - ); - - _exit(1); - + NetworkServer(port, !serveronly); + + /* never reached */ + exit(0); + case -1: - fatal("fork() failed"); - + Error(ERR_RETURN, + "cannot create network server process - no network games"); + standalone = TRUE; + return; + default: + /* we are parent process -- resume normal operation */ return; } } @@ -262,7 +197,9 @@ BOOL ConnectToServer(char *host, int port) if (!host) { printf("No rocksndiamonds server on localhost - starting up one ...\n"); - startserver(); + + InitNetworkServer(port); + for (i=0; i<6; i++) { u_sleep(500000); @@ -288,7 +225,7 @@ void SendToServer_Nickname(char *nickname) { static char msgbuf[300]; - buf[1] = OP_NICK; + buf[1] = OP_NICKNAME; memcpy(&buf[2], nickname, strlen(nickname)); sendbuf(2 + strlen(nickname)); sprintf(msgbuf, "you set your nick to \"%s\"", nickname); @@ -297,7 +234,7 @@ void SendToServer_Nickname(char *nickname) void SendToServer_ProtocolVersion() { - buf[1] = OP_VERSION; + buf[1] = OP_PROTOCOL_VERSION; buf[2] = PROT_VERS_1; buf[3] = PROT_VERS_2; buf[4] = PROT_VERS_3; @@ -307,7 +244,7 @@ void SendToServer_ProtocolVersion() void SendToServer_NrWanted(int nr_wanted) { - buf[1] = OP_NRWANTED; + buf[1] = OP_NUMBER_WANTED; buf[2] = nr_wanted; sendbuf(3); @@ -317,7 +254,7 @@ void SendToServer_StartPlaying() { unsigned long new_random_seed = InitRND(NEW_RANDOMIZE); - buf[1] = OP_PLAY; + buf[1] = OP_START_PLAYING; buf[2] = (byte)(level_nr >> 8); buf[3] = (byte)(level_nr & 0xff); buf[4] = (byte)(leveldir_nr >> 8); @@ -335,7 +272,7 @@ void SendToServer_StartPlaying() void SendToServer_MovePlayer(byte player_action) { - buf[1] = OP_MOVE; + buf[1] = OP_MOVE_FIGURE; buf[2] = player_action; sendbuf(3); @@ -359,12 +296,12 @@ void handlemessages() switch(buf[1]) { - case OP_YOUARE: + case OP_YOUR_NUMBER: { int new_client_nr = buf[2]; int new_index_nr = new_client_nr - 1; - printf("OP_YOUARE: %d\n", buf[0]); + printf("OP_YOUR_NUMBER: %d\n", buf[0]); me.nr = new_client_nr; stored_player[new_index_nr] = *local_player; @@ -381,13 +318,13 @@ void handlemessages() break; } - case OP_NRWANTED: + case OP_NUMBER_WANTED: { int client_nr_wanted = buf[2]; int new_client_nr = buf[3]; int new_index_nr = new_client_nr - 1; - printf("OP_NRWANTED: %d\n", buf[0]); + printf("OP_NUMBER_WANTED: %d\n", buf[0]); if (new_client_nr != client_nr_wanted) { @@ -420,8 +357,8 @@ void handlemessages() break; } - case OP_NEW: - printf("OP_NEW: %d\n", buf[0]); + case OP_PLAYER_CONNECTED: + printf("OP_PLAYER_CONNECTED: %d\n", buf[0]); sprintf(msgbuf, "new client %d connected", buf[0]); sysmsg(msgbuf); @@ -440,8 +377,8 @@ void handlemessages() break; - case OP_NICK: - printf("OP_NICK: %d\n", buf[0]); + case OP_NICKNAME: + printf("OP_NICKNAME: %d\n", buf[0]); u = finduser(buf[0]); buf[len] = 0; sprintf(msgbuf, "client %d calls itself \"%s\"", buf[0], &buf[2]); @@ -463,20 +400,22 @@ void handlemessages() break; - case OP_BADVERS: + case OP_BAD_PROTOCOL_VERSION: Error(ERR_RETURN, "protocol version mismatch"); Error(ERR_EXIT, "server expects %d.%d.x instead of %d.%d.%d", buf[2], buf[3], PROT_VERS_1, PROT_VERS_2, PROT_VERS_3); break; - case OP_PLAY: + case OP_START_PLAYING: { int new_level_nr, new_leveldir_nr; unsigned long new_random_seed; unsigned char *new_leveldir_name; + /* if (game_status == PLAYING) break; + */ new_level_nr = (buf[2] << 8) + buf[3]; new_leveldir_nr = (buf[4] << 8) + buf[5]; @@ -484,7 +423,7 @@ void handlemessages() (buf[6] << 24) | (buf[7] << 16) | (buf[8] << 8) | (buf[9]); new_leveldir_name = &buf[10]; - printf("OP_PLAY: %d\n", buf[0]); + printf("OP_START_PLAYING: %d\n", buf[0]); sprintf(msgbuf, "client %d starts game [level %d from levedir %d (%s)]\n", buf[0], new_level_nr, @@ -516,10 +455,10 @@ void handlemessages() */ if (tape.recording) - { tape.random_seed = new_random_seed; - InitRND(tape.random_seed); - } + + InitRND(new_random_seed); + /* printf("tape.random_seed == %d\n", tape.random_seed); @@ -531,7 +470,7 @@ void handlemessages() break; } - case OP_MOVE: + case OP_MOVE_FIGURE: { int frame_nr; int i; @@ -635,7 +574,7 @@ void HandleNetworking() { int r; - r = read(sfd, readbuf + nread, BUFLEN - nread); + r = read(sfd, readbuf + nread, MAX_BUFFER_SIZE - nread); if (r < 0) fatal("Error reading from server");