1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 21:09:41 +00:00

added local script compiling

This commit is contained in:
Marc Zinnschlag 2010-07-02 17:21:27 +02:00
parent 2064c43d89
commit 076b01559f
9 changed files with 187 additions and 39 deletions

View file

@ -41,7 +41,9 @@ set(GAMESCRIPT
apps/openmw/mwscript/scriptmanager.cpp) apps/openmw/mwscript/scriptmanager.cpp)
set(GAMESCRIPT_HEADER set(GAMESCRIPT_HEADER
apps/openmw/mwscript/locals.hpp apps/openmw/mwscript/locals.hpp
apps/openmw/mwscript/scriptmanager.hpp) apps/openmw/mwscript/scriptmanager.hpp
apps/openmw/mwscript/compilercontext.hpp
apps/openmw/mwscript/compilercontextscript.hpp)
source_group(apps\\openmw\\mwscript FILES ${GAMESCRIPT} ${GAMESCRIPT_HEADER}) source_group(apps\\openmw\\mwscript FILES ${GAMESCRIPT} ${GAMESCRIPT_HEADER})
set(APPS ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT}) set(APPS ${GAME} ${GAMEREND} ${GAMEINPUT} ${GAMESCRIPT})

View file

@ -9,6 +9,7 @@
#include "mwinput/inputmanager.hpp" #include "mwinput/inputmanager.hpp"
#include "mwscript/scriptmanager.hpp" #include "mwscript/scriptmanager.hpp"
#include "mwscript/compilercontextscript.hpp"
#include "world.hpp" #include "world.hpp"
@ -30,12 +31,13 @@ void OMW::Engine::executeLocalScripts()
for (World::ScriptList::const_iterator iter (mWorld->getLocalScripts().begin()); for (World::ScriptList::const_iterator iter (mWorld->getLocalScripts().begin());
iter!=mWorld->getLocalScripts().end(); ++iter) iter!=mWorld->getLocalScripts().end(); ++iter)
{ {
mScriptManager->run (iter->first); mScriptManager->run (iter->first, *iter->second);
} }
} }
OMW::Engine::Engine() : mWorld(NULL), mDebug (false), mScriptManager (0) OMW::Engine::Engine()
: mWorld(NULL), mDebug (false), mScriptManager (0), mScriptContext (0)
{ {
mspCommandServer.reset( mspCommandServer.reset(
new OMW::CommandServer::Server(&mCommandQueue, kCommandServerPort)); new OMW::CommandServer::Server(&mCommandQueue, kCommandServerPort));
@ -46,6 +48,7 @@ OMW::Engine::~Engine()
// mspCommandServer->stop(); // mspCommandServer->stop();
delete mWorld; delete mWorld;
delete mScriptManager; delete mScriptManager;
delete mScriptContext;
} }
// Load all BSA files in data directory. // Load all BSA files in data directory.
@ -159,7 +162,10 @@ void OMW::Engine::go()
// Create the world // Create the world
mWorld = new World (mOgre, mDataDir, mMaster, mCellName); mWorld = new World (mOgre, mDataDir, mMaster, mCellName);
mScriptManager = new MWScript::ScriptManager (mWorld->getStore(), mVerboseScripts); mScriptContext = new MWScript::CompilerContextScript;
mScriptManager = new MWScript::ScriptManager (mWorld->getStore(), mVerboseScripts,
*mScriptContext);
executeLocalScripts(); // TODO move into a framelistener executeLocalScripts(); // TODO move into a framelistener

View file

