Merge branch 'upstream'

This commit is contained in:
Stefan 2009-08-10 20:44:19 +00:00
commit 1b1d19bec5
10 changed files with 289 additions and 279 deletions

View File

@ -25,7 +25,7 @@ list.o: list.c bomber.h list.h utils.h
menu.o: menu.c announce.h bomber.h draw.h game.h gfx.h list.h menu.h network.h sound.h utils.h menu.o: menu.c announce.h bomber.h draw.h game.h gfx.h list.h menu.h network.h sound.h utils.h
network.o: network.c announce.h bomber.h game.h menu.h network.h utils.h network.o: network.c announce.h bomber.h draw.h game.h menu.h network.h utils.h
sound.o: sound.c sound.h sound.o: sound.c sound.h

View File

@ -166,13 +166,24 @@ typedef struct bonustile {
int type; int type;
} bonustile; } bonustile;
#define TILE_NONE -1 enum tile_types {
#define TILE_BOMB 5 TILE_NONE = -1,
#define TILE_FLAME 2 TILE_DISEASE = 0,
#define TILE_GOLDFLAME 7 TILE_KICK = 1,
#define TILE_CONTROL 9 TILE_FLAME = 2,
#define TILE_SKATES 4 TILE_PUNCH = 3,
#define TILE_TURTLE 14 TILE_SKATES = 4,
TILE_BOMB = 5,
TILE_SPOOGE = 6,
TILE_GOLDFLAME = 7,
TILE_BAD_DISEASE = 8,
TILE_TRIGGER = 9,
TILE_RANDOM = 10,
TILE_JELLY = 11,
TILE_GRAB = 12,
TILE_RANDOM2 = 13,
TILE_TURTLE = 14
};
#define ACT_INVALID 0x88 #define ACT_INVALID 0x88
@ -204,7 +215,7 @@ typedef struct bonustile {
#define MAXTHINGS 500 #define MAXTHINGS 500
#define MAXSETS 8 #define MAXSETS 8
#define MAXSPRITES 128 #define MAXSPRITES 256
#define MAXDAMAGES 512 #define MAXDAMAGES 512
#define MAXBOMBSDETONATED 32 #define MAXBOMBSDETONATED 32

24
draw.c
View File

@ -446,3 +446,27 @@ void loadgfx() {
free(gs); free(gs);
bigscrprintf("Done loading graphics\n"); bigscrprintf("Done loading graphics\n");
} }
void failure(char *str,...) {
char output[256];
va_list ap;
int len;
long now;
va_start(ap, str);
len = vsnprintf(output, sizeof(output), str, ap);
if (len >= 256) len = 255; /* truncated string */
clear();
drawbigstring((IXSIZE - len*bigfontxsize) / 2, (IYSIZE-bigfontysize) / 2, output);
copyup();
now = longtime();
while (!exitflag && longtime()-now < 3) {
scaninput();
if (anydown()) {
takedown();
return;
}
}
}

2
draw.h
View File

@ -21,6 +21,8 @@ int screentoarrayy(int y);
int arraytoscreenx(int x); int arraytoscreenx(int x);
int arraytoscreeny(int y); int arraytoscreeny(int y);
void failure(char *str,...);
extern int bigfontxsize,bigfontysize,bigfontyspace; extern int bigfontxsize,bigfontysize,bigfontyspace;
/* On screen array variables */ /* On screen array variables */

118
game.c
View File

