root/trunk/src/trinitycore/CliRunnable.cpp @ 237

Revision 237, 10.6 kB (checked in by yumileroy, 17 years ago)

[svn] DynamicObject? should only be visible for caster if it is not in distance. However, I do not think this will fix the bug that dynamic object update freezes the server.

Original author: megamage
Date: 2008-11-15 11:56:59-06:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21/// \addtogroup Trinityd
22/// @{
23/// \file
24
25#include "Common.h"
26#include "Language.h"
27#include "Log.h"
28#include "World.h"
29#include "ScriptCalls.h"
30#include "ObjectMgr.h"
31#include "WorldSession.h"
32#include "SystemConfig.h"
33#include "Config/ConfigEnv.h"
34#include "Util.h"
35#include "AccountMgr.h"
36#include "CliRunnable.h"
37#include "MapManager.h"
38#include "Player.h"
39#include "Chat.h"
40
41void utf8print(const char* str)
42{
43#if PLATFORM == PLATFORM_WINDOWS
44#define UTF8ZPRINTF utf8printf
45        wchar_t wtemp_buf[6000];
46    size_t wtemp_len = 6000-1;
47    if(!Utf8toWStr(str,strlen(str),wtemp_buf,wtemp_len))
48        return;
49
50    char temp_buf[6000];
51    CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1);
52    printf(temp_buf);
53#else
54    printf(str);
55#endif
56}
57
58/// Delete a user account and all associated characters in this realm
59/// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm, delete account chars in realm then delete account
60bool ChatHandler::HandleAccountDeleteCommand(const char* args)
61{
62    if(!*args)
63        return false;
64
65    ///- Get the account name from the command line
66    char *account_name_str=strtok ((char*)args," ");
67    if (!account_name_str)
68        return false;
69
70    std::string account_name = account_name_str;
71    if(!AccountMgr::normilizeString(account_name))
72    {
73        PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
74        SetSentErrorMessage(true);
75        return false;
76    }
77
78    uint32 account_id = accmgr.GetId(account_name);
79    if(!account_id)
80    {
81        PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
82        SetSentErrorMessage(true);
83        return false;
84    }
85
86    /// Commands not recommended call from chat, but support anyway
87    if(m_session)
88    {
89        uint32 targetSecurity = accmgr.GetSecurity(account_id);
90
91        /// can delete only for account with less security
92        /// This is also reject self apply in fact
93        if (targetSecurity >= m_session->GetSecurity())
94        {
95            SendSysMessage (LANG_YOURS_SECURITY_IS_LOW);
96            SetSentErrorMessage (true);
97            return false;
98        }
99    }
100
101    AccountOpResult result = accmgr.DeleteAccount(account_id);
102    switch(result)
103    {
104        case AOR_OK:
105            PSendSysMessage(LANG_ACCOUNT_DELETED,account_name.c_str());
106            break;
107        case AOR_NAME_NOT_EXIST:
108            PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
109            SetSentErrorMessage(true);
110            return false;
111        case AOR_DB_INTERNAL_ERROR:
112            PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR,account_name.c_str());
113            SetSentErrorMessage(true);
114            return false;
115        default:
116            PSendSysMessage(LANG_ACCOUNT_NOT_DELETED,account_name.c_str());
117            SetSentErrorMessage(true);
118            return false;
119    }
120
121    return true;
122}
123
124bool ChatHandler::HandleCharacterDeleteCommand(const char* args)
125{
126    if(!*args)
127        return false;
128
129    char *character_name_str = strtok((char*)args," ");
130    if(!character_name_str)
131        return false;
132
133    std::string character_name = character_name_str;
134    if(!normalizePlayerName(character_name))
135        return false;
136
137    uint64 character_guid;
138    uint32 account_id;
139
140    Player *player = objmgr.GetPlayer(character_name.c_str());
141    if(player)
142    {
143        character_guid = player->GetGUID();
144        account_id = player->GetSession()->GetAccountId();
145        player->GetSession()->KickPlayer();
146    }
147    else
148    {
149        character_guid = objmgr.GetPlayerGUIDByName(character_name);
150        if(!character_guid)
151        {
152            PSendSysMessage(LANG_NO_PLAYER,character_name.c_str());
153            SetSentErrorMessage(true);
154            return false;
155        }
156
157        account_id = objmgr.GetPlayerAccountIdByGUID(character_guid);
158    }
159
160    std::string account_name;
161    accmgr.GetName (account_id,account_name);
162
163    Player::DeleteFromDB(character_guid, account_id, true);
164    PSendSysMessage(LANG_CHARACTER_DELETED,character_name.c_str(),GUID_LOPART(character_guid),account_name.c_str(), account_id);
165    return true;
166}
167
168/// Exit the realm
169bool ChatHandler::HandleServerExitCommand(const char* args)
170{
171    SendSysMessage(LANG_COMMAND_EXIT);
172    World::m_stopEvent = true;
173    return true;
174}
175
176/// Display info on users currently in the realm
177bool ChatHandler::HandleAccountOnlineListCommand(const char* args)
178{
179    ///- Get the list of accounts ID logged to the realm
180    QueryResult *resultDB = CharacterDatabase.Query("SELECT name,account FROM characters WHERE online > 0");
181    if (!resultDB)
182        return true;
183
184    ///- Display the list of account/characters online
185    SendSysMessage("=====================================================================");
186    SendSysMessage(LANG_ACCOUNT_LIST_HEADER);
187    SendSysMessage("=====================================================================");
188
189    ///- Circle through accounts
190    do
191    {
192        Field *fieldsDB = resultDB->Fetch();
193        std::string name = fieldsDB[0].GetCppString();
194        uint32 account = fieldsDB[1].GetUInt32();
195
196        ///- Get the username, last IP and GM level of each account
197        // No SQL injection. account is uint32.
198        //                                                      0         1        2        3
199        QueryResult *resultLogin = loginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account);
200
201        if(resultLogin)
202        {
203            Field *fieldsLogin = resultLogin->Fetch();
204            PSendSysMessage("|%15s| %20s | %15s |%4d|%5d|",
205                fieldsLogin[0].GetString(),name.c_str(),fieldsLogin[1].GetString(),fieldsLogin[2].GetUInt32(),fieldsLogin[3].GetUInt32());
206
207            delete resultLogin;
208        }
209        else
210            PSendSysMessage(LANG_ACCOUNT_LIST_ERROR,name.c_str());
211
212    }while(resultDB->NextRow());
213
214    delete resultDB;
215
216    SendSysMessage("=====================================================================");
217    return true;
218}
219
220/// Create an account
221bool ChatHandler::HandleAccountCreateCommand(const char* args)
222{
223    if(!*args)
224        return false;
225
226    ///- %Parse the command line arguments
227    char *szAcc = strtok((char*)args, " ");
228    char *szPassword = strtok(NULL, " ");
229    if(!szAcc || !szPassword)
230        return false;
231
232    // normilized in accmgr.CreateAccount
233    std::string account_name = szAcc;
234    std::string password = szPassword;
235
236    AccountOpResult result = accmgr.CreateAccount(account_name, password);
237    switch(result)
238    {
239        case AOR_OK:
240            PSendSysMessage(LANG_ACCOUNT_CREATED,account_name.c_str());
241            break;
242        case AOR_NAME_TOO_LONG:
243            SendSysMessage(LANG_ACCOUNT_TOO_LONG);
244            SetSentErrorMessage(true);
245            return false;
246        case AOR_NAME_ALREDY_EXIST:
247            SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST);
248            SetSentErrorMessage(true);
249            return false;
250        case AOR_DB_INTERNAL_ERROR:
251            PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR,account_name.c_str());
252            SetSentErrorMessage(true);
253            return false;
254        default:
255            PSendSysMessage(LANG_ACCOUNT_NOT_CREATED,account_name.c_str());
256            SetSentErrorMessage(true);
257            return false;
258    }
259
260    return true;
261}
262
263/// Set the level of logging
264bool ChatHandler::HandleServerSetLogLevelCommand(const char *args)
265{
266    if(!*args)
267        return false;
268
269    char *NewLevel = strtok((char*)args, " ");
270    if (!NewLevel)
271        return false;
272
273    sLog.SetLogLevel(NewLevel);
274    return true;
275}
276
277/// @}
278
279#ifdef linux
280// Non-blocking keypress detector, when return pressed, return 1, else always return 0
281int kb_hit_return()
282{
283    struct timeval tv;
284    fd_set fds;
285    tv.tv_sec = 0;
286    tv.tv_usec = 0;
287    FD_ZERO(&fds);
288    FD_SET(STDIN_FILENO, &fds);
289    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
290    return FD_ISSET(STDIN_FILENO, &fds);
291}
292#endif
293
294/// %Thread start
295void CliRunnable::run()
296{
297    ///- Init new SQL thread for the world database (one connection call enough)
298    WorldDatabase.ThreadStart();                                // let thread do safe mySQL requests
299
300    char commandbuf[256];
301
302    ///- Display the list of available CLI functions then beep
303    sLog.outString();
304
305    if(sConfig.GetBoolDefault("BeepAtStart", true))
306        printf("\a");                                       // \a = Alert
307
308    // print this here the first time
309    // later it will be printed after command queue updates
310    printf("TC>");
311
312    ///- As long as the World is running (no World::m_stopEvent), get the command line and handle it
313    while (!World::m_stopEvent)
314    {
315        fflush(stdout);
316        #ifdef linux
317        while (!kb_hit_return() && !World::m_stopEvent)
318            // With this, we limit CLI to 10commands/second
319            usleep(100);
320        if (World::m_stopEvent)
321            break;
322        #endif
323        char *command_str = fgets(commandbuf,sizeof(commandbuf),stdin);
324        if (command_str != NULL)
325        {
326            for(int x=0;command_str[x];x++)
327                if(command_str[x]=='\r'||command_str[x]=='\n')
328            {
329                command_str[x]=0;
330                break;
331            }
332
333
334            if(!*command_str)
335            {
336                printf("TC>");
337                continue;
338            }
339
340            std::string command;
341            if(!consoleToUtf8(command_str,command))         // convert from console encoding to utf8
342            {
343                printf("TC>");
344                continue;
345            }
346
347            sWorld.QueueCliCommand(&utf8print,command.c_str());
348        }
349        else if (feof(stdin))
350        {
351            World::m_stopEvent = true;
352        }
353    }
354
355    ///- End the database thread
356    WorldDatabase.ThreadEnd();                                  // free mySQL thread resources
357}
Note: See TracBrowser for help on using the browser.