Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

replaced the temporary names of all ConsoleCommand related classes and functions by their real names

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