Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7483 was 7483, checked in by dafrick, 14 years ago

Removing some debug output and come minor cleaning up.

  • Property svn:eol-style set to native
File size: 10.9 KB
Line 
1
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:
26 *      Damian 'Mozork' Frick
27 *
28 */
29
30#include "Script.h"
31
32#include "core/command/CommandExecutor.h"
33#include "core/CoreIncludes.h"
34#include "core/EventIncludes.h"
35#include "core/GameMode.h"
36#include "core/LuaState.h"
37#include "core/XMLPort.h"
38#include "network/Host.h"
39#include "network/NetworkFunction.h"
40
41#include "PlayerManager.h"
42#include "infos/PlayerInfo.h"
43#include "interfaces/PlayerTrigger.h"
44#include "worldentities/pawns/Pawn.h"
45
46namespace orxonox
47{
48    CreateFactory(Script);
49
50    registerStaticNetworkFunction(Script::executeHelper);
51
52    // Initializing constants.
53    /*static*/ const std::string Script::NORMAL = "normal";
54    /*static*/ const std::string Script::LUA = "lua";
55    /*static*/ const int Script::INF = -1;
56
57    /**
58    @brief
59        Constructor. Registers and initializes the object.
60    @param creator
61        The creator of this object.
62    */
63    Script::Script(BaseObject* creator) : BaseObject(creator), Synchronisable(creator)
64    {
65        RegisterObject(Script);
66
67        // Initialize variables.
68        this->remainingExecutions_ = Script::INF;
69        this->mode_ = ScriptMode::normal;
70        this->onLoad_ = true;
71        this->times_ = Script::INF;
72        this->needsGraphics_ = false;
73    }
74
75    /**
76    @brief
77        Destructor. Cleans up.
78    */
79    Script::~Script()
80    {
81        //if(this->isInitialized() && this->luaState_ != NULL)
82        //    delete this->luaState_;
83    }
84
85    /**
86    @brief
87        Method for creating a Script object through XML.
88    @param xmlelement
89        The element.
90    @param mode
91        The mode.
92    */
93    void Script::XMLPort(Element& xmlelement, XMLPort::Mode mode)
94    {
95        SUPER(Script, XMLPort, xmlelement, mode);
96
97        XMLPortParam(Script, "code", setCode, getCode, xmlelement, mode);
98        XMLPortParamTemplate(Script, "mode", setMode, getMode, xmlelement, mode, const std::string&).defaultValues(Script::NORMAL);
99        XMLPortParam(Script, "onLoad", setOnLoad, isOnLoad, xmlelement, mode).defaultValues(true);
100        XMLPortParam(Script, "times", setTimes, getTimes, xmlelement, mode).defaultValues(Script::INF);
101        XMLPortParam(Script, "needsGraphics", setNeedsGraphics, getNeedsGraphics, xmlelement, mode).defaultValues(false);
102        XMLPortParam(Script, "forAll", setForAll, isForAll, xmlelement, mode).defaultValues(false);
103
104        XMLPortEventSink(Script, BaseObject, "trigger", trigger, xmlelement, mode);
105
106        if(this->isOnLoad()) // If the object is onLoad the code is executed at once for the server.
107            this->execute(0);
108    }
109
110    /**
111    @brief
112        Creates a port that can be used to channel events and react to them.
113    @param xmlelement
114        The element.
115    @param mode
116        The mode.
117    */
118    void Script::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
119    {
120        SUPER(Script, XMLEventPort, xmlelement, mode);
121
122        XMLPortEventState(Script, BaseObject, "trigger", trigger, xmlelement, mode);
123    }
124
125    /**
126    @brief
127        Is called when an event comes in trough the event port.
128    @param triggered
129        Whether the event is triggering or un-triggering.
130    @param trigger
131        The object that caused the event to be fired.
132    @return
133        Returns true if successful.
134    */
135    bool Script::trigger(bool triggered, BaseObject* trigger)
136    {
137        if(!triggered || !this->isActive()) // If the Script is inactive it cannot be executed.
138            return false;
139
140        COUT(4) << "Script (&" << this << ") triggered." << std::endl;
141
142        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
143        Pawn* pawn = NULL;
144
145        // If the trigger is a PlayerTrigger.
146        if(pTrigger != NULL)
147        {
148            if(!pTrigger->isForPlayer())  // The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
149                return false;
150            else
151                pawn = pTrigger->getTriggeringPlayer();
152        }
153        else
154            return false;
155
156        if(pawn == NULL)  //TODO: Will this ever happen? If not, change in NotificationDispatcher as well.
157        {
158            COUT(4) << "The Script was triggered by an entity other than a Pawn. (" << trigger->getIdentifier()->getName() << ")" << std::endl;
159            return false;
160        }
161
162        // Extract the PlayerInfo from the Pawn.
163        PlayerInfo* player = pawn->getPlayer();
164
165        if(player == NULL)
166        {
167            COUT(3) << "The PlayerInfo* is NULL." << std::endl;
168            return false;
169        }
170
171        this->execute(player->getClientID());
172        return true;
173    }
174
175    /**
176    @brief
177        Executes the Scripts code for the input client, depending on the mode.
178    @param clientId
179        The Id of the client the Script should be executed for.
180    @param fromCallback
181        Whether this method is executed in response to the connectedCallback().
182    */
183    void Script::execute(unsigned int clientId, bool fromCallback)
184    {
185        // 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.
186        if(GameMode::isServer() || GameMode::isStandalone())
187        {
188            // If the number of executions have been used up.
189            if(this->times_ != Script::INF && this->remainingExecutions_ == 0)
190                return;
191        }
192
193        // If this is either the standalone mode or we're on the client we want to be.
194        if(GameMode::isStandalone() || Host::getPlayerID() == clientId)
195        {
196           this->executeHelper(this->getCode(), this->getMode(), this->getNeedsGraphics());
197        }
198
199        // If this is the server and we're not on the client we want to be.
200        if(!GameMode::isStandalone() && GameMode::isServer() && Host::getPlayerID() != clientId)
201        {
202            // If this is not the result of a clientConnected callback and we want to execute the code for all clients.
203            //TODO: In this case does the server get executed as well?
204            if(!fromCallback && this->isForAll())
205            {
206                const std::map<unsigned int, PlayerInfo*> clients = PlayerManager::getInstance().getClients();
207                for(std::map<unsigned int, PlayerInfo*>::const_iterator it = clients.begin(); it != clients.end(); it++)
208                {
209                    callStaticNetworkFunction(Script::executeHelper, it->first, this->getCode(), this->getMode(), this->getNeedsGraphics());
210                    if(this->times_ != Script::INF) // Decrement the number of remaining executions.
211                        this->remainingExecutions_--;
212                }
213            }
214            // Else we execute the code just for the specified client.
215            else
216            {
217                callStaticNetworkFunction(Script::executeHelper, clientId, this->getCode(), this->getMode(), this->getNeedsGraphics());
218                if(this->times_ != Script::INF) // Decrement the number of remaining executions.
219                    this->remainingExecutions_--;
220            }
221        }
222    }
223
224    /**
225    @brief
226        Helper method that is used to reach this Script object on other clients.
227    */
228    /*static*/ void Script::executeHelper(const std::string& code, const std::string& mode, bool needsGraphics)
229    {
230        // If the code needs graphics to be executed but the GameMode doesn't show graphics the code isn't executed.
231        if(needsGraphics && !GameMode::showsGraphics())
232            return;
233
234        if(mode == Script::NORMAL) // If the mode is 'normal'.
235            CommandExecutor::execute(code);
236        else if(mode == Script::LUA) // If it's 'lua'.
237        {
238            LuaState* luaState = new LuaState();
239            luaState->doString(code);
240            delete luaState;
241        }
242    }
243
244    /**
245    @brief
246        Callback that is called when a new client has connected.
247    @param clientId
248        The clientId of the new client that has connected.
249    */
250    void Script::clientConnected(unsigned int clientId)
251    {
252        // If this is the server and the Script is specified as being 'onLoad'.
253        if(!GameMode::isStandalone() && GameMode::isServer() && this->isOnLoad())
254        {
255            this->execute(clientId, true);
256        }
257    }
258
259    /**
260    @brief
261        Sets the mode of the Script.
262    @param mode
263        The mode as a string.
264    */
265    void Script::setMode(const std::string& mode)
266    {
267        if(mode == Script::NORMAL)
268        {
269            this->setMode(ScriptMode::normal);
270            this->modeStr_ = Script::NORMAL;
271        }
272        else if(mode == Script::LUA)
273        {
274            this->setMode(ScriptMode::lua);
275            this->modeStr_ = Script::LUA;
276        }
277        else
278        {
279            COUT(2) << "Invalid mode '" << mode << "' in Script object. Setting to 'normal'." << std::endl;
280            this->setMode(ScriptMode::normal);
281            this->modeStr_ = Script::NORMAL;
282        }
283    }
284
285    /**
286    @brief
287        Sets the mode to the mode specified in this->modeStr_.
288        This is used internally for networking purposes.
289    */
290    void Script::modeChanged(void)
291    {
292        this->setMode(this->modeStr_);
293    }
294
295    /**
296    @brief
297        Get the mode of the Script.
298    @return
299        Returns the mode as a string.
300    */
301    const std::string& Script::getMode(void)
302    {
303        switch(this->mode_)
304        {
305            case ScriptMode::normal:
306                return Script::NORMAL;
307            case ScriptMode::lua:
308                return Script::LUA;
309            default: // This will never happen...
310                return Script::NORMAL;
311        }
312    }
313
314    /**
315    @brief
316        Set the number of times this Script is executed at the most.
317        -1 denotes infinity.
318    @param times
319        The number of times to be set.
320    */
321    void Script::setTimes(int times)
322    {
323        if(times >= -1)
324        {
325            this->times_ = times;
326            this->remainingExecutions_ = times;
327        }
328        else
329        {
330            COUT(2) << "Invalid times '" << times << "' in Script. Setting to infinity." << std::endl;
331            this->times_ = Script::INF;
332            this->remainingExecutions_ = Script::INF;
333        }
334    }
335
336}
Note: See TracBrowser for help on using the repository browser.