From: Daniel Karbach Date: Sat, 1 Dec 2012 09:51:05 +0000 (+0100) Subject: lousy implementation of "array of identifiers" type X-Git-Url: http://git.localhorst.tv/?p=l2e.git;a=commitdiff_plain;h=a67f7e662c85b2b8d46f26a3c6e018b2df6eb318 lousy implementation of "array of identifiers" type see bug #34 --- diff --git a/src/loader/Interpreter.cpp b/src/loader/Interpreter.cpp index 7dcb41e..e64110d 100644 --- a/src/loader/Interpreter.cpp +++ b/src/loader/Interpreter.cpp @@ -127,10 +127,9 @@ void Interpreter::ReadLiteral(const Definition &dfn) { void Interpreter::ReadLiteral(int typeId, int id, char *object, const Literal &literal) { switch (literal.GetType()) { case Literal::ARRAY_VALUES: - throw Error("named value arrays are not supported, sorry"); - break; case Literal::ARRAY_PROPS: - throw Error("named property list arrays are not supported, sorry"); + case Literal::ARRAY_IDENTS: + throw Error("named arrays are not supported, sorry"); break; case Literal::BOOLEAN: new (object) bool(literal.GetBoolean()); @@ -177,10 +176,9 @@ void *Interpreter::GetObject(int typeId, const Value &v) { int typeId(0), id(0); switch (v.GetLiteral().GetType()) { case Literal::ARRAY_VALUES: - throw Error("cannot copy value arrays, sorry"); - break; case Literal::ARRAY_PROPS: - throw Error("cannot copy property list arrays, sorry"); + case Literal::ARRAY_IDENTS: + throw Error("cannot copy arrays, sorry"); break; case Literal::BOOLEAN: { @@ -287,20 +285,35 @@ void Interpreter::ReadObject(int typeId, int id, char *object, const PropertyLis char *dest(object + fd.Offset()); if (fd.IsAggregate()) { int arraySize(i->second->GetLiteral().ArraySize()); - char *aggregate(alloc.Alloc(fieldType.Size() * arraySize)); - char *iter(aggregate); + char *aggregate; if (i->second->GetLiteral().GetType() == Literal::ARRAY_PROPS) { + aggregate = alloc.Alloc(fieldType.Size() * arraySize); + char *iter = aggregate; const vector &list(i->second->GetLiteral().GetPropertyLists()); for (vector::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) { fieldType.Construct(iter); ReadObject(fieldType.TypeId(), -1, iter, **j); } - } else { + } else if (i->second->GetLiteral().GetType() == Literal::ARRAY_VALUES) { + aggregate = alloc.Alloc(fieldType.Size() * arraySize); + char *iter = aggregate; const vector &list(i->second->GetLiteral().GetValues()); for (vector::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += fieldType.Size()) { fieldType.Construct(iter); ReadLiteral(fieldType.TypeId(), -1, iter, (*j)->GetLiteral()); } + } else { + aggregate = alloc.Alloc(sizeof(char *) * arraySize); + char *iter = aggregate; + const vector &list(i->second->GetLiteral().GetIdentifiers()); + for (vector::const_iterator j(list.begin()), end(list.end()); j != end; ++j, iter += sizeof(void *)) { + if (source.IsDefined(*j)) { + *reinterpret_cast(iter) + = GetObject(fd.TypeId(), *j); + } else { + Postpone(typeId, id, fd.Offset() + (iter - aggregate), *j, fd.TypeId(), false); + } + } } if (fd.IsReferenced()) { std::memcpy(dest, &aggregate, sizeof(char *)); diff --git a/src/loader/ParsedSource.cpp b/src/loader/ParsedSource.cpp index 042dd69..9059747 100644 --- a/src/loader/ParsedSource.cpp +++ b/src/loader/ParsedSource.cpp @@ -200,6 +200,17 @@ Literal::Literal(const string &typeName, const vector &pls) } +Literal::Literal(const string &typeName, const vector &ids) +: props(0) +, typeName(typeName) +, identifiers(ids) +, i1(0), i2(0) +, i3(0), i4(0) +, b(false) +, type(ARRAY_IDENTS) { + +} + Literal::Literal(bool b) : props(0) , typeName("Boolean") @@ -324,6 +335,14 @@ const vector &Literal::GetPropertyLists() const { } } +const vector &Literal::GetIdentifiers() const { + if (type == ARRAY_IDENTS) { + return identifiers; + } else { + throw runtime_error("tried to access identifiers of non-array literal"); + } +} + bool Literal::GetBoolean() const { if (type == BOOLEAN) { return b; @@ -535,6 +554,9 @@ ostream &operator <<(ostream &out, const loader::Literal &l) { case loader::Literal::ARRAY_PROPS: out << "array of property lists"; break; + case loader::Literal::ARRAY_IDENTS: + out << "array of identifiers"; + break; case loader::Literal::BOOLEAN: out << "boolean, " << (l.GetBoolean() ? "true" : "false"); break; diff --git a/src/loader/ParsedSource.h b/src/loader/ParsedSource.h index b0578a7..c843de1 100644 --- a/src/loader/ParsedSource.h +++ b/src/loader/ParsedSource.h @@ -51,6 +51,7 @@ public: enum Type { ARRAY_VALUES, ARRAY_PROPS, + ARRAY_IDENTS, BOOLEAN, COLOR, NUMBER, @@ -62,15 +63,27 @@ public: }; public: + /// array of values explicit Literal(const std::vector &); + /// array of objects Literal(const std::string &, const std::vector &); + /// array of identifiers + Literal(const std::string &, const std::vector &); + /// boolean explicit Literal(bool); + /// color Literal(int r, int g, int b, int a = 255); + /// number explicit Literal(int number); + /// path string Literal(const std::string &dir, const std::string &path); + /// string Literal(const std::string &); + /// vector Literal(int x, int y); + /// object Literal(const std::string &typeName, PropertyList *properties); + /// script explicit Literal(const std::vector &); ~Literal(); private: @@ -79,12 +92,14 @@ private: public: Type GetType() const { return type; } - bool IsArray() const { return GetType() == ARRAY_VALUES || GetType() == ARRAY_PROPS; } + bool IsArray() const { return GetType() == ARRAY_VALUES || GetType() == ARRAY_PROPS || GetType() == ARRAY_IDENTS; } bool IsObject() const { return GetType() == OBJECT; } - int ArraySize() const { return GetType() == ARRAY_VALUES ? GetValues().size() : GetPropertyLists().size(); } + int ArraySize() const { return GetType() == ARRAY_VALUES ? GetValues().size() + : (GetType() == ARRAY_PROPS ? GetPropertyLists().size() : GetIdentifiers().size()); } const std::vector &GetValues() const; const std::vector &GetPropertyLists() const; + const std::vector &GetIdentifiers() const; bool GetBoolean() const; int GetRed() const; int GetGreen() const; @@ -103,6 +118,7 @@ private: std::string typeName, str; std::vector values; std::vector propertyLists; + std::vector identifiers; std::vector script; int i1, i2, i3, i4; bool b; diff --git a/src/loader/Parser.cpp b/src/loader/Parser.cpp index cba4f31..3f5f344 100644 --- a/src/loader/Parser.cpp +++ b/src/loader/Parser.cpp @@ -259,17 +259,33 @@ Literal *Parser::ParseArray() { Token probe(GetToken()); if (probe.type == Token::TYPE_NAME) { - vector values; - while (t.type != Token::BRACKET_CLOSE) { - PropertyList *value(ParsePropertyList()); - values.push_back(value); + t = GetToken(); + tok.Putback(t); + if (t.type == Token::ANGLE_BRACKET_OPEN) { + vector values; + while (t.type != Token::BRACKET_CLOSE) { + PropertyList *value(ParsePropertyList()); + values.push_back(value); - t = GetToken(); - if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) { - throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]"); + t = GetToken(); + if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) { + throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]"); + } + } + return new Literal(probe.str, values); + } else { + vector values; + while (t.type != Token::BRACKET_CLOSE) { + string value(ParseIdentifier()); + values.push_back(value); + + t = GetToken(); + if (t.type != Token::BRACKET_CLOSE && t.type != Token::COMMA) { + throw Error(file, tok.Line(), string("unexpected token ") + TokenTypeToString(t.type) + ", expected , or ]"); + } } + return new Literal(probe.str, values); } - return new Literal(probe.str, values); } else { tok.Putback(probe); diff --git a/src/map/Entity.h b/src/map/Entity.h index a6c4201..d1746c7 100644 --- a/src/map/Entity.h +++ b/src/map/Entity.h @@ -110,9 +110,9 @@ public: /// Add monsters. This will cause the entity to be Hostile() and result in a /// battle scene with given monsters when touched. - void SetMonsters(battle::Monster *m, int num) { monsters = m; numMonsters = num; } - battle::Monster *MonstersBegin() { return monsters; } - battle::Monster *MonstersEnd() { return monsters + numMonsters; } + void SetMonsters(battle::Monster **m, int num) { monsters = m; numMonsters = num; } + battle::Monster **MonstersBegin() { return monsters; } + battle::Monster **MonstersEnd() { return monsters + numMonsters; } /// Get an entity that should follow in this one's steps or 0 if none. Entity *Follower() { return follower; } @@ -143,7 +143,7 @@ private: const graphics::Animation *animation; const graphics::Sprite *sprite; battle::PartyLayout *partyLayout; - battle::Monster *monsters; + battle::Monster **monsters; int numMonsters; graphics::AnimationRunner runner; geometry::Vector spriteOffset; diff --git a/src/map/MapState.cpp b/src/map/MapState.cpp index 7b0905d..d678dab 100644 --- a/src/map/MapState.cpp +++ b/src/map/MapState.cpp @@ -296,8 +296,8 @@ bool MapState::CheckMonster() { battleState->AddHero(*game->state->party[i]); } } - for (battle::Monster *monster((*e)->MonstersBegin()); monster != (*e)->MonstersEnd(); ++monster) { - battleState->AddMonster(*monster); + for (battle::Monster **monster((*e)->MonstersBegin()); monster != (*e)->MonstersEnd(); ++monster) { + battleState->AddMonster(**monster); } ColorFade *fadeIn(new ColorFade(this, 0, 500, true)); diff --git a/test-data/maps.l2s b/test-data/maps.l2s index e5ffbcd..b70aa3c 100644 --- a/test-data/maps.l2s +++ b/test-data/maps.l2s @@ -185,8 +185,11 @@ export Map map1 { repeat: true }, position: <2, 1>, - partyLayout: monstersLayout - // TODO: monsters + partyLayout: monstersLayout, + monsters: [ Monster + lizard, + lizard + ] }, { sprite: Sprite {