Crossfire Server, Trunk
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];
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  loadAnimationBlock(buffer, filename, buf + 10);
132  continue;
133  }
134 
135  if (on_face == NULL) {
136  LOG(llevError, "faces: got line with no face set in %s: %s\n", filename.c_str(), buf);
137  } else if (!strncmp(buf, "visibility", 10)) {
138  on_face->visibility = atoi(buf+11);
139  } else if (!strncmp(buf, "magicmap", 8)) {
140  cp = buf+9;
141  on_face->magicmap = find_color(cp) | (on_face->magicmap & FACE_FLOOR);
142  } else if (!strncmp(buf, "is_floor", 8)) {
143  int value = atoi(buf+9);
144  if (value)
145  on_face->magicmap |= FACE_FLOOR;
146  } else
147  LOG(llevDebug, "faces: unknown line in file %s: %s\n", filename.c_str(), buf);
148  }
149 
150  if (on_face) {
151  LOG(llevError, "unfinished face in %s\n", filename.c_str());
152  if (on_face->name) {
153  free_string(on_face->name);
154  }
155  free(on_face);
156  }
157 }
AssetsTracker::assetDefined
virtual void assetDefined(const archetype *asset, const std::string &filename)
Definition: AssetsTracker.h:34
global.h
llevError
@ llevError
Definition: logger.h:11
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
FaceLoader::m_faces
Faces * m_faces
Definition: FaceLoader.h:34
AssetsCollection::get
T * get(const Key &name)
Definition: AssetsCollection.h:89
FaceLoader::FaceLoader
FaceLoader(Faces *faces, AllAnimations *animations, AssetsTracker *tracker)
Definition: FaceLoader.cpp:22
AssetsTracker.h
Faces.h
FaceLoader.h
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:1552
space
Crossfire Protocol most of the time after the actual code was already omit certain important and possibly make life miserable any new developer or curious player should be able to find most of the relevant information here If inconsistencies are found or this documentation proves to be consider the latest server side protocol code in the public source code repository as the authoritative reference Introduction If you were ever curious enough to telnet or netcat to a Crossfire chances are you were sorely disappointed While the protocol may seem to use plain text at it actually uses a mix of ASCII and binary data This handbook attempts to document various aspects of the Crossfire protocol As consult the README file to find out how to get in touch with helpful people via mailing and more History the communications plan was set to be a text based system It was up to the server and client to parse these messages and determine what to do These messages were assumed to be line per message At a reasonably early stage of Eric Anderson wrote a then the data itself you could send many data and after the other end could decode these commands This works fairly but I think the creation of numerous sub packets has some performance hit the eutl was not especially well so writing a client for a different platform became more Eric left to work on other products shortly after writing his which didn t really leave anyone with a full understanding of the socket code I have decided to remove the eutl dependency At least one advantage is that having this network related code directly in the client and server makes error handling a bit easier cleaner Packet Format the outside packet method the byte size for the size information is not included here Eutl originally used bytes for the size to bytes seems it makes a least some sense The actual data is something of the nature of the commands listed below It is a text followed by possible other data The remaining data can be binary it is up to the client and server to decode what it sent The commands as described below is just the data portion of the packet If writing a new remember that you must take into account the size of the packet There is no termination of other than knowing how long it should be For most everything that is sent is text This is more or less how things worked under except it packed the ints into bytes in a known order In some we handle ints as in they are sent as binary information How any command handles it is detailed below in the command description The S and C represent the direction of the we use MSB as well as any ints or shorts that get sent inside the packets All packets are defined to have at least one word of followed by a space
Definition: protocol.txt:85
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
Face::name
sstring name
Definition: face.h:19
dragon_attune.animations
dictionary animations
Definition: dragon_attune.py:25
compat.h
FaceLoader::loadAnimationBlock
void loadAnimationBlock(BufferReader *reader, const std::string &full_path, const char *animation_name)
Definition: FaceLoader.cpp:27
FACE_FLOOR
#define FACE_FLOOR
Definition: newclient.h:292
Faces
Definition: Faces.h:19
FaceLoader::m_tracker
AssetsTracker * m_tracker
Definition: FaceLoader.h:36
animate.anim
string anim
Definition: animate.py:20
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
Face::magicmap
uint8_t magicmap
Definition: face.h:17
Face::visibility
uint8_t visibility
Definition: face.h:16
AssetsCollection::define
T * define(const Key &name, T *asset)
Definition: AssetsCollection.h:120
Animations.h
BufferReader
Definition: bufferreader.cpp:21
autojail.value
value
Definition: autojail.py:6
find_color
uint8_t find_color(const char *name)
Definition: image.cpp:75
FaceLoader::m_animations
AllAnimations * m_animations
Definition: FaceLoader.h:35
AssetsTracker
Definition: AssetsTracker.h:26
AllAnimations
Definition: Animations.h:19
dragon_attune.faces
dictionary faces
Definition: dragon_attune.py:31
Face
Definition: face.h:14
MAX_ANIMATIONS
#define MAX_ANIMATIONS
Definition: define.h:39
Animations
Definition: face.h:25
Face::smoothface
Face * smoothface
Definition: face.h:18
FaceLoader::load
virtual void load(BufferReader *reader, const std::string &filename) override
Definition: FaceLoader.cpp:77
if
if(!(yy_init))
Definition: loader.c:2626
llevDebug
@ llevDebug
Definition: logger.h:13
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.cpp:102