Crossfire Server  1.75.0
FaceLoader.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 "FaceLoader.h"
14 #include "Faces.h"
15 #include "Animations.h"
16 #include "AssetsTracker.h"
17 
18 #include "global.h"
19 #include "compat.h"
20 #include "string.h"
21 
23  : m_faces(faces), m_animations(animations), m_tracker(tracker)
24 {
25 }
26 
27 void FaceLoader::loadAnimationBlock(BufferReader *reader, const std::string &full_path, const char *animation_name) {
28  char *buf;
29  int num_frames = 0, i;
30  const Face *faces[MAX_ANIMATIONS];
31  Animations *anim;
32 
33  anim = static_cast<Animations *>(calloc(1, sizeof(Animations)));
34  anim->name = add_string(animation_name);
35  anim->faces = NULL;
36  anim->facings = 1;
37  anim->num_animations = 0;
38 
39  while ((buf = bufferreader_next_line(reader)) != NULL) {
40  if (*buf == '#')
41  continue;
42  if (strlen(buf) == 0)
43  continue;
44 
45  if (!strncmp(buf, "mina", 4)) {
46  anim->faces = static_cast<const Face **>(malloc(sizeof(Face*)*num_frames));
47  for (i = 0; i < num_frames; i++)
48  anim->faces[i] = faces[i];
49  anim->num_animations = num_frames;
50  if (num_frames <= 1) {
51  LOG(llevDebug, "anim: %s has less then two faces in %s\n",
52  anim->name, full_path.c_str());
53  }
54  if (num_frames % anim->facings) {
55  LOG(llevDebug, "anim: %s has %d frames: not a multiple of facings (%d) in %s\n",
56  anim->name, num_frames,
57  anim->facings, full_path.c_str());
58  }
59  m_animations->define(anim->name, anim);
60  if (m_tracker) {
61  m_tracker->assetDefined(anim, full_path);
62  }
63  return;
64  } else if (!strncmp(buf, "facings", 7)) {
65  if (!(anim->facings = atoi(buf+7))) {
66  LOG(llevDebug, "anim: %s has 0 facings in %s (line %s)\n",
67  anim->name, full_path.c_str(), buf);
68  anim->facings = 1;
69  }
70  } else {
71  const Face *face = find_face(buf);
72  faces[num_frames++] = face;
73  }
74  }
75 }
76 
77 void FaceLoader::load(BufferReader *buffer, const std::string& filename) {
78  char *buf, *cp;
79  Face *on_face = NULL;
80 
81  while ((buf = bufferreader_next_line(buffer)) != NULL) {
82  if (*buf == '#' || *buf == '\0')
83  continue;
84  if (!strncmp(buf, "end", 3)) {
85  if (on_face) {
86  on_face = m_faces->define(on_face->name, on_face);
87  if (m_tracker) {
88  m_tracker->assetDefined(on_face, filename);
89  }
90  on_face = NULL;
91  }
92  continue;
93  }
94 
95  if (!strncmp(buf, "smoothface ", 11)) {
96  if (on_face) {
97  on_face->smoothface = m_faces->get(buf + 11);
98  } else {
99  char *space = strchr(buf + 11, ' ');
100  if (!space) {
101  LOG(llevError, "Invalid 'smoothface' %s in %s\n", buf, filename.c_str());
102  } else {
103  (*space) = '\0';
104  space++;
105  auto original = m_faces->get(buf + 11);
106  auto smoothed = m_faces->get(space);
107  original->smoothface = smoothed;
108  }
109  }
110  continue;
111  }
112 
113  if (!strncmp(buf, "face ", 5)) {
114  cp = buf+5;
115 
116  if (on_face) {
117  LOG(llevError, "'face' within a 'face' in %s\n", filename.c_str());
118  if (on_face->name) {
119  free_string(on_face->name);
120  }
121  free(on_face);
122  }
123  on_face = static_cast<Face *>(calloc(1, sizeof(Face)));
124  on_face->name = add_string(cp);
125  on_face->visibility = 0;
126  on_face->magicmap = 0;
127  continue;
128  }
129 
130  if (!strncmp(buf, "animation ", 10)) {
131  if (on_face)
132  LOG(llevError, "faces: 'animation' in 'face' block is deprecated in %s\n", filename.c_str());
133  loadAnimationBlock(buffer, filename, buf + 10);
134  continue;
135  }
136 
137  if (on_face == NULL) {
138  LOG(llevError, "faces: got line with no face set in %s: %s\n", filename.c_str(), buf);
139  } else if (!strncmp(buf, "visibility", 10)) {
140  on_face->visibility = atoi(buf+11);
141  } else if (!strncmp(buf, "magicmap", 8)) {
142  cp = buf+9;
143  on_face->magicmap = find_color(cp) | (on_face->magicmap & FACE_FLOOR);
144  } else if (!strncmp(buf, "is_floor", 8)) {
145  int value = atoi(buf+9);
146  if (value)
147  on_face->magicmap |= FACE_FLOOR;
148  } else
149  LOG(llevError, "faces: unknown line in file %s: %s\n", filename.c_str(), buf);
150  }
151 
152  if (on_face) {
153  LOG(llevError, "unfinished face in %s\n", filename.c_str());
154  if (on_face->name) {
155  free_string(on_face->name);
156  }
157  free(on_face);
158  }
159 }
Error, serious thing.
Definition: logger.h:11
This represents one animation.
Definition: face.h:25
Face * smoothface
Smoothed face for this, NULL for none.
Definition: face.h:18
T * get(const Key &name)
Get a named asset.
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
New face structure - this enforces the notion that data is face by face only - you can not change the...
Definition: face.h:14
virtual void load(BufferReader *reader, const std::string &filename) override
Load assets from the specified reader.
Definition: FaceLoader.cpp:77
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
#define FACE_FLOOR
Definition: newclient.h:318
Global type definitions and header inclusions.
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:294
uint8_t num_animations
How many different faces to animate, size of the faces array.
Definition: face.h:27
AssetsTracker * m_tracker
Definition: FaceLoader.h:36
#define MAX_ANIMATIONS
Definition: define.h:39
Base class to be informed of where an asset is defined.
Definition: AssetsTracker.h:24
FaceLoader(Faces *faces, AllAnimations *animations, AssetsTracker *tracker)
Definition: FaceLoader.cpp:22
Faces * m_faces
Definition: FaceLoader.h:34
Compatibility implementations of useful nonstandard types and functions.
uint8_t facings
How many facings (1,2,4,8).
Definition: face.h:28
AllAnimations * m_animations
Definition: FaceLoader.h:35
virtual void assetDefined(const archetype *asset, const std::string &filename)
Function called when an asset is defined in a file.
Definition: AssetsTracker.h:32
void loadAnimationBlock(BufferReader *reader, const std::string &full_path, const char *animation_name)
Definition: FaceLoader.cpp:27
uint8_t visibility
How visible is the face compared to other faces, highest wins.
Definition: face.h:16
Only for debugging purposes.
Definition: logger.h:13
const Face * find_face(const char *name)
Definition: assets.cpp:286
const Face ** faces
The actual faces for the animation.
Definition: face.h:30
uint8_t find_color(const char *name)
Finds a color by name.
Definition: image.cpp:75
sstring name
Name of the animation sequence.
Definition: face.h:26
StringBuffer * buf
Definition: readable.cpp:1563
char * bufferreader_next_line(BufferReader *br)
Return the next line in the buffer, as separated by a newline.
Definition: Faces.h:19
uint8_t magicmap
Color to show this in magic map.
Definition: face.h:17
sstring name
Face name, as used by archetypes and such.
Definition: face.h:19
T * define(const Key &name, T *asset)
Define an asset, erasing an existing one.