Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow running roc only #68

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions aura.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@

bot_war3path = C:\Program Files\Warcraft III

### whether to act as Warcraft III: The Frozen Throne or not
### set this to 0 to act as Warcraft III: Reign of Chaos (you WILL NOT need to enter a TFT cd key to login to battle.net)
### set this to 1 to act as Warcraft III: The Frozen Throne (you WILL need to enter a TFT cd key to login to battle.net)

bot_tft = 0

### the address Aura will bind to when hosting games (leave it blank to bind to all available addresses)
### if you don't know what this is just leave it blank

Expand Down
25 changes: 25 additions & 0 deletions src/aura.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ CAura::CAura(CConfig* CFG)
m_UDPSocket->SetBroadcastTarget(CFG->GetString("udp_broadcasttarget", string()));
m_UDPSocket->SetDontRoute(CFG->GetInt("udp_dontroute", 0) == 0 ? false : true);

m_TFT = CFG->GetInt("bot_tft", 1) == 0 ? false : true;

if (m_TFT)
Print("[GHOST] acting as Warcraft III: The Frozen Throne");
else
Print("[GHOST] acting as Warcraft III: Reign of Chaos");

m_ReconnectPort = CFG->GetInt("bot_reconnectport", 6113);

if (m_ReconnectSocket->Listen(m_BindAddress, m_ReconnectPort))
Expand Down Expand Up @@ -317,6 +324,24 @@ CAura::CAura(CConfig* CFG)
if (Server.empty())
break;

if (CDKeyROC.empty())
{
Print("[AURA] missing " + Prefix + "cdkeyroc, skipping this battle.net connection");
break;
}

if (m_TFT && CDKeyTFT.empty())
{
Print("[AURA] missing " + Prefix + "cdkeytft, skipping this battle.net connection");
break;
}

if (UserName.empty())
{
Print("[AURA] missing " + Prefix + "username, skipping this battle.net connection");
break;
}

Print("[AURA] found battle.net connection #" + to_string(i) + " for server [" + Server + "]");

if (Locale == "system")
Expand Down
1 change: 1 addition & 0 deletions src/aura.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class CAura
bool m_AutoLock; // config value: auto lock games when the owner is present
bool m_Ready; // indicates if there's lacking configuration info so we can quit
bool m_LCPings; // config value: use LC style pings (divide actual pings by two)
bool m_TFT; // config value: TFT enabled or not

explicit CAura(CConfig* CFG);
~CAura();
Expand Down
10 changes: 6 additions & 4 deletions src/bncsutilinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ inline static std::string CaseInsensitiveFileExists(const std::string& path, std
return "";
}

