File indexing completed on 2024-05-19 05:40:49
0001 /*************************************************************************** 0002 * Copyright (C) 2021 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 "updater/media/campaignupdater.h" 0021 0022 #include "data/campaign.h" 0023 #include "data/media.h" 0024 #include "diceparser/dicealias.h" 0025 #include "diceparser_qobject/diceroller.h" 0026 #include "model/characterstatemodel.h" 0027 #include "model/dicealiasmodel.h" 0028 #include "model/nonplayablecharactermodel.h" 0029 #include "utils/logcategories.h" 0030 #include "worker/fileserializer.h" 0031 #include "worker/messagehelper.h" 0032 #include <QDir> 0033 0034 namespace campaign 0035 { 0036 CampaignUpdater::CampaignUpdater(DiceRoller* dice, Campaign* manager, QObject* parent) 0037 : QObject(parent), m_campaign(manager), m_dice(dice) 0038 { 0039 setCampaign(manager); 0040 0041 ReceiveEvent::registerNetworkReceiver(NetMsg::CampaignCategory, this); 0042 } 0043 0044 void CampaignUpdater::setCampaign(Campaign* campaign) 0045 { 0046 if(campaign == m_campaign) 0047 return; 0048 m_campaign= campaign; 0049 0050 // GM player 0051 auto model= m_campaign->diceAliases(); 0052 0053 connect(model, &DiceAliasModel::aliasAdded, this, &CampaignUpdater::updateDiceAliases); 0054 connect(model, &DiceAliasModel::aliasRemoved, this, &CampaignUpdater::updateDiceAliases); 0055 connect(model, &DiceAliasModel::aliasMoved, this, &CampaignUpdater::updateDiceAliases); 0056 connect(model, &DiceAliasModel::modelReset, this, &CampaignUpdater::updateDiceAliases); 0057 connect(model, &DiceAliasModel::dataChanged, this, &CampaignUpdater::updateDiceAliases); 0058 connect(model, &DiceAliasModel::aliasChanged, this, &CampaignUpdater::updateDiceAliases); 0059 0060 updateDiceAliases(); 0061 0062 // GM player 0063 auto states= m_campaign->stateModel(); 0064 0065 auto updateState= [this]() 0066 { 0067 if(!canForward()) 0068 return; 0069 auto const& states= m_campaign->stateModel()->statesList(); 0070 FileSerializer::writeStatesIntoCampaign(m_campaign->rootDirectory(), 0071 FileSerializer::statesToArray(states, m_campaign->rootDirectory())); 0072 updateStateModel(); 0073 auto list= new QList<CharacterState*>(); 0074 std::transform(std::begin(states), std::end(states), std::back_inserter(*list), 0075 [](const std::unique_ptr<CharacterState>& item) { return item.get(); }); 0076 Character::setListOfCharacterState(list); 0077 }; 0078 0079 connect(states, &CharacterStateModel::characterStateAdded, this, updateState); 0080 connect(states, &CharacterStateModel::stateRemoved, this, updateState); 0081 connect(states, &CharacterStateModel::stateMoved, this, updateState); 0082 connect(states, &CharacterStateModel::modelReset, this, updateState); 0083 connect(states, &CharacterStateModel::dataChanged, this, updateState); 0084 connect(states, &CharacterStateModel::stateChanged, this, updateState); 0085 0086 // updateNPCModel 0087 auto npcModel= m_campaign->npcModel(); 0088 auto updateNpcModel= [this]() 0089 { 0090 auto const& npcs= m_campaign->npcModel()->npcList(); 0091 if(!npcs.empty()) 0092 FileSerializer::writeNpcIntoCampaign(m_campaign->rootDirectory(), 0093 FileSerializer::npcToArray(npcs, m_campaign->rootDirectory())); 0094 }; 0095 connect(npcModel, &NonPlayableCharacterModel::characterAdded, this, updateNpcModel); 0096 connect(npcModel, &NonPlayableCharacterModel::characterRemoved, this, updateNpcModel); 0097 connect(npcModel, &NonPlayableCharacterModel::dataChanged, this, updateNpcModel); 0098 connect(npcModel, &NonPlayableCharacterModel::modelReset, this, updateNpcModel); 0099 0100 auto updateCampaign= [this]() 0101 { FileSerializer::writeCampaignInfo(m_campaign->rootDirectory(), FileSerializer::campaignToObject(m_campaign)); }; 0102 0103 connect(m_campaign, &Campaign::nameChanged, this, updateCampaign); 0104 connect(m_campaign, &Campaign::currentChapterChanged, this, updateCampaign); 0105 connect(m_campaign, &Campaign::mediaAdded, this, updateCampaign); 0106 connect(m_campaign, &Campaign::mediaNameChanged, this, updateCampaign); 0107 connect(m_campaign, &Campaign::mediaRemoved, this, updateCampaign); 0108 } 0109 0110 NetWorkReceiver::SendType CampaignUpdater::processMessage(NetworkMessageReader* msg) 0111 { 0112 if(msg->action() == NetMsg::CharactereStateModel && msg->category() == NetMsg::CampaignCategory && !m_localIsGm) 0113 { 0114 setUpdating(true); 0115 MessageHelper::fetchCharacterStatesFromNetwork(msg, m_campaign->stateModel()); 0116 setUpdating(false); 0117 } 0118 else if(msg->action() == NetMsg::DiceAliasModel && msg->category() == NetMsg::CampaignCategory && !m_localIsGm) 0119 { 0120 MessageHelper::fetchDiceAliasFromNetwork(msg, m_dice->aliases()); 0121 } 0122 return NetWorkReceiver::NONE; 0123 } 0124 0125 DiceRoller* CampaignUpdater::diceParser() const 0126 { 0127 return m_dice; 0128 } 0129 0130 bool CampaignUpdater::localIsGM() 0131 { 0132 return m_localIsGm; 0133 } 0134 0135 void CampaignUpdater::updateDiceModel() 0136 { 0137 if(localIsGM()) 0138 MessageHelper::sendOffAllDiceAlias(m_campaign->diceAliases()); 0139 } 0140 0141 void CampaignUpdater::updateStateModel() 0142 { 0143 if(localIsGM()) 0144 MessageHelper::sendOffAllCharacterState(m_campaign->stateModel()); 0145 } 0146 0147 void CampaignUpdater::saveCampaignTo(const QString& dir) 0148 { 0149 createCampaignTemplate(dir); 0150 saveDataInto(dir); 0151 } 0152 0153 void CampaignUpdater::save() 0154 { 0155 saveDataInto(m_campaign->rootDirectory()); 0156 } 0157 0158 void CampaignUpdater::saveDataInto(const QString& path) 0159 { 0160 // Dice Aliases 0161 const auto& newAliases= m_campaign->diceAliases()->aliases(); 0162 FileSerializer::writeDiceAliasIntoCampaign(path, FileSerializer::dicesToArray(newAliases)); 0163 0164 // States 0165 auto const& states= m_campaign->stateModel()->statesList(); 0166 if(!states.empty()) 0167 FileSerializer::writeStatesIntoCampaign(path, FileSerializer::statesToArray(states, path)); 0168 0169 // NPC 0170 0171 auto const& npcs= m_campaign->npcModel()->npcList(); 0172 if(!npcs.empty()) 0173 FileSerializer::writeNpcIntoCampaign(path, FileSerializer::npcToArray(npcs, m_campaign->rootDirectory())); 0174 0175 // Campaign Info 0176 FileSerializer::writeCampaignInfo(path, FileSerializer::campaignToObject(m_campaign)); 0177 } 0178 0179 void CampaignUpdater::setLocalIsGM(bool b) 0180 { 0181 if(b == m_localIsGm) 0182 return; 0183 m_localIsGm= b; 0184 emit localIsGMChanged(); 0185 } 0186 0187 bool CampaignUpdater::createCampaignTemplate(const QString& dirPath) 0188 { 0189 auto dir= QDir(dirPath); 0190 0191 if(dir.exists() && !dir.isEmpty()) 0192 { 0193 qCInfo(logCategory::campaign) << tr("'%1' is not empty").arg(dirPath); 0194 return false; 0195 } 0196 else if(!dir.exists()) 0197 { 0198 auto parentDir= dir; 0199 parentDir.cdUp(); 0200 if(!parentDir.mkdir(dirPath)) 0201 { 0202 qCInfo(logCategory::campaign) << tr("Could not create '%1'").arg(dirPath); 0203 return false; 0204 } 0205 FileSerializer::createCampaignDirectory(dirPath); 0206 } 0207 else 0208 { 0209 FileSerializer::createCampaignDirectory(dirPath); 0210 } 0211 return true; 0212 } 0213 0214 void CampaignUpdater::updateDiceAliases() 0215 { 0216 if(!canForward()) 0217 return; 0218 auto aliases= m_dice->aliases(); 0219 if(!aliases) 0220 return; 0221 qDeleteAll(*aliases); 0222 aliases->clear(); 0223 const auto& newAliases= m_campaign->diceAliases()->aliases(); 0224 std::for_each(std::begin(newAliases), std::end(newAliases), 0225 [aliases](const std::unique_ptr<DiceAlias>& alias) 0226 { 0227 auto p= alias.get(); 0228 aliases->append(new DiceAlias(*p)); 0229 }); 0230 0231 FileSerializer::writeDiceAliasIntoCampaign(m_campaign->rootDirectory(), FileSerializer::dicesToArray(newAliases)); 0232 updateDiceModel(); 0233 } 0234 0235 void CampaignUpdater::setUpdating(bool b) 0236 { 0237 m_updatingModel= b; 0238 } 0239 0240 bool CampaignUpdater::canForward() 0241 { 0242 return !m_updatingModel && m_localIsGm; 0243 } 0244 } // namespace campaign