@ -12,6 +12,11 @@
#include "mwrender/mwscene.hpp" #include "mwrender/mwscene.hpp"
namespace Compiler
{
class Context;
}
namespace MWScript namespace MWScript
{ {
class ScriptManager; class ScriptManager;
@ -39,6 +44,7 @@ namespace OMW
std::auto_ptr<OMW::CommandServer::Server> mspCommandServer; std::auto_ptr<OMW::CommandServer::Server> mspCommandServer;
MWScript::ScriptManager *mScriptManager; MWScript::ScriptManager *mScriptManager;
Compiler::Context *mScriptContext;
// not implemented // not implemented
Engine (const Engine&); Engine (const Engine&);

View file

@ -0,0 +1,15 @@
#ifndef GAME_SCRIPT_COMPILERCONTEXT_H
#define GAME_SCRIPT_COMPILERCONTEXT_H
#include <components/compiler/context.hpp>
namespace MWScript
{
class CompilerContext : public Compiler::Context
{
};
}
#endif

View file

@ -0,0 +1,22 @@
#ifndef GAME_SCRIPT_COMPILERCONTEXTSCRIPT_H
#define GAME_SCRIPT_COMPILERCONTEXTSCRIPT_H
#include "compilercontext.hpp"
namespace MWScript
{
/// Context for local scripts, global scripts and targetted scripts
class CompilerContextScript : public CompilerContext
{
public:
// Is the compiler allowed to declare local variables?
virtual bool canDeclareLocals() const
{
return true;
}
};
}
#endif

View file

@ -1,18 +1,97 @@
#include "scriptmanager.hpp" #include "scriptmanager.hpp"
#include <components/compiler/scanner.hpp>
#include <cassert>
#include <iostream> #include <iostream>
#include <sstream>
#include <exception>
#include <components/esm/loadscpt.hpp>
#include <components/esm_store/store.hpp>
namespace MWScript namespace MWScript
{ {
ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose) ScriptManager::ScriptManager (const ESMS::ESMStore& store, bool verbose,
: mStore (store), mVerbose (verbose) Compiler::Context& compilerContext)
: mErrorHandler (std::cerr), mStore (store), mVerbose (verbose),
mCompilerContext (compilerContext), mParser (mErrorHandler, mCompilerContext)
{} {}
void ScriptManager::run (const std::string& name/*, Compiler::Context& compilerContext, bool ScriptManager::compile (const std::string& name)
Interpreter::Context& interpreterContext, Locals& locals*/)
{ {
std::cout << "script request: " << name << std::endl; mParser.reset();
mErrorHandler.reset();
bool Success = true;
if (const ESM::Script *script = mStore.scripts.find (name))
{
if (mVerbose)
std::cout << "compiling script: " << name << std::endl;
try
{
std::istringstream input (script->scriptText);
Compiler::Scanner scanner (mErrorHandler, input);
scanner.scan (mParser);
if (!mErrorHandler.isGood())
Success = false;
}
catch (const std::exception& error)
{
Success = false;
}
if (!Success && mVerbose)
{
std::cerr
<< "compiling failed: " << name << std::endl
<< script->scriptText
<< std::endl << std::endl;
}
if (Success)
{
std::vector<Interpreter::Type_Code> code;
mParser.getCode (code);
mScripts.insert (std::make_pair (name, code));
// TODO sanity check on generated locals
return true;
}
}
return false;
}
void ScriptManager::run (const std::string& name/*,
Interpreter::Context& interpreterContext*/, Locals& locals)
{
// compile script
std::map<std::string, std::vector<Interpreter::Type_Code> >::iterator iter =
mScripts.find (name);
if (iter==mScripts.end())
{
if (!compile (name))
{
// failed -> ignore script from now on.
std::vector<Interpreter::Type_Code> empty;
mScripts.insert (std::make_pair (name, empty));
return;
}
iter = mScripts.find (name);
assert (iter!=mScripts.end());
}
// execute script
} }
} }

View file

@ -5,6 +5,9 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <components/compiler/streamerrorhandler.hpp>
#include <components/compiler/fileparser.hpp>
#include <components/interpreter/types.hpp> #include <components/interpreter/types.hpp>
namespace ESMS namespace ESMS
@ -28,20 +31,25 @@ namespace MWScript
class ScriptManager class ScriptManager
{ {
Compiler::StreamErrorHandler mErrorHandler;
const ESMS::ESMStore& mStore; const ESMS::ESMStore& mStore;
bool mVerbose; bool mVerbose;
Compiler::Context& mCompilerContext;
Compiler::FileParser mParser;
std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts; std::map<std::string, std::vector<Interpreter::Type_Code> > mScripts;
bool compile (const std::string& name);
public: public:
ScriptManager (const ESMS::ESMStore& store, bool verbose); ScriptManager (const ESMS::ESMStore& store, bool verbose,
Compiler::Context& compilerContext);
void run (const std::string& name/*, Compiler::Context& compilerContext, void run (const std::string& name/*,
Interpreter::Context& interpreterContext, Locals& locals*/); Interpreter::Context& interpreterContext*/, Locals& locals);
}; };
}; };
#endif #endif

View file

