void Pony::saveInventory() { win.logMsg(QObject::tr("%1 UDP: Saving 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::ReadWrite)) { win.logMsg(QObject::tr("%1 UDP: Error Saving Inventory for %2 (%3)").arg(LOG_SEVERE).arg(QString().setNum(netviewId)).arg(owner->name)); 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(wornItm.size()); for (const WearableItem& item : wornItm) { newEntry += uint8ToData(item.index); newEntry += uint32ToData(item.id); } invData += newEntry; file.resize(0); file.write(invData); file.close(); }
void sendAddItemRPC(Player* player, const InventoryItem& item) { QByteArray data; data += uint16ToData(player->pony.netviewId); data += 0x6; data += uint32ToData(item.id); data += uint32ToData(item.amount); data += uint32ToData(item.index); sendMessage(player, MsgUserReliableOrdered18, data); }
void sendBeginShop(Player* player, Pony* npcShop) { QByteArray data; data += uint16ToData(npcShop->netviewId); data += 0x16; // BeginShop data += uint32ToData(npcShop->inv.size()); for (const InventoryItem& item : npcShop->inv) { data += uint32ToData(item.id); data += uint32ToData(item.amount); } data += stringToData("Wearable Items"); sendMessage(player, MsgUserReliableOrdered18, data); }
void sendSetBitsRPC(Player* player) { QByteArray data(3, 0x10); data[0] = (quint8)(player->pony.netviewId & 0xFF); data[1] = (quint8)((player->pony.netviewId>>8) & 0xFF); data += uint32ToData(player->pony.nBits); sendMessage(player, MsgUserReliableOrdered18, data); }
void sendDeleteItemRPC(Player* player, uint8_t index, uint32_t qty) { QByteArray data; data += uint16ToData(player->pony.netviewId); data += 0x7; data += uint8ToData(index); data += uint32ToData(qty); sendMessage(player, MsgUserReliableOrdered18, data); }
void sendWearItemRPC(Pony* wearing, Player* dest, const WearableItem& item) { QByteArray data; data += uint16ToData(wearing->netviewId); data += 0x8; data += uint32ToData(item.id); data += uint8ToData(item.index); sendMessage(dest, MsgUserReliableOrdered18, data); }
void sendWearItemRPC(Player* player, const WearableItem& item) { QByteArray data; data += uint16ToData(player->pony.netviewId); data += 0x8; data += uint32ToData(item.id); data += uint8ToData(item.index); sendMessage(player, MsgUserReliableOrdered18, data); }
Quest::Quest(QString path, Player *Owner) { QFile file(path); if (!file.open(QFile::ReadOnly)) { app.logError(QObject::tr("Error reading quest DB")); app.stopGameServer(); throw std::exception(); } QList<QString> lines = QString(file.readAll().replace('\r',"")).split('\n'); owner = Owner; commands = new QList<QList<QString> >; name = new QString(); descr = new QString(); npc = new Pony(nullptr); // A NPC doesn't have an owner player ! npc->id = 0; npc->netviewId = 0; id = 0; state = 0; eip = 0; // Parse the metadata, add everything else as quest commands for (int i=0; i<lines.size(); i++) { QList<QString> line = lines[i].split(" ", QString::SkipEmptyParts); if (!line.size() || lines[i][0]=='#') continue; if (line[0] == "name") if (line.size()>=2) npc->name = lines[i].mid(line[0].size()+1); else throw QString(QObject::tr("Quest::Quest: Error reading name, quest %1").arg(path)); else if (line[0] == "scene") if (line.size()>=2) npc->sceneName = lines[i].mid(line[0].size()+1).toLower(); else throw QString(QObject::tr("Quest::Quest: Error reading scene, quest %1").arg(path)); else if (line[0] == "ponyData") { if (line.size()==2) { QByteArray ponyData = QByteArray::fromBase64(line[1].toLatin1()); // Read the ponyData unsigned strlen; unsigned lensize=0; { unsigned char num3; int num=0, num2=0; do { num3 = ponyData[lensize]; lensize++; num |= (num3 & 0x7f) << num2; num2 += 7; } while ((num3 & 0x80) != 0); strlen = (uint) num; } int nameSize = strlen + lensize; int ponyDataSize = ponyData.size() - nameSize; if (ponyDataSize == 43) { app.logMessage(QString("Quest::Quest: PonyData of quest %1 is in old format, converting") .arg(path)); ponyData += uint32ToData(0); // Member ID ponyData.insert(nameSize+17+3,ponyData.mid(nameSize+17,3)); // Hair color 2 (copy of color 1) } npc->ponyData = ponyData; } else throw QString(QObject::tr("Quest::Quest: Error reading ponyData, quest %1").arg(path)); } else if (line[0] == "pos") if (line.size()==4) { bool ok1, ok2, ok3; npc->pos = UVector(line[1].toFloat(&ok1), line[2].toFloat(&ok2), line[3].toFloat(&ok3)); if (!(ok1 && ok2 && ok3)) throw QString(QObject::tr("Quest::Quest: Error reading pos, quest %1").arg(path)); } else throw QString(QObject::tr("Quest::Quest: Error reading pos, quest %1").arg(path)); else if (line[0] == "rot") if (line.size()==5) { bool ok1, ok2, ok3, ok4; npc->rot = UQuaternion(line[1].toFloat(&ok1), line[2].toFloat(&ok2), line[3].toFloat(&ok3), line[4].toFloat(&ok4)); if (!(ok1 && ok2 && ok3 && ok4)) throw QString(QObject::tr("Quest::Quest: Error reading rot, quest %1").arg(path)); } else throw QString(QObject::tr("Quest::Quest: Error reading rot, quest %1").arg(path)); else if (line[0] == "wear") { for (int i=1; i<line.size(); i++) { bool ok; int itemId = line[i].toInt(&ok); if (!ok) throw QString(QObject::tr("Quest::Quest: Error reading wear, quest %1").arg(path)); WearableItem item; item.id = itemId; item.index = wearablePositionsToSlot(wearablePositionsMap[itemId]); npc->worn << item; } } else if (line[0] == "shop") { for (int i=1; i<line.size(); i++) { bool ok; int itemId = line[i].toInt(&ok); if (!ok) throw QString(QObject::tr("Quest::Quest: Error reading shop, quest %1").arg(path)); InventoryItem item; item.id = itemId; item.index = i-1; item.amount = (quint32)-1; npc->inv << item; } } else if (line[0] == "questId") if (line.size()==2) { id = line[1].toInt(); SceneEntity::lastIdMutex.lock(); npc->id = 0; npc->netviewId = id; SceneEntity::lastIdMutex.unlock(); } else throw QString(QObject::tr("Quest::Quest: Error reading questId, quest %1").arg(path)); else if (line[0] == "questName") if (line.size()>=2) *name = lines[i].mid(line[0].size()+1); else throw QString(QObject::tr("Quest::Quest: Error reading questName, quest %1").arg(path)); else if (line[0] == "questDescr") if (line.size()>=2) *descr = lines[i].mid(line[0].size()+1); else throw QString(QObject::tr("Quest::Quest: Error reading questDescr, quest %1").arg(path)); else commands->append(line); } }