548 lines
15 KiB
C
548 lines
15 KiB
C
|
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as
|
||
|
// published by the Free Software Foundation, either version 3 of the
|
||
|
// License, or (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
#include "nel/misc/types_nl.h"
|
||
|
#include "nel/misc/debug.h"
|
||
|
#include "nel/misc/string_common.h"
|
||
|
#include "nel/misc/path.h"
|
||
|
#include "nel/misc/sstring.h"
|
||
|
#include "nel/misc/smart_ptr.h"
|
||
|
#include "nel/misc/factory.h"
|
||
|
#include "nel/ligo/primitive.h"
|
||
|
#include "nel/ligo/primitive_utils.h"
|
||
|
#include "nel/ligo/ligo_config.h"
|
||
|
#include "../../../common/src/game_share/string_manager_sender.h"
|
||
|
#include "nel/misc/string_conversion.h"
|
||
|
#include <string>
|
||
|
#include <numeric>
|
||
|
|
||
|
class CMissionData;
|
||
|
class IStep;
|
||
|
|
||
|
const std::string NL("\n\r");
|
||
|
|
||
|
/// Exception thows when the parser meet somethink invalid.
|
||
|
struct EParseException
|
||
|
{
|
||
|
EParseException(NLLIGO::IPrimitive *prim, const char *why)
|
||
|
: Primitive(prim),
|
||
|
Why(why)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
NLLIGO::IPrimitive *Primitive;
|
||
|
std::string Why;
|
||
|
};
|
||
|
|
||
|
|
||
|
// utility to untag a variable (tag are the '$' added before and after the var name)
|
||
|
inline void untagVar(std::string &var)
|
||
|
{
|
||
|
if (!var.empty())
|
||
|
{
|
||
|
if (var[0] != '$')
|
||
|
var = "";
|
||
|
else
|
||
|
{
|
||
|
var = var.substr(1);
|
||
|
if (var[var.size()-1] != '$')
|
||
|
var = "";
|
||
|
else
|
||
|
var = var.substr(0, var.size()-1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// utility to 'tabulate' the lines in a string
|
||
|
void tabulateLine(std::string &text, uint nbTabs);
|
||
|
|
||
|
|
||
|
/* Interface class for variables types*/
|
||
|
class IVar
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
typedef NLLIGO::IPrimitive * TCtorParam;
|
||
|
|
||
|
enum TVarType
|
||
|
{
|
||
|
vt_integer,
|
||
|
vt_npc,
|
||
|
vt_item,
|
||
|
vt_place,
|
||
|
vt_text
|
||
|
};
|
||
|
|
||
|
IVar(TVarType type, NLLIGO::IPrimitive *prim)
|
||
|
{
|
||
|
_VarType = type;
|
||
|
_VarName = getPrimProperty(prim, "var_name");
|
||
|
}
|
||
|
|
||
|
// force virtual destructor
|
||
|
virtual ~IVar() {}
|
||
|
|
||
|
/** Return the variable type. Should return a string to
|
||
|
* limit coupling with implementation ?
|
||
|
*/
|
||
|
TVarType getVarType() const
|
||
|
{
|
||
|
return _VarType;
|
||
|
}
|
||
|
|
||
|
/** Return the type of the variable as defined in the string manager.
|
||
|
* Can return NB_ENTITY_TYPES for compiler variable that don't match
|
||
|
* to a type in the string manager.
|
||
|
*/
|
||
|
virtual STRING_MANAGER::TParamType getStringManagerType()=0;
|
||
|
|
||
|
/// Return the name of the variable.
|
||
|
const std::string getVarName() const
|
||
|
{
|
||
|
return _VarName;
|
||
|
}
|
||
|
|
||
|
/// Evaluate the content of the variable with an optional sub part.
|
||
|
virtual std::string evalVar(const std::string &subPart) = 0;
|
||
|
|
||
|
/** Factory method to create new variable. Caller become responsible
|
||
|
* for deleting the allocated variable.
|
||
|
*/
|
||
|
static IVar *createVar(CMissionData &md, NLLIGO::IPrimitive *prim);
|
||
|
|
||
|
/// Generate variable declaration in mission script
|
||
|
virtual std::string genDecl(CMissionData &md) = 0;
|
||
|
|
||
|
/// Generate the phrase
|
||
|
virtual std::string genPhrase()
|
||
|
{
|
||
|
static std::string emptyString;
|
||
|
return emptyString;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
/// Helper function to read a primitive property.
|
||
|
std::string getPrimProperty(NLLIGO::IPrimitive *prim, const std::string &propName)
|
||
|
{
|
||
|
std::string *s;
|
||
|
if (prim->getPropertyByName(propName.c_str(), s))
|
||
|
return *s;
|
||
|
else
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
/// Helper function to read a primitive array property
|
||
|
std::vector<std::string> getPrimPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propName)
|
||
|
{
|
||
|
std::vector<std::string> *sv;
|
||
|
if (prim->getPropertyByName(propName.c_str(), sv))
|
||
|
return *sv;
|
||
|
else
|
||
|
return std::vector<std::string>();
|
||
|
}
|
||
|
protected:
|
||
|
/// Variable type.
|
||
|
TVarType _VarType;
|
||
|
/// Variable name.
|
||
|
std::string _VarName;
|
||
|
};
|
||
|
|
||
|
class CMissionData;
|
||
|
|
||
|
|
||
|
/** Class for text management.
|
||
|
* Handle different expression of text such
|
||
|
* phrase identifier, reference to text variable
|
||
|
* or literal string.
|
||
|
* The class also handle the parameter list for
|
||
|
* the phrase.
|
||
|
*/
|
||
|
class CPhrase
|
||
|
{
|
||
|
public:
|
||
|
/// Structure to store phrase parameters infos.
|
||
|
struct TParamInfo
|
||
|
{
|
||
|
/// The name of the parameter
|
||
|
std::string ParamName;
|
||
|
/// Compiler param
|
||
|
std::string CompilerParam;
|
||
|
/// The type of the parameters (as defined in the string manager).
|
||
|
STRING_MANAGER::TParamType ParamType;
|
||
|
|
||
|
TParamInfo()
|
||
|
: ParamType(STRING_MANAGER::NB_PARAM_TYPES)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
TParamInfo(const std::string &name, STRING_MANAGER::TParamType type, const std::string &compilerParam = "")
|
||
|
: ParamName(name),
|
||
|
ParamType(type),
|
||
|
CompilerParam(compilerParam)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
typedef std::vector<std::vector<TParamInfo> > TPredefParams;
|
||
|
|
||
|
private:
|
||
|
|
||
|
/** Number of variant for this phrase.
|
||
|
* Zero denote that there is no variant, thus no need to add
|
||
|
* a postfix number after the phrase identifier for literal
|
||
|
* generated phrase.
|
||
|
*/
|
||
|
uint32 _NumEntry;
|
||
|
|
||
|
/** The phrase id. This is the identifier that must be use with the
|
||
|
* string manager.
|
||
|
*/
|
||
|
std::string _PhraseId;
|
||
|
/** String literal value. When the user fill a quoted string, then
|
||
|
* this property receive the string value of the quoted string.
|
||
|
*/
|
||
|
std::vector<std::string> _PhraseLiterals;
|
||
|
/** Suffixe for literal string identifier */
|
||
|
std::string _Suffixe;
|
||
|
/// The list of default parameters.
|
||
|
TPredefParams _DefaultParams;
|
||
|
/// The list of additional parameters.
|
||
|
std::vector<TParamInfo> _AdditionalParams;
|
||
|
public:
|
||
|
|
||
|
|
||
|
/// init the phrase
|
||
|
void initPhrase (CMissionData &md,
|
||
|
NLLIGO::IPrimitive *prim,
|
||
|
const std::vector<std::string> &texts,
|
||
|
uint32 numEntry = 0,
|
||
|
const TPredefParams &predefParams = TPredefParams());
|
||
|
|
||
|
/// generate the common string script for any script instruction.
|
||
|
std::string genScript(CMissionData &md);
|
||
|
|
||
|
/** generate the phrase file content. Return empty string
|
||
|
* if the phrase is not a literal.
|
||
|
*/
|
||
|
std::string genPhrase();
|
||
|
|
||
|
/// Test if the phrase is empty
|
||
|
bool isEmpty();
|
||
|
|
||
|
/// Test if the phrase contains some additionnal parameters
|
||
|
bool asAdditionnalParams();
|
||
|
};
|
||
|
|
||
|
|
||
|
/* Class for jumps */
|
||
|
struct TJumpInfo
|
||
|
{
|
||
|
std::string StepName;
|
||
|
std::string JumpName;
|
||
|
bool Discardable;
|
||
|
|
||
|
TJumpInfo(const std::string &stepName, const std::string &jumpName = std::string(), bool discardable = true)
|
||
|
: StepName(stepName),
|
||
|
JumpName(jumpName),
|
||
|
Discardable(discardable)
|
||
|
{}
|
||
|
|
||
|
bool operator <(const TJumpInfo &other) const
|
||
|
{
|
||
|
return StepName < other.StepName;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/* Class for mission information storing */
|
||
|
class CMissionData : public NLMISC::CRefCount
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
CMissionData();
|
||
|
~CMissionData();
|
||
|
|
||
|
|
||
|
// void setAlias(const std::string &alias) { _Alias = alias; }
|
||
|
// const std::string &getAlias() { return _Alias; }
|
||
|
|
||
|
void setMissionName(const std::string &missionName);
|
||
|
const std::string &getMissionName();
|
||
|
|
||
|
const std::string &getGiverPrimitive() { return _GiverPrimitive; }
|
||
|
void setGiverPrimitive(const std::string &giverPrimitive) { _GiverPrimitive = giverPrimitive; }
|
||
|
|
||
|
const std::string &getGiverName() { return _MissionGiver; }
|
||
|
void setGiverName(const std::string &giverName) { _MissionGiver = giverName; }
|
||
|
|
||
|
bool addVariable(NLLIGO::IPrimitive *prim, IVar *var);
|
||
|
|
||
|
IVar *getVariable(const std::string &varName);
|
||
|
|
||
|
bool addStep(IStep *step);
|
||
|
void addStepName(const std::string &name, IStep *step) { _StepsByNames[name] = step; }
|
||
|
|
||
|
IStep *getNextStep(IStep *current);
|
||
|
|
||
|
IStep *getStepByName(const std::string &stepName);
|
||
|
|
||
|
std::string generateMissionScript(const std::string &primFileName);
|
||
|
|
||
|
std::string generatePhraseFile();
|
||
|
|
||
|
std::string generateDotScript();
|
||
|
|
||
|
void parseMissionHeader(NLLIGO::IPrimitive *prim);
|
||
|
void initHeaderPhrase(NLLIGO::IPrimitive *prim);
|
||
|
void parsePrerequisites(NLLIGO::IPrimitive *prim);
|
||
|
|
||
|
std::string replaceVar(NLLIGO::IPrimitive *prim, const std::string &str);
|
||
|
std::vector<std::string> replaceVar(NLLIGO::IPrimitive *prim, const std::vector<std::string> &strs);
|
||
|
|
||
|
std::string getProperty(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail);
|
||
|
std::vector<std::string> getPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail);
|
||
|
|
||
|
|
||
|
bool isThereAJumpTo(const std::string &stepName);
|
||
|
|
||
|
bool isGuildMission() const
|
||
|
{
|
||
|
return _Guild;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
std::string genPreRequisites();
|
||
|
|
||
|
// forbidden copy constructor !
|
||
|
CMissionData(const CMissionData &other)
|
||
|
{
|
||
|
nlstop;
|
||
|
}
|
||
|
|
||
|
// std::string _Alias;
|
||
|
std::string _MissionName;
|
||
|
std::string _MissionGiver;
|
||
|
std::string _GiverPrimitive;
|
||
|
bool _MonoInstance;
|
||
|
bool _RunOnce;
|
||
|
bool _Replayable;
|
||
|
bool _Solo;
|
||
|
bool _Guild;
|
||
|
bool _NotInJournal;
|
||
|
bool _AutoRemoveFromJournal; // When mission ends (fail or success) automatically remove it from the journal
|
||
|
std::string _MissionCategory;
|
||
|
uint32 _PlayerReplayTimer;
|
||
|
uint32 _GlobalReplayTimer;
|
||
|
bool _NotProposed;
|
||
|
bool _NonAbandonnable;
|
||
|
bool _NeedValidation;
|
||
|
bool _FailIfInventoryIsFull;
|
||
|
std::string _MissionIcon;
|
||
|
|
||
|
std::vector<std::string> _MissionTitleRaw;
|
||
|
CPhrase _MissionTitle;
|
||
|
std::vector<std::string> _MissionDescriptionRaw;
|
||
|
CPhrase _MissionDescription;
|
||
|
|
||
|
bool _MissionAuto;
|
||
|
std::vector<std::string> _MissionAutoMenuRaw;
|
||
|
CPhrase _MissionAutoMenu;
|
||
|
|
||
|
////// Pre requisites /////////
|
||
|
struct TReqSkill
|
||
|
{
|
||
|
std::string Skill;
|
||
|
std::string MinLevel;
|
||
|
std::string MaxLevel;
|
||
|
};
|
||
|
|
||
|
struct TReqFame
|
||
|
{
|
||
|
std::string Faction;
|
||
|
std::string Fame;
|
||
|
};
|
||
|
std::vector<TReqSkill> _ReqSkills;
|
||
|
std::vector<std::string> _ReqMissionDone;
|
||
|
std::vector<std::string> _ReqMissionNotDone;
|
||
|
std::vector<std::string> _ReqMissionRunning;
|
||
|
std::vector<std::string> _ReqMissionNotRunning;
|
||
|
std::vector<std::string> _ReqWearItem;
|
||
|
std::vector<std::string> _ReqOwnItem;
|
||
|
std::string _ReqTitle;
|
||
|
std::vector<TReqFame> _ReqFames;
|
||
|
bool _ReqGuild;
|
||
|
std::string _ReqGrade;
|
||
|
std::string _ReqTeamSize;
|
||
|
std::vector<std::string> _ReqBrick;
|
||
|
std::string _ReqSeason;
|
||
|
// bool _ReqEncycloTasksDone;
|
||
|
std::string _ReqEncyclo;
|
||
|
std::string _ReqEncycloNeg;
|
||
|
std::string _ReqEventFaction;
|
||
|
|
||
|
/// The list of parent missions
|
||
|
std::set<std::string> _ParentMissions;
|
||
|
/// The list of variable by name
|
||
|
std::map<std::string, IVar*> _Variables;
|
||
|
/// The list of variable in primitive order
|
||
|
std::vector<IVar*> _VariablesOrder;
|
||
|
/// the list of step in execution order
|
||
|
std::vector<IStep*> _Steps;
|
||
|
/// The list of step sorted by step name
|
||
|
std::map<std::string, IStep *> _StepsByNames;
|
||
|
|
||
|
std::set<TJumpInfo> _JumpPoints;
|
||
|
|
||
|
};
|
||
|
|
||
|
typedef NLMISC::CSmartPtr<CMissionData> TMissionDataPtr;
|
||
|
|
||
|
/** This class manage the compilation of missions contained under a
|
||
|
* primitive file node.
|
||
|
*/
|
||
|
class CMissionCompiler
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/** Generate the dot language script for the missions under the specified node.
|
||
|
* This method is primarily used for world editor mission display.
|
||
|
*/
|
||
|
// std::vector<std::string> generateDotScript(NLLIGO::NLLIGO::IPrimitive *rootPrim);
|
||
|
bool generateDotScript(NLLIGO::IPrimitive *missionPrim, std::string &dotScript, std::string &log);
|
||
|
|
||
|
/** compile one mission. The primitive node must be
|
||
|
* a mission tree root node.
|
||
|
* fileName must receive the primitive file name. It is used
|
||
|
*/
|
||
|
bool compileMission(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName);
|
||
|
|
||
|
/** Compile all the missions found under the given primitive node.
|
||
|
* The primitive tree is searched recursively ti find all the
|
||
|
* mission tree nodes.
|
||
|
* All the compiled missions are stored internaly in precompiled form.
|
||
|
*/
|
||
|
bool compileMissions(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName);
|
||
|
|
||
|
/** Install the generated script into the destination primitive files */
|
||
|
bool installCompiledMission(NLLIGO::CLigoConfig &ligoConfig, const std::string &primFileName);
|
||
|
|
||
|
/// Publish the modified to the path parameter
|
||
|
bool publishFiles(const std::string &serverPathPrim, const std::string &serverPathText, const std::string &localPathText);
|
||
|
|
||
|
/// Search for text in the file : add it if it's not in
|
||
|
bool includeText(const std::string filename, const std::string text);
|
||
|
|
||
|
/// Parse the pre requisite node of a mission.
|
||
|
bool parsePreRequisite(CMissionData &md, NLLIGO::IPrimitive *preReq);
|
||
|
|
||
|
/// Parse the steps of a missions.
|
||
|
bool parseSteps(CMissionData &md, NLLIGO::IPrimitive *steps, IStep *parent=NULL);
|
||
|
bool parseOneStep(CMissionData &md, NLLIGO::IPrimitive *stepToParse, IStep *parent, bool bEndOfBranch);
|
||
|
|
||
|
/// Helper to retrive a property in a primitive node.
|
||
|
std::string getProp(NLLIGO::IPrimitive *prim, const std::string &propName);
|
||
|
/// Helper to retreive the class name of a primitive node.
|
||
|
std::string getClass(NLLIGO::IPrimitive *prim);
|
||
|
/// Parse the variable of a missions.
|
||
|
bool parseVariables(CMissionData &md, NLLIGO::IPrimitive *variables);
|
||
|
|
||
|
|
||
|
/// Get full paths of files to publish
|
||
|
uint getFileToPublishCount() { return (uint)_FilesToPublish.size(); }
|
||
|
std::string getFileToPublish(uint index) { nlassert(index < _FilesToPublish.size()); return _FilesToPublish[index]; }
|
||
|
|
||
|
|
||
|
std::vector <TMissionDataPtr> &getMissions()
|
||
|
{
|
||
|
return _CompiledMission;
|
||
|
}
|
||
|
uint getMissionsCount()
|
||
|
{
|
||
|
return (uint)_CompiledMission.size();
|
||
|
}
|
||
|
TMissionDataPtr getMission(uint index)
|
||
|
{
|
||
|
nlassert(index < _CompiledMission.size());
|
||
|
return _CompiledMission[index];
|
||
|
}
|
||
|
|
||
|
|
||
|
private:
|
||
|
|
||
|
/// Storage for loaded primitive
|
||
|
struct TLoadedPrimitive
|
||
|
{
|
||
|
NLLIGO::CPrimitives *PrimDoc;
|
||
|
std::string FullFileName;
|
||
|
|
||
|
TLoadedPrimitive()
|
||
|
: PrimDoc(NULL)
|
||
|
{}
|
||
|
|
||
|
TLoadedPrimitive(NLLIGO::CPrimitives *primDoc, const std::string &fullFileName)
|
||
|
: PrimDoc(primDoc),
|
||
|
FullFileName(fullFileName)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// Storage for precompiled missions.
|
||
|
std::vector <TMissionDataPtr> _CompiledMission;
|
||
|
|
||
|
/// Storage for files to publish
|
||
|
std::vector<std::string> _FilesToPublish;
|
||
|
};
|
||
|
|
||
|
|
||
|
// Class to easily handle var and var name pair
|
||
|
struct TCompilerVarName
|
||
|
{
|
||
|
typedef std::vector <std::vector<struct TCompilerVarName> > TPredefParams;
|
||
|
// Default parameter name
|
||
|
std::string _DefaultName;
|
||
|
// Type of script parameter
|
||
|
STRING_MANAGER::TParamType _ParamType;
|
||
|
// the name of the compiler var, like 'the_creature' in $the_creature$ = chab1
|
||
|
std::string _VarName;
|
||
|
// the value of the compiler var line 'chab1' in $the_creature$ = chab1
|
||
|
std::string _VarValue;
|
||
|
|
||
|
void init(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string propName);
|
||
|
|
||
|
void initWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string &text);
|
||
|
|
||
|
CPhrase::TParamInfo getParamInfo() const;
|
||
|
|
||
|
bool empty() const;
|
||
|
|
||
|
operator const std::string () const;
|
||
|
|
||
|
operator CPhrase::TParamInfo() const;
|
||
|
|
||
|
//static void getPhrasePredef(const TCompilerVarName::TPredefParams& compilerParams, CPhrase::TPredefParams& params);
|
||
|
|
||
|
static std::vector<TCompilerVarName> getPropertyArrayWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName);
|
||
|
static std::vector<TCompilerVarName> getPropertyArrayWithTextStaticDefaultName(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName);
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
std::string operator+(const TCompilerVarName& left, const std::string & right);
|
||
|
std::string operator+(const std::string & left, const TCompilerVarName& right);
|
||
|
|
||
|
|