@ -19,17 +19,24 @@ namespace OMW
MWScript::Locals mLocals; // if we find the overhead of heaving a locals MWScript::Locals mLocals; // if we find the overhead of heaving a locals
// object in the refdata of refs without a script, // object in the refdata of refs without a script,
// we can make this a pointer later. // we can make this a pointer later.
bool mHasLocals;
public: public:
RefData() : mHasLocals (false) {}
std::string getHandle() std::string getHandle()
{ {
return mHandle; return mHandle;
} }
void setLocals (const ESM::Script& script) void setLocals (const ESM::Script& script)
{
if (!mHasLocals)
{ {
mLocals.configure (script); mLocals.configure (script);
mHasLocals = true;
}
} }
void setHandle (const std::string& handle) void setHandle (const std::string& handle)

View file

@ -10,20 +10,23 @@
namespace namespace
{ {
template<typename T> template<typename T>
void listCellScripts (ESMS::CellRefList<T, OMW::RefData>& cellRefList, void listCellScripts (const ESMS::ESMStore& store,
OMW::World::ScriptList& scriptList) ESMS::CellRefList<T, OMW::RefData>& cellRefList, OMW::World::ScriptList& scriptList)
{ {
for (typename ESMS::CellRefList<T, OMW::RefData>::List::iterator iter ( for (typename ESMS::CellRefList<T, OMW::RefData>::List::iterator iter (
cellRefList.list.begin()); cellRefList.list.begin());
iter!=cellRefList.list.end(); ++iter) iter!=cellRefList.list.end(); ++iter)
{ {
if (!iter->base->script.empty()) if (!iter->base->script.empty())
{
if (const ESM::Script *script = store.scripts.find (iter->base->script))
{
iter->mData.setLocals (*script);
scriptList.push_back ( scriptList.push_back (
std::make_pair (iter->base->script, static_cast<MWScript::Locals *> (0))); std::make_pair (iter->base->script, &iter->mData.getLocals()));
}
// TODO local variables }
} }
} }
} }
@ -32,23 +35,23 @@ namespace OMW
{ {
void World::insertInteriorScripts (ESMS::CellStore<OMW::RefData>& cell) void World::insertInteriorScripts (ESMS::CellStore<OMW::RefData>& cell)
{ {
listCellScripts (cell.activators, mLocalScripts); listCellScripts (mStore, cell.activators, mLocalScripts);
listCellScripts (cell.potions, mLocalScripts); listCellScripts (mStore, cell.potions, mLocalScripts);
listCellScripts (cell.appas, mLocalScripts); listCellScripts (mStore, cell.appas, mLocalScripts);
listCellScripts (cell.armors, mLocalScripts); listCellScripts (mStore, cell.armors, mLocalScripts);
listCellScripts (cell.books, mLocalScripts); listCellScripts (mStore, cell.books, mLocalScripts);
listCellScripts (cell.clothes, mLocalScripts); listCellScripts (mStore, cell.clothes, mLocalScripts);
listCellScripts (cell.containers, mLocalScripts); listCellScripts (mStore, cell.containers, mLocalScripts);
listCellScripts (cell.creatures, mLocalScripts); listCellScripts (mStore, cell.creatures, mLocalScripts);
listCellScripts (cell.doors, mLocalScripts); listCellScripts (mStore, cell.doors, mLocalScripts);
listCellScripts (cell.ingreds, mLocalScripts); listCellScripts (mStore, cell.ingreds, mLocalScripts);
listCellScripts (cell.lights, mLocalScripts); listCellScripts (mStore, cell.lights, mLocalScripts);
listCellScripts (cell.lockpicks, mLocalScripts); listCellScripts (mStore, cell.lockpicks, mLocalScripts);
listCellScripts (cell.miscItems, mLocalScripts); listCellScripts (mStore, cell.miscItems, mLocalScripts);
listCellScripts (cell.npcs, mLocalScripts); listCellScripts (mStore, cell.npcs, mLocalScripts);
listCellScripts (cell.probes, mLocalScripts); listCellScripts (mStore, cell.probes, mLocalScripts);
listCellScripts (cell.repairs, mLocalScripts); listCellScripts (mStore, cell.repairs, mLocalScripts);
listCellScripts (cell.weapons, mLocalScripts); listCellScripts (mStore, cell.weapons, mLocalScripts);
} }
World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,