///////////////////////////////////////////////////////////////////////////////// ////// Released under the GPL see gpl.txt ////// Written by and copyrighted by: Michael Gibson (c)2003,2004,2005,2006,2007 //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #define ACK 0x06 // Acknowledgement #define NAK 0x15 // Negative Acknowlegement #define NuLl 0x00 // pure null int x; //general loop variable int i_incoming_player; int player_num=0; //number of players on the server int player_x[25]; //player's x position int player_y[25]; //player's y postion int player_gld[25]; //player gold int player_slv[25]; //player silver int player_cpr[25]; //player copper int player_str[25]; //player strength int player_pos[25][25]; //player possesion up to 25 //to sale, keep, or barter. int player_maj[25]; //player has magic or force; int player_hatchet[25]={0}; //does player have a hatchet; //default no; 0=no,1=yes has one int player_lumber[25]; //harvested lumber int player_charm[25]={0}; //player charmed? No by default int player_w_in_hand[25]={1}; //does the player have weapon in hand //default yes int player_h_in_hand[25]={0}; //does the player have hatchet in hand //default no int player_dex[25]; //player dexterity int dex_adj[25]; //adjustment for dexterity (weight of weapon) int player_exp[25]; //player experiance points int player_wep[25]; //player's weapon int wep_wear[25]; //hit points for weapon (wear and tear) int player_rac[25]; //player's race int player_sex[25]; //player's sex int player_head[25]; int player_body[25]; int player_armor[25]; //armor int player_hair[25]; int player_total_armor[25]; //total protection from armor char *player_name[25]; //player's name int map[512][512]; //map of 512 tiles by 512 tiles int xmax, ymax; //max size of map int conf_wep_dam[9]; int conf_wep_wear[9]; int conf_dex_adj[9]; /* modules */ void readmap(); //Reads Map into memory void load_config(); //Read config file void socket_connect(); // Setup TCP and UDP server connect void socket_bind(); // Setup TCP and UDP server Bind port to card void Rsocket(); // Setup UDP client mode socket void Rconnect(); // Setup UDP client mode connect void proc_udp(); // Process both client and server UDP communication void TCP_proc(); // Process TCP server packets /* socket variables */ struct sockaddr_in fsin; //TCP server structure struct servent *pse; struct protoent *ppe; //What protocal will the server talk? struct sockaddr_in sin; struct sockaddr_in cliAddr, servAddr; // UDP server structure int cliLen; int udp_sock = 0, // UDP server socket value bind1 = 0, // Server bind successful? lis = 0; // Server listen successful? int alen = 0, server = 0; // UDP server file discriptor char send_buff[177]; // UDP send buffer char recv_buff[39]; // TCP recieve buffer int result = 0; // success return int n = 0; // TCP return value int portno; // port server is listening on [configurable] int sockfd_udp; // UDP client file discriptor struct sockaddr_in serv_addr, cli_addr; char server_ip[25][25]; // The game client's server Address int server_port=1112; // The game client's port [not configurable] char tmp_str[50]; FILE *fp; // File pointer used for reading config and map /////////////////////////////////////////////////// // main() /////////////////////////////////////////////////// int main(){ readmap(); //Read map setbuf(stdout, NULL); //null out stdout buffer socket_connect(); //UDP server SOCKET CONNECTION socket_bind(); //UDP server SOCKET BINDING for(;;){ //Endless loop proc_udp(); //Process UDP server and client packets } return(0); } /////////////////////////////////////////////////// // CONNECT SOCKET /////////////////////////////////////////////////// void socket_connect() { bzero((char *)&sin, sizeof(sin)); servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = htonl(INADDR_ANY); //Load UDP server address load_config(); servAddr.sin_port = htons(portno); //Load and Convert UDP port to Little Ind ppe = getprotobyname("udp"); //Declare UPD setbuf(stdout, NULL); server = socket(PF_INET, SOCK_DGRAM, ppe->p_proto); } ///////////////////////////////////////////////// // SOCKET BINDING ///////////////////////////////////////////////// void socket_bind() { bind1 = bind(server, (struct sockaddr *) &servAddr,sizeof(servAddr)); printf("\n%d value of bind\n", bind1); } //////////////////////////////////////////////////// // proc_udp //////////////////////////////////////////////////// void proc_udp() { char text_message[50]; char incoming_player[3]; char player_direction; int from_player; int i_sendto_player; int is_attack_possible; int is_attack_success; int map_x,map_y; strcpy(recv_buff,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); /* receive message */ cliLen = sizeof(cliAddr); n = recvfrom(server, recv_buff, 39, 0, (struct sockaddr *) &cliAddr, &cliLen); printf("recieved: %s\n",recv_buff); //start communication with remote Rsocket(); //Create socket Rconnect(); //Connect to remote client game server // 0123 // PQ R if(recv_buff[3] == 'R'){ //Checking to see if it is a request to play player_num++; //increment number of players x=5; //start reading IP at character 5 do{ server_ip[player_num][x-5]=recv_buff[x]; //read IP from packet x++; }while(recv_buff[x]!=' '); //do while not at end of stream printf("Recieved request to play from %s\n",server_ip[player_num]); printf("Now sending back Initial Data packet\n"); // 000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000011111 // 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 printf(send_buff,"ID%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d", // HT pl# plx ply mp1 mp2 mp3 mp4 mp5 mp6 mp7 mp8 mp9 mp0 mp1 mp2 mp3 mp4 mp5 mp6 mp7 mp8 mp9 mp0 mp1 mp2 mp3 mp4 mp5 player_num, player_x[player_num], player_y[player_num], map[player_x[player_num] - 2][player_y[player_num] - 2], map[player_x[player_num] - 1][player_y[player_num] - 2], map[player_x[player_num] ][player_y[player_num] - 2], map[player_x[player_num] + 1][player_y[player_num] - 2], map[player_x[player_num] + 2][player_y[player_num] - 2], map[player_x[player_num] - 2][player_y[player_num] - 1], map[player_x[player_num] - 1][player_y[player_num] - 1], map[player_x[player_num] ][player_y[player_num] - 1], map[player_x[player_num] + 1][player_y[player_num] - 1], map[player_x[player_num] + 2][player_y[player_num] - 1], map[player_x[player_num] - 2][player_y[player_num] ], map[player_x[player_num] - 1][player_y[player_num] ], map[player_x[player_num] ][player_y[player_num] ], map[player_x[player_num] + 1][player_y[player_num] ], map[player_x[player_num] + 2][player_y[player_num] ], map[player_x[player_num] - 2][player_y[player_num] + 1], map[player_x[player_num] - 1][player_y[player_num] + 1], map[player_x[player_num] ][player_y[player_num] + 1], map[player_x[player_num] + 1][player_y[player_num] + 1], map[player_x[player_num] + 2][player_y[player_num] + 1], map[player_x[player_num] - 2][player_y[player_num] + 2], map[player_x[player_num] - 1][player_y[player_num] + 2], map[player_x[player_num] ][player_y[player_num] + 2], map[player_x[player_num] + 1][player_y[player_num] + 2], map[player_x[player_num] + 2][player_y[player_num] + 2]); //Format Initial Data packet printf("Map sent:\n%04d %04d %04d %04d %04d \n%04d %04d %04d %04d %04d\n%04d %04d %04d %04d %04d\n%04d %04d %04d %04d %04d\n%04d %04d %04d %04d %04d\n", map[player_x[player_num] - 2][player_y[player_num] - 2], map[player_x[player_num] - 1][player_y[player_num] - 2], map[player_x[player_num] ][player_y[player_num] - 2], map[player_x[player_num] + 1][player_y[player_num] - 2], map[player_x[player_num] + 2][player_y[player_num] - 2], map[player_x[player_num] - 2][player_y[player_num] - 1], map[player_x[player_num] - 1][player_y[player_num] - 1], map[player_x[player_num] ][player_y[player_num] - 1], map[player_x[player_num] + 1][player_y[player_num] - 1], map[player_x[player_num] + 2][player_y[player_num] - 1], map[player_x[player_num] - 2][player_y[player_num] ], map[player_x[player_num] - 1][player_y[player_num] ], map[player_x[player_num] ][player_y[player_num] ], map[player_x[player_num] + 1][player_y[player_num] ], map[player_x[player_num] + 2][player_y[player_num] ], map[player_x[player_num] - 2][player_y[player_num] + 1], map[player_x[player_num] - 1][player_y[player_num] + 1], map[player_x[player_num] ][player_y[player_num] + 1], map[player_x[player_num] + 1][player_y[player_num] + 1], map[player_x[player_num] + 2][player_y[player_num] + 1], map[player_x[player_num] - 2][player_y[player_num] + 2], map[player_x[player_num] - 1][player_y[player_num] + 2], map[player_x[player_num] ][player_y[player_num] + 2], map[player_x[player_num] + 1][player_y[player_num] + 2], map[player_x[player_num] + 2][player_y[player_num] + 2]); result=send(sockfd_udp, send_buff, strlen(send_buff), 0); //send response packet printf("send buffer: '%s'\n",send_buff); //show content of sent packet printf("length is %d\n\n",strlen(send_buff)); //show length } // 11111111112222222222333 // 012345678901234567890123456789012 // new PP 0001 002 002 002 002 002 002 1 if(recv_buff[1]=='P'){ //player packet sprintf(tmp_str,"%c%c%c%c",recv_buff[3],recv_buff[4],recv_buff[5],recv_buff[6]); i_incoming_player=atoi(tmp_str); sprintf(tmp_str,"%c%c%c",recv_buff[8],recv_buff[9],recv_buff[10]); player_rac[i_incoming_player]=atoi(tmp_str); sprintf(tmp_str,"%c%c%c",recv_buff[12],recv_buff[13], recv_buff[14]); player_wep[i_incoming_player]=atoi(tmp_str); sprintf(tmp_str,"%c%c%c",recv_buff[16],recv_buff[17], recv_buff[18]); player_head[i_incoming_player]=atoi(tmp_str); sprintf(tmp_str,"%c%c%c",recv_buff[20],recv_buff[21], recv_buff[22]); player_hair[i_incoming_player]=atoi(tmp_str); sprintf(tmp_str,"%c%c%c",recv_buff[24],recv_buff[25], recv_buff[26]); player_body[i_incoming_player]=atoi(tmp_str); sprintf(tmp_str,"%c%c%c",recv_buff[28],recv_buff[29], recv_buff[30]); player_armor[i_incoming_player]=atoi(tmp_str); sprintf(tmp_str,"%c",recv_buff[32]); player_sex[i_incoming_player]=atoi(tmp_str); player_comp(player_rac[i_incoming_player],&player_str[i_incoming_player],&player_dex[i_incoming_player],&player_exp[i_incoming_player]); weapon_comp(player_wep[i_incoming_player],&wep_wear[i_incoming_player],&dex_adj[i_incoming_player], conf_wep_wear, conf_dex_adj); player_total_armor[i_incoming_player] = armor_comp(player_armor[i_incoming_player], &dex_adj[i_incoming_player]); // 000000000011111111 // 012345678901234567 // PP 11 11 11 111 11 sprintf(send_buff,"PP %02d %02d %02d %03d %02d ", player_str[i_incoming_player], player_dex[i_incoming_player], player_exp[i_incoming_player], wep_wear[i_incoming_player], dex_adj[i_incoming_player]); //Format Player Property packet result=send(sockfd_udp, send_buff, strlen(send_buff), 0); //send response packet printf("send buffer: '%s'\n",send_buff); //show content of sent packet printf("length is %d\n\n",strlen(send_buff)); //show length } // 0123 // PQ S //if(recv_buff[3] == 'S'){ //Checking to see if it is a Start // printf("Recieved Start request, Sending response\n"); // sprintf(send_buff,"startok"); //Format responce packet // result=send(sockfd_udp, send_buff, strlen(send_buff), 0); //send response packet // printf("send buffer: '%s'\n",send_buff); //show content of sent packet // printf("length is %d\n\n",strlen(send_buff)); //show length //} //end of if poll ///////////////////////////////////////////////////////////////// // Movement Packet // |012345678| // |MO 9999 9| // |pt plr d| if(recv_buff[0]=='M' && recv_buff[1]=='O'){ sprintf(incoming_player,"%c%c%c%c", recv_buff[3], recv_buff[4], recv_buff[5], recv_buff[6]); i_incoming_player=atoi(incoming_player); player_direction = recv_buff[8]; if(can_player_move(player_str[i_incoming_player],player_rac[i_incoming_player],map[player_x[i_incoming_player]][player_y[i_incoming_player]])){ if(player_direction == '1'){ printf("%d asked to move North",i_incoming_player); player_y[i_incoming_player]=player_y[i_incoming_player] - 1; if( player_y[i_incoming_player] <= 0) player_y[i_incoming_player] = 0; } if(player_direction == '2'){ player_y[i_incoming_player]=player_y[i_incoming_player] - 1; if( player_y[i_incoming_player] <= 0) player_y[i_incoming_player] = 0; player_x[i_incoming_player]=player_x[i_incoming_player] + 1; if( player_x[i_incoming_player] >= xmax) player_x[i_incoming_player] = xmax; } if(player_direction == '3'){ printf("%d asked to move East",i_incoming_player); player_x[i_incoming_player]=player_x[i_incoming_player] + 1; if( player_x[i_incoming_player] >= xmax) player_x[i_incoming_player] = xmax; } if(player_direction == '4'){ player_y[i_incoming_player]=player_y[i_incoming_player] + 1; if( player_y[i_incoming_player] >= ymax) player_y[i_incoming_player] = ymax; player_x[i_incoming_player]=player_x[i_incoming_player] + 1; if( player_x[i_incoming_player] >= ymax) player_x[i_incoming_player] = ymax; } if(player_direction == '5'){ printf("%d asked to move South",i_incoming_player); player_y[i_incoming_player]=player_y[i_incoming_player] + 1; if( player_y[i_incoming_player] >= ymax) player_y[i_incoming_player] = ymax; } if(player_direction == '6'){ player_y[i_incoming_player]=player_y[i_incoming_player] + 1; if( player_y[i_incoming_player] >= ymax) player_y[i_incoming_player] = ymax; player_x[i_incoming_player]=player_x[i_incoming_player] - 1; if( player_x[i_incoming_player] <= 0) player_x[i_incoming_player] = 0; } if(player_direction == '7'){ player_x[i_incoming_player]=player_x[i_incoming_player] - 1; if( player_x[i_incoming_player] <= 0) player_x[i_incoming_player] = 0; } if(player_direction == '8'){ player_y[i_incoming_player]=player_y[i_incoming_player] - 1; if( player_y[i_incoming_player] <= 0) player_y[i_incoming_player] = 0; player_x[i_incoming_player]=player_x[i_incoming_player] - 1; if( player_x[i_incoming_player] <= 0) player_x[i_incoming_player] = 0; } } //end of can player move check_tile(&map[player_x[i_incoming_player]][player_y[i_incoming_player]], &player_charm[i_incoming_player], &player_h_in_hand[i_incoming_player], &player_cpr[i_incoming_player],&player_slv[i_incoming_player],&player_gld[i_incoming_player], &player_hatchet[i_incoming_player], &player_lumber[i_incoming_player], &player_x[i_incoming_player], &player_y[i_incoming_player]); //check for specail tiles and if so do appropriate action. sprintf(send_buff,"PL %03d",player_num); //Format responce packet(player list) result=send(sockfd_udp, send_buff, strlen(send_buff),0); //send reponse packet (player list) printf("send buffer: %s\n",send_buff); //show content of sent packet printf("length is %d\n\n",strlen(send_buff)); //show length for(x=1;x<=player_num;x++){ sprintf(send_buff,"PI %03d %03d %03d %02d %02d %02d %03d %03d %03d %1d %1d %03d %03d %03d %03d", x, player_x[x],player_y[x], player_str[x], player_wep[x], player_dex[x], player_gld[x], player_slv[x], player_cpr[x], player_rac[x], player_sex[x], player_head[x], player_hair[x],player_body[x],player_armor[x]); result=send(sockfd_udp,send_buff,strlen(send_buff),0); //send response packet printf("send buffer: %s\n",send_buff); //show content of sent packet printf("length is %d\n\n",strlen(send_buff)); //show length } //these checks keep map in check but allows player to move to edge of map. //the above check keep player from leaving map if(player_x[player_num] >= 2){ map_x = player_x[player_num];} if(player_x[player_num] == 0 || player_x[player_num] == 1){ map_x=2;} if(player_y[player_num] >= 2){ map_y = player_y[player_num];} if(player_y[player_num] == 0 || player_y[player_num] == 1) {map_y=2;} // 000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900 // 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 sprintf(send_buff,"MI%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d%04d", map[map_x - 2][map_y - 2], map[map_x - 1][map_y - 2], map[map_x ][map_y - 2], map[map_x + 1][map_y - 2], map[map_x + 2][map_y - 2], map[map_x - 2][map_y - 1], map[map_x - 1][map_y - 1], map[map_x ][map_y - 1], map[map_x + 1][map_y - 1], map[map_x + 2][map_y - 1], map[map_x - 2][map_y ], map[map_x - 1][map_y ], map[map_x ][map_y ], map[map_x + 1][map_y ], map[map_x + 2][map_y ], map[map_x - 2][map_y + 1], map[map_x - 1][map_y + 1], map[map_x ][map_y + 1], map[map_x + 1][map_y + 1], map[map_x + 2][map_y + 1], map[map_x - 2][map_y + 2], map[map_x - 1][map_y + 2], map[map_x ][map_y + 2], map[map_x + 1][map_y + 2], map[map_x + 2][map_y + 2]); result=send(sockfd_udp, send_buff, strlen(send_buff), 0); //send map packet printf("'%s'\n",send_buff); if(result >=0) printf("Local map sent\n"); } // end of MO response // Attack packet // 012345678901 // AT 0001 0002 if(recv_buff[0]=='A' && recv_buff[1]=='T'){ sprintf(incoming_player,"%c%c%c%c", recv_buff[3], recv_buff[4], recv_buff[5], recv_buff[6]); i_incoming_player=atoi(from_player); sprintf(incoming_player,"%c%c%c%c", recv_buff[8], recv_buff[9], recv_buff[10], recv_buff[11]); i_sendto_player=atoi(incoming_player); ///check if player A can Attack player B is_attack_possible = attack_possible(player_x[i_incoming_player], player_y[i_incoming_player], player_exp[i_incoming_player], player_wep[i_incoming_player], player_x[i_sendto_player], player_y[i_sendto_player], player_charm[i_sendto_player]); //if the attack is not possible, out of range. if(is_attack_possible == 0){ printf("Player %d is trying to attack player %d \n",i_incoming_player, i_sendto_player); printf("Player %d is out of range of player %d \n",i_incoming_player, i_sendto_player); printf("Attack Failed\n"); //need to notify player why attack failed //UDP reply printf("Attempting to send: AT F 0\n"); result=send(sockfd_udp,"AT F 0 ", 7, 0); printf("packet sent\n"); } //yep it is possible to attack player B if(is_attack_possible == 1 || is_attack_possible == 2){ printf("Player %d is attacking player %d \n",i_incoming_player, i_sendto_player); //the attack is possible so lets check to see if we were successful. is_attack_success = attack_success(player_dex[i_incoming_player], dex_adj[i_incoming_player], &wep_wear[i_incoming_player], &player_exp[i_incoming_player], player_dex[i_sendto_player], player_total_armor[i_sendto_player]); if(is_attack_success==1){ //experiance is auto added in attack_success() funtion above; //this function needs to be added properly ~mg //now check if dex has gone up do to experiance //eval_dex(int *player_dex, int player_rac, int player_exp); printf("Player %d attack against player %d was a success \n",i_incoming_player, i_sendto_player); // let players know this infromation by packets result=send(sockfd_udp, "AT S 0 ", 7, 0); // calculate damage // randome calc taken out because of bug ~mg // the below line just removes 1 from the character's strength player_str[i_sendto_player] = player_str[i_sendto_player] - 1; //temp to see if it works if(player_str[i_sendto_player] <= 0) player_str[i_sendto_player]=0; } else{ //let player know that it was not a success result=send(sockfd_udp, "AT F M ", 7, 0); } } if(is_attack_possible == 3){ printf("Player %d is trying to attack player %d \n",i_incoming_player, i_sendto_player); printf("Player %d is under a spell/force of player %d \n",i_incoming_player, i_sendto_player); printf("Failed\n"); //need to notify player why attack failed result=send(sockfd_udp, "AT F 3", 6, 0); } } // Text message Packet // 000000000011111111112222222 // 012345678901234567890123456 // TM 0001 0002 message here++ // teminated by two if(recv_buff[0]=='T' && recv_buff[1]=='M'){ sprintf(incoming_player,"%c%c%c%c",recv_buff[3],recv_buff[4],recv_buff[5],recv_buff[6]); i_incoming_player=atoi(incoming_player); sprintf(incoming_player,"%c%c%c%c",recv_buff[8],recv_buff[9],recv_buff[10],recv_buff[11]); i_sendto_player=atoi(incoming_player); x=13; do{ text_message[x-11]=recv_buff[x]; }while(recv_buff[x] != '+' && recv_buff[x+1] != '+'); Rsocket(); Rconnect(); //Connect to remote client game server // Forwarded Text message Packet // 0000000000111111111122 // 0123456789012345678901 // FT 0001 message here++ sprintf(send_buff,"FT %04d %s++",from_player,text_message); //Todo: //check how close the player are from eatch other. if( abs( player_x[i_incoming_player] - player_x[i_sendto_player] ) <= 2 && abs(player_y[i_incoming_player] - player_y[i_sendto_player] ) <= 2){ result=send(server, send_buff, strlen(send_buff), 0); //send msg packet if(result >=0) printf("forwarded text message sent\n"); } } // end of text messaging if(recv_buff[0]=='S' && recv_buff[1]=='S'){ sprintf(incoming_player,"%c%c%c%c", recv_buff[3], recv_buff[4], recv_buff[5], recv_buff[6]); i_incoming_player=atoi(incoming_player); Rsocket(); Rconnect(); //Connect to remote client game server sprintf(send_buff,"%c",ACK); result=send(server, send_buff, strlen(send_buff), 0); //send back Ack if(result >=0) printf("forwarded text message sent\n"); } // end of Server Status printf("++closing udp_sock\n"); //close(udp_sock); //Close UDP server close(sockfd_udp); } //////////////////////////////////////////////// // ReadMap /////////////////////////////////////////////// void readmap() { int x, y; //x and y cords int num_of_players; //number of players for map system("clear"); //clear screen fp=fopen("map.dat","r"); //open map printf("Reading Map.....\n"); fscanf(fp,"%d",&num_of_players); //read number of players printf("This map supports %d players.\n",num_of_players); for(x=1;x<=num_of_players;x++){ fscanf(fp,"%d",&player_x[x]); //read players x start cord fscanf(fp,"%d",&player_y[x]); //read players y start cord } fscanf(fp,"%d",&xmax); //read maps width fscanf(fp,"%d",&ymax); //read maps height printf("Map size= %d x %d\n",xmax, ymax); for(x=0;x