Esempio n. 1
0
void Pony::respawn()
{
    health = maxHealth;

    sendLoadSceneRPC(owner, sceneName);
    dead = false;
}
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);

                }
            }
        }
    }
}
// Processes the commands entered directly in the server, not the chat messages
void Widget::sendCmdLine()
{
    if (!enableGameServer)
    {
        logMessage(QObject::tr("This is not a game server, commands are disabled"));
        return;
    }

    QString str = ui->cmdLine->text();

    if (str == "clear")
    {
        ui->log->clear();
        return;
    }
    else if (str == "stop")
    {
        delete this;
        return;
    }
    else if (str == "listTcpPlayers")
    {
        for (int i=0; i<tcpPlayers.size(); i++)
        {
            Player* p = tcpPlayers[i];
            logMessage(p->name+" "+p->IP+":"+QString().setNum(p->port));
        }
        return;
    }
    else if (str.startsWith("setPeer"))
    {
        if (udpPlayers.size() == 1)
        {
            cmdPeer = udpPlayers[0];
            QString peerName = cmdPeer->IP + " " + QString().setNum(cmdPeer->port);
            logMessage(QObject::tr("UDP: Peer set to %1").arg(peerName));
            return;
        }

        str = str.right(str.size()-8);
        QStringList args = str.split(':');
        bool ok;
        if (args.size() != 2)
        {
            if (args.size() != 1)
            {
                logMessage(QObject::tr("UDP: setPeer takes a pony id or ip:port combination"));
                return;
            }
            quint16 id = args[0].toUInt(&ok);
            if (!ok)
            {
                logMessage(QObject::tr("UDP: setPeer takes a pony id as argument"));
                return;
            }
            for (int i=0; i<udpPlayers.size();i++)
            {
                if (udpPlayers[i]->pony.id == id)
                {
                    cmdPeer = Player::findPlayer(udpPlayers,udpPlayers[i]->IP, udpPlayers[i]->port);
                    logMessage(QObject::tr("UDP: Peer set to %1").arg(udpPlayers[i]->pony.name));
                    return;
                }
            }
            logMessage(QObject::tr("UDP: Peer not found (id %1)").arg(args[0]));
            return;
        }

        quint16 port = args[1].toUInt(&ok);
        if (!ok)
        {
            logMessage(QObject::tr("UDP: setPeer takes a port as argument"));
            return;
        }

        cmdPeer = Player::findPlayer(udpPlayers,args[0], port);
        if (cmdPeer->IP!="")
            logMessage(QObject::tr("UDP: Peer set to %1").arg(str));
        else
            logMessage(QObject::tr("UDP: Peer not found (%1)").arg(str));
        return;
    }
    else if (str.startsWith("listPeers"))
    {
        if (str.size()<=10)
        {
            for (int i=0; i<win.udpPlayers.size();i++)
                win.logMessage(QString().setNum(win.udpPlayers[i]->pony.id)
                               +" ("+QString().setNum(win.udpPlayers[i]->pony.netviewId)+")"
                               +"   "+win.udpPlayers[i]->pony.name
                               +"   "+win.udpPlayers[i]->IP
                               +":"+QString().setNum(win.udpPlayers[i]->port)
                               +"   "+QString().setNum((int)timestampNow()-win.udpPlayers[i]->lastPingTime)+"s");
            return;
        }
        str = str.right(str.size()-10);
        Scene* scene = findScene(str);
        if (scene->name.isEmpty())
            win.logMessage(QObject::tr("Can't find scene"));
        else
            for (int i=0; i<scene->players.size();i++)
                win.logMessage(win.udpPlayers[i]->IP
                               +":"+QString().setNum(win.udpPlayers[i]->port)
                               +" "+QString().setNum((int)timestampNow()-win.udpPlayers[i]->lastPingTime)+"s");
        return;
    }
    else if (str.startsWith("listVortexes"))
    {
        for (int i=0; i<scenes.size(); i++)
        {
            win.logMessage("Scene "+scenes[i].name);
            for (int j=0; j<scenes[i].vortexes.size(); j++)
                win.logMessage("Vortex "+QString().setNum(scenes[i].vortexes[j].id)
                               +" to "+scenes[i].vortexes[j].destName+" "
                               +QString().setNum(scenes[i].vortexes[j].destPos.x)+" "
                               +QString().setNum(scenes[i].vortexes[j].destPos.y)+" "
                               +QString().setNum(scenes[i].vortexes[j].destPos.z));
        }
        return;
    }
    else if (str.startsWith("sync"))
    {
        win.logMessage(QObject::tr("UDP: Syncing manually"));
        sync.doSync();
        return;
    }
    // DEBUG global commands from now on
    else if (str==("dbgStressLoad"))
    {
        // Send all the players to the GemMines at the same time
        for (int i=0; i<udpPlayers.size(); i++)
            sendLoadSceneRPC(udpPlayers[i], "GemMines");
        return;
    }
    else if (str.startsWith("dbgStressLoad"))
    {
        str = str.mid(14);
        // Send all the players to the given scene at the same time
        for (int i=0; i<udpPlayers.size(); i++)
            sendLoadSceneRPC(udpPlayers[i], str);
        return;
    }
    else if (str.startsWith("tele"))
    {
        str = str.right(str.size()-5);
        QStringList args = str.split(' ');
        if (args.size() != 2)
        {
            logStatusMessage(QObject::tr("Error: Usage is tele ponyIdToMove destinationPonyId"));
            return;
        }
        bool ok;
        bool ok1;
        bool ok2 = false;
        quint16 sourceID = args[0].toUInt(&ok);
        quint16 destID = args[1].toUInt(&ok1);
        Player* sourcePeer;
        if (!ok && !ok1)
        {
            logStatusMessage(QObject::tr("Error: Usage is tele ponyIdToMove destinationPonyId"));
            return;
        }
        for (int i=0; i<udpPlayers.size();i++)
        {
            if (udpPlayers[i]->pony.id == sourceID)
            {
                sourcePeer = udpPlayers[i];
                ok2 = true;
                break;
            }
        }
        if (!ok2)
        {
            logStatusMessage(QObject::tr("Error: Source peer does not exist!"));
            return;
        }
        for (int i=0; i<udpPlayers.size();i++)
        {
            if (udpPlayers[i]->pony.id == destID)
            {
                logMessage(QObject::tr("UDP: Teleported %1 to %2").arg(sourcePeer->pony.name,udpPlayers[i]->pony.name));
                if (udpPlayers[i]->pony.sceneName.toLower() != sourcePeer->pony.sceneName.toLower())
                    sendLoadSceneRPC(sourcePeer, udpPlayers[i]->pony.sceneName, udpPlayers[i]->pony.pos);
                else
                    sendMove(sourcePeer, udpPlayers[i]->pony.pos.x, udpPlayers[i]->pony.pos.y, udpPlayers[i]->pony.pos.z);
                return;
            }
        }
        logMessage(QObject::tr("Error: Destination peer does not exist!"));
    }
    if (cmdPeer->IP=="")
    {
        logMessage(QObject::tr("Select a peer first with setPeer/listPeers"));
        return;
    }
    else // Refresh peer info
    {
        cmdPeer = Player::findPlayer(udpPlayers,cmdPeer->IP, cmdPeer->port);
        if (cmdPeer->IP=="")
        {
            logMessage(QObject::tr("UDP: Peer not found"));
            return;
        }
    }

    // User commands from now on (requires setPeer)
    if (str.startsWith("disconnect"))
    {
        logMessage(QObject::tr("UDP: Disconnecting"));
        sendMessage(cmdPeer,MsgDisconnect, "Connection closed by the server admin");
        Player::disconnectPlayerCleanup(cmdPeer); // Save game and remove the player
    }
    else if (str.startsWith("load"))
    {
        str = str.mid(5);
        sendLoadSceneRPC(cmdPeer, str);
    }
    else if (str.startsWith("getPos"))
    {
        logMessage(QObject::tr("Pos : ","Short for position") + QString().setNum(cmdPeer->pony.pos.x)
                   + " " + QString().setNum(cmdPeer->pony.pos.y)
                   + " " + QString().setNum(cmdPeer->pony.pos.z));
    }
    else if (str.startsWith("getRot"))
    {
        logMessage(QObject::tr("Rot : x=","Short for rotation") + QString().setNum(cmdPeer->pony.rot.x)
                   + ", y=" + QString().setNum(cmdPeer->pony.rot.y)
                   + ", z=" + QString().setNum(cmdPeer->pony.rot.z)
                   + ", w=" + QString().setNum(cmdPeer->pony.rot.w));
    }
    else if (str.startsWith("getPonyData"))
    {
        logMessage("ponyData : "+cmdPeer->pony.ponyData.toBase64());
    }
    else if (str.startsWith("sendPonies"))
    {
        sendPonies(cmdPeer);
    }
    else if (str.startsWith("sendUtils3"))
    {
        logMessage(QObject::tr("UDP: Sending Utils3 request"));
        QByteArray data(1,3);
        sendMessage(cmdPeer,MsgUserReliableOrdered6,data);
    }
    else if (str.startsWith("setPlayerId"))
    {
        str = str.right(str.size()-12);
        QByteArray data(3,4);
        bool ok;
        unsigned id = str.toUInt(&ok);
        if (ok)
        {
            logMessage(QObject::tr("UDP: Sending setPlayerId request"));
            data[1]=(quint8)(id&0xFF);
            data[2]=(quint8)((id >> 8)&0xFF);
            sendMessage(cmdPeer,MsgUserReliableOrdered6,data);
        }
        else
void receiveChatMessage(QByteArray msg, Player* player)
{
    QString txt = dataToString(msg.mid(7));
    QString author = player->pony.name;
    //win.logMessage("Chat "+author+":"+txt);

    if (txt.startsWith("/stuck") || txt.startsWith("unstuck me"))
    {
        sendLoadSceneRPC(player, player->pony.sceneName);
    }
    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<win.udpPlayers.size(); i++)
            {
                if (win.udpPlayers[i]->inGame>=2 && win.udpPlayers[i]->pony.name.toLower().remove(" ").startsWith(txt.toLower().section(" ", 1, 1)))
                {
                    txt = txt.remove(0, txt.indexOf(" ", 5) + 1);
                    sendChatMessage(win.udpPlayers[i], "<span color=\"yellow\">[PM] </span>" + txt, author, ChatLocal);
                    sendChatMessage(player, "<span color=\"yellow\">[PM to " + win.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<win.udpPlayers.size(); i++)
            if (win.udpPlayers[i]->inGame>=2)
                namesmsg += "<br />#b" + win.udpPlayers[i]->pony.name + "#b<br /><span color=\"yellow\"> - in " + win.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<win.scenes.size(); i++)
                msgtosend += "<br />" + win.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())
                win.logMessage("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<win.udpPlayers.size(); i++)
            {
                if (win.udpPlayers[i]->inGame>=2)
                {
                    if (rollnum > -1)
                        sendChatMessage(win.udpPlayers[i], rollstr, "[Server]", ChatGeneral);
                    else if (actmsg)
                        sendChatMessage(win.udpPlayers[i], txt, "", ChatGeneral);
                    else if (txt.startsWith(">"))
                        sendChatMessage(win.udpPlayers[i], "<span color=\"green\">" + txt + "</span>", author, ChatGeneral);
                    else
                        sendChatMessage(win.udpPlayers[i], txt, author, ChatGeneral);

                }
            }
        }
    }
}