Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

ConsoleCommand::getCommand should return a const pointer

  • Property svn:eol-style set to native
File size: 18.9 KB
RevLine 
[1505]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
[7214]31#include "util/Convert.h"
[7228]32#include "util/StringUtils.h"
[7203]33#include "core/Language.h"
[7222]34#include "core/GameMode.h"
[7179]35
36namespace orxonox
37{
[7236]38    ConsoleCommand::ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
[7179]39    {
[7185]40        this->bActive_ = true;
[7215]41        this->bHidden_ = false;
42        this->accessLevel_ = AccessLevel::All;
43
[7214]44        this->baseName_ = name;
[7267]45        this->baseFunctor_ = executor->getFunctor();
[7214]46
[7215]47        this->argumentCompleter_[0] = 0;
48        this->argumentCompleter_[1] = 0;
49        this->argumentCompleter_[2] = 0;
50        this->argumentCompleter_[3] = 0;
51        this->argumentCompleter_[4] = 0;
52
53        this->keybindMode_ = KeybindMode::OnPress;
54        this->inputConfiguredParam_ = -1;
55
[7214]56        if (bInitialized)
57            this->executor_ = executor;
58
[7236]59        ConsoleCommand::registerCommand(group, name, this);
[7179]60    }
61
[7236]62    ConsoleCommand::~ConsoleCommand()
[7214]63    {
[7236]64        ConsoleCommand::unregisterCommand(this);
[7214]65    }
66
[7236]67    ConsoleCommand& ConsoleCommand::addShortcut()
[7179]68    {
[7236]69        ConsoleCommand::registerCommand("", this->baseName_, this);
[7179]70        return *this;
71    }
72
[7236]73    ConsoleCommand& ConsoleCommand::addShortcut(const std::string&  name)
[7179]74    {
[7236]75        ConsoleCommand::registerCommand("", name, this);
[7179]76        return *this;
77    }
78
[7236]79    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group)
[7179]80    {
[7236]81        ConsoleCommand::registerCommand(group, this->baseName_, this);
[7179]82        return *this;
83    }
84
[7236]85    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
[7179]86    {
[7236]87        ConsoleCommand::registerCommand(group, name, this);
[7179]88        return *this;
89    }
90
[7236]91    bool ConsoleCommand::isActive() const
[7179]92    {
[7218]93        return (this->bActive_ && this->executor_ && this->executor_->getFunctor() && (this->executor_->getFunctor()->getType() == Functor::Type::Static || this->executor_->getFunctor()->getRawObjectPointer()));
[7214]94    }
95
[7236]96    bool ConsoleCommand::hasAccess() const
[7222]97    {
98        switch (this->accessLevel_)
99        {
100            case AccessLevel::All:        return true;
101            case AccessLevel::Standalone: return GameMode::isStandalone();
102            case AccessLevel::Master:     return GameMode::isMaster();
103            case AccessLevel::Server:     return GameMode::hasServer();
104            case AccessLevel::Client:     return GameMode::isClient();
105            case AccessLevel::Online:     return (GameMode::hasServer() || GameMode::isClient());
106            case AccessLevel::Offline:    return GameMode::isStandalone();
107            case AccessLevel::None:       return false;
108            default:                      return false;
109        }
110    }
111
[7236]112    bool ConsoleCommand::headersMatch(const FunctorPtr& functor)
[7214]113    {
[7267]114        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), functor->getParamCount());
[7214]115
[7267]116        if (this->baseFunctor_->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
[7214]117            return false;
[7267]118        else if (functor->getParamCount() <= this->baseFunctor_->getParamCount())
[7214]119            return true;
120        else if (!this->executor_)
121            return false;
122        else
[7179]123        {
[7267]124            for (unsigned int i = this->baseFunctor_->getParamCount(); i < functor->getParamCount(); ++i)
125            {
[7214]126                if (!this->executor_->defaultValueSet(i))
[7267]127                {
128                    COUT(2) << "Default value " << i << " is missing" << std::endl;
[7214]129                    return false;
[7267]130                }
131            }
[7214]132
[7185]133            return true;
[7179]134        }
[7214]135    }
[7185]136
[7236]137    bool ConsoleCommand::headersMatch(const ExecutorPtr& executor)
[7214]138    {
[7267]139        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), executor->getParamCount());
[7214]140
[7267]141        if (this->baseFunctor_->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
[7214]142            return false;
[7267]143        else if (executor->getParamCount() <= this->baseFunctor_->getParamCount())
[7214]144            return true;
145        else
[7179]146        {
[7267]147            for (unsigned int i = this->baseFunctor_->getParamCount(); i < executor->getParamCount(); ++i)
148            {
[7214]149                if (!executor->defaultValueSet(i))
[7267]150                {
151                    COUT(2) << "Default value " << i << " is missing" << std::endl;
[7214]152                    return false;
[7267]153                }
154            }
[7214]155
156            return true;
157        }
158    }
159
[7236]160    bool ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
[7214]161    {
162        if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
163        {
164            this->executor_ = executor;
[7272]165            this->objectStack_.clear();
[7214]166            return true;
167        }
168        else
169        {
170            COUT(1) << "Error: Couldn't assign new executor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
[7185]171            return false;
[7179]172        }
[7214]173    }
[7185]174
[7236]175    bool ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
[7214]176    {
177        if (!functor || bForce || this->headersMatch(functor))
178        {
179            if (this->executor_)
180                this->executor_->setFunctor(functor);
[7218]181            else if (functor)
[7214]182                this->executor_ = createExecutor(functor);
[7272]183            this->objectStack_.clear();
[7214]184
185            return true;
186        }
187        else
188        {
189            COUT(1) << "Error: Couldn't assign new functor to console command \"" << this->baseName_ << "\", headers don't match." << std::endl;
190            return false;
191        }
[7179]192    }
193
[7236]194    void ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
[7179]195    {
[7214]196        Command command;
[7270]197        command.executor_ = this->executor_;
[7214]198        if (command.executor_)
[7270]199            command.functor_ = this->executor_->getFunctor();
[7272]200        command.objectStack_ = this->objectStack_;
[7185]201
[7214]202        if (this->setFunction(executor, bForce))
203            this->commandStack_.push(command);
[7179]204    }
205
[7236]206    void ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
[7179]207    {
[7214]208        Command command;
[7270]209        command.executor_ = this->executor_;
[7214]210        if (command.executor_)
[7270]211            command.functor_ = this->executor_->getFunctor();
[7272]212        command.objectStack_ = this->objectStack_;
[7214]213
214        if (this->setFunction(functor, bForce))
215            this->commandStack_.push(command);
[7185]216    }
[7179]217
[7236]218    void ConsoleCommand::pushFunction()
[7185]219    {
[7214]220        if (this->executor_)
221            this->pushFunction(new Executor(*this->executor_.get()));
222        else
223            COUT(1) << "Error: Couldn't push copy of executor in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
[7179]224    }
225
[7236]226    void ConsoleCommand::popFunction()
[7179]227    {
[7214]228        Command command;
229        if (!this->commandStack_.empty())
[7179]230        {
[7214]231            command = this->commandStack_.top();
232            this->commandStack_.pop();
[7179]233        }
[7214]234
235        this->executor_ = command.executor_;
236        if (command.executor_)
237            this->executor_->setFunctor(command.functor_);
[7272]238        this->objectStack_ = command.objectStack_;
[7179]239    }
240
[7236]241    void ConsoleCommand::resetFunction()
[7218]242    {
243        if (this->executor_)
244            this->executor_->setFunctor(0);
[7272]245        this->objectStack_.clear();
[7218]246    }
247
[7236]248    const ExecutorPtr& ConsoleCommand::getExecutor() const
[7179]249    {
[7214]250        return this->executor_;
[7179]251    }
252
[7236]253    bool ConsoleCommand::setObject(void* object)
[7214]254    {
255        if (this->executor_)
[7185]256        {
[7214]257            if (this->executor_->getFunctor())
258            {
259                this->executor_->getFunctor()->setRawObjectPointer(object);
260                return true;
261            }
262            else if (object)
263                COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no functor set." << std::endl;
[7185]264        }
[7214]265        else if (object)
266            COUT(1) << "Error: Can't assign object to console command \"" << this->baseName_ << "\", no executor set." << std::endl;
267
268        return false;
[7179]269    }
270
[7236]271    void ConsoleCommand::pushObject(void* object)
[7214]272    {
273        void* oldobject = this->getObject();
274        if (this->setObject(object))
[7272]275            this->objectStack_.push_back(oldobject);
[7214]276    }
277
[7236]278    void ConsoleCommand::popObject()
[7185]279    {
280        void* newobject = 0;
281        if (!this->objectStack_.empty())
282        {
[7272]283            newobject = this->objectStack_.back();
284            this->objectStack_.pop_back();
[7185]285        }
286        this->setObject(newobject);
287    }
288
[7236]289    void* ConsoleCommand::getObject() const
[7185]290    {
[7214]291        if (this->executor_ && this->executor_->getFunctor())
292            return this->executor_->getFunctor()->getRawObjectPointer();
[7185]293        else
294            return 0;
295    }
296
[7236]297    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1)
[7215]298    {
299        if (this->executor_)
300            this->executor_->setDefaultValues(param1);
301        else
302            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
303
304        return *this;
305    }
306
[7236]307    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2)
[7215]308    {
309        if (this->executor_)
310            this->executor_->setDefaultValues(param1, param2);
311        else
312            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
313
314        return *this;
315    }
316
[7236]317    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
[7215]318    {
319        if (this->executor_)
320            this->executor_->setDefaultValues(param1, param2, param3);
321        else
322            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
323
324        return *this;
325    }
326
[7236]327    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
[7215]328    {
329        if (this->executor_)
330            this->executor_->setDefaultValues(param1, param2, param3, param4);
331        else
332            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
333
334        return *this;
335    }
336
[7236]337    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
[7215]338    {
339        if (this->executor_)
340            this->executor_->setDefaultValues(param1, param2, param3, param4, param5);
341        else
342            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
343
344        return *this;
345    }
346
[7236]347    ConsoleCommand& ConsoleCommand::defaultValue(unsigned int index, const MultiType& param)
[7215]348    {
349        if (this->executor_)
350            this->executor_->setDefaultValue(index, param);
351        else
352            COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
353
354        return *this;
355    }
356
[7236]357    ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int param, ArgumentCompleter* completer)
[7215]358    {
359        if (param < 5)
360            this->argumentCompleter_[param] = completer;
361        else
362            COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << " in console command \"" << this->baseName_ << "\": index out of bound." << std::endl;
363
364        return *this;
365    }
366
[7236]367    ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int param) const
[7215]368    {
369        if (param < 5)
370            return this->argumentCompleter_[param];
371        else
372            return 0;
373    }
374
[7236]375    ConsoleCommand& ConsoleCommand::description(const std::string& description)
[7215]376    {
377        this->description_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::function");
378        AddLanguageEntry(this->description_, description);
379        return *this;
380    }
381
[7236]382    const std::string& ConsoleCommand::getDescription() const
[7215]383    {
384        return GetLocalisation_noerror(this->description_);
385    }
386
[7236]387    ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int param, const std::string& description)
[7215]388    {
389        if (param < MAX_FUNCTOR_ARGUMENTS)
390        {
391            this->descriptionParam_[param] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(param));
392            AddLanguageEntry(this->descriptionParam_[param], description);
393        }
394        return *this;
395    }
396
[7236]397    const std::string& ConsoleCommand::getDescriptionParam(unsigned int param) const
[7215]398    {
399        if (param < MAX_FUNCTOR_ARGUMENTS)
400            return GetLocalisation_noerror(this->descriptionParam_[param]);
401
402        return this->descriptionParam_[0];
403    }
404
[7236]405    ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
[7215]406    {
407        this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::returnvalue");
408        AddLanguageEntry(this->descriptionReturnvalue_, description);
409        return *this;
410    }
411
[7236]412    const std::string& ConsoleCommand::getDescriptionReturnvalue(int param) const
[7215]413    {
414        return GetLocalisation_noerror(this->descriptionReturnvalue_);
415    }
416
[7282]417    /* static */ const ConsoleCommand* ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
[7179]418    {
[7236]419        std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMap().find(group);
420        if (it_group != ConsoleCommand::getCommandMap().end())
[7179]421        {
[7236]422            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
[7179]423            if (it_name != it_group->second.end())
424            {
425                return it_name->second;
426            }
427        }
428        if (bPrintError)
429        {
430            if (group == "")
[7198]431                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
[7179]432            else
[7198]433                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
[7179]434        }
435        return 0;
436    }
437
[7282]438    /* static */ const ConsoleCommand* ConsoleCommand::getCommandLC(const std::string& group, const std::string& name, bool bPrintError)
[7228]439    {
440        std::string groupLC = getLowercase(group);
441        std::string nameLC = getLowercase(name);
442
[7236]443        std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMapLC().find(groupLC);
444        if (it_group != ConsoleCommand::getCommandMapLC().end())
[7228]445        {
[7236]446            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(nameLC);
[7228]447            if (it_name != it_group->second.end())
448            {
449                return it_name->second;
450            }
451        }
452        if (bPrintError)
453        {
454            if (group == "")
455                COUT(1) << "Error: Couldn't find console command with shortcut \"" << name << "\"" << std::endl;
456            else
457                COUT(1) << "Error: Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << std::endl;
458        }
459        return 0;
460    }
461
[7236]462    /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMap()
[7179]463    {
[7236]464        static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMap;
[7179]465        return commandMap;
466    }
467
[7236]468    /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMapLC()
[7228]469    {
[7236]470        static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMapLC;
[7228]471        return commandMapLC;
472    }
473
[7236]474    /* static */ void ConsoleCommand::registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command)
[7179]475    {
476        if (name == "")
477            return;
478
[7236]479        if (ConsoleCommand::getCommand(group, name) != 0)
[7179]480        {
481            if (group == "")
[7214]482                COUT(2) << "Warning: A console command with shortcut \"" << name << "\" already exists." << std::endl;
[7179]483            else
[7214]484                COUT(2) << "Warning: A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << std::endl;
[7179]485        }
486        else
487        {
[7236]488            ConsoleCommand::getCommandMap()[group][name] = command;
489            ConsoleCommand::getCommandMapLC()[getLowercase(group)][getLowercase(name)] = command;
[7179]490        }
491    }
[7214]492
[7236]493    /* static */ void ConsoleCommand::unregisterCommand(ConsoleCommand* command)
[7214]494    {
[7236]495        for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMap().begin(); it_group != ConsoleCommand::getCommandMap().end(); )
[7214]496        {
[7236]497            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
[7214]498            {
499                if (it_name->second == command)
500                    it_group->second.erase(it_name++);
501                else
502                    ++it_name;
503            }
504
505            if (it_group->second.empty())
[7236]506                ConsoleCommand::getCommandMap().erase(it_group++);
[7214]507            else
508                ++it_group;
509        }
[7228]510
[7236]511        for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMapLC().begin(); it_group != ConsoleCommand::getCommandMapLC().end(); )
[7228]512        {
[7236]513            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
[7228]514            {
515                if (it_name->second == command)
516                    it_group->second.erase(it_name++);
517                else
518                    ++it_name;
519            }
520
521            if (it_group->second.empty())
[7236]522                ConsoleCommand::getCommandMapLC().erase(it_group++);
[7228]523            else
524                ++it_group;
525        }
[7214]526    }
[7216]527
[7236]528    /* static */ void ConsoleCommand::destroyAll()
[7216]529    {
[7236]530        while (!ConsoleCommand::getCommandMap().empty() && !ConsoleCommand::getCommandMap().begin()->second.empty())
531            delete ConsoleCommand::getCommandMap().begin()->second.begin()->second;
[7216]532    }
[7179]533}
Note: See TracBrowser for help on using the repository browser.