Crossfire Server, Trunk
MessageLoader.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 2020 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 "MessageLoader.h"
14 #include "Messages.h"
15 
16 #include "global.h"
17 #include "compat.h"
18 #include "string.h"
19 #include "AssetsTracker.h"
20 
21 MessageLoader::MessageLoader(Messages* messages, AssetsTracker *tracker) : m_messages(messages), m_tracker(tracker) {
22 }
23 
24 void MessageLoader::load(BufferReader *reader, const std::string &filename) {
25  char *buf, msgbuf[HUGE_BUF], *cp;
26  int text = 0, nrofmsg = 0;
27 
28  LOG(llevDebug, "Reading messages from %s...\n", filename.c_str());
29 
30  GeneralMessage *tmp = NULL;
31 
32  while ((buf = bufferreader_next_line(reader)) != NULL) {
33  if (*buf == '#' || (*buf == '\0' && !text))
34  continue;
35 
36  // Remove trailing whitespace
37  cp = buf + strlen(buf);
38  while (cp > buf && (cp[-1] == ' ' || cp[-1] == '\t'))
39  cp--;
40  if (cp > buf) {
41  *cp = '\0';
42  }
43 
44  if (tmp != NULL) {
45  if (text && strncmp(buf, "ENDMSG", 6) == 0) {
46  if (strlen(msgbuf) > BOOK_BUF) {
47  LOG(llevDebug, "Warning: this string exceeded max book buf size:\n");
48  LOG(llevDebug, " %s\n", msgbuf);
49  }
50  tmp->message = add_string(msgbuf);
51  if (tmp->identifier[0] != '\n' && tmp->title == NULL) {
52  LOG(llevError, "Error: message can't have identifier without title, file %s on line %zu\n", filename.c_str(), bufferreader_current_line(reader));
53  }
54  tmp = m_messages->define(tmp->identifier, tmp);
55  if (m_tracker) {
57  }
58  nrofmsg++;
59  tmp = NULL;
60  text = 0;
61  } else if (text) {
62  if (!buf_overflow(msgbuf, buf, HUGE_BUF-1)) {
63  strcat(msgbuf, buf);
64  strcat(msgbuf, "\n");
65  } else {
66  LOG(llevInfo, "Warning: truncating book at %s, line %zu\n", filename.c_str(), bufferreader_current_line(reader));
67  }
68  } else if (strcmp(buf, "TEXT") == 0) {
69  text = 1;
70  } else if (strncmp(buf, "CHANCE ", 7) == 0) {
71  tmp->chance = atoi(buf + 7);
72  } else if (strncmp(buf, "TITLE ", 6) == 0) {
73  tmp->title = add_string(buf + 6);
74  } else if (strncmp(buf, "QUEST ", 6) == 0) {
75  tmp->quest_code = add_string(buf + 6);
76  } else if (strncmp(buf, "FACE ", 5) == 0) {
77  const Face *face = find_face(buf + 5);
78  tmp->face = face;
79  } else {
80  LOG(llevInfo, "Warning: unknown line %s, in file %s line %zu\n", buf, filename.c_str(), bufferreader_current_line(reader));
81  }
82  } else if (strncmp(buf, "MSG", 3) == 0) {
83  tmp = (GeneralMessage *)calloc(1, sizeof(GeneralMessage));
84  tmp->face = NULL;
85  if (buf[3] == ' ') {
86  int i = 4;
87  while (buf[i] == ' ')
88  i++;
89  if (buf[i] != '\0') {
90  tmp->identifier = add_string(buf + i);
91  }
92  }
93  /* We need an identifier, so generate one from filename and line, that should be unique enough! */
94  if (!tmp->identifier) {
95  snprintf(msgbuf, sizeof(msgbuf), "\n%s\n%zu", filename.c_str(), bufferreader_current_line(reader));
96  tmp->identifier = add_string(msgbuf);
97  }
98  strcpy(msgbuf, ""); /* reset msgbuf for new message */
99  } else {
100  LOG(llevInfo, "Warning: syntax error at %s, line %zu\n", filename.c_str(), bufferreader_current_line(reader));
101  }
102  }
103 
104  if (tmp != NULL) {
105  LOG(llevError, "Invalid file %s", filename.c_str());
107  }
108 
109  LOG(llevDebug, "done messages %s, found %d messages.\n", filename.c_str(), nrofmsg);
110 }
Face
Definition: face.h:14
global.h
GeneralMessage
Definition: book.h:44
bufferreader_current_line
size_t bufferreader_current_line(BufferReader *br)
Definition: bufferreader.cpp:140
llevError
@ llevError
Definition: logger.h:11
MessageLoader::m_tracker
AssetsTracker * m_tracker
Definition: MessageLoader.h:34
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
MessageLoader::MessageLoader
MessageLoader(Messages *messages, AssetsTracker *tracker)
Definition: MessageLoader.cpp:21
Messages.h
MessageLoader::m_messages
Messages * m_messages
Definition: MessageLoader.h:33
Ice.tmp
int tmp
Definition: Ice.py:207
Messages
Definition: Messages.h:22
SEE_LAST_ERROR
@ SEE_LAST_ERROR
Definition: define.h:52
npc_dialog.filename
filename
Definition: npc_dialog.py:99
find_face
const Face * find_face(const char *name)
Definition: assets.cpp:282
buf
StringBuffer * buf
Definition: readable.cpp:1565
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
AssetsTracker
Definition: AssetsTracker.h:26
AssetsCollection::define
T * define(const Key &name, T *asset)
Definition: AssetsCollection.h:120
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
compat.h
AssetsTracker::assetDefined
virtual void assetDefined(const archetype *asset, const std::string &filename)
Definition: AssetsTracker.h:34
AssetsTracker.h
guild_entry.text
text
Definition: guild_entry.py:41
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:590
navar-midane_apply.messages
list messages
Definition: navar-midane_apply.py:8
llevInfo
@ llevInfo
Definition: logger.h:12
msgbuf
static char msgbuf[HUGE_BUF]
Definition: loader.cpp:35880
BOOK_BUF
#define BOOK_BUF
Definition: book.h:16
MessageLoader::load
virtual void load(BufferReader *reader, const std::string &filename) override
Definition: MessageLoader.cpp:24
MessageLoader.h
buf_overflow
int buf_overflow(const char *buf1, const char *buf2, size_t bufsize)
Definition: shstr.cpp:398
BufferReader
Definition: bufferreader.cpp:21
llevDebug
@ llevDebug
Definition: logger.h:13
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.cpp:102