]> git.localhorst.tv Git - l2e.git/blob - src/loader/Interpreter.cpp
added destructors for ParsedSource & Co. to free some resources
[l2e.git] / src / loader / Interpreter.cpp
1 /*
2  * Interpreter.cpp
3  *
4  *  Created on: Aug 26, 2012
5  *      Author: holy
6  */
7
8 #include "Interpreter.h"
9
10 #include "ParsedSource.h"
11 #include "../battle/Hero.h"
12 #include "../battle/Monster.h"
13 #include "../graphics/ComplexAnimation.h"
14 #include "../graphics/SimpleAnimation.h"
15 #include "../graphics/Sprite.h"
16
17 #include <SDL_image.h>
18
19 using battle::Hero;
20 using battle::Monster;
21 using battle::Stats;
22 using graphics::Animation;
23 using graphics::ComplexAnimation;
24 using graphics::SimpleAnimation;
25 using graphics::Sprite;
26 using geometry::Vector;
27 using std::map;
28 using std::set;
29 using std::string;
30 using std::vector;
31
32 namespace loader {
33
34 Animation *Interpreter::GetAnimation(const std::string &name) {
35         map<string, Animation *>::const_iterator i(animations.find(name));
36         if (i != animations.end()) {
37                 return i->second;
38         } else {
39                 throw Error("access to undefined Animation " + name);
40         }
41 }
42
43 Hero *Interpreter::GetHero(const std::string &name) {
44         map<string, Hero *>::const_iterator i(heroes.find(name));
45         if (i != heroes.end()) {
46                 return i->second;
47         } else {
48                 throw Error("access to undefined Hero " + name);
49         }
50 }
51
52 Monster *Interpreter::GetMonster(const std::string &name) {
53         map<string, Monster *>::const_iterator i(monsters.find(name));
54         if (i != monsters.end()) {
55                 return i->second;
56         } else {
57                 throw Error("access to undefined Monster " + name);
58         }
59 }
60
61 int Interpreter::GetNumber(const std::string &name) const {
62         map<string, int>::const_iterator i(numbers.find(name));
63         if (i != numbers.end()) {
64                 return i->second;
65         } else {
66                 throw Error("access to undefined Number " + name);
67         }
68 }
69
70 Sprite *Interpreter::GetSprite(const std::string &name) {
71         map<string, Sprite *>::const_iterator i(sprites.find(name));
72         if (i != sprites.end()) {
73                 return i->second;
74         } else {
75                 throw Error("access to undefined Sprite " + name);
76         }
77 }
78
79
80 void Interpreter::ReadSource() {
81         for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
82                 ReadDefinition(source.GetDefinition(*i));
83         }
84 }
85
86 void Interpreter::ReadDefinition(const Definition &dfn) {
87         if (parsedDefinitions.find(dfn.Identifier()) != parsedDefinitions.end()) {
88                 return;
89         }
90         if (dfn.HasLiteralValue()) {
91                 ReadLiteral(dfn);
92         } else {
93                 ReadObject(dfn);
94         }
95 }
96
97 void Interpreter::ReadLiteral(const Definition &dfn) {
98         switch (dfn.GetLiteral()->GetType()) {
99                 case Literal::ARRAY_VALUES:
100                         throw Error("unhandled literal: array of values");
101                         break;
102                 case Literal::ARRAY_PROPS:
103                         throw Error("unhandled literal: array of properties");
104                         break;
105                 case Literal::BOOLEAN:
106                         throw Error("unhandled literal: boolean");
107                         break;
108                 case Literal::COLOR:
109                         throw Error("unhandled literal: color");
110                         break;
111                 case Literal::NUMBER:
112                         numbers[dfn.Identifier()] = dfn.GetLiteral()->GetNumber();
113                         break;
114                 case Literal::STRING:
115                         throw Error("unhandled literal: string");
116                         break;
117                 case Literal::VECTOR:
118                         throw Error("unhandled literal: vector");
119                         break;
120                 case Literal::OBJECT:
121                         throw Error("unhandled literal: object");
122                         break;
123         }
124 }
125
126 Animation *Interpreter::GetAnimation(const Value &v) {
127         if (v.IsLiteral()) {
128                 if (v.GetLiteral().GetTypeName() == "ComplexAnimation") {
129                         ComplexAnimation *a(new ComplexAnimation);
130                         ReadComplexAnimation(*a, *v.GetLiteral().GetProperties());
131                         return a;
132                 } else {
133                         SimpleAnimation *a(new SimpleAnimation);
134                         ReadSimpleAnimation(*a, *v.GetLiteral().GetProperties());
135                         return a;
136                 }
137         } else if (animations.count(v.GetIdentifier())) {
138                 return animations[v.GetIdentifier()];
139         } else if (source.IsDefined(v.GetIdentifier())) {
140                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
141                 if (animations.count(v.GetIdentifier())) {
142                         return animations[v.GetIdentifier()];
143                 } else {
144                         throw Error("cannot use " + source.GetDefinition(v.GetIdentifier()).Identifier() + " " + v.GetIdentifier() + " as animation");
145                 }
146         } else {
147                 throw Error("use of undefined Animation " + v.GetIdentifier());
148         }
149 }
150
151 const vector<Value *> &Interpreter::GetValueArray(const Value &v) {
152         if (v.IsLiteral()) {
153                 return v.GetLiteral().GetValues();
154         } else {
155                 throw Error("identifier resolution not implemented for arrays of values");
156         }
157 }
158
159 const vector<PropertyList *> &Interpreter::GetPropertyListArray(const Value &v) {
160         if (v.IsLiteral()) {
161                 return v.GetLiteral().GetPropertyLists();
162         } else {
163                 throw Error("identifier resolution not implemented for arrays of property lists");
164         }
165 }
166
167 bool Interpreter::GetBoolean(const Value &v) {
168         if (v.IsLiteral()) {
169                 return v.GetLiteral().GetBoolean();
170         } else {
171                 throw Error("identifier resolution not implemented for booleans");
172         }
173 }
174
175 SDL_Surface *Interpreter::GetImage(const Value &v) {
176         const char *file(GetString(v));
177         return IMG_Load(file);
178 }
179
180 int Interpreter::GetNumber(const Value &v) {
181         if (v.IsLiteral()) {
182                 return v.GetLiteral().GetNumber();
183         } else if (numbers.count(v.GetIdentifier())) {
184                 return numbers[v.GetIdentifier()];
185         } else {
186                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
187                 if (numbers.count(v.GetIdentifier())) {
188                         return numbers[v.GetIdentifier()];
189                 } else {
190                         throw Error("use of undefined Number " + v.GetIdentifier());
191                 }
192         }
193 }
194
195 const PropertyList *Interpreter::GetPropertyList(const Value &v) {
196         if (v.IsLiteral()) {
197                 return v.GetLiteral().GetProperties();
198         } else {
199                 throw Error("identifier resolution not implemented for property lists");
200         }
201 }
202
203 Sprite *Interpreter::GetSprite(const Value &v) {
204         if (v.IsLiteral()) {
205                 Sprite *s(new Sprite);
206                 ReadSprite(*s, *v.GetLiteral().GetProperties());
207                 return s;
208         } else if (sprites.count(v.GetIdentifier())) {
209                 return sprites[v.GetIdentifier()];
210         } else {
211                 ReadDefinition(source.GetDefinition(v.GetIdentifier()));
212                 if (sprites.count(v.GetIdentifier())) {
213                         return sprites[v.GetIdentifier()];
214                 } else {
215                         throw Error("use of undefined Sprite " + v.GetIdentifier());
216                 }
217         }
218 }
219
220 const char *Interpreter::GetString(const Value &v) {
221         if (v.IsLiteral()) {
222                 return v.GetLiteral().GetString().c_str();
223         } else {
224                 throw Error("identifier resolution not implemented for strings");
225         }
226 }
227
228 Vector<int> Interpreter::GetVector(const Value &v) {
229         if (v.IsLiteral()) {
230                 return Vector<int>(v.GetLiteral().GetX(), v.GetLiteral().GetY());
231         } else {
232                 throw Error("identifier resolution not implemented for vectors");
233         }
234 }
235
236
237 void Interpreter::ReadObject(const Definition &dfn) {
238         if (dfn.TypeName() == "Hero") {
239                 Hero *h(new Hero);
240                 ReadHero(*h, *dfn.GetProperties());
241                 heroes[dfn.Identifier()] = h;
242         } else if (dfn.TypeName() == "Monster") {
243                 Monster *m(new Monster);
244                 ReadMonster(*m, *dfn.GetProperties());
245                 monsters[dfn.Identifier()] = m;
246         } else if (dfn.TypeName() == "Sprite") {
247                 Sprite *s(new Sprite);
248                 ReadSprite(*s, *dfn.GetProperties());
249                 sprites[dfn.Identifier()] = s;
250         } else {
251                 throw Error("unhandled object: " + dfn.TypeName());
252         }
253 }
254
255
256 void Interpreter::ReadComplexAnimation(ComplexAnimation &a, const PropertyList &props) {
257         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
258                 if (i->first == "sprite") {
259                         a.SetSprite(GetSprite(*i->second));
260                 } else if (i->first == "frametime") {
261                         a.SetFrameTime(GetNumber(*i->second));
262                 } else if (i->first == "repeat") {
263                         a.SetRepeat(GetBoolean(*i->second));
264                 } else if (i->first == "frames") {
265                         const vector<PropertyList *> &values(GetPropertyListArray(*i->second));
266                         for (vector<PropertyList *>::const_iterator i(values.begin()), end(values.end()); i != end; ++i) {
267                                 ComplexAnimation::FrameProp frame;
268                                 ReadComplexAnimationFrame(frame, **i);
269                                 a.AddFrame(frame);
270                         }
271                 } else {
272                         throw Error("unknown ComplexAnimation property: " + i->first);
273                 }
274         }
275 }
276
277 void Interpreter::ReadComplexAnimationFrame(ComplexAnimation::FrameProp &f, const PropertyList &props) {
278         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
279                 if (i->first == "column") {
280                         f.col = GetNumber(*i->second);
281                 } else if (i->first == "row") {
282                         f.row = GetNumber(*i->second);
283                 } else if (i->first == "disposition") {
284                         f.disposition = GetVector(*i->second);
285                 } else {
286                         throw Error("unknown ComplexAnimationFrame property: " + i->first);
287                 }
288         }
289 }
290
291 void Interpreter::ReadHero(Hero &h, const PropertyList &props) {
292         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
293                 if (i->first == "name") {
294                         h.SetName(GetString(*i->second));
295                 } else if (i->first == "sprite") {
296                         h.SetSprite(GetSprite(*i->second));
297                 } else if (i->first == "level") {
298                         h.SetLevel(GetNumber(*i->second));
299                 } else if (i->first == "maxHealth") {
300                         h.SetMaxHealth(GetNumber(*i->second));
301                 } else if (i->first == "health") {
302                         h.SetHealth(GetNumber(*i->second));
303                 } else if (i->first == "maxMana") {
304                         h.SetMaxMana(GetNumber(*i->second));
305                 } else if (i->first == "mana") {
306                         h.SetMana(GetNumber(*i->second));
307                 } else if (i->first == "ip") {
308                         h.SetIP(GetNumber(*i->second));
309                 } else if (i->first == "stats") {
310                         battle::Stats stats;
311                         ReadStats(stats, *GetPropertyList(*i->second));
312                         h.SetStats(stats);
313                 } else if (i->first == "attackAnimation") {
314                         h.SetAttackAnimation(GetAnimation(*i->second));
315                 } else if (i->first == "spellAnimation") {
316                         h.SetSpellAnimation(GetAnimation(*i->second));
317                 } else if (i->first == "meleeAnimation") {
318                         h.SetMeleeAnimation(GetAnimation(*i->second));
319                 } else {
320                         throw Error("unknown Hero property: " + i->first);
321                 }
322         }
323 }
324
325 void Interpreter::ReadMonster(Monster &m, const PropertyList &props) {
326         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
327                 if (i->first == "name") {
328                         m.SetName(GetString(*i->second));
329                 } else if (i->first == "sprite") {
330                         m.SetSprite(GetSprite(*i->second));
331                 } else if (i->first == "level") {
332                         m.SetLevel(GetNumber(*i->second));
333                 } else if (i->first == "maxHealth") {
334                         m.SetMaxHealth(GetNumber(*i->second));
335                 } else if (i->first == "health") {
336                         m.SetHealth(GetNumber(*i->second));
337                 } else if (i->first == "maxMana") {
338                         m.SetMaxMana(GetNumber(*i->second));
339                 } else if (i->first == "mana") {
340                         m.SetMana(GetNumber(*i->second));
341                 } else if (i->first == "stats") {
342                         battle::Stats stats;
343                         ReadStats(stats, *GetPropertyList(*i->second));
344                         m.SetStats(stats);
345                 } else if (i->first == "attackAnimation") {
346                         m.SetAttackAnimation(GetAnimation(*i->second));
347                 } else {
348                         throw Error("unknown Monster property: " + i->first);
349                 }
350         }
351 }
352
353 void Interpreter::ReadSimpleAnimation(SimpleAnimation &a, const PropertyList &props) {
354         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
355                 if (i->first == "sprite") {
356                         a.SetSprite(GetSprite(*i->second));
357                 } else if (i->first == "frametime") {
358                         a.SetFrameTime(GetNumber(*i->second));
359                 } else if (i->first == "repeat") {
360                         a.SetRepeat(GetBoolean(*i->second));
361                 } else if (i->first == "framecount") {
362                         a.SetNumFrames(GetNumber(*i->second));
363                 } else if (i->first == "col") {
364                         a.SetCol(GetNumber(*i->second));
365                 } else if (i->first == "row") {
366                         a.SetRow(GetNumber(*i->second));
367                 } else {
368                         throw Error("unknown SimpleAnimation property: " + i->first);
369                 }
370         }
371 }
372
373 void Interpreter::ReadSprite(Sprite &s, const PropertyList &props) {
374         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
375                 if (i->first == "image") {
376                         s.SetSurface(GetImage(*i->second));
377                 } else if (i->first == "size") {
378                         s.SetSize(GetVector(*i->second));
379                 } else if (i->first == "offset") {
380                         s.SetOffset(GetVector(*i->second));
381                 } else {
382                         throw Error("unknown Sprite property: " + i->first);
383                 }
384         }
385 }
386
387 void Interpreter::ReadStats(Stats &s, const PropertyList &props) {
388         for (PropertyList::ConstIterator i(props.Begin()), end(props.End()); i != end; ++i) {
389                 if (i->first == "atp") {
390                         s.SetAttack(GetNumber(*i->second));
391                 } else if (i->first == "dfp") {
392                         s.SetDefense(GetNumber(*i->second));
393                 } else if (i->first == "str") {
394                         s.SetStrength(GetNumber(*i->second));
395                 } else if (i->first == "agl") {
396                         s.SetAgility(GetNumber(*i->second));
397                 } else if (i->first == "int") {
398                         s.SetIntelligence(GetNumber(*i->second));
399                 } else if (i->first == "gut") {
400                         s.SetGut(GetNumber(*i->second));
401                 } else if (i->first == "mgr") {
402                         s.SetMagicResistance(GetNumber(*i->second));
403                 } else {
404                         throw Error("unknown Stats property: " + i->first);
405                 }
406         }
407 }
408
409 }