247 lines
7.4 KiB
C++
247 lines
7.4 KiB
C++
#include "Multiplayer.hpp"
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <cctype>
|
|
#include <algorithm>
|
|
#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;
|
|
}
|
|
} |