Crossfire Server, Trunk
MessageFile.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 2022 the Crossfire Development Team
5  *
6  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
7  * welcome to redistribute it under certain conditions. For details, please
8  * see COPYING and LICENSE.
9  *
10  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
11  */
12 
13 #include <qiodevice.h>
14 #include <qfile.h>
15 #include <qscriptengine.h>
16 #include <QDebug>
17 
18 #include "MessageFile.h"
19 #include "quests/QuestWrapper.h"
20 
21 #include "global.h"
22 
24 {
25  myIsModified = false;
26 }
27 
28 MessageRule::MessageRule(const MessageRule& original) : QObject()
29 {
30  myIsModified = true;
31  myMatch = original.match();
32  myPreconditions = original.preconditions();
33  myMessages = original.messages();
34  myPostconditions = original.postconditions();
35  myReplies = original.replies();
36 }
37 
39 {
40 }
41 
42 const QString& MessageRule::comment() const
43 {
44  return myComment;
45 }
46 
47 void MessageRule::setComment(const QString& comment)
48 {
50 }
51 
52 const QStringList& MessageRule::match() const
53 {
54  return myMatch;
55 }
56 
57 QStringList& MessageRule::match()
58 {
59  return myMatch;
60 }
61 
62 void MessageRule::setMatch(const QStringList& match)
63 {
64  myMatch = match;
65 }
66 
67 const QList<QStringList>& MessageRule::preconditions() const
68 {
69  return myPreconditions;
70 }
71 
72 void MessageRule::setPreconditions(const QList<QStringList>& preconditions)
73 {
75 }
76 
77 const QList<QStringList>& MessageRule::postconditions() const
78 {
79  return myPostconditions;
80 }
81 
82 void MessageRule::setPostconditions(const QList<QStringList>& postconditions)
83 {
85 }
86 
87 const QStringList& MessageRule::messages() const
88 {
89  return myMessages;
90 }
91 
92 void MessageRule::setMessages(const QStringList& messages)
93 {
95 }
96 
97 const QStringList& MessageRule::include() const
98 {
99  return myInclude;
100 }
101 
102 void MessageRule::setInclude(const QStringList& include)
103 {
104  myInclude = include;
105 }
106 
107 const QList<QStringList>& MessageRule::replies() const
108 {
109  return myReplies;
110 }
111 
112 void MessageRule::setReplies(const QList<QStringList>& replies)
113 {
114  myReplies = replies;
115 }
116 
118 {
119  return myIsModified;
120 }
121 
122 void MessageRule::setModified(bool modified)
123 {
124  myIsModified = modified;
125 }
126 
127 MessageFile::MessageFile(AssetWrapper *parent, const QString& path) : AssetWrapper(parent, "Message") {
128  myPath = path;
129  myIsModified = false;
130 }
131 
133 {
134  qDeleteAll(myRules);
135 }
136 
138 {
139  MessageFile* copy = new MessageFile(nullptr, myPath);
140  copy->myLocation = myLocation;
141  for (auto rule : myRules)
142  copy->myRules.append(new MessageRule(*rule));
143  copy->myMaps = myMaps;
144  return copy;
145 }
146 
147 void MessageFile::copy(const MessageFile* other)
148 {
149  myPath = other->myPath;
150  myLocation = other->myLocation;
151  qDeleteAll(myRules);
152  myRules.clear();
153  for (auto rule : other->myRules)
154  myRules.append(new MessageRule(*rule));
155  myMaps = other->myMaps;
156 }
157 
158 const QString& MessageFile::location() const
159 {
160  return myLocation;
161 }
162 
163 const QString& MessageFile::path() const
164 {
165  return myPath;
166 }
167 
168 void MessageFile::setPath(const QString& path)
169 {
170  if (myPath != path)
171  {
172  myPath = path;
173  setModified();
174  }
175 }
176 
177 void MessageFile::setLocation(const QString& location)
178 {
179  if (myLocation != location)
180  {
182  setModified();
183  }
184 }
185 
186 void convert(QScriptValue& value, QList<QStringList>& list)
187 {
188  list.clear();
189  int length = value.property("length").toInt32();
190  for (int l = 0; l < length; l++)
191  {
192  QStringList items;
193  QScriptValue sub = value.property(l);
194 
195  int subl = sub.property("length").toInt32();
196  for (int s = 0; s < subl; s++)
197  items.append(sub.property(s).toString());
198 
199  list.append(items);
200  }
201 }
202 
204 {
205  QString full = QString("%1/%2/%3").arg(settings.datadir, settings.mapdir, myPath);
206  QFile file(full);
207  file.open(QIODevice::ReadOnly);
208 
209  QByteArray data = file.readAll();
210  if (data.size() == 0)
211  return false;
212  QString script = data;
213  if (!script.startsWith('['))
214  script = "[" + script + "]";
215 
216  QScriptValue value;
217  QScriptEngine engine;
218  value = engine.evaluate(script);
219  if (engine.hasUncaughtException())
220  {
221  qDebug() << "message file evaluate error" << myPath << engine.uncaughtException().toString();
222  return false;
223  }
224 
225  QScriptValue first = value.property(0);
226  myLocation = first.property("location").toString();
227 
228  QScriptValue rules = first.property("rules");
229  int length = rules.property("length").toInt32();
230  for (int r = 0; r < length; r++)
231  {
232  MessageRule* rule = new MessageRule();
233  myRules.append(rule);
234  QScriptValue v = rules.property(r);
235 
236  rule->setComment(v.property("comment").toString());
237 
238  QStringList items;
239  qScriptValueToSequence(v.property("match"), items);
240  rule->setMatch(items);
241 
242  QList<QStringList> lists;
243  QScriptValue p = v.property("pre");
244  convert(p, lists);
245  rule->setPreconditions(lists);
246 
247  p = v.property("post");
248  convert(p, lists);
249  rule->setPostconditions(lists);
250 
251  items.clear();
252  qScriptValueToSequence(v.property("include"), items);
253  rule->setInclude(items);
254 
255  items.clear();
256  qScriptValueToSequence(v.property("msg"), items);
257  rule->setMessages(items);
258 
259  p = v.property("replies");
260  convert(p, lists);
261  rule->setReplies(lists);
262  }
263  return true;
264 }
265 
266 QList<MessageRule*>& MessageFile::rules()
267 {
268  return myRules;
269 }
270 
271 QList<CREMapInformation*>& MessageFile::maps()
272 {
273  return myMaps;
274 }
275 
276 QString convert(const QString& text)
277 {
278  QString tmp(text);
279  return tmp.replace('"', "\\\"").replace('\n', "\\n");
280 }
281 
282 QString convert(const QStringList& list)
283 {
284  QStringList one;
285  foreach(const QString& line, list)
286  {
287  one.append("\"" + convert(line) + "\"");
288  }
289  return "[" + one.join(", ") + "]";
290 }
291 
292 QString convert(const QList<QStringList>& data)
293 {
294  QStringList lines;
295 
296  foreach(const QStringList& list, data)
297  {
298  lines.append(convert(list));
299  }
300 
301  return "[" + lines.join(", ") + "]";
302 }
303 
304 QString convert(const MessageRule* rule)
305 {
306  QString result;
307 
308  if (!rule->include().isEmpty())
309  {
310  result += "{\n \"include\" : " + convert(rule->include());
311  if (!rule->preconditions().isEmpty())
312  result += ",\n \"pre\" : " + convert(rule->preconditions());
313  result += "\n }";
314  return result;
315  }
316 
317  result += "{\n";
318 
319  if (!rule->comment().isEmpty())
320  {
321  result += " \"comment\" : \"";
322  result += convert(rule->comment());
323  result += "\",\n";
324  }
325 
326  result += " \"match\" : ";
327  result += convert(rule->match());
328 
329  result += ",\n \"pre\" : ";
330  result += convert(rule->preconditions());
331 
332  result += ",\n \"post\" : ";
333  result += convert(rule->postconditions());
334 
335  result += ",\n \"msg\" : ";
336  result += convert(rule->messages());
337 
338  if (!rule->replies().isEmpty())
339  {
340  result += ",\n \"replies\" : ";
341  result += convert(rule->replies());
342  }
343 
344  result += "\n }";
345 
346  return result;
347 }
348 
350 {
351  bool one = myIsModified;
352  foreach(MessageRule* rule, myRules)
353  {
354  if (rule->isModified())
355  {
356  one = true;
357  break;
358  }
359  }
360  if (!one)
361  return;
362 
363  qDebug() << "MessageFile saving" << myPath;
364 
365  QString data = "{\n";
366  if (!myLocation.isEmpty())
367  data += " \"location\" : \"" + myLocation + "\",\n";
368  data += " \"rules\": [\n ";
369 
370  QStringList rules;
371  foreach(MessageRule* rule, myRules)
372  {
373  rules.append(convert(rule));
374  rule->setModified(false);
375  }
376 
377  data += rules.join(", ");
378  data += "\n]}\n";
379 
380  QString full = QString("%1/%2/%3").arg(settings.datadir, settings.mapdir, myPath);
381  QFile file(full);
382  file.open(QIODevice::WriteOnly | QIODevice::Truncate);
383  file.write(data.toLatin1());
384  file.close();
385 
386  setModified(false);
387 }
388 
390 {
391  return myIsModified;
392 }
393 
394 void MessageFile::setModified(bool modified)
395 {
397 }
398 
399 AssetWrapper::PossibleUse MessageFile::uses(const AssetWrapper *asset, std::string &) const {
400  auto quest = dynamic_cast<const QuestWrapper *>(asset);
401  if (quest) {
402  foreach(const MessageRule* rule, myRules) {
403  QList<QStringList> conditions = rule->preconditions();
404  conditions.append(rule->postconditions());
405  foreach(QStringList list, conditions) {
406  if (list.size() > 1 && (list[0] == "quest" || list[0] == "questdone") && list[1] == quest->wrappedItem()->quest_code) {
407  return Uses;
408  }
409  }
410  }
411  return DoesntUse;
412  }
413  return DoesntUse;
414 }
MessageFile::path
QString path
Definition: MessageFile.h:71
npc_dialog.location
string location
Definition: npc_dialog.py:49
Settings::mapdir
const char * mapdir
Definition: global.h:255
global.h
settings
struct Settings settings
Definition: init.cpp:139
banquet.l
l
Definition: banquet.py:164
MessageFile::copy
void copy(const MessageFile *other)
Definition: MessageFile.cpp:147
MessageRule::~MessageRule
virtual ~MessageRule()
Definition: MessageFile.cpp:38
MessageFile::~MessageFile
virtual ~MessageFile()
Definition: MessageFile.cpp:132
MessageRule::setPostconditions
void setPostconditions(const QList< QStringList > &postconditions)
Definition: MessageFile.cpp:82
MessageFile::maps
QList< CREMapInformation * > & maps()
Definition: MessageFile.cpp:271
MessageFile::duplicate
MessageFile * duplicate() const
Definition: MessageFile.cpp:137
MessageFile::isModified
bool isModified() const
Definition: MessageFile.cpp:389
Settings::datadir
const char * datadir
Definition: global.h:252
QuestWrapper
Definition: QuestWrapper.h:66
AssetWrapper::PossibleUse
PossibleUse
Definition: AssetWrapper.h:31
guildoracle.list
list
Definition: guildoracle.py:87
MessageRule::myComment
QString myComment
Definition: MessageFile.h:55
mad_mage_user.file
file
Definition: mad_mage_user.py:15
Ice.tmp
int tmp
Definition: Ice.py:207
MessageFile::myLocation
QString myLocation
Definition: MessageFile.h:112
MessageFile::save
void save()
Definition: MessageFile.cpp:349
MessageRule::myPostconditions
QList< QStringList > myPostconditions
Definition: MessageFile.h:58
MessageFile
Definition: MessageFile.h:68
MessageFile::myIsModified
bool myIsModified
Definition: MessageFile.h:110
MessageRule::messages
const QStringList & messages() const
Definition: MessageFile.cpp:87
MessageRule::setInclude
void setInclude(const QStringList &include)
Definition: MessageFile.cpp:102
MessageRule::setMatch
void setMatch(const QStringList &match)
Definition: MessageFile.cpp:62
npc_dialog.replies
replies
Definition: npc_dialog.py:105
QuestWrapper.h
quest
Definition: quest.py:1
convert
void convert(QScriptValue &value, QList< QStringList > &list)
Definition: MessageFile.cpp:186
is_valid_types_gen.line
line
Definition: is_valid_types_gen.py:34
MessageFile::MessageFile
MessageFile(AssetWrapper *parent, const QString &path)
Definition: MessageFile.cpp:127
MessageRule::include
const QStringList & include() const
Definition: MessageFile.cpp:97
rotate-tower.result
bool result
Definition: rotate-tower.py:13
MessageFile::setLocation
void setLocation(const QString &location)
Definition: MessageFile.cpp:177
AssetWrapper
Definition: AssetWrapper.h:25
MessageRule::MessageRule
MessageRule()
Definition: MessageFile.cpp:23
MessageRule::myPreconditions
QList< QStringList > myPreconditions
Definition: MessageFile.h:57
python_init.path
path
Definition: python_init.py:8
MessageRule::setModified
void setModified(bool modified=true)
Definition: MessageFile.cpp:122
MessageFile::setPath
void setPath(const QString &path)
Definition: MessageFile.cpp:168
navar-midane_time.data
data
Definition: navar-midane_time.py:11
MessageRule::myInclude
QStringList myInclude
Definition: MessageFile.h:60
MessageRule::myMessages
QStringList myMessages
Definition: MessageFile.h:59
MessageRule::setPreconditions
void setPreconditions(const QList< QStringList > &preconditions)
Definition: MessageFile.cpp:72
push.match
bool match
Definition: push.py:61
MessageFile::setModified
void setModified(bool modified=true)
Definition: MessageFile.cpp:394
AssetWrapper::Uses
@ Uses
Definition: AssetWrapper.h:31
AssetWrapper::modified
void modified()
guild_entry.text
text
Definition: guild_entry.py:44
navar-midane_apply.messages
list messages
Definition: navar-midane_apply.py:8
MessageFile::rules
QList< MessageRule * > & rules()
Definition: MessageFile.cpp:266
MessageRule::myMatch
QStringList myMatch
Definition: MessageFile.h:56
MessageRule::replies
const QList< QStringList > & replies() const
Definition: MessageFile.cpp:107
MessageFile.h
MessageRule::setReplies
void setReplies(const QList< QStringList > &replies)
Definition: MessageFile.cpp:112
MessageRule::myReplies
QList< QStringList > myReplies
Definition: MessageFile.h:61
MessageFile::myRules
QList< MessageRule * > myRules
Definition: MessageFile.h:113
MessageFile::uses
virtual PossibleUse uses(const AssetWrapper *asset, std::string &) const override
Definition: MessageFile.cpp:399
MessageFile::parseFile
bool parseFile()
Definition: MessageFile.cpp:203
autojail.value
value
Definition: autojail.py:6
MessageFile::location
QString location
Definition: MessageFile.h:72
MessageRule::match
const QStringList & match() const
Definition: MessageFile.cpp:52
MessageRule::preconditions
const QList< QStringList > & preconditions() const
Definition: MessageFile.cpp:67
MessageFile::myPath
QString myPath
Definition: MessageFile.h:111
lists
ignore_list ** lists
Definition: gridarta-types-convert.cpp:73
MessageRule::myIsModified
bool myIsModified
Definition: MessageFile.h:54
MessageRule::postconditions
const QList< QStringList > & postconditions() const
Definition: MessageFile.cpp:77
MessageRule::isModified
bool isModified() const
Definition: MessageFile.cpp:117
AssetWrapper::DoesntUse
@ DoesntUse
Definition: AssetWrapper.h:31
MessageRule::setComment
void setComment(const QString &comment)
Definition: MessageFile.cpp:47
MessageFile::myMaps
QList< CREMapInformation * > myMaps
Definition: MessageFile.h:114
npc_dialog.rule
rule
Definition: npc_dialog.py:108
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
MessageRule
Definition: MessageFile.h:25
MessageRule::setMessages
void setMessages(const QStringList &messages)
Definition: MessageFile.cpp:92
MessageRule::comment
const QString & comment() const
Definition: MessageFile.cpp:42