@ -23,8 +23,6 @@ static int detonatetake=0;
static list activeflames; static list activeflames;
static list activeplayers; static list activeplayers;
#define REGISTERLEN (1+4+4+4+16+1)
figure walking[MAXSETS][NUMWALKFRAMES]; figure walking[MAXSETS][NUMWALKFRAMES];
solid background,backgroundoriginal; solid background,backgroundoriginal;
@ -32,19 +30,18 @@ solid background,backgroundoriginal;
unsigned char field[32][32]; unsigned char field[32][32];
void *info[32][32]; void *info[32][32];
int gamemode = 0;
char exitflag = 0; char exitflag = 0;
static int framecount = 0; static int framecount = 0;
char playername[16]; char playername[16];
static int gountil, mycount; static int mycount;
static int bonustotal; static int bonustotal;
static const int bonuschances[]= { static const int bonuschances[]= {
TILE_BOMB,20, TILE_BOMB,20,
TILE_FLAME,20, TILE_FLAME,20,
TILE_CONTROL,2, TILE_TRIGGER,2,
TILE_GOLDFLAME,2, TILE_GOLDFLAME,2,
TILE_SKATES,20, TILE_SKATES,20,
TILE_TURTLE,5, TILE_TURTLE,5,
@ -53,7 +50,7 @@ TILE_NONE,160
static GameOptions gameoptions; static GameOptions gameoptions;
static const unsigned char playerpositions[] = { /* color, x, y */ static const unsigned char playerpositions[MAXNETNODES*3] = { /* color, x, y */
2,0,0, 2,0,0,
3,14,10, 3,14,10,
4,14,0, 4,14,0,
@ -94,7 +91,7 @@ static void initplayers(void) {
const unsigned char *p; const unsigned char *p;
int c,x,y; int c,x,y;
if(!network) { if(NETWORK_NONE == network) {
initplayer(2,0,0,-1); initplayer(2,0,0,-1);
return; return;
} }
@ -109,10 +106,11 @@ static void initplayers(void) {
} }
static void firstzero(void) { static void firstzero(void) {
gountil=mycount=mydatacount=0; mycount = mydatacount = 0;
memset(latestactions,0,sizeof(latestactions)); memset(latestactions,0,sizeof(latestactions));
memset(latestcounts,0,sizeof(latestcounts)); memset(latestcounts,0,sizeof(latestcounts));
actionput=actioncount=0; memset(actionblock,0,sizeof(actionblock));
actioncount = 0;
} }
static void initgame() { static void initgame() {
@ -173,33 +171,6 @@ static void initgame() {
copyup(); copyup();
} }
void run_single_player(void) {
int code;
network=0;
firstzero();
do {
initgame();
while(!(code=iterate())) ++framecount;
} while (code != CODE_QUIT);
gamemode=0;
}
void run_network_game(void) {
int code;
firstzero();
do {
initgame();
while(!(code=iterate())) ++framecount;
} while (code != CODE_QUIT);
network = 0;
gamemode = 0;
}
static void addflame(player *owner,int px,int py) { static void addflame(player *owner,int px,int py) {
flame *fl,*fl2; flame *fl,*fl2;
@ -714,10 +685,10 @@ static void applybonus(player *pl,bonustile *bonus) {
maxflame=arraynumx>arraynumy ? arraynumx : arraynumy; maxflame=arraynumx>arraynumy ? arraynumx : arraynumy;
type=bonus->type; type=bonus->type;
deletebonus(bonus); deletebonus(bonus);
switch(type) switch(type) {
{
case TILE_BOMB: case TILE_BOMB:
++(pl->bombsavailable); if (pl->bombsavailable < 9)
++(pl->bombsavailable);
break; break;
case TILE_FLAME: case TILE_FLAME:
if(pl->flamelength<maxflame) if(pl->flamelength<maxflame)
@ -726,7 +697,7 @@ static void applybonus(player *pl,bonustile *bonus) {
case TILE_GOLDFLAME: case TILE_GOLDFLAME:
pl->flamelength=maxflame; pl->flamelength=maxflame;
break; break;
case TILE_CONTROL: case TILE_TRIGGER:
pl->flags|=FLG_CONTROL; pl->flags|=FLG_CONTROL;
break; break;
case TILE_SKATES: case TILE_SKATES:
@ -863,9 +834,10 @@ static int getaction(void) {
return what; return what;
} }
int iterate(void) { static int iterate(void) {
int i; int i;
static int deathcount=0; int gountil; /* destination tick */
static int deathcount = 0;
mypause(); mypause();
scaninput(); scaninput();
@ -874,22 +846,22 @@ int iterate(void) {
clearspritelist(); clearspritelist();
gfxunlock(); gfxunlock();
myaction=getaction(); myaction = getaction();
if(!network && myaction==ACT_QUIT) return CODE_QUIT; if (NETWORK_NONE == network && myaction==ACT_QUIT) return CODE_QUIT;
i=networktraffic(); if (NETWORK_NONE == network) {
if(i<0) gountil = mycount + 1; /* single step in singly player mode */
gountil=mycount+1; } else {
else gountil = networktraffic(); /* as master single step, as slave as many as we can do */
gountil=i; }
while(mycount<gountil) { while (mycount < gountil) { /* simulate ticks up to gountil */
++mycount; ++mycount;
if(network) { if (NETWORK_NONE != network) {
i=gountil-mycount; i = gountil - mycount;
if(i>=ACTIONHIST) // too far behind if(i >= ACTIONHIST) // too far behind
return CODE_QUIT; goto leave_game;
memcpy(actions,actionblock+i*MAXNETNODES,MAXNETNODES); memcpy(actions, actionblock+i*MAXNETNODES, MAXNETNODES);
if(actions[myslot]==ACT_QUIT) return CODE_QUIT; if (actions[myslot] == ACT_QUIT) return CODE_QUIT;
} }
processbombs(); processbombs();
dodetonations(); dodetonations();
@ -919,16 +891,14 @@ int iterate(void) {
if(!activegeneric.next) { if(!activegeneric.next) {
player *pl; player *pl;
int deadplayers = 0; int deadplayers = 0;
pl=activeplayers.next; i = 0;
i=0; for (pl = activeplayers.next; pl; pl = pl->next) {
while(pl) {
if(!(pl->flags & FLG_DEAD)) if(!(pl->flags & FLG_DEAD))
++i; ++i;
else else
deadplayers++; deadplayers++;
pl=pl->next;
} }
if (deadplayers > 0 && (!i || (network && i==1))) { if (deadplayers > 0 && (!i || (NETWORK_NONE != network && i==1))) {
++deathcount; ++deathcount;
if(deathcount==25) if(deathcount==25)
return CODE_ALLDEAD; return CODE_ALLDEAD;
@ -936,8 +906,34 @@ int iterate(void) {
deathcount=0; deathcount=0;
} }
return CODE_CONT; return CODE_CONT;
leave_game: /* client disconnect/timeout: send ACT_QUIT to master */
myaction = ACT_QUIT;
networktraffic();
return CODE_QUIT;
} }
void set_game_options(GameOptions *options) { void set_game_options(GameOptions *options) {
gameoptions = *options; gameoptions = *options;
} }
void run_single_player(void) {
int code;
network = NETWORK_NONE;
firstzero();
do {
initgame();
while(!(code=iterate()) && !exitflag) ++framecount;
} while (code != CODE_QUIT && !exitflag);
}
void run_network_game(void) {
int code;
firstzero();
do {
initgame();
while (!(code=iterate()) && !exitflag) ++framecount;
} while (code != CODE_QUIT && !exitflag);
}

1
game.h
View File

@ -21,7 +21,6 @@ void run_network_game(void);
void set_game_options(GameOptions *options); void set_game_options(GameOptions *options);
extern char playername[16]; extern char playername[16];
extern int gamemode;
extern solid background,backgroundoriginal; extern solid background,backgroundoriginal;

205
menu.c
View File

@ -118,7 +118,8 @@ static int domenu(menuname whichmenu, int (*pause)(void)) {
} }
} }
} }
return 0; menudelta = 0;
return menuexit;
} }
static void menustart() { static void menustart() {
@ -172,84 +173,13 @@ static void addexit(char *item,...) {
/* game menues */ /* game menues */
static void drawjoinscreen(void) {
int i;
char name[17];
char temp[64];
#define JX (IXSIZE/3)
#define JY (IYSIZE/4)
clear();
centerbig(20,"JOIN NETWORK GAME");
drawbigstring(JX,JY,"SLOT NAME");
for(i=0;i<MAXNETNODES;++i)
{
if(!netnodes[i].used) continue;
memmove(name,netnodes[i].name,16);
name[16]=0;
sprintf(temp," %d %s",i+1,name);
drawbigstring(JX,JY+(i+1)*bigfontyspace,temp);
}
}
static int tryjoin(int which) {
int res;
if (0 == (res = send_join(&gamelistentries[which].netname, playername)))
return 0;
for ( ;; ) {
switch (res) {
case 1: return 0;
case 2:
drawjoinscreen();
copyup();
break;
case 3: return 1;
default: break;
}
scaninput();
while(anydown()) {
switch(takedown()) {
case 0x1b:
send_quit();
return 0;
}
}
res=scaninvite(200);
}
return 0;
}
static void main_menu(void) {
int sel;
while(!exitflag) {
menustart();
additem("BOMBER MAIN MENU");
additem("EXIT GAME");
additem("START SINGLE PLAYER GAME");
additem("OPTIONS");
// additem("REMAP MOVEMENT KEYS");
additem("START NETWORK GAME");
additem("JOIN NETWORK GAME");
sel=domenu(MENU_MAIN, NULL);
if(!sel) {exitflag=1;break;}
if(sel==1) {gamemode=1;break;}
if(sel==2) {gamemode=2;break;}
if(sel==3) {gamemode=3;break;}
if(sel==4) {gamemode=4;break;}
}
}
char *densities[]={"PACKED","HIGH","MEDIUM","LOW"}; char *densities[]={"PACKED","HIGH","MEDIUM","LOW"};
char *generosities[]={"LOW","MEDIUM","HIGH","RIDICULOUS"}; char *generosities[]={"LOW","MEDIUM","HIGH","RIDICULOUS"};
static void config_menu(void) { static void config_menu(void) {
int sel; int sel;
for(;;) { while (!exitflag) {
menustart(); menustart();
additem("GAME OPTIONS"); additem("GAME OPTIONS");
additem("RETURN TO MAIN MENU"); additem("RETURN TO MAIN MENU");
@ -258,30 +188,29 @@ static void config_menu(void) {
additem("INITIAL FLAME LENGTH: %d",configopts.flames+1); additem("INITIAL FLAME LENGTH: %d",configopts.flames+1);
additem("INITIAL NUMBER OF BOMBS: %d",configopts.bombs+1); additem("INITIAL NUMBER OF BOMBS: %d",configopts.bombs+1);
sel=domenu(MENU_CONFIG, NULL); sel=domenu(MENU_CONFIG, NULL);
if(!sel) {gamemode=0;break;} switch (sel) {
if(sel==1) { case 0:
return;
case 1:
configopts.density+=menudelta; configopts.density+=menudelta;
configopts.density&=3; configopts.density&=3;
} break;
if(sel==2) { case 2:
configopts.generosity+=menudelta; configopts.generosity+=menudelta;
configopts.generosity&=3; configopts.generosity&=3;
} break;
if(sel==3) { case 3:
configopts.flames+=menudelta; configopts.flames+=menudelta;
configopts.flames&=7; configopts.flames&=7;
} break;
if(sel==4) { case 4:
configopts.bombs+=menudelta; configopts.bombs+=menudelta;
configopts.bombs&=7; configopts.bombs&=7;
break;
} }
} }
} }
static void failure(char *str,...) {
gamemode=0;
}
static void draw_host_game(void) { static void draw_host_game(void) {
int i; int i;
char *name; char *name;
@ -319,13 +248,12 @@ static void host_game(void) {
case 0x1b: case 0x1b:
unregistergame(); unregistergame();
cancel_network_game(); cancel_network_game();
gamemode=0;
return; return;
case ' ': case ' ':
case 13: case 13:
unregistergame(); unregistergame();
if (begin_network_game()) { if (begin_network_game()) {
gamemode=5; run_network_game();
return; return;
} }
send_invites(); send_invites();
@ -338,8 +266,58 @@ static void host_game(void) {
send_invites(); send_invites();
draw_host_game(); draw_host_game();
} }
}
gamemode=0; static void drawjoinscreen(void) {
int i;
char name[17];
char temp[64];
#define JX (IXSIZE/3)
#define JY (IYSIZE/4)
clear();
centerbig(20,"JOIN NETWORK GAME");
drawbigstring(JX,JY,"SLOT NAME");
for (i = 0; i < MAXNETNODES; ++i) {
if(!netnodes[i].used) continue;
memmove(name,netnodes[i].name,16);
name[16]=0;
sprintf(temp," %d %s",i+1,name);
drawbigstring(JX,JY+(i+1)*bigfontyspace,temp);
}
}
static int tryjoin(int which) {
int res;
if (0 == (res = send_join(&gamelistentries[which].netname, playername))) {
return 0;
}
while (!exitflag) {
switch (res) {
case 1:
failure("Game closed");
return 0;
case 2:
drawjoinscreen();
copyup();
break;
case 3: return 1;
default: break;
}
scaninput();
while(anydown()) {
switch(takedown()) {
case 0x1b:
send_quit();
return 0;
}
}
res=scaninvite(200);
}
return 0;
} }
static int join_game_pause(void) { static int join_game_pause(void) {
@ -353,7 +331,6 @@ static void join_game(void) {
int sel = -1; int sel = -1;
if (!searchgames()) { if (!searchgames()) {
gamemode = 0;
return; return;
} }
@ -372,33 +349,49 @@ static void join_game(void) {
addexit("EXIT"); addexit("EXIT");
} }
sel = domenu(MENU_JOIN, join_game_pause); sel = domenu(MENU_JOIN, join_game_pause);
if (menudelta < 0) sel = -1;
} }
stop_search(); stop_search();
if(menuexit == sel || !gamelistsize) { if(menuexit == sel || !gamelistsize) {
gamemode=0;
return; return;
} }
if(!tryjoin(sel)) { if(!tryjoin(sel)) {
gamemode=0;
return; return;
} }
network = NETWORK_SLAVE; run_network_game();
gamemode=5;
} }
void (*modefunctions[])()= {
main_menu,
run_single_player,
config_menu,
host_game,
join_game,
run_network_game,
};
void mainloop(void) { void mainloop(void) {
exitflag=0; int sel;
while(!exitflag)
modefunctions[gamemode](); exitflag = 0;
while(!exitflag) {
menustart();
additem("BOMBER MAIN MENU");
additem("EXIT GAME");
additem("START SINGLE PLAYER GAME");
additem("OPTIONS");
// additem("REMAP MOVEMENT KEYS");
additem("START NETWORK GAME");
additem("JOIN NETWORK GAME");
sel=domenu(MENU_MAIN, NULL);
if (menudelta < 0) sel = -1;
switch (sel) {
case 0:
return;
case 1:
run_single_player();
break;
case 2:
config_menu();
break;
case 3:
host_game();
break;
case 4:
join_game();
break;
}
}
} }

2
menu.h
View File

@ -3,8 +3,6 @@
void mainloop(void); void mainloop(void);
int iterate(void); /* bomber.c */
extern struct GameOptions configopts; extern struct GameOptions configopts;
#endif #endif

178
network.c
View File

@ -5,13 +5,14 @@
#include "menu.h" #include "menu.h"
#include "network.h" #include "network.h"
#include "utils.h" #include "utils.h"
#include "draw.h"
#define MAXMSG 4096 #define MAXMSG 4096
int udpsocket; int udpsocket;
const unsigned char gameversion[4]={0xda,0x01,0x00,0x05}; const unsigned char gameversion[4]={0xda,0x01,0x00,0x06};
struct netnode netnodes[64]; struct netnode netnodes[MAXNETNODES];
static int informsize; static int informsize;
static unsigned char regpacket[64]; static unsigned char regpacket[64];
@ -26,8 +27,7 @@ int mydatacount;
int myslot; int myslot;
network_type network = NETWORK_NONE; network_type network = NETWORK_NONE;
static unsigned char hist[ACTIONHIST][MAXNETNODES]; int actioncount;
int actionput,actioncount;
unsigned char actionblock[ACTIONHIST*MAXNETNODES]; unsigned char actionblock[ACTIONHIST*MAXNETNODES];
int myaction; int myaction;
@ -52,7 +52,7 @@ enum network_packet_types {
/* slave -> master packets */ /* slave -> master packets */
PKT_MYDATA, /* 4 bytes unique #,4 bytes frame #, 1 byte data */ PKT_MYDATA, /* 4 bytes unique #,4 bytes frame #, 1 byte data */
/* master -> slave packets */ /* master -> slave packets */
PKT_STEP, /* 4 bytes unique #, 4 bytes frame #, 8 bytes ACT_* */ PKT_STEP, /* 4 bytes unique #, 4 bytes frame #, history x MAXNETNODES bytes ACT_* */
PKT_INVALID = 0xff PKT_INVALID = 0xff
}; };
@ -63,6 +63,13 @@ enum reject_reason {
/* TODO: password? */ /* TODO: password? */
}; };
#define _REJECT_LAST REJECT_VERSION
const char *reject_reason_str[] = {
"Server full",
"Version mismatch"
};
/* all bytes stored MSB first */ /* all bytes stored MSB first */
/* /*
@ -246,56 +253,35 @@ static int isvalidmsg_from_master() {
/* Handling game actions */ /* Handling game actions */
static void addactions(void) { static void addactions(void) {
memmove(hist[actionput],actions,MAXNETNODES); memmove(actionblock+MAXNETNODES, actionblock, (ACTIONHIST-1)*MAXNETNODES);
++actionput; memcpy(actionblock, actions, MAXNETNODES);
if(actionput==ACTIONHIST)
actionput=0;
++actioncount; ++actioncount;
} }
static void buildactions(void) {
unsigned char *p;
int i,j;
p=actionblock;
i=0;
while(i<20) {
if(actioncount-i>0) {
j=actionput-i-1;
if(j<0) j+=ACTIONHIST;
memmove(p,hist[j],MAXNETNODES);
} else {
memset(p,0,MAXNETNODES);
}
p+=MAXNETNODES;
++i;
}
}
static void sendactions(int which) { static void sendactions(int which) {
unsigned char msg[512]; unsigned char msg[512];
msg[0] = PKT_STEP; msg[0] = PKT_STEP;
write_unique(msg+1); write_unique(msg + 1);
writeuint32(msg+5, actioncount); writeuint32(msg + 5, actioncount);
memcpy(msg+9,actionblock,MAXNETNODES*ACTIONHIST); memcpy(msg + 9, actionblock, MAXNETNODES*ACTIONHIST);
putmsg(&netnodes[which].netname,msg,MAXNETNODES*ACTIONHIST+9); putmsg(&netnodes[which].netname, msg, MAXNETNODES*ACTIONHIST + 9);
} }
static void sendmine(int frame) { static void sendmine(int frame) {
unsigned char msg[64]; unsigned char msg[64];
msg[0] = PKT_MYDATA; msg[0] = PKT_MYDATA;
write_unique(msg+1); write_unique(msg + 1);
writeuint32(msg+5, frame); writeuint32(msg + 5, frame);
msg[9]=myaction; msg[9] = myaction;
putmsg(&mastername,msg,10); putmsg(&mastername, msg, 10);
} }
int networktraffic(void) { int networktraffic(void) {
int i; int i;
int length; int length;
int whosent; int whosent;
unsigned char newactions[MAXNETNODES];
long now; long now;
long count; long count;
@ -303,70 +289,68 @@ int networktraffic(void) {
case NETWORK_NONE: case NETWORK_NONE:
return -1; return -1;
case NETWORK_MASTER: case NETWORK_MASTER:
memcpy(newactions,latestactions,MAXNETNODES); memcpy(actions,latestactions,MAXNETNODES);
newactions[0]=myaction; actions[0]=myaction;
now=gtime(); if (myaction == ACT_QUIT) {
for(;;) { for (i = 1; i < MAXNETNODES; ++i) {
if(gtime()-now>15) break; if (netnodes[i].used)
length=getmsg(5); actions[i]=ACT_QUIT;
if(length>0 && *mesg!=PKT_MYDATA) fprintf(stderr, "Strange packet %d\n", (int) *mesg); }
// check for unexpected old packets... } else {
// for example JOIN on frame 0, respond with BEGIN if player already in game now=gtime();
// respond with uninvite INVITE on JOIN from others for(;;) {
if(length<10) continue; if(gtime()-now>15) break;
whosent = isvalidmsg_from_slave(); length=getmsg(5);
if(whosent<=0) continue; if(length>0 && *mesg!=PKT_MYDATA) fprintf(stderr, "Strange packet %d\n", (int) *mesg);
count=readuint32(mesg+5); /* check for unexpected old packets...
if(count>latestcounts[whosent]) { * for example JOIN on frame 0, respond with BEGIN if player already in game
latestcounts[whosent]=count; * respond with uninvite INVITE on JOIN from others
newactions[whosent]=mesg[9]; */
if (length < 10) continue;
whosent = isvalidmsg_from_slave();
if (whosent <= 0) continue;
count = readuint32(mesg+5);
if (count > latestcounts[whosent]) {
latestcounts[whosent] = count;
actions[whosent] = mesg[9];
}
} }
} }
if(myaction==ACT_QUIT) {
for(i=1;i<MAXNETNODES;++i)
if(netnodes[i].used)
newactions[i]=ACT_QUIT;
}
memmove(actions,newactions,sizeof(actions)); addactions(); /* update action history block */
addactions();
buildactions(); for (i = 1; i < MAXNETNODES; ++i) {
for(i=1;i<MAXNETNODES;++i) if(netnodes[i].used) {
if(netnodes[i].used) sendactions(i); /* send actions to every active node */
sendactions(i); if (actions[i]==ACT_QUIT)
for(i=1;i<MAXNETNODES;++i) netnodes[i].used=0; /* remove disconnected clients */
if(netnodes[i].used && actions[i]==ACT_QUIT) }
netnodes[i].used=0; }
return actioncount; return actioncount;
case NETWORK_SLAVE: case NETWORK_SLAVE:
{ count = -1; /* set to actioncount if we got at least one packet */
long latest=-1; now = gtime();
long lastsent;
lastsent=now=gtime(); ++mydatacount;
++mydatacount; sendmine(mydatacount);
sendmine(mydatacount);
for(;;) { for(;;) {
/* /* if we got already one packet we only wait 3msec, otherwise 30msec */
if(gtime()-lastsent>=1) long cur = gtime();
{ if (count >= 0 && cur - now > 3) break;
lastsent=gtime(); if (exitflag || cur - now > 30) break;
sendmine(mydatacount);
} length = getmsg(count >= 0 ? 3 : 20);
*/
if(latest>=0 && gtime()-now>3) break; if (MAXNETNODES*ACTIONHIST+9 != length) continue;
length=getmsg(3); if (!isvalidmsg_from_master()) continue;
if(length==MAXNETNODES*ACTIONHIST+9 &&
sender.sin_addr.s_addr==mastername.sin_addr.s_addr && i = readuint32(mesg+5);
sender.sin_port==mastername.sin_port) { if (i < actioncount) continue;
i=readuint32(mesg+5); count = actioncount = i;
if(i<latest) continue; memcpy(actionblock,mesg+9,MAXNETNODES*ACTIONHIST);
latest=i;
memmove(actionblock,mesg+9,MAXNETNODES*ACTIONHIST);
}
}
return latest;
} }
return actioncount;
} }
return -1; return -1;
} }
@ -671,6 +655,7 @@ int scaninvite(int msec) {
} }
if (*mesg == PKT_BEGIN) { if (*mesg == PKT_BEGIN) {
network = NETWORK_SLAVE;
return 3; return 3;
} else { } else {
return 2; return 2;
@ -708,12 +693,17 @@ int send_join(struct sockaddr_in *netname, char playername[16]) {
if (!read_inform(&buf,&size)) return 0; if (!read_inform(&buf,&size)) return 0;
return 2; return 2;
case PKT_REJECT: case PKT_REJECT:
/* TODO: print reject message */ if (size < 10 || mesg[9] > _REJECT_LAST) {
failure("Couldn't connect");
} else {
failure("Couldn't connect: %s", reject_reason_str[mesg[9]]);
}
return 0; return 0;
default: default:
break; break;
} }
} }
failure("Could not connect - Timeout");
return 0; return 0;
} }

View File

@ -5,13 +5,15 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#define MAXNETNODES 8
struct netnode { struct netnode {
struct sockaddr_in netname; struct sockaddr_in netname;
char name[16]; char name[16];
char used; char used;
}; };
extern struct netnode netnodes[64]; extern struct netnode netnodes[MAXNETNODES];
void getsocket(void); void getsocket(void);
void freesocket(void); void freesocket(void);
@ -27,11 +29,6 @@ int begin_network_game();
void send_invites(); void send_invites();
void cancel_network_game(); void cancel_network_game();
#define MAXNETNODES 10
extern struct netnode netnodes[64];
extern int udpsocket;
extern const unsigned char gameversion[4]; extern const unsigned char gameversion[4];
typedef enum { NETWORK_NONE = 0, NETWORK_MASTER, NETWORK_SLAVE } network_type; typedef enum { NETWORK_NONE = 0, NETWORK_MASTER, NETWORK_SLAVE } network_type;