// // Created by Иван Ильин on 25.05.2021. // #include #include #include #include #include #include #include #include "ShooterClient.h" #include "ShooterMsgType.h" ShooterClient::ShooterClient(std::shared_ptr player) : _player(player) { EventHandler::listen( Event("take_bonus"), [this](const std::string& name){ this->takeBonus(name); } ); EventHandler::listen( Event("damage_player"), [this](sf::Uint16 targetId, double damage) { damagePlayer(targetId, damage); } ); EventHandler::listen( Event("your_bullet"), [this](const Vec3D &from, const Vec3D &to) { sendTrace(from, to); }); EventHandler::listen( Event("change_weapon"), [this](const std::string &name){ changeWeapon(name); } ); } void ShooterClient::updatePacket() { sf::Packet packet; packet << MsgType::ClientUpdate << _player->position().x() << _player->position().y() << _player->position().z() << _player->angle().y() << _player->headAngle() << _player->playerNickName(); _socket.send(packet, _socket.serverId()); } void ShooterClient::processInit(sf::Packet &packet) { sf::Uint16 targetId; double x, y, z, health; int kills, deaths; while (packet >> targetId >> x >> y >> z >> health >> kills >> deaths) { if (targetId != _socket.ownId()) { EventHandler::call(Event("spawn_player"), targetId); _players[targetId]->translateToPoint(Vec3D{x, y, z}); _players[targetId]->setHealth(health); _players[targetId]->setKills(kills); _players[targetId]->setDeaths(deaths); } } } void ShooterClient::processUpdate(sf::Packet &packet) { sf::Uint16 targetId; double x, y, z, health, bodyAngle, headAngle; std::string playerName; while (packet >> targetId >> x >> y >> z >> health >> bodyAngle >> headAngle >> playerName) { if (_players.count(targetId)) { std::string name = "Enemy_" + std::to_string(targetId); Vec3D newPosition = Vec3D{x, y, z}; bool isAnimate = (_players[targetId]->position() - newPosition).sqrAbs() > 0.2; _players[targetId]->translateToPoint(newPosition); _players[targetId]->setHealth(health); _players[targetId]->rotateToAngle(Vec3D{0, bodyAngle, 0}); _players[targetId]->setPlayerNickName(playerName); auto head = _players[targetId]->attached(ObjectNameTag(name + "_head")); auto weapon = _players[targetId]->attached(ObjectNameTag("Enemy_" + std::to_string(targetId) + "_weapon")); auto foot1 = _players[targetId]->attached(ObjectNameTag(name + "_foot_1")); auto foot2 = _players[targetId]->attached(ObjectNameTag(name + "_foot_2")); if (head != nullptr) { head->rotateLeft(headAngle - _players[targetId]->headAngle()); } if (weapon != nullptr) { weapon->rotateLeft(headAngle - _players[targetId]->headAngle()); } if (isAnimate) { if (foot1 != nullptr && foot2 != nullptr && !Timeline::isInAnimList(AnimationListTag(name + "_foot1_rotation"))) { Timeline::addAnimation(AnimationListTag(name + "_foot1_rotation"), foot1, 0.6, 0.2, Animation::LoopOut::None, Animation::InterpolationType::Linear); Timeline::addAnimation(AnimationListTag(name + "_foot1_rotation"), 0); Timeline::addAnimation(AnimationListTag(name + "_foot1_rotation"), foot1, -1.2, 0.2, Animation::LoopOut::None, Animation::InterpolationType::Linear); Timeline::addAnimation(AnimationListTag(name + "_foot1_rotation"), 0); Timeline::addAnimation(AnimationListTag(name + "_foot1_rotation"), foot1, 0.6, 0.2, Animation::LoopOut::None, Animation::InterpolationType::Linear); Timeline::addAnimation(AnimationListTag(name + "_foot2_rotation"), foot2, -0.6, 0.2, Animation::LoopOut::None, Animation::InterpolationType::Linear); Timeline::addAnimation(AnimationListTag(name + "_foot2_rotation"), 0); Timeline::addAnimation(AnimationListTag(name + "_foot2_rotation"), foot2, 1.2, 0.2, Animation::LoopOut::None, Animation::InterpolationType::Linear); Timeline::addAnimation(AnimationListTag(name + "_foot2_rotation"), 0); Timeline::addAnimation(AnimationListTag(name + "_foot2_rotation"), foot2, -0.6, 0.2, Animation::LoopOut::None, Animation::InterpolationType::Linear); } } _players[targetId]->setHeadAngle(headAngle); } else if (targetId == _socket.ownId()) { _player->setHealth(health); } } } void ShooterClient::processNewClient(sf::Packet &packet) { sf::Uint16 targetId; packet >> targetId; EventHandler::call(Event("spawn_player"), targetId); } void ShooterClient::processDisconnect(sf::Uint16 targetId) { if (targetId != _socket.ownId() && _players.count(targetId)) { _players.erase(targetId); EventHandler::call(Event("remove_player"), targetId); } } void ShooterClient::sendMessage(const std::string& message){ if (message.length() == 0) return; chatManager->addNewMessage(_player->playerNickName(), message); sf::Packet packet; packet << MsgType::Custom << ShooterMsgType::newMessage << message; _socket.send(packet, _socket.serverId()); } void ShooterClient::sendChatMessage(const std::string& message, const std::string& name) { chatManager->addNewMessage(name, message); } void ShooterClient::processCustomPacket(sf::Packet &packet) { sf::Uint16 buffId[2]; double dbuff[10]; std::string tmp, tmp2; ShooterMsgType type; packet >> type; std::string name, message; switch (type) { case ShooterMsgType::Kill: packet >> buffId[0] >> buffId[1]; _lastEvent = ""; if (buffId[1] == _socket.ownId()) { _player->addKill(); SoundController::loadAndPlay(SoundTag("kill"), ShooterConsts::KILL_SOUND); _lastEvent += _player->playerNickName(); } else { _players[buffId[1]]->addKill(); _lastEvent += _players[buffId[1]]->playerNickName(); } _lastEvent += " ~> "; if (buffId[0] == _socket.ownId()) { _player->addDeath(); auto camera = _player->attached(ObjectNameTag("Camera")); if (camera == nullptr) { break; } _player->unattach(ObjectNameTag("Camera")); _player->translateToPoint(Vec3D{10000}); camera->rotateLeft(-camera->angleLeftUpLookAt().x()); camera->transform(Matrix4x4::Rotation(-_player->angle())); Timeline::addAnimation(AnimationListTag("camera_anim"), camera, Vec3D(0, 30, -100)); Timeline::addAnimation(AnimationListTag("camera_anim"), 0); Timeline::addAnimation(AnimationListTag("camera_anim"), camera, Vec3D(0), Vec3D{0, Consts::PI, 0}, 5, Animation::LoopOut::None, Animation::InterpolationType::Linear); Timeline::addAnimation(AnimationListTag("camera_anim"), 0); Timeline::addAnimation(AnimationListTag("camera_anim"), [this, camera]() { // respawn _player->translateToPoint( Vec3D{50.0 * (-1 + 2.0 * (double) rand() / RAND_MAX), 30.0 * (double) rand() / RAND_MAX, 50.0 * (-1 + 2.0 * (double) rand() / RAND_MAX)}); _player->reInitWeapons(); _player->setFullAbility(); camera->rotateToAngle(Vec3D(0)); camera->transform(Matrix4x4::Rotation(Vec3D(_player->angle()))); camera->rotateLeft(_player->headAngle()); camera->translateToPoint(_player->position() + Vec3D{0, 1.8, 0}); _player->attach(camera); }, 1, 0.1); SoundController::loadAndPlay(SoundTag("death"), ShooterConsts::DEATH_SOUND); _lastEvent += _player->playerNickName(); } else { _players[buffId[0]]->addDeath(); _lastEvent += _players[buffId[0]]->playerNickName(); } break; case ShooterMsgType::FireTrace: if (buffId[0] != _socket.ownId()) { packet >> dbuff[0] >> dbuff[1] >> dbuff[2] >> dbuff[3] >> dbuff[4] >> dbuff[5]; EventHandler::call( Event("enemy_bullet"), Vec3D(dbuff[0], dbuff[1], dbuff[2]), Vec3D(dbuff[3], dbuff[4], dbuff[5])); } break; case ShooterMsgType::InitBonuses: while (packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]) { EventHandler::call( Event("add_bonus"), tmp, Vec3D(dbuff[0], dbuff[1], dbuff[2])); } break; case ShooterMsgType::AddBonus: packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]; EventHandler::call( Event("add_bonus"), tmp, Vec3D(dbuff[0], dbuff[1], dbuff[2])); break; case ShooterMsgType::RemoveBonus: packet >> tmp; EventHandler::call( Event("remove_bonus"), ObjectNameTag(tmp)); break; case ShooterMsgType::ChangeWeapon: packet >> buffId[0] >> tmp; EventHandler::call( Event("change_enemy_weapon"), tmp, buffId[0]); break; case ShooterMsgType::newMessage: packet >> name >> message; sendChatMessage(message, name); break; default: Log::log("ShooterClient::processCustomPacket: unknown message type " + std::to_string(static_cast(type))); return; } } void ShooterClient::processDisconnected() { for (auto it = _players.begin(); it != _players.end();) { processDisconnect(it++->first); } } void ShooterClient::damagePlayer(sf::Uint16 targetId, double damage) { sf::Packet packet; packet << MsgType::Custom << ShooterMsgType::Damage << targetId << damage; _socket.sendRely(packet, _socket.serverId()); Log::log("ShooterClient: damagePlayer " + std::to_string(targetId) + " ( -" + std::to_string(damage) + "hp )"); } void ShooterClient::sendTrace(const Vec3D &from, const Vec3D &to) { sf::Packet packet; packet << MsgType::Custom << ShooterMsgType::FireTrace << from.x() << from.y() << from.z() << to.x() << to.y() << to.z(); _socket.send(packet, _socket.serverId()); } void ShooterClient::takeBonus(const std::string &bonusName) { sf::Packet packet; packet << MsgType::Custom << ShooterMsgType::RemoveBonus << bonusName; _socket.sendRely(packet, _socket.serverId()); EventHandler::call( Event("remove_bonus"), ObjectNameTag(bonusName)); } void ShooterClient::changeWeapon(const std::string &weaponName) { sf::Packet packet; packet << MsgType::Custom << ShooterMsgType::ChangeWeapon << weaponName; _socket.sendRely(packet, _socket.serverId()); } void ShooterClient::addPlayer(sf::Uint16 id, std::shared_ptr player) { _players.insert({id, player}); } void ShooterClient::requestMap(const std::string& clientIp, std::string *current_map) { Log::log("---------[FTP server]---------"); sf::Ftp ftp; sf::Ftp::Response connectResponse = ftp.connect(clientIp, 21); if (connectResponse.isOk()) { ftp.login(); sf::Ftp::ListingResponse dirResponse = ftp.getDirectoryListing("current_map/"); Log::log("Response code: "+std::to_string(dirResponse.getStatus())+" | Message: "+dirResponse.getMessage()); if (dirResponse.isOk()) { const std::vector& listing = dirResponse.getListing(); if (listing.size() != 0) { for (std::vector::const_iterator it = listing.begin(); it != listing.end(); ++it) Log::log("- "+*it); sf::Ftp::Response downloadResponse = ftp.download(listing.at(0), "./obj/maps/", sf::Ftp::Ascii); Log::log("Response code: "+std::to_string(downloadResponse.getStatus())+" | Message: "+downloadResponse.getMessage()); if (downloadResponse.isOk()) { std::string map_path = listing.at(0); map_path = "./obj/maps"+map_path.substr(map_path.find("/")); Log::log("Map set to: "+map_path); *current_map = map_path; } } else { Log::log("there is no map file"); } } ftp.disconnect(); } else { Log::log("Couldn't connect to FTP server with ip: "+clientIp+" and port: 21"); } Log::log("------------------------------"); }