Ejemplo n.º 1
0
void Pony::saveInventory()
{
    win.logMessage("UDP: Saving inventory for "+QString().setNum(netviewId)+" ("+owner->name+")", udpTag);

    QDir playerPath(QDir::currentPath());
    playerPath.cd("data");
    playerPath.cd("players");
    playerPath.mkdir(owner->name.toLatin1());

    QFile file(QDir::currentPath()+"/data/players/"+owner->name.toLatin1()+"/inventory.dat");
    if (!file.open(QIODevice::ReadWrite))
    {
        win.logMessage("Error saving inventory for "+QString().setNum(netviewId)+" ("+owner->name+")", sysTag);
        return;
    }
    QByteArray invData = file.readAll();

    // Try to find an existing entry for this pony, if found delete it. Then go at the end.
    for (int i=0; i<invData.size();)
    {
        // Read the name
        QString entryName = dataToString(invData.mid(i));
        int nameSize = entryName.size()+getVUint32Size(invData.mid(i));
        //win.logMessage("saveInventory : Reading entry "+entryName);

        quint8 invSize = invData[i+nameSize+4];
        quint8 wornSize = invData[i+nameSize+4+1+invSize*9]; // Serialized sizeof InventoryItem is 9
        if (entryName == this->name) // Delete the entry, we'll rewrite it at the end
        {
            invData.remove(i,nameSize+4+1+invSize*9+1+wornSize*5);
            break;
        }
        else // Skip this entry
            i += nameSize+4+1+invSize*9+1+wornSize*5;
    }

    // Now add our data at the end of the file
    QByteArray newEntry = stringToData(this->name);
    newEntry += uint32ToData(nBits);
    newEntry += uint8ToData(inv.size());
    for (const InventoryItem& item : inv)
    {
        newEntry += uint8ToData(item.index);
        newEntry += uint32ToData(item.id);
        newEntry += uint32ToData(item.amount);
    }
    newEntry += uint8ToData(worn.size());
    for (const WearableItem& item : worn)
    {
        newEntry += uint8ToData(item.index);
        newEntry += uint32ToData(item.id);
    }
    invData += newEntry;
    file.resize(0);
    file.write(invData);
    file.close();
}
Ejemplo n.º 2
0
void Pony::loadQuests()
{
    win.logMessage("UDP: Loading quests for "+QString().setNum(netviewId)+" ("+owner->name+")", udpTag);

    QDir playerPath(QDir::currentPath());
    playerPath.cd("data");
    playerPath.cd("players");
    playerPath.mkdir(owner->name.toLatin1());

    QFile file(QDir::currentPath()+"/data/players/"+owner->name.toLatin1()+"/quests.dat");
    if (!file.open(QIODevice::ReadOnly))
    {
        win.logMessage("Error loading quests for "+QString().setNum(netviewId)+" ("+owner->name+")", sysTag);
        return;
    }
    QByteArray questData = file.readAll();
    file.close();

    // Try to find an existing entry for this pony and load it.
    for (int i=0; i<questData.size();)
    {
        // Read the name
        QString entryName = dataToString(questData.mid(i));
        int nameSize = entryName.size()+getVUint32Size(questData.mid(i));
        i+=nameSize;
        //win.logMessage("loadQuests : Reading entry "+entryName);

        quint16 nquests = dataToUint16(questData.mid(i));
        i+=2;
        if (entryName == this->name) // Read the entry
        {
            for (int j=0; j<nquests; j++)
            {
                quint16 questId = dataToUint16(questData.mid(i));
                quint16 questState = dataToUint16(questData.mid(i+2));
                i+=4;
                for (Quest& quest : quests)
                {
                    if (quest.id == questId)
                    {
                        quest.state = questState;
                        break;
                    }
                }
            }
            return;
        }
        else
            i += nquests * 4;
    }
}
Ejemplo n.º 3
0
void Pony::saveQuests()
{
    win.logMessage("UDP: Saving quests for "+QString().setNum(netviewId)+" ("+owner->name+")", udpTag);

    QDir playerPath(QDir::currentPath());
    playerPath.cd("data");
    playerPath.cd("players");
    playerPath.mkdir(owner->name.toLatin1());

    QFile file(QDir::currentPath()+"/data/players/"+owner->name.toLatin1()+"/quests.dat");
    if (!file.open(QIODevice::ReadWrite))
    {
        win.logMessage("Error saving quests for "+QString().setNum(netviewId)+" ("+owner->name+")", udpTag);
        return;
    }
    QByteArray questData = file.readAll();

    // Try to find an existing entry for this pony, if found delete it. Then go at the end.
    for (int i=0; i<questData.size();)
    {
        // Read the name
        QString entryName = dataToString(questData.mid(i));
        int nameSize = entryName.size()+getVUint32Size(questData.mid(i));
        //win.logMessage("saveQuests : Reading entry "+entryName);

        quint16 entryDataSize = 4 * dataToUint16(questData.mid(i+nameSize));
        if (entryName == this->name) // Delete the entry, we'll rewrite it at the end
        {
            questData.remove(i,nameSize+entryDataSize+2);
            break;
        }
        else
            i += nameSize+entryDataSize+2;
    }

    // Now add our data at the end of the file
    QByteArray newEntry = stringToData(this->name);
    newEntry += (quint8)(quests.size() & 0xFF);
    newEntry += (quint8)((quests.size() >> 8) & 0xFF);
    for (const Quest& quest : quests)
    {
        newEntry += (quint8)(quest.id & 0xFF);
        newEntry += (quint8)((quest.id >> 8) & 0xFF);
        newEntry += (quint8)(quest.state & 0xFF);
        newEntry += (quint8)((quest.state >> 8) & 0xFF);
    }
    questData += newEntry;
    file.resize(0);
    file.write(questData);
    file.close();
}
Ejemplo n.º 4
0
void Widget::udpProcessPendingDatagrams()
{
    while (udpSocket->hasPendingDatagrams())
    {
        QHostAddress rAddr;
        quint16 rPort;
        QByteArray datagram;
        qint64 dataRead = 0;
        int datagramSize = udpSocket->pendingDatagramSize();
        datagram.resize(datagramSize);

        while(dataRead < datagram.size())
        {
            qint64 readNow = udpSocket->readDatagram(datagram.data()+dataRead, datagramSize, &rAddr, &rPort); // le +dataRead sur un tableau, ça décale le pointeur d'un offset de taille dataRead !
            if(readNow != -1)
            {
                dataRead += readNow; // Remember the total number of bytes read, so we know when to stop
                if (datagramSize > (datagram.size() - dataRead)) // Make sure we don't overflow
                    datagramSize = (datagram.size() - dataRead);
            }
            else
            {
                logStatusMessage(QString("Socket error : ").arg(udpSocket->errorString()));
                return;
            }
        }

        // Add player on connection
        if ((unsigned char)datagram[0]==MsgConnect && (unsigned char)datagram[1]==0
                && (unsigned char)datagram[2]==0 && datagram.size()>=22)
        {
            QString name = dataToString(datagram.right(datagram.size()-22));
            int nameFullSize = getVUint32Size(datagram.right(datagram.size()-22))+name.size();
            QString sesskey = dataToString(datagram.right(datagram.size()-22-nameFullSize));
            //logMessage(QString("UDP: Connect detected with name : ")+name);
            //logMessage(QString("UDP: Connect detected with sesskey : ")+sesskey);
            //logMessage(QString("UDP: Datagram was : ")+datagram.toHex());

            bool is_sesskey_valid = true;

            if (enableSessKeyValidation) {
                is_sesskey_valid = QCryptographicHash::hash(QString(sesskey.right(40) + saltPassword).toLatin1(),
                                                            QCryptographicHash::Md5).toHex() == sesskey.left(32);
            }

            if (is_sesskey_valid)
            {
                //logMessage("Sesskey token accepted");

                // Create new player if needed, else just update player
                Player* newPlayer = Player::findPlayer(udpPlayers, rAddr.toString(),rPort);
                if (newPlayer->IP != rAddr.toString()) // IP:Port not found in player list
                {
                    newPlayer->resetNetwork();
                    //newPlayer->connected = true; // Not really connected until we finish the handshake
                    newPlayer->name = name;
                    newPlayer->IP = rAddr.toString();
                    newPlayer->port = rPort;

                    // Check if we have too many players connected
                    int n=0;
                    for (int i=0;i<udpPlayers.size();i++)
                        if (udpPlayers[i]->connected)
                            n++;
                    if (n>=maxConnected)
                    {
                        sendMessage(newPlayer, MsgDisconnect, "Error : Too many players connected. Try again later.");
                    }
                    else
                        // If not add the player
                        udpPlayers << newPlayer;
                }
                else  // IP:Port found in player list
                {
                    if (newPlayer->connected) // TODO: Error, player already connected
                    {
                        sendMessage(newPlayer, MsgDisconnect, "Error : Player already connected.");
                        return;
                    }

                    // Check if we have too many players connected
                    int n=0;
                    for (int i=0;i<udpPlayers.size();i++)
                        if (udpPlayers[i]->connected)
                            n++;
                    if (n>=maxConnected)
                    {
                        sendMessage(newPlayer, MsgDisconnect, "Error : Too many players connected. Try again later.");
                    }

                    newPlayer->resetNetwork();
                    newPlayer->name = name;
                    newPlayer->IP = rAddr.toString();
                    newPlayer->port = rPort;
                    //newPlayer->connected = true; // We're not really connected until we finish the handshake
                }
            }
            else
            {
                QString badHash = QCryptographicHash::hash((QString(sesskey.right(40))
                                +saltPassword).toLatin1(), QCryptographicHash::Md5).toHex();
                logMessage("UDP: Sesskey rejected: got '"+badHash+"' instead of '"+sesskey.left(32)
                           +"', passhash was '"+QString(sesskey.right(40)));
                Player* newPlayer = new Player;
                newPlayer->IP = rAddr.toString();
                newPlayer->port = rPort;
                sendMessage(newPlayer, MsgDisconnect, "Error : Wrong sesskey hash.");
                return;
            }
        }

        Player* player = Player::findPlayer(udpPlayers, rAddr.toString(), rPort);
        if (player->IP == rAddr.toString() && player->port == rPort)
        {
            // Acquire datas
            player->receivedDatas->append(datagram);

            // Process data
            receiveMessage(player);
        }
        else // You need to connect with TCP first
        {
            logMessage("UDP: Request from unknown peer rejected : "+rAddr.toString()+":"+QString().setNum(rPort));
            // Send disconnect message manually
            QString data("You're not connected, please login first. (aka the server has no idea who the hell you are)");
            QByteArray msg(6,0);
            msg[0] = MsgDisconnect;
            msg[3] = (quint8)(((data.size()+1)*8)&0xFF);
            msg[4] = (quint8)((((data.size()+1)*8)>>8)&0xFF);
            msg[5] = (quint8)data.size();
            msg += data;
            win.udpSocket->writeDatagram(msg,rAddr,rPort);
        }
    }
}
Ejemplo n.º 5
0
bool Pony::loadInventory()
{
    win.logMsg(QObject::tr("%1 UDP: Loading Inventory for %2 (%3)").arg(LOG_INFO).arg(QString().setNum(netviewId)).arg(owner->name));

    QDir playerPath(QDir::currentPath());
    playerPath.cd("data");
    playerPath.cd("players");
    playerPath.mkdir(owner->name.toLatin1());

    QFile file(QDir::currentPath()+"/data/players/"+owner->name.toLatin1()+"/inventory.lpd");
    if (!file.open(QIODevice::ReadOnly))
    {
        win.logMsg(QObject::tr("%1 UDP: Error Loading Inventory for %2 (%3)").arg(LOG_SEVERE).arg(QString().setNum(netviewId)).arg(owner->name));
        return false;
    }
    QByteArray invData = file.readAll();
    file.close();

    // Try to find an existing entry for this pony, if found load it.
    for (int i=0; i<invData.size();)
    {
        // Read the name
        QString entryName = dataToString(invData.mid(i));
        int nameSize = entryName.size()+getVUint32Size(invData.mid(i));
        //win.logMessage("loadInventory : Reading entry "+entryName);

        quint8 invSize = invData[i+nameSize+4];
        quint8 wornSize = invData[i+nameSize+4+1+invSize*9]; // Serialized sizeof InventoryItem is 9
        if (entryName == this->name)
        {
            i += nameSize;
            nBits = dataToUint32(invData.mid(i));
            i+=5; // Skip nBits and invSize
            inv.clear();
            for (int j=0; j<invSize; j++)
            {
                InventoryItem item;
                item.index = invData[i];
                i++;
                item.id = dataToUint32(invData.mid(i));
                i+=4;
                item.amount = dataToUint32(invData.mid(i));
                i+=4;
                inv.append(item);
            }
            i++; // Skip wornSize
            wornItm.clear();
            wornSlots = 0;
            for (int j=0; j<wornSize; j++)
            {
                WearableItem item;
                item.index = invData[i];
                i++;
                item.id = dataToUint32(invData.mid(i));
                i+=4;
                wornItm.append(item);
                wornSlots |= loe.wearablePositionsMap[item.id];
            }
            return true;
        }
        else // Skip this entry
            i += nameSize+4+1+invSize*9+1+wornSize*5;
    }
    return false; // Entry not found
}
Ejemplo n.º 6
0
void Widget::udpProcessPendingDatagrams()
{
    while (udpSocket->hasPendingDatagrams())
    {
        QHostAddress rAddr;
        quint16 rPort;
        QByteArray datagram;
        qint64 dataRead = 0;
        int datagramSize = udpSocket->pendingDatagramSize();
        datagram.resize(datagramSize);

        while(dataRead < datagram.size())
        {
            qint64 readNow = udpSocket->readDatagram(datagram.data()+dataRead, datagramSize, &rAddr, &rPort); // le +dataRead sur un tableau, ça décale le pointeur d'un offset de taille dataRead !
            if(readNow != -1)
            {
                dataRead += readNow; // Counts the number of bytes read in total, stop when DataRead reached pendingDatagramSize
                if (datagramSize > (datagram.size() - dataRead)) // Evite de lire après la fin du tableau en mode fragmenté, evite donc que dataSent dépasse datagramSize, sinon Overflow et envoi de données inutiles et aléatoires !!
                    datagramSize = (datagram.size() - dataRead);
                //QMessageBox::information(NULL,"SenderInfo",QString("DatagramSize : %1  sentNow : %2  dataSent : %3 Sizeof(datagram->data()) : %4").arg(QString().setNum(datagramSize),QString().setNum(sentNow),QString().setNum(dataSent),QString().setNum(datagram->size())));
            }
            else
            {
                // Here, we add a message to the udpMessages for filtering later.
                logStatusMessage(QString("Socket error: ").arg(udpSocket->errorString()), udpTag);
                return;
            }
        }

        // Add player on connection
        if ((unsigned char)datagram[0]==MsgConnect && (unsigned char)datagram[1]==0
                && (unsigned char)datagram[2]==0 && datagram.size()>=22)
        {
            QString name = dataToString(datagram.right(datagram.size()-22));
            int nameFullSize = getVUint32Size(datagram.right(datagram.size()-22))+name.size();
            QString sesskey = dataToString(datagram.right(datagram.size()-22-nameFullSize));
            //logMessage(QString("UDP: Connect detected with name : ")+name, udpTag);
            //logMessage(QString("UDP: Connect detected with sesskey : ")+sesskey, udpTag);
            //logMessage(QString("UDP: Datagram was : ")+datagram.toHex(), udpTag);

            bool is_sesskey_valid = true;

            if (enableSessKeyValidation) {
                is_sesskey_valid = QCryptographicHash::hash(QString(sesskey.right(40) + saltPassword).toLatin1(), QCryptographicHash::Md5).toHex() == sesskey.left(32);
            }

            if (is_sesskey_valid)
            {
                //logMessage("Sesskey token accepted", udpTag);

                // Create new player if needed, else just update player
                Player* newPlayer = Player::findPlayer(udpPlayers, rAddr.toString(),rPort);
                if (newPlayer->IP != rAddr.toString()) // IP:Port not found in player list
                {
                    newPlayer->resetNetwork();
                    //newPlayer->connected = true; // Not really connected until we finish the handshake
                    newPlayer->name = name;
                    newPlayer->IP = rAddr.toString();
                    newPlayer->port = rPort;

                    // Check if we have too many players connected
                    int n=0;
                    for (int i=0;i<udpPlayers.size();i++)
                        if (udpPlayers[i]->connected)
                            n++;
                    if (n>=maxConnected)
                    {
                        sendMessage(newPlayer, MsgDisconnect, "Error: Too many players connected. Try again later.");
                    }
                    else
                        // If not add the player
                        udpPlayers << newPlayer;
                }
                else  // IP:Port found in player list
                {
                    if (newPlayer->connected) // TODO: Error, player already connected
                    {
                        sendMessage(newPlayer, MsgDisconnect, "Error: Player already connected.");
                        return;
                    }

                    // Check if we have too many players connected
                    int n=0;
                    for (int i=0;i<udpPlayers.size();i++)
                        if (udpPlayers[i]->connected)
                            n++;
                    if (n>=maxConnected)
                    {
                        sendMessage(newPlayer, MsgDisconnect, "Error: Too many players connected. Try again later.");
                    }

                    newPlayer->resetNetwork();
                    newPlayer->name = name;
                    newPlayer->IP = rAddr.toString();
                    newPlayer->port = rPort;
                    //newPlayer->connected = true; // We're not really connected until we finish the handshake
                }
            }
            else
            {
                QString badHash = QCryptographicHash::hash((QString(sesskey.right(40))
                                +saltPassword).toLatin1(), QCryptographicHash::Md5).toHex();
                logMessage("UDP: Sesskey rejected: got '"+badHash+"' instead of '"+sesskey.left(32)+"', passhash was '"+QString(sesskey.right(40)), udpTag);
                Player* newPlayer = new Player;
                newPlayer->IP = rAddr.toString();
                newPlayer->port = rPort;
                sendMessage(newPlayer, MsgDisconnect, "Error : Wrong sesskey hash.");
                return;
            }
        }

        Player* player = Player::findPlayer(udpPlayers, rAddr.toString(), rPort);
        if (player->IP == rAddr.toString() && player->port == rPort)
        {
            // Acquire data
            player->receivedDatas->append(datagram);

            // Process data
            receiveMessage(player);
        }
        else // You need to connect with TCP first
        {
            logMessage("UDP: Request from unknown peer rejected : "+rAddr.toString()+":"+QString().setNum(rPort), udpTag);
            // Send disconnect message manually, with an appropriate message.
            QString data("BITCH, YOU ARE EITHER A HACKER OR THE SERVER JUST HATES THE F**K OUT OF YOU. RELOG OR YOU AINT GETTIN ON THIS SERVER, K?");
            QByteArray msg(6,0);
            msg[0] = MsgDisconnect;
            msg[3] = (quint8)(((data.size()+1)*8)&0xFF);
            msg[4] = (quint8)((((data.size()+1)*8)>>8)&0xFF);
            msg[5] = (quint8)data.size();
            msg += data;
            win.udpSocket->writeDatagram(msg,rAddr,rPort);
        }
    }
}