#include "Multiplayer.hpp" #include #include #include #include #include "Game.hpp" // #define SERVER_ADDRESS "127.0.0.1" #define SERVER_ADDRESS "sffnetwork.su" void Multiplayer::connect(const char* name) { printf("name %s\n", name); m_name = name; m_state = MultiplayerState::CONNECTING; client = enet_host_create(nullptr, 1, LAST_CHANNEL, 0, 0); if (!client) { printf("client null\n"); exit(1); } ENetAddress address; enet_address_set_host(&address, SERVER_ADDRESS); address.port = 7777; peer = enet_host_connect(client, &address, LAST_CHANNEL, 0); if (peer == nullptr) { printf("peer null\n"); enet_host_destroy(client); exit(1); } ENetEvent event; auto res = enet_host_service(client, &event, 5000); if (res <= 0 || event.type != ENET_EVENT_TYPE_CONNECT) { enet_peer_reset(peer); printf("Failed to connect to server!\n"); exit(1); } auto packet_size = 1 + 2 + strlen(name); auto login_packet = new char[packet_size]; login_packet[0] = Header::IDENTIFICATION; *(uint16_t*)(login_packet + 1) = strlen(name); memcpy(login_packet + 3, name, strlen(name)); if (sendPacket(login_packet, packet_size)) { printf("trying to reg!!\n"); m_state = MultiplayerState::LOGGING_IN; } } int Multiplayer::sendPacket(char* data, int size, Channel channel, bool reliable) { auto enetPacket = enet_packet_create(data, size, reliable ? ENET_PACKET_FLAG_RELIABLE : ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); return enet_peer_send(peer, channel, enetPacket) == 0; } void Multiplayer::update(float dt) { ENetEvent event; while (enet_host_service(client, &event, 0) > 0) { switch (event.type) { case ENET_EVENT_TYPE_RECEIVE: { // printf("packet received\n"); auto bytes = event.packet->data; // for (int i = 0; i < event.packet->dataLength; i++) { // printf("%02X ", bytes[i]); // } // printf("\n"); switch (bytes[0]) { case LOAD_PLAYER: { // all players get this when a new player connects bytes++; uint16_t nameLen = *(uint16_t*)bytes; bytes += 2; auto name = new char[nameLen + 1]; memcpy(name, bytes, nameLen); bytes += nameLen; name[nameLen] = 0; uint32_t playerID = *(uint32_t*)bytes; bytes += 4; float serverTime = *(float*)bytes; printf("- load player name %s id %i server time %f\n", name, playerID, serverTime); Game::get().chatMessages.push_back({"Player " + std::string(name) + " has joined.", (float)GetTime()}); if (m_name == name) { printf("- its me!\n"); m_id = playerID; m_state = MultiplayerState::PLAYING; Game::get().serverTime = serverTime; char packet = Header::LOAD_PLAYERS; sendPacket(&packet, 1); } else { // std::string texture = "assets/"; // std::string nicknamee = name; // std::transform(nicknamee.begin(), nicknamee.end(), nicknamee.begin(), ::tolower); // texture.append(nicknamee).append(".png"); auto p = Player(skinFromName(name), name); p.pos.y = -400; Game::get().otherPlayers[playerID] = p; } break; } case LOAD_PLAYERS: { // get list of all players on server with their id,pos,name printf("- load players packet size %i\n", event.packet->dataLength); bytes++; auto num = *bytes; bytes++; for (int i = 0; i < num; i++) { auto id = *(uint32_t*)bytes; bytes += 4; auto x = *(float*)bytes; bytes += 4; auto y = *(float*)bytes; bytes += 4; auto nameLen = *(uint16_t*)bytes; bytes += 2; auto name = new char[nameLen + 1]; name[nameLen] = 0; memcpy(name, bytes, nameLen); bytes += nameLen; printf("- - player: x %f y %f name %s id %i\n", x, y, name, id); // std::string texture = "assets/"; // std::string nicknamee = name; // std::transform(nicknamee.begin(), nicknamee.end(), nicknamee.begin(), ::tolower); // texture.append(nicknamee).append(".png"); auto p = Player(skinFromName(name), name); // auto p = Player(texture.c_str(), name); p.pos = {x, y}; Game::get().otherPlayers[id] = p; } break; } case PLAYER: { // pos of all players bytes++; auto num = *bytes; bytes++; for (int i = 0; i < num; i++) { auto id = *(uint32_t*)bytes; bytes += 4; auto x = *(float*)bytes; bytes += 4; auto y = *(float*)bytes; bytes += 4; if (id == peer->connectID) { continue; } if (Game::get().otherPlayers.contains(id)) { auto& p = Game::get().otherPlayers[id]; // Game::get().otherPlayers[id].pos = {x, y}; auto delta_x = x - p.pos.x; p.pos = {x, y}; p.vel.x = delta_x; // p.walkRight = delta_x > 0; if (delta_x > 0) { p.walkRight = true; } else if (delta_x < 0) { p.walkRight = false; } } } break; } case MESSAGE: { bytes++; auto len = *(uint16_t*)bytes; bytes += 2; auto msg = new char[len + 1]; msg[len] = 0; memcpy(msg, bytes, len); Game::get().chatMessages.push_back({msg, (float)GetTime()}); delete[] msg; break; } default: { printf("- unk packet %i\n", bytes[0]); break; } } break; } case ENET_EVENT_TYPE_DISCONNECT: { printf("Connection closed.\n"); break; } default: break; } } m_updateTime += dt; const auto POS_TIME = 1 / 30.f; if (m_updateTime > POS_TIME) { // printf("sending pos\n"); m_updateTime -= POS_TIME; auto data = new char[1 + 4 + 4]; data[0] = Header::PLAYER; *(float*)(data + 1) = Game::get().player.pos.x; *(float*)(data + 1 + 4) = Game::get().player.pos.y; sendPacket(data, 1 + 4 + 4); delete[] data; } }