| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- #include <asm-generic/errno.h>
- #include <stdio.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <errno.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include "scufeng/log.h"
- #include "networking.h"
- #include "MultiPlayer.h"
- #include "game.h"
- #include "game_common.h"
- #include "GameState_net.h"
- static bool handle_game_state_msg(MultiPlayer *const mp) {
- GameStateMsg msg;
- if (!recv_msg(mp->conn_s, NET_MSG_GAME_STATE, (uint8_t *) &msg)) {
- return false;
- }
- GameStateMsg_to_GameState(&msg, &mp->state);
- return true;
- }
- bool MultiPlayer_alloc(
- MultiPlayer *const mp,
- const unsigned int screen_w,
- const unsigned int screen_h,
- const char *server_host,
- const uint16_t server_port
- ) {
- struct protoent *proto = getprotobyname("tcp");
- mp->sock = socket(AF_INET, SOCK_STREAM, proto->p_proto);
- if (mp->sock == -1) {
- SE_LOG_FATALF("socket failed: %d %s", errno, strerror(errno));
- }
- struct in_addr server_addr;
- int res = inet_aton(server_host, &server_addr);
- if (res == 0) {
- close(mp->sock);
- SE_LOG_FATAL("inet_aton failed");
- }
- struct sockaddr_in server_sockaddr = {
- .sin_family = AF_INET,
- .sin_addr = server_addr,
- .sin_port = htons(server_port)
- };
- res = connect(
- mp->sock,
- (struct sockaddr *) &server_sockaddr,
- sizeof(server_sockaddr)
- );
- if (res == -1) {
- close(mp->sock);
- SE_LOG_ERRORF("connect failed: %d %s", errno, strerror(errno));
- return false;
- }
- SE_LOG("Connected to server");
- mp->conn_s = fdopen(mp->sock, "r+");
- if (mp->conn_s == nullptr) {
- close(mp->sock);
- SE_LOG_ERRORF("fdopen failed: (%d) %s", errno, strerror(errno));
- return false;
- }
- NetMsgType msg_type;
- if (recv_msg_type(mp->conn_s, &msg_type) == ECONNRESET) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERROR("Connection reset");
- return false;
- }
- if (msg_type != NET_MSG_IS_PLAYER_1) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERRORF("Did not get IS_PLAYER_1 msg, got: %u", msg_type);
- return false;
- }
- IsPlayer1Msg p1_msg = { 0 };
- if (!recv_msg(mp->conn_s, NET_MSG_IS_PLAYER_1, (uint8_t *) &p1_msg)) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERROR("Connection reset");
- return false;
- }
- mp->is_player_1 = (bool) p1_msg.player1;
- if (mp->is_player_1) {
- SE_LOG("I am player 1");
- } else {
- SE_LOG("I am player 2");
- }
- SE_LOG("Waiting for game start");
- mp->state = GameState_new(game_default_params, false);
- if (recv_msg_type(mp->conn_s, &msg_type) == ECONNRESET) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERROR("Connection reset");
- return false;
- }
- if (msg_type != NET_MSG_GAME_STATE) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_FATALF("[MultiPlayer_alloc] Did not get GAME_STATE msg, got: %u", msg_type);
- }
- if (!handle_game_state_msg(mp)) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERROR("Connection reset");
- return false;
- }
- if (recv_msg_type(mp->conn_s, &msg_type) == ECONNRESET) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERROR("Connection reset");
- return false;
- }
- if (msg_type != NET_MSG_GAME_START) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_FATALF("[MultiPlayer_alloc] Did not get GAME_START msg, got: %u", msg_type);
- }
- if (!send_msg(mp->conn_s, NET_MSG_GAME_START, nullptr)) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERROR("Connection reset");
- return false;
- }
- if (fcntl(mp->sock, F_SETFL, O_NONBLOCK) != 0) {
- fclose(mp->conn_s);
- close(mp->sock);
- SE_LOG_ERRORF("fcntl failed on mp->sock: (%d) %s", errno, strerror(errno));
- return false;
- }
- SE_LOG("Game started");
- mp->screen_w = screen_w;
- mp->screen_h = screen_h;
- mp->shapes = GameShapes_alloc(screen_w, screen_h, game_default_params);
- return mp;
- }
- void MultiPlayer_free(MultiPlayer *const mp) {
- fclose(mp->conn_s);
- mp->conn_s = nullptr;
- // close(mp->conn);
- // mp->conn = 0;
- close(mp->sock);
- mp->sock = 0;
- GameShapes_free(&mp->shapes);
- }
- static void handle_paddle_pos_msg(MultiPlayer *const mp) {
- PaddleUpdateMsg msg;
- recv_msg(mp->conn_s, NET_MSG_PADDLE_POS, (uint8_t *) &msg);
- mp->state.paddle_l.pos[1] = msg.l_pos_y;
- mp->state.paddle_l.dirv[1] = msg.l_dirv_y;
- mp->state.paddle_r.pos[1] = msg.r_pos_y;
- mp->state.paddle_r.dirv[1] = msg.r_dirv_y;
- }
- static void handle_ball_update_msg(MultiPlayer *const mp) {
- BallUpdateMsg msg;
- recv_msg(mp->conn_s, NET_MSG_BALL_UPDATE, (uint8_t *) &msg);
- mp->state.ball.pos[0] = msg.ball_pos_x;
- mp->state.ball.pos[1] = msg.ball_pos_y;
- mp->state.ball.dirv[0] = msg.ball_dirv_x;
- mp->state.ball.dirv[1] = msg.ball_dirv_y;
- }
- static void handle_score_update_msg(MultiPlayer *const mp) {
- ScoreUpdateMsg msg;
- recv_msg(mp->conn_s, NET_MSG_SCORE_UPDATE, (uint8_t *) &msg);
- mp->state.score_l = msg.l_score;
- mp->state.score_r = msg.r_score;
- SE_LOGF("score_l: %d score_r: %d", mp->state.score_l, mp->state.score_r);
- }
- static void handle_input(
- const MultiPlayer *const mp,
- bool *dir_changed,
- SEDirection *new_dir,
- bool *quit
- ) {
- if (se_get_key(SE_KEY_ESCAPE) == SE_KEY_ACTION_PRESS) {
- *quit = true;
- return;
- }
- *new_dir = SE_NONE;
- *dir_changed = false;
- const SEDirection current_dir = GameState_paddle_l_dir_get(&mp->state);
- if (se_get_key(SE_KEY_W) == SE_KEY_ACTION_PRESS) {
- if (current_dir != SE_UP) {
- *new_dir = SE_UP;
- *dir_changed = true;
- }
- } else if (se_get_key(SE_KEY_S) == SE_KEY_ACTION_PRESS) {
- if (current_dir != SE_DOWN) {
- *new_dir = SE_DOWN;
- *dir_changed = true;
- }
- } else if (current_dir != SE_NONE) {
- *new_dir = SE_NONE;
- *dir_changed = true;
- }
- }
- Screen MultiPlayer_tick(MultiPlayer *const mp, const double delta) {
- NetMsgType msg_type;
- while (true) {
- const int res = recv_msg_type(mp->conn_s, &msg_type);
- if (res == 0) {
- switch (msg_type) {
- case NET_MSG_PADDLE_CHANGE_DIR:
- break;
- case NET_MSG_PADDLE_POS:
- handle_paddle_pos_msg(mp);
- break;
- case NET_MSG_GAME_STATE:
- handle_game_state_msg(mp);
- break;
- case NET_MSG_IS_PLAYER_1:
- case NET_MSG_GAME_START:
- break;
- case NET_MSG_BALL_UPDATE:
- handle_ball_update_msg(mp);
- break;
- case NET_MSG_SCORE_UPDATE:
- handle_score_update_msg(mp);
- break;
- }
- break;
- } else if (res == ECONNRESET) {
- SE_LOG_ERROR("Connection reset");
- return PONG_MAIN_MENU;
- } else if (res == EWOULDBLOCK) {
- break;
- } else {
- SE_LOG_FATALF("[MultiPlayer_tick] Unhandled return value: %d", res);
- }
- // SE_LOGF("Got message: %s", NetMsgType_to_str(msg_type));
- }
- bool dir_changed = false;
- SEDirection new_dir;
- bool quit = false;
- handle_input(mp, &dir_changed, &new_dir, &quit);
- if (quit) {
- return PONG_MAIN_MENU;
- }
- if (dir_changed) {
- GameState_paddle_l_change_dir(&mp->state, new_dir);
- const PaddleChangeDirMsg msg = {
- .dir = (uint8_t) new_dir
- };
- if (!send_msg(mp->conn_s, NET_MSG_PADDLE_CHANGE_DIR, (uint8_t *) &msg)) {
- SE_LOG_ERROR("Connection reset");
- return PONG_MAIN_MENU;
- }
- }
- GameState_update(&mp->state, delta);
- GameShapes_update(&mp->shapes, &mp->state, mp->screen_w, mp->screen_h);
- GameShapes_render(&mp->shapes, &mp->state, mp->screen_w, mp->screen_h);
- return PONG_MULTIPLAYER;
- }
|