void Player::disconnectPlayerCleanup(Player* player) { static QMutex playerCleanupMutex; // Save the pony QList<Pony> ponies = loadPonies(player); for (int i=0; i<ponies.size(); i++) if (ponies[i].ponyData == player->pony.ponyData) ponies[i] = player->pony; savePonies(player, ponies); player->pony.saveQuests(); player->pony.saveInventory(); QString uIP = player->IP; quint16 uPort = player->port; Scene* scene = findScene(player->pony.sceneName); if (scene->name.isEmpty()) logMessage(tr("UDP: Can't find scene for player cleanup")); //app.logMessage("playerCleanup locking"); playerCleanupMutex.lock(); removePlayer(scene->players, uIP, uPort); for (int i=0; i<scene->players.size(); i++) sendNetviewRemove(scene->players[i], player->pony.netviewId); player->udpDelayedSend(); // We're about to remove the player, we can't delay the send player->udpSendReliableTimer->stop(); player->udpSendReliableGroupTimer->stop(); removePlayer(Player::udpPlayers, uIP, uPort); delete player; //app.logMessage("playerCleanup unlocking"); playerCleanupMutex.unlock(); }
void Pony::kill() { health = 0; dead = true; Scene* scene = findScene(sceneName); for (Player* player : scene->players) { if (player->pony.netviewId != netviewId) sendNetviewRemove(player, netviewId, NetviewRemoveReasonKill); } respawn(); }
void sendLoadSceneRPC(Player* player, QString sceneName) // Loads a scene and send to the default spawn { win.logMessage(QString("UDP: Loading scene \"") + sceneName + "\" on "+QString().setNum(player->pony.netviewId)); Vortex vortex = findVortex(sceneName, 0); if (vortex.destName.isEmpty()) { win.logMessage("UDP: Scene not in vortex DB. Aborting scene load."); return; } Scene* scene = findScene(sceneName); Scene* oldScene = findScene(player->pony.sceneName); if (scene->name.isEmpty() || oldScene->name.isEmpty()) { win.logMessage("UDP: Can't find the scene, aborting"); return; } // Update scene players //win.logMessage("sendLoadSceneRPC: locking"); levelLoadMutex.lock(); player->inGame=1; player->pony.pos = vortex.destPos; player->pony.sceneName = sceneName; player->lastValidReceivedAnimation.clear(); // Changing scenes resets animations Player::removePlayer(oldScene->players, player->IP, player->port); if (oldScene->name != sceneName) { // Send remove RPC to the other players of the old scene for (int i=0; i<oldScene->players.size(); i++) sendNetviewRemove(oldScene->players[i], player->pony.netviewId); // Send instantiate to the players of the new scene for (int i=0; i<scene->players.size(); i++) if (scene->players[i]->inGame>=2) sendNetviewInstantiate(player, scene->players[i]); } scene->players << player; QByteArray data(1,5); data += stringToData(sceneName); sendMessage(player,MsgUserReliableOrdered6,data); // Sends a 48 //win.logMessage("sendLoadSceneRPC: unlocking"); levelLoadMutex.unlock(); }
void sendLoadSceneRPC(Player* player, QString sceneName, UVector pos) // Loads a scene and send to the given pos { win.logMessage(QString(QString("UDP: Loading scene \"")+sceneName +"\" to "+QString().setNum(player->pony.netviewId) +" at "+QString().setNum(pos.x)+" " +QString().setNum(pos.y)+" " +QString().setNum(pos.z))); Scene* scene = findScene(sceneName); Scene* oldScene = findScene(player->pony.sceneName); if (scene->name.isEmpty() || oldScene->name.isEmpty()) { win.logMessage("UDP: Can't find the scene, aborting"); return; } // Update scene players //win.logMessage("sendLoadSceneRPC pos: locking"); levelLoadMutex.lock(); player->inGame=1; player->pony.pos = pos; player->pony.sceneName = sceneName.toLower(); player->lastValidReceivedAnimation.clear(); // Changing scenes resets animations Player::removePlayer(oldScene->players, player->IP, player->port); if (oldScene->name.toLower() != sceneName.toLower()) { // Send remove RPC to the other players of the old scene for (int i=0; i<oldScene->players.size(); i++) sendNetviewRemove(oldScene->players[i], player->pony.netviewId); // Send instantiate to the players of the new scene for (int i=0; i<scene->players.size(); i++) if (scene->players[i]->inGame>=2) sendNetviewInstantiate(&player->pony, scene->players[i]); } scene->players << player; QByteArray data(1,5); data += stringToData(sceneName.toLower()); sendMessage(player,MsgUserReliableOrdered6,data); // Sends a 48 //win.logMessage("sendLoadSceneRPC pos: unlocking"); levelLoadMutex.unlock(); }
void receiveChatMessage(QByteArray msg, Player* player) { QString txt = dataToString(msg.mid(7)); QString author = player->pony.name; //logMessage("Chat "+author+":"+txt); if (txt.startsWith("/stuck") || txt.startsWith("unstuck me")) { sendLoadSceneRPC(player, player->pony.sceneName); } else if (txt == ":anhero") { QTimer *anheroTimer = new QTimer(); anheroTimer->setSingleShot(true); QString deadPlayerName = player->name; QObject::connect(anheroTimer, &QTimer::timeout, [=]() { // Find player again instead of reusing pointer, in case they disconnect Player* deadPlayer = Player::findPlayer(Player::udpPlayers, deadPlayerName); if (deadPlayer->connected && deadPlayer->pony.dead) { sendSetStatRPC(deadPlayer, 1, deadPlayer->pony.health); Scene* scene = findScene(deadPlayer->pony.sceneName); for (Player* other : scene->players) sendNetviewInstantiate(&deadPlayer->pony, other); deadPlayer->pony.dead = false; } delete anheroTimer; // Don't delete deadPlayer here. That kills the player's session } ); if (!player->pony.dead) { player->pony.dead = true; sendSetStatRPC(player, 1, 0); anheroTimer->start(5000); Scene* scene = findScene(player->pony.sceneName); for (Player* other : scene->players) sendNetviewRemove(other, player->pony.netviewId, NetviewRemoveReasonKill); } } else if (txt == ":commands") { sendChatMessage(player, "<span color=\"yellow\">List of Commands:</span><br /><em>:roll</em><br /><span color=\"yellow\">Rolls a random number between 00 and 99</span><br /><em>:msg player message</em><br /><span color=\"yellow\">Sends a private message to a player</span><br /><em>:names</em><br /><span color=\"yellow\">Lists all players on the server</span><br /><em>:me action</em><br /><span color=\"yellow\">States your current action</span><br /><em>:tp location</em><br /><span color=\"yellow\">Teleports your pony to the specified region</span>", "[Server]", ChatLocal); } else if (txt.startsWith(":msg")) { if(txt.count(" ") < 2) sendChatMessage(player, ":msg<br /><span color=\"yellow\">Usage:</span><br /><em>:msg player message</em><br /><span color=\"yellow\">Player names are case-insensitive, ignore spaces and you do not need to type out their full name.</span>", author, ChatLocal); else { for (int i=0; i<Player::udpPlayers.size(); i++) { if (Player::udpPlayers[i]->inGame>=2 && Player::udpPlayers[i]->pony.name.toLower().remove(" ") .startsWith(txt.toLower().section(" ", 1, 1))) { txt = txt.remove(0, txt.indexOf(" ", 5) + 1); sendChatMessage(Player::udpPlayers[i], "<span color=\"yellow\">[PM] </span>" + txt, author, ChatLocal); sendChatMessage(player, "<span color=\"yellow\">[PM to " + Player::udpPlayers[i]->pony.name + "] </span>" + txt, author, ChatLocal); } } } } else if (txt.startsWith(":names")) { QString namesmsg = "<span color=\"yellow\">Players currently in game:</span>"; for (int i=0; i<Player::udpPlayers.size(); i++) if (Player::udpPlayers[i]->inGame>=2) namesmsg += "<br />#b" + Player::udpPlayers[i]->pony.name + "#b<br /><span color=\"yellow\"> - in " + Player::udpPlayers[i]->pony.sceneName + "</span>"; sendChatMessage(player, namesmsg, "[Server]", ChatLocal); } else if (txt.startsWith(":tp")) { if (txt.count(" ") < 1) { QString msgtosend = ":tp<br /><span color=\"yellow\">Usage:</span><br /><em>:tp location</em><br /><span color=\"yellow\">Available locations:</span><em>"; for (int i=0; i<Scene::scenes.size(); i++) msgtosend += "<br />" + Scene::scenes[i].name; sendChatMessage(player, msgtosend + "</em>", author, ChatLocal); } else sendLoadSceneRPC(player, txt.remove(0, 4)); } else if (txt == ":me") { sendChatMessage(player, ":me<br /><span color=\"yellow\">Usage:</span><br /><em>:me action</em>", author, ChatLocal); } else // Broadcast the message { int rollnum = -1; QString rollstr; bool actmsg = false; if (txt == ":roll") { if (player->chatRollCooldownEnd < QDateTime::currentDateTime()) { rollnum = qrand() % 100; rollstr.sprintf("<span color=\"yellow\">#b%s#b rolls %02d</span>", author.toLocal8Bit().data(), rollnum); player->chatRollCooldownEnd = QDateTime::currentDateTime().addSecs(10); } } if (txt.startsWith(":me ")) { actmsg = true; txt.remove(0, 3); txt = "<em>#b* " + author + "#b" + txt + "</em>"; } if ((quint8)msg[6] == 8) // Local chat only { Scene* scene = findScene(player->pony.sceneName); if (scene->name.isEmpty()) logMessage(QObject::tr("UDP: Can't find the scene for chat message, aborting")); else { for (int i=0; i<scene->players.size(); i++) { if (scene->players[i]->inGame>=2) { if (rollnum > -1) sendChatMessage(scene->players[i], rollstr, "[Server]", ChatLocal); else if (actmsg) sendChatMessage(scene->players[i], txt, "", ChatLocal); else if (txt.startsWith(">")) sendChatMessage(scene->players[i], "<span color=\"green\">" + txt + "</span>", author, ChatLocal); else sendChatMessage(scene->players[i], txt, author, ChatLocal); } } } } else // Send globally { for (int i=0; i<Player::udpPlayers.size(); i++) { if (Player::udpPlayers[i]->inGame>=2) { if (rollnum > -1) sendChatMessage(Player::udpPlayers[i], rollstr, "[Server]", ChatGeneral); else if (actmsg) sendChatMessage(Player::udpPlayers[i], txt, "", ChatGeneral); else if (txt.startsWith(">")) sendChatMessage(Player::udpPlayers[i], "<span color=\"green\">" + txt + "</span>", author, ChatGeneral); else sendChatMessage(Player::udpPlayers[i], txt, author, ChatGeneral); } } } } }