File indexing completed on 2024-05-05 05:40:40

0001 /***************************************************************************
0002  *  Copyright (C) 2020 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "worker/playermessagehelper.h"
0021 
0022 #include <QBuffer>
0023 #include <QCoreApplication>
0024 #include <QDebug>
0025 
0026 #include "data/character.h"
0027 #include "data/player.h"
0028 #include "data/charactervision.h"
0029 
0030 #include "network/networkmessagereader.h"
0031 #include "network/networkmessagewriter.h"
0032 
0033 void PlayerMessageHelper::sendOffConnectionInfo(Player* player, const QByteArray& password)
0034 {
0035     if(player == nullptr)
0036         return;
0037 
0038     NetworkMessageWriter msg(NetMsg::AdministrationCategory, NetMsg::ConnectionInfo);
0039     msg.byteArray32(password);
0040     msg.string32(player->name());
0041     msg.string32(player->uuid());
0042     msg.sendToServer();
0043 }
0044 
0045 void PlayerMessageHelper::sendOffPlayerInformations(Player* player)
0046 {
0047     NetworkMessageWriter message(NetMsg::UserCategory, NetMsg::PlayerConnectionAction);
0048     writePlayerIntoMessage(message, player);
0049     message.sendToServer();
0050 }
0051 
0052 void PlayerMessageHelper::writePlayerIntoMessage(NetworkMessageWriter& msg, Player* player)
0053 {
0054     if(nullptr == player)
0055         return;
0056 
0057     msg.string16(player->name());
0058     msg.string8(player->uuid());
0059     auto color= player->getColor();
0060     msg.rgb(color.rgb());
0061     msg.uint8(player->isGM() ? 1 : 0);
0062     msg.string16(QCoreApplication::instance()->applicationVersion());
0063 
0064     auto avatar= player->avatar();
0065 
0066     msg.uint8(static_cast<quint8>(!avatar.isNull()));
0067     if(!avatar.isNull())
0068     {
0069         msg.byteArray32(avatar);
0070     }
0071 
0072     const auto& characters= player->children();
0073     // Characters
0074     msg.int32(static_cast<int>(characters.size()));
0075 
0076     std::for_each(characters.begin(), characters.end(),
0077                   [&msg](const std::unique_ptr<Character>& character)
0078                   { writeCharacterIntoMessage(msg, character.get()); });
0079 
0080     /*QByteArray array;
0081     QDataStream out(&array, QIODevice::WriteOnly);
0082     out.setVersion(QDataStream::Qt_5_7);
0083     out << player->features();
0084 
0085     msg.byteArray32(array);*/
0086 }
0087 
0088 void PlayerMessageHelper::writeVisionIntoMessage(NetworkMessageWriter& msg, CharacterVision* vision)
0089 {
0090     if(nullptr == vision)
0091     {
0092         qWarning() << "Vision can't be serialized into network message";
0093         return;
0094     }
0095 
0096     auto pos = vision->position();
0097     msg.real(pos.x());
0098     msg.real(pos.y());
0099     msg.real(vision->angle());
0100     msg.uint8(vision->shape());
0101     msg.uint8(static_cast<quint8>(vision->visible()));
0102     msg.real(vision->radius());
0103 }
0104 
0105 void PlayerMessageHelper::writeCharacterIntoMessage(NetworkMessageWriter& msg, Character* character)
0106 {
0107     if(nullptr == character)
0108         return;
0109 
0110     auto parent= character->parentPerson();
0111     msg.string8(nullptr != parent ? parent->uuid() : QStringLiteral("nullptr"));
0112     msg.string8(character->uuid());
0113     msg.string16(character->name());
0114     msg.string16(character->stateId());
0115     msg.uint8(static_cast<quint8>(character->isNpc()));
0116     msg.int32(character->number());
0117     auto color= character->getColor();
0118     msg.rgb(color.rgb());
0119     auto lifeColor = character->getLifeColor();
0120     msg.rgb(lifeColor.rgb());
0121     msg.int32(character->getHealthPointsCurrent());
0122     msg.int32(character->getHealthPointsMin());
0123     msg.int32(character->getHealthPointsMax());
0124     msg.int32(character->getInitiativeScore());
0125     msg.string32(character->initCommand());
0126     msg.real(character->getDistancePerTurn());
0127     msg.uint8(static_cast<quint8>(character->hasInitScore()));
0128 
0129     auto avatar= character->avatar();
0130 
0131     msg.uint8(static_cast<quint8>(!avatar.isNull()));
0132     if(!avatar.isNull())
0133         msg.byteArray32(avatar);
0134 }
0135 
0136 bool PlayerMessageHelper::readPlayer(NetworkMessageReader& msg, Player* player)
0137 {
0138     if(!msg.isValid() || nullptr == player)
0139     {
0140         qWarning() << "Network message OUT OF MEMORY player";
0141         return false;
0142     }
0143 
0144     auto name= msg.string16();
0145     auto uuid= msg.string8();
0146     auto color= QColor(msg.rgb());
0147     auto gameMaster= (msg.uint8() != 0);
0148     auto softVersion= msg.string16();
0149 
0150     // auto player= new Player(uuid, name, color, gameMaster);
0151     qDebug() << player->name() << "new player name" << name;
0152     player->setUuid(uuid);
0153     player->setName(name);
0154     player->setColor(color);
0155     player->setGM(gameMaster);
0156     player->setUserVersion(softVersion);
0157 
0158     bool hasAvatar= static_cast<bool>(msg.uint8());
0159     if(hasAvatar)
0160     {
0161         player->setAvatar(msg.byteArray32());
0162     }
0163 
0164     int childCount= msg.int32();
0165     qDebug() << "character count: " << childCount;
0166     for(int i= 0; (i < childCount && msg.isValid()); ++i)
0167     {
0168         try
0169         {
0170             QString parentId;
0171             Character* child= readCharacter(msg,parentId);
0172             player->addCharacter(child);
0173         }
0174         catch(std::bad_alloc&)
0175         {
0176             qWarning() << "Bad alloc";
0177             return false;
0178         }
0179     }
0180     if(!msg.isValid())
0181     {
0182         qWarning() << "Network message OUT OF MEMORY player after character";
0183         return false;
0184     }
0185     /*QByteArray array= msg.byteArray32();
0186     QDataStream in(&array, QIODevice::ReadOnly);
0187     in.setVersion(QDataStream::Qt_5_7);
0188     QMap<QString, quint8> features;
0189     in >> features;
0190     for(auto key : features.keys())
0191     {
0192         auto value= features.value(key);
0193         player->setFeature(key, value);
0194     }*/
0195     return true;
0196 }
0197 
0198 Character* PlayerMessageHelper::readCharacter(NetworkMessageReader& msg, QString& parentId)
0199 {
0200     if(!msg.isValid())
0201         return {};
0202     auto character= new Character();
0203     parentId= msg.string8();
0204     character->setUuid(msg.string8());
0205     character->setName(msg.string16());
0206     character->setStateId(msg.string16());
0207     character->setNpc(static_cast<bool>(msg.uint8()));
0208     character->setNumber(msg.int32());
0209     character->setColor(QColor(msg.rgb()));
0210     character->setLifeColor(QColor(msg.rgb()));
0211     character->setHealthPointsCurrent(msg.int32());
0212     character->setHealthPointsMin(msg.int32());
0213     character->setHealthPointsMax(msg.int32());
0214     character->setInitiativeScore(msg.int32());
0215     character->setInitCommand(msg.string32());
0216     character->setDistancePerTurn(msg.real());
0217     character->setHasInitiative(static_cast<bool>(msg.uint8()));
0218 
0219     bool hasAvatar= static_cast<bool>(msg.uint8());
0220 
0221     if(hasAvatar)
0222     {
0223         auto byte= msg.byteArray32();
0224         character->setAvatar(byte);
0225     }
0226 
0227     return character;
0228 }