From aa0e847547240ce28d988ca539c2a079d9dd366c Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Sun, 30 Apr 2023 23:52:53 +0300 Subject: [PATCH] v1.0.0-dev --- .gitignore | 3 + README.md | 14 ++ images/logo.png | Bin 0 -> 3906 bytes server/CMakeLists.txt | 32 ++++ server/calculation.c | 275 ++++++++++++++++++++++++++++++++ server/calculation.h | 41 +++++ server/common.c | 26 +++ server/common.h | 33 ++++ server/connection.c | 334 +++++++++++++++++++++++++++++++++++++++ server/connection.h | 155 ++++++++++++++++++ server/data.c | 60 +++++++ server/games/games.c | 89 +++++++++++ server/games/games.h | 46 ++++++ server/lib/common.c | 10 ++ server/lib/common.h | 33 ++++ server/lib/enet.c | 36 +++++ server/lib/enet.h | 27 ++++ server/lib/event.c | 30 ++++ server/lib/event.h | 28 ++++ server/lib/message.c | 10 ++ server/lib/message.h | 21 +++ server/lib/timer.c | 38 +++++ server/lib/timer.h | 31 ++++ server/main.c | 41 +++++ server/objects/objects.c | 194 +++++++++++++++++++++++ server/objects/objects.h | 114 +++++++++++++ server/server.h | 19 +++ server/update.c | 164 +++++++++++++++++++ server/update.h | 31 ++++ server/users/users.c | 88 +++++++++++ server/users/users.h | 64 ++++++++ 31 files changed, 2087 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 images/logo.png create mode 100644 server/CMakeLists.txt create mode 100644 server/calculation.c create mode 100644 server/calculation.h create mode 100644 server/common.c create mode 100644 server/common.h create mode 100644 server/connection.c create mode 100644 server/connection.h create mode 100644 server/data.c create mode 100644 server/games/games.c create mode 100644 server/games/games.h create mode 100644 server/lib/common.c create mode 100644 server/lib/common.h create mode 100644 server/lib/enet.c create mode 100644 server/lib/enet.h create mode 100644 server/lib/event.c create mode 100644 server/lib/event.h create mode 100644 server/lib/message.c create mode 100644 server/lib/message.h create mode 100644 server/lib/timer.c create mode 100644 server/lib/timer.h create mode 100644 server/main.c create mode 100644 server/objects/objects.c create mode 100644 server/objects/objects.h create mode 100644 server/server.h create mode 100644 server/update.c create mode 100644 server/update.h create mode 100644 server/users/users.c create mode 100644 server/users/users.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9624c75 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +build +spaceserver diff --git a/README.md b/README.md new file mode 100644 index 0000000..a579533 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +![logo](images/logo.png) + +[SpaceShooter](https://git.zhirov.kz/games/spaceshooter) Network Game Server. + +This server is under development. Currently, the repository has been suspended since 2020. + +## Build + +```sh +mkdir build +cd build +cmake -B . -S ../server +make +``` diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..28c85a28e8bb40cd008abaff2d3c9a7513cfe5a1 GIT binary patch literal 3906 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 +#include + +/************************************************************ + * SHIP + ***********************************************************/ + +void srv_move_ship(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->ship_size; i++) + { + SERVER_SHIP* ship = objects->ships[i]; + + if(ship->active) + { + SERVER_USER* user = NULL; + + for(int j = 0; j < game->user_size; j++) + if(game->user[j] && game->user[j]->id == ship->ID) + user = game->user[j]; + + ship->y += user->command.dy * ship->speed * data->timer.elapsed_time; + if(ship->y < 0) + ship->y = 0; + else if(ship->y > game->display_height) + ship->y = game->display_height; + + ship->x += user->command.dx * ship->speed * data->timer.elapsed_time; + if(ship->x < 0) + ship->x = 0; + else if(ship->x > 900 * game->scale_factor) + ship->x = 900 * game->scale_factor; + + message->ship[i].dx = user->command.dx; + message->ship[i].dy = user->command.dy; + } + + message->ship[i].ID = ship->ID; + message->ship[i].x = ship->x; + message->ship[i].y = ship->y; + message->ship[i].lives = ship->lives; + message->ship[i].score = ship->score; + message->ship[i].active = ship->active; + } +} + + +/************************************************************ + * BULLET + ***********************************************************/ + +void srv_fire_bullet(SERVER_GAME* game) +{ + for(int i = 0; i < game->user_size; i++) + { + if(game->user[i] && game->user[i]->command.fire) + { + SERVER_OBJECTS* objects = &game->objects; + SERVER_SHIP* ship = NULL; + + for(int j = 0; j < objects->ship_size; j++) + if(objects->ships[j]->ID == game->user[i]->id) + ship = objects->ships[j]; + + if(!ship->active) continue; + + for(int j = 0; j < objects->bullet_size; j++) + { + SERVER_BULLET* bullet = objects->bullets[j]; + + if(!bullet->live && bullet->ID == game->user[i]->id) + { + bullet->x = ship->x + 17; + bullet->y = ship->y; + bullet->live = true; + + break; + } + } + } + } +} + +void srv_update_bullet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->bullet_size; i++) + { + SERVER_BULLET* bullet = objects->bullets[i]; + + if(bullet->live) + { + bullet->x += bullet->speed * data->timer.elapsed_time; + if(bullet->x > game->display_width) + bullet->live = false; + } + + message->bullet[i].ID = bullet->ID; + message->bullet[i].active = bullet->active; + message->bullet[i].live = bullet->live; + message->bullet[i].x = bullet->x; + message->bullet[i].y = bullet->y; + } +} + + +void srv_collide_bullet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->bullet_size; i++) + { + SERVER_BULLET* bullet = objects->bullets[i]; + + if(bullet->live) + { + for(int j = 0; j < objects->comet_size; j++) + { + SERVER_COMET* comet = objects->comets[j]; + + if(comet->live) + { + if(bullet->x > (comet->x - comet->boundx) && + bullet->x < (comet->x + comet->boundx) && + bullet->y > (comet->y - comet->boundy) && + bullet->y < (comet->y + comet->boundy)) + { + bullet->live = false; + comet->live = false; + + for(int k = 0; k < objects->ship_size; k++) + if(bullet->ID == objects->ships[k]->ID) + objects->ships[k]->score++; + + srv_start_explosions(game, message, bullet->x, bullet->y); + } + } + } + } + } +} + +/************************************************************ + * COMET + ***********************************************************/ + +void srv_start_comet(SERVER_GAME* game) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->comet_size; i++) + { + SERVER_COMET* comet = objects->comets[i]; + + if(!comet->live) + { + if(rand() % 500 == 0) + { + comet->live = true; + comet->x = game->display_width; + comet->y = 30 + rand() % (game->display_height - 60); + break; + } + } + } + +} + +void srv_update_comet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->comet_size; i++) + { + SERVER_COMET* comet = objects->comets[i]; + + if(comet->live) + comet->x -= comet->speed * data->timer.elapsed_time; + + message->comet[i].live = comet->live; + message->comet[i].x = comet->x; + message->comet[i].y = comet->y; + } +} + +void srv_collide_comet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->comet_size; i++) + { + SERVER_COMET* comet = objects->comets[i]; + + if(!comet->live) continue; + + for(int j = 0; j < objects->ship_size; j++) + { + SERVER_SHIP* ship = objects->ships[j]; + + if(!ship->active) continue; + + if((comet->x - comet->boundx) < (ship->x + ship->boundx) && + (comet->x + comet->boundx) > (ship->x - ship->boundx) && + (comet->y - comet->boundy) < (ship->y + ship->boundy) && + (comet->y + comet->boundy) > (ship->y - ship->boundy)) + { + ship->lives--; + comet->live = false; + + srv_start_explosions(game, message, ship->x, ship->y); + } + else if(comet->x < 0) + { + comet->live = false; + ship->lives--; + } + + if(ship->lives <= 0) + ship->active = false; + } + } +} + +/************************************************************ + * EXPLOSION + ***********************************************************/ + +static void srv_start_explosions(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message, int x, int y) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->explosion_size; i++) + { + SERVER_EXPLOSION* explosion = objects->explosions[i]; + + if(!explosion->live) + { + explosion->live = true; + explosion->x = x; + explosion->y = y; + + message->explosion[i].live = explosion->live; + message->explosion[i].x = explosion->x; + message->explosion[i].y = explosion->y; + + break; + } + } +} + +void srv_update_explosions(SERVER_DATA* data, SERVER_GAME* game) +{ + SERVER_OBJECTS* objects = &game->objects; + + for(int i = 0; i < objects->explosion_size; i++) + { + SERVER_EXPLOSION* explosion = objects->explosions[i]; + + if(explosion->live) + { + explosion->lifetime += data->timer.elapsed_time; + + if(explosion->lifetime >= 1.5) + { + explosion->lifetime = 0; + explosion->live = false; + } + } + } +} + diff --git a/server/calculation.h b/server/calculation.h new file mode 100644 index 0000000..f4d088f --- /dev/null +++ b/server/calculation.h @@ -0,0 +1,41 @@ +/* + * File: calculation.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.26 + */ + +#ifndef server_calculation +#define server_calculation + +#include "games.h" +#include "common.h" +#include "connection.h" + +/************************************************************ + * SHIP + ***********************************************************/ +void srv_move_ship(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message); +/************************************************************ + * BULLET + ***********************************************************/ +void srv_fire_bullet(SERVER_GAME* game); +void srv_update_bullet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message); +void srv_collide_bullet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message); +/************************************************************ + * COMET + ***********************************************************/ +void srv_start_comet(SERVER_GAME* game); +void srv_update_comet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message); +void srv_collide_comet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message); +/************************************************************ + * EXPLOSION + ***********************************************************/ +static void srv_start_explosions(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message, int x, int y); +void srv_update_explosions(SERVER_DATA* data, SERVER_GAME* game); + +#endif + + + diff --git a/server/common.c b/server/common.c new file mode 100644 index 0000000..250b86d --- /dev/null +++ b/server/common.c @@ -0,0 +1,26 @@ +#define _DEFAULT_SOURCE +#include +#include + +#include "common.h" +#include "lib/message.h" + +void srv_catch_signal(int signal, void (*handler)(int)) +{ + struct sigaction action; + action.sa_handler = handler; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + show_message_error(sigaction(signal, &action, NULL) == 0, "Failed to register signal"); +} + +void srv_stop_server(int signal) +{ + SERVER_DATA* data = srv_get_server_data(NULL); + + data->done = true; + + puts("--------------------------------------------------"); + puts("Останавливаю сервер! Без паники!"); +} diff --git a/server/common.h b/server/common.h new file mode 100644 index 0000000..bc0c54a --- /dev/null +++ b/server/common.h @@ -0,0 +1,33 @@ +/* + * File: common.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.14 + */ + +#ifndef server_data +#define server_data + +#include "lib/common.h" +#include "users.h" +#include "games.h" + +typedef struct srv_data +{ + SERVER_ENET enet; + SERVER_TIMER timer; + SERVER_EVENT event; + SERVER_USERS users; + SERVER_GAMES games; + bool done; +} SERVER_DATA; + +SERVER_DATA* srv_create_data(SERVER_DATA* data, SERVER_PARAMETRS parametrs); +void srv_destroy_data(SERVER_DATA* data); +SERVER_DATA* srv_get_server_data(SERVER_DATA* data); + +void srv_catch_signal(int signal, void (*handler)(int)); +void srv_stop_server(int signal); + +#endif diff --git a/server/connection.c b/server/connection.c new file mode 100644 index 0000000..c360fd0 --- /dev/null +++ b/server/connection.c @@ -0,0 +1,334 @@ +#include "connection.h" +#include +#include "message.h" + +/************************************************************ + * CONNECTION HANDLING + ***********************************************************/ + +void srv_send_receive(SERVER_DATA* data) +{ + ENetPacket *packet; + ENetEvent event; + SERVER_MESSAGE_NONE* message_none; + SERVER_MESSAGE_JOINGAME* message_list; + SERVER_MESSAGE_SENDPARTY* message_party; + SERVER_MESSAGE_GAME* message_game; + + while (enet_host_service(data->enet.server, &event, 0) > 0) + { + switch(event.type) + { + case ENET_EVENT_TYPE_NONE: + break; + case ENET_EVENT_TYPE_CONNECT: + printf("Сервер: новый пользователь из %x:%hu\n", event.peer->address.host, event.peer->address.port); + + SERVER_USER* user = srv_get_free_user(&data->users); + show_message_error(user, "Failed to allocate free game"); + // Отсоединить пользователя +// enet_peer_disconnect_now(event.peer, 0); + user->peer = event.peer; // сохранить пир в пользователе + + event.peer->data = malloc(sizeof(int)); + *(int*)event.peer->data = user->id; + printf("Сервер: пользователь присоединён #%d\n", user->id); + break; + case ENET_EVENT_TYPE_RECEIVE: + { + int user_id = *(int*)event.peer->data; + + switch(data->users.user[user_id]->state) + { + case STATE_NONE: + message_none = (SERVER_MESSAGE_NONE*)event.packet->data; + srv_readmessage_none(data, user_id, message_none); + break; + case STATE_LIST: + message_list = (SERVER_MESSAGE_JOINGAME*)event.packet->data; + srv_readmessage_list(data, user_id, message_list); + break; + case STATE_PARTY: + message_party = (SERVER_MESSAGE_SENDPARTY*)event.packet->data; + srv_readmessage_party(data, user_id, message_party); + break; + case STATE_GAME: + message_game = (SERVER_MESSAGE_GAME*)event.packet->data; + srv_readmessage_game(data, user_id, message_game); + break; + } + + enet_packet_destroy(event.packet); + break; + } + case ENET_EVENT_TYPE_DISCONNECT: + { + int user_id = *(int*)event.peer->data; + srv_removing_from_game(data, data->users.user[user_id]); + srv_clear_user(data->users.user[user_id]); + + printf("Сервер: пользователь #%d был отсоединён\n", user_id); + // сообщить пользователям об отсоединении клиента + + free(event.peer->data); + event.peer->data = NULL; + break; + } + } + } +} + +static void srv_readmessage_none(SERVER_DATA* data, int user_id, SERVER_MESSAGE_NONE* message) +{ + SERVER_USER* user = data->users.user[user_id]; + + user->display_height = message->display_height; + user->display_width = message->display_width; + user->scale_factor = message->scale_factor; + user->is_creator = message->is_creator; + user->is_ready = message->is_ready; + strncpy(user->nickname, message->nickname, 40); + + if(message->is_creator) + srv_create_new_game(data, user, message->game_name); + + srv_change_state(data, user_id, message->state); +} + +static void srv_readmessage_list(SERVER_DATA* data, int user_id, SERVER_MESSAGE_JOINGAME* message) +{ + SERVER_USER* user = data->users.user[user_id]; + SERVER_GAME* game = data->games.game[message->id]; + + ENetPacket *packet; + SERVER_MESSAGE_LIST answer; + + if(game->count_connected < 3) + { + game->count_connected++; + + srv_change_state(data, user_id, message->state); + + user->game_id = message->id; + user->in_game = true; + + for(int i = 0; i < game->user_size; i++) + if(!game->user[i]) + { + game->user[i] = user; + + break; + } + + answer.state = message->state; + + packet = enet_packet_create(&answer, sizeof(answer), ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(user->peer, 0, packet); + } +} + +static void srv_readmessage_party(SERVER_DATA* data, int user_id, SERVER_MESSAGE_SENDPARTY* message) +{ + SERVER_USER* user = data->users.user[user_id]; + + switch(message->state) + { + case STATE_LIST: + if(message->kick_user) + user = data->users.user[message->user_id]; + + srv_removing_from_game(data, user); + user->state = message->state; + user->in_game = false; + user->is_ready = false; + user->game_id = -1; + user->is_creator = false; + + srv_send_change_state(user, message->state); + break; + case STATE_PARTY: + user->is_ready = message->is_ready; + break; + case STATE_GAME: + srv_start_game(data, user); + break; + } +} + +static void srv_readmessage_game(SERVER_DATA* data, int user_id, SERVER_MESSAGE_GAME* message) +{ + SERVER_USER* user = data->users.user[user_id]; + + switch(message->state) + { + case STATE_GAME: + { + user->command.dx = message->dx; + user->command.dy = message->dy; + user->command.fire = message->fire; + + break; + } + } +} + +static void srv_change_state(SERVER_DATA* data, int user_id, SERVER_STATE state) +{ + SERVER_USER* user = data->users.user[user_id]; + + user->state = state; +} + +static void srv_create_new_game(SERVER_DATA* data, SERVER_USER* user, const char* game_name) +{ + // Creating a new game and placing the user there + SERVER_GAME* game = srv_get_free_game(&data->games); + // Отправить сообщение в случае, если нет места для создания новой игры + show_message_error(game, "Failed to allocate free game"); + + user->game_id = game->id; + user->in_game = true; + game->user[0] = user; + game->count_connected++; + strncpy(game->game_name, game_name, 40); +} + +static void srv_removing_from_game(SERVER_DATA* data, SERVER_USER* user) +{ + if(user->in_game) + { + SERVER_GAME* game = data->games.game[user->game_id]; + + for(int i = 0; i < game->user_size; i++) + if(game->user[i] && game->user[i]->id == user->id) + { + game->user[i] = NULL; + --game->count_connected; + + if(game->game_started) + { + for(int j = 0; j < game->objects.ship_size; j++) + if(user->id == game->objects.ships[j]->ID) + game->objects.ships[j]->active = false; + + for(int j = 0; j < game->objects.bullet_size; j++) + if(user->id == game->objects.bullets[j]->ID) + game->objects.bullets[j]->active = false; + } + + if(game->count_connected == 0) + { + if(game->game_started) + srv_destroy_objects(&game->objects); + + srv_clear_games(game); + } + else if(user->is_creator) + { + for(int j = 0; j < game->user_size; j++) + if(game->user[j]) + { + game->user[j]->is_creator = true; + game->user[j]->is_ready = true; + + break; + } + } + + break; + } + } +} + +static void srv_start_game(SERVER_DATA* data, SERVER_USER* user) +{ + if(user->in_game) + { + bool users_ready = true; + + SERVER_GAME* game = data->games.game[user->game_id]; + + for(int i = 0; i < game->user_size; i++) + if(game->user[i]) + if(!game->user[i]->is_ready) + { + users_ready = false; + break; + } + + if(users_ready) + { + game->game_started = true; + + srv_init_objects(game); + + for(int i = 0; i < game->user_size; i++) + if(game->user[i]) + { + game->user[i]->command.dx = 0; + game->user[i]->command.dy = 0; + game->user[i]->command.fire = false; + + game->user[i]->state = STATE_GAME; + + srv_send_change_state(game->user[i], STATE_GAME); + } + } + } +} + +static void srv_send_change_state(SERVER_USER* user, SERVER_STATE state) +{ + ENetPacket *packet; + SERVER_MESSAGE_PARTY message; + + message.state = state; + packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(user->peer, 0, packet); +} + + +static void srv_init_objects(SERVER_GAME* game) +{ + SERVER_OBJECTS* objects = &game->objects; + int count_users = game->count_connected; + + int start_position = 0; + int position_ratio = 1; // part user position + bool start_ratio = false; + int iterator = 0; + + srv_create_objects(objects, count_users, 5 * count_users, 15, 5 * count_users); + + for(int i = 0; i < game->user_size; i++) + if(game->user[i] && game->user[i]->is_creator) + { + game->display_width = game->user[i]->display_width; + game->display_height = game->user[i]->display_height; + game->scale_factor = game->user[i]->scale_factor; + break; + } + + start_position = game->display_height / (count_users * 2); + + for(int i = 0; i < game->user_size; i++) + if(game->user[i]) + { + if(start_ratio) + position_ratio += 2; + else + start_ratio = true; + + srv_init_ships(objects, iterator, game->user[i]->id, 3, 1, 1, 10, 12, 0, 0, 50, 41, 46, 3, 3, 0, 250, 20, start_position * position_ratio); + + for(int j = iterator++ * 5; j < iterator * 5; j++) + srv_init_bullets(objects, j, game->user[i]->id, 500, 0, 0); + } + + for(int i = 0; i < objects->comet_size; i++) + srv_init_comets(objects, i, 0, 21, rand() % 2 ? 1 : -1, 35, 35, 0, 0, 2, 96, 96, 143, 250, 0, 0); + + for(int i = 0; i < objects->explosion_size; i++) + srv_init_explosions(objects, i, 8, 1, 0, 0, 1, 128, 128, 31, 0, 0); +} + diff --git a/server/connection.h b/server/connection.h new file mode 100644 index 0000000..2bd157d --- /dev/null +++ b/server/connection.h @@ -0,0 +1,155 @@ +/* + * File: connection.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.14 + */ + +#ifndef server_connection +#define server_connection + +#include "common.h" + +typedef struct srv_usercommand +{ + int dx; + int dy; + bool fire; +} SERVER_USER_COMMAND; + +typedef struct srv_userdata +{ + int id; + char nickname[40]; + bool is_ready; + SERVER_USER_COMMAND command; +} SERVER_USER_DATA; + +typedef struct srv_gamedata +{ + int id; + char game_name[40]; + int count_connected; +} SERVER_GAME_DATA; + +typedef struct srv_message_none +{ + int display_width; + int display_height; + float scale_factor; + SERVER_STATE state; + char game_name[40]; + char nickname[40]; + bool is_creator; + bool is_ready; +} SERVER_MESSAGE_NONE; + +typedef struct srv_message_list +{ + SERVER_GAME_DATA games[3]; + SERVER_STATE state; + int count_game; +} SERVER_MESSAGE_LIST; + +typedef struct srv_message_party +{ + int game_id; + int user_id; + SERVER_USER_DATA users[3]; + char game_name[40]; + int count_connected; + bool game_started; + bool active; + bool is_creator; + bool is_ready; + SERVER_STATE state; +} SERVER_MESSAGE_PARTY; + +typedef struct srv_message_sendparty +{ + SERVER_STATE state; + bool is_creator; + bool is_ready; + bool kick_user; + int user_id; +} SERVER_MESSAGE_SENDPARTY; + +typedef struct srv_message_joingame +{ + int id; + SERVER_STATE state; +} SERVER_MESSAGE_JOINGAME; + +typedef struct srv_message_game +{ + int dx; + int dy; + bool fire; + SERVER_STATE state; +} SERVER_MESSAGE_GAME; + +// GAME + +typedef struct srv_update_ship +{ + int ID; + int x; + int y; + int dx; + int dy; + int lives; + int score; + bool active; +} SERVER_UPDATE_SHIP; + +typedef struct srv_update_bullet +{ + int ID; + int x; + int y; + bool live; + bool active; +} SERVER_UPDATE_BULLET; + +typedef struct srv_update_comet +{ + int x; + int y; + bool live; +} SERVER_UPDATE_COMET; + +typedef struct srv_update_explosion +{ + int x; + int y; + bool live; +} SERVER_UPDATE_EXPLOSION; + +typedef struct srv_message_update +{ + SERVER_UPDATE_SHIP ship[3]; + SERVER_UPDATE_BULLET bullet[15]; + SERVER_UPDATE_COMET comet[15]; + SERVER_UPDATE_EXPLOSION explosion[15]; +} SERVER_MESSAGE_UPDATE; + +void srv_send_receive(SERVER_DATA* data); +static void srv_readmessage_none(SERVER_DATA* data, int user_id, SERVER_MESSAGE_NONE* message); +static void srv_readmessage_list(SERVER_DATA* data, int user_id, SERVER_MESSAGE_JOINGAME* message); +static void srv_readmessage_party(SERVER_DATA* data, int user_id, SERVER_MESSAGE_SENDPARTY* message); +static void srv_readmessage_game(SERVER_DATA* data, int user_id, SERVER_MESSAGE_GAME* message); +static void srv_change_state(SERVER_DATA* data, int user_id, SERVER_STATE state); + +static void srv_create_new_game(SERVER_DATA* data, SERVER_USER* user, const char* game_name); +static void srv_removing_from_game(SERVER_DATA* data, SERVER_USER* user); +static void srv_start_game(SERVER_DATA* data, SERVER_USER* user); + +static void srv_send_change_state(SERVER_USER* user, SERVER_STATE state); + +static void srv_init_objects(SERVER_GAME* game); + +#endif + + + diff --git a/server/data.c b/server/data.c new file mode 100644 index 0000000..7118367 --- /dev/null +++ b/server/data.c @@ -0,0 +1,60 @@ +#include + +#include "common.h" +#include "message.h" + +SERVER_DATA* srv_create_data(SERVER_DATA* data, SERVER_PARAMETRS parametrs) +{ + if(!data) + { + data = (SERVER_DATA*)malloc(sizeof(SERVER_DATA)); + show_message_error(data, "Failed to allocate space for SERVER_DATA"); + } + + srv_create_enet(&data->enet, parametrs.port); + puts("Enet создан!"); + srv_create_timer(&data->timer, parametrs.FPS); + puts("Таймер загружен. Готов к запуску!"); + srv_create_event(&data->event, &data->timer); + puts("События ждут указаний!"); + srv_create_users(&data->users, parametrs.users); + puts("Место для игроков выделено!"); + srv_create_games(&data->games, parametrs.games); + puts("Место для игр выделено!"); + puts("Все системы в норме! Запускаю сервер!"); + puts("--------------------------------------------------"); + + data->done = false; + + srv_get_server_data(data); + // Server Stop Event Logging + srv_catch_signal(SIGINT, srv_stop_server); + + return data; +} + +void srv_destroy_data(SERVER_DATA* data) +{ + srv_destroy_enet(&data->enet); + puts("Почистил Enet!"); + srv_destroy_event(&data->event); + puts("С событиями тоже разобрался!"); + srv_destroy_timer(&data->timer); + puts("Кто говорил, что временем нельзя управлять? Таймер остановлен!"); + srv_destroy_users(&data->users); + puts("Освободил выделенное место для игроков!"); + srv_destroy_games(&data->games); + puts("Освободил выделенное место для игр!"); + free(data); + puts("Сервер остановлен! Порядок!"); +} + +SERVER_DATA* srv_get_server_data(SERVER_DATA* data) +{ + static SERVER_DATA* server; + + if(data) + server = data; + + return server; +} diff --git a/server/games/games.c b/server/games/games.c new file mode 100644 index 0000000..80ff138 --- /dev/null +++ b/server/games/games.c @@ -0,0 +1,89 @@ +#include "games.h" +#include "message.h" + +SERVER_GAMES* srv_create_games(SERVER_GAMES* games, int game_size) +{ + if(!games) + { + games = (SERVER_GAMES*)malloc(sizeof(SERVER_GAMES)); + show_message_error(games, "Failed to allocate space for SERVER_GAMES"); + } + + games->game_size = game_size; + + if(game_size) + { + games->game = (SERVER_GAME**)malloc(sizeof(SERVER_GAME*) * game_size); + show_message_error(games->game, "Failed to allocate space for SERVER_GAME collection"); + + for(int i = 0; i < game_size; i++) + { + games->game[i] = (SERVER_GAME*)malloc(sizeof(SERVER_GAME)); + show_message_error(games->game[i], "Failed to allocate space for SERVER_USER"); + + games->game[i]->user = (SERVER_USER**)malloc(sizeof(SERVER_USER*) * 3); + show_message_error(games->game[i]->user, "Failed to allocate space for SERVER_USER collection"); + + games->game[i]->active = false; + games->game[i]->game_started = false; + games->game[i]->count_connected = 0; + games->game[i]->user_size = 3; + games->game[i]->game_name[0] = '\0'; + games->game[i]->display_width = 0; + games->game[i]->display_height = 0; + games->game[i]->scale_factor = 0; + + for(int j = 0; j < 3; j++) + games->game[i]->user[j] = NULL; + } + } + else + games->game = NULL; + + return games; +} + +void srv_free_games(SERVER_GAMES* games) +{ + srv_destroy_games(games); + free(games); +} + +void srv_destroy_games(SERVER_GAMES* games) +{ + for(int i = 0; i < games->game_size; i++) + { + free(games->game[i]->user); + free(games->game[i]); + } + + free(games->game); +} + +// return pointer +SERVER_GAME* srv_get_free_game(SERVER_GAMES* games) +{ + for(int i = 0; i < games->game_size; i++) + if(!games->game[i]->active) + { + games->game[i]->active = true; + games->game[i]->id = i; + return games->game[i]; + } + + return NULL; +} + +void srv_clear_games(SERVER_GAME* game) +{ + for(int i = 0; i < game->user_size; i++) + game->user[i] = NULL; + + game->active = false; + game->game_started = false; + game->count_connected = 0; + game->game_name[0] = '\0'; + game->display_width = 0; + game->display_height = 0; + game->scale_factor = 0; +} diff --git a/server/games/games.h b/server/games/games.h new file mode 100644 index 0000000..78978b8 --- /dev/null +++ b/server/games/games.h @@ -0,0 +1,46 @@ +/* + * File: games.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.15 + */ + +#ifndef server_games +#define server_games + +#include "users.h" +#include "objects.h" + +typedef struct srv_game +{ + int id; + int display_width; + int display_height; + float scale_factor; + char game_name[40]; + SERVER_USER** user; + int user_size; + int count_connected; + bool game_started; + bool active; + SERVER_OBJECTS objects; +} SERVER_GAME; + +typedef struct srv_games +{ + SERVER_GAME** game; + int game_size; +} SERVER_GAMES; + +SERVER_GAMES* srv_create_games(SERVER_GAMES* games, int game_size); +void srv_free_games(SERVER_GAMES* games); +void srv_destroy_games(SERVER_GAMES* games); + +void srv_clear_games(SERVER_GAME* game); +SERVER_GAME* srv_get_free_game(SERVER_GAMES* games); + +#endif + + + diff --git a/server/lib/common.c b/server/lib/common.c new file mode 100644 index 0000000..9ecdf1c --- /dev/null +++ b/server/lib/common.c @@ -0,0 +1,10 @@ +#include + +#include "common.h" +#include "message.h" + +void srv_load_resources() +{ + show_message_error(al_init(), "Failed to initialize Allegro"); + show_message_error(srv_check_init_enet(enet_initialize()), "Failed to enet initialize"); +} diff --git a/server/lib/common.h b/server/lib/common.h new file mode 100644 index 0000000..7e066be --- /dev/null +++ b/server/lib/common.h @@ -0,0 +1,33 @@ +/* + * File: common.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.13 + */ + +#ifndef server_common +#define server_common + +#include "enet.h" +#include "timer.h" +#include "event.h" + +typedef struct srv_resource +{ + SERVER_ENET enet; + SERVER_TIMER timer; + SERVER_EVENT event; +} SERVER_RESOURCE; + +typedef struct cl_parametrs +{ + int port; + int FPS; + int users; + int games; +} SERVER_PARAMETRS; + +void srv_load_resources(); + +#endif diff --git a/server/lib/enet.c b/server/lib/enet.c new file mode 100644 index 0000000..fe6c017 --- /dev/null +++ b/server/lib/enet.c @@ -0,0 +1,36 @@ +#include "enet.h" +#include "message.h" + +SERVER_ENET* srv_create_enet(SERVER_ENET* enet, int port) +{ + if(!enet) + { + enet = (SERVER_ENET*)malloc(sizeof(SERVER_ENET)); + show_message_error(enet, "Failed to allocate space for SERVER_ENET"); + } + + enet->address.host = ENET_HOST_ANY; + enet->address.port = port; + + enet->server = enet_host_create(&enet->address, 32, 2, 0, 0); + show_message_error(enet->server, "Failed to enet host create"); + + return enet; +} + +void srv_free_enet(SERVER_ENET* enet) +{ + srv_destroy_enet(enet); + free(enet); +} + +void srv_destroy_enet(SERVER_ENET* enet) +{ + enet_host_destroy(enet->server); + enet_deinitialize(); +} + +bool srv_check_init_enet(int result) +{ + return result == 0; +} diff --git a/server/lib/enet.h b/server/lib/enet.h new file mode 100644 index 0000000..4a2cda7 --- /dev/null +++ b/server/lib/enet.h @@ -0,0 +1,27 @@ +/* + * File: enet.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.13 + */ + +#ifndef server_enet +#define server_enet + +#include +#include + +typedef struct srv_enet +{ + ENetHost* server; + ENetAddress address; +} SERVER_ENET; + +SERVER_ENET* srv_create_enet(SERVER_ENET* enet, int port); +void srv_free_enet(SERVER_ENET* enet); +void srv_destroy_enet(SERVER_ENET* enet); + +bool srv_check_init_enet(int result); + +#endif diff --git a/server/lib/event.c b/server/lib/event.c new file mode 100644 index 0000000..17fa7ae --- /dev/null +++ b/server/lib/event.c @@ -0,0 +1,30 @@ +#include "event.h" +#include "message.h" + +SERVER_EVENT* srv_create_event(SERVER_EVENT* event, SERVER_TIMER* timer) +{ + if(!event) + { + event = (SERVER_EVENT*)malloc(sizeof(SERVER_EVENT)); + show_message_error(event, "Failed to allocate space for SERVER_EVENT"); + } + + event->queue = al_create_event_queue(); + show_message_error(event->queue, "Failed to create Allegro event"); + + if(timer) + al_register_event_source(event->queue, al_get_timer_event_source(timer->al_timer)); + + return event; +} + +void srv_free_event(SERVER_EVENT* event) +{ + srv_destroy_event(event); + free(event); +}; + +void srv_destroy_event(SERVER_EVENT* event) +{ + al_destroy_event_queue(event->queue); +} diff --git a/server/lib/event.h b/server/lib/event.h new file mode 100644 index 0000000..683ea2b --- /dev/null +++ b/server/lib/event.h @@ -0,0 +1,28 @@ +/* + * File: event.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.13 + */ + +#ifndef server_event +#define server_event + +#include +#include "timer.h" + +typedef struct srv_event +{ + ALLEGRO_EVENT_QUEUE* queue; + ALLEGRO_EVENT current; +} SERVER_EVENT; + +SERVER_EVENT* srv_create_event(SERVER_EVENT* event, SERVER_TIMER* timer); +void srv_free_event(SERVER_EVENT* event); +void srv_destroy_event(SERVER_EVENT* event); + +#endif + + + diff --git a/server/lib/message.c b/server/lib/message.c new file mode 100644 index 0000000..218d1af --- /dev/null +++ b/server/lib/message.c @@ -0,0 +1,10 @@ +#include "message.h" + +void show_message_error(bool result, const char* message) +{ + if(!result) + { + printf("%s\n", message); + exit(EXIT_FAILURE); + } +} diff --git a/server/lib/message.h b/server/lib/message.h new file mode 100644 index 0000000..8cf8524 --- /dev/null +++ b/server/lib/message.h @@ -0,0 +1,21 @@ +/* + * File: message.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.13 + */ + +#ifndef server_message +#define server_message + +#include +#include +#include + +void show_message_error(bool result, const char* message); + +#endif + + + diff --git a/server/lib/timer.c b/server/lib/timer.c new file mode 100644 index 0000000..e602440 --- /dev/null +++ b/server/lib/timer.c @@ -0,0 +1,38 @@ +#include "timer.h" +#include "message.h" + +SERVER_TIMER* srv_create_timer(SERVER_TIMER* timer, int FPS) +{ + if(!timer) + { + timer = (SERVER_TIMER*)malloc(sizeof(SERVER_TIMER)); + show_message_error(timer, "Failed to allocate space for SERVER_TIMER"); + } + + timer->al_timer = al_create_timer(1.0 / FPS); + show_message_error(timer->al_timer, "Failed to create Allegro timer"); + + timer->last_time = 0.0; + timer->current_time = 0.0; + timer->elapsed_time = 0.0; + + return timer; +} + +void srv_free_timer(SERVER_TIMER* timer) +{ + srv_destroy_timer(timer); + free(timer); +} + +void srv_destroy_timer(SERVER_TIMER* timer) +{ + al_destroy_timer(timer->al_timer); +} + +void srv_update_time(SERVER_TIMER* timer) +{ + timer->last_time = timer->current_time; + timer->current_time = al_get_time(); + timer->elapsed_time = timer->current_time - timer->last_time; +} diff --git a/server/lib/timer.h b/server/lib/timer.h new file mode 100644 index 0000000..1a9cb29 --- /dev/null +++ b/server/lib/timer.h @@ -0,0 +1,31 @@ +/* + * File: timer.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.13 + */ + +#ifndef server_timer +#define server_timer + +#include + +typedef struct srv_timer +{ + ALLEGRO_TIMER* al_timer; + double last_time; + double current_time; + double elapsed_time; +} SERVER_TIMER; + +SERVER_TIMER* srv_create_timer(SERVER_TIMER* timer, int FPS); + +void srv_free_timer(SERVER_TIMER* timer); +void srv_destroy_timer(SERVER_TIMER* timer); +void srv_update_time(SERVER_TIMER* timer); + +#endif + + + diff --git a/server/main.c b/server/main.c new file mode 100644 index 0000000..4728866 --- /dev/null +++ b/server/main.c @@ -0,0 +1,41 @@ +#include +#include "server.h" + +int main(int argc, char** argv) +{ + srv_load_resources(); + + SERVER_PARAMETRS parametrs = + { + .port = 9234, + .FPS = 60, + .users = 30, + .games = 3 + }; + + SERVER_DATA* data = srv_create_data(NULL, parametrs); + + al_start_timer(data->timer.al_timer); + data->timer.current_time = al_current_time(); + + srand(time(NULL)); + + while(!data->done) + { + al_wait_for_event(data->event.queue, &data->event.current); + + if(data->event.current.type == ALLEGRO_EVENT_TIMER) + { + srv_update_time(&data->timer); + // возможно тут нужно сделать потоки + srv_game_update(data); + srv_client_update(data); + + srv_send_receive(data); + } + } + + srv_destroy_data(data); + + return EXIT_SUCCESS; +} diff --git a/server/objects/objects.c b/server/objects/objects.c new file mode 100644 index 0000000..7750d57 --- /dev/null +++ b/server/objects/objects.c @@ -0,0 +1,194 @@ +#include "objects.h" +#include "message.h" + +SERVER_OBJECTS* srv_create_objects(SERVER_OBJECTS* objects, int ship_size, int bullet_size, int comet_size, int explosion_size) +{ + if(!objects) + { + SERVER_OBJECTS* objects = (SERVER_OBJECTS*)malloc(sizeof(SERVER_OBJECTS)); + show_message_error(objects, "Failed to allocate space for SERVER_OBJECTS"); + } + + objects->ship_size = ship_size; + objects->bullet_size = bullet_size; + objects->comet_size = comet_size; + objects->explosion_size = explosion_size; + + objects->ships = srv_create_ships(ship_size); + objects->bullets = srv_create_bullets(bullet_size); + objects->comets = srv_create_comets(comet_size); + objects->explosions = srv_create_explosions(explosion_size); + + return objects; +} + +void srv_free_objects(SERVER_OBJECTS* objects) +{ + srv_destroy_objects(objects); + free(objects); +} + +void srv_destroy_objects(SERVER_OBJECTS* objects) +{ + if(objects->ship_size > 0) + { + for(int i = 0; i < objects->ship_size; i++) + free(objects->ships[i]); + free(objects->ships); + } + + if(objects->bullet_size > 0) + { + for(int i = 0; i < objects->bullet_size; i++) + free(objects->bullets[i]); + free(objects->bullets); + } + + if(objects->comet_size > 0) + { + for(int i = 0; i < objects->comet_size; i++) + free(objects->comets[i]); + free(objects->comets); + } + + if(objects->explosion_size > 0) + { + for(int i = 0; i < objects->explosion_size; i++) + free(objects->explosions[i]); + free(objects->explosions); + } +} + +static SERVER_SHIP** srv_create_ships(int size) +{ + SERVER_SHIP** ships = (SERVER_SHIP**)malloc(sizeof(SERVER_SHIP*) * size); + show_message_error(ships, "Failed to allocate space for SERVER_SHIP collection"); + + for(int i = 0; i < size; i++) + { + ships[i] = (SERVER_SHIP*)malloc(sizeof(SERVER_SHIP)); + show_message_error(ships[i], "Failed to allocate space for SERVER_SHIP"); + } + + return ships; +} + +static SERVER_BULLET** srv_create_bullets(int size) +{ + SERVER_BULLET** bullets = (SERVER_BULLET**)malloc(sizeof(SERVER_BULLET*) * size); + show_message_error(bullets, "Failed to allocate space for SERVER_BULLET collection"); + + for(int i = 0; i < size; i++) + { + bullets[i] = (SERVER_BULLET*)malloc(sizeof(SERVER_BULLET)); + show_message_error(bullets[i], "Failed to allocate space for SERVER_BULLET"); + } + + return bullets; +} + +static SERVER_COMET** srv_create_comets(int size) +{ + SERVER_COMET** comets = (SERVER_COMET**)malloc(sizeof(SERVER_COMET*) * size); + show_message_error(comets, "Failed to allocate space for SERVER_COMET collection"); + + for(int i = 0; i < size; i++) + { + comets[i] = (SERVER_COMET*)malloc(sizeof(SERVER_COMET)); + show_message_error(comets[i], "Failed to allocate space for SERVER_COMET"); + } + + return comets; +} + +static SERVER_EXPLOSION** srv_create_explosions(int size) +{ + SERVER_EXPLOSION** explosions = (SERVER_EXPLOSION**)malloc(sizeof(SERVER_EXPLOSION*) * size); + show_message_error(explosions, "Failed to allocate space for SERVER_EXPLOSION collection"); + + for(int i = 0; i < size; i++) + { + explosions[i] = (SERVER_EXPLOSION*)malloc(sizeof(SERVER_EXPLOSION)); + show_message_error(explosions[i], "Failed to allocate space for SERVER_EXPLOSION"); + } + + return explosions; +} + +void srv_init_ships(SERVER_OBJECTS* objects, int key_ship, int ID, int animation_columns, int animation_direction, int animation_row, int boundx, int boundy, int cur_frame, + int frame_count, int frame_delay, int frame_height, int frame_width, int lives, int max_frame, int score, int speed, int x, int y) +{ + SERVER_SHIP* ship = objects->ships[key_ship]; + + ship->ID = ID; + ship->animation_columns = animation_columns; + ship->animation_direction = animation_direction; + ship->animation_row = animation_row; + ship->boundx = boundx; + ship->boundy = boundy; + ship->cur_frame = cur_frame; + ship->frame_count = frame_count; + ship->frame_delay = frame_delay; + ship->frame_height = frame_height; + ship->frame_width = frame_width; + ship->lives = lives; + ship->max_frame = max_frame; + ship->score = score; + ship->speed = speed; + ship->x = x; + ship->y = y; + ship->active = true; +} + +void srv_init_bullets(SERVER_OBJECTS* objects, int key_bullet, int ID, int speed, int x, int y) +{ + SERVER_BULLET* bullet = objects->bullets[key_bullet]; + + bullet->ID = ID; + bullet->live = false; + bullet->speed = speed; + bullet->x = x; + bullet->y = y; + bullet->active = true; +} + +void srv_init_comets(SERVER_OBJECTS* objects, int key_comet, int ID, int animation_columns, int animation_direction, int boundx, int boundy, int cur_frame, + int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int speed, int x, int y) +{ + SERVER_COMET* comet = objects->comets[key_comet]; + + comet->ID = ID; + comet->animation_columns = animation_columns; + comet->animation_direction = animation_direction; + comet->boundx = boundx; + comet->boundy = boundy; + comet->cur_frame = cur_frame; + comet->frame_count = frame_count; + comet->frame_delay = frame_delay; + comet->frame_height = frame_height; + comet->frame_width = frame_width; + comet->max_frame = max_frame; + comet->speed = speed; + comet->live = false; + comet->x = x; + comet->y = y; +} + +void srv_init_explosions(SERVER_OBJECTS* objects, int key_explosion, int animation_columns, int animation_direction, int cur_frame, + int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int x, int y) +{ + SERVER_EXPLOSION* explosion = objects->explosions[key_explosion]; + + explosion->animation_columns = animation_columns; + explosion->animation_direction = animation_direction; + explosion->cur_frame = cur_frame; + explosion->frame_count = frame_count; + explosion->frame_delay = frame_delay; + explosion->frame_height = frame_height; + explosion->frame_width = frame_width; + explosion->live = false; + explosion->max_frame = max_frame; + explosion->x = x; + explosion->y = y; + explosion->lifetime = 0; +} diff --git a/server/objects/objects.h b/server/objects/objects.h new file mode 100644 index 0000000..0f17fdb --- /dev/null +++ b/server/objects/objects.h @@ -0,0 +1,114 @@ +/* + * File: objects.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.03 + */ + +#ifndef server_objects +#define server_objects + +#include + +typedef struct srv_ship +{ + int ID; + int x; + int y; + int lives; + int speed; + int boundx; + int boundy; + int score; + bool active; + + int max_frame; + int cur_frame; + int frame_count; + int frame_delay; + int frame_width; + int frame_height; + int animation_columns; + int animation_direction; + + int animation_row; +} SERVER_SHIP; + +typedef struct srv_bullet +{ + int ID; + int x; + int y; + bool live; + int speed; + bool active; +} SERVER_BULLET; + +typedef struct srv_comet +{ + int ID; + int x; + int y; + bool live; + int speed; + int boundx; + int boundy; + + int max_frame; + int cur_frame; + int frame_count; + int frame_delay; + int frame_width; + int frame_height; + int animation_columns; + int animation_direction; +} SERVER_COMET; + +typedef struct srv_explosion +{ + int x; + int y; + bool live; + float lifetime; + + int max_frame; + int cur_frame; + int frame_count; + int frame_delay; + int frame_width; + int frame_height; + int animation_columns; + int animation_direction; +} SERVER_EXPLOSION; + +typedef struct srv_objects +{ + SERVER_SHIP** ships; + int ship_size; + SERVER_BULLET** bullets; + int bullet_size; + SERVER_COMET** comets; + int comet_size; + SERVER_EXPLOSION** explosions; + int explosion_size; +} SERVER_OBJECTS; + +SERVER_OBJECTS* srv_create_objects(SERVER_OBJECTS* data, int ship_size, int bullet_size, int comet_size, int explosion_size); +void srv_free_objects(SERVER_OBJECTS* objects); +void srv_destroy_objects(SERVER_OBJECTS* objects); + +static SERVER_SHIP** srv_create_ships(int size); +static SERVER_BULLET** srv_create_bullets(int size); +static SERVER_COMET** srv_create_comets(int size); +static SERVER_EXPLOSION** srv_create_explosions(int size); + +void srv_init_ships(SERVER_OBJECTS* objects, int key_ship, int ID, int animation_columns, int animation_direction, int animation_row, int boundx, int boundy, int cur_frame, + int frame_count, int frame_delay, int frame_height, int frame_width, int lives, int max_frame, int score, int speed, int x, int y); +void srv_init_bullets(SERVER_OBJECTS* objects, int key_bullet, int ID, int speed, int x, int y); +void srv_init_comets(SERVER_OBJECTS* objects, int key_comet, int ID, int animation_columns, int animation_direction, int boundx, int boundy, int cur_frame, + int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int speed, int x, int y); +void srv_init_explosions(SERVER_OBJECTS* objects, int key_explosion, int animation_columns, int animation_direction, int cur_frame, + int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int x, int y); + +#endif diff --git a/server/server.h b/server/server.h new file mode 100644 index 0000000..b6bb4dd --- /dev/null +++ b/server/server.h @@ -0,0 +1,19 @@ +/* + * File: server.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.14 + */ + +#ifndef SERVER_H +#define SERVER_H + +#include "common.h" +#include "connection.h" +#include "update.h" + +#endif + + + diff --git a/server/update.c b/server/update.c new file mode 100644 index 0000000..cb8e375 --- /dev/null +++ b/server/update.c @@ -0,0 +1,164 @@ +#include "update.h" +#include "connection.h" +#include + +/************************************************************ + * UPDATE GAMES + ***********************************************************/ + +void srv_game_update(SERVER_DATA* data) +{ + for(int i = 0; i < data->games.game_size; i++) + { + if(!data->games.game[i]->active) continue; + + SERVER_GAME* game = data->games.game[i]; + + if(game->game_started) + srv_handle_game(data, game); + else + srv_handle_party(data, game); + } +} + +static void srv_handle_party(SERVER_DATA* data, SERVER_GAME* game) +{ + ENetPacket *packet; + SERVER_MESSAGE_PARTY message; + + int iterator = 0; + + for(int i = 0; i < game->user_size; i++) + if(game->user[i]) + { + message.users[iterator].id = game->user[i]->id; + message.users[iterator].is_ready = game->user[i]->is_ready; + strncpy(message.users[iterator].nickname, game->user[i]->nickname, 40); + iterator++; + } + + message.count_connected = game->count_connected; + message.game_id = game->id; + message.active = game->active; + message.game_started = game->game_started; + strncpy(message.game_name, game->game_name, 40); + + for(int i = 0; i < game->user_size; i++) + if(game->user[i]) + { + message.is_creator = game->user[i]->is_creator; + message.is_ready = game->user[i]->is_ready; + message.user_id = game->user[i]->id; + packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(game->user[i]->peer, 0, packet); + } +} + +static void srv_handle_game(SERVER_DATA* data, SERVER_GAME* game) +{ + ENetPacket *packet; + SERVER_MESSAGE_UPDATE message; + + srv_clear_message(&message); + + srv_update_explosions(data, game); + srv_move_ship(data, game, &message); + srv_fire_bullet(game); + srv_update_bullet(data, game, &message); + srv_start_comet(game); + srv_update_comet(data, game, &message); + srv_collide_bullet(game, &message); + srv_collide_comet(game, &message); + + for(int i = 0; i < game->user_size; i++) + if(game->user[i]) + { + packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(game->user[i]->peer, 0, packet); + } +} + +static void srv_clear_message(SERVER_MESSAGE_UPDATE* message) +{ + for(int i = 0; i < 15; i++) + { + message->explosion[i].live = false; + message->explosion[i].x = 0; + message->explosion[i].y = 0; + } + for(int i = 0; i < 15; i++) + { + message->comet[i].live = false; + message->comet[i].x = 0; + message->comet[i].y = 0; + } + for(int i = 0; i < 15; i++) + { + message->bullet[i].ID = -1; + message->bullet[i].active = false; + message->bullet[i].live = false; + message->bullet[i].x = 0; + message->bullet[i].y = 0; + } + for(int i = 0; i < 3; i++) + { + message->ship[i].ID = -1; + message->ship[i].active = false; + message->ship[i].dx = 0; + message->ship[i].dy = 0; + message->ship[i].lives = 0; + message->ship[i].score = 0; + message->ship[i].x = 0; + message->ship[i].y = 0; + } +} + +/************************************************************ + * UPDATE USERS + ***********************************************************/ + +void srv_client_update(SERVER_DATA* data) +{ + for(int i = 0; i < data->users.user_size; i++) + { + if(!data->users.user[i]->active) continue; + + SERVER_USER* user = data->users.user[i]; + + switch(user->state) + { + case STATE_LIST: + srv_handle_userlist(data, user); + break; + case STATE_PARTY: + break; + case STATE_GAME: + break; + } + } +} + +static void srv_handle_userlist(SERVER_DATA* data, SERVER_USER* user) +{ + ENetPacket *packet; + SERVER_MESSAGE_LIST message; + + message.count_game = 0; + + int iterator = 0; + + for(int i = 0; i < 3; i++) + if(data->games.game[i]->active && !data->games.game[i]->game_started) + { + message.games[iterator].id = data->games.game[i]->id; + message.games[iterator].count_connected = data->games.game[i]->count_connected; + strncpy(message.games[iterator].game_name, data->games.game[i]->game_name, 40); + message.count_game++; + iterator++; + } + + message.state = STATE_LIST; + packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(user->peer, 0, packet); +} + diff --git a/server/update.h b/server/update.h new file mode 100644 index 0000000..c4240b2 --- /dev/null +++ b/server/update.h @@ -0,0 +1,31 @@ +/* + * File: update.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.15 + */ + +#ifndef server_update +#define server_update + +#include "common.h" +#include "calculation.h" + +/************************************************************ + * UPDATE USERS + ***********************************************************/ +void srv_client_update(SERVER_DATA* data); +static void srv_handle_userlist(SERVER_DATA* data, SERVER_USER* user); +/************************************************************ + * UPDATE GAMES + ***********************************************************/ +void srv_game_update(SERVER_DATA* data); +static void srv_handle_party(SERVER_DATA* data, SERVER_GAME* game); +static void srv_handle_game(SERVER_DATA* data, SERVER_GAME* game); +static void srv_clear_message(SERVER_MESSAGE_UPDATE* message); + +#endif + + + diff --git a/server/users/users.c b/server/users/users.c new file mode 100644 index 0000000..c526c64 --- /dev/null +++ b/server/users/users.c @@ -0,0 +1,88 @@ +#include "users.h" +#include "message.h" + +SERVER_USERS* srv_create_users(SERVER_USERS* users, int user_size) +{ + if(!users) + { + users = (SERVER_USERS*)malloc(sizeof(SERVER_USERS)); + show_message_error(users, "Failed to allocate space for SERVER_USERS"); + } + + users->user_size = user_size; + + if(user_size) + { + users->user = (SERVER_USER**)malloc(sizeof(SERVER_USER*) * user_size); + show_message_error(users->user, "Failed to allocate space for SERVER_USER collection"); + + for(int i = 0; i < user_size; i++) + { + users->user[i] = (SERVER_USER*)malloc(sizeof(SERVER_USER)); + show_message_error(users->user[i], "Failed to allocate space for SERVER_USER"); + + users->user[i]->id = -1; + users->user[i]->active = false; + users->user[i]->is_creator = false; + users->user[i]->is_ready = false; + users->user[i]->in_game = false; + users->user[i]->game_id = -1; + users->user[i]->state = STATE_NONE; + users->user[i]->nickname[0] = '\0'; + users->user[i]->display_width = 0; + users->user[i]->display_height = 0; + users->user[i]->scale_factor = 0; + users->user[i]->command.dx = 0; + users->user[i]->command.dy = 0; + users->user[i]->command.fire = false; + } + } + else + users->user = NULL; + + return users; +} + +void srv_free_users(SERVER_USERS* users) +{ + srv_destroy_users(users); + free(users); +} + +void srv_destroy_users(SERVER_USERS* users) +{ + for(int i = 0; i < users->user_size; i++) + free(users->user[i]); + + free(users->user); +} + +SERVER_USER* srv_get_free_user(SERVER_USERS* users) +{ + for(int i = 0; i < users->user_size; i++) + if(!users->user[i]->active) + { + users->user[i]->id = i; + users->user[i]->active = true; + return users->user[i]; + } + + return NULL; +} + +void srv_clear_user(SERVER_USER* user) +{ + user->id = -1; + user->game_id = -1; + user->active = false; + user->is_ready = false; + user->in_game = false; + user->state = STATE_NONE; + user->nickname[0] = '\0'; + user->display_width = 0; + user->display_height = 0; + user->command.dx = 0; + user->command.dy = 0; + user->command.fire = false; + user->scale_factor = 0; +} diff --git a/server/users/users.h b/server/users/users.h new file mode 100644 index 0000000..7506f56 --- /dev/null +++ b/server/users/users.h @@ -0,0 +1,64 @@ +/* + * File: users.h + * Author: Alexander Zhirov + * Connection with me (telegram messanger): @alexanderzhirov + * + * Created on 2020.06.14 + */ + +#ifndef server_users +#define server_users + +#include +#include + +typedef enum srv_state +{ + STATE_NONE, + STATE_LIST, + STATE_PARTY, + STATE_GAME, + STATE_DISCONNECT +} SERVER_STATE; + +typedef struct srv_game_command +{ + int dx; + int dy; + bool fire; +} SERVER_GAME_COMMAND; + +typedef struct srv_user +{ + int id; + int game_id; + char nickname[40]; + int display_width; + int display_height; + float scale_factor; + SERVER_STATE state; + bool in_game; + bool is_creator; // game creator + bool is_ready; + bool active; + ENetPeer* peer; + SERVER_GAME_COMMAND command; +} SERVER_USER; + +typedef struct srv_users +{ + SERVER_USER** user; + int user_size; +} SERVER_USERS; + +SERVER_USERS* srv_create_users(SERVER_USERS* users, int user_size); +void srv_free_users(SERVER_USERS* users); +void srv_destroy_users(SERVER_USERS* users); + +void srv_clear_user(SERVER_USER* user); +SERVER_USER* srv_get_free_user(SERVER_USERS* users); + +#endif + + +