Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/core/command/ConsoleCommand.cc @ 7222

Last change on this file since 7222 was 7222, checked in by landauf, 14 years ago

added access level checking

  • Property svn:eol-style set to native
File size: 16.4 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "ConsoleCommand.h"
30
31#include "util/Convert.h"
32#include "core/Language.h"
33#include "core/GameMode.h"
34
35namespace orxonox
36{
37    _ConsoleCommand::_ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
38    {
39        this->bActive_ = true;
40        this->bHidden_ = false;
41        this->accessLevel_ = AccessLevel::All;
42
43        this->baseName_ = name;
44        this->baseExecutor_ = executor;
45
46        this->argumentCompleter_[0] = 0;
47        this->argumentCompleter_[1] = 0;
48        this->argumentCompleter_[2] = 0;
49        this->argumentCompleter_[3] = 0;
50        this->argumentCompleter_[4] = 0;
51
52        this->keybindMode_ = KeybindMode::OnPress;
53        this->inputConfiguredParam_ = -1;
54
55        if (bInitialized)
56            this->executor_ = executor;
57
58        _ConsoleCommand::registerCommand(group, name, this);
59    }
60
61    _ConsoleCommand::~_ConsoleCommand()
62    {
63        _ConsoleCommand::unregisterCommand(this);
64    }
65
66    _ConsoleCommand& _ConsoleCommand::addShortcut()
67    {
68        _ConsoleCommand::registerCommand("", this->baseName_, this);
69        return *this;
70    }
71
72    _ConsoleCommand& _ConsoleCommand::addShortcut(const std::string&  name)
73    {
74        _ConsoleCommand::registerCommand("", name, this);
75        return *this;
76    }
77
78    _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group)
79    {
80        _ConsoleCommand::registerCommand(group, this->baseName_, this);
81        return *this;
82    }
83
84    _ConsoleCommand& _ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
85    {
86        _ConsoleCommand::registerCommand(group, name, this);
87        return *this;
88    }
89
90    bool _ConsoleCommand::isActive() const
91    {
92        return (this->bActive_ && this->executor_ && this->executor_->getFunctor() && (this->executor_->getFunctor()->getType() == Functor::Type::Static || this->executor_->getFunctor()->getRawObjectPointer()));
93    }
94
95    bool _ConsoleCommand::hasAccess() const
96    {
97        switch (this->accessLevel_)
98        {
99            case AccessLevel::All:        return true;
100            case AccessLevel::Standalone: return GameMode::isStandalone();
101            case AccessLevel::Master:     return GameMode::isMaster();
102            case AccessLevel::Server:     return GameMode::hasServer();
103            case AccessLevel::Client:     return GameMode::isClient();
104            case AccessLevel::Online:     return (GameMode::hasServer() || GameMode::isClient());
105            case AccessLevel::Offline:    return GameMode::isStandalone();
106            case AccessLevel::None:       return false;
107            default:                      return false;
108        }
109    }
110
111    bool _ConsoleCommand::headersMatch(const FunctorPtr& functor)
112    {
113        unsigned int minparams = std::min(this->baseExecutor_->getParamCount(), functor->getParamCount());
114
115        if (this->baseExecutor_->getFunctor()->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
116            return false;
117        else if (functor->getParamCount() <= this->baseExecutor_->getParamCount())
118            return true;
119        else if (!this->executor_)
120            return false;
121        else
122        {
123            for (unsigned int i = this->baseExecutor_->getParamCount(); i < functor->getParamCount(); ++i)
124                if (!this->executor_->defaultValueSet(i))
125                    return false;
126
127            return true;
128        }
129    }
130
131    bool _ConsoleCommand::headersMatch(const ExecutorPtr& executor)
132    {
133        unsigned int minparams = std::min(this->baseExecutor_->getParamCount(), executor->getParamCount());
134
135        if (this->baseExecutor_->getFunctor()->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
136            return false;
137        else if (executor->getParamCount() <= this->baseExecutor_->getParamCount())
138            return true;
139        else
140        {
141            for (unsigned int i = this->baseExecutor_->getParamCount(); i < executor->getParamCount(); ++i)
142                if (!executor->defaultValueSet(i))
143                    return false;
144
145            return true;
146        }
147    }
148
149    bool _ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
150    {
151        if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
152        {
153            this->executor_ = executor;
154            return true;
155        }
156        else
157        {
158            COUT(1) << "Error: Couldn't assign new executor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
159            return false;
160        }
161    }
162
163    bool _ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
164    {
165        if (!functor || bForce || this->headersMatch(functor))
166        {
167            if (this->executor_)
168                this->executor_->setFunctor(functor);
169            else if (functor)
170                this->executor_ = createExecutor(functor);
171
172            return true;
173        }
174        else
175        {
176            COUT(1) << "Error: Couldn't assign new functor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
177            return false;
178        }
179    }
180
181    void _ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
182    {
183        Command command;
184        command.executor_ = this->getExecutor();
185        if (command.executor_)
186            command.functor_ = this->getExecutor()->getFunctor();
187
188        if (this->setFunction(executor, bForce))
189            this->commandStack_.push(command);
190    }
191
192    void _ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
193    {
194        Command command;
195        command.executor_ = this->getExecutor();
196        if (command.executor_)
197            command.functor_ = this->getExecutor()->getFunctor();
198
199        if (this->setFunction(functor, bForce))
200            this->commandStack_.push(command);
201    }
202
203    void _ConsoleCommand::pushFunction()
204    {
205        if (this->executor_)
206            this->pushFunction(new Executor(*this->executor_.get()));
207        else
208            COUT(1) << "Error: Couldn't push copy of executor in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
209    }
210
211    void _ConsoleCommand::popFunction()
212    {
213        Command command;
214        if (!this->commandStack_.empty())
215        {
216            command = this->commandStack_.top();
217            this->commandStack_.pop();
218        }
219
220        this->executor_ = command.executor_;
221        if (command.executor_)
222            this->executor_->setFunctor(command.functor_);
223    }
224
225    void _ConsoleCommand::resetFunction()
226    {
227        if (this->executor_)
228            this->executor_->setFunctor(0);
229    }
230
231    const ExecutorPtr& _ConsoleCommand::getExecutor() const
232    {
233        return this->executor_;
234    }
235
236    bool _ConsoleCommand::setObject(void* object)
237    {
238        if (this->executor_)
239        {
240            if (this->executor_->getFunctor())
241            {
242                this->executor_->getFunctor()->setRawObjectPointer(object);
243                return true;
244            }
245            else if (object)
246                COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no functor set." << std::endl;
247        }
248        else if (object)
249            COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no executor set." << std::endl;
250
251        return false;
252    }
253
254    void _ConsoleCommand::pushObject(void* object)
255    {
256        void* oldobject = this->getObject();
257        if (this->setObject(object))
258            this->objectStack_.push(oldobject);
259    }
260
261    void _ConsoleCommand::popObject()
262    {
263        void* newobject = 0;
264        if (!this->objectStack_.empty())
265        {
266            newobject = this->objectStack_.top();
267            this->objectStack_.pop();
268        }
269        this->setObject(newobject);
270    }
271
272    void* _ConsoleCommand::getObject() const
273    {
274        if (this->executor_ && this->executor_->getFunctor())
275            return this->executor_->getFunctor()->getRawObjectPointer();
276        else
277            return 0;
278    }
279
280    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1)
281    {
282        if (this->executor_)
283            this->executor_->setDefaultValues(param1);
284        else
285            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
286
287        return *this;
288    }
289
290    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2)
291    {
292        if (this->executor_)
293            this->executor_->setDefaultValues(param1, param2);
294        else
295            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
296
297        return *this;
298    }
299
300    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
301    {
302        if (this->executor_)
303            this->executor_->setDefaultValues(param1, param2, param3);
304        else
305            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
306
307        return *this;
308    }
309
310    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
311    {
312        if (this->executor_)
313            this->executor_->setDefaultValues(param1, param2, param3, param4);
314        else
315            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
316
317        return *this;
318    }
319
320    _ConsoleCommand& _ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
321    {
322        if (this->executor_)
323            this->executor_->setDefaultValues(param1, param2, param3, param4, param5);
324        else
325            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
326
327        return *this;
328    }
329
330    _ConsoleCommand& _ConsoleCommand::defaultValue(unsigned int index, const MultiType& param)
331    {
332        if (this->executor_)
333            this->executor_->setDefaultValue(index, param);
334        else
335            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
336
337        return *this;
338    }
339
340    _ConsoleCommand& _ConsoleCommand::argumentCompleter(unsigned int param, ArgumentCompleter* completer)
341    {
342        if (param < 5)
343            this->argumentCompleter_[param] = completer;
344        else
345            COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << " in console command \"" << this->baseName_ << "\": index out of bound." << std::endl;
346
347        return *this;
348    }
349
350    ArgumentCompleter* _ConsoleCommand::getArgumentCompleter(unsigned int param) const
351    {
352        if (param < 5)
353            return this->argumentCompleter_[param];
354        else
355            return 0;
356    }
357
358    _ConsoleCommand& _ConsoleCommand::description(const std::string& description)
359    {
360        this->description_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::function");
361        AddLanguageEntry(this->description_, description);
362        return *this;
363    }
364
365    const std::string& _ConsoleCommand::getDescription() const
366    {
367        return GetLocalisation_noerror(this->description_);
368    }
369
370    _ConsoleCommand& _ConsoleCommand::descriptionParam(unsigned int param, const std::string& description)
371    {
372        if (param < MAX_FUNCTOR_ARGUMENTS)
373        {
374            this->descriptionParam_[param] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(param));
375            AddLanguageEntry(this->descriptionParam_[param], description);
376        }
377        return *this;
378    }
379
380    const std::string& _ConsoleCommand::getDescriptionParam(unsigned int param) const
381    {
382        if (param < MAX_FUNCTOR_ARGUMENTS)
383            return GetLocalisation_noerror(this->descriptionParam_[param]);
384
385        return this->descriptionParam_[0];
386    }
387
388    _ConsoleCommand& _ConsoleCommand::descriptionReturnvalue(const std::string& description)
389    {
390        this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::returnvalue");
391        AddLanguageEntry(this->descriptionReturnvalue_, description);
392        return *this;
393    }
394
395    const std::string& _ConsoleCommand::getDescriptionReturnvalue(int param) const
396    {
397        return GetLocalisation_noerror(this->descriptionReturnvalue_);
398    }
399
400    /* static */ const _ConsoleCommand* _ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
401    {
402        std::map<std::string, std::map<std::string, _ConsoleCommand*> >::const_iterator it_group = _ConsoleCommand::getCommandMap().find(group);
403        if (it_group != _ConsoleCommand::getCommandMap().end())
404        {
405            std::map<std::string, _ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
406            if (it_name != it_group->second.end())
407            {
408                return it_name->second;
409            }
410        }
411        if (bPrintError)
412        {
413            if (group == "")
414                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
415            else
416                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
417        }
418        return 0;
419    }
420
421    /* static */ std::map<std::string, std::map<std::string, _ConsoleCommand*> >& _ConsoleCommand::getCommandMap()
422    {
423        static std::map<std::string, std::map<std::string, _ConsoleCommand*> > commandMap;
424        return commandMap;
425    }
426
427    /* static */ void _ConsoleCommand::registerCommand(const std::string& group, const std::string& name, _ConsoleCommand* command)
428    {
429        if (name == "")
430            return;
431
432        if (_ConsoleCommand::getCommand(group, name) != 0)
433        {
434            if (group == "")
435                COUT(2) << "Warning: A console command with shortcut \"" << name << "\" already exists." << std::endl;
436            else
437                COUT(2) << "Warning: A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << std::endl;
438        }
439        else
440        {
441            _ConsoleCommand::getCommandMap()[group][name] = command;
442        }
443    }
444
445    /* static */ void _ConsoleCommand::unregisterCommand(_ConsoleCommand* command)
446    {
447        for (std::map<std::string, std::map<std::string, _ConsoleCommand*> >::iterator it_group = _ConsoleCommand::getCommandMap().begin(); it_group != _ConsoleCommand::getCommandMap().end(); )
448        {
449            for (std::map<std::string, _ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
450            {
451                if (it_name->second == command)
452                    it_group->second.erase(it_name++);
453                else
454                    ++it_name;
455            }
456
457            if (it_group->second.empty())
458                _ConsoleCommand::getCommandMap().erase(it_group++);
459            else
460                ++it_group;
461        }
462    }
463
464    /* static */ void _ConsoleCommand::destroyAll()
465    {
466        while (!_ConsoleCommand::getCommandMap().empty() && !_ConsoleCommand::getCommandMap().begin()->second.empty())
467            delete _ConsoleCommand::getCommandMap().begin()->second.begin()->second;
468    }
469}
Note: See TracBrowser for help on using the repository browser.