diff --git a/SQCSim-common/SQCSim-common.vcxproj b/SQCSim-common/SQCSim-common.vcxproj index 4ba7bd4..c618082 100644 --- a/SQCSim-common/SQCSim-common.vcxproj +++ b/SQCSim-common/SQCSim-common.vcxproj @@ -48,7 +48,7 @@ StaticLibrary false - v143 + ClangCL true Unicode diff --git a/SQCSim-common/bullet.cpp b/SQCSim-common/bullet.cpp index 9b26861..a489c55 100644 --- a/SQCSim-common/bullet.cpp +++ b/SQCSim-common/bullet.cpp @@ -3,19 +3,32 @@ Bullet::Bullet(Vector3f pos, Vector3f dir) : m_startpos(pos), m_currentpos(pos), m_velocity(dir) {} -Bullet::Bullet(Vector3f pos, Vector3f dir, uint64_t tid): m_startpos(pos), m_currentpos(pos), m_velocity(dir), m_tid(tid) {} +Bullet::Bullet(Vector3f pos, Vector3f dir, uint64_t shooter_id): m_startpos(pos), m_currentpos(pos), m_velocity(dir), m_shooter_id(shooter_id) {} Bullet::~Bullet() {} -bool Bullet::Update(World* world, float elapsedtime, int perframe, std::unordered_map mapPlayer) { +bool Bullet::Update(World* world, float elapsedtime, int perframe, std::unordered_map mapPlayer, netprot::ChunkMod** chunkmod) { int max = 100 / perframe; float damage = 0.057f; for (int x = 0; x < max; ++x) { m_currentpos += m_velocity * elapsedtime; for (auto& [key, player] : mapPlayer) { - if ((m_currentpos - player->GetPosition()).Length() < .4f) { + bool hit = false; + if ((m_currentpos - player->GetPosition()).Length() < .6f) { + hit = true; + } + if ((m_currentpos - player->GetPOV()).Length() < .2f) { + damage *= 2; // HEADSHOT! + hit = true; + } + if (hit && !player->AmIDead()) { player->InflictDamage(damage); + player->m_hit = true; + + if (player->AmIDead()) + player->Killer = m_shooter_id; + return true; } } @@ -23,6 +36,14 @@ bool Bullet::Update(World* world, float elapsedtime, int perframe, std::unordere if (!world->ChunkAt(m_currentpos)) return true; else if (world->BlockAt(m_currentpos) != BTYPE_AIR) { + if (chunkmod) { + using namespace netprot; + *chunkmod = new ChunkMod(); + (*chunkmod)->old_b_type = world->BlockAt(m_currentpos); + (*chunkmod)->b_type = BTYPE_AIR; + (*chunkmod)->pos = m_currentpos; + } + world->ChangeBlockAtPosition(BTYPE_AIR, m_currentpos); return true; } @@ -47,6 +68,6 @@ Vector3f Bullet::getVel() const { return m_velocity; } -uint64_t Bullet::getTeamID(){ - return m_tid; -} +//uint64_t Bullet::getTeamID(){ +// return m_tid; +//} diff --git a/SQCSim-common/bullet.h b/SQCSim-common/bullet.h index 04bbfad..3f875d9 100644 --- a/SQCSim-common/bullet.h +++ b/SQCSim-common/bullet.h @@ -5,7 +5,7 @@ #include "define.h" #include "vector3.h" #include "player.h" - +#include "netprotocol.h" class World; class Player; @@ -16,17 +16,17 @@ public: Bullet(Vector3f pos, Vector3f dir, uint64_t tid); ~Bullet(); - bool Update(World* world, float elapsedtime, int perframe, std::unordered_map m_mapPlayer); + bool Update(World* world, float elapsedtime, int perframe, std::unordered_map m_mapPlayer, netprot::ChunkMod** chunkmod); void Transpose(int& x, int& z); Vector3f getPos() const; Vector3f getVel() const; - uint64_t getTeamID(); + //uint64_t getTeamID(); private: Vector3f m_startpos, m_currentpos, m_velocity; - uint64_t m_tid = 0; + uint64_t m_shooter_id = 0; }; diff --git a/SQCSim-common/define.h b/SQCSim-common/define.h index 4e7b0b0..685bf5d 100644 --- a/SQCSim-common/define.h +++ b/SQCSim-common/define.h @@ -41,8 +41,11 @@ typedef uint8_t BlockType; enum BLOCK_TYPE { BTYPE_AIR, BTYPE_DIRT, BTYPE_GRASS, BTYPE_METAL, BTYPE_ICE, BTYPE_GREENGRASS, BTYPE_LAST }; typedef uint8_t BoostType; enum BOOST_TYPE { BTYPE_SPEED, BTYPE_HEAL, BTYPE_DAMAGE, BTYPE_INVINCIBLE, BTYPE_BOOST_LAST }; + +//anim enum ANIM_TYPE { STILL = 0, SHOOTING = 8, JUMPING = 16, JUMPINGSHOOTING = 24, DEAD = 32, TYPE_LAST = 40}; enum ANIM_POS {FRONT, QUARTER_FRONT_LEFT, QUATER_FRONT_RIGHT, PROFIL_LEFT, PROFIL_RIGHT, QUARTER_BACK_LEFT, QUARTER_BACK_RIGHT, BACK , POS_LAST}; + typedef uint64_t Timestamp; #ifdef _WIN32 @@ -74,6 +77,7 @@ typedef uint64_t Timestamp; #include #include #include +#include #define flag_t unsigned int #define addrlen_t unsigned int diff --git a/SQCSim-common/netprotocol.cpp b/SQCSim-common/netprotocol.cpp index ad1a24b..68feda2 100644 --- a/SQCSim-common/netprotocol.cpp +++ b/SQCSim-common/netprotocol.cpp @@ -29,13 +29,13 @@ void netprot::Serialize(Input* in, char* buf[], uint32_t* buflen) { Keys keys = in->keys; uint8_t keys8 = // Reste un bit. - keys.forward & 0b10000000 | - keys.backward & 0b01000000 | - keys.left & 0b00100000 | - keys.right & 0b00010000 | - keys.jump & 0b00001000 | - keys.shoot & 0b00000100 | - keys.block & 0b00000010; + (keys.forward ? 0b10000000 : 0) | + (keys.backward ? 0b01000000 : 0) | + (keys.left ? 0b00100000 : 0) | + (keys.right ? 0b00010000 : 0) | + (keys.jump ? 0b00001000 : 0) | + (keys.shoot ? 0b00000100 : 0) | + (keys.block ? 0b00000010 : 0); memcpy(*buf + sizeof(uint64_t) * 2 + 1, &keys8, sizeof(uint8_t)); @@ -90,14 +90,14 @@ void netprot::Serialize(Output* out, char* buf[], uint32_t* buflen) { States states = out->states; uint8_t states8 = - states.jumping & 0b10000000 | - states.shooting & 0b01000000 | - states.hit & 0b00100000 | - states.powerup & 0b00010000 | - states.dead & 0b00001000 | - states.still & 0b00000100 | - states.jumpshot & 0b00000010 | - states.running & 0b00000001; + (states.jumping ? 0b10000000 : 0) | + (states.shooting ? 0b01000000 : 0) | + (states.hit ? 0b00100000 : 0) | + (states.powerup ? 0b00010000 : 0) | + (states.dead ? 0b00001000 : 0) | + (states.still ? 0b00000100 : 0) | + (states.jumpshot ? 0b00000010 : 0) | + (states.running ? 0b00000001 : 0); memcpy(*buf + sizeof(uint64_t) * 2 + 1, &states8, sizeof(uint8_t)); @@ -181,8 +181,6 @@ void netprot::Serialize(Sync* sync, char* buf[], uint32_t* buflen) { memcpy(*buf + sizeof(uint64_t) * 2 + sizeof(uint32_t) + 1, ammo8, sizeof(uint16_t)); - memcpy(*buf + sizeof(uint64_t) * 2 + sizeof(uint32_t) + sizeof(uint16_t) + 1, &sync->hp, sizeof(uint8_t)); - uint32_t vec[3]; memcpy(vec, &sync->position, sizeof(Vector3f)); // Pour d�naturer les floats. @@ -200,9 +198,21 @@ void netprot::Serialize(Sync* sync, char* buf[], uint32_t* buflen) { (uint8_t)((vec[2] >> 8) & 0xFF), (uint8_t)(vec[2] & 0xFF) }; - memcpy(*buf + sizeof(uint64_t) * 2 + sizeof(uint32_t) + sizeof(uint16_t) + 2, vec8, sizeof(uint32_t) * 3); + memcpy(*buf + sizeof(uint64_t) * 2 + sizeof(uint32_t) + sizeof(uint16_t) + 1, vec8, sizeof(uint32_t) * 3); - *buflen = sizeof(uint64_t) * 2 + sizeof(uint32_t) * 4 + sizeof(uint16_t) + 2; + uint32_t hp; + + memcpy(&hp, &sync->hp, sizeof(float)); + + uint8_t hp8[4] = { + (uint8_t)((hp >> 24) & 0xFF), + (uint8_t)((hp >> 16) & 0xFF), + (uint8_t)((hp >> 8) & 0xFF), + (uint8_t)(hp & 0xFF) }; + + memcpy(*buf + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 4 + sizeof(uint16_t) + 1, hp8, sizeof(float)); + + *buflen = sizeof(uint64_t) * 2 + sizeof(uint32_t) * 4 + sizeof(uint16_t) + sizeof(float) + 1; } void netprot::Serialize(TeamInfo* tinfo, char* buf[], uint32_t* buflen) { @@ -210,7 +220,8 @@ void netprot::Serialize(TeamInfo* tinfo, char* buf[], uint32_t* buflen) { size_t namesize = std::strlen(tinfo->name) + 1; - memcpy(*buf + 1, &tinfo->name, namesize); + strcpy(*buf + 1, namesize, tinfo->name); + uint64_t tid = tinfo->id; uint8_t tid8[sizeof(uint64_t)] = { (uint8_t)((tid >> 56) & 0xFF), @@ -233,7 +244,8 @@ void netprot::Serialize(LoginInfo* linfo, char* buf[], uint32_t* buflen) { size_t namesize = std::strlen(linfo->name) + 1; - memcpy(*buf + 1, &linfo->name, namesize); + strcpy(*buf + 1, namesize, linfo->name); + uint64_t sid = linfo->sid; uint8_t sid8[sizeof(uint64_t)] = { (uint8_t)((sid >> 56) & 0xFF), @@ -270,7 +282,8 @@ void netprot::Serialize(PlayerInfo* pinfo, char* buf[], uint32_t* buflen) { size_t namesize = std::strlen(pinfo->name) + 1; - memcpy(*buf + 1, &pinfo->name, namesize); + strcpy(*buf + 1, namesize, pinfo->name); + uint64_t id = pinfo->id; uint8_t id8[sizeof(uint64_t)] = { (uint8_t)((id >> 56) & 0xFF), @@ -397,11 +410,110 @@ void netprot::Serialize(Chat* chat, char* buf[], uint32_t* buflen) { size_t messize = std::strlen(chat->mess) + 1; - memcpy(*buf + 1 + sizeof(uint64_t) * 3, &chat->mess, messize); + strcpy(*buf + 1 + sizeof(uint64_t) * 3, messize, chat->mess); *buflen = messize + sizeof(uint64_t) * 3 + 2; } +void netprot::Serialize(ChunkMod* chmod, char* buf[], uint32_t* buflen) { + *buf[0] = (char)netprot::PACKET_TYPE::CHUNKMOD; + + uint32_t vec[3]; + memcpy(vec, &chmod->pos, sizeof(Vector3f)); // Pour d�naturer les floats. + + uint8_t vec8[3 * sizeof(uint32_t)] = { + (uint8_t)((vec[0] >> 24) & 0xFF), + (uint8_t)((vec[0] >> 16) & 0xFF), + (uint8_t)((vec[0] >> 8) & 0xFF), + (uint8_t)(vec[0] & 0xFF), + (uint8_t)((vec[1] >> 24) & 0xFF), + (uint8_t)((vec[1] >> 16) & 0xFF), + (uint8_t)((vec[1] >> 8) & 0xFF), + (uint8_t)(vec[1] & 0xFF), + (uint8_t)((vec[2] >> 24) & 0xFF), + (uint8_t)((vec[2] >> 16) & 0xFF), + (uint8_t)((vec[2] >> 8) & 0xFF), + (uint8_t)(vec[2] & 0xFF) }; + + memcpy(*buf + 1, vec8, sizeof(uint32_t) * 3); + + memcpy(*buf + sizeof(uint32_t) * 3 + 1, &chmod->b_type, sizeof(BlockType)); + memcpy(*buf + sizeof(uint32_t) * 3 + 2, &chmod->old_b_type, sizeof(BlockType)); + + *buflen = sizeof(uint32_t) * 3 + 3; +} + +void netprot::Serialize(BulletAdd* bull, char* buf[], uint32_t* buflen) { + *buf[0] = (char)netprot::PACKET_TYPE::BULLET; + + uint64_t tstamp = bull->tstamp; + uint8_t ts8[sizeof(uint64_t)] = { + (uint8_t)((tstamp >> 56) & 0xFF), + (uint8_t)((tstamp >> 48) & 0xFF), + (uint8_t)((tstamp >> 40) & 0xFF), + (uint8_t)((tstamp >> 32) & 0xFF), + (uint8_t)((tstamp >> 24) & 0xFF), + (uint8_t)((tstamp >> 16) & 0xFF), + (uint8_t)((tstamp >> 8) & 0xFF), + (uint8_t)(tstamp & 0xFF) + }; + + memcpy(*buf + 1, ts8, sizeof(uint64_t)); + + uint64_t tid = bull->id; + uint8_t tid8[sizeof(uint64_t)] = { + (uint8_t)((tid >> 56) & 0xFF), + (uint8_t)((tid >> 48) & 0xFF), + (uint8_t)((tid >> 40) & 0xFF), + (uint8_t)((tid >> 32) & 0xFF), + (uint8_t)((tid >> 24) & 0xFF), + (uint8_t)((tid >> 16) & 0xFF), + (uint8_t)((tid >> 8) & 0xFF), + (uint8_t)(tid & 0xFF) + }; + + memcpy(*buf + 1 + sizeof(uint64_t), tid8, sizeof(uint64_t)); + + uint32_t vec[3]; + memcpy(vec, &bull->pos, sizeof(Vector3f)); // Pour d�naturer les floats. + + uint8_t vec8[3 * sizeof(uint32_t)] = { + (uint8_t)((vec[0] >> 24) & 0xFF), + (uint8_t)((vec[0] >> 16) & 0xFF), + (uint8_t)((vec[0] >> 8) & 0xFF), + (uint8_t)(vec[0] & 0xFF), + (uint8_t)((vec[1] >> 24) & 0xFF), + (uint8_t)((vec[1] >> 16) & 0xFF), + (uint8_t)((vec[1] >> 8) & 0xFF), + (uint8_t)(vec[1] & 0xFF), + (uint8_t)((vec[2] >> 24) & 0xFF), + (uint8_t)((vec[2] >> 16) & 0xFF), + (uint8_t)((vec[2] >> 8) & 0xFF), + (uint8_t)(vec[2] & 0xFF) }; + + memcpy(*buf + 1 + sizeof(uint64_t) * 2, vec8, sizeof(uint32_t) * 3); + + memcpy(vec, &bull->dir, sizeof(Vector3f)); // Pour d�naturer les floats. + + uint8_t dir8[3 * sizeof(uint32_t)] = { + (uint8_t)((vec[0] >> 24) & 0xFF), + (uint8_t)((vec[0] >> 16) & 0xFF), + (uint8_t)((vec[0] >> 8) & 0xFF), + (uint8_t)(vec[0] & 0xFF), + (uint8_t)((vec[1] >> 24) & 0xFF), + (uint8_t)((vec[1] >> 16) & 0xFF), + (uint8_t)((vec[1] >> 8) & 0xFF), + (uint8_t)(vec[1] & 0xFF), + (uint8_t)((vec[2] >> 24) & 0xFF), + (uint8_t)((vec[2] >> 16) & 0xFF), + (uint8_t)((vec[2] >> 8) & 0xFF), + (uint8_t)(vec[2] & 0xFF) }; + + memcpy(*buf + 1 + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 3, dir8, sizeof(uint32_t) * 3); + + *buflen = 1 + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 6; +} + void netprot::Serialize(ErrorLog* errlog, char* buf[], uint32_t* buflen) { *buf[0] = (char)netprot::PACKET_TYPE::ERRLOG; @@ -416,7 +528,7 @@ void netprot::Serialize(ErrorLog* errlog, char* buf[], uint32_t* buflen) { -bool netprot::Deserialize(Input* in, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(Input* in, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(Input)) return false; @@ -476,7 +588,7 @@ bool netprot::Deserialize(Input* in, char* buf, uint32_t *buflen) { return true; } -bool netprot::Deserialize(Output* out, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(Output* out, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(Output)) return false; @@ -508,10 +620,12 @@ bool netprot::Deserialize(Output* out, char* buf, uint32_t *buflen) { out->states.jumping = states & 0b10000000; out->states.shooting = states & 0b01000000; out->states.hit = states & 0b00100000; - out->states.dead = states & 0b00010000; - out->states.still = states & 0b00001000; - out->states.jumpshot = states & 0b00000100; - out->states.running = states & 0b00000010; + out->states.powerup = states & 0b00010000; + out->states.dead = states & 0b00001000; + out->states.still = states & 0b00000100; + out->states.jumpshot = states & 0b00000010; + out->states.running = states & 0b00000001; + uint8_t subvec[3 * sizeof(uint32_t)] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; memcpy(subvec, &buf[2 + sizeof(uint64_t) * 2], sizeof(uint8_t) * 12); @@ -553,7 +667,7 @@ bool netprot::Deserialize(Output* out, char* buf, uint32_t *buflen) { return true; } -bool netprot::Deserialize(Sync* sync, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(Sync* sync, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(Sync)) return false; @@ -592,10 +706,9 @@ bool netprot::Deserialize(Sync* sync, char* buf, uint32_t *buflen) { (uint16_t)diff[0] << 8 | (uint16_t)diff[1]; - memcpy(&sync->hp, &buf[1 + sizeof(uint64_t) * 2 + sizeof(uint32_t) + sizeof(uint16_t)], sizeof(uint8_t)); uint8_t subvec[3 * sizeof(uint32_t)] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; - memcpy(subvec, &buf[2 + sizeof(uint64_t) * 2 + sizeof(uint32_t) + sizeof(uint16_t)], sizeof(uint8_t) * 12); + memcpy(subvec, &buf[1 + sizeof(uint64_t) * 2 + sizeof(uint32_t) + sizeof(uint16_t)], sizeof(uint8_t) * 12); uint32_t vec[3] = { (uint32_t)subvec[0] << 24 | (uint32_t)subvec[1] << 16 | @@ -612,12 +725,23 @@ bool netprot::Deserialize(Sync* sync, char* buf, uint32_t *buflen) { memcpy(&sync->position, vec, sizeof(uint32_t) * 3); - *buflen = sizeof(uint64_t) * 2 + sizeof(uint32_t) * 4 + sizeof(uint16_t) + 2; + uint8_t hp8[4]; + + memcpy(&hp8, &buf[1 + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 4 + sizeof(uint16_t)], sizeof(uint32_t)); + + uint32_t hp = (uint32_t)hp8[0] << 24 | + (uint32_t)hp8[1] << 16 | + (uint32_t)hp8[2] << 8 | + (uint32_t)hp8[3]; + + memcpy(&sync->hp, &hp, sizeof(float)); + + *buflen = 1 + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 4 + sizeof(uint16_t) + sizeof(float); return true; } -bool netprot::Deserialize(TeamInfo* tinfo, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(TeamInfo* tinfo, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(LoginInfo)) return false; @@ -626,7 +750,7 @@ bool netprot::Deserialize(TeamInfo* tinfo, char* buf, uint32_t *buflen) { if (namesize > 32) return false; - memcpy(&tinfo->name, &buf[1], namesize); + strcpy(tinfo->name, namesize, &buf[1]); uint8_t diff[sizeof(uint64_t)] = { 0,0,0,0,0,0,0,0 }; memcpy(diff, &buf[namesize + 1], sizeof(uint64_t)); @@ -645,7 +769,7 @@ bool netprot::Deserialize(TeamInfo* tinfo, char* buf, uint32_t *buflen) { return true; } -bool netprot::Deserialize(LoginInfo* linfo, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(LoginInfo* linfo, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(LoginInfo)) return false; @@ -654,7 +778,7 @@ bool netprot::Deserialize(LoginInfo* linfo, char* buf, uint32_t *buflen) { if (namesize > 32) return false; - memcpy(&linfo->name, &buf[1], namesize); + strcpy(linfo->name, namesize, &buf[1]); uint8_t diff[sizeof(uint64_t)] = { 0,0,0,0,0,0,0,0 }; memcpy(diff, &buf[namesize + 1], sizeof(uint64_t)); @@ -684,7 +808,7 @@ bool netprot::Deserialize(LoginInfo* linfo, char* buf, uint32_t *buflen) { return true; } -bool netprot::Deserialize(PlayerInfo* pinfo, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(PlayerInfo* pinfo, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(PlayerInfo)) return false; @@ -693,7 +817,7 @@ bool netprot::Deserialize(PlayerInfo* pinfo, char* buf, uint32_t *buflen) { if (namesize > 32) return false; - memcpy(&pinfo->name, &buf[1], namesize); + strcpy(pinfo->name, namesize, &buf[1]); uint8_t diff[sizeof(uint64_t)] = { 0,0,0,0,0,0,0,0 }; memcpy(diff, &buf[namesize + 1], sizeof(uint64_t)); @@ -723,7 +847,7 @@ bool netprot::Deserialize(PlayerInfo* pinfo, char* buf, uint32_t *buflen) { return true; } -bool netprot::Deserialize(GameInfo* ginfo, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(GameInfo* ginfo, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(GameInfo)) return false; @@ -766,7 +890,7 @@ bool netprot::Deserialize(GameInfo* ginfo, char* buf, uint32_t *buflen) { return true; } -bool netprot::Deserialize(Chat* chat, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(Chat* chat, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(Chat)) return false; @@ -806,19 +930,119 @@ bool netprot::Deserialize(Chat* chat, char* buf, uint32_t *buflen) { (uint64_t)dstt[6] << 8 | (uint64_t)dstt[7]; - size_t messsize = std::strlen(buf + sizeof(uint64_t) * 3) + 1; + size_t messsize = std::strlen(&buf[sizeof(uint64_t) * 3]) + 1; if (messsize > 140) return false; - memcpy(&chat->mess, &buf[1 + sizeof(uint64_t) * 3], messsize); + char* ciboire = &buf[1 + sizeof(uint64_t) * 3]; + + strcpy(chat->mess, 140, ciboire); + + //*buflen = messsize + sizeof(uint64_t) * 3 + 1; - *buflen = messsize + sizeof(uint64_t) * 3 + 2; - return true; } -bool netprot::Deserialize(ErrorLog* errlog, char* buf, uint32_t *buflen) { +bool netprot::Deserialize(ChunkMod* chmod, char* buf, uint32_t* buflen) { + if (*buflen <= sizeof(ChunkMod)) + return false; + + uint8_t subvec[3 * sizeof(uint32_t)] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; + memcpy(subvec, &buf[1], sizeof(uint8_t) * 12); + uint32_t vec[3] = { + (uint32_t)subvec[0] << 24 | + (uint32_t)subvec[1] << 16 | + (uint32_t)subvec[2] << 8 | + (uint32_t)subvec[3], + (uint32_t)subvec[4] << 24 | + (uint32_t)subvec[5] << 16 | + (uint32_t)subvec[6] << 8 | + (uint32_t)subvec[7], + (uint32_t)subvec[8] << 24 | + (uint32_t)subvec[9] << 16 | + (uint32_t)subvec[10] << 8 | + (uint32_t)subvec[11] }; + + memcpy(&chmod->pos, vec, sizeof(uint32_t) * 3); + + memcpy(&chmod->b_type, &buf[1 + sizeof(uint8_t) * 12], sizeof(BlockType)); + memcpy(&chmod->old_b_type, &buf[2 + sizeof(uint8_t) * 12], sizeof(BlockType)); + + *buflen = sizeof(uint32_t) * 3 + 3; + + return true; +} + +bool netprot::Deserialize(BulletAdd* bull, char* buf, uint32_t* buflen) { + if (*buflen <= sizeof(BulletAdd)) + return false; + + uint8_t tst[sizeof(uint64_t)] = { 0,0,0,0,0,0,0,0 }; + memcpy(tst, &buf[1], sizeof(uint64_t)); + bull->tstamp = + (uint64_t)tst[0] << 56 | + (uint64_t)tst[1] << 48 | + (uint64_t)tst[2] << 40 | + (uint64_t)tst[3] << 32 | + (uint64_t)tst[4] << 24 | + (uint64_t)tst[5] << 16 | + (uint64_t)tst[6] << 8 | + (uint64_t)tst[7]; + + memcpy(tst, &buf[1 + sizeof(uint64_t)], sizeof(uint64_t)); + bull->id = + (uint64_t)tst[0] << 56 | + (uint64_t)tst[1] << 48 | + (uint64_t)tst[2] << 40 | + (uint64_t)tst[3] << 32 | + (uint64_t)tst[4] << 24 | + (uint64_t)tst[5] << 16 | + (uint64_t)tst[6] << 8 | + (uint64_t)tst[7]; + + uint8_t subvec[3 * sizeof(uint32_t)] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; + memcpy(subvec, &buf[1 + sizeof(uint64_t) * 2], sizeof(uint8_t) * 12); + uint32_t vec[3] = { + (uint32_t)subvec[0] << 24 | + (uint32_t)subvec[1] << 16 | + (uint32_t)subvec[2] << 8 | + (uint32_t)subvec[3], + (uint32_t)subvec[4] << 24 | + (uint32_t)subvec[5] << 16 | + (uint32_t)subvec[6] << 8 | + (uint32_t)subvec[7], + (uint32_t)subvec[8] << 24 | + (uint32_t)subvec[9] << 16 | + (uint32_t)subvec[10] << 8 | + (uint32_t)subvec[11] }; + + memcpy(&bull->pos, vec, sizeof(uint32_t) * 3); + + memcpy(subvec, &buf[1 + sizeof(uint64_t) * 2 + sizeof(uint8_t) * 12], sizeof(uint8_t) * 12); + + uint32_t dir[3] = { + (uint32_t)subvec[0] << 24 | + (uint32_t)subvec[1] << 16 | + (uint32_t)subvec[2] << 8 | + (uint32_t)subvec[3], + (uint32_t)subvec[4] << 24 | + (uint32_t)subvec[5] << 16 | + (uint32_t)subvec[6] << 8 | + (uint32_t)subvec[7], + (uint32_t)subvec[8] << 24 | + (uint32_t)subvec[9] << 16 | + (uint32_t)subvec[10] << 8 | + (uint32_t)subvec[11] }; + + memcpy(&bull->dir, dir, sizeof(uint32_t) * 3); + + *buflen = 1 + sizeof(uint64_t) * 2 + sizeof(uint8_t) * 24; + + return true; +} + +bool netprot::Deserialize(ErrorLog* errlog, char* buf, uint32_t* buflen) { if (*buflen <= sizeof(ErrorLog)) return false; @@ -845,7 +1069,7 @@ netprot::PACKET_TYPE netprot::getType(char* buf, const uint32_t buflen) { return (netprot::PACKET_TYPE)buf[0]; } -netprot::Packet netprot::getPack(char* buf, uint32_t *buflen) { +netprot::Packet netprot::getPack(char* buf, uint32_t* buflen) { Packet pck = { nullptr, PACKET_TYPE::ERR }; Input* in = nullptr; Output* out = nullptr; @@ -911,9 +1135,7 @@ netprot::Packet netprot::getPack(char* buf, uint32_t *buflen) { return pck; } -netprot::Packet netprot::getPack(netprot::Buffer* buf) { - return netprot::getPack(buf->ptr, &buf->len); -} +netprot::Packet netprot::getPack(netprot::Buffer* buf) { return netprot::getPack(buf->ptr, &buf->len); } bool netprot::emptyPack(netprot::Packet pck) { switch (pck.type) { @@ -950,13 +1172,12 @@ netprot::Packet netprot::makePack(void* ptr, PACKET_TYPE type) { return pck; } -std::vector netprot::recvPacks(SOCKET sock, Buffer* buf, Buffer* outbuf) { - std::vector lsPck; - int len = buf->tmp? buf->tmp - buf->ptr: 0, +void netprot::recvPacks(SOCKET sock, Buffer* buf, std::vector* lsPck) { + int len = buf->tmp ? buf->tmp - buf->ptr : 0, end = 0; - char * cursor = buf->tmp ? buf->tmp: nullptr , - * next = buf->tmp ? buf->tmp + 1: buf->ptr, - * last = buf->tmp ? buf->tmp: buf->ptr; + char* cursor = buf->tmp ? buf->tmp : nullptr, + * next = buf->tmp ? buf->tmp + 1 : buf->ptr, + * last = buf->tmp ? buf->tmp : buf->ptr; bool ended = true; struct pollfd fds[1]; @@ -967,15 +1188,15 @@ std::vector netprot::recvPacks(SOCKET sock, Buffer* buf, Buffer* outbuf) if (!poll(fds, 1, 0)) { if (ended) buf->tmp = nullptr; - return lsPck; + return; } - + int bytes = recv(sock, &buf->ptr[len], buf->len - len, 0); if (bytes <= 0) { // si recv() retourne -1 ou 0; ça veut dire qu'il y a plus rien a lire qui n'a pas déjà été traité. if (ended) buf->tmp = nullptr; - return lsPck; - } + return; + } len += bytes; end = len; @@ -998,24 +1219,14 @@ std::vector netprot::recvPacks(SOCKET sock, Buffer* buf, Buffer* outbuf) cmp = memcmp(cursor, Footer, sizeof(uint32_t)); if (cmp == 0) { - if (!outbuf) { - lsPck.push_back(last); - cursor += sizeof(uint32_t); - last = cursor; - next = cursor + 1; - } - else { - memcpy(&outbuf->ptr[cursor - last], last, cursor - last); - lsPck.push_back(&outbuf->ptr[cursor - last]); - cursor += sizeof(uint32_t); - last = cursor; - next = cursor + 1; - } + lsPck->push_back(last); + cursor += sizeof(uint32_t); + last = cursor; + next = cursor + 1; } } else { - if (!outbuf) - buf->tmp = last; + buf->tmp = last; cursor = &buf->ptr[len]; next = cursor + 1; break; @@ -1024,8 +1235,7 @@ std::vector netprot::recvPacks(SOCKET sock, Buffer* buf, Buffer* outbuf) } } -std::vector netprot::recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, Buffer* outbuf) { - std::vector lsPck; +void netprot::recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, std::vector* lsPck) { int len = buf->tmp ? buf->tmp - buf->ptr : 0, end = 0; char* cursor = buf->tmp ? buf->tmp : nullptr, @@ -1043,14 +1253,14 @@ std::vector netprot::recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in if (!poll(fds, 1, 0)) { if (ended) buf->tmp = nullptr; - return lsPck; + return; } int bytes = recvfrom(sock, &buf->ptr[len], buf->len - len, 0, (sockaddr*)&sockad, &socklen); if (bytes <= 0) { // si recv() retourne -1 ou 0; ça veut dire qu'il y a plus rien a lire qui n'a pas déjà été traité. if (ended) buf->tmp = nullptr; - return lsPck; + return; } len += bytes; end = len; @@ -1074,24 +1284,14 @@ std::vector netprot::recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in cmp = memcmp(cursor, Footer, sizeof(uint32_t)); if (cmp == 0) { - if (!outbuf) { - lsPck.push_back(last); - cursor += sizeof(uint32_t); - last = cursor; - next = cursor + 1; - } - else { - memcpy(&outbuf->ptr[cursor - last], last, cursor - last); - lsPck.push_back(&outbuf->ptr[cursor - last]); - cursor += sizeof(uint32_t); - last = cursor; - next = cursor + 1; - } + lsPck->push_back(last); + cursor += sizeof(uint32_t); + last = cursor; + next = cursor + 1; } } else { - if (!outbuf) - buf->tmp = last; + buf->tmp = last; cursor = &buf->ptr[len]; next = cursor + 1; break; diff --git a/SQCSim-common/netprotocol.h b/SQCSim-common/netprotocol.h index b6f78c9..6171bcf 100644 --- a/SQCSim-common/netprotocol.h +++ b/SQCSim-common/netprotocol.h @@ -12,14 +12,14 @@ namespace netprot { ERR, INPUT, OUTPUT, SYNC, TEAMINF, SELFINF, PLAYINF, LOGINF, CHUNKMOD, PLAYERMOD, PICKUPMOD, - GAMEINFO, ENDINFO , CHAT, ERRLOG, - LAST_PACK + GAMEINFO, ENDINFO , BULLET, + CHAT, ERRLOG, LAST_PACK }; /* Structures */ struct Buffer { // Pour pouvoir rendre l'utilisation des buffers plus clean. - char* ptr = new char[BUFFER_LENGTH] { 1 }, * tmp = nullptr; + char *ptr = new char[BUFFER_LENGTH] { 1 }, *tmp = nullptr; uint32_t len = BUFFER_LENGTH; ~Buffer() { delete[] ptr; } @@ -27,7 +27,7 @@ namespace netprot { }; struct Packet { // Pour pouvoir recevoir les paquets du recv() sans avoir à les aiguiller dans la même thread. - void* ptr = nullptr; // Notez que le pointeur doit être supprimé séparément lorsqu'il n'est plus utile. + void *ptr = nullptr; // Notez que le pointeur doit être supprimé séparément lorsqu'il n'est plus utile. PACKET_TYPE type = PACKET_TYPE::ERR; }; @@ -38,24 +38,24 @@ namespace netprot { /* Sous-structures */ struct Keys { - bool forward, - backward, - left, - right, - jump, - shoot, - block; + bool forward = false, + backward = false, + left = false, + right = false, + jump = false, + shoot = false, + block = false; }; struct States { - bool jumping, - shooting, - hit, - powerup, - dead, - still, - jumpshot, - running; + bool jumping = false, + shooting = false, + hit = false, + powerup = false, + dead = false, + still = false, + jumpshot = false, + running = false; }; /* Structures de paquets */ @@ -80,37 +80,37 @@ namespace netprot { uint64_t sid = 0; uint32_t timer = 0; uint16_t ammo = 0; - uint8_t hp = 0; + float hp = 0; Vector3f position; Sync() {} Sync(Sync* sync) : timestamp(sync->timestamp), sid(sync->sid), timer(sync->timer), ammo(sync->ammo), hp(sync->hp), position(sync->position) {} }; struct TeamInfo { // cli <-> srv TCP once - char name[32]; + char *name = new char[32]; uint64_t id = 0; TeamInfo() {} - TeamInfo(TeamInfo* tem) : id(tem->id) { strcpy(tem->name, name); } + TeamInfo(TeamInfo* tem) : id(tem->id) { strcpy(name, 32, tem->name); } + ~TeamInfo() { delete[] name; } }; struct LoginInfo { // cli <-> srv TCP once - char name[32]; + char *name = new char[32]; uint64_t sid = 0, tid = 0; LoginInfo() {} - LoginInfo(LoginInfo* ply): sid(ply->sid), tid(ply->tid) { strcpy(ply->name, name); } + LoginInfo(LoginInfo* log): sid(log->sid), tid(log->tid) { strcpy(name, 32, log->name); } + ~LoginInfo() { delete[] name; } }; struct PlayerInfo { // cli <-> srv TCP once - char name[32]; + char *name = new char[32]; uint64_t id = 0, tid = 0; PlayerInfo() {} - PlayerInfo(PlayerInfo* log) : id(log->id), tid(log->tid) { - strcpy(log->name, name); - }; - PlayerInfo(int id, int tid, std::string strname) : id(id), tid(tid) { memcpy((void*)strname.c_str(), name, strname.length()); - } + PlayerInfo(PlayerInfo* ply) : id(ply->id), tid(ply->tid) { strcpy(name, 32, ply->name); }; + PlayerInfo(int id, int tid, std::string strname) : id(id), tid(tid) { strcpy(name, 32, strname.c_str()); } + ~PlayerInfo() { delete[] name; } }; struct GameInfo { // cli <-> srv TCP event (before game start)/ once @@ -125,16 +125,29 @@ namespace netprot { uint64_t src_id = 0, dest_id = 0, dest_team_id = 0; - char mess[140]; // Good 'nough for twitr, good 'nough for me. + char *mess = new char[140]; // Good 'nough for twitr, good 'nough for me. Chat() {} - Chat(Chat* cha) : src_id(cha->src_id), dest_id(cha->dest_id), dest_team_id(cha->dest_team_id) { strcpy(cha->mess, mess); } + Chat(Chat* cha) : src_id(cha->src_id), dest_id(cha->dest_id), dest_team_id(cha->dest_team_id) { strcpy(mess, 140, cha->mess); } + ~Chat() { delete[] mess; } + }; + + struct ChunkMod { + Vector3f pos; + BlockType b_type, old_b_type; + }; + + struct BulletAdd { + Timestamp tstamp; + Vector3f pos, dir; + uint64_t id; }; struct ErrorLog { // srv -> cli TCP event - char mess[140]; - bool is_fatal; + char *mess = new char[140]; + bool is_fatal = false; ErrorLog() {}; - ErrorLog(ErrorLog* err) : is_fatal(err->is_fatal) { strcpy(err->mess, mess); } + ErrorLog(ErrorLog* err) : is_fatal(err->is_fatal) { strcpy(mess, 140, err->mess); } + ~ErrorLog() { delete[] mess; } }; /* Fonctions */ @@ -147,6 +160,8 @@ namespace netprot { void Serialize(PlayerInfo* pinfo, char* buf[], uint32_t* buflen); // srv void Serialize(GameInfo* ginfo, char* buf[], uint32_t* buflen); // cli/srv void Serialize(Chat* chat, char* buf[], uint32_t* buflen); // cli/srv + void Serialize(ChunkMod* chmod, char* buf[], uint32_t* buflen); // srv + void Serialize(BulletAdd* bull, char* buf[], uint32_t* buflen); // srv void Serialize(ErrorLog* errlog, char* buf[], uint32_t* buflen); // srv bool Deserialize(Input* in, char* buf, uint32_t* buflen); // srv @@ -157,6 +172,8 @@ namespace netprot { bool Deserialize(PlayerInfo* pinfo, char* buf, uint32_t* buflen); // cli bool Deserialize(GameInfo* ginfo, char* buf, uint32_t* buflen); // cli bool Deserialize(Chat* chat, char* buf, uint32_t* buflen); // srv/cli + bool Deserialize(ChunkMod* chmod, char* buf, uint32_t* buflen); // cli + bool Deserialize(BulletAdd* bull, char* buf, uint32_t* buflen); // cli bool Deserialize(ErrorLog* errlog, char* buf, uint32_t* buflen); // srv PACKET_TYPE getType(char* buf, uint32_t buflen); @@ -176,8 +193,8 @@ namespace netprot { template void sendPack(SOCKET sock, T* pack, Buffer* buf); template void sendPackTo(SOCKET sock, T* pack, Buffer* buf, sockaddr_in* sockad); - std::vector recvPacks(SOCKET sock, Buffer* buf, Buffer* oufbuf = nullptr); - std::vector recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, Buffer* oufbuf = nullptr); + void recvPacks(SOCKET sock, Buffer* buf, std::vector* lsPck); + void recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, std::vector* lsPck); /* Templates */ diff --git a/SQCSim-common/player.cpp b/SQCSim-common/player.cpp index b88ba18..85df138 100644 --- a/SQCSim-common/player.cpp +++ b/SQCSim-common/player.cpp @@ -14,43 +14,53 @@ void Player::TurnLeftRight(float value) { m_rotY += value; if (m_rotY > 360) m_rotY = 0; else if (m_rotY < -360) m_rotY = 0; + + float yrotrad = (m_rotY / 57.2957795056f); // 180/Pi = 57.295... + float xrotrad = (m_rotX / 57.2957795056f); + + m_direction = Vector3f(cos(xrotrad) * sin(yrotrad), + -sin(xrotrad), + cos(xrotrad) * -cos(yrotrad)); + + m_direction.Normalize(); } void Player::TurnTopBottom(float value) { m_rotX += value; if (m_rotX > 80) m_rotX = 80; else if (m_rotX < -80) m_rotX = -80; -} - -Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jump, bool shoot, float elapsedTime) { - - Vector3f delta = Vector3f(0, 0, 0); float yrotrad = (m_rotY / 57.2957795056f); // 180/Pi = 57.295... float xrotrad = (m_rotX / 57.2957795056f); m_direction = Vector3f(cos(xrotrad) * sin(yrotrad), - -sin(xrotrad), - cos(xrotrad) * -cos(yrotrad)); + -sin(xrotrad), + cos(xrotrad) * -cos(yrotrad)); m_direction.Normalize(); +} + +Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jump, bool shoot, float elapsedTime) { + Vector3f delta = Vector3f(0, 0, 0); + + Vector3f dir = m_direction; + + dir.y = 0; if (front) { - delta.x += float(sin(yrotrad)) * elapsedTime * 10.f; - delta.z += float(-cos(yrotrad)) * elapsedTime * 10.f; + delta += dir; } else if (back) { - delta.x += float(-sin(yrotrad)) * elapsedTime * 10.f; - delta.z += float(cos(yrotrad)) * elapsedTime * 10.f; + delta -= dir; } if (left) { - delta.x += float(-cos(yrotrad)) * elapsedTime * 10.f; - delta.z += float(-sin(yrotrad)) * elapsedTime * 10.f; + delta.x += dir.z; + delta.z += -dir.x; } else if (right) { - delta.x += float(cos(yrotrad)) * elapsedTime * 10.f; - delta.z += float(sin(yrotrad)) * elapsedTime * 10.f; + delta.x -= dir.z; + delta.z -= -dir.x; } delta.Normalize(); @@ -194,11 +204,11 @@ Player::Sound Player::ApplyPhysics(Vector3f input, World* world, float elapsedTi void Player::ApplyTransformation(Transformation& transformation, bool rel, bool rot) const { transformation.ApplyRotation(-m_rotX, 1, 0, 0); transformation.ApplyRotation(-m_rotY, 0, 1, 0); + + if (rel) transformation.ApplyTranslation(-GetPOV()); - if (!rot) { - transformation.ApplyRotation(-m_rotX, 1, 0, 0); - transformation.ApplyRotation(-m_rotY, 0, 1, 0); - } + + } void Player::GetBooster(Booster boosttype) @@ -246,8 +256,12 @@ void Player::RemoveBooster(float elapsedtime) } void Player::SetDirection(Vector3f dir) { m_direction = dir; } +void Player::Move(Vector3f diff) { m_position -= diff; } + Vector3f Player::GetPosition() const { return Vector3f(m_position.x + CHUNK_SIZE_X * WORLD_SIZE_X / 2, m_position.y, m_position.z + CHUNK_SIZE_Z * WORLD_SIZE_Y / 2); } +Vector3f Player::GetPositionAbs() const { return m_position; } + Vector3f Player::GetVelocity() const { return m_velocity; } Vector3f Player::GetPOV() const { return Vector3f(GetPosition().x, m_POV, GetPosition().z); } @@ -262,26 +276,24 @@ void Player::Teleport(int& x, int& z) { m_position.x -= x * CHUNK_SIZE_X; m_position.z -= z * CHUNK_SIZE_Z; } -bool Player::AmIDead() -{ - return m_hp <= 0; -} +bool Player::GetIsAirborne() const { return m_airborne; } +bool Player::AmIDead() { return m_hp <= 0; } -void Player::InflictDamage(float hitPoints) -{ - +void Player::InflictDamage(float hitPoints) { m_hp -= hitPoints; - - if (AmIDead()) - { // Quand le joueur est mort. - - - - } + if (m_hp < 0) + m_hp == 0; + //if (AmIDead()) + //{ // Quand le joueur est mort. + //} } +int Player::getScore() const { return m_score; } + +void Player::addPoint() { ++m_score; } + uint64_t Player::getId() const { return id; } diff --git a/SQCSim-common/player.h b/SQCSim-common/player.h index 4792d4a..6117605 100644 --- a/SQCSim-common/player.h +++ b/SQCSim-common/player.h @@ -25,7 +25,9 @@ public: void ApplyTransformation(Transformation& transformation, bool rel = true, bool rot = true) const; void SetDirection(Vector3f dir); + void Move(Vector3f diff); Vector3f GetPosition() const; + Vector3f GetPositionAbs() const; Vector3f GetDirection() const; Vector3f GetVelocity() const; Vector3f GetPOV() const; @@ -33,8 +35,14 @@ public: float GetHP() const; void Teleport(int& x, int& z); + bool GetIsAirborne() const; bool AmIDead(); void InflictDamage(float hitPoints); + int getScore() const; + void addPoint(); + uint64_t Killer = 0; + std::string m_username; + bool m_hit = false; private: uint64_t getId() const; @@ -44,8 +52,8 @@ protected: Vector3f m_velocity; Vector3f m_direction; - std::string m_username; uint64_t id = 0; + int m_score = 0; float m_rotX = 0; float m_rotY = 0; diff --git a/SQCSim-common/world.cpp b/SQCSim-common/world.cpp index 70d6eb6..2791ca1 100644 --- a/SQCSim-common/world.cpp +++ b/SQCSim-common/world.cpp @@ -169,31 +169,26 @@ void World::Update(Bullet* bullets[MAX_BULLETS], const Vector3f& player_pos, Blo UpdateWorld(player_pos, blockinfo); //TransposeWorld(player_pos, bullets); } -// -//void World::UpdateChunk(int& updates, unsigned int chx, unsigned int chy, BlockInfo* blockinfo[BTYPE_LAST]) { -// if (updates == 0 && ChunkAt(chx, 1, chy) && -// ChunkAt(chx, 1, chy)->IsDirty()) { -// ChunkAt(chx, 1, chy)->Update(blockinfo, this); -// updates = FRAMES_UPDATE_CHUNKS; -// } -// -//} -void World::ChangeBlockAtCursor(BlockType blockType, const Vector3f& player_pos, const Vector3f& player_dir, bool& block) { +netprot::ChunkMod* World::ChangeBlockAtCursor(BlockType blockType, const Vector3f& player_pos, const Vector3f& player_dir, bool& block, bool net) { Vector3f currentPos = player_pos; Vector3f currentBlock = currentPos; Vector3f ray = player_dir; + BlockType oldbtype; + netprot::ChunkMod* cmod = nullptr; bool found = false; - if (block) return; + if (block) return cmod; while ((currentPos - currentBlock).Length() <= MAX_SELECTION_DISTANCE && !found) { currentBlock += ray / 10.f; BlockType bt = BlockAt(currentBlock); - if (bt != BTYPE_AIR) + if (bt != BTYPE_AIR) { found = true; + oldbtype = bt; + } } if (found) @@ -219,21 +214,30 @@ void World::ChangeBlockAtCursor(BlockType blockType, const Vector3f& player_pos, (By == PyA || By == PyB || By == PyC) && - Bz == Pz)) + Bz == Pz)) { found = true; + oldbtype = bt; + } } } } if (found && (int)currentBlock.y < CHUNK_SIZE_Y) { + if (net) { + cmod = new netprot::ChunkMod(); + cmod->old_b_type = oldbtype; + cmod->b_type = blockType; + cmod->pos = currentBlock; + } int bx = (int)currentBlock.x % CHUNK_SIZE_X; int by = (int)currentBlock.y % CHUNK_SIZE_Y; int bz = (int)currentBlock.z % CHUNK_SIZE_Z; - ChunkAt(currentBlock)->SetBlock(bx, by, bz, blockType, this); ChunkAt(currentBlock)->MakeModified(); block = true; } + + return cmod; } void World::ChangeBlockAtPosition(BlockType blockType, Vector3f pos) { diff --git a/SQCSim-common/world.h b/SQCSim-common/world.h index e9b4840..06c513b 100644 --- a/SQCSim-common/world.h +++ b/SQCSim-common/world.h @@ -11,6 +11,7 @@ #include "array2d.h" #include "bullet.h" #include "chunk.h" +#include "netprotocol.h" class Chunk; class Bullet; @@ -37,7 +38,7 @@ public: void GetScope(unsigned int& x, unsigned int& y); - void ChangeBlockAtCursor(BlockType blockType, const Vector3f& player_pos, const Vector3f& player_dir, bool& block); + netprot::ChunkMod* ChangeBlockAtCursor(BlockType blockType, const Vector3f& player_pos, const Vector3f& player_dir, bool& block, bool net); void ChangeBlockAtPosition(BlockType blockType, Vector3f pos); void CleanUpWorld(int& deleteframes, bool clear); int GettbDeleted() const; diff --git a/SQCSim-srv/SQCSim-srv.vcxproj b/SQCSim-srv/SQCSim-srv.vcxproj index d080276..b0dcd9c 100644 --- a/SQCSim-srv/SQCSim-srv.vcxproj +++ b/SQCSim-srv/SQCSim-srv.vcxproj @@ -48,7 +48,7 @@ Application false - v143 + ClangCL true Unicode diff --git a/SQCSim-srv/connection.cpp b/SQCSim-srv/connection.cpp index 4ac9968..669ae8f 100644 --- a/SQCSim-srv/connection.cpp +++ b/SQCSim-srv/connection.cpp @@ -2,26 +2,28 @@ -Connection::Connection(SOCKET sock, - sockaddr_in sockaddr, - LoginInfo log, - PlayerInfo play): - m_sock(sock), - m_addr(sockaddr), - m_loginfo(log), - m_playinfo(play) { +Connection::Connection(SOCKET sock, + sockaddr_in sockaddr, + LoginInfo *log, + PlayerInfo *play) : + m_sock(sock), + m_addr(sockaddr), + m_loginfo(*log), + m_playinfo(*play) { } -Connection::~Connection() { closesocket(m_sock); } +Connection::~Connection() { + delete player; + closesocket(m_sock); } -uint64_t Connection::GetHash(bool self) const { return self? m_loginfo.sid: m_playinfo.id; } +uint64_t Connection::GetHash(bool self) const { return self ? m_loginfo.sid : m_playinfo.id; } uint64_t Connection::GetTeamHash() const { return m_loginfo.tid; } std::string Connection::GetName() const { return m_loginfo.name; } -void Connection::AddInput(Input in) { m_input_manifest.insert({ in.timestamp, in }); } +void Connection::AddInput(Input in) { m_input_manifest.insert({ in.timestamp, in }); m_input_vector.push_back(in); } Output* Connection::getOutput(Timestamp time) { auto out = m_output_manifest.find(time); @@ -50,70 +52,157 @@ sockaddr_in* Connection::getAddr() const { return (sockaddr_in*)&m_addr; } void Connection::getPacks(SOCKET sock) { std::vector lsPck; Input in; - while (true) { - lsPck = recvPacksFrom(sock, &m_buf, m_addr); - - for (auto& pck : lsPck) { - uint32_t bsize = m_buf.len - (pck - m_buf.ptr); - switch (netprot::getType(pck, 1)) { - using enum netprot::PACKET_TYPE; - case INPUT: - if (Deserialize(&in, pck, &bsize)) - m_input_manifest[in.timestamp] = in; - break; - default: break; + Sync sync; + recvPacksFrom(sock, &m_buf, m_addr, &lsPck); + for (auto& pck : lsPck) { + uint32_t bsize = m_buf.len - (pck - m_buf.ptr); + switch (netprot::getType(pck, 1)) { + using enum netprot::PACKET_TYPE; + case INPUT: + if (Deserialize(&in, pck, &bsize)) { + m_input_manifest[in.timestamp] = in; + m_input_vector.push_back(in); } + break; + case SYNC: + if (Deserialize(&sync, pck, &bsize)) + m_nsync = true; + break; + default: break; } - lsPck.clear(); } + lsPck.clear(); } -void Connection::sendPacks(SOCKET sock, std::unordered_map conns) { - while (m_last_out < m_output_manifest.size()) { - Output out = m_output_manifest.at(m_last_out++); - +void Connection::sendPacks(SOCKET sock, std::unordered_map conns, const uint32_t timer) { + static int outs = 0; + static Timestamp last = 0; + while (!m_output_vector.empty()) { + Output out = m_output_vector.front(); for (auto& [key, conn] : conns) { - if (m_playinfo.id == conn->GetHash(true)) + if (m_playinfo.id == conn->GetHash(false)) continue; sendPackTo(sock, &out, &m_bufout, conn->getAddr()); } + ++outs; + + [[unlikely]] if (last == 0) // ! + last = out.timestamp; + + outs += out.timestamp + last; + + if (outs >= 1000) { + outs -= 1000; + Sync sync; + sync.hp = player->GetHP(); + sync.timestamp = out.timestamp; + sync.position = out.position; + sync.sid = m_loginfo.sid; + sync.timer = timer; + sync.timestamp = out.timestamp; + sync.ammo = -1; + sendPackTo(sock, &sync, &m_bufout, &m_addr); + } + + m_output_vector.pop_front(); } } -void Connection::Run(World* world) { +Timestamp Connection::Run(World* world) { Input in, last; Output out; + Timestamp tstamp = 0; float el; if (m_input_manifest.size() < 2) - return; + return tstamp; - while (m_last_in < m_input_manifest.size()) { - in = m_input_manifest.at(m_last_in + 1); - last = m_input_manifest.at(m_last_in); + if (player->AmIDead()) { + m_input_manifest.clear(); + return tstamp; + } - el = (float)(in.timestamp - last.timestamp) / 1000.; - player.get()->SetDirection(in.direction); - player.get()->ApplyPhysics(player.get()->GetInput(in.keys.forward, - in.keys.backward, - in.keys.left, - in.keys.right, - in.keys.jump, false, el), world, el); + while (m_last_in < m_input_vector.size() - 1) { + in = m_input_vector.at(m_last_in + 1); + last = m_input_vector.at(m_last_in); - out.position = player.get()->GetPosition(); + el = (double)(in.timestamp - last.timestamp) / 1000.; + + if (m_shoot_acc > 0.) { + m_shoot_acc -= el; + if (m_shoot_acc < 0.) + m_shoot_acc = 0; + } + + player->SetDirection(in.direction); + player->ApplyPhysics(player->GetInput(in.keys.forward, + in.keys.backward, + in.keys.left, + in.keys.right, + in.keys.jump, false, el), world, el); + + if (player->GetPosition().y < -20.) { + player->InflictDamage(9000.); + player->Killer = GetHash(true); + } + + out.states.jumping = player->GetIsAirborne(); + out.states.running = player->GetVelocity().Length() > .5f; + out.states.still = !out.states.running && !out.states.jumping; + out.states.hit = player->m_hit; + player->m_hit = false; + + if (player->AmIDead()) { + in.keys.shoot = false; + in.keys.block = false; + out.states.dead = true; + } + + static bool toggle = false; + if (in.keys.block) { + if (!toggle) { + toggle = true; + bool block = false; + ChunkMod* cmod = world->ChangeBlockAtCursor(BLOCK_TYPE::BTYPE_METAL, + player->GetPosition(), + player->GetDirection(), + block, true); + if (cmod) + ChunkDiffs.push_back(std::move(cmod)); + } + } + else toggle = false; + + out.states.shooting = in.keys.shoot; + + if (out.states.jumping && out.states.shooting) + out.states.jumpshot = true; + else out.states.jumpshot = false; + + if (in.keys.shoot && m_shoot_acc <= 0.) { + Bullets.push_back(std::move(new Bullet(player->GetPOV() + player->GetDirection(), player->GetDirection(), GetHash(true)))); + m_shoot_acc = BULLET_TIME; + } + + out.position = player->GetPositionAbs(); out.direction = in.direction; out.timestamp = in.timestamp; out.id = m_playinfo.id; - m_output_manifest[out.timestamp] = out; + m_output_vector.push_back(out); + tstamp = out.timestamp; ++m_last_in; } + + return tstamp; } void Connection::CleanInputManifest(Timestamp time) { - auto wat = m_input_manifest.find(time); + // auto wat = m_input_manifest.find(time); - while (wat != m_input_manifest.begin()) - m_input_manifest.erase(wat--); + // while (wat != m_input_manifest.begin()) + // m_input_manifest.erase(wat--); } + +Timestamp Connection::GetTStamp() const { return m_tstamp; } diff --git a/SQCSim-srv/connection.h b/SQCSim-srv/connection.h index af9c2df..3c5ac23 100644 --- a/SQCSim-srv/connection.h +++ b/SQCSim-srv/connection.h @@ -16,11 +16,11 @@ public: Connection( SOCKET sock, sockaddr_in sockaddr, - LoginInfo log, - PlayerInfo play); + LoginInfo *log, + PlayerInfo *play); ~Connection(); - std::unique_ptr player = nullptr; + Player* player = nullptr; uint64_t GetHash(bool self = true) const; uint64_t GetTeamHash() const; @@ -34,16 +34,29 @@ public: sockaddr_in* getAddr() const; void getPacks(SOCKET sock); - void sendPacks(SOCKET sock, std::unordered_map conns); + void sendPacks(SOCKET sock, std::unordered_map conns, const uint32_t timer); - void Run(World* world); + Timestamp Run(World* world); void CleanInputManifest(Timestamp time); + + bool m_nsync = true; + + std::vector Bullets; + std::vector ChunkDiffs; + + Timestamp GetTStamp() const; + private: std::unordered_map m_input_manifest; + std::vector m_input_vector; std::unordered_map m_output_manifest; + std::deque m_output_vector; std::unordered_map m_chatlog; + float m_shoot_acc = 0; + Timestamp m_tstamp = 0; + SOCKET m_sock; sockaddr_in m_addr; LoginInfo m_loginfo; diff --git a/SQCSim-srv/define.h b/SQCSim-srv/define.h index e30bd49..a334446 100644 --- a/SQCSim-srv/define.h +++ b/SQCSim-srv/define.h @@ -11,4 +11,20 @@ #define ID_LIST_SIZE 127 #define SRV_MANUAL_SETUP true +// @ = Dead guy, $ = Killer. +const std::vector DEATHMESSAGES = { "@ has gone to meet their maker.", + "@ has bit the dust, if you know what I mean.", + "@ has ceased to be.", + "@ is no more.", + "@ is like, super dead.", + "Requiescat In Pace, @.", + "So long, @, and thanks for all the lols!", + "@ has a bad case of being dead.", + "@ has finally seen the light!", + "Thought @ was hot; guess what? He's not. He is dead, dead, dead.", + "@ did not want to live forever.", + "$ made @ die for their country.", + "$ has become death, destroyer of @.", + "$ did not make @ feel lucky." }; + #endif diff --git a/SQCSim-srv/main.cpp b/SQCSim-srv/main.cpp index 98d39f9..74c28e1 100644 --- a/SQCSim-srv/main.cpp +++ b/SQCSim-srv/main.cpp @@ -3,6 +3,11 @@ int main() { std::unique_ptr server = std::make_unique(); if (server->Init() == 0) - if (server->Ready() == 0) + while (server->Ready() == 0) { server->Run(); + if (!server->NewGameRequested()) + break; + server->Cleanup(); + } + server->DeInit(); } \ No newline at end of file diff --git a/SQCSim-srv/server.cpp b/SQCSim-srv/server.cpp index e724269..edf740c 100644 --- a/SQCSim-srv/server.cpp +++ b/SQCSim-srv/server.cpp @@ -17,10 +17,11 @@ Server::~Server() { if (m_sock_udp) closesocket(m_sock_udp); if (m_sock_tcp) - closesocket(m_sock_tcp); - for (const auto& [key, player] : m_players) - closesocket(player->getSock()); - m_players.clear(); + closesocket(m_sock_tcp); + for (const auto& [key, player] : m_conns) + closesocket(player->getSock()); + m_conns.clear(); + delete m_world; #ifdef _WIN32 WSACleanup(); #endif @@ -68,35 +69,39 @@ int Server::Init() { } int Server::Ready() { - int nbrjoueurs = 0, + int nbrjoueurs = 0, nbrconn = 0; bool readystart = false; do { Log("Entrez la duree de la partie: ", false, false); std::cin.getline(m_buf.ptr, BUFFER_LENGTH); - try { + try { m_game.countdown = std::stoi(m_buf.ptr); - } catch(const std::exception& e) { + } + catch (const std::exception& e) { Log(e.what(), true, false); m_game.countdown = 0; } } while (m_game.countdown < 1); - do { + m_game.seed = 9370707; + /*do { Log("Entrez le seed de la partie: ", false, false); std::cin.getline(m_buf.ptr, BUFFER_LENGTH); - try { - m_game.seed = std::stoi(m_buf.ptr); - } catch(const std::exception& e) { + try { + std::stoi(m_buf.ptr); + } + catch (const std::exception& e) { Log(e.what(), true, false); m_game.seed = 0; } - } while (m_game.seed < 1); + } while (m_game.seed < 1);*/ do { Log("Entrez le nombre de joueurs: ", false, false); std::cin.getline(m_buf.ptr, BUFFER_LENGTH); - try { + try { nbrjoueurs = std::stoi(m_buf.ptr); - } catch(const std::exception& e) { + } + catch (const std::exception& e) { Log(e.what(), true, false); nbrjoueurs = 0; } @@ -112,9 +117,9 @@ int Server::Ready() { } buildIdList(ID_LIST_SIZE); - + Log("A l'ecoute sur le port: " + std::to_string(SRV_PORT), false, false); - + while (!readystart) { sockaddr_in sockad; addrlen_t addrlen = sizeof(sockad); @@ -127,14 +132,14 @@ int Server::Ready() { str.append(inet_ntop(AF_INET, &sockad.sin_addr, m_buf.ptr, m_buf.len)).append(": ").append(std::to_string(sockad.sin_port)); if (recv(sock, m_buf.ptr, m_buf.len, 0) > 0) { - PlayerInfo play; + PlayerInfo* play = new PlayerInfo(); m_buf.len = BUFFER_LENGTH; Packet pck = getPack(&m_buf); if (pck.type != PACKET_TYPE::LOGINF) { Log("Paquet invalide.", true, false); if (pck.type != PACKET_TYPE::ERR) - netprot::emptyPack(pck); + netprot::emptyPack(pck); continue; // Passer au prochain appel si c'est pas un LoginInfo ou un LoginInfo invalide qui rentre. } LoginInfo* log = (LoginInfo*)pck.ptr; @@ -144,33 +149,36 @@ int Server::Ready() { Log(str.append(" Nom: ").append(log->name), false, false); str.clear(); - - Log(str.append(log->name).append(" SID: [").append(std::to_string(log->sid).append("]")), false, false); - sendPack(sock, log, &m_buf); - - play.id = getUniqueId(); - strcpy(play.name, log->name); - - play.tid = log->tid; - sendPack(sock, &m_game, &m_buf); - Connection* conn = new Connection(sock, sockad, *log, play); + sendPackTo(m_sock_udp, log, &m_buf, &sockad); - for (auto& [key, player] : m_players) { - sendPack(player->getSock(), &play, &m_buf); // Envoyer les infos de joueur distant aux joueurs d�j� connect�s - sendPack(sock, player->getInfo(), &m_buf); // et envoyer les infos des joueurs distants au nouveau joueur. - } + play->id = getUniqueId(); + play->tid = log->tid; + strcpy(play->name, 32, log->name); - m_players[log->sid] = std::move(conn); + Log(str.append(play->name).append(" SID: [").append(std::to_string(log->sid)).append("]") + .append(" ID: [").append(std::to_string(play->id)).append("]") + .append(" TID: [").append(std::to_string(play->tid)).append("]"), false, false); + play->tid = log->tid; - delete log; + sendPackTo(m_sock_udp, &m_game, &m_buf, &sockad); + Connection* conn = new Connection(sock, sockad, log, play); + + m_conns[log->sid] = conn; if (++nbrconn >= nbrjoueurs) readystart = true; } } } + for (auto& [keyin, playin] : m_conns) // Not pretty, but it works. + for (auto& [keyout, playout] : m_conns) { + if (keyin == keyout) + continue; + sendPackTo(m_sock_udp, playout->getInfo(), &m_buf, playin->getAddr()); // et envoyer les infos des joueurs distants au nouveau joueur. + } + return 0; } @@ -179,65 +187,232 @@ void Server::Run() { Input in; sockaddr_in sockad; addrlen_t socklen = sizeof(sockad); - + Log("Debut de la partie...", false, false); - int players = m_players.size(); + int players = m_conns.size(); m_world = new World(); m_world->SetSeed(m_game.seed); m_world->GetChunks().Reset(nullptr); m_world->BuildWorld(); - - for (auto& [key, conn] : m_players) { // Creation des instances de joueurs et premier sync. - conn->player = std::make_unique(Vector3f(8.5f, CHUNK_SIZE_Y + 1.8f, 8.5f)); + + for (auto& [key, conn] : m_conns) { // Creation des instances de joueurs et premier sync. + if (!conn) { + m_conns.erase(key); + continue; + } + int x = (rand() % (CHUNK_SIZE_X * WORLD_SIZE_X - 1) - (CHUNK_SIZE_X * WORLD_SIZE_X / 2)) / 8, + y = (rand() % (CHUNK_SIZE_Y * WORLD_SIZE_Y - 1) - (CHUNK_SIZE_Y * WORLD_SIZE_Y / 2)) / 8; + conn->player = new Player(Vector3f(x + .5f, CHUNK_SIZE_Y + 1.8f, y + .5f)); + conn->player->m_username = conn->GetName(); + m_players[key] = conn->player; Sync sync; - sync.position = conn->player->GetPosition(); + sync.position = conn->player->GetPositionAbs(); sync.hp = conn->player->GetHP(); sync.sid = key; sync.ammo = 0; sync.timestamp = 0; sync.timer = m_game.countdown; - sendPack(conn->getSock(), &sync, &m_buf); + sendPackTo(m_sock_udp, &sync, &m_buf, conn->getAddr()); } + + int timer = m_game.countdown, sync_acc = 0, deadplayers = 0; + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); + Timestamp last = 0; + std::vector chatlog; + std::vector chunkdiffs; + std::vector bullets; + std::vector::iterator> bullit; + std::vector netbull; + std::vector lsPck; + Chat* startchat = new Chat(); + startchat->src_id = 0; + char startmess[] = "How would -YOU- like to die today, motherf-words?"; + + strcpy(startchat->mess, 140, startmess); + + chatlog.emplace_back(startchat); + while (!endgame) { - for (auto& [key, conn] : m_players) { - conn->getPacks(m_sock_udp); - conn->Run(m_world); - conn->sendPacks(m_sock_udp, m_players); + using namespace std::chrono; + Timestamp tstamp = duration_cast(high_resolution_clock::now() - start).count(); + + if (last == 0) + last = tstamp; + sync_acc += tstamp - last; + if (sync_acc >= 1000) { + while (sync_acc >= 1000) + sync_acc -= 1000; + --timer; + std::string str = "Timer: "; + Log(str.append(std::to_string(timer)), false, false); } + last = tstamp; + + + for (auto& [key, conn] : m_conns) { + + /* In */ + + Input in; Sync sync; + + recvPacks(m_sock_udp, &m_buf, &lsPck); + for (auto& pck : lsPck) { + uint32_t bsize = m_buf.len - (pck - m_buf.ptr); + switch (netprot::getType(pck, 1)) { + using enum netprot::PACKET_TYPE; + case INPUT: + if (Deserialize(&in, pck, &bsize)) { + if (m_conns.count(in.sid)) + m_conns[in.sid]->AddInput(in); + } + break; + case SYNC: + if (Deserialize(&sync, pck, &bsize)) {} + break; + default: break; + } + } + lsPck.clear(); + + /* Process */ + + if (conn->m_nsync) { + Timestamp tstamp = conn->Run(m_world); + + if (conn->player->AmIDead()) { + Chat* chat = new Chat(); + chat->dest_id = chat->dest_team_id = chat->src_id = 0; + + std::string killer = m_conns.at(conn->player->Killer)->player->GetUsername(); + + std::string mess = getDeathMessage(conn->player->GetUsername(), killer); + + strcpy(chat->mess, 140, mess.c_str()); + chatlog.emplace_back(chat); + ++deadplayers; + conn->m_nsync = false; + } + else { + for (auto& chmo : conn->ChunkDiffs) + chunkdiffs.emplace_back(std::move(chmo)); + conn->ChunkDiffs.clear(); + + for (auto& bull : conn->Bullets) { + bullets.emplace_back(bull); + //Log("POW!", false, false); + BulletAdd* nbul = new BulletAdd(); + nbul->pos = bull->getPos(); + nbul->dir = bull->getVel(); + nbul->id = key; + nbul->tstamp = tstamp; + + netbull.emplace_back(std::move(nbul)); + } + conn->Bullets.clear(); + } + + /* Out */ + + conn->sendPacks(m_sock_udp, m_conns, timer); + } + if ((deadplayers == players - 1 && deadplayers != 0) || timer <= 0) + endgame = true; + } + + for (auto& bull : netbull) { + for (auto& [key, conn] : m_conns) + if (bull->id != conn->GetHash(false)) // Pour pas repitcher au joueur sa propre balle. + sendPackTo(m_sock_udp, bull, &m_buf, conn->getAddr()); + delete bull; + } + netbull.clear(); + + for (auto bull = bullets.begin(); bull != bullets.end(); ++bull) { + ChunkMod* cmod = nullptr; + Bullet* bullet = *bull; + if (bullet->Update(m_world, (1. / 60.), 20, m_players, &cmod)) { + if (cmod) + chunkdiffs.emplace_back(cmod); + bullit.push_back(bull); + delete bullet; + } + } + for (auto& bull: bullit) + bullets.erase(bull); + bullit.clear(); + + for (auto& chat : chatlog) { + Log(chat->mess, false, false); + for (auto& [key, conn] : m_conns) + sendPackTo(m_sock_udp, chat, &m_buf, conn->getAddr()); + delete chat; + } + chatlog.clear(); + + for (auto& chmo : chunkdiffs) { + for (auto& [key, conn] : m_conns) + sendPackTo(m_sock_udp, chmo, &m_buf, conn->getAddr()); + delete chmo; + } + chunkdiffs.clear(); } - //while (true) { - // if (recvfrom(m_sock_udp, m_buf.ptr, m_buf.len, 0, (sockaddr*)&sockad, &socklen) > 0) { - // Packet pck = getPack(&m_buf); - // switch (pck.type) { - // using enum netprot::PACKET_TYPE; - // case ERR: std::puts("ERROR!"); break; - // case INPUT: std::puts("INPUT!"); break; - // case OUTPUT: std::puts("OUTPUT!"); break; - // case SYNC: std::puts("SYNC!"); break; - // case TEAMINF: std::puts("TEAMINF!"); break; - // case SELFINF: std::puts("SELFINF!"); break; - // case PLAYINF: std::puts("PLAYINF!"); break; - // case LOGINF: std::puts("LOGINF!"); break; - // case CHUNKMOD: std::puts("CHUNKMOD!"); break; - // case PLAYERMOD: std::puts("PLAYERMOD!"); break; - // case PICKUPMOD: std::puts("PICKUPMOD!"); break; - // case GAMEINFO: std::puts("GAMEINFO!"); break; - // case ENDINFO: std::puts("ENDINFO!"); break; - // case CHAT: std::puts("CHAT!"); break; - // case ERRLOG: std::puts("ERRLOG!"); break; - // case LAST_PACK: [[falltrough]]; - // default: std::puts("wtf?!"); break; - // } - // netprot::emptyPack(pck); - // } - //} + Chat end; + end.src_id = 0; + char endmess[] = "Game over, man. Game over."; + strcpy(end.mess, 140, endmess); + for (auto& [key, conn] : m_conns) { + std::string str = conn->player->GetUsername(); + Log(str.append(" ").append(std::to_string(conn->player->GetHP())), false, false); + + } + + for (auto& [key, conn] : m_conns) + sendPackTo(m_sock_udp, &end, &m_buf, conn->getAddr()); + + // TODO: Gérer les 2-3 secondes post-game avant le billboard pour pas avoir un whiplash à la fin de la game. + + char* ch = new char[2]; + std::cout << "Nouvelle partie? [o/N] "; + std::cin.getline(ch, 2); + std::cout << std::endl; + + m_exit = true; + if (ch[0] == 'o' || ch[0] == 'O') + m_exit = false; + + delete[] ch; } +void Server::Cleanup() { + for (auto& [key, conn] : m_conns) + delete conn; + + m_conns.clear(); + m_players.clear(); + delete m_world; + m_world = nullptr; +} + +void Server::DeInit() { + if (m_logfile.is_open()) + m_logfile.close(); + if (m_sock_udp) + closesocket(m_sock_udp); + if (m_sock_tcp) + closesocket(m_sock_tcp); + +#ifdef _WIN32 + WSACleanup(); +#endif +} + +bool Server::NewGameRequested() const { return !m_exit; } + inline std::string Server::LogTimestamp() { time_t rawtime; tm timeinfo; @@ -260,13 +435,13 @@ inline std::string Server::LogTimestamp() { void Server::Log(std::string str, bool is_error = false, bool is_fatal = false) { switch (m_log) { using enum LOG_DEST; // C++20! - case LOGFILE: - m_logfile << LogTimestamp() << (is_fatal ? "FATAL " : "") << (is_error ? "ERROR " : "") << str << std::endl; - break; - case CONSOLE: [[fallthrough]]; // Pour dire que c'est voulu que ça traverse vers le case en dessous (C++17!) - default: - std::cout << LogTimestamp() << (is_fatal ? "FATAL " : "") << (is_error ? "ERROR " : "") << str << std::endl; - break; + case LOGFILE: + m_logfile << LogTimestamp() << (is_fatal ? "FATAL " : "") << (is_error ? "ERROR " : "") << str << std::endl; + break; + case CONSOLE: [[fallthrough]]; // Pour dire que c'est voulu que ça traverse vers le case en dessous (C++17!) + default: + std::cout << LogTimestamp() << (is_fatal ? "FATAL " : "") << (is_error ? "ERROR " : "") << str << std::endl; + break; } if (is_fatal) { @@ -276,10 +451,11 @@ void Server::Log(std::string str, bool is_error = false, bool is_fatal = false) closesocket(m_sock_udp); if (m_sock_tcp) closesocket(m_sock_tcp); - for (const auto& [key, player] : m_players) { + for (const auto& [key, player] : m_conns) closesocket(player->getSock()); - } - m_players.clear(); + + delete m_world; + m_conns.clear(); #ifdef _WIN32 WSACleanup(); #endif @@ -293,7 +469,7 @@ void Server::buildIdList(size_t size) { srand(time(NULL)); do lst.insert(((uint64_t)rand() << 32 | rand())); while (lst.size() < size); - + m_ids = std::vector(lst.begin(), lst.end()); } @@ -302,3 +478,34 @@ uint64_t Server::getUniqueId() { m_ids.pop_back(); return id; } + +std::string Server::getDeathMessage(std::string username, std::string killer) const { + std::string mess; + std::string temp = DEATHMESSAGES.at(rand() % DEATHMESSAGES.size()); + size_t ind = temp.find('@'); + size_t indk = temp.find('$'); + bool bypass = false; + + if (indk == std::string::npos) + bypass = true; + + if (ind < indk || bypass) { + mess.append(temp.substr(0, ind)); + mess.append(username); + if (!bypass) { + mess.append(temp.substr(ind + 1, indk - 1)); + mess.append(killer); + mess.append(temp.substr(indk + 1)); + } + else mess.append(temp.substr(ind + 1)); + } + else { + mess.append(temp.substr(0, indk)); + mess.append(killer); + mess.append(temp.substr(indk + 1, ind - 1)); + mess.append(username); + mess.append(temp.substr(ind + 1)); + } + + return mess; +} diff --git a/SQCSim-srv/server.h b/SQCSim-srv/server.h index dd5a397..c70a457 100644 --- a/SQCSim-srv/server.h +++ b/SQCSim-srv/server.h @@ -1,6 +1,7 @@ #ifndef SERVER_H__ #define SERVER_H__ +#include #include #include #include @@ -23,6 +24,9 @@ public: int Init(); int Ready(); void Run(); + void Cleanup(); + void DeInit(); + bool NewGameRequested() const; private: @@ -36,19 +40,21 @@ private: Buffer m_buf; - std::unordered_map m_players; + std::unordered_map m_players; + std::unordered_map m_conns; std::unordered_map m_chatlog; std::vector m_ids; GameInfo m_game; World* m_world = nullptr; - const bool m_manual_setup = SRV_MANUAL_SETUP; + bool m_exit = true; std::string LogTimestamp(); void Log(std::string str, bool is_error, bool is_fatal); void buildIdList(size_t size); uint64_t getUniqueId(); + std::string getDeathMessage(std::string username, std::string killer) const; }; diff --git a/SQCSim2021/SQCSim2021.vcxproj b/SQCSim2021/SQCSim2021.vcxproj index 31e1b8b..7d14bc6 100644 --- a/SQCSim2021/SQCSim2021.vcxproj +++ b/SQCSim2021/SQCSim2021.vcxproj @@ -91,7 +91,7 @@ false true Unicode - v143 + ClangCL @@ -196,7 +196,7 @@ Fast - Console + Windows false true true diff --git a/SQCSim2021/audio.cpp b/SQCSim2021/audio.cpp index 7691f88..fda7368 100644 --- a/SQCSim2021/audio.cpp +++ b/SQCSim2021/audio.cpp @@ -14,7 +14,7 @@ Audio::Audio(const char * music) { m_engine->setRolloffFactor(2); m_engine->setDefault3DSoundMinDistance(.1); m_engine->setDefault3DSoundMaxDistance(1000); - m_music = m_engine->play2D(music, false, true, true, irrklang::ESM_STREAMING); + m_music = m_engine->play2D(music, true, true, true, irrklang::ESM_STREAMING); } Audio::~Audio() { diff --git a/SQCSim2021/booster.cpp b/SQCSim2021/booster.cpp index 593e16e..4e7417f 100644 --- a/SQCSim2021/booster.cpp +++ b/SQCSim2021/booster.cpp @@ -1,4 +1,4 @@ -#include "booster.h"; +#include "booster.h" void Booster::RenderBillboard(const Vector3f pos, TextureAtlas& textureAtlas, Shader& shader, Transformation tran) { @@ -43,4 +43,4 @@ void Booster::RenderBillboard(const Vector3f pos, TextureAtlas& textureAtlas, S shader.Disable(); //tran.ApplyTranslation(-m_position); //glEnable(GL_DEPTH_TEST); -} \ No newline at end of file +} diff --git a/SQCSim2021/cmake/CMakeLists.txt b/SQCSim2021/cmake/CMakeLists.txt index 4da3eb4..d9ccd33 100644 --- a/SQCSim2021/cmake/CMakeLists.txt +++ b/SQCSim2021/cmake/CMakeLists.txt @@ -28,6 +28,7 @@ include_directories( add_library(SQCSim-common + "${SQCSIM_COMMON_DIR}boostinfo.cpp" "${SQCSIM_COMMON_DIR}blockinfo.cpp" "${SQCSIM_COMMON_DIR}bullet.cpp" "${SQCSIM_COMMON_DIR}chunk.cpp" @@ -40,6 +41,7 @@ add_library(SQCSim-common add_executable(SQCSim-client "../audio.cpp" + "../booster.cpp" "../connector.cpp" "../engine.cpp" "../mesh.cpp" diff --git a/SQCSim2021/connector.cpp b/SQCSim2021/connector.cpp index 867e36e..bcde34e 100644 --- a/SQCSim2021/connector.cpp +++ b/SQCSim2021/connector.cpp @@ -65,20 +65,15 @@ int Connector::Connect(const char* srv_addr, std::string name) { netprot::Buffer bf; netprot::LoginInfo log; - strcpy(log.name, name.c_str()); + strcpy(log.name, 32, name.c_str()); netprot::sendPack(m_sock_tcp, &log, &bf); - //using namespace std::chrono_literals; - //std::this_thread::sleep_for(100ms); - - memset(bf.ptr, '\0', BUFFER_LENGTH); - bool ready = false; int errors = 0; std::vector lsPck; while (!ready) { - lsPck = netprot::recvPacks(m_sock_tcp, &bf); + netprot::recvPacks(m_sock_udp, &bf, &lsPck); for (auto& pck : lsPck) { uint32_t bsize = bf.len - (pck - bf.ptr); @@ -97,7 +92,10 @@ int Connector::Connect(const char* srv_addr, std::string name) { pl = new netprot::PlayerInfo(); if (!netprot::Deserialize(pl, pck, &bsize)) ++errors; - else m_players[pl->id] = pl; + else { + m_players[pl->id] = pl; + std::cout << "A challenger appears! " << pl->name << std::endl; + } break; case TEAMINF: // TODO: Faire dequoi avec TeamInfo si on fini par avoir des teams. diff --git a/SQCSim2021/define.h b/SQCSim2021/define.h index e8b9e47..d0382a7 100644 --- a/SQCSim2021/define.h +++ b/SQCSim2021/define.h @@ -28,8 +28,17 @@ #define BASE_WIDTH 640 #define BASE_HEIGHT 480 + #define ANIME_PATH_JUMP "./media/textures/AssetOtherPlayer/FinalPNGJumping/" #define ANIME_PATH_STILL "./media/textures/AssetOtherPlayer/FinalPNGStanding/" + +//1 = jump shoot sans anim, 2 = jump shoot avec anim +#define ANIM_PATH_JSHOOT1 "./media/textures/AssetOtherPlayer/FinalPNGJumpingShooting/" +#define ANIM_PATH_JSHOOT2 "./media/textures/AssetOtherPlayer/FinalPNGJumpingShooting/ShootingJump/" +//1 = shoot sans anim, 2 = shoot avec anim +#define ANIM_PATH_SSHOOT1 "./media/textures/AssetOtherPlayer/FinalPNGShooting/" +#define ANIM_PATH_SSHOOT2 "./media/textures/AssetOtherPlayer/FinalPNGShooting/Shooting/" + #define TEXTURE_PATH "./media/textures/" #define SHADER_PATH "./media/shaders/" #define AUDIO_PATH "./media/audio/" @@ -39,8 +48,8 @@ enum GameState { MAIN_MENU, SPLASH, + LOBBY, OPTIONS, - QUIT, PLAY, PAUSE }; diff --git a/SQCSim2021/engine.cpp b/SQCSim2021/engine.cpp index 1fc1afb..d27ca25 100644 --- a/SQCSim2021/engine.cpp +++ b/SQCSim2021/engine.cpp @@ -18,7 +18,7 @@ struct Notification { // Use a vector to manage notifications std::vector notifications; -Engine::Engine() : m_remotePlayer(&m_pinfo), m_pinfo() {} +Engine::Engine() {} Engine::~Engine() { m_world.CleanUpWorld(m_renderCount, true); @@ -29,19 +29,12 @@ Engine::~Engine() { } void Engine::Init() { - GLenum glewErr = glewInit(); - if (glewErr != GLEW_OK) { - std::cerr << " ERREUR GLEW : " << glewGetErrorString(glewErr) << std::endl; - abort(); - } - - uint64_t seed = SEED; - glDisable(GL_FRAMEBUFFER_SRGB); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glEnable(GL_POINT_SMOOTH); glEnable(GL_BLEND); + glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); @@ -62,80 +55,34 @@ void Engine::Init() { // Objet de skybox avec sa propre texture et son propre shader! m_skybox.Init(0.2f); // Objet de musique! - //m_audio.ToggleMusicState(); - + //m_menuaudio.ToggleMusicState(); + // Array pour les balles. for (int x = 0; x < MAX_BULLETS; ++x) { m_bullets[x] = nullptr; m_whoosh[x] = nullptr; } - char* ch = new char[2]; - - std::cout << "Jouer en ligne? [o/N] "; - std::cin.getline(ch, 2); - std::cout << std::endl; - - if (*ch == 'o' || *ch == 'O') { - char* input = new char[32]; - std::string playname, srvname; - - while (playname.size() < 1) { - std::cout << "Veuillez entrer un nom de joueur: "; - std::cin.getline(input, 32); - std::cout << std::endl; - playname = input; - if (playname.size() < 1 || playname.size() > 32) - std::puts("Nom invalide."); - } - while (srvname.size() < 1) { - std::cout << "Veuillez entrer une adresse de serveur: "; - std::cin.getline(input, 32); - std::cout << std::endl; - srvname = input; - if (srvname.size() < 1 || srvname.size() > 32) - std::puts("Adresse serveur invalide."); - } - delete[] input; - - if (!m_conn.Init()) { - if (!m_conn.Connect(srvname.c_str(), playname)) { - // setup jeu en reseau. - std::cout << "ID recu du serveur: " << std::to_string(m_conn.getId()) << "!" << std::endl; - std::cout << "Seed recu du serveur: " << std::to_string(m_conn.getSeed()) << "!" << std::endl; - m_player = Player(m_conn.getOrigin().position); - - for (auto& [key, player] : m_conn.m_players) - m_players[key] = new RemotePlayer(player); - - seed = m_conn.getSeed(); - m_networkgame = true; - } - else std::cout << "Erreur de connexion." << std::endl; - } - else std::cout << "Erreur de creation de socket." << std::endl; - } - delete[] ch; - - m_world.SetSeed(seed); - - // Init Chunks m_world.GetChunks().Reset(nullptr); - - m_startTime = std::chrono::high_resolution_clock::now(); - - m_remotePlayer.SetPosition(Vector3f(.5, CHUNK_SIZE_Y + 10., .5)); + m_world.SetSeed(SEED); } void Engine::DeInit() {} void Engine::LoadResource() { + GLenum glewErr = glewInit(); + if (glewErr != GLEW_OK) { + std::cerr << " ERREUR GLEW : " << glewGetErrorString(glewErr) << std::endl; + abort(); + } + LoadTexture(m_skybox.GetTexture(), TEXTURE_PATH "skybox.png", true); LoadTexture(m_textureCrosshair, TEXTURE_PATH "cross.bmp", true); LoadTexture(m_textureFont, TEXTURE_PATH "font.bmp", true); LoadTexture(m_textureGun, TEXTURE_PATH "gun01.png", false); LoadTexture(m_texturePovGun, TEXTURE_PATH "GUN.png", false); + LoadTexture(m_textureLobbyMenu, TEXTURE_PATH "menus/backgrounds/bgLobby.png", false); LoadTexture(m_textureMainMenu, TEXTURE_PATH "menus/backgrounds/bgMainMenu.png", false); LoadTexture(m_texturePauseMenu, TEXTURE_PATH "menus/backgrounds/bgPause.png", false); LoadTexture(m_textureOptionsMenu, TEXTURE_PATH "menus/backgrounds/bgOptions.png", false); @@ -155,12 +102,18 @@ void Engine::LoadResource() { LoadTexture(m_textureOptSensitivity, TEXTURE_PATH "menus/buttons/options/optSensitivity.png", false); LoadTexture(m_textureOptSfx, TEXTURE_PATH "menus/buttons/options/optSfx.png", false); + LoadTexture(m_textureLobbyServer, TEXTURE_PATH "menus/labels/labelServer.png", false); + LoadTexture(m_textureLobbyIdentify, TEXTURE_PATH "menus/labels/labelIdentify.png", false); + LoadTexture(m_textureHd, TEXTURE_PATH "menus/labels/labelHd.png", false); LoadTexture(m_textureHd, TEXTURE_PATH "menus/labels/labelHd.png", false); LoadTexture(m_textureFhd, TEXTURE_PATH "menus/labels/labelFhd.png", false); LoadTexture(m_textureQhd, TEXTURE_PATH "menus/labels/labelQhd.png", false); LoadTexture(m_textureUhd, TEXTURE_PATH "menus/labels/labelUhd.png", false); LoadTexture(m_textureMenuTitle, TEXTURE_PATH "menus/labels/labelTitle.png", false); + LoadTexture(m_texturePauseResume, TEXTURE_PATH "menus/buttons/pause/pauseResume.png", false); + LoadTexture(m_texturePauseMainMenu, TEXTURE_PATH "menus/buttons/pause/pauseMainMenu.png", false); + LoadTexture(m_textureMenuBack, TEXTURE_PATH "menus/buttons/main/mainBack.png", false); LoadTexture(m_textureMenuMulti, TEXTURE_PATH "menus/buttons/main/mainMulti.png", false); LoadTexture(m_textureMenuOptions, TEXTURE_PATH "menus/buttons/main/mainOptions.png", false); @@ -180,28 +133,70 @@ void Engine::LoadResource() { //AJOUTER LES TEXTURES DANS L'ORDRE DE L'ÉNUM + //STILL//STANDING + TextureAtlas::TextureIndex StillFront = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueFrontRight.png"); //0 + TextureAtlas::TextureIndex StillQuarterFrontLeft = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueLeft.png"); //1 + TextureAtlas::TextureIndex StillQuarterFrontRight = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueRight.png"); //2 + TextureAtlas::TextureIndex StillProfiltLeft = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueProfilLeft.png"); //3 + TextureAtlas::TextureIndex StillProfiltRight = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueProfilRight.png"); //4 + TextureAtlas::TextureIndex StillQuarterBackLeft = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueLeftBack.png"); //5 + TextureAtlas::TextureIndex StillQuarterBackRight = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueRightBack.png"); //6 + TextureAtlas::TextureIndex StillBack = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueBackRight.png"); //7 + + //SHOOTINGSTILL SANS TIRER + TextureAtlas::TextureIndex StillFrontShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueFrontRightShootingRight.png"); ////9 + TextureAtlas::TextureIndex StillQuarterFrontLeftShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueFrontRightShootingRight.png"); ////10 + TextureAtlas::TextureIndex StillQuarterFrontRightShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueRightShootingRight.png"); ////11 + TextureAtlas::TextureIndex StillProfiltLeftShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueProfilShootingLeft.png"); ////12 + TextureAtlas::TextureIndex StillProfiltRightShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueProfilShootingRight.png"); ////13 + TextureAtlas::TextureIndex StillQuarterBackLeftShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueBackLeftShootingLeft.png"); ////14 + TextureAtlas::TextureIndex StillQuarterBackRightShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueBackRightShootingRight.png"); ////15 + TextureAtlas::TextureIndex StillBackShoot = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT1 "BlueShootingBackRight.png"); ////16 + + //SHOOTINGSTILL TIRER + TextureAtlas::TextureIndex StillFrontShootFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueFrontRightShootingRightShoot1.png"); ////17 + TextureAtlas::TextureIndex StillQuarterFrontLeftFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueLeftShootingLeftShoot1.png"); ////18 + TextureAtlas::TextureIndex StillQuarterFrontRightShootFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueRightShootingRightShoot1.png"); ////19 + TextureAtlas::TextureIndex StillProfiltLeftShootFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueProfilShootingLeftShoot1.png"); ////20 + TextureAtlas::TextureIndex StillProfiltRightShootFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueProfilShootingRightShoot1.png"); ////21 + TextureAtlas::TextureIndex StillQuarterBackLeftShootFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueBackLeftShootingLeftShoot1.png"); ////22 + TextureAtlas::TextureIndex StillQuarterBackRightShootFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueBackRightShootingRightShoot1.png"); ////23 + TextureAtlas::TextureIndex StillBackShootFire = m_animeAtlas.AddTexture(ANIM_PATH_SSHOOT2 "BlueShootingBackRightShoot1.png"); ////24 + + //JUMP - //TextureAtlas::TextureIndex JumpBack = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueBackJumpRight.png"); - //TextureAtlas::TextureIndex JumpFront = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueFrontJumpRight.png"); - //TextureAtlas::TextureIndex JumpQuarterBackLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftBackJumpLeft.png"); - //TextureAtlas::TextureIndex JumpQuarterBackRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightBackJumpRight.png"); - //TextureAtlas::TextureIndex JumpProfiltLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilJumpLeft.png"); - //TextureAtlas::TextureIndex JumpProfiltRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilJumpRight.png"); - //TextureAtlas::TextureIndex JumpQuarterFrontLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftFrontJumpLeft.png"); - //TextureAtlas::TextureIndex JumpQuarterFrontRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightFrontJumpRight.png"); + TextureAtlas::TextureIndex JumpFront = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueFrontJumpRight.png"); ////25 + TextureAtlas::TextureIndex JumpQuarterFrontLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftFrontJumpLeft.png"); ////26 + TextureAtlas::TextureIndex JumpQuarterFrontRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightFrontJumpRight.png"); ////27 + TextureAtlas::TextureIndex JumpProfiltLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilJumpLeft.png"); ////28 + TextureAtlas::TextureIndex JumpProfiltRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilJumpRight.png"); ////29 + TextureAtlas::TextureIndex JumpQuarterBackLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftBackJumpLeft.png"); ////30 + TextureAtlas::TextureIndex JumpQuarterBackRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightBackJumpRight.png"); ////31 + TextureAtlas::TextureIndex JumpBack = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueBackJumpRight.png"); ////32 + + + //SHOOTINGJUMP SANS TIRER + TextureAtlas::TextureIndex JumpFrontShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BlueFrontJumpRightShootingRight.png"); ////33 + TextureAtlas::TextureIndex JumpQuarterFrontLeftShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BlueFrontLeftJumpLeftShootingLeft.png"); ////34 + TextureAtlas::TextureIndex JumpQuarterFrontRightShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BlueFrontRightJumpRightShootingRight.png"); ////35 + TextureAtlas::TextureIndex JumpProfiltLeftShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BlueProfilLeftJumpLeftShootingLeft.png"); ////36 + TextureAtlas::TextureIndex JumpProfiltRightShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BluerProfilRightJumprightShootingRight.png"); ////37 + TextureAtlas::TextureIndex JumpQuarterBackLeftShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BlueBackLeftJumpLeftShootingLeft.png"); ////38 + TextureAtlas::TextureIndex JumpQuarterBackRightShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BlueBackRightJumpRightShootingRight.png"); ////39 + TextureAtlas::TextureIndex JumpBackShoot = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT1 "BlueBackJumpRightShootingRight.png"); ////40 + + + //SHOOTINGJUMP TIRER + TextureAtlas::TextureIndex JumpFrontShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BlueFrontJumpRightShootingRightShoot1.png"); ////41 + TextureAtlas::TextureIndex JumpQuarterFrontLeftShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BlueFrontLeftJumpLeftShootingLeftShoot1.png"); ////42 + TextureAtlas::TextureIndex JumpQuarterFrontRightShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BlueFrontRightJumpRightShootingRightShoot1.png"); ////43 + TextureAtlas::TextureIndex JumpProfiltLeftShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BlueProfilLeftJumpLeftShootingLeftShoot1.png"); ////44 + TextureAtlas::TextureIndex JumpProfiltRightShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BluerProfilRightJumprightShootingRightShoot1.png"); ////45 + TextureAtlas::TextureIndex JumpQuarterBackLeftShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BlueBackLeftJumpLeftShootingLeftShoot1.png"); ////46 + TextureAtlas::TextureIndex JumpQuarterBackRightShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BlueBackRightJumpRightShootingRightShoot1.png"); ////47 + TextureAtlas::TextureIndex JumpBackShootFire = m_animeAtlas.AddTexture(ANIM_PATH_JSHOOT2 "BlueBackJumpRightShootingRightShoot1.png"); ////48 - //STILL - //TextureAtlas::TextureIndex StillBack = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueBackRight.png"); - TextureAtlas::TextureIndex StillFront = m_animeAtlas.AddTexture(ANIME_PATH_STILL "BlueFrontRight.png"); - //TextureAtlas::TextureIndex StillQuarterBackLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeftBack.png"); - //TextureAtlas::TextureIndex StillQuarterBackRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRightBack.png"); - //TextureAtlas::TextureIndex StillProfiltLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilLeft.png"); - //TextureAtlas::TextureIndex StillProfiltRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueProfilRight.png"); - //TextureAtlas::TextureIndex StillQuarterFrontLeft = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueLeft.png"); - //TextureAtlas::TextureIndex StillQuarterFrontRight = m_animeAtlas.AddTexture(ANIME_PATH_JUMP "BlueRight.png"); - //SHOOTINGSTILL - //SHOOTINGJUMP if (!m_animeAtlas.Generate(TEXTURE_SIZE, false)) { std::cout << " Unable to generate texture atlas ..." << std::endl; @@ -325,6 +320,7 @@ void Engine::ProcessNotificationQueue() { glMatrixMode(GL_PROJECTION); glPopMatrix(); + glMatrixMode(GL_MODELVIEW); glPopMatrix(); @@ -343,14 +339,10 @@ void Engine::DisplayCrosshair() { glLoadIdentity(); glTranslated(Width() / 2 - crossSize / 2, Height() / 2 - crossSize / 2, 0); glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2i(0, 0); - glTexCoord2f(1, 0); - glVertex2i(crossSize, 0); - glTexCoord2f(1, 1); - glVertex2i(crossSize, crossSize); - glTexCoord2f(0, 1); - glVertex2i(0, crossSize); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(crossSize, 0); + glTexCoord2f(1, 1); glVertex2i(crossSize, crossSize); + glTexCoord2f(0, 1); glVertex2i(0, crossSize); glEnd(); } @@ -360,6 +352,7 @@ void Engine::DisplayHud(int timer) { glBindTexture(GL_TEXTURE_2D, 0); glLoadIdentity(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glClear(GL_STENCIL_BUFFER_BIT); float itemBackgroundWidthProportion = 0.25f; float itemBackgroundHeightProportion = 0.175f; @@ -381,6 +374,8 @@ void Engine::DisplayHud(int timer) { // HP Bar float playerHp = m_player.GetHP(); + if (playerHp < 0.) + playerHp == 0; float facteurOmbrage = m_displayInfo ? 0.5f : 1.0f; float hpBarWidthProportion = 0.25f; @@ -466,26 +461,26 @@ void Engine::DrawHud(float elapsedTime, BlockType bloc) { glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBlendEquation(GL_FUNC_ADD); - glEnable(GL_BLEND); glMatrixMode(GL_PROJECTION); glPushMatrix(); - glLoadIdentity(); glOrtho(0, Width(), 0, Height(), -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); + glLoadIdentity(); int timer = GetCountdown(elapsedTime); - for (int i = 1; i < WORLD_SIZE_X; i++) { + /*for (int i = 1; i < WORLD_SIZE_X; i++) { if (timer <= COUNTDOWN - m_timerReductionChunk * i) { m_world.RemoveChunk(m_nbReductionChunk * i); m_renderer.RemoveChunk(m_nbReductionChunk * i); } - } + }*/ if (m_keyK) { SystemNotification(m_messageNotification); m_keyK = false; @@ -511,14 +506,13 @@ void Engine::DrawHud(float elapsedTime, BlockType bloc) { glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR); glBlendEquation(GL_FUNC_SUBTRACT); - glEnable(GL_STENCIL_TEST); - glEnable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); glPopMatrix(); - glMatrixMode(GL_MODELVIEW); glPopMatrix(); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); } void Engine::DisplayPovGun() { @@ -531,12 +525,12 @@ void Engine::DisplayPovGun() { glMatrixMode(GL_PROJECTION); glPushMatrix(); - glLoadIdentity(); glOrtho(0, Width(), 0, Height(), -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); + glLoadIdentity(); float baseXOffsetPercentage = 0.4958; float baseWidthPercentage = 0.4688; @@ -547,30 +541,21 @@ void Engine::DisplayPovGun() { float quadHeight = baseHeightPercentage * Height(); m_texturePovGun.Bind(); - glLoadIdentity(); glTranslated(xTranslation, 0, 0); glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2i(0, 0); - glTexCoord2f(1, 0); - glVertex2i(quadWidth, 0); - glTexCoord2f(1, 1); - glVertex2i(quadWidth, quadHeight); - glTexCoord2f(0, 1); - glVertex2i(0, quadHeight); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(quadWidth, 0); + glTexCoord2f(1, 1); glVertex2i(quadWidth, quadHeight); + glTexCoord2f(0, 1); glVertex2i(0, quadHeight); glEnd(); - // Reset du blend function - glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR); - glBlendEquation(GL_FUNC_SUBTRACT); - - glEnable(GL_STENCIL_TEST); - glEnable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); + + glEnable(GL_STENCIL_TEST); + glEnable(GL_DEPTH_TEST); } void Engine::PrintText(float x, float y, const std::string& t, float charSizeMultiplier) { @@ -607,23 +592,41 @@ void Engine::PrintText(float x, float y, const std::string& t, float charSizeMul int Engine::GetFps(float elapsedTime) const { return 1 / elapsedTime; } int Engine::GetCountdown(float elapsedTime) { - if (m_resetcountdown) { - m_nbReductionChunk = 4; - m_timerReductionChunk = 30; - m_countdown = m_time + COUNTDOWN; - m_resetcountdown = false; - } - if (m_countdown < m_time) - Stop(); - if (!m_stopcountdown) - m_time += elapsedTime; - return m_countdown - (int)m_time; + return m_countdown; } int Engine::GetOptionsChoice() { return m_selectedOption; } +bool Engine::StartMultiplayerGame() { + bool ok = true; + if (!m_conn.Init()) { + if (!m_conn.Connect(m_serverAddr.c_str(), m_username)) { + // setup jeu en reseau. + std::cout << "ID recu du serveur: " << std::to_string(m_conn.getId()) << "!" << std::endl; + std::cout << "Seed recu du serveur: " << std::to_string(m_conn.getSeed()) << "!" << std::endl; + m_player = Player(m_conn.getOrigin().position); + + for (auto& [key, player] : m_conn.m_players) + m_players[key] = new RemotePlayer(player); + + //m_world.SetSeed(m_conn.getSeed()); + m_world.SetSeed(9370707); + m_networkgame = true; + } + else { + std::cout << "Erreur de connexion." << std::endl; + ok = false; + } + } + else { + std::cout << "Erreur de creation de socket." << std::endl; + ok = false; + } + return ok; +} + void Engine::DisplayInfo(float elapsedTime, BlockType bloc) { m_textureFont.Bind(); std::ostringstream ss; @@ -655,7 +658,7 @@ void Engine::DisplayInfo(float elapsedTime, BlockType bloc) { fPosY = fPosYJump; fPosY -= charSize; - ss << " Velocity : " << m_remotePlayer.GetVelocity(); + ss << " Velocity : " << m_player.GetVelocity(); PrintText(fPosX, fPosY, ss.str()); ss.str(""); fPosY -= charSize; @@ -665,16 +668,16 @@ void Engine::DisplayInfo(float elapsedTime, BlockType bloc) { ss.str(""); fPosY -= charSize; - ss << " Remote Position : " << m_remotePlayer.GetPosition();//m_player.GetPosition(); + ss << " Remote Position : " << m_otherplayerpos; PrintText(fPosX, fPosY, ss.str()); ss.str(""); fPosY -= charSize; - ss << " Block : "; - if (bloc == BTYPE_LAST) - ss << "Weapon"; - else - ss << (int)bloc; + //ss << " Block : "; + //if (bloc == BTYPE_LAST) + // ss << "Weapon"; + //else + // ss << (int)bloc; PrintText(fPosX, fPosYJump, ss.str()); } @@ -709,15 +712,119 @@ void Engine::DisplaySplashScreen() { glPopMatrix(); } -void Engine::DisplayPauseMenu() { +void Engine::DisplayLobbyMenu(float elapsedTime) { + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + m_textureLobbyMenu.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(Width(), 0); + glTexCoord2f(1, 1); glVertex2i(Width(), Height()); + glTexCoord2f(0, 1); glVertex2i(0, Height()); + glEnd(); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + if (m_settingUsername) { + SetPlayerUsername(elapsedTime); + } + else if (m_settingServer) { + SetServerAddress(elapsedTime); + } + + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void Engine::SetPlayerUsername(float elapsedTime) { + m_textureLobbyIdentify.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(Width() * 0.6, Height() * 0.75); + glTexCoord2f(1, 0); glVertex2i(Width() * 0.975, Height() * 0.75); + glTexCoord2f(1, 1); glVertex2i(Width() * 0.975, Height() * 0.95); + glTexCoord2f(0, 1); glVertex2i(Width() * 0.6, Height() * 0.95); + glEnd(); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + HandlePlayerInput(elapsedTime); + glDisable(GL_BLEND); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + +void Engine::SetServerAddress(float elapsedTime) { + m_textureLobbyServer.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(Width() * 0.6, Height() * 0.75); + glTexCoord2f(1, 0); glVertex2i(Width() * 0.975, Height() * 0.75); + glTexCoord2f(1, 1); glVertex2i(Width() * 0.975, Height() * 0.95); + glTexCoord2f(0, 1); glVertex2i(Width() * 0.6, Height() * 0.95); + glEnd(); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + HandlePlayerInput(elapsedTime); + glDisable(GL_BLEND); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +} + +void Engine::DisplayPauseMenu(float elapsedTime) { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); m_texturePauseMenu.Bind(); glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2i(0, 0); - glTexCoord2f(1, 0); glVertex2i(Width(), 0); - glTexCoord2f(1, 1); glVertex2i(Width(), Height()); + glTexCoord2f(0, 0); glVertex2i(0, 0); + glTexCoord2f(1, 0); glVertex2i(Width(), 0); + glTexCoord2f(1, 1); glVertex2i(Width(), Height()); glTexCoord2f(0, 1); glVertex2i(0, Height()); glEnd(); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + m_texturePauseResume.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(Width() * 0.025f, Height() * 0.75); + glTexCoord2f(1, 0); glVertex2i(Width() * 0.33f, Height() * 0.75); + glTexCoord2f(1, 1); glVertex2i(Width() * 0.33f, Height() * 0.95); + glTexCoord2f(0, 1); glVertex2i(Width() * 0.025f, Height() * 0.95); + glEnd(); + + m_texturePauseMainMenu.Bind(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2i(Width() * 0.67f, Height() * 0.75); + glTexCoord2f(1, 0); glVertex2i(Width() * 0.9975f, Height() * 0.75); + glTexCoord2f(1, 1); glVertex2i(Width() * 0.9975f, Height() * 0.95); + glTexCoord2f(0, 1); glVertex2i(Width() * 0.67f, Height() * 0.95); + glEnd(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } void Engine::DisplayMainMenu() { @@ -1155,25 +1262,49 @@ void Engine::Render(float elapsedTime) { return; } + if (m_gamestate == GameState::LOBBY) { + DisplayLobbyMenu(elapsedTime); + if (m_multiReady) { + if (StartMultiplayerGame()) { + std::cout << "Starting multiplayer game reached" << std::endl; + m_gamestate = GameState::PLAY; + //m_menuaudio.ToggleMusicState(); + m_audio.ToggleMusicState(); + m_startTime = std::chrono::high_resolution_clock::now(); + } + else { + std::cout << "Cannot reach server." << std::endl; + m_gamestate = GameState::MAIN_MENU; + } + } + return; + } + if (m_gamestate == GameState::PAUSE) { - DisplayPauseMenu(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + DisplayPauseMenu(elapsedTime); + ShowCursor(); return; } if (m_gamestate == GameState::PLAY) { HideCursor(); - CenterMouse(); //D�placement de centermouse dans l'action de jouer + CenterMouse(); - //static float gameTime = elapsedTime; static irrklang::ISound* step; // Pour les sons de pas. static float pollTime = 0; static float bulletTime = 0; - static float gameTime = 0; static BlockType bloc = 1; if (elapsedTime > 0.1f) return; - //gameTime += elapsedTime; pollTime += elapsedTime; Transformation all; @@ -1214,22 +1345,12 @@ void Engine::Render(float elapsedTime) { m_player.ApplyTransformation(skybox, false); // Version d'ApplyTransformation qui ne tient compte que de la rotation // (donc l'objet ne bouge pas relativement au joueur, ce qui est pratique pour une skybox!). - m_player.ApplyTransformation(remotePlayer, true, false); - if (m_key1) bloc++; - else if (m_key2) bloc--; - - if (m_mouseWU) bloc++; - else if (m_mouseWD) bloc--; - if (bloc == BTYPE_LAST + 1) bloc = BTYPE_AIR + 1; - else if (bloc == BTYPE_AIR) bloc = BTYPE_LAST; // La selection de BTYPE_LAST �quipe l'arme. m_mouseWU = m_mouseWD = m_key1 = m_key2 = false; - - if (m_mouseL) { - if (bloc != BTYPE_LAST) - m_world.ChangeBlockAtCursor(bloc, m_player.GetPosition(), m_player.GetDirection(), m_block); - else if (bulletTime <= 0.f) { + netprot::ChunkMod* cmod = nullptr; + if (!m_player.AmIDead() && m_mouseL) { + if (bulletTime <= 0.f) { for (int x = 0; x < MAX_BULLETS; ++x) // Ajouter une balle dans l'array (aussi connu sous le nom de "faire pow pow"). if (!m_bullets[x]) { m_bullets[x] = new Bullet(m_player.GetPOV() + m_player.GetDirection(), m_player.GetDirection()); @@ -1250,80 +1371,105 @@ void Engine::Render(float elapsedTime) { } } else if (m_mouseR) - m_world.ChangeBlockAtCursor(BTYPE_AIR, m_player.GetPosition(), m_player.GetDirection(), m_block); + cmod = m_world.ChangeBlockAtCursor(BTYPE_METAL, m_player.GetPosition(), m_player.GetDirection(), m_block, m_networkgame); + static netprot::ChunkMod** wat = &m_chunkmod; for (int x = 0; x < MAX_BULLETS; ++x) { // Array de bullets en jeu. if (m_bullets[x]) { for (int b = 0; b < BULLET_UPDATES_PER_FRAME; ++b) { - if (m_bullets[x]->Update(&m_world, elapsedTime, BULLET_UPDATES_PER_FRAME, m_players)) { + if (m_bullets[x]->Update(&m_world, elapsedTime, BULLET_UPDATES_PER_FRAME, m_players, m_networkgame ? wat : nullptr)) { m_bullets[x]->~Bullet(); - if (m_whoosh[x]) - m_whoosh[x]->drop(); + + if (m_chunkmod) { + m_chunkmod_manifest.push_back(std::move(m_chunkmod)); + m_chunkmod = nullptr; + } m_bullets[x] = nullptr; - m_whoosh[x] = nullptr; + //if (m_whoosh[x]) + // m_whoosh[x]->drop(); + //m_whoosh[x] = nullptr; break; } - else if (!m_whoosh[x]) { - m_whoosh[x] = m_audio.Create3DAudioObj(m_whoosh[x], AUDIO_PATH "noise.wav", m_bullets[x]->getPos(), m_bullets[x]->getVel(), true, (m_bullets[x]->getPos() - m_player.GetPosition()).Length()); - } - else { - Vector3f pos = m_bullets[x]->getPos(), vel = m_bullets[x]->getVel(); - m_audio.Render3DAudioObj(m_whoosh[x], pos, vel, 5 - (m_bullets[x]->getPos() - m_player.GetPosition()).Length()); - } + // else if (!m_whoosh[x]) { + // m_whoosh[x] = m_audio.Create3DAudioObj(m_whoosh[x], AUDIO_PATH "noise.wav", m_bullets[x]->getPos(), m_bullets[x]->getVel(), true, (m_bullets[x]->getPos() - m_player.GetPosition()).Length()); + // } + // else { + // Vector3f pos = m_bullets[x]->getPos(), vel = m_bullets[x]->getVel(); + // m_audio.Render3DAudioObj(m_whoosh[x], pos, vel, 5 - (m_bullets[x]->getPos() - m_player.GetPosition()).Length()); + // } } } } - gameTime += elapsedTime * 10; - - Vector3f dance = Vector3f(sin(gameTime), 0, cos(-gameTime)); - dance.Normalize(); - m_remotePlayer.ApplyPhysics(dance, &m_world, elapsedTime); m_world.Update(m_bullets, m_player.GetPosition(), m_blockinfo); m_renderer.UpdateMesh(&m_world, m_player.GetPosition(), m_blockinfo); - m_remotePlayer.Render(m_animeAtlas, m_shader01, all, elapsedTime); - m_booster.RenderBillboard({ 195,16,195 }, m_textureAtlas, m_shader01, all); - - if (m_isSkybox) m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas); - - //glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - //m_remotePlayer.Render(m_textureAtlas, m_shader01, all, elapsedTime); - m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas); if (m_isSkybox) m_skybox.Render(skybox); - DrawHud(elapsedTime, bloc); - DisplayPovGun(); ProcessNotificationQueue(); if (m_damage) { InstantDamage(); } - static bool fell = false; - if (m_player.GetPosition().y < 1.7f && !fell) { + static bool died = false; + if ((m_player.GetPosition().y < -1.7f || m_player.AmIDead()) && !died) { m_audio.Create3DAudioObj(m_scream, AUDIO_PATH "scream.wav", m_player.GetPOV(), m_player.GetVelocity(), false, 1.f); - fell = true; + died = true; } - else if (m_player.GetPosition().y < -20.f) { - m_player = Player(Vector3f(.5f, CHUNK_SIZE_Y + 1.8f, .5f)); // Respawn si le bonho- joueur tombe en bas du monde. - fell = false; + if (m_player.GetPosition().y < -21.f || died) { + died = false; + std::string user = m_player.m_username.append(" (Dead)"); + m_player = Player(Vector3f(.5, CHUNK_SIZE_Y + 1.7f, .5), 0, 0); + m_player.m_username = user; + m_player.InflictDamage(-m_player.GetHP()); } + m_time += elapsedTime; + if (m_networkgame) { // Pour se gerer le paquet. + static bool has_synced = false; using namespace std::chrono; using namespace netprot; Timestamp tstamp = duration_cast(high_resolution_clock::now() - m_startTime).count(); + static Timestamp last = 0; Input input; Sync sync; uint64_t id = m_conn.getId(); static std::vector lsPck; + static int sync_acc = 0, cmod_acc = 0; - if (false) { // TODO: Faire un checkup pour chaque ~1000ms. + if (cmod) + m_chunkmod_manifest.emplace_back(cmod); + + if (last == 0) + last = tstamp; + + sync_acc += tstamp - last; + cmod_acc += tstamp - last; + last = tstamp; + + if (sync_acc >= 1000) { + sync_acc -= 1000; sync.sid = id; sync.timestamp = tstamp; - sync.position = m_player.GetPosition(); + sync.position = m_player.GetPositionAbs(); sync.hp = m_player.GetHP(); - // TODO: Garrocher ca quelque-part. + if (!has_synced) { + has_synced = true; + sendPackTo(m_conn.m_sock_udp, &sync, &m_bufout, &m_conn.m_srvsockaddr); + } + m_syncs[sync.timestamp] = sync; + } + + if (cmod_acc >= 3000) { + while (cmod_acc >= 3000) + cmod_acc -= 3000; + if (!m_chunkmod_manifest.empty()) { + ChunkMod* cmod = m_chunkmod_manifest.front(); + m_chunkmod_manifest.pop_front(); + m_world.ChangeBlockAtPosition(cmod->old_b_type, cmod->pos); + delete cmod; + } } input.sid = id; @@ -1339,11 +1485,11 @@ void Engine::Render(float elapsedTime) { sendPackTo(m_conn.m_sock_udp, &input, &m_bufout, &m_conn.m_srvsockaddr); - lsPck = recvPacks(m_conn.m_sock_udp, &m_buf); + recvPacks(m_conn.m_sock_udp, &m_buf, &lsPck); char* prevptr = nullptr; + Chat chat; for (auto& pck : lsPck) { // We could make a few threads out of this. - Sync sync; - Output out; + Sync sync; Output out; ChunkMod cmod; BulletAdd bull; if (!prevptr) prevptr = m_buf.ptr; uint32_t bsize = m_buf.len - (pck - prevptr); @@ -1352,23 +1498,110 @@ void Engine::Render(float elapsedTime) { using enum PACKET_TYPE; case SYNC: if (Deserialize(&sync, pck, &bsize)) { - if (sync.sid != m_conn.getId()) + if (sync.sid != m_conn.getId()) { + SystemNotification("syncsid be no good."); break; - // TODO: Vérifier si les positions concordent au sync local. + } + if (m_syncs.count(sync.timestamp)) { + Sync comp = m_syncs[sync.timestamp]; + + std::cout << sync.hp << std::endl; + + m_player.InflictDamage(sync.hp - comp.hp); + + Vector3f diff = sync.position - comp.position; + + if (diff.y < 1.) + diff.y = 0; + + if (diff.Length() > 1.5) { + diff.Normalize(); + m_player.Move(-diff); + } + + m_countdown = sync.timer; + + m_syncs.erase(sync.timestamp); + } } break; case OUTPUT: if (Deserialize(&out, pck, &bsize)) { - RemotePlayer* r = (RemotePlayer*)m_players[out.id]; - r->Feed(out); + if (!m_players.contains(out.id)) { + SystemNotification(std::to_string(out.id).append(" is id no good.")); + break; + } + RemotePlayer* rt = static_cast(m_players[out.id]); + rt->Feed(out); + if (rt->AmIDead()) { + m_audio.Create3DAudioObj(m_scream, AUDIO_PATH "scream.wav", m_player.GetPOV(), m_player.GetVelocity(), false, 1.f); + } } break; + case CHUNKMOD: + if (Deserialize(&cmod, pck, &bsize)) { + if (!std::erase_if(m_chunkmod_manifest, // Efface le chunkmod du manifeste s'il est dedans et reset le countdown, sinon fait la modification. + [cmod](ChunkMod* c) { + return cmod.pos == c->pos && + cmod.b_type == c->b_type && + cmod.old_b_type == c->old_b_type; + })) + m_world.ChangeBlockAtPosition(cmod.b_type, cmod.pos); + else cmod_acc = 0; + } + else SystemNotification("cmod iznogoud."); + break; + case BULLET: + if (Deserialize(&bull, pck, &bsize)) { + Bullet* bult = new Bullet(bull.pos, bull.dir); + for (int x = 0; x < MAX_BULLETS; ++x) // Ajouter une balle dans l'array (aussi connu sous le nom de "faire pow pow"). + if (!m_bullets[x]) { + m_bullets[x] = bult; + break; + } + else if (x == MAX_BULLETS - 1) { // S'il y a pas d'espace dans l'array, prendre la place de la première balle de l'array. + m_bullets[0]->~Bullet(); + m_bullets[0] = bult; + break; + } + m_audio.Create3DAudioObj(m_powpow, AUDIO_PATH "pow.wav", bull.pos, bull.dir, false, 1.f); + } + else SystemNotification("Bullet is kraput."); + break; + case CHAT: + if (Deserialize(&chat, pck, &bsize)) + SystemNotification(chat.mess); + else SystemNotification("Chat iznogoud."); + break; default: + SystemNotification("packet be no good."); break; } } lsPck.clear(); + + glDisable(GL_CULL_FACE); + for (auto& [key, player] : m_players) { + RemotePlayer* rt = static_cast(player); + glClear(GL_STENCIL_BUFFER_BIT); + rt->Render(m_animeAtlas, m_shader01, all, elapsedTime, m_player); + } + glEnable(GL_CULL_FACE); } + else { + if (m_resetcountdown) { + m_nbReductionChunk = 4; + m_timerReductionChunk = 30; + m_countdown = m_time + COUNTDOWN; + m_resetcountdown = false; + } + if (!m_stopcountdown) { + m_countdown = COUNTDOWN - (int)m_time; + } + } + + DrawHud(elapsedTime, bloc); + DisplayPovGun(); } } @@ -1450,9 +1683,11 @@ void Engine::DrawSlider(float centerX, float centerY, float value, float minVal, } } - - void Engine::KeyPressEvent(unsigned char key) { + if (m_gamestate == LOBBY) { + m_inputChar = SimulateKeyboard(key); + return; + } switch (key) { case 0: // A - Gauche if (!m_keyA) { @@ -1475,13 +1710,16 @@ void Engine::KeyPressEvent(unsigned char key) { } break; case 36: // ESC - Quitter + if (m_networkgame) + Stop(); if (m_gamestate == GameState::PLAY) { m_gamestate = GameState::PAUSE; } else if (m_gamestate == GameState::PAUSE) { m_gamestate = GameState::PLAY; } - //Stop(); + //m_menuaudio.ToggleMusicState(); + m_audio.ToggleMusicState(); break; case 57: // Space - Sauter if (!m_keySpace) { @@ -1533,6 +1771,12 @@ void Engine::KeyPressEvent(unsigned char key) { } void Engine::KeyReleaseEvent(unsigned char key) { + if (m_gamestate == LOBBY) { + if (key == 38) { + m_keyShift = false; + } + return; + } switch (key) { case 0: // A - Stop gauche m_keyA = false; @@ -1565,7 +1809,7 @@ void Engine::KeyReleaseEvent(unsigned char key) { m_keyL = false; break; case 12: // M - Toggle music - m_audio.ToggleMusicState(); + //m_audio.ToggleMusicState(); break; case 15: for (int x = 0; x < MAX_BULLETS; ++x) // Ajouter une balle dans l'array (aussi connu sous le nom de "faire pow pow"). @@ -1604,12 +1848,254 @@ void Engine::KeyReleaseEvent(unsigned char key) { case 28: // 2 m_key2 = true; break; + case 38: // Shift + m_keyShift = false; + break; case 57: // Espace - Stop sauter m_keySpace = false; break; + case 58: // Enter - comfirm input + m_keyEnter = false; + break; + case 59: // backspace - remove char + m_keyBackspace = false; + break; } } +char Engine::SimulateKeyboard(unsigned char key) { + switch (key) { + case 0: // A + if (!m_keyShift) { m_inputChar = 'a'; } + else { m_inputChar = 'A'; } + break; + case 1: // B + if (!m_keyShift) { m_inputChar = 'b'; } + else { m_inputChar = 'B'; } + break; + case 2: // C + if (!m_keyShift) { m_inputChar = 'c'; } + else { m_inputChar = 'C'; } + break; + case 3: // D + if (!m_keyShift) { m_inputChar = 'd'; } + else { m_inputChar = 'D'; } + break; + case 4: // E + if (!m_keyShift) { m_inputChar = 'e'; } + else { m_inputChar = 'E'; } + break; + case 5: // F + if (!m_keyShift) { m_inputChar = 'f'; } + else { m_inputChar = 'F'; } + break; + case 6: // G + if (!m_keyShift) { m_inputChar = 'g'; } + else { m_inputChar = 'G'; } + break; + case 7: // H + if (!m_keyShift) { m_inputChar = 'h'; } + else { m_inputChar = 'H'; } + break; + case 8: // I + if (!m_keyShift) { m_inputChar = 'i'; } + else { m_inputChar = 'I'; } + break; + case 9: // J + if (!m_keyShift) { m_inputChar = 'j'; } + else { m_inputChar = 'J'; } + break; + case 10: // K + if (!m_keyShift) { m_inputChar = 'k'; } + else { m_inputChar = 'K'; } + break; + case 11: // L + if (!m_keyShift) { m_inputChar = 'l'; } + else { m_inputChar = 'L'; } + break; + case 12: // M + if (!m_keyShift) { m_inputChar = 'm'; } + else { m_inputChar = 'M'; } + break; + case 13: // N + if (!m_keyShift) { m_inputChar = 'n'; } + else { m_inputChar = 'N'; } + break; + case 14: // O + if (!m_keyShift) { m_inputChar = 'o'; } + else { m_inputChar = 'O'; } + break; + case 15: // P + if (!m_keyShift) { m_inputChar = 'p'; } + else { m_inputChar = 'P'; } + break; + case 16: // Q + if (!m_keyShift) { m_inputChar = 'q'; } + else { m_inputChar = 'Q'; } + break; + case 17: // R + if (!m_keyShift) { m_inputChar = 'r'; } + else { m_inputChar = 'R'; } + break; + case 18: // S + if (!m_keyShift) { m_inputChar = 's'; } + else { m_inputChar = 'S'; } + break; + case 19: // T + if (!m_keyShift) { m_inputChar = 't'; } + else { m_inputChar = 'T'; } + break; + case 20: // U + if (!m_keyShift) { m_inputChar = 'u'; } + else { m_inputChar = 'U'; } + break; + case 21: // V + if (!m_keyShift) { m_inputChar = 'v'; } + else { m_inputChar = 'V'; } + break; + case 22: // W + if (!m_keyShift) { m_inputChar = 'w'; } + else { m_inputChar = 'W'; } + break; + case 23: // X + if (!m_keyShift) { m_inputChar = 'x'; } + else { m_inputChar = 'X'; } + break; + case 24: // Y + if (!m_keyShift) { m_inputChar = 'y'; } + else { m_inputChar = 'Y'; } + break; + case 25: // Z + if (!m_keyShift) { m_inputChar = 'z'; } + else { m_inputChar = 'Z'; } + break; + case 26: // 0 + if (!m_keyShift) { m_inputChar = '0'; } + else { m_inputChar = ')'; } + break; + case 27: // 1 + if (!m_keyShift) { m_inputChar = '1'; } + else { m_inputChar = '!'; } + break; + case 28: // 2 + if (!m_keyShift) { m_inputChar = '2'; } + else { m_inputChar = '\"'; } + break; + case 29: // 3 + if (!m_keyShift) { m_inputChar = '3'; } + else { m_inputChar = '/'; } + break; + case 30: // 4 + if (!m_keyShift) { m_inputChar = '4'; } + else { m_inputChar = '$'; } + break; + case 31: // 5 + if (!m_keyShift) { m_inputChar = '5'; } + else { m_inputChar = '%'; } + break; + case 32: // 6 + if (!m_keyShift) { m_inputChar = '6'; } + else { m_inputChar = '?'; } + break; + case 33: // 7 + if (!m_keyShift) { m_inputChar = '7'; } + else { m_inputChar = '&'; } + break; + case 34: // 8 + if (!m_keyShift) { m_inputChar = '8'; } + else { m_inputChar = '*'; } + break; + case 35: // 9 + if (!m_keyShift) { m_inputChar = '9'; } + else { m_inputChar = ')'; } + break; + case 38: // SHIFT + m_keyShift = true; + break; + case 50: // . (Period) + m_inputChar = '.'; + break; + case 56: // _ (Underscore) + if (!m_keyShift) { m_inputChar = '-'; } + else { m_inputChar = '_'; } + break; + case 57: // SPACE + m_inputChar = ' '; + break; + case 58: // ENTER + m_keyEnter = true; + break; + case 59: // BACKSPACE + m_keyBackspace = true; + break; + default: + m_invalidChar = true; + break; + } + + if ((int)key != 38 && !m_invalidChar) { + m_charChanged = true; + } + + m_invalidChar = false; + return m_inputChar; +} + +void Engine::HandlePlayerInput(float elapsedTime) { + static float lobbyTime = 0.0f; + lobbyTime += elapsedTime; + float onInterval = 0.5f; + float offInterval = 1.0f; + + m_textureFont.Bind(); + std::ostringstream ss; + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + if (m_charChanged) { + if (m_keyBackspace) { + if (!m_currentInputString.empty()) { + m_currentInputString.pop_back(); + } + m_keyBackspace = false; + } + else if (m_keyEnter) { + if (m_settingUsername) { + if (!m_currentInputString.empty() && + m_currentInputString.size() > 1 && + m_currentInputString.size() < 26) { + m_username = m_currentInputString; + m_currentInputString = ""; + m_settingUsername = false; + m_settingServer = true; + } + } + else if (m_settingServer) { + if (!m_currentInputString.empty()) { + m_serverAddr = m_currentInputString; + m_currentInputString = ""; + m_settingServer = false; + m_multiReady = true; + } + } + m_keyEnter = false; + } + else if (m_settingUsername && m_currentInputString.size() < 26) { + m_currentInputString += m_inputChar; + } + else if (m_settingServer && m_currentInputString.size() < 15) { + m_currentInputString += m_inputChar; + } + } + + ss << m_currentInputString; + m_charChanged = false; + + ss << (lobbyTime < onInterval ? "_" : (lobbyTime > onInterval && lobbyTime < offInterval) ? " " : (lobbyTime = 0.0f, "")); + PrintText(Width() * 0.6f, Height() * 0.4f, ss.str(), 2.0f); +} + + void Engine::MouseMoveEvent(int x, int y) { if (m_gamestate == GameState::PLAY) { m_player.TurnLeftRight(x - (Width() / 2)); @@ -1690,6 +2176,7 @@ void Engine::MousePressEvent(const MOUSE_BUTTON& button, int x, int y) { if (x > leftButton && x < rightButton && y > bottomFirst && y < topFirst) { if (m_selectedPlayOptions) { m_gamestate = GameState::PLAY; + m_audio.ToggleMusicState(); } else { m_selectedPlayOptions = true; @@ -1697,7 +2184,8 @@ void Engine::MousePressEvent(const MOUSE_BUTTON& button, int x, int y) { } else if (x > leftButton && x < rightButton && y > bottomSecond && y < topSecond) { if (m_selectedPlayOptions) { - m_gamestate = GameState::PLAY; + m_gamestate = GameState::LOBBY; + m_settingUsername = true; } else { m_gamestate = GameState::OPTIONS; @@ -1708,7 +2196,7 @@ void Engine::MousePressEvent(const MOUSE_BUTTON& button, int x, int y) { m_selectedPlayOptions = false; } else { - m_gamestate = GameState::QUIT; + Stop(); } } } @@ -1807,6 +2295,26 @@ void Engine::MousePressEvent(const MOUSE_BUTTON& button, int x, int y) { m_selectedGameplaySensitivityBar = true; } } + else if (m_gamestate == GameState::PAUSE) { + float leftResume = centerX - Width() * 0.4735f; + float rightResume = centerX - Width() * 0.1765f; + float topResume = centerY - Height() * 0.271f; + float bottomResume = centerY - Height() * 0.4415f; + + float leftMainMenu = centerX + Width() * 0.17f; + float rightMainMenu = centerX + Width() * 0.4875f; + float topMainMenu = centerY - Height() * 0.255f; + float bottomMainMenu = centerY - Height() * 0.4415f; + + if (x > leftResume && x < rightResume && y > bottomResume && y < topResume) { + m_gamestate = GameState::PLAY; + m_audio.ToggleMusicState(); + } + else if (x > leftMainMenu && x < rightMainMenu && y > bottomMainMenu && y < topMainMenu) { + m_gamestate = GameState::MAIN_MENU; + m_selectedPlayOptions = false; + } + } } void Engine::MouseReleaseEvent(const MOUSE_BUTTON& button, int x, int y) { diff --git a/SQCSim2021/engine.h b/SQCSim2021/engine.h index aff6ebd..1f4bcbc 100644 --- a/SQCSim2021/engine.h +++ b/SQCSim2021/engine.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "../SQCSim-common/array2d.h" #include "../SQCSim-common/blockinfo.h" #include "../SQCSim-common/boostinfo.h" @@ -45,6 +46,7 @@ private: int GetFps(float elapsedTime) const; int GetCountdown(float elapsedTime); int GetOptionsChoice(); + bool StartMultiplayerGame(); bool LoadTexture(Texture& texture, const std::string& filename, bool useMipmaps = true, bool stopOnError = true); @@ -61,13 +63,18 @@ private: void DisplayInfo(float elapsedTime, BlockType bloc); void DisplaySplashScreen(); - void DisplayPauseMenu(); void DisplayMainMenu(); void DrawButtonBackgrounds(float centerX, float centerY, int iterations); void DrawMainMenuButtons(float centerX, float centerY); void DrawSingleMultiButtons(float centerX, float centerY); + void DisplayLobbyMenu(float elapsedTime); + void SetPlayerUsername(float elapsedTime); + void SetServerAddress(float elapsedTime); + + void DisplayPauseMenu(float elapsedTime); + void DisplayOptionsMenu(); void DisplayAudioMenu(float centerX, float centerY); void DisplayGraphicsMenu(float centerX, float centerY); @@ -76,25 +83,20 @@ private: void DisplayBarPercentValue(float centerX, float centerY, float posX, float posY, float minVal, float maxVal, float value); void DrawSlider(float centerX, float centerY, float value, float minVal, float maxVal, float bottomSideValue, float topSideValue); - void PrintText(float x, float y, const std::string& t, float charSizeMultiplier = 1.0f); void ProcessNotificationQueue(); + char SimulateKeyboard(unsigned char key); + void HandlePlayerInput(float elapsedTime); - Connector m_conn; - - Audio m_audio = Audio(AUDIO_PATH "start.wav"); + //udio m_menuaudio = Audio(AUDIO_PATH "menumusic.wav"); + Audio m_audio = Audio(AUDIO_PATH "music01.wav"); irrklang::ISound* m_powpow, * m_scream; irrklang::ISound* m_whoosh[MAX_BULLETS]; Bullet* m_bullets[MAX_BULLETS]; - std::chrono::high_resolution_clock::time_point m_startTime; - std::unordered_map m_players; - netprot::Buffer m_buf, m_bufout; - - netprot::PlayerInfo m_pinfo; - RemotePlayer m_remotePlayer = RemotePlayer(netprot::PlayerInfo(), Vector3f(5.5f, CHUNK_SIZE_Y + 1.8f, 5.5f)); - std::string m_messageNotification = ""; + //Menu + Vector3f m_otherplayerpos = Vector3f(999, 999, 999); World m_world = World(); Player m_player = Player(Vector3f(.5f, CHUNK_SIZE_Y + 1.8f, .5f)); @@ -122,6 +124,7 @@ private: Texture m_texturePovGun; Texture m_textureSkybox; + Texture m_textureLobbyMenu; Texture m_textureMainMenu; Texture m_textureOptionsMenu; Texture m_texturePauseMenu; @@ -131,9 +134,15 @@ private: Texture m_textureFhd; Texture m_textureQhd; Texture m_textureUhd; + + Texture m_textureLobbyServer; + Texture m_textureLobbyIdentify; Texture m_textureCheck; Texture m_textureChecked; + Texture m_texturePauseResume; + Texture m_texturePauseMainMenu; + Texture m_textureOptAudio; Texture m_textureOptBack; Texture m_textureOptGameplay; @@ -196,6 +205,16 @@ private: bool m_selectedPlayOptions = false; bool m_selectedOptions = false; bool m_selectedQuit = false; + + std::string m_currentInputString; + std::string m_username; + std::string m_serverAddr; + char m_inputChar = 0; + bool m_invalidChar = false; + bool m_charChanged = false; + bool m_settingUsername = false; + bool m_settingServer = false; + bool m_multiReady = false; bool m_key1 = false; bool m_key2 = false; @@ -205,7 +224,10 @@ private: bool m_keyA = false; bool m_keyS = false; bool m_keyD = false; + bool m_keyEnter = false; bool m_keySpace = false; + bool m_keyShift = false; + bool m_keyBackspace = false; bool m_mouseL = false; bool m_mouseR = false; @@ -217,6 +239,16 @@ private: float m_mousemy = 0; bool m_networkgame = false; + + Connector m_conn; + std::deque m_chunkmod_manifest; + std::chrono::high_resolution_clock::time_point m_startTime; + std::unordered_map m_players; + netprot::Buffer m_buf, m_bufout; + netprot::ChunkMod* m_chunkmod = nullptr; + + std::unordered_map m_syncs; + std::string m_messageNotification = ""; }; #endif // ENGINE_H__ diff --git a/SQCSim2021/media/textures/menus/backgrounds/bgLobby.png b/SQCSim2021/media/textures/menus/backgrounds/bgLobby.png new file mode 100644 index 0000000..fab6550 Binary files /dev/null and b/SQCSim2021/media/textures/menus/backgrounds/bgLobby.png differ diff --git a/SQCSim2021/media/textures/menus/backgrounds/bgPause.png b/SQCSim2021/media/textures/menus/backgrounds/bgPause.png index c236e26..38bece6 100644 Binary files a/SQCSim2021/media/textures/menus/backgrounds/bgPause.png and b/SQCSim2021/media/textures/menus/backgrounds/bgPause.png differ diff --git a/SQCSim2021/media/textures/menus/buttons/pause/pauseMainMenu.png b/SQCSim2021/media/textures/menus/buttons/pause/pauseMainMenu.png new file mode 100644 index 0000000..701a9a6 Binary files /dev/null and b/SQCSim2021/media/textures/menus/buttons/pause/pauseMainMenu.png differ diff --git a/SQCSim2021/media/textures/menus/buttons/pause/pauseResume.png b/SQCSim2021/media/textures/menus/buttons/pause/pauseResume.png new file mode 100644 index 0000000..7615eb5 Binary files /dev/null and b/SQCSim2021/media/textures/menus/buttons/pause/pauseResume.png differ diff --git a/SQCSim2021/media/textures/menus/labels/labelIdentify.png b/SQCSim2021/media/textures/menus/labels/labelIdentify.png new file mode 100644 index 0000000..6656fd9 Binary files /dev/null and b/SQCSim2021/media/textures/menus/labels/labelIdentify.png differ diff --git a/SQCSim2021/media/textures/menus/labels/labelServer.png b/SQCSim2021/media/textures/menus/labels/labelServer.png new file mode 100644 index 0000000..33c0652 Binary files /dev/null and b/SQCSim2021/media/textures/menus/labels/labelServer.png differ diff --git a/SQCSim2021/openglcontext.cpp b/SQCSim2021/openglcontext.cpp index 6284446..f0263cd 100644 --- a/SQCSim2021/openglcontext.cpp +++ b/SQCSim2021/openglcontext.cpp @@ -16,8 +16,8 @@ bool OpenglContext::Start(const std::string& title, int width, int height, bool m_fullscreen = fullscreen; InitWindow(width, height); - Init(); LoadResource(); + Init(); sf::Clock clock; diff --git a/SQCSim2021/remoteplayer.cpp b/SQCSim2021/remoteplayer.cpp index c2247ba..47bd809 100644 --- a/SQCSim2021/remoteplayer.cpp +++ b/SQCSim2021/remoteplayer.cpp @@ -10,14 +10,10 @@ RemotePlayer::RemotePlayer(netprot::PlayerInfo pinfo) : m_pinfo(pinfo), m_aminacc(0.0f), m_animstate(Anim::STILL), m_team_id(0), current(), previous(), m_texture_front(), Player(Vector3f(0, 0, 0)){ - LoadTexture(m_texture_front, TEXTURE_PATH "AssetOtherPlayer/FinalPNGStanding/BlueFrontRight.png", false, false); - } RemotePlayer::RemotePlayer(netprot::PlayerInfo pinfo, const Vector3f& pos) : m_pinfo(pinfo), m_aminacc(0.0f), m_animstate(Anim::STILL), m_team_id(0), current(), previous(), m_texture_front(), Player(pos) { - LoadTexture(m_texture_front, TEXTURE_PATH "AssetOtherPlayer/FinalPNGStanding/BlueFrontRight.png", false, false); - } @@ -33,6 +29,11 @@ void RemotePlayer::Init() void RemotePlayer::Feed(const netprot::Output out) { + m_position = Vector3f(out.position); + m_direction = Vector3f(out.direction); + + current.states = out.states; + //current.position = out.position; //current.direction = out.direction; //current.states = out.states; @@ -75,35 +76,232 @@ void RemotePlayer::Feed(const netprot::Output out) { //previous.position = current.position; //previous.states = current.states; //previous.id = current.id; + + //m_direction = current.direction; + //m_position = current.position; } -void RemotePlayer::Render(TextureAtlas& atlas, Shader& shader, Transformation tran, float elapsedTime) + + + +void RemotePlayer::Render(TextureAtlas& atlas, Shader& shader, Transformation tran, float elapsedTime, Player& camera) { - float x = GetPosition().x; - float y = GetPosition().y; - float z = GetPosition().z; float width = 1.f; float height = 1.7f; + Vector3f DiffCam = GetPosition() - camera.GetPosition(); + Vector3f UpCam = Vector3f(0.f, 1.f, 0.f); + + Vector3f CrossA = DiffCam.Cross(UpCam); + Vector3f CrossB = DiffCam.Cross(CrossA); + + CrossA.Normalize(); + CrossB.Normalize(); + + Vector3f playerPosition = GetPosition() + Vector3f(0.f, -.75f, 0.f); + + Vector3f v2 = (playerPosition + CrossA * 0.5 * width + CrossB * 0.5 * height); + Vector3f v1 = (playerPosition - CrossA * 0.5 * width + CrossB * 0.5 * height); + Vector3f v3 = (playerPosition + CrossA * 0.5 * width - CrossB * 0.5 * height); + Vector3f v4 = (playerPosition - CrossA * 0.5 * width - CrossB * 0.5 * height); + + Vector3f angleRemote = GetDirection(); + Vector3f angleCam = (v1 - v2).Cross(v3 - v2); - //Matrix4 mat4 = tran.GetMatrix(); - //mat4 VP = pMatrix * vMatrix; - //Vector3f CameraRight = Vector3f(mat4.Get11(), mat4.Get21(), mat4.Get31()); - //Vector3f CameraUp = Vector3f(mat4.Get12(), mat4.Get22(), mat4.Get32()); + angleCam.y = 0; + angleRemote.y = 0; + angleCam.Normalize(); + angleRemote.Normalize(); + + float angle = angleRemote.Dot(angleCam); + int index = 0; + angle = -angle; + Vector3f side = angleRemote.Cross(angleCam); + + static float time = 0.f; + static bool Shooting = false; + bool isLeft = side.y > 0; + + time += elapsedTime; + if (time >= 200) + { + time -= 200; + if (!current.states.shooting) + Shooting = false; + else + Shooting = !Shooting; + } + + + + if (angle >= 0.75) //Face - side positif + { + if(current.states.shooting){ + if (Shooting) + index = 17; + else + index = 9; + } + else if (current.states.jumpshot) { + if (Shooting) + index = 41; + else + index = 33; + } + else if (current.states.jumping) + index = 25; + else if (current.states.running && current.states.still) + index = 0; + + } + else if (angle >= 0.25 && isLeft) //Frontleft + { + if (current.states.shooting) { + if (Shooting) + index = 18; + else + index = 10; + } + else if (current.states.jumpshot) { + if (Shooting) + index = 42; + else + index = 34; + } + else if (current.states.jumping ) + index = 26; + else if (current.states.running && current.states.still) + index = 1; + + } + else if (angle >= -0.25 && isLeft) //ProfileLeft + { + if (current.states.shooting) { + if (Shooting) + index = 20; + else + index = 12; + } + else if (current.states.jumpshot ) { + if (Shooting) + index = 44; + else + index = 36; + } + else if (current.states.jumping ) + index = 28; + else if (current.states.running && current.states.still) + index = 3; + + } + else if (angle >= -0.75 && isLeft) //BackLeft + { + if (current.states.shooting) { + if (Shooting) + index = 22; + else + index = 14; + } + else if (current.states.jumpshot) { + if (Shooting) + index = 46; + else + index = 38; + } + else if (current.states.jumping) + index = 30; + else if (current.states.running && current.states.still) + index = 5; + } + else if (angle < -0.75) //Dos - side négatif + { + if (current.states.shooting) { + if (Shooting) + index = 24; + else + index = 16; + } + else if (current.states.jumpshot) { + if (Shooting) + index = 48; + else + index = 40; + } + else if (current.states.jumping ) + index = 32; + else if (current.states.running && current.states.still) + index = 7; + + } + else if (angle >= 0.25 && !isLeft) //FrontRight + { + if (current.states.shooting) { + if (Shooting) + index = 19; + else + index = 11; + } + else if (current.states.jumpshot) { + if (Shooting) + index = 43; + else + index = 35; + } + else if (current.states.jumping) + index = 27; + else if (current.states.running && current.states.still) + index = 2; + + } + else if (angle >= -0.25 && !isLeft) //ProfileRight + { + if (current.states.shooting) { + if (Shooting) + index = 21; + else + index = 13; + } + else if (current.states.jumpshot) { + if (Shooting) + index = 45; + else + index = 37; + } + else if (current.states.jumping) + index = 29; + else if (current.states.running && current.states.still) + index = 4; + + } + else if (angle >= -0.75 && !isLeft) //BackRight + { + if (current.states.shooting) { + if (Shooting) + index = 23; + else + index = 15; + } + else if (current.states.jumpshot) { + if (Shooting) + index = 47; + else + index = 39; + } + else if (current.states.jumping) + index = 31; + else if (current.states.running && current.states.still) + index = 6; + + } + - //Vector3f v1 = (m_position + CameraRight * 0.5 * width + CameraUp * -0.5 * width); - //Vector3f v2 = (m_position + CameraRight * 0.5 * width + CameraUp * 0.5 * width); - //Vector3f v4 = (m_position + CameraRight * -0.5 * width + CameraUp * -0.5 * width); - //Vector3f v3 = (m_position + CameraRight * -0.5 * width + CameraUp * 0.5 * width); - //tran.ApplyTranslation(m_position); float u, v, w, h; - //glDisable(GL_DEPTH_TEST); + shader.Use(); atlas.Bind(); - atlas.TextureIndexToCoord(0, u, v, w, h); - //glLoadIdentity(); + atlas.TextureIndexToCoord(index, u, v, w, h); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -111,20 +309,19 @@ void RemotePlayer::Render(TextureAtlas& atlas, Shader& shader, Transformation tr glLoadMatrixf(tran.GetMatrix().GetInternalValues()); glBegin(GL_QUADS); - glTexCoord2f(u, v); glVertex3f(x - width/2., y - height, z); //glVertex3f(v4.x, v4.y, v4.z);//glVertex3f(0, 50, 0); - glTexCoord2f(u + w, v); glVertex3f(x+width/2., y - height, z); //glVertex3f(v3.x, v3.y, v3.z); //glVertex3f(50,50, 0); - glTexCoord2f(u + w, v + h); glVertex3f(x+width/2., y, z); //glVertex3f(v2.x, v2.y, v2.z); //glVertex3f(50, 0, 0); - glTexCoord2f(u, v + h); glVertex3f(x-width/2., y, z); //glVertex3f(v1.x, v1.y, v1.z);// glVertex3f(0, 0, 0); - glEnd(); + glTexCoord2f(u, v); glVertex3f(v1.x, v1.y, v1.z); + glTexCoord2f(u + w, v); glVertex3f(v2.x, v2.y, v2.z); + glTexCoord2f(u + w, v + h); glVertex3f(v3.x, v3.y, v3.z); + glTexCoord2f(u, v + h); glVertex3f(v4.x, v4.y, v4.z); + glEnd(); glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR); glBlendEquation(GL_FUNC_SUBTRACT); glDisable(GL_BLEND); shader.Disable(); - //tran.ApplyTranslation(-m_position); - //glEnable(GL_DEPTH_TEST); + } bool RemotePlayer::LoadTexture(Texture& texture, const std::string& filename, bool useMipmaps, bool stopOnError) diff --git a/SQCSim2021/remoteplayer.h b/SQCSim2021/remoteplayer.h index e782000..fcd5626 100644 --- a/SQCSim2021/remoteplayer.h +++ b/SQCSim2021/remoteplayer.h @@ -21,7 +21,7 @@ public: void Init(); void Feed(const netprot::Output out); - void Render(TextureAtlas& atlas, Shader& shader, Transformation tran, float elapsedTime); + void Render(TextureAtlas& atlas, Shader& shader, Transformation tran, float elapsedTime, Player& camera); bool LoadTexture(Texture& texture, const std::string& filename, bool useMipmaps, bool stopOnError); void SetPosition(Vector3f pos) { m_position = pos; }