khanat-opennel-code/code/ryzom/server/src/ags_test/command_event_manager.h

230 lines
6.1 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/>.
#ifndef NL_COMMAND_EVENT_MANAGER_H
#define NL_COMMAND_EVENT_MANAGER_H
#include "nel/misc/types_nl.h"
#include "nel/misc/common.h"
#include "nel/misc/debug.h"
#include "nel/misc/command.h"
#include "nel/misc/eval_num_expr.h"
#include "nel/net/unified_network.h"
#include <map>
#include <vector>
#include <string>
/**
* A Manager that triggers events and is receptive to events
* \author Benjamin Legros
* \author Nevrax France
* \date 2001
*/
class CCommandEventManager
{
friend void cbProcessScriptEvent( NLNET::CMessage& msgin, const std::string &serviceName, uint16 serviceId );
public:
/// A type of variable, basically consisting in a name and a value (as a string)
typedef std::pair<std::string, std::string> TVar;
/// The variable environment of a script
class CEnvironment : public NLMISC::CEvalNumExpr
{
private:
/// The map type of vars
typedef std::map<std::string, std::string> TVarMap;
/// The map of vars itself
TVarMap _Map;
/// The empty string
std::string _Empty;
public:
CEnvironment() : _Empty("") {}
/// Clear the whole environment
void clear() { _Map.clear(); }
/// Checks if var exists
bool exists(const std::string &var) { return _Map.find(var) != _Map.end(); }
/// Get the value of a var
const std::string &get(const std::string &var) { TVarMap::iterator it=_Map.find(var); return (it!=_Map.end()) ? (*it).second : _Empty; }
/// Set the value of a var
const std::string &set(const std::string &var, const std::string &value)
{
std::pair<TVarMap::iterator, bool> res = _Map.insert(std::make_pair<std::string, std::string>(var, value));
if (!res.second)
(*(res.first)).second = value;
return (*(res.first)).second;
}
/// Erases a var
void erase(const std::string &var) { _Map.erase(var); }
/// Replaces text by value in string (variable must have the form $(variable) to be replaced by their value)
std::string replace(const std::string &text);
protected:
virtual NLMISC::CEvalNumExpr::TReturnState evalValue(const char *value, double &result)
{
TVarMap::iterator it;
if (*value == '?')
{
it = _Map.find(value+1);
if (it == _Map.end())
result = 0.0;
else
result = 1.0;
return NLMISC::CEvalNumExpr::NoError;
}
else
{
it = _Map.find(value);
if (it == _Map.end())
return NLMISC::CEvalNumExpr::UnkownValue;
result = atof((*it).second.c_str());
return NLMISC::CEvalNumExpr::NoError;
}
}
};
class CScript;
/// A script node
class CScriptNode
{
public:
enum EState
{
Ok,
Error,
Halt,
};
/// The line in the script for this node
uint Line;
/// Current running script
CScriptNode *CurrentRun;
/// The root script
CScript *Root;
public:
/// default constructor
CScriptNode() : Line(0), CurrentRun(NULL) {}
/// virtual destructor
virtual ~CScriptNode() {}
/// Execute the script node, returns the next node to be executed, or NULL if script finished
virtual EState execute(CEnvironment &env) = 0;
protected:
/// Execute current node (previous run returned halt)
EState goOnCurrentRun(CEnvironment &env)
{
if (!CurrentRun)
return Error;
EState state = CurrentRun->execute(env);
if (state == Ok)
CurrentRun = NULL;
return state;
}
/// Execute child
EState executeChild(CScriptNode* child, CEnvironment &env)
{
EState state = child->execute(env);
if (state == Halt || state == Error)
CurrentRun = child;
return state;
}
};
/// The script class that receives events, generates events, and triggers commands
class CScript
{
public:
/// The name of the script
std::string Name;
/// The script environment
CEnvironment Environment;
/// The script text
CScriptNode *Root;
/// Verbosity
bool Verbose;
/// Constructor.
CScript(const std::string &name) : Name(name), Verbose(false) {}
///
bool parse(const char *text);
/// Inits script before execution with no default parameters
void init() { init(std::vector<TVar>()); }
/// Inits script before execution, using default parameters
void init(const std::vector<TVar> &initVars)
{
uint i;
for (i=0; i<initVars.size(); ++i)
Environment.set(initVars[i].first, initVars[i].second);
}
/// Runs script till it is finished or it waits for an event
bool run();
};
private:
typedef std::map<std::string, CScript*> TScriptMap;
static TScriptMap _RunningScripts;
static std::string _Empty;
public:
static void init();
static void release();
static bool update();
static bool runScript(const std::string &scriptName, const std::string &scriptFile, bool verbose=false);
static bool stopScript(const std::string &scriptName);
static const std::string &getVarInScript(const std::string &scriptName, const std::string &varName);
static void setVarInScript(const std::string &scriptName, const std::string &varName, const std::string &value);
static void eraseVarInScript(const std::string &scriptName, const std::string &varName);
static void sendEvent(const std::string &var, const std::string &value);
static void setScriptVerbose(const std::string &scriptName, bool verbosity=true);
private:
/// Constructor
CCommandEventManager();
protected:
//
static void processEvent(const std::string &var, const std::string &value);
};
#endif // NL_COMMAND_EVENT_MANAGER_H
/* End of command_event_manager.h */