Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/objects/Script.cc @ 11800

Last change on this file since 11800 was 11099, checked in by muemart, 9 years ago

Fix loads of doxygen warnings and other documentation issues

  • Property svn:eol-style set to native
File size: 10.7 KB
RevLine 
[7482]1
[1383]2/*
3 *   ORXONOX - the hottest 3D action shooter ever to exist
4 *                    > www.orxonox.net <
5 *
6 *
7 *   License notice:
8 *
9 *   This program is free software; you can redistribute it and/or
10 *   modify it under the terms of the GNU General Public License
11 *   as published by the Free Software Foundation; either version 2
12 *   of the License, or (at your option) any later version.
13 *
14 *   This program is distributed in the hope that it will be useful,
15 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *   GNU General Public License for more details.
18 *
19 *   You should have received a copy of the GNU General Public License
20 *   along with this program; if not, write to the Free Software
21 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 *
23 *   Author:
24 *      Benjamin Knecht
25 *   Co-authors:
[7404]26 *      Damian 'Mozork' Frick
[1383]27 *
28 */
29
30#include "Script.h"
[1906]31
[7404]32#include "core/command/CommandExecutor.h"
[1383]33#include "core/CoreIncludes.h"
[7404]34#include "core/EventIncludes.h"
[7463]35#include "core/GameMode.h"
[5695]36#include "core/LuaState.h"
37#include "core/XMLPort.h"
[7474]38#include "network/Host.h"
[10624]39#include "network/NetworkFunctionIncludes.h"
[1383]40
[7474]41#include "PlayerManager.h"
42#include "infos/PlayerInfo.h"
43#include "interfaces/PlayerTrigger.h"
44#include "worldentities/pawns/Pawn.h"
45
[1383]46namespace orxonox
47{
[9667]48    RegisterClass(Script);
[1383]49
[7482]50    registerStaticNetworkFunction(Script::executeHelper);
[7474]51
[7404]52    // Initializing constants.
53    /*static*/ const std::string Script::NORMAL = "normal";
54    /*static*/ const std::string Script::LUA = "lua";
[7406]55    /*static*/ const int Script::INF = -1;
[7404]56
57    /**
58    @brief
59        Constructor. Registers and initializes the object.
60    */
[9667]61    Script::Script(Context* context) : BaseObject(context)
[5695]62    {
63        RegisterObject(Script);
[1383]64
[7404]65        // Initialize variables.
66        this->remainingExecutions_ = Script::INF;
[7463]67        this->mode_ = ScriptMode::normal;
68        this->onLoad_ = true;
69        this->times_ = Script::INF;
70        this->needsGraphics_ = false;
[5695]71    }
[1383]72
[7404]73    /**
74    @brief
75        Destructor. Cleans up.
76    */
[5695]77    Script::~Script()
78    {
[7486]79
[5695]80    }
[1383]81
[7404]82    /**
83    @brief
84        Method for creating a Script object through XML.
[7407]85    @param xmlelement
[7404]86        The element.
87    @param mode
88        The mode.
89    */
[7407]90    void Script::XMLPort(Element& xmlelement, XMLPort::Mode mode)
[5695]91    {
[7408]92        SUPER(Script, XMLPort, xmlelement, mode);
[1383]93
[7407]94        XMLPortParam(Script, "code", setCode, getCode, xmlelement, mode);
95        XMLPortParamTemplate(Script, "mode", setMode, getMode, xmlelement, mode, const std::string&).defaultValues(Script::NORMAL);
96        XMLPortParam(Script, "onLoad", setOnLoad, isOnLoad, xmlelement, mode).defaultValues(true);
97        XMLPortParam(Script, "times", setTimes, getTimes, xmlelement, mode).defaultValues(Script::INF);
[7463]98        XMLPortParam(Script, "needsGraphics", setNeedsGraphics, getNeedsGraphics, xmlelement, mode).defaultValues(false);
[7474]99        XMLPortParam(Script, "forAll", setForAll, isForAll, xmlelement, mode).defaultValues(false);
[7404]100
[7407]101        XMLPortEventSink(Script, BaseObject, "trigger", trigger, xmlelement, mode);
[7404]102
[7482]103        if(this->isOnLoad()) // If the object is onLoad the code is executed at once for the server.
[7486]104            this->execute(0, true);
[5695]105    }
[1383]106
[7404]107    /**
108    @brief
109        Creates a port that can be used to channel events and react to them.
[7407]110    @param xmlelement
[7404]111        The element.
112    @param mode
113        The mode.
114    */
[7407]115    void Script::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
[7404]116    {
[7408]117        SUPER(Script, XMLEventPort, xmlelement, mode);
[7404]118
[7407]119        XMLPortEventState(Script, BaseObject, "trigger", trigger, xmlelement, mode);
[7404]120    }
121
122    /**
123    @brief
124        Is called when an event comes in trough the event port.
125    @param triggered
126        Whether the event is triggering or un-triggering.
[7474]127    @param trigger
128        The object that caused the event to be fired.
129    @return
130        Returns true if successful.
[7404]131    */
[7474]132    bool Script::trigger(bool triggered, BaseObject* trigger)
[7404]133    {
[7474]134        if(!triggered || !this->isActive()) // If the Script is inactive it cannot be executed.
135            return false;
136
[8858]137        orxout(verbose, context::misc::script) << "Script (&" << this << ") triggered." << endl;
[7474]138
139        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
[11071]140        PlayerInfo* player = nullptr;
[7474]141
142        // If the trigger is a PlayerTrigger.
[11071]143        if(pTrigger != nullptr)
[7474]144        {
145            if(!pTrigger->isForPlayer())  // The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
146                return false;
147            else
[8706]148                player = pTrigger->getTriggeringPlayer();
[7474]149        }
150        else
151            return false;
152
[11071]153        if(player == nullptr)  //TODO: Will this ever happen? If not, change in NotificationDispatcher as well.
[7474]154        {
[8858]155            orxout(internal_warning) << "The Script was triggered by an entity other than a Pawn. (" << trigger->getIdentifier()->getName() << ")" << endl;
[7474]156            return false;
157        }
158
159        this->execute(player->getClientID());
160        return true;
[7404]161    }
162
163    /**
164    @brief
[7474]165        Executes the Scripts code for the input client, depending on the mode.
166    @param clientId
167        The Id of the client the Script should be executed for.
[7486]168    @param onLoad
169        Whether this method is executed as a result of the onLoad parameter being set to true. Default is false.
[7404]170    */
[7486]171    void Script::execute(unsigned int clientId, bool onLoad)
[5695]172    {
[7482]173        // If this is the server or we're in standalone mode we check whether we still want to execute the code and if so decrease the number of remaining executions.
[7486]174        if(GameMode::isMaster())
[7474]175        {
176            // If the number of executions have been used up.
[7493]177            if(this->times_ != Script::INF && this->remainingExecutions_ <= 0)
[7474]178                return;
179        }
[7463]180
[7482]181        // If this is either the standalone mode or we're on the client we want to be.
[7474]182        if(GameMode::isStandalone() || Host::getPlayerID() == clientId)
[7404]183        {
[7486]184            this->executeHelper(this->getCode(), this->getMode(), this->getNeedsGraphics());
185            if(GameMode::isMaster() && !onLoad && this->times_ != Script::INF) // Decrement the number of remaining executions.
186                this->remainingExecutions_--;
[7482]187        }
[7474]188
[7482]189        // If this is the server and we're not on the client we want to be.
[7486]190        if(GameMode::isServer() && Host::getPlayerID() != clientId)
[7474]191        {
[7486]192            // If we want to execute the code for all clients and the server.
193            if(this->isForAll())
[7474]194            {
195                const std::map<unsigned int, PlayerInfo*> clients = PlayerManager::getInstance().getClients();
[11071]196                for(const auto& mapEntry : clients)
[7474]197                {
[11071]198                    callStaticNetworkFunction(&Script::executeHelper, mapEntry.first, this->getCode(), this->getMode(), this->getNeedsGraphics());
[7483]199                    if(this->times_ != Script::INF) // Decrement the number of remaining executions.
[7493]200                    {
[7483]201                        this->remainingExecutions_--;
[7493]202                        if(this->remainingExecutions_ <= 0)
203                            break;
204                    }
[7474]205                }
206            }
[7482]207            // Else we execute the code just for the specified client.
[7474]208            else
209            {
[10624]210                callStaticNetworkFunction(&Script::executeHelper, clientId, this->getCode(), this->getMode(), this->getNeedsGraphics());
[7483]211                if(this->times_ != Script::INF) // Decrement the number of remaining executions.
212                    this->remainingExecutions_--;
[7474]213            }
214        }
215    }
[7404]216
[7482]217    /**
218    @brief
219        Helper method that is used to reach this Script object on other clients.
220    */
221    /*static*/ void Script::executeHelper(const std::string& code, const std::string& mode, bool needsGraphics)
222    {
223        // If the code needs graphics to be executed but the GameMode doesn't show graphics the code isn't executed.
224        if(needsGraphics && !GameMode::showsGraphics())
225            return;
226
227        if(mode == Script::NORMAL) // If the mode is 'normal'.
228            CommandExecutor::execute(code);
229        else if(mode == Script::LUA) // If it's 'lua'.
230        {
[7483]231            LuaState* luaState = new LuaState();
232            luaState->doString(code);
233            delete luaState;
[7482]234        }
235    }
236
237    /**
238    @brief
239        Callback that is called when a new client has connected.
240    @param clientId
241        The clientId of the new client that has connected.
242    */
[7474]243    void Script::clientConnected(unsigned int clientId)
244    {
[7482]245        // If this is the server and the Script is specified as being 'onLoad'.
[7486]246        if(GameMode::isServer() && this->isOnLoad())
[7474]247        {
[10624]248            callStaticNetworkFunction(&Script::executeHelper, clientId, this->getCode(), this->getMode(), this->getNeedsGraphics());
[7474]249        }
[5695]250    }
[7404]251
252    /**
253    @brief
254        Sets the mode of the Script.
255    @param mode
256        The mode as a string.
257    */
258    void Script::setMode(const std::string& mode)
259    {
260        if(mode == Script::NORMAL)
[7474]261        {
[7404]262            this->setMode(ScriptMode::normal);
[7474]263            this->modeStr_ = Script::NORMAL;
264        }
[7404]265        else if(mode == Script::LUA)
266        {
267            this->setMode(ScriptMode::lua);
[7474]268            this->modeStr_ = Script::LUA;
[7404]269        }
270        else
271        {
[8858]272            orxout(internal_warning) << "Invalid mode '" << mode << "' in Script object. Setting to 'normal'." << endl;
[7404]273            this->setMode(ScriptMode::normal);
[7474]274            this->modeStr_ = Script::NORMAL;
[7404]275        }
276    }
277
278    /**
279    @brief
[7482]280        Sets the mode to the mode specified in this->modeStr_.
281        This is used internally for networking purposes.
282    */
283    void Script::modeChanged(void)
284    {
285        this->setMode(this->modeStr_);
286    }
287
288    /**
289    @brief
[7404]290        Get the mode of the Script.
291    @return
292        Returns the mode as a string.
293    */
294    const std::string& Script::getMode(void)
295    {
296        switch(this->mode_)
297        {
298            case ScriptMode::normal:
299                return Script::NORMAL;
300            case ScriptMode::lua:
301                return Script::LUA;
[7410]302            default: // This will never happen...
303                return Script::NORMAL;
[7404]304        }
305    }
306
307    /**
308    @brief
309        Set the number of times this Script is executed at the most.
310        -1 denotes infinity.
311    @param times
312        The number of times to be set.
313    */
314    void Script::setTimes(int times)
315    {
316        if(times >= -1)
317        {
318            this->times_ = times;
319            this->remainingExecutions_ = times;
320        }
321        else
322        {
[8858]323            orxout(internal_warning) << "Invalid times '" << times << "' in Script. Setting to infinity." << endl;
[7404]324            this->times_ = Script::INF;
[7474]325            this->remainingExecutions_ = Script::INF;
[7404]326        }
327    }
328
[1383]329}
Note: See TracBrowser for help on using the repository browser.