[3.3.5a] Implementing new console commands menu

User Tag List

Results 1 to 12 of 12
  1. #1
    Natrist's Avatar Member
    Reputation
    11
    Join Date
    Mar 2013
    Posts
    146
    Thanks G/R
    9/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [3.3.5a] Implementing new console commands

    Hello,

    I am writing here in hope to find someone to help me out with implementing new console commands.

    Basically, I am working on a World of Warcraft emulator with a group of friends and I am assigned to the GM systems (auto-reply on accept whispers off, GM Satisfaction Surveys system, etc.) but it doesn't stop there; I am also coding the existing debug console commands.

    So far I have 'worldpor't, 'charmport', and 'logout' commands implemented and working as they should. Port is on its way as soon as I find out just exactly what it does.
    However, I want more: I want to be able to use all commands real developers and GMs use by unlocking them if possible (00407870 InstallGameConsoleCommands ([WoW][3.3.5.12340] Info Dump Thread)) or else register my own commands with the same name, help messages, and functions as any command I can find.

    For those of you who do not know what the console does, I have taken the following screenshots from the World of Warcraft alpha:





    I have been told that this could be done by DLL injection, but I have no knowledge on the matter and any help would be greatly appreciated.
    I would also like to know what 'InstallGameConsoleCommands' and 'ClientRegisterConsoleCommands' do.

    EDIT:
    I am decent in C++ but however don't know much about reverse-engineering even though I have Ollydbg installed and know about as much as how to attach it to a running process.
    A video of my current implementations of the console commands will be posted shortly.

    Feel free to contact me on Skype (tristan.cormier) with any pertinent information you may have.
    Thank you for reading and have a nice day!



    Kind Regards,

    Tristan 'Natrist' Cormier
    C++ Programmer
    CorsairCore
    Last edited by Natrist; 03-21-2013 at 10:57 AM.

    [3.3.5a] Implementing new console commands
  2. #2
    TOM_RUS's Avatar Legendary
    Reputation
    914
    Join Date
    May 2008
    Posts
    699
    Thanks G/R
    0/52
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Paste2 - Viewing Paste 3246609

    I played a bit with adding console commands in the past (wow 4.x). Above is C# code I used.
    Last edited by TOM_RUS; 03-21-2013 at 01:23 PM.

  3. #3
    Natrist's Avatar Member
    Reputation
    11
    Join Date
    Mar 2013
    Posts
    146
    Thanks G/R
    9/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you very much for this little but quite helpful paste, but I have a perhaps newbie question; how do I use this code?
    I haven't worked on client edits yet and I am truly clueless about DLLs as well. I'll try to play around and see if I can get anything to work in the mean time.

    Also, how would I make the command send a client opcode to the server?
    I would like to code my commands server-side, as I want them to do something and not just display a line in the console.

    By the way, do you know if 'InstallGameConsoleCommands' could actually make all console commands accessible -- including the hidden debug, game, and gm ones?

  4. #4
    TOM_RUS's Avatar Legendary
    Reputation
    914
    Join Date
    May 2008
    Posts
    699
    Thanks G/R
    0/52
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Natrist View Post
    By the way, do you know if 'InstallGameConsoleCommands' could actually make all console commands accessible -- including the hidden debug, game, and gm ones?
    There's no hidden console commands in retail client.

  5. #5
    Natrist's Avatar Member
    Reputation
    11
    Join Date
    Mar 2013
    Posts
    146
    Thanks G/R
    9/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh, OK. I thought there was some way to unlock them but I guess they use a different client for that.
    How do I make the console command send an opcode anyway? Is that possible?

  6. #6
    l0l1dk's Avatar Elite User

    Reputation
    499
    Join Date
    Sep 2010
    Posts
    342
    Thanks G/R
    1/6
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Natrist View Post
    Oh, OK. I thought there was some way to unlock them but I guess they use a different client for that.
    How do I make the console command send an opcode anyway? Is that possible?
    You'd have to call the functions to send a packet from the console command callback you've registered, and then handle those packets in the server. Packets can be sent by with the CDataStore functions and ClientServices::Send2. Here's my packet class (it's C++). Maybe it'll help.
    Last edited by l0l1dk; 03-21-2013 at 03:01 PM.

  7. #7
    Natrist's Avatar Member
    Reputation
    11
    Join Date
    Mar 2013
    Posts
    146
    Thanks G/R
    9/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Alright, I will try this out and let you know how it goes.
    It would have been nice if someone could have written a template for me to use over and over again since I plan on implementing at least 15 commands.

  8. #8
    Jadd's Avatar 🐸 Premium Seller
    Reputation
    1515
    Join Date
    May 2008
    Posts
    2,433
    Thanks G/R
    81/336
    Trade Feedback
    1 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Natrist View Post
    Alright, I will try this out and let you know how it goes.
    It would have been nice if someone could have written a template for me to use over and over again since I plan on implementing at least 15 commands.
    You're in the wrong forum if you want to be spoonfed. RTFM.

  9. #9
    culino2's Avatar Elite User
    Reputation
    336
    Join Date
    Feb 2013
    Posts
    183
    Thanks G/R
    139/72
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes you can add your own opcodes in the emu/client.
    The first 4 bytes are standing for the opcode if you use send2.

    You didn't mentioned that you use your own core in the 3.3.5 info dump thread (i thought you want to 'crack' some existing servers)

    It's really simple to realize, just learn the basics.

  10. #10
    Robske's Avatar Contributor
    Reputation
    305
    Join Date
    May 2007
    Posts
    1,062
    Thanks G/R
    3/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you take a look at how the client creates and sends packets it shouldn't really take you that long to figure out. It's quite straight forward.

    It's as simple as creating a data store and pointing it to your packet buffer, then passing the data store to the appropriate send method.

    If you're in control of the server, you can have any packet structure you desire
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." - Martin Golding
    "I cried a little earlier when I had to poop" - Sku

  11. #11
    TOM_RUS's Avatar Legendary
    Reputation
    914
    Join Date
    May 2008
    Posts
    699
    Thanks G/R
    0/52
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    I hope this will answer all questions.

    Code:
    00769100 ConsoleCommandRegister
    BOOL ConsoleCommandRegister(char  const* command, int (*)(char  const*, char  const*) callback, CATEGORY category, char  const* help);
    
    007689E0 ConsoleCommandUnregister
    ConsoleCommandUnregister(char  const* command)
    
    enum CommandCategory
    {
      CATEGORY_Debug = 0x0,
      CATEGORY_Graphics = 0x1,
      CATEGORY_Console = 0x2,
      CATEGORY_Combat = 0x3,
      CATEGORY_Game = 0x4,
      CATEGORY_Default = 0x5,
      CATEGORY_Net = 0x6,
      CATEGORY_Sound = 0x7,
      CATEGORY_Gm = 0x8,
    };
    
    struct CDataStore
    {
      void *vTable;
      unsigned __int8 *m_buffer;
      unsigned int m_base;
      unsigned int m_alloc;
      unsigned int m_size;
      unsigned int m_read;
    };
    
    void __cdecl GameClientCommands::Install()
    {
      ConsoleCommandRegister("port", CCommand_Teleport, CATEGORY_Debug, 0);
      ConsoleCommandRegister("charmport", CCommand_CharmTeleport, CATEGORY_Debug, 0);
      ConsoleCommandRegister("worldport", CCommand_WorldTeleport, CATEGORY_Debug, 0);
      ConsoleCommandRegister("setrawpos", CCommand_SetRawPos, CATEGORY_Debug, 0);
      ConsoleCommandRegister("showplayer", CCommand_TogglePlayer, CATEGORY_Graphics, 0);
      ConsoleCommandRegister("togglehelm", CCommand_ToggleHelm, CATEGORY_Game, 0);
      ConsoleCommandRegister("togglecloak", CCommand_ToggleCloak, CATEGORY_Game, 0);
    }
    
    void __cdecl GameClientCommands::Uninstall()
    {
      ConsoleCommandUnregister("port");
      ConsoleCommandUnregister("charmport");
      ConsoleCommandUnregister("worldport");
      ConsoleCommandUnregister("setrawpos");
      ConsoleCommandUnregister("showplayer");
      ConsoleCommandUnregister("togglehelm");
      ConsoleCommandUnregister("togglecloak");
    }
    
    int __cdecl CCommand_WorldTeleport(char *cmd, char *args)
    {
      double v2; // st7@0
      WGUID guid; // qax@1
      void *pPlayer; // ebx@1
      WorldSafeLocsRec *v5; // edi@1
      int result; // eax@2
      DWORD map; // esi@6
      C3Vector *v8; // eax@6
      float v9; // ecx@6
      float v10; // edx@6
      float v11; // eax@6
      int v12; // eax@15
      int v13; // esi@15
      int v14; // ebx@16
      char *area; // ecx@24
      int ticks; // ebx@29
      QWORD v17; // ST10_8@29
      int v18; // [sp+4h] [bp-88h]@1
      char v19[64]; // [sp+10h] [bp-7Ch]@4
      CDataStore data; // [sp+50h] [bp-3Ch]@29
      C3Vector v21; // [sp+68h] [bp-24h]@6
      float x; // [sp+74h] [bp-18h]@6
      float y; // [sp+78h] [bp-14h]@6
      float z; // [sp+7Ch] [bp-10h]@6
      char v25[4]; // [sp+80h] [bp-Ch]@1
      float v26; // [sp+88h] [bp-4h]@1
    
      strcpy(v25, "\t\r\n\" ");
      guid = ClntObjMgrGetActivePlayerGuid();
      pPlayer = ClntObjMgrObjectPtr(guid, TYPEMASK_PLAYER, ".../Player_C.h", 160);
      v5 = 0;
      LODWORD(v26) = pPlayer;
      if ( !pPlayer )
        return 1;
      if ( IsNumeric(*args) )
      {
        SStrTokenize(&args, v19, 64, v25, 0);
        if ( !v19[0] )
        {
          ConsoleWrite("Usage: worldport <continentID> [x y z] [facing]", 4);
          return 0;
        }
        map = SStrToUnsigned(v19);
        v8 = (*(*pPlayer + 44))(pPlayer, &v21, v18); // pPlayer->GetPosition(&pos);
        v9 = v8->X;
        v10 = v8->Y;
        v11 = v8->Z;
        x = v9;
        y = v10;
        z = v11;
        SStrTokenize(&args, v19, 64, v25, 0);
        if ( v19[0] )
        {
          v2 = SStrToFloat(v19);
          x = v2;
        }
        SStrTokenize(&args, v19, 64, v25, 0);
        if ( v19[0] )
        {
          v2 = SStrToFloat(v19);
          y = v2;
        }
        SStrTokenize(&args, v19, 64, v25, 0);
        if ( v19[0] )
        {
          v2 = SStrToFloat(v19);
          z = v2;
        }
        SStrTokenize(&args, v19, 64, v25, 0);
        if ( v19[0] )
          v2 = SStrToFloat(v19) * 0.017453292;
        else
          (*(*pPlayer + 52))(pPlayer); // o = pPlayer->GetOrientation();
      }
      else
      {
        v12 = g_WorldSafeLocsDB.numRows;
        v13 = 0;
        if ( g_WorldSafeLocsDB.numRows <= 0 )
        {
    LABEL_23:
          ConsolePrintf("Could not find location: %s", args);
          return 1;
        }
        v14 = 0;
        while ( 1 )
        {
          if ( v13 >= v5 && v13 < v12 )
            v5 = &g_WorldSafeLocsDB.FirstRow[v14];
          if ( sub_76F770(v5->m_AreaName_lang, args) )// compare string
            break;
          v12 = g_WorldSafeLocsDB.numRows;
          ++v13;
          v14 += 6;
          if ( v13 >= g_WorldSafeLocsDB.numRows )
            goto LABEL_23;
          v5 = 0;
        }
        area = v5->m_AreaName_lang;
        map = v5->m_continent;
        x = v5->m_locX;
        y = v5->m_locY;
        v2 = v5->m_locZ;
        z = v5->m_locZ;
        ConsolePrintf("Porting to %s", area);
        (*(*LODWORD(v26) + 52))(v18); // o = pPlayer->GetOrientation();
        v5 = 0;
      }
      v26 = v2;
      if ( map >= g_MapDB.minIndex && map <= g_MapDB.maxIndex && g_MapDB.Rows[map - g_MapDB.minIndex] != v5 )
      {
        ticks = PerformanceCounter();
        CDataStore::GenPacket(&data);
        CDataStore::PutInt32(&data, CMSG_WORLD_TELEPORT);
        CDataStore::PutInt32(&data, ticks);
        CDataStore::PutInt32(&data, map);
        HIDWORD(v17) = v5; // v5 is 0 ?
        LODWORD(v17) = v5; // v5 is 0 ?
        CDataStore::PutInt64(&data, v17);           // may be player guid?
        CDataStore::PutFloat(&data, x);
        CDataStore::PutFloat(&data, y);
        CDataStore::PutFloat(&data, z);
        CDataStore::PutFloat(&data, v26);           // o
        data.m_read = v5; // v5 is 0 ?
        ClientServices::SendPacket(&data);
        CDataStore::Release(&data);
        result = 1;
      }
      else
      {
        ConsoleWriteA("Bad world number: %i\n", 3, map);
        result = 0;
      }
      return result;
    }
    
    signed int __cdecl CCommand_SetRawPos(char *cmd, char *args)
    {
      WGUID guid; // qax@1
      CGPlayer_C *pPlayer; // esi@1
      double v4; // st7@8
      double v5; // st7@10
      char v7[64]; // [sp+8h] [bp-7Ch]@5
      CDataStore data; // [sp+48h] [bp-3Ch]@16
      C3Vector v9; // [sp+60h] [bp-24h]@10
      C3Vector pos; // [sp+6Ch] [bp-18h]@1
      char v11[4]; // [sp+78h] [bp-Ch]@1
      float o; // [sp+80h] [bp-4h]@16
    
      pos.X = 0.0;
      pos.Y = 0.0;
      pos.Z = 0.0;
      strcpy(v11, "\t\r\n\" ,");
      guid = ClntObjMgrGetActivePlayerGuid();
      pPlayer = ClntObjMgrObjectPtr(guid, TYPEMASK_PLAYER, ".../Player_C.h", 160);
      if ( !pPlayer )
        return 1;
      if ( !*args || !IsNumeric(*args) && *args != '-' )
      {
        ConsoleWrite("Usage: setrawpos [x y z] [facing]", 4);
        return 0;
      }
      SStrTokenize(&args, v7, 64, v11, 0);
      if ( !v7[0] || (pos.X = SStrToFloat(v7), SStrTokenize(&args, v7, 64, v11, 0), !v7[0]) )
        return 0;
      pos.Y = SStrToFloat(v7);
      SStrTokenize(&args, v7, 64, v11, 0);
      if ( v7[0] )
        v4 = SStrToFloat(v7);
      else
        v4 = 0.0;
      pos.Z = v4;
      CMovement::GetPosition(pPlayer->UnitBase.movementInfo, &v9, &pos);
      v5 = 0.0;
      if ( !World::IsValidPosition(&v9, 0.0) )
      {
        ConsoleWrite("Coordinates out of range\n", 0);
        return 1;
      }
      SStrTokenize(&args, v7, 64, v11, 0);
      if ( v7[0] )
        v5 = SStrToFloat(v7) * 0.017453292;
      else
        (*(pPlayer->UnitBase.ObjectBase.vtable + 14))(pPlayer);
      o = v5;
      CDataStore::GenPacket(&data);
      CDataStore::PutInt32(&data, CMSG_MOVE_SET_RAW_POSITION);
      CDataStore::PutVector3(&data, &pos);
      CDataStore::PutFloat(&data, o);
      data.m_read = 0;
      ClientServices::SendPacket(&data);
      CDataStore::Release(&data);
      return 1;
    }
    
    int __cdecl CCommand_ToggleHelm(char *cmd, char *args)
    {
      WGUID guid; // qax@1
      CGPlayer_C *pPlayer; // esi@1
      CDataStore data; // [sp+8h] [bp-18h]@2
    
      guid = ClntObjMgrGetActivePlayerGuid();
      pPlayer = ClntObjMgrObjectPtr(guid, TYPEMASK_PLAYER, ".../Player_C.h", 160);
      if ( pPlayer )
      {
        CDataStore::GenPacket(&data);
        CDataStore::PutInt32(&data, CMSG_SHOWING_HELM);
        CDataStore::PutInt8(&data, (pPlayer->PlayerData->PLAYER_FLAGS >> 10) & 1);
        data.m_read = 0;
        ClientServices::SendPacket(&data);
        CDataStore::Release(&data);
      }
      return 1;
    }
    
    int __cdecl CCommand_ToggleCloak(char *cmd, char *args)
    {
      WGUID guid; // qax@1
      CGPlayer_C *pPlayer; // esi@1
      CDataStore data; // [sp+8h] [bp-18h]@2
    
      guid = ClntObjMgrGetActivePlayerGuid();
      pPlayer = ClntObjMgrObjectPtr(guid, TYPEMASK_PLAYER, ".../Player_C.h", 160);
      if ( pPlayer )
      {
        CDataStore::GenPacket(&data);
        CDataStore::PutInt32(&data, CMSG_SHOWING_CLOAK);
        CDataStore::PutInt8(&data, (pPlayer->PlayerData->PLAYER_FLAGS >> 11) & 1);
        data.m_read = 0;
        ClientServices::SendPacket(&data);
        CDataStore::Release(&data);
      }
      return 1;
    }
    Last edited by TOM_RUS; 03-22-2013 at 06:58 AM.

  12. #12
    Natrist's Avatar Member
    Reputation
    11
    Join Date
    Mar 2013
    Posts
    146
    Thanks G/R
    9/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you very much for all the information provided. I'll try to fly on my own wings now.

Similar Threads

  1. Cataclysm New Console Commands List
    By hp94 in forum World of Warcraft General
    Replies: 5
    Last Post: 09-21-2010, 10:11 AM
  2. [MOD] Lookup DisplayID (modelID), new GM command
    By latruwski in forum World of Warcraft Emulator Servers
    Replies: 6
    Last Post: 01-21-2008, 01:26 AM
  3. [Ascent]Added New GM command !! Change Gender of characters!
    By latruwski in forum World of Warcraft Emulator Servers
    Replies: 27
    Last Post: 11-07-2007, 05:37 AM
  4. PTR fun with console command
    By feiern in forum World of Warcraft Exploits
    Replies: 26
    Last Post: 09-25-2007, 06:22 PM
  5. WoW Console Commands [X-Post from another site.]
    By n4cht in forum World of Warcraft Exploits
    Replies: 30
    Last Post: 03-22-2007, 05:36 AM
All times are GMT -5. The time now is 02:41 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search