00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cstddef>
00023
00024 #include "defines.h"
00025 #include "game-server/accountconnection.hpp"
00026 #include "game-server/character.hpp"
00027 #include "game-server/gamehandler.hpp"
00028 #include "game-server/inventory.hpp"
00029 #include "game-server/item.hpp"
00030 #include "game-server/itemmanager.hpp"
00031 #include "game-server/mapmanager.hpp"
00032 #include "game-server/monster.hpp"
00033 #include "game-server/monstermanager.hpp"
00034 #include "game-server/state.hpp"
00035
00036 template< typename T >
00037 static T proxy_cast(intptr_t v)
00038 { return (T)v; }
00039
00040 template<>
00041 const std::string &proxy_cast(intptr_t v)
00042 { return *(const std::string *)v; }
00043
00044 template< typename T1 >
00045 static void proxy(void (*f)(), Character *from, intptr_t const args[1])
00046 {
00047 ((void (*)(Character *, T1))f)
00048 (from, proxy_cast<T1>(args[0]));
00049 }
00050
00051 template< typename T1, typename T2 >
00052 static void proxy(void (*f)(), Character *from, intptr_t const args[2])
00053 {
00054 ((void (*)(Character *, T1, T2))f)
00055 (from, proxy_cast<T1>(args[0]), proxy_cast<T2>(args[1]));
00056 }
00057
00058 template< typename T1, typename T2, typename T3 >
00059 static void proxy(void (*f)(), Character *from, intptr_t const args[3])
00060 {
00061 ((void (*)(Character *, T1, T2, T3))f)
00062 (from, proxy_cast<T1>(args[0]), proxy_cast<T2>(args[1]),
00063 proxy_cast<T3>(args[2]));
00064 }
00065
00066 template< typename T1, typename T2, typename T3, typename T4 >
00067 static void proxy(void (*f)(), Character *from, intptr_t const args[4])
00068 {
00069 ((void (*)(Character *, T1, T2, T3, T4))f)
00070 (from, proxy_cast<T1>(args[0]), proxy_cast<T2>(args[1]),
00071 proxy_cast<T3>(args[2]), proxy_cast<T4>(args[3]));
00072 }
00073
00078 template< typename T > struct Argument;
00079
00080 template<> struct Argument< int >
00081 { static char const type = 'n'; };
00082 template<> struct Argument< const std::string & >
00083 { static char const type = 's'; };
00084 template<> struct Argument< Character * >
00085 { static char const type = 'c'; };
00086 template<> struct Argument< MapComposite * >
00087 { static char const type = 'm'; };
00088 template<> struct Argument< ItemClass * >
00089 { static char const type = 'i'; };
00090 template<> struct Argument< MonsterClass * >
00091 { static char const type = 'o'; };
00092
00096 struct Command
00097 {
00098 const char *name;
00099 void (*handler)(void (*f)(), Character *, intptr_t const[]);
00100 void (*target)();
00101 char type[4];
00102 unsigned char level;
00103 };
00104
00108 template< typename T1 >
00109 static Command handle(const char *name, int level,
00110 void (*f)(Character *, T1))
00111 {
00112 Command c;
00113 c.name = name;
00114 c.level = level;
00115 c.handler = &proxy< T1 >;
00116 c.target = (void (*)())f;
00117 c.type[0] = Argument<T1>::type;
00118 c.type[1] = 0;
00119 return c;
00120 }
00121
00125 template< typename T1, typename T2 >
00126 static Command handle(const char *name, int level,
00127 void (*f)(Character *, T1, T2))
00128 {
00129 Command c;
00130 c.name = name;
00131 c.level = level;
00132 c.handler = &proxy< T1, T2 >;
00133 c.target = (void (*)())f;
00134 c.type[0] = Argument<T1>::type;
00135 c.type[1] = Argument<T2>::type;
00136 c.type[2] = 0;
00137 return c;
00138 }
00139
00143 template< typename T1, typename T2, typename T3 >
00144 static Command handle(const char *name, int level,
00145 void (*f)(Character *, T1, T2, T3))
00146 {
00147 Command c;
00148 c.name = name;
00149 c.level = level;
00150 c.handler = &proxy< T1, T2, T3 >;
00151 c.target = (void (*)())f;
00152 c.type[0] = Argument<T1>::type;
00153 c.type[1] = Argument<T2>::type;
00154 c.type[2] = Argument<T3>::type;
00155 c.type[3] = 0;
00156 return c;
00157 }
00158
00162 template< typename T1, typename T2, typename T3, typename T4 >
00163 static Command handle(const char *name, int level,
00164 void (*f)(Character *, T1, T2, T3, T4))
00165 {
00166 Command c;
00167 c.name = name;
00168 c.level = level;
00169 c.handler = &proxy< T1, T2, T3, T4 >;
00170 c.target = (void (*)())f;
00171 c.type[0] = Argument<T1>::type;
00172 c.type[1] = Argument<T2>::type;
00173 c.type[2] = Argument<T3>::type;
00174 c.type[3] = Argument<T4>::type;
00175 return c;
00176 }
00177
00178 static void warp(Character *, Character *q, MapComposite *m, int x, int y)
00179 {
00180 GameState::warp(q, m, x, y);
00181 }
00182
00183 static void item(Character *, Character *q, ItemClass *it, int nb)
00184 {
00185 Inventory(q).insert(it->getDatabaseID(), nb);
00186 }
00187
00188 static void money(Character *, Character *q, int nb)
00189 {
00190 Inventory(q).changeMoney(nb);
00191 }
00192
00193 static void drop(Character *from, ItemClass *it, int nb)
00194 {
00195 Item *item = new Item(it, nb);
00196 item->setMap(from->getMap());
00197 item->setPosition(from->getPosition());
00198 GameState::insertSafe(item);
00199 }
00200
00201 static void spawn(Character *from, MonsterClass *specy, int nb)
00202 {
00203 MapComposite *map = from->getMap();
00204 const Point &pos = from->getPosition();
00205
00206 for (int i = 0; i < nb; ++i)
00207 {
00208 Being *monster = new Monster(specy);
00209 monster->setMap(map);
00210 monster->setPosition(pos);
00211 monster->clearDestination();
00212 if (!GameState::insertSafe(monster))
00213 {
00214
00215 break;
00216 }
00217 }
00218 }
00219
00220 static void goto_(Character *from, Character *ch)
00221 {
00222 MapComposite *m = ch->getMap();
00223 const Point &pos = ch->getPosition();
00224 GameState::warp(from, m, pos.x, pos.y);
00225 }
00226
00227 static void recall(Character *from, Character *ch)
00228 {
00229 MapComposite *m = from->getMap();
00230 const Point &pos = from->getPosition();
00231 GameState::warp(ch, m, pos.x, pos.y);
00232 }
00233
00234 static void reload(Character *, const std::string &db)
00235 {
00236 if (db == "items")
00237 {
00238 ItemManager::reload();
00239 }
00240 else if (db == "monsters")
00241 {
00242 MonsterManager::reload();
00243 }
00244 }
00245
00246 static void ban(Character *from, Character *ch, const std::string &duration)
00247 {
00248 if (from->getAccountLevel() <= ch->getAccountLevel())
00249 {
00250
00251 return;
00252 }
00253
00254 int d = atoi(duration.c_str());
00255 switch (duration[duration.length() - 1])
00256 {
00257 case 'd': d = d * 24;
00258 case 'h': d = d * 60;
00259 }
00260 accountHandler->banCharacter(ch, d);
00261 }
00262
00263 static void attribute(Character*, Character *ch, int attr, int value)
00264 {
00265 ch->setAttribute(attr, value);
00266 }
00267
00271 static Command const commands[] =
00272 {
00273 handle("warp", AL_GM, warp),
00274 handle("item", AL_GM, item),
00275 handle("drop", AL_GM, drop),
00276 handle("money", AL_GM, money),
00277 handle("spawn", AL_GM, spawn),
00278 handle("goto", AL_GM, goto_),
00279 handle("recall", AL_GM, recall),
00280 handle("reload", AL_ADMIN, reload),
00281 handle("ban", AL_GM, ban),
00282 handle("attribute", AL_GM, attribute),
00283 };
00284
00288 static void say(Character * ch, const std::string &message)
00289 {
00290 GameState::sayTo(ch, NULL, message);
00291 }
00292
00293
00297 void runCommand(Character *ch, const std::string &text)
00298 {
00299 const Command *c = NULL;
00300 std::string::size_type npos = std::string::npos;
00301 std::string::size_type pos = text.find(' ');
00302
00303 std::string s(text, 1, pos == npos ? npos : pos - 1);
00304
00305
00306 for (int i = 0; i < (int)(sizeof(commands) / sizeof(commands[0])); ++i)
00307 {
00308 if (s == commands[i].name)
00309 {
00310 c = &commands[i];
00311 break;
00312 }
00313 }
00314
00315 if (!c)
00316 {
00317 say(ch, "The command " + s + " was not found");
00318 return;
00319 }
00320
00321 if (c->level > ch->getAccountLevel())
00322 {
00323 say(ch, "You have insufficient rights to perform the " + s + " command");
00324 return;
00325 }
00326
00327 intptr_t args[4];
00328
00329 for (int i = 0; i < 4 && c->type[i]; ++i)
00330 {
00331 if (pos == npos || pos + 1 >= text.length())
00332 {
00333
00334 say(ch, "Not enough parameters for the " + s +
00335 " command. See the command documentation for details");
00336 return;
00337 }
00338
00339 std::string::size_type pos2 = text.find(' ', pos + 1);
00340 std::string arg(text, pos + 1, pos2 == npos ? npos : pos2 - pos - 1);
00341 if (arg.empty())
00342 {
00343
00344 say(ch, "One of your parameters was empty");
00345 return;
00346 }
00347
00348 switch (c->type[i])
00349 {
00350 case 'c':
00351 if (arg == "#")
00352 {
00353
00354 args[i] = (intptr_t)ch;
00355 }
00356 else
00357 {
00358 GameClient *c = gameHandler->getClientByNameSlow(arg);
00359 if (!c)
00360 {
00361
00362
00363 say(ch, "Player " + arg + " was not found");
00364 return;
00365 }
00366 if (c->status != CLIENT_CONNECTED)
00367 {
00368
00369 say(ch, "Player " + arg + " is offline");
00370 return;
00371 }
00372 args[i] = (intptr_t)c->character;
00373 }
00374 break;
00375
00376 case 'i':
00377 if (ItemClass *ic = ItemManager::getItem(atoi(arg.c_str())))
00378 {
00379 args[i] = (intptr_t)ic;
00380 }
00381 else
00382 {
00383
00384 say(ch, "No item was found with id " + arg);
00385 return;
00386 }
00387 break;
00388
00389 case 'm':
00390 if (arg == "#")
00391 {
00392
00393 args[i] = (intptr_t)ch->getMap();
00394 }
00395 else if (MapComposite *m = MapManager::getMap(atoi(arg.c_str())))
00396 {
00397 args[i] = (intptr_t)m;
00398 }
00399 else
00400 {
00401
00402 say(ch, "Map " + arg + " was not found");
00403 return;
00404 }
00405 break;
00406
00407 case 'n':
00408 args[i] = atoi(arg.c_str());
00409 break;
00410
00411 case 'o':
00412 if (MonsterClass *mc = MonsterManager::getMonster(atoi(arg.c_str())))
00413 {
00414 args[i] = (intptr_t)mc;
00415 }
00416 else
00417 {
00418
00419 say(ch, "No monster with id " + arg + " was found");
00420 return;
00421 }
00422 break;
00423
00424 case 's':
00425 args[i] = (intptr_t)new std::string(arg);
00426 break;
00427
00428 }
00429 pos = pos2;
00430 }
00431
00432
00433 c->handler(c->target, ch, args);
00434
00435
00436 for (int i = 0; i < 4 && c->type[i]; ++i)
00437 {
00438 if (c->type[i] == 's')
00439 {
00440 delete (std::string *)args[i];
00441 }
00442 }
00443 }