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