Server-Client Protocol (Part 4) LAST


 

Posted by Maj.Bitch on January 20, 1999 at 19:32:46:

Title: Server-Client Protocols (Part IV)
Difficulty: Difficult
By: Philip (aka Maj.Bitch)
Email: peblair@gv.net
Date: 1-20-99
Note: Please give credit where credit is due.
======================================================

//==============================================
void set_map_name(protocol *state,char *mapname){
state->shared->smn(state->shared->smn_arg,mapname);
}

//==============================================
void init_edicts(protocol *state){
unsigned c;

if (state->delta_frame == 0xffffffff){
memcpy(state->shared->edicts,state->baseline, sizeof(edict)*MAX_EDICTS);
return;}

for (c=0;c<16;c++){
if (state->oldframe_nums[c] != state->delta_frame) continue;
memcpy(state->shared->edicts,state->oldframes[c], sizeof(edict)*MAX_EDICTS);
return;}

printf(stderr,"Server requested delta frame we do not have\n");
exit(7);
}

//==============================================
void save_frame(protocol *state){
unsigned c;
for (c=0;c<15;c++){
memcpy(state->oldframes[c],state->oldframes[c+1], sizeof(edict)*MAX_EDICTS);
state->oldframe_nums[c] = state->oldframe_nums[c+1];}

memcpy(state->oldframes[15],state->shared->edicts, sizeof(edict)*MAX_EDICTS);
state->oldframe_nums[15] = state->frame_num;
}

//==============================================
void send_ack(protocol *state){
buffer *buf;

buf = newbuffer();

putLEu32(buf,state->seq);
putLEu32(buf,state->last_seq);
putLEu16(buf,state->qport);

sock_send(state->sock,buf);

freebuffer(buf);

state->seq++;
}

//==============================================
void parse_connected(protocol *state,buffer *buf,unsigned long seq){
state->last_seq = seq;
if ((seq & HIDDEN_BIT) || (getsize(buf) == 8))
send_ack(state);
proc_ack(state,getLEu32(buf));
parse_messages(state,buf);
}

//==============================================
void parse_packet(protocol *state,buffer *buf){
unsigned long seq;

seq = getLEu32(buf);
if (seq == 0xffffffff)
parse_connectionless(state,buf);
else
parse_connected(state,buf,seq);
}

//==============================================
void proc_need_ack(protocol *state){
double now;

if (state->need_ack == NULL) return;

now = gettime();
if ((now-state->need_ack_last) < state->shared->ping) return;
state->need_ack_last = now;

if (state->need_ack->seq == 0)
state->need_ack->seq = state->seq;

bufsetppos(state->need_ack->buf,0);
putLEu32(state->need_ack->buf,HIDDEN_BIT | state->seq);
putLEu32(state->need_ack->buf,state->last_seq);

sock_send(state->sock,state->need_ack->buf);

state->seq++;
ping_start(state);
}

//==============================================
void proc_packet(protocol *state){
buffer *buf;

buf = sock_recv(state->sock);
if (!buf) return;
parse_packet(state,buf);
freebuffer(buf);
}

//==============================================
void clear_data(protocol *state){
int c;
state->delta_frame = 0xffffffff;
for (c=0;c<16;c++)
state->oldframe_nums[c] = 0xffffffff;
memset(state->baseline,0,sizeof(edict)*MAX_EDICTS);
memset(state->shared->edicts,0,sizeof(edict)*MAX_EDICTS);
state->delta_angles = vec_mk(0.0,0.0,0.0);
}

//==============================================
void protocol_update(protocol *state){

switch(state->level){
case PRE_CHALLENGE:
send_getchallenge(state);
state->level = POST_CHALLENGE;
break;

case POST_CHALLENGE:
state->level = PRE_CHALLENGE;
break;

case PRE_CONNECT:
send_connect(state);
state->level = POST_CONNECT;
break;

case POST_CONNECT:
state->level = PRE_CONNECT;
break;

case POST_SYN:
clear_data(state);
protocol_send_console_command(state,"new\n");
state->level = PRE_GAME;
break;

case PRE_GAME: break;

case IN_GAME: break;

case POST_GAME:
protocol_send_console_command(state,"disconnect\n");
state->level = PRE_GAME_OVER;
break;

case PRE_GAME_OVER:
if (!state->need_ack) state->level = GAME_OVER;
break;

case GAME_OVER: break;

default:
printf(stderr,"internal error: unknown state\n");
exit(7);
} // switch

proc_need_ack(state);
proc_packet(state);
}

//==============================================
int protocol_getstate(protocol *state){
return (state->level-IN_GAME);
}


That's about all I can think of for this stuff..

If I come up with more, I'll post..

Have Fun!

regards,
philip