diff --git a/polymer/eduke32/Makefile b/polymer/eduke32/Makefile index 6bcd0a07b..7b639c8ca 100644 --- a/polymer/eduke32/Makefile +++ b/polymer/eduke32/Makefile @@ -248,11 +248,7 @@ endif # TARGETS -ifeq ($(PLATFORM),WINDOWS) -all: notice eduke32$(EXESUFFIX) mapster32$(EXESUFFIX) duke3d_w32$(EXESUFFIX) -else all: notice eduke32$(EXESUFFIX) mapster32$(EXESUFFIX) -endif all: $(BUILD_FINISHED) diff --git a/polymer/eduke32/Makefile.deps b/polymer/eduke32/Makefile.deps index 8f0c87d22..8656e6ab4 100644 --- a/polymer/eduke32/Makefile.deps +++ b/polymer/eduke32/Makefile.deps @@ -1,7 +1,7 @@ duke3d_h=$(EINC)/build.h $(EINC)/polymer.h $(EINC)/pragmas.h $(EINC)/compat.h $(EINC)/cache1d.h $(EINC)/baselayer.h $(SRC)/jmact/types.h $(SRC)/jmact/file_lib.h $(SRC)/jmact/util_lib.h $(SRC)/jmact/keyboard.h $(SRC)/jmact/control.h $(INC)/gamedefs.h $(INC)/function.h $(INC)/config.h $(INC)/sounds.h $(INC)/rts.h $(INC)/_rts.h $(INC)/soundefs.h $(SRC)/jaudiolib/fx_man.h $(SRC)/jaudiolib/music.h $(INC)/namesdyn.h $(INC)/funct.h $(INC)/duke3d.h gamedef_h=$(SRC)/gamedef.h -$(OBJ)/game.$o: $(SRC)/game.c $(SRC)/jmact/scriplib.h $(duke3d_h) $(INC)/osdfuncs.h $(INC)/osdcmds.h $(INC)/grpscan.h +$(OBJ)/game.$o: $(SRC)/game.c $(SRC)/sync.c $(SRC)/jmact/scriplib.h $(duke3d_h) $(INC)/osdfuncs.h $(INC)/osdcmds.h $(INC)/grpscan.h $(OBJ)/actors.$o: $(SRC)/actors.c $(duke3d_h) $(OBJ)/anim.$o: $(SRC)/anim.c $(duke3d_h) $(SRC)/jmact/animlib.h $(OBJ)/gamedef.$o: $(SRC)/gamedef.c $(duke3d_h) $(gamedef_h) diff --git a/polymer/eduke32/build/src/mmulti_unstable.c b/polymer/eduke32/build/src/mmulti_unstable.c index 1dd8e4b41..557376af1 100644 --- a/polymer/eduke32/build/src/mmulti_unstable.c +++ b/polymer/eduke32/build/src/mmulti_unstable.c @@ -75,16 +75,16 @@ char syncstate = 0; #define MAXPACKETSIZE 2048 typedef struct { - short intnum; /* communication between Game and the driver */ +// short intnum; /* communication between Game and the driver */ short command; /* 1-send, 2-get */ short other; /* dest for send, set by get (-1 = no packet) */ short numbytes; short myconnectindex; short numplayers; - short gametype; /* gametype: 1-serial,2-modem,3-net */ +// short gametype; /* gametype: 1-serial,2-modem,3-net */ short filler; char buffer[MAXPACKETSIZE]; - intptr_t longcalladdress; +// intptr_t longcalladdress; } gcomtype; static gcomtype *gcom; @@ -622,7 +622,6 @@ void genericmultifunction(int other, char *bufptr, int messleng, int command) #define IPSEG3(ip) ((((unsigned int) ip) & 0x0000FF00) >> 8) #define IPSEG4(ip) ((((unsigned int) ip) & 0x000000FF) ) -#define MAX_PLAYERS 16 #define BUILD_DEFAULT_UDP_PORT 23513 /* eh...why not? */ #define CLIENT_POLL_DELAY 5000 /* ms between pings at peer-to-peer startup. */ #define HEADER_PEER_GREETING 245 @@ -634,7 +633,7 @@ static struct { int host; unsigned short port; -} allowed_addresses[MAX_PLAYERS]; /* only respond to these IPs. */ +} allowed_addresses[MAXPLAYERS]; /* only respond to these IPs. */ #if PLATFORM_WIN32 /* @@ -1025,7 +1024,7 @@ static int wait_for_other_players(gcomtype *gcom, int myip) int rc; int ip; unsigned short port; - unsigned short heard_from[MAX_PLAYERS]; + unsigned short heard_from[MAXPLAYERS]; int max; int remaining; @@ -1207,7 +1206,7 @@ static int connect_to_server(gcomtype *gcom, int myip) int ip; unsigned short port; int first_send = 1; - unsigned short heard_from[MAX_PLAYERS]; + unsigned short heard_from[MAXPLAYERS]; unsigned int resendat; int max; int remaining; @@ -1282,7 +1281,7 @@ static int connect_to_server(gcomtype *gcom, int myip) continue; } - for (i=0;i MAX_PLAYERS - 1) + if (bcast > MAXPLAYERS - 1) { initprintf("WARNING: Too many broadcast players.\n"); - bcast = MAX_PLAYERS - 1; + bcast = MAXPLAYERS - 1; } bogus = 0; @@ -1949,7 +1948,7 @@ static int parse_udp_config(int argc, char **argv, gcomtype *gcom) unsigned short port=BUILD_DEFAULT_UDP_PORT; if ((tok = get_token(&ptr)) != NULL) { - if (gcom->numplayers >= MAX_PLAYERS - 1) + if (gcom->numplayers >= MAXPLAYERS - 1) initprintf("WARNING: Too many allowed IP addresses.\n"); else if (parse_interface(tok, &host, &port)) @@ -2030,7 +2029,7 @@ gcomtype *init_network_transport(int argc, char **argv) deinit_network_transport(NULL); return(NULL); } - retval->gametype = 3; /* gametype: 1-serial,2-modem,3-net */ +// retval->gametype = 3; /* gametype: 1-serial,2-modem,3-net */ } return(retval); diff --git a/polymer/eduke32/source/duke3d.h b/polymer/eduke32/source/duke3d.h index 8837bd3aa..330b4bbea 100644 --- a/polymer/eduke32/source/duke3d.h +++ b/polymer/eduke32/source/duke3d.h @@ -687,7 +687,13 @@ extern int gamequit; extern char pus,pub; extern int camerashitable,freezerhurtowner,lasermode; -extern char syncstat; + +// TENSW: on really bad network connections, the sync FIFO queue can overflow if it is the +// same size as the move fifo. +#define MAXSYNCBYTES 16 +#define SYNCFIFOSIZ 1024 + +extern char syncstat[MAXSYNCBYTES]; extern signed char multiwho, multipos, multiwhat, multiflag; extern int syncvaltail, syncvaltottail; extern int numfreezebounces,rpgblastradius,pipebombblastradius,tripbombblastradius,shrinkerblastradius,morterblastradius,bouncemineblastradius,seenineblastradius; @@ -706,6 +712,8 @@ extern int stereomode, stereowidth, stereopixelwidth; extern int myaimmode, myaimstat, omyaimstat; +extern unsigned int MoveThingsCount; + #define IFISGLMODE if (getrendermode() >= 3) #define IFISSOFTMODE if (getrendermode() < 3) @@ -1055,7 +1063,8 @@ typedef struct { int32 pcolor, pteam, frags[MAXPLAYERS], wchoice[MAX_WEAPONS]; char vote, gotvote, playerreadyflag, playerquitflag; - char user_name[32], syncval[MOVEFIFOSIZ]; + char user_name[32]; + char syncval[SYNCFIFOSIZ][MAXSYNCBYTES]; } playerdata_t; extern input_t inputfifo[MOVEFIFOSIZ][MAXPLAYERS]; diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index dbff03c28..a4e9b04c2 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -647,11 +647,14 @@ void adduserquote(const char *daquote) int lastpackettime = 0; +#include "sync.c" + void getpackets(void) { int i, j, k, l; int other; int packbufleng; + int sb; input_t *osyn, *nsyn; @@ -752,25 +755,44 @@ void getpackets(void) g_player[i].movefifoend++; } + /* while (j != packbufleng) + { + for (i=connecthead;i>=0;i=connectpoint2[i]) + if (i != myconnectindex) + { + g_player[i].syncval[g_player[i].syncvalhead&(MOVEFIFOSIZ-1)] = packbuf[j]; + g_player[i].syncvalhead++; + } + j++; + } */ while (j != packbufleng) { - for (i=connecthead;i>=0;i=connectpoint2[i]) + for (i = connecthead; i >= 0; i = connectpoint2[i]) + { if (i != myconnectindex) { - g_player[i].syncval[g_player[i].syncvalhead&(MOVEFIFOSIZ-1)] = packbuf[j]; + for (sb = 0; sb < NumSyncBytes; sb++) + { + g_player[i].syncval[g_player[i].syncvalhead & (SYNCFIFOSIZ - 1)][sb] = packbuf[j + sb]; + } + g_player[i].syncvalhead++; } - j++; + } + + j += NumSyncBytes; } - for (i=connecthead;i>=0;i=connectpoint2[i]) - if (i != myconnectindex) - for (j=movesperpacket-1;j>=1;j--) - { - copybufbyte(&nsyn[i],&inputfifo[g_player[i].movefifoend&(MOVEFIFOSIZ-1)][i],sizeof(input_t)); - g_player[i].movefifoend++; - } + GetSyncInfoFromPacket(packbuf, packbufleng, &j, other); + /* for (i=connecthead;i>=0;i=connectpoint2[i]) + if (i != myconnectindex) + for (j=movesperpacket-1;j>=1;j--) + { + copybufbyte(&nsyn[i],&inputfifo[g_player[i].movefifoend&(MOVEFIFOSIZ-1)][i],sizeof(input_t)); + g_player[i].movefifoend++; + } + */ movefifosendplc += movesperpacket; break; @@ -797,11 +819,12 @@ void getpackets(void) if (k&2048) nsyn[other].extbits = ((nsyn[other].extbits&0x00ffffff)|((int)packbuf[j++])<<24); */ g_player[other].movefifoend++; - while (j != packbufleng) - { - g_player[other].syncval[g_player[other].syncvalhead&(MOVEFIFOSIZ-1)] = packbuf[j++]; - g_player[other].syncvalhead++; - } + /* while (j != packbufleng) + { + g_player[other].syncval[g_player[other].syncvalhead&(MOVEFIFOSIZ-1)] = packbuf[j++]; + g_player[other].syncvalhead++; + } */ + GetSyncInfoFromPacket(packbuf, packbufleng, &j, other); for (i=movesperpacket-1;i>=1;i--) { @@ -856,12 +879,14 @@ void getpackets(void) if (j > packbufleng) initprintf("INVALID GAME PACKET!!! (packet %d, %d too many bytes (%d %d))\n",packbuf[0],j-packbufleng,packbufleng,k); - - while (j < packbufleng) - { - g_player[other].syncval[g_player[other].syncvalhead&(MOVEFIFOSIZ-1)] = packbuf[j++]; - g_player[other].syncvalhead++; - } + /* + while (j < packbufleng) + { + g_player[other].syncval[g_player[other].syncvalhead&(MOVEFIFOSIZ-1)] = packbuf[j++]; + g_player[other].syncvalhead++; + } + */ + GetSyncInfoFromPacket(packbuf, packbufleng, &j, other); break; case 127: @@ -871,7 +896,7 @@ void getpackets(void) if (g_player[other].playerreadyflag == 0) initprintf("Player %d is ready\n", other); g_player[other].playerreadyflag++; - break; + return; case 255: gameexit(" "); break; @@ -1170,9 +1195,12 @@ void faketimerhandler(void) getpackets(); if (getoutputcirclesize() >= 16) return; - for (i=connecthead;i>=0;i=connectpoint2[i]) - if (i != myconnectindex) - if (g_player[i].movefifoend < g_player[myconnectindex].movefifoend-200) return; +// for (i=connecthead;i>=0;i=connectpoint2[i]) +// if (i != myconnectindex) +// if (g_player[i].movefifoend < g_player[myconnectindex].movefifoend-200) return; + + if (g_player[myconnectindex].movefifoend - movefifoplc >= 100) + return; getinput(myconnectindex); @@ -1222,12 +1250,14 @@ void faketimerhandler(void) mymaxlag = max(mymaxlag,k); } - if (((g_player[myconnectindex].movefifoend-1)&(TIMERUPDATESIZ-1)) == 0) + if (((g_player[myconnectindex].movefifoend - 1) & (TIMERUPDATESIZ - 1)) == 0) { - i = mymaxlag-bufferjitter; + i = mymaxlag - bufferjitter; mymaxlag = 0; - if (i > 0) bufferjitter += ((3+i)>>2); - else if (i < 0) bufferjitter -= ((1-i)>>2); + if (i > 0) + bufferjitter += ((2 + i) >> 2); + else if (i < 0) + bufferjitter -= ((2 - i) >> 2); } if (networkmode == 1) @@ -1239,23 +1269,38 @@ void faketimerhandler(void) //Fix timers and buffer/jitter value if (((g_player[myconnectindex].movefifoend-1)&(TIMERUPDATESIZ-1)) == 0) { - if (myconnectindex != connecthead) + if (myconnectindex == connecthead) { - i = g_player[connecthead].myminlag-otherminlag; - if (klabs(i) > 8) i >>= 1; - else if (klabs(i) > 2) i = ksgn(i); - else i = 0; + for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i]) + packbuf[j++] = min(max(g_player[i].myminlag, -128), 127); + } + else + { + i = g_player[connecthead].myminlag - otherminlag; + if (klabs(i) > 2) + { + ////DSPRINTF(ds,"lag correction: %d,%d,%d",i,Player[connecthead].myminlag,otherminlag); + //MONO_PRINT(ds); - totalclock -= TICSPERFRAME*i; - g_player[connecthead].myminlag -= i; - otherminlag += i; + if (klabs(i) > 8) + { + if (i < 0) + i++; + i >>= 1; + } + else + { + if (i < 0) + i = -1; + if (i > 0) + i = 1; + } + totalclock -= TICSPERFRAME * i; + otherminlag += i; + } } - if (myconnectindex == connecthead) - for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) - packbuf[j++] = min(max(g_player[i].myminlag,-128),127); - - for (i=connecthead;i>=0;i=connectpoint2[i]) + for (i = connecthead; i >= 0; i = connectpoint2[i]) g_player[i].myminlag = 0x7fffffff; } @@ -1300,11 +1345,13 @@ void faketimerhandler(void) if ((nsyn[0].extbits^osyn[0].extbits)&0x00ff0000) packbuf[j++] = ((nsyn[0].extbits>>16)&255), packbuf[k] |= 4; if ((nsyn[0].extbits^osyn[0].extbits)&0xff000000) packbuf[j++] = ((nsyn[0].extbits>>24)&255), packbuf[k] |= 8; */ - while (g_player[myconnectindex].syncvalhead != syncvaltail) - { - packbuf[j++] = g_player[myconnectindex].syncval[syncvaltail&(MOVEFIFOSIZ-1)]; - syncvaltail++; - } + /* while (g_player[myconnectindex].syncvalhead != syncvaltail) + { + packbuf[j++] = g_player[myconnectindex].syncval[syncvaltail&(MOVEFIFOSIZ-1)]; + syncvaltail++; + } */ + + AddSyncInfoToPacket(&j); for (i=connecthead;i>=0;i=connectpoint2[i]) if (i != myconnectindex) @@ -1317,17 +1364,30 @@ void faketimerhandler(void) //Fix timers and buffer/jitter value if (((g_player[myconnectindex].movefifoend-1)&(TIMERUPDATESIZ-1)) == 0) { - i = g_player[connecthead].myminlag-otherminlag; - if (klabs(i) > 8) i >>= 1; - else if (klabs(i) > 2) i = ksgn(i); - else i = 0; + i = g_player[connecthead].myminlag - otherminlag; + if (klabs(i) > 2) + { + if (klabs(i) > 8) + { + if (i < 0) + i++; + i >>= 1; + } + else + { + if (i < 0) + i = -1; + if (i > 0) + i = 1; + } + totalclock -= TICSPERFRAME * i; + otherminlag += i; + } - totalclock -= TICSPERFRAME*i; - g_player[connecthead].myminlag -= i; - otherminlag += i; - - for (i=connecthead;i>=0;i=connectpoint2[i]) + for (i = connecthead; i >= 0; i = connectpoint2[i]) + { g_player[i].myminlag = 0x7fffffff; + } } packbuf[0] = 1; @@ -1371,11 +1431,12 @@ void faketimerhandler(void) if ((nsyn[0].extbits^osyn[0].extbits)&0x00ff0000) packbuf[j++] = ((nsyn[0].extbits>>16)&255), packbuf[2] |= 4; if ((nsyn[0].extbits^osyn[0].extbits)&0xff000000) packbuf[j++] = ((nsyn[0].extbits>>24)&255), packbuf[2] |= 8; */ - while (g_player[myconnectindex].syncvalhead != syncvaltail) - { - packbuf[j++] = g_player[myconnectindex].syncval[syncvaltail&(MOVEFIFOSIZ-1)]; - syncvaltail++; - } + /* while (g_player[myconnectindex].syncvalhead != syncvaltail) + { + packbuf[j++] = g_player[myconnectindex].syncval[syncvaltail&(MOVEFIFOSIZ-1)]; + syncvaltail++; + } */ + AddSyncInfoToPacket(&j); sendpacket(connecthead,packbuf,j); return; @@ -1459,11 +1520,12 @@ void faketimerhandler(void) k++; } - while (g_player[myconnectindex].syncvalhead != syncvaltail) - { - packbuf[j++] = g_player[myconnectindex].syncval[syncvaltail&(MOVEFIFOSIZ-1)]; - syncvaltail++; - } + /* while (g_player[myconnectindex].syncvalhead != syncvaltail) + { + packbuf[j++] = g_player[myconnectindex].syncval[syncvaltail&(MOVEFIFOSIZ-1)]; + syncvaltail++; + } */ + AddSyncInfoToPacket(&j); for (i=connectpoint2[connecthead];i>=0;i=connectpoint2[i]) if (g_player[i].playerquitflag) @@ -1509,7 +1571,7 @@ static void caches(void) k += 6; } } - +/* static void checksync(void) { int i; @@ -1547,7 +1609,7 @@ static void checksync(void) } #endif } - +*/ void check_fta_sounds(int i) { if (sprite[i].extra > 0) @@ -3862,7 +3924,8 @@ void displayrest(int smoothratio) if (ud.overhead_on > 0) { - smoothratio = min(max(smoothratio,0),65536); + // smoothratio = min(max(smoothratio,0),65536); + smoothratio = min(max((totalclock - ototalclock) * (65536 / TICSPERFRAME),0),65536); dointerpolations(smoothratio); if (ud.scrollmode == 0) { @@ -4170,9 +4233,9 @@ void drawbackground(void) //if (ud.recstat == 0 || ud.recstat == 1 || (ud.recstat == 2 && ud.reccnt > 0)) // JBF 20040717 { // if (ud.screen_size == 8 && ud.statusbarmode == 0) - // y1 = scale(ydim,200-scale(tilesizy[BOTTOMSTATUSBAR],ud.statusbarscale,100),200); + // y1 = scale(ydim,200-scale(tilesizy[BOTTOMSTATUSBAR],ud.statusbarscale,100),200); //else - if (gametype_flags[ud.coop] & GAMETYPE_FLAG_FRAGBAR) + if (gametype_flags[ud.coop] & GAMETYPE_FLAG_FRAGBAR) { if (ud.multimode > 1) y1 += scale(ydim,8,200); if (ud.multimode > 4) y1 += scale(ydim,8,200); @@ -4235,12 +4298,12 @@ void drawbackground(void) */ // when not rendering a game, fullscreen wipe x2 = (xdim - scale(xdim,ud.statusbarscale,100)) >> 1; - for (y=y2-y2%tilesizy[dapicnum];y>1;x+=tilesizx[dapicnum]) - { - rotatesprite(x<<16,y<<16,65536L,0,dapicnum,8,0,8+16+64,0,y2,x2,ydim-1); - rotatesprite((xdim-x)<<16,y<<16,65536L,0,dapicnum,8,0,8+16+64,xdim-x2-1,y2,xdim-1,ydim-1); - } + for (y=y2-y2%tilesizy[dapicnum];y>1;x+=tilesizx[dapicnum]) + { + rotatesprite(x<<16,y<<16,65536L,0,dapicnum,8,0,8+16+64,0,y2,x2,ydim-1); + rotatesprite((xdim-x)<<16,y<<16,65536L,0,dapicnum,8,0,8+16+64,xdim-x2-1,y2,xdim-1,ydim-1); + } } @@ -4482,7 +4545,8 @@ void displayrooms(int snum,int smoothratio) if (ud.overhead_on == 2 || ud.show_help || (p->cursectnum == -1 && getrendermode() < 3)) return; - smoothratio = min(max(smoothratio,0),65536); +// smoothratio = min(max(smoothratio,0),65536); + smoothratio = min(max((totalclock - ototalclock) * (65536 / TICSPERFRAME),0),65536); visibility = (int)(p->visibility*(numplayers>1?1.f:r_ambientlightrecip)); @@ -10186,21 +10250,21 @@ static void Logo(void) KB_ClearKeysDown(); // JBF MOUSE_ClearButton(LEFT_MOUSE); } -/* - if (ud.multimode > 1) - { - setgamepalette(g_player[myconnectindex].ps, titlepal, 11); - rotatesprite(0,0,65536L,0,BETASCREEN,0,0,2+8+16+64,0,0,xdim-1,ydim-1); + /* + if (ud.multimode > 1) + { + setgamepalette(g_player[myconnectindex].ps, titlepal, 11); + rotatesprite(0,0,65536L,0,BETASCREEN,0,0,2+8+16+64,0,0,xdim-1,ydim-1); - rotatesprite(160<<16,(104)<<16,60<<10,0,DUKENUKEM,0,0,2+8,0,0,xdim-1,ydim-1); - rotatesprite(160<<16,(129)<<16,30<<11,0,THREEDEE,0,0,2+8,0,0,xdim-1,ydim-1); - if (PLUTOPAK) // JBF 20030804 - rotatesprite(160<<16,(151)<<16,30<<11,0,PLUTOPAKSPRITE+1,0,0,2+8,0,0,xdim-1,ydim-1); + rotatesprite(160<<16,(104)<<16,60<<10,0,DUKENUKEM,0,0,2+8,0,0,xdim-1,ydim-1); + rotatesprite(160<<16,(129)<<16,30<<11,0,THREEDEE,0,0,2+8,0,0,xdim-1,ydim-1); + if (PLUTOPAK) // JBF 20030804 + rotatesprite(160<<16,(151)<<16,30<<11,0,PLUTOPAKSPRITE+1,0,0,2+8,0,0,xdim-1,ydim-1); - gametext(160,190,"WAITING FOR PLAYERS",14,2); - nextpage(); - } -*/ + gametext(160,190,"WAITING FOR PLAYERS",14,2); + nextpage(); + } + */ waitforeverybody(); flushperms(); @@ -10903,6 +10967,8 @@ void app_main(int argc,const char **argv) ud.multimode = 1; + initsynccrc(); + checkcommandline(argc,argv); #ifdef RENDERTYPEWIN @@ -11591,7 +11657,8 @@ MAIN_LOOP_RESTART: if (debug_on) caches(); - checksync(); +// checksync(); + SyncStatMessage(); if (VOLUMEONE) { @@ -12500,7 +12567,7 @@ ENDFAKEPROCESSINPUT: static int domovethings(void) { int i, j; - char ch; +// char ch; for (i=connecthead;i>=0;i=connectpoint2[i]) if (g_player[i].sync->bits&(1<<17)) @@ -12670,15 +12737,20 @@ static int domovethings(void) if (j < 0 && networkmode == 0) gameexit("Server terminated"); } + /* + if ((numplayers >= 2) && ((movefifoplc&7) == 7)) + { + ch = (char)(randomseed&255); + for (i=connecthead;i>=0;i=connectpoint2[i]) + ch += ((g_player[i].ps->posx+g_player[i].ps->posy+g_player[i].ps->posz+g_player[i].ps->ang+g_player[i].ps->horiz)&255); + g_player[myconnectindex].syncval[g_player[myconnectindex].syncvalhead&(MOVEFIFOSIZ-1)] = ch; + g_player[myconnectindex].syncvalhead++; + } + */ - if ((numplayers >= 2) && ((movefifoplc&7) == 7)) - { - ch = (char)(randomseed&255); - for (i=connecthead;i>=0;i=connectpoint2[i]) - ch += ((g_player[i].ps->posx+g_player[i].ps->posy+g_player[i].ps->posz+g_player[i].ps->ang+g_player[i].ps->horiz)&255); - g_player[myconnectindex].syncval[g_player[myconnectindex].syncvalhead&(MOVEFIFOSIZ-1)] = ch; - g_player[myconnectindex].syncvalhead++; - } + getsyncstat(); + + MoveThingsCount++; if (ud.recstat == 1) record(); diff --git a/polymer/eduke32/source/gameexec.c b/polymer/eduke32/source/gameexec.c index 0f064805e..60c9029ec 100644 --- a/polymer/eduke32/source/gameexec.c +++ b/polymer/eduke32/source/gameexec.c @@ -2088,7 +2088,7 @@ static int parse(void) int y1=scale(GetGameVarID(*insptr++,g_i,g_p),ydim,200); int x2=scale(GetGameVarID(*insptr++,g_i,g_p),xdim,320); int y2=scale(GetGameVarID(*insptr++,g_i,g_p),ydim,200); - int smoothratio = 65536; + int smoothratio = min(max((totalclock - ototalclock) * (65536 / TICSPERFRAME),0),65536); if (x1 > x2) swaplong(&x1,&x2); if (y1 > y2) swaplong(&y1,&y2); diff --git a/polymer/eduke32/source/global.c b/polymer/eduke32/source/global.c index bc0da1ac4..5294de007 100644 --- a/polymer/eduke32/source/global.c +++ b/polymer/eduke32/source/global.c @@ -87,7 +87,7 @@ playerspawn_t g_PlayerSpawnPoints[MAXPLAYERS]; user_defs ud; char pus, pub; -char syncstat; +char syncstat[MAXSYNCBYTES]; int syncvaltail, syncvaltottail; input_t loc; @@ -181,4 +181,5 @@ char setupfilename[BMAX_PATH]= "duke3d.cfg"; // char datetimestring[] = ""__DATE__" "__TIME__""; int doquicksave = 0; +unsigned int MoveThingsCount = 0; diff --git a/polymer/eduke32/source/premap.c b/polymer/eduke32/source/premap.c index c9c42259c..190770952 100644 --- a/polymer/eduke32/source/premap.c +++ b/polymer/eduke32/source/premap.c @@ -1503,6 +1503,7 @@ void resettimevars(void) lockclock = 0L; ready2send = 1; leveltexttime = 85; + MoveThingsCount = 0; } void waitforeverybody() @@ -1580,7 +1581,7 @@ void clearfifo(void) syncvaltail = 0L; syncvaltottail = 0L; - syncstat = 0; + memset(&syncstat, 0, sizeof(syncstat)); bufferjitter = 1; mymaxlag = otherminlag = 0; jump_input = 0; diff --git a/polymer/eduke32/source/sync.c b/polymer/eduke32/source/sync.c new file mode 100644 index 000000000..a79ca46d6 --- /dev/null +++ b/polymer/eduke32/source/sync.c @@ -0,0 +1,463 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior 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; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +int NumSyncBytes = 1; +char sync_first[MAXSYNCBYTES][60]; +int sync_found = 0; + +static int crctable[256]; +#define updatecrc(dcrc,xz) (dcrc = (crctable[((dcrc)>>8)^((xz)&255)]^((dcrc)<<8))) + +void initsynccrc(void) +{ + int i, j, k, a; + + for (j=0;j<256;j++) //Calculate CRC table + { + k = (j<<8); a = 0; + for (i=7;i>=0;i--) + { + if (((k^a)&0x8000) > 0) + a = ((a<<1)&65535) ^ 0x1021; //0x1021 = genpoly + else + a = ((a<<1)&65535); + k = ((k<<1)&65535); + } + crctable[j] = (a&65535); + } +} + +char PlayerSync(void) +{ + short i; + unsigned short crc = 0; + player_struct *pp; + + for (i = connecthead; i >= 0; i = connectpoint2[i]) + { + pp = g_player[i].ps; + updatecrc(crc, pp->posx & 255); + updatecrc(crc, pp->posy & 255); + updatecrc(crc, pp->posz & 255); + updatecrc(crc, pp->ang & 255); + } + + return ((char) crc & 255); +} + +char PlayerSync2(void) +{ + short i; + unsigned short crc = 0; + player_struct *pp; + + for (i = connecthead; i >= 0; i = connectpoint2[i]) + { + pp = g_player[i].ps; + + updatecrc(crc, pp->horiz & 255); + updatecrc(crc, sprite[pp->i].extra & 255); + updatecrc(crc, pp->bobcounter & 255); + } + + return ((char) crc & 255); +} +/* +char SOSync(void) +{ + unsigned short crc = 0; + SECTOR_OBJECTp sop; + + for (sop = SectorObject; sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++) + { + // if (sop->xmid == MAXLONG) + // continue; + + updatecrc(crc, (sop->xmid) & 255); + updatecrc(crc, (sop->ymid) & 255); + updatecrc(crc, (sop->zmid) & 255); + updatecrc(crc, (sop->vel) & 255); + updatecrc(crc, (sop->ang) & 255); + updatecrc(crc, (sop->ang_moving) & 255); + updatecrc(crc, (sop->spin_ang) & 255); + } + + return ((char) crc & 255); +} + + +char EnemySync(void) +{ + unsigned short crc = 0; + short j, nextj; + spritetype *spr; + extern char DemoTmpName[]; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], j, nextj) + { + spr = &sprite[j]; + updatecrc(crc, (spr->x) & 255); + updatecrc(crc, (spr->y) & 255); + updatecrc(crc, (spr->z) & 255); + updatecrc(crc, (spr->ang) & 255); + } + + return ((char) crc & 255); +} + +char MissileSync(void) +{ + unsigned short crc = 0; + short j, nextj; + spritetype *spr; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_MISSILE], j, nextj) + { + spr = &sprite[j]; + updatecrc(crc, (spr->x) & 255); + updatecrc(crc, (spr->y) & 255); + updatecrc(crc, (spr->z) & 255); + updatecrc(crc, (spr->ang) & 255); + } + + return ((char) crc & 255); +} + +char MissileSkip4Sync(void) +{ + unsigned short crc = 0; + short j, nextj; + spritetype *spr; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_MISSILE_SKIP4], j, nextj) + { + spr = &sprite[j]; + updatecrc(crc, (spr->x) & 255); + updatecrc(crc, (spr->y) & 255); + updatecrc(crc, (spr->z) & 255); + updatecrc(crc, (spr->ang) & 255); + } + + return ((char) crc & 255); +} + +char ShrapSync(void) +{ + unsigned short crc = 0; + short j, nextj; + spritetype *spr; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_SHRAP], j, nextj) + { + spr = &sprite[j]; + updatecrc(crc, (spr->x) & 255); + updatecrc(crc, (spr->y) & 255); + updatecrc(crc, (spr->z) & 255); + updatecrc(crc, (spr->ang) & 255); + } + + return ((char) crc & 255); +} + +char MiscSync(void) +{ + unsigned short crc = 0; + short j, nextj; + spritetype *spr; + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_MISC], j, nextj) + { + spr = &sprite[j]; + updatecrc(crc, (spr->x) & 255); + updatecrc(crc, (spr->y) & 255); + updatecrc(crc, (spr->z) & 255); + updatecrc(crc, (spr->ang) & 255); + } + + return ((char) crc & 255); +} +*/ +char RandomSync(void) +{ + unsigned short crc = 0; + + updatecrc(crc, randomseed & 255); + updatecrc(crc, (randomseed >> 8) & 255); + + if (NumSyncBytes == 1) + { + updatecrc(crc,PlayerSync() & 255); + updatecrc(crc,PlayerSync2() & 255); +// updatecrc(crc,WeaponSync() & 255); + } + + return ((char) crc & 255); +} + +/* + movefta(); //ST 2 + moveweapons(); //ST 4 + movetransports(); //ST 9 + + moveplayers(); //ST 10 + movefallers(); //ST 12 + moveexplosions(); //ST 5 + + moveactors(); //ST 1 + moveeffectors(); //ST 3 + + movestandables(); //ST 6 + movefx(); //ST 11 +*/ + +char *SyncNames[] = +{ + "RandomSync", + "PlayerSync", + "PlayerSync2", + /* "FTASync", + "WeaponSync", + "TransportSync", + "FallerSync", + "ExplosionSync", + "ActorSync", + "EffectorSync", + "StandableSync", + "FXSync", */ + NULL +}; + +static char(*SyncFunc[MAXSYNCBYTES + 1])(void) = +{ + RandomSync, + PlayerSync, + PlayerSync2, + /* FTASync, + WeaponSync, + TransportSync, + FallerSync, + ExplosionSync, + ActorSync, + EffectorSync, + StandableSync, + FXSync, */ + NULL +}; + +void getsyncstat(void) +{ + int i; + playerdata_t *pp = &g_player[myconnectindex]; + unsigned int val; + static unsigned int count; + + if (numplayers < 2) + return; + + for (i = 0; SyncFunc[i]; i++) + { + pp->syncval[pp->syncvalhead & (SYNCFIFOSIZ - 1)][i] = (*SyncFunc[i])(); + } + + val = pp->syncval[pp->syncvalhead & (SYNCFIFOSIZ - 1)][0]; + count += val; + + pp->syncvalhead++; +} + +//////////////////////////////////////////////////////////////////////// +// +// Sync Message print +// +//////////////////////////////////////////////////////////////////////// + + +void SyncStatMessage(void) +{ + int i, j; + static unsigned int MoveCount = 0; + extern unsigned int MoveThingsCount; + +// if (!SyncPrintMode) +// return; + + if (numplayers <= 1) + return; + + for (i = 0; i < NumSyncBytes; i++) + { + // syncstat is NON 0 - out of sync + if (syncstat[i] != 0) + { + if (NumSyncBytes > 1) + { + sprintf(tempbuf, "GAME OUT OF SYNC - %s", SyncNames[i]); + printext256(68L, 68L + (i * 8), 1, 31, tempbuf, 0); + } + + if (!sync_found && sync_first[i][0] == '\0') + { + // sync_found one so test all of them and then never test again + sync_found = TRUE; + + // save off loop count + MoveCount = MoveThingsCount; + + for (j = 0; j < NumSyncBytes; j++) + { + if (syncstat[j] != 0 && sync_first[j][0] == '\0') + { + sprintf(tempbuf, "OUT OF SYNC - %s", SyncNames[j]); + strcpy(sync_first[j], tempbuf); + } + } + } + } + } + + // print out the sync_first message you got + for (i = 0; i < NumSyncBytes; i++) + { + if (sync_first[i][0] != '\0') + { + if (NumSyncBytes > 1) + { + sprintf(tempbuf, "FIRST %s", sync_first[i]); + printext256(50L, 0L, 1, 31, tempbuf, 0); + sprintf(tempbuf, "MoveCount %d",MoveCount); + printext256(50L, 10L, 1, 31, tempbuf, 0); + } + else + { +// short w,h; + // production out of sync error + +// sprintf(tempbuf,"GAME OUT OF SYNC!"); +// MNU_MeasureString(tempbuf, &w, &h); + // MNU_DrawString(TEXT_TEST_COL(w), 20, tempbuf, 0, 19); + +// sprintf(tempbuf,"Restart the game."); + // MNU_MeasureString(tempbuf, &w, &h); + // MNU_DrawString(TEXT_TEST_COL(w), 30, tempbuf, 0, 19); + printext256(4L,130L,31,0,"Out Of Sync - Please restart game",0); + printext256(4L,138L,31,0,"RUN DN3DHELP.EXE for information.",0); + } + } + } + +// if (syncstate != 0) +// printext256(68L, 92L, 1, 31, "Missed Network packet!", 0); +} + + +void AddSyncInfoToPacket(int *j) +{ + int sb; + int count = 0; + + // sync testing + while (g_player[myconnectindex].syncvalhead != syncvaltail && count++ < 4) + { + for (sb = 0; sb < NumSyncBytes; sb++) + packbuf[(*j)++] = g_player[myconnectindex].syncval[syncvaltail & (SYNCFIFOSIZ - 1)][sb]; + + syncvaltail++; + } +} + +void GetSyncInfoFromPacket(char *packbuf, int packbufleng, int *j, int otherconnectindex) +{ + int sb, i; + extern int syncvaltail, syncvaltottail; + playerdata_t *ppo = &g_player[otherconnectindex]; + char found = 0; + + // have had problems with this routine crashing when players quit + // games. + + // if ready2send is not set then don't try to get sync info + + if (!ready2send) + return; + + // Suspect that its trying to traverse the connect list + // for a player that does not exist. This tries to take care of that + + for (i=connecthead;i>=0;i=connectpoint2[i]) + { + if (otherconnectindex == i) + found = 1; + } + + if (!found) + return; + + // sync testing + //while ((*j) != packbufleng) // changed this on Kens suggestion + while ((*j) < packbufleng) + { + for (sb = 0; sb < NumSyncBytes; sb++) + { + ppo->syncval[ppo->syncvalhead & (SYNCFIFOSIZ - 1)][sb] = packbuf[(*j)++]; + } + ppo->syncvalhead++; + } + + // update syncstat + // if any of the syncstat vars is non-0 then there is a problem + for (i=connecthead;i>=0;i=connectpoint2[i]) + { + if (g_player[i].syncvalhead == syncvaltottail) + return; + } + + //for (sb = 0; sb < NumSyncBytes; sb++) + // syncstat[sb] = 0; + + while (1) + { + for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i]) + { + for (sb = 0; sb < NumSyncBytes; sb++) + { + if (g_player[i].syncval[syncvaltottail & (SYNCFIFOSIZ - 1)][sb] != g_player[connecthead].syncval[syncvaltottail & (SYNCFIFOSIZ - 1)][sb]) + { + syncstat[sb] = 1; + } + } + } + + syncvaltottail++; + + for (i=connecthead;i>=0;i=connectpoint2[i]) + { + if (g_player[i].syncvalhead == syncvaltottail) + return; + } + } +} + +