/* * network.cpp * * Created on: 12.01.2011 * Author: gmueller */ #include "network.h" #include #include #include ENetHost *host = 0; ENetPeer *client_peer = 0; void setup_network(const char *remote) { if (enet_initialize() != 0) { throw "failed to initialize enet"; } if (remote == NULL) { fprintf(stdout, "Start server.\n"); ENetAddress address; address.host = ENET_HOST_ANY; address.port = 1234; host = enet_host_create(&address, 32, 2, 0, 0); if (host == NULL) { fprintf(stderr, "An error occurred while trying to create an ENet server host.\n"); exit( EXIT_FAILURE); } } else { fprintf(stdout, "Start client.\n"); ENetAddress address; ENetEvent event; host = enet_host_create(NULL, 1, 2, 57600 / 8, 14400 / 8); if (host == NULL) { fprintf(stderr, "An error occurred while trying to create an ENet client host.\n"); exit( EXIT_FAILURE); } enet_address_set_host(&address, remote); address.port = 1234; /* Initiate the connection, allocating the two channels 0 and 1. */ client_peer = enet_host_connect(host, &address, 2, 0); if (client_peer == NULL) { fprintf(stderr, "No available peers for initiating an ENet connection.\n"); exit( EXIT_FAILURE); } /* Wait up to 5 seconds for the connection attempt to succeed. */ if (enet_host_service(host, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) { puts("Connection succeeded."); } else { /* Either the 5 seconds are up or a disconnect event was */ /* received. Reset the peer in the event the 5 seconds */ /* had run out without any significant event. */ enet_peer_reset(client_peer); fprintf(stderr, "Connection to %s failed.", remote); } } } void shutdown_network() { enet_host_destroy(host); enet_deinitialize(); } void send_game_updates(game_t *game) { size_t i; for (i = 0; i < GAME_PLAYER_COUNT; i++) { if (game->player[i].status == 0) continue; player_update_message_t msg; msg.msg_id = MESSAGE_PLAYER_UPDATE; msg.player_id = game->player[i].id; msg.x = game->player[i].x; msg.y = game->player[i].y; msg.z = game->player[i].z; msg.vx = game->player[i].vx; msg.vy = game->player[i].vy; msg.vz = game->player[i].vz; msg.points = game->player[i].points; ENetPacket * packet = enet_packet_create(&msg, sizeof(msg), 0); enet_host_broadcast(host, 0, packet); } for (i = 0; i < GAME_TEAM_COUNT; i++) { team_update_message_t msg; msg.msg_id = MESSAGE_TEAM_UPDATE; msg.team_id = game->team[i].id; msg.points = game->team[i].points; msg.wins = game->team[i].wins; ENetPacket * packet = enet_packet_create(&msg, sizeof(msg), 0); enet_host_broadcast(host, 0, packet); } enet_host_flush(host); } void dispatch_message(enet_uint8 *data, size_t length, game_t *game) { message_t *msg = (message_t *) data; switch (msg->msg_id) { case MESSAGE_PLAYER_SPAWN: { player_spawn_message_t *sm = (player_spawn_message_t *) data; team_t *team = game_team(game, sm->team_id); player_t *player = game_spawn_player_id(game, team, sm->player_id); break; } case MESSAGE_PLAYER_KILL: { player_kill_message_t *sm = (player_kill_message_t *) data; player_t *player = game_player(game, sm->player_id); player->status = 0; player->team = 0; break; } case MESSAGE_ACCEPT: { accept_message_t *am = (accept_message_t *) data; game->local_player = game_player(game, am->player_id); printf("Spwan as %d.%d\n", game->local_player->team->id, game->local_player->id); break; } case MESSAGE_PLAYER_UPDATE: { player_update_message_t *um = (player_update_message_t *) data; player_t *player = game_player(game, um->player_id); if (player != game->local_player) { player->x = um->x + um->vx * 0.0001; player->y = um->y + um->vy * 0.0001; player->z = um->z + um->vz * 0.0001; player->vx = um->vx; player->vy = um->vy; player->vz = um->vz; } else { if (fabs(um->x - player->x) < 10.0) { player->vx = um->vx + (um->x - player->x); } else { player->x = um->x; player->vx = um->vx; } if (fabs(um->y - player->y) < 10.0) { player->vy = um->vy + (um->y - player->y); } else { player->y = um->y; player->vy = um->vy; } if (fabs(um->z - player->z) < 10.0) { player->vz = um->vz + (um->z - player->z); } else { player->z = um->z; player->vz = um->vz; } } player->points = um->points; break; } case MESSAGE_POINT_UPDATE: { point_update_mesage_t *msg = (point_update_mesage_t *) data; point_t *p = &game->point[msg->point_index]; p->status = msg->status; p->x = msg->x; p->y = msg->y; p->z = msg->z; break; } case MESSAGE_PLAYER_ACCELERATE: { player_accelerate_message_t *um = (player_accelerate_message_t *) data; player_t *player = game_player(game, um->player_id); player->vx += um->x; player->vy += um->y; player->vz += um->z; break; } case MESSAGE_BOMB_DROP: { bomb_drop_meesage_t *m = (bomb_drop_meesage_t *) data; bomb_t *bomb = game_spawn_bomb(game); if (bomb == NULL) return; bomb->x = m->x + m->vx * 0.0001; bomb->y = m->y + m->vy * 0.0001; bomb->z = m->z + m->vz * 0.0001; bomb->vx = m->vx; bomb->vy = m->vy; bomb->vz = m->vz; bomb->ttl = m->ttl; if (client_peer == NULL) { ENetPacket * packet = enet_packet_create(data, length, ENET_PACKET_FLAG_RELIABLE); enet_host_broadcast(host, 0, packet); } break; } case MESSAGE_TEAM_UPDATE: { team_update_message_t *m = (team_update_message_t *) data; team_t *team = game_team(game, m->team_id); if (team == NULL) return; team->points = m->points; team->wins = m->wins; break; } }; } void service_network(game_t *game) { ENetEvent event; /* Wait up to 1000 milliseconds for an event. */ while (enet_host_service(host, &event, 0) > 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: printf("A new client connected from %x:%u.\n", event.peer->address.host, event.peer->address.port); { // bring new client up to date size_t i; for (i = 0; i < GAME_PLAYER_COUNT; i++) { if (game->player[i].status == 0) continue; // send player spawn message player_spawn_message_t spwan_msg; spwan_msg.msg_id = MESSAGE_PLAYER_SPAWN; spwan_msg.team_id = game->player[i].team->id; spwan_msg.player_id = game->player[i].id; ENetPacket * packet = enet_packet_create(&spwan_msg, sizeof(spwan_msg), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(event.peer, 0, packet); } for (i = 0; i < GAME_POINT_COUNT; i++) { if (game->point[i].status == 0) continue; point_update_mesage_t msg; msg.msg_id = MESSAGE_POINT_UPDATE; msg.point_index = i; msg.status = game->point[i].status; msg.x = game->point[i].x; msg.y = game->point[i].y; msg.z = game->point[i].z; ENetPacket * packet = enet_packet_create(&msg, sizeof(msg), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(event.peer, 0, packet); } team_t *team = game_team_with_least_players(game); player_t *player = game_spawn_player(game, team); printf("Spwan as %d.%d\n", team->id, player->id); event.peer->data = player; // send player spawn message player_spawn_message_t spwan_msg; spwan_msg.msg_id = MESSAGE_PLAYER_SPAWN; spwan_msg.team_id = team->id; spwan_msg.player_id = player->id; ENetPacket * packet = enet_packet_create(&spwan_msg, sizeof(spwan_msg), ENET_PACKET_FLAG_RELIABLE); enet_host_broadcast(host, 0, packet); // send team and player accept_message_t msg; msg.msg_id = MESSAGE_ACCEPT; msg.player_id = player->id; packet = enet_packet_create(&msg, sizeof(msg), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(event.peer, 0, packet); // send state } break; case ENET_EVENT_TYPE_RECEIVE: { dispatch_message(event.packet->data, event.packet->dataLength, game); enet_packet_destroy(event.packet); break; } case ENET_EVENT_TYPE_DISCONNECT: printf("%s disconected.\n", event.peer -> data); { /* Reset the peer's client information. */ player_t *player = (player_t *) event.peer->data; player->status = 0; player->team = 0; // send player spawn message player_kill_message_t msg; msg.msg_id = MESSAGE_PLAYER_KILL; msg.player_id = player->id; ENetPacket * packet = enet_packet_create(&msg, sizeof(msg), ENET_PACKET_FLAG_RELIABLE); enet_host_broadcast(host, 0, packet); } event.peer->data = NULL; break; } } } void send_message(uint8_t *data, size_t length, game_t *game) { if (client_peer) { ENetPacket * packet = enet_packet_create(data, length, ENET_PACKET_FLAG_RELIABLE); enet_peer_send(client_peer, 0, packet); } else { dispatch_message(data, length, game); } }