bool CBNCSUtilInterface::HELP_SID_AUTH_CHECK(const string& war3Path, const string& keyROC, const string& keyTFT, const string& valueStringFormula, const string& mpqFileName, const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& serverToken, const uint8_t war3Version)
bool CBNCSUtilInterface::HELP_SID_AUTH_CHECK(bool TFT, const string& war3Path, const string& keyROC, const string& keyTFT, const string& valueStringFormula, const string& mpqFileName, const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& serverToken, const uint8_t war3Version)
{
const string FileWar3EXE = [&]() {
if (war3Version >= 28)
Expand Down Expand Up @@ -105,16 +105,18 @@ bool CBNCSUtilInterface::HELP_SID_AUTH_CHECK(const string& war3Path, const strin
m_EXEVersion = CreateByteArray(EXEVersion, false);
m_EXEVersionHash = CreateByteArray(EXEVersionHash, false);
m_KeyInfoROC = CreateKeyInfo(keyROC, ByteArrayToUInt32(clientToken, false), ByteArrayToUInt32(serverToken, false));
m_KeyInfoTFT = CreateKeyInfo(keyTFT, ByteArrayToUInt32(clientToken, false), ByteArrayToUInt32(serverToken, false));

if (m_KeyInfoROC.size() == 36 && m_KeyInfoTFT.size() == 36)
if (TFT)
m_KeyInfoTFT = CreateKeyInfo(keyTFT, ByteArrayToUInt32(clientToken, false), ByteArrayToUInt32(serverToken, false));

if (m_KeyInfoROC.size() == 36 && (!TFT || m_KeyInfoTFT.size() == 36))
return true;
else
{
if (m_KeyInfoROC.size() != 36)
Print("[BNCSUI] unable to create ROC key info - invalid ROC key");

if (m_KeyInfoTFT.size() != 36)
if (TFT && m_KeyInfoTFT.size() != 36)
Print("[BNCSUI] unable to create TFT key info - invalid TFT key");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/bncsutilinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class CBNCSUtilInterface

void Reset(const std::string& userName, const std::string& userPassword);

bool HELP_SID_AUTH_CHECK(const std::string& war3Path, const std::string& keyROC, const std::string& keyTFT, const std::string& valueStringFormula, const std::string& mpqFileName, const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& serverToken, const uint8_t war3Version);
bool HELP_SID_AUTH_CHECK(bool TFT, const std::string& war3Path, const std::string& keyROC, const std::string& keyTFT, const std::string& valueStringFormula, const std::string& mpqFileName, const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& serverToken, const uint8_t war3Version);
bool HELP_SID_AUTH_ACCOUNTLOGON();
bool HELP_SID_AUTH_ACCOUNTLOGONPROOF(const std::vector<uint8_t>& salt, const std::vector<uint8_t>& serverKey);
bool HELP_PvPGNPasswordHash(const std::string& userPassword);
Expand Down
13 changes: 8 additions & 5 deletions src/bnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ bool CBNET::Update(void* fd, void* send_fd)

if (m_Protocol->RECEIVE_SID_AUTH_INFO(Data))
{
if (m_BNCSUtil->HELP_SID_AUTH_CHECK(m_Aura->m_Warcraft3Path, m_CDKeyROC, m_CDKeyTFT, m_Protocol->GetValueStringFormulaString(), m_Protocol->GetIX86VerFileNameString(), m_Protocol->GetClientToken(), m_Protocol->GetServerToken(), m_War3Version))
if (m_BNCSUtil->HELP_SID_AUTH_CHECK(m_Aura->m_TFT, m_Aura->m_Warcraft3Path, m_CDKeyROC, m_CDKeyTFT, m_Protocol->GetValueStringFormulaString(), m_Protocol->GetIX86VerFileNameString(), m_Protocol->GetClientToken(), m_Protocol->GetServerToken(), m_War3Version))
{
// override the exe information generated by bncsutil if specified in the config file
// apparently this is useful for pvpgn users
Expand All @@ -261,9 +261,12 @@ bool CBNET::Update(void* fd, void* send_fd)
m_BNCSUtil->SetEXEVersionHash(m_EXEVersionHash);
}

Print("[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: The Frozen Throne");
if (m_Aura->m_TFT)
Print("[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: The Frozen Throne");
else
Print("[BNET: " + m_ServerAlias + "] attempting to auth as Warcraft III: Reign of Chaos");

m_Socket->PutBytes(m_Protocol->SEND_SID_AUTH_CHECK(m_Protocol->GetClientToken(), m_BNCSUtil->GetEXEVersion(), m_BNCSUtil->GetEXEVersionHash(), m_BNCSUtil->GetKeyInfoROC(), m_BNCSUtil->GetKeyInfoTFT(), m_BNCSUtil->GetEXEInfo(), "Aura"));
m_Socket->PutBytes(m_Protocol->SEND_SID_AUTH_CHECK(m_Aura->m_TFT, m_Protocol->GetClientToken(), m_BNCSUtil->GetEXEVersion(), m_BNCSUtil->GetEXEVersionHash(), m_BNCSUtil->GetKeyInfoROC(), m_BNCSUtil->GetKeyInfoTFT(), m_BNCSUtil->GetEXEInfo(), "Aura"));
}
else
{
Expand Down Expand Up @@ -486,7 +489,7 @@ bool CBNET::Update(void* fd, void* send_fd)

Print2("[BNET: " + m_ServerAlias + "] connected");
m_Socket->PutBytes(m_Protocol->SEND_PROTOCOL_INITIALIZE_SELECTOR());
m_Socket->PutBytes(m_Protocol->SEND_SID_AUTH_INFO(m_War3Version, m_LocaleID, m_CountryAbbrev, m_Country));
m_Socket->PutBytes(m_Protocol->SEND_SID_AUTH_INFO(m_War3Version, m_Aura->m_TFT, m_LocaleID, m_CountryAbbrev, m_Country));
m_Socket->DoSend(static_cast<fd_set*>(send_fd));
m_LastNullTime = Time;
m_LastOutPacketTicks = Ticks;
Expand Down Expand Up @@ -1164,7 +1167,7 @@ void CBNET::ProcessChatEvent(const CIncomingChatEvent* chatEvent)
// note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect)
// note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect)

m_Aura->m_UDPSocket->SendTo(IP, Port, m_Aura->m_CurrentGame->GetProtocol()->SEND_W3GS_GAMEINFO(m_Aura->m_LANWar3Version, CreateByteArray(static_cast<uint32_t>(MAPGAMETYPE_UNKNOWN0), false), m_Aura->m_CurrentGame->GetMap()->GetMapGameFlags(), m_Aura->m_CurrentGame->GetMap()->GetMapWidth(), m_Aura->m_CurrentGame->GetMap()->GetMapHeight(), m_Aura->m_CurrentGame->GetGameName(), "Clan 007", 0, m_Aura->m_CurrentGame->GetMap()->GetMapPath(), m_Aura->m_CurrentGame->GetMap()->GetMapCRC(), MAX_SLOTS, MAX_SLOTS, m_Aura->m_CurrentGame->GetHostPort(), m_Aura->m_CurrentGame->GetHostCounter() & 0x0FFFFFFF, m_Aura->m_CurrentGame->GetEntryKey()));
m_Aura->m_UDPSocket->SendTo(IP, Port, m_Aura->m_CurrentGame->GetProtocol()->SEND_W3GS_GAMEINFO(m_Aura->m_TFT, m_Aura->m_LANWar3Version, CreateByteArray(static_cast<uint32_t>(MAPGAMETYPE_UNKNOWN0), false), m_Aura->m_CurrentGame->GetMap()->GetMapGameFlags(), m_Aura->m_CurrentGame->GetMap()->GetMapWidth(), m_Aura->m_CurrentGame->GetMap()->GetMapHeight(), m_Aura->m_CurrentGame->GetGameName(), "Clan 007", 0, m_Aura->m_CurrentGame->GetMap()->GetMapPath(), m_Aura->m_CurrentGame->GetMap()->GetMapCRC(), MAX_SLOTS, MAX_SLOTS, m_Aura->m_CurrentGame->GetHostPort(), m_Aura->m_CurrentGame->GetHostCounter() & 0x0FFFFFFF, m_Aura->m_CurrentGame->GetEntryKey()));
}

break;
Expand Down
17 changes: 13 additions & 4 deletions src/bnetprotocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,10 +558,11 @@ std::vector<uint8_t> CBNETProtocol::SEND_SID_NETGAMEPORT(uint16_t serverPort)
return packet;
}

std::vector<uint8_t> CBNETProtocol::SEND_SID_AUTH_INFO(uint8_t ver, uint32_t localeID, const string& countryAbbrev, const string& country)
std::vector<uint8_t> CBNETProtocol::SEND_SID_AUTH_INFO(uint8_t ver, bool TFT, uint32_t localeID, const string& countryAbbrev, const string& country)
{
const uint8_t ProtocolID[] = {0, 0, 0, 0};
const uint8_t PlatformID[] = {54, 56, 88, 73}; // "IX86"
const uint8_t ProductID_ROC[] = {51, 82, 65, 87}; // "WAR3"
const uint8_t ProductID_TFT[] = {80, 88, 51, 87}; // "W3XP"
const uint8_t Version[] = {ver, 0, 0, 0};
const uint8_t Language[] = {83, 85, 110, 101}; // "enUS"
Expand All @@ -575,7 +576,12 @@ std::vector<uint8_t> CBNETProtocol::SEND_SID_AUTH_INFO(uint8_t ver, uint32_t loc
packet.push_back(0); // packet length will be assigned later
AppendByteArray(packet, ProtocolID, 4); // Protocol ID
AppendByteArray(packet, PlatformID, 4); // Platform ID
AppendByteArray(packet, ProductID_TFT, 4); // Product ID (TFT)

if (TFT)
AppendByteArray(packet, ProductID_TFT, 4); // Product ID (TFT)
else
AppendByteArray(packet, ProductID_ROC, 4); // Product ID (ROC)

AppendByteArray(packet, Version, 4); // Version
AppendByteArray(packet, Language, 4); // Language (hardcoded as enUS to ensure battle.net sends the bot messages in English)
AppendByteArray(packet, LocalIP, 4); // Local IP for NAT compatibility
Expand All @@ -589,7 +595,7 @@ std::vector<uint8_t> CBNETProtocol::SEND_SID_AUTH_INFO(uint8_t ver, uint32_t loc
return packet;
}

std::vector<uint8_t> CBNETProtocol::SEND_SID_AUTH_CHECK(const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& exeVersion, const std::vector<uint8_t>& exeVersionHash, const std::vector<uint8_t>& keyInfoROC, const std::vector<uint8_t>& keyInfoTFT, const string& exeInfo, const string& keyOwnerName)
std::vector<uint8_t> CBNETProtocol::SEND_SID_AUTH_CHECK(bool TFT, const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& exeVersion, const std::vector<uint8_t>& exeVersionHash, const std::vector<uint8_t>& keyInfoROC, const std::vector<uint8_t>& keyInfoTFT, const string& exeInfo, const string& keyOwnerName)
{
std::vector<uint8_t> packet;

Expand All @@ -607,7 +613,10 @@ std::vector<uint8_t> CBNETProtocol::SEND_SID_AUTH_CHECK(const std::vector<uint8_
AppendByteArray(packet, NumKeys, false); // number of keys in this packet
AppendByteArray(packet, static_cast<uint32_t>(0), false); // boolean Using Spawn (32 bit)
AppendByteArrayFast(packet, keyInfoROC); // ROC Key Info
AppendByteArrayFast(packet, keyInfoTFT); // TFT Key Info

if (TFT)
AppendByteArrayFast(packet, keyInfoTFT); // TFT Key Info

AppendByteArrayFast(packet, exeInfo); // EXE Info
AppendByteArrayFast(packet, keyOwnerName); // CD Key Owner Name
AssignLength(packet);
Expand Down
4 changes: 2 additions & 2 deletions src/bnetprotocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ class CBNETProtocol
std::vector<uint8_t> SEND_SID_PING(const std::vector<uint8_t>& pingValue);
std::vector<uint8_t> SEND_SID_LOGONRESPONSE(const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& serverToken, const std::vector<uint8_t>& passwordHash, const std::string& accountName);
std::vector<uint8_t> SEND_SID_NETGAMEPORT(uint16_t serverPort);
std::vector<uint8_t> SEND_SID_AUTH_INFO(uint8_t ver, uint32_t localeID, const std::string& countryAbbrev, const std::string& country);
std::vector<uint8_t> SEND_SID_AUTH_CHECK(const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& exeVersion, const std::vector<uint8_t>& exeVersionHash, const std::vector<uint8_t>& keyInfoROC, const std::vector<uint8_t>& keyInfoTFT, const std::string& exeInfo, const std::string& keyOwnerName);
std::vector<uint8_t> SEND_SID_AUTH_INFO(uint8_t ver, bool TFT, uint32_t localeID, const std::string& countryAbbrev, const std::string& country);
std::vector<uint8_t> SEND_SID_AUTH_CHECK(bool TFT, const std::vector<uint8_t>& clientToken, const std::vector<uint8_t>& exeVersion, const std::vector<uint8_t>& exeVersionHash, const std::vector<uint8_t>& keyInfoROC, const std::vector<uint8_t>& keyInfoTFT, const std::string& exeInfo, const std::string& keyOwnerName);
std::vector<uint8_t> SEND_SID_AUTH_ACCOUNTLOGON(const std::vector<uint8_t>& clientPublicKey, const std::string& accountName);
std::vector<uint8_t> SEND_SID_AUTH_ACCOUNTLOGONPROOF(const std::vector<uint8_t>& clientPasswordProof);
std::vector<uint8_t> SEND_SID_FRIENDLIST();
Expand Down
6 changes: 3 additions & 3 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ bool CGame::Update(void* fd, void* send_fd)
// note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect)
// note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect)

m_Aura->m_UDPSocket->Broadcast(6112, m_Protocol->SEND_W3GS_GAMEINFO(m_Aura->m_LANWar3Version, CreateByteArray(static_cast<uint32_t>(MAPGAMETYPE_UNKNOWN0), false), m_Map->GetMapGameFlags(), m_Map->GetMapWidth(), m_Map->GetMapHeight(), m_GameName, "Clan 007", 0, m_Map->GetMapPath(), m_Map->GetMapCRC(), MAX_SLOTS, MAX_SLOTS, m_HostPort, m_HostCounter & 0x0FFFFFFF, m_EntryKey));
m_Aura->m_UDPSocket->Broadcast(6112, m_Protocol->SEND_W3GS_GAMEINFO(m_Aura->m_TFT, m_Aura->m_LANWar3Version, CreateByteArray(static_cast<uint32_t>(MAPGAMETYPE_UNKNOWN0), false), m_Map->GetMapGameFlags(), m_Map->GetMapWidth(), m_Map->GetMapHeight(), m_GameName, "Clan 007", 0, m_Map->GetMapPath(), m_Map->GetMapCRC(), MAX_SLOTS, MAX_SLOTS, m_HostPort, m_HostCounter & 0x0FFFFFFF, m_EntryKey));
}

m_LastPingTime = Time;
Expand Down Expand Up @@ -2686,8 +2686,8 @@ bool CGame::EventPlayerBotCommand(CGamePlayer* player, string& command, string&

// note: the PrivateGame flag is not set when broadcasting to LAN (as you might expect)
// note: we do not use m_Map->GetMapGameType because none of the filters are set when broadcasting to LAN (also as you might expect)
m_Aura->m_UDPSocket->SendTo(IP, Port, m_Protocol->SEND_W3GS_GAMEINFO(m_Aura->m_LANWar3Version, CreateByteArray(static_cast<uint32_t>(MAPGAMETYPE_UNKNOWN0), false), m_Map->GetMapGameFlags(), m_Map->GetMapWidth(), m_Map->GetMapHeight(), m_GameName, "Clan 007", 0, m_Map->GetMapPath(), m_Map->GetMapCRC(), MAX_SLOTS, MAX_SLOTS, m_HostPort, m_HostCounter & 0x0FFFFFFF, m_EntryKey));

m_Aura->m_UDPSocket->SendTo(IP, Port, m_Protocol->SEND_W3GS_GAMEINFO(m_Aura->m_TFT, m_Aura->m_LANWar3Version, CreateByteArray(static_cast<uint32_t>(MAPGAMETYPE_UNKNOWN0), false), m_Map->GetMapGameFlags(), m_Map->GetMapWidth(), m_Map->GetMapHeight(), m_GameName, "Clan 007", 0, m_Map->GetMapPath(), m_Map->GetMapCRC(), MAX_SLOTS, MAX_SLOTS, m_HostPort, m_HostCounter & 0x0FFFFFFF, m_EntryKey));
}

break;
Expand Down
32 changes: 28 additions & 4 deletions src/gameprotocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,10 +469,13 @@ std::vector<uint8_t> CGameProtocol::SEND_W3GS_STOP_LAG(CGamePlayer* player)
return packet;
}

std::vector<uint8_t> CGameProtocol::SEND_W3GS_GAMEINFO(uint8_t war3Version, const std::vector<uint8_t>& mapGameType, const std::vector<uint8_t>& mapFlags, const std::vector<uint8_t>& mapWidth, const std::vector<uint8_t>& mapHeight, const string& gameName, const string& hostName, uint32_t upTime, const string& mapPath, const std::vector<uint8_t>& mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter, uint32_t entryKey)
std::vector<uint8_t> CGameProtocol::SEND_W3GS_GAMEINFO(bool TFT, uint8_t war3Version, const std::vector<uint8_t>& mapGameType, const std::vector<uint8_t>& mapFlags, const std::vector<uint8_t>& mapWidth, const std::vector<uint8_t>& mapHeight, const string& gameName, const string& hostName, uint32_t upTime, const string& mapPath, const std::vector<uint8_t>& mapCRC, uint32_t slotsTotal, uint32_t slotsOpen, uint16_t port, uint32_t hostCounter, uint32_t entryKey)
{
if (mapGameType.size() == 4 && mapFlags.size() == 4 && mapWidth.size() == 2 && mapHeight.size() == 2 && !gameName.empty() && !hostName.empty() && !mapPath.empty() && mapCRC.size() == 4)
{
const uint8_t ProductID_ROC[] = {51, 82, 65, 87}; // "WAR3"
const uint8_t ProductID_TFT[] = {80, 88, 51, 87}; // "W3XP"
const uint8_t Version[] = {war3Version, 0, 0, 0};
const uint8_t Unknown2[] = {1, 0, 0, 0};

// make the stat string
Expand All @@ -489,8 +492,14 @@ std::vector<uint8_t> CGameProtocol::SEND_W3GS_GAMEINFO(uint8_t war3Version, cons
StatString = EncodeStatString(StatString);

// make the rest of the packet
std::vector<uint8_t> packet = {W3GS_HEADER_CONSTANT, W3GS_GAMEINFO, 0, 0};

std::vector<uint8_t> packet = {W3GS_HEADER_CONSTANT, W3GS_GAMEINFO, 0, 0, 80, 88, 51, 87, war3Version, 0, 0, 0};
if (TFT)
AppendByteArray(packet, ProductID_TFT, 4); // Product ID (TFT)
else
AppendByteArray(packet, ProductID_ROC, 4); // Product ID (ROC)

AppendByteArray(packet, Version, 4);
AppendByteArray(packet, hostCounter, false); // Host Counter
AppendByteArray(packet, entryKey, false); // Entry Key
AppendByteArrayFast(packet, gameName); // Game Name
Expand All @@ -511,9 +520,24 @@ std::vector<uint8_t> CGameProtocol::SEND_W3GS_GAMEINFO(uint8_t war3Version, cons
return std::vector<uint8_t>();
}

std::vector<uint8_t> CGameProtocol::SEND_W3GS_CREATEGAME(uint8_t war3Version)
std::vector<uint8_t> CGameProtocol::SEND_W3GS_CREATEGAME(bool TFT, uint8_t war3Version)
{
return std::vector<uint8_t>{W3GS_HEADER_CONSTANT, W3GS_CREATEGAME, 16, 0, 80, 88, 51, 87, war3Version, 0, 0, 0, 1, 0, 0, 0};
const uint8_t ProductID_ROC[] = { 51, 82, 65, 87 }; // "WAR3"
const uint8_t ProductID_TFT[] = { 80, 88, 51, 87 }; // "W3XP"
const uint8_t Version[] = { war3Version, 0, 0, 0 };
const uint8_t Unknown2[] = { 1, 0, 0, 0 };

std::vector<uint8_t> packet = {W3GS_HEADER_CONSTANT, W3GS_CREATEGAME, 16, 0};

if (TFT)
AppendByteArray(packet, ProductID_TFT, 4); // Product ID (TFT)
else
AppendByteArray(packet, ProductID_ROC, 4); // Product ID (ROC)

AppendByteArray(packet, Version, 4);
AppendByteArray(packet, Unknown2, 4);

return packet;
}

std::vector<uint8_t> CGameProtocol::SEND_W3GS_REFRESHGAME(uint32_t players, uint32_t playerSlots)
Expand Down
Loading