add marketplace emulation
This commit is contained in:
parent
d0bff32467
commit
1e9aee1227
@ -501,7 +501,7 @@ namespace demonware
|
||||
void post_unpack() override
|
||||
{
|
||||
#ifdef DW_DEBUG
|
||||
//utils::hook::jump(0x141285040, bd_logger_stub, true);
|
||||
utils::hook::jump(0x141285040, bd_logger_stub, true);
|
||||
#endif
|
||||
|
||||
utils::hook::set<uint8_t>(0x14B5BB96F, 0x0); // CURLOPT_SSL_VERIFYPEER
|
||||
|
@ -267,7 +267,8 @@ namespace patches
|
||||
dvars::override::register_int("dvl", 0, 0, 0, game::DVAR_FLAG_READ);
|
||||
|
||||
// killswitches
|
||||
dvars::override::register_bool("killswitch_store", true, game::DVAR_FLAG_READ);
|
||||
dvars::override::register_bool("mission_team_contracts_enabled", true, game::DVAR_FLAG_READ);
|
||||
//dvars::override::register_bool("killswitch_store", true, game::DVAR_FLAG_READ);
|
||||
dvars::override::register_bool("killswitch_matchID", true, game::DVAR_FLAG_READ);
|
||||
|
||||
// announcer packs
|
||||
|
@ -128,6 +128,24 @@ namespace demonware
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_struct(void* output)
|
||||
{
|
||||
if (!this->read_data_type(BD_BB_STRUCTURED_DATA_TYPE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int size;
|
||||
this->read_uint32(&size);
|
||||
|
||||
auto data = const_cast<char*>(this->buffer_.data()) + this->current_byte_;
|
||||
memcpy(output, data, size);
|
||||
|
||||
this->current_byte_ += size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_data_type(const unsigned char expected)
|
||||
{
|
||||
if (!this->use_data_types_) return true;
|
||||
@ -248,6 +266,14 @@ namespace demonware
|
||||
return this->write(length, data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_struct(void* data, const int length)
|
||||
{
|
||||
this->write_data_type(BD_BB_STRUCTURED_DATA_TYPE);
|
||||
this->write_uint32(length);
|
||||
|
||||
return this->write(length, data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_array_header(const unsigned char type, const unsigned int element_count,
|
||||
const unsigned int element_size)
|
||||
{
|
||||
|
@ -26,6 +26,7 @@ namespace demonware
|
||||
bool read_string(std::string* output);
|
||||
bool read_blob(char** output, int* length);
|
||||
bool read_blob(std::string* output);
|
||||
bool read_struct(void* output);
|
||||
bool read_data_type(unsigned char expected);
|
||||
|
||||
bool read_array_header(unsigned char expected, unsigned int* element_count,
|
||||
@ -46,6 +47,7 @@ namespace demonware
|
||||
bool write_string(const std::string& data);
|
||||
bool write_blob(const char* data, int length);
|
||||
bool write_blob(const std::string& data);
|
||||
bool write_struct(void* data, int length);
|
||||
|
||||
bool write_array_header(unsigned char type, unsigned int element_count, unsigned int element_size);
|
||||
|
||||
|
@ -246,10 +246,10 @@ namespace demonware
|
||||
class bdContextUserStorageFileInfo final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
std::uint32_t create_time;
|
||||
std::uint32_t modifed_time;
|
||||
uint32_t create_time;
|
||||
uint32_t modifed_time;
|
||||
bool priv;
|
||||
std::uint64_t owner_id;
|
||||
uint64_t owner_id;
|
||||
std::string account_type;
|
||||
std::string filename;
|
||||
|
||||
@ -277,7 +277,7 @@ namespace demonware
|
||||
class bdPublicProfileInfo final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
std::uint64_t m_entityID;
|
||||
uint64_t m_entityID;
|
||||
std::string m_memberplayer_card;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
@ -346,18 +346,87 @@ namespace demonware
|
||||
{
|
||||
public:
|
||||
uint64_t user_id;
|
||||
int64_t performance;
|
||||
float performance;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->write_uint64(this->user_id);
|
||||
buffer->write_int64(this->performance);
|
||||
buffer->write_float(this->performance);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->read_uint64(&this->user_id);
|
||||
buffer->read_int64(&this->performance);
|
||||
buffer->read_float(&this->performance);
|
||||
}
|
||||
};
|
||||
|
||||
class bdRewardEvent final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
uint32_t push_type;
|
||||
unsigned char r2;
|
||||
uint64_t user_id;
|
||||
std::string platform1;
|
||||
std::string platform2;
|
||||
int32_t rewardEventType;
|
||||
uint32_t r7;
|
||||
int32_t r8;
|
||||
std::string json_buffer;
|
||||
|
||||
void serialize(byte_buffer* data) override
|
||||
{
|
||||
data->write_uint32(push_type);
|
||||
data->write_ubyte(r2);
|
||||
data->write_uint64(user_id);
|
||||
data->write_string(platform1);
|
||||
data->write_string(platform2);
|
||||
data->write_int32(rewardEventType);
|
||||
data->write_uint32(r7);
|
||||
data->write_int32(r8);
|
||||
data->write_string(json_buffer);
|
||||
}
|
||||
};
|
||||
|
||||
class bdMarketplaceInventory final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
uint64_t m_playerId;
|
||||
std::string unk;
|
||||
uint32_t m_itemId;
|
||||
uint32_t m_itemQuantity;
|
||||
uint32_t m_itemXp;
|
||||
std::string m_itemData;
|
||||
uint32_t m_expireDateTime;
|
||||
int64_t m_expiryDuration;
|
||||
uint16_t m_collisionField;
|
||||
uint32_t m_modDateTime;
|
||||
|
||||
void serialize(byte_buffer* data) override
|
||||
{
|
||||
data->write_uint64(m_playerId);
|
||||
data->write_string(unk);
|
||||
data->write_uint32(m_itemId);
|
||||
data->write_uint32(m_itemQuantity);
|
||||
data->write_uint32(m_itemXp);
|
||||
data->write_blob(m_itemData);
|
||||
data->write_uint32(m_expireDateTime);
|
||||
data->write_int64(m_expiryDuration);
|
||||
data->write_uint16(m_collisionField);
|
||||
data->write_uint32(m_modDateTime);
|
||||
}
|
||||
};
|
||||
|
||||
class bdMarketplaceCurrency final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
std::uint8_t m_currencyId;
|
||||
std::uint32_t m_value;
|
||||
|
||||
void serialize(byte_buffer* data) override
|
||||
{
|
||||
data->write_ubyte(m_currencyId);
|
||||
data->write_uint32(m_value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
//#define DW_DEBUG
|
||||
#define DW_DEBUG
|
||||
|
||||
#include "game/types/demonware.hpp"
|
||||
using namespace game::demonware;
|
||||
@ -13,4 +13,6 @@ using namespace game::demonware;
|
||||
#include "reply.hpp"
|
||||
#include "service.hpp"
|
||||
|
||||
#include "loot/loot.hpp"
|
||||
|
||||
#include "services.hpp"
|
621
src/client/game/demonware/loot/loot.cpp
Normal file
621
src/client/game/demonware/loot/loot.cpp
Normal file
@ -0,0 +1,621 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../dw_include.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "utils/io.hpp"
|
||||
#include "utils/json.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
namespace loot
|
||||
{
|
||||
const std::string& json_data_path = "iw7-mod/players2/user/loot/loot.json";
|
||||
nlohmann::json json_buffer;
|
||||
|
||||
namespace csv
|
||||
{
|
||||
struct LootCsv
|
||||
{
|
||||
std::string file;
|
||||
std::uint32_t index;
|
||||
std::uint32_t quality;
|
||||
std::uint32_t salvageReturned;
|
||||
std::uint32_t cost;
|
||||
};
|
||||
|
||||
struct LootCrateCsv
|
||||
{
|
||||
std::string file;
|
||||
std::uint32_t index;
|
||||
std::uint32_t cost;
|
||||
std::uint32_t premiumCost;
|
||||
std::uint32_t CODPointsSKU;
|
||||
};
|
||||
|
||||
LootCsv weapon
|
||||
{
|
||||
.file = "mp/loot/iw7_weapon_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 6,
|
||||
.salvageReturned = 3,
|
||||
.cost = 4,
|
||||
};
|
||||
|
||||
LootCsv killstreak
|
||||
{
|
||||
.file = "mp/loot/iw7_killstreak_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 3,
|
||||
.cost = 4,
|
||||
};
|
||||
|
||||
LootCsv consumable
|
||||
{
|
||||
.file = "mp/loot/iw7_consumable_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_attachments
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_attachments_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_calling_cards
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_calling_cards_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_camos
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_camos_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_emblems
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_emblems_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_emotes
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_emotes_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_heroes
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_heroes_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_reticles
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_reticles_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv cosmetic_rigs
|
||||
{
|
||||
.file = "mp/loot/iw7_cosmetic_rigs_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 4,
|
||||
.cost = 5,
|
||||
};
|
||||
|
||||
LootCsv zombiefatefortune
|
||||
{
|
||||
.file = "cp/loot/iw7_zombiefatefortune_loot_master.csv",
|
||||
.index = 0,
|
||||
.quality = 2,
|
||||
.salvageReturned = 0xFF,
|
||||
.cost = 0xFF,
|
||||
};
|
||||
|
||||
LootCrateCsv loot_crate
|
||||
{
|
||||
.file = "mp/loot/iw7_loot_crate_loot_master.csv",
|
||||
.index = 0,
|
||||
.cost = 3,
|
||||
.premiumCost = 4,
|
||||
.CODPointsSKU = 5,
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<std::uint32_t> lootmap_weapon;
|
||||
std::vector<std::uint32_t> lootmap_killstreak;
|
||||
std::vector<std::uint32_t> lootmap_consumable;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_attachments;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_calling_cards;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_camos;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_emblems;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_emotes;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_heroes;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_reticles;
|
||||
std::vector<std::uint32_t> lootmap_cosmetic_rigs;
|
||||
std::vector<std::uint32_t> lootmap_zombiefatefortune;
|
||||
|
||||
std::unordered_map<std::uint32_t, Item> m_lootmap;
|
||||
|
||||
struct LootCrate
|
||||
{
|
||||
std::uint32_t cost;
|
||||
std::uint32_t premiumCost;
|
||||
std::uint32_t salvageCost;
|
||||
};
|
||||
|
||||
std::unordered_map<std::uint32_t, LootCrate> lootcrates;
|
||||
|
||||
void read_loot_csv(csv::LootCsv& csv, std::vector<std::uint32_t>& lootmap)
|
||||
{
|
||||
lootmap.clear();
|
||||
|
||||
const auto asset = game::DB_FindXAssetHeader(game::ASSET_TYPE_STRINGTABLE, csv.file.data(), 0).stringTable;
|
||||
|
||||
for (auto row = 0; row < asset->rowCount; row++)
|
||||
{
|
||||
const std::uint32_t id = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv.index));
|
||||
const std::uint32_t quality = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv.quality));
|
||||
|
||||
std::uint32_t salvageReturned = 0;
|
||||
std::uint32_t cost = 0;
|
||||
if (csv.salvageReturned != 0xFF)
|
||||
{
|
||||
salvageReturned = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv.salvageReturned));
|
||||
}
|
||||
if (csv.cost != 0xFF)
|
||||
{
|
||||
cost = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv.cost));
|
||||
}
|
||||
|
||||
const Item loot = { id, quality, salvageReturned, cost };
|
||||
m_lootmap[id] = loot;
|
||||
lootmap.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
void read_weapon_csv()
|
||||
{
|
||||
read_loot_csv(csv::weapon, lootmap_weapon);
|
||||
}
|
||||
|
||||
void read_killstreak_csv()
|
||||
{
|
||||
read_loot_csv(csv::killstreak, lootmap_killstreak);
|
||||
}
|
||||
|
||||
void read_consumable_csv()
|
||||
{
|
||||
read_loot_csv(csv::consumable, lootmap_consumable);
|
||||
}
|
||||
|
||||
void read_cosmetic_attachments_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_attachments, lootmap_cosmetic_attachments);
|
||||
}
|
||||
|
||||
void read_cosmetic_calling_cards_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_calling_cards, lootmap_cosmetic_calling_cards);
|
||||
}
|
||||
|
||||
void read_cosmetic_camos_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_camos, lootmap_cosmetic_camos);
|
||||
}
|
||||
|
||||
void read_cosmetic_emblems_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_emblems, lootmap_cosmetic_emblems);
|
||||
}
|
||||
|
||||
void read_cosmetic_emotes_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_emotes, lootmap_cosmetic_emotes);
|
||||
}
|
||||
|
||||
void read_cosmetic_heroes_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_heroes, lootmap_cosmetic_heroes);
|
||||
}
|
||||
|
||||
void read_cosmetic_reticles_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_reticles, lootmap_cosmetic_reticles);
|
||||
}
|
||||
|
||||
void read_cosmetic_rigs_csv()
|
||||
{
|
||||
read_loot_csv(csv::cosmetic_rigs, lootmap_cosmetic_rigs);
|
||||
}
|
||||
|
||||
void read_zombiefatefortune_csv()
|
||||
{
|
||||
read_loot_csv(csv::zombiefatefortune, lootmap_zombiefatefortune);
|
||||
}
|
||||
|
||||
void read_loot_crate_csv()
|
||||
{
|
||||
lootcrates.clear();
|
||||
|
||||
const auto asset = game::DB_FindXAssetHeader(game::ASSET_TYPE_STRINGTABLE, csv::loot_crate.file.data(), 0).stringTable;
|
||||
|
||||
for (auto row = 0; row < asset->rowCount; row++)
|
||||
{
|
||||
const std::uint32_t id = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv::loot_crate.index));
|
||||
const std::uint32_t cost = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv::loot_crate.cost));
|
||||
const std::uint32_t premiumCost = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv::loot_crate.premiumCost));
|
||||
const std::uint32_t CODPointsSKU = std::atoi(game::StringTable_GetColumnValueForRow(asset, row, csv::loot_crate.CODPointsSKU));
|
||||
lootcrates[id] = { cost, premiumCost, CODPointsSKU };
|
||||
}
|
||||
}
|
||||
|
||||
void cache_loot()
|
||||
{
|
||||
static bool once = false;
|
||||
if (once) return;
|
||||
once = true;
|
||||
|
||||
m_lootmap.clear();
|
||||
|
||||
// mp
|
||||
read_weapon_csv();
|
||||
read_killstreak_csv();
|
||||
read_consumable_csv();
|
||||
read_cosmetic_attachments_csv();
|
||||
read_cosmetic_calling_cards_csv();
|
||||
read_cosmetic_camos_csv();
|
||||
read_cosmetic_emblems_csv();
|
||||
read_cosmetic_emotes_csv();
|
||||
read_cosmetic_heroes_csv();
|
||||
read_cosmetic_reticles_csv();
|
||||
read_cosmetic_rigs_csv();
|
||||
|
||||
// cp
|
||||
read_zombiefatefortune_csv();
|
||||
|
||||
// crates
|
||||
read_loot_crate_csv();
|
||||
}
|
||||
|
||||
// Brought to you by ChatGPT
|
||||
std::vector<Item> get_random_loot_from_map(std::vector<std::uint32_t>& lootmap, const size_t itemAmount, const float luckFactor, std::uint32_t quaranteedQuality = 0)
|
||||
{
|
||||
// Edge case: if the vector is empty
|
||||
if (lootmap.empty()) {
|
||||
throw std::runtime_error("Lootmap is empty");
|
||||
}
|
||||
|
||||
// Edge case: if itemAmount is more than the number of available items
|
||||
if (itemAmount > lootmap.size()) {
|
||||
throw std::runtime_error("Item amount exceeds the number of available items");
|
||||
}
|
||||
|
||||
// Validate the luckFactor (should be positive)
|
||||
if (luckFactor <= 0) {
|
||||
throw std::invalid_argument("Luck factor must be greater than zero");
|
||||
}
|
||||
|
||||
// Calculate the total weight based on adjusted rarity values
|
||||
double totalWeight = 0;
|
||||
std::vector<double> adjustedWeights(lootmap.size());
|
||||
|
||||
for (size_t i = 0; i < lootmap.size(); ++i) {
|
||||
if (!get_loot(lootmap[i]).quality) continue;
|
||||
|
||||
// Calculate weight as inverse of rarity, adjusted by luckFactor
|
||||
adjustedWeights[i] = 1.0 / std::pow(get_loot(lootmap[i]).quality, luckFactor);
|
||||
totalWeight += adjustedWeights[i];
|
||||
}
|
||||
|
||||
assert(adjustedWeights.size() >= itemAmount);
|
||||
|
||||
// Set up the random number generator
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> dis(0.0, totalWeight);
|
||||
|
||||
std::vector<Item> selectedItems;
|
||||
|
||||
// Select items
|
||||
while (selectedItems.size() < itemAmount) {
|
||||
double randomValue = dis(gen);
|
||||
double cumulativeWeight = 0;
|
||||
|
||||
// Find the item corresponding to the random value
|
||||
for (size_t i = 0; i < lootmap.size(); ++i) {
|
||||
cumulativeWeight += adjustedWeights[i];
|
||||
if (randomValue < cumulativeWeight) {
|
||||
if (quaranteedQuality && get_loot(lootmap[i]).quality < quaranteedQuality)
|
||||
continue;
|
||||
else
|
||||
quaranteedQuality = 0;
|
||||
|
||||
// Add item to the result if it's not already selected
|
||||
if (std::find(selectedItems.begin(), selectedItems.end(), get_loot(lootmap[i])) == selectedItems.end()) {
|
||||
selectedItems.push_back(get_loot(lootmap[i]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selectedItems;
|
||||
}
|
||||
|
||||
std::vector<std::uint32_t> combined_mp_lootmaps;
|
||||
std::vector<std::uint32_t> combine_mp_lootmaps()
|
||||
{
|
||||
std::vector<std::uint32_t>& lootmap = combined_mp_lootmaps;
|
||||
if (!combined_mp_lootmaps.empty())
|
||||
{
|
||||
return combined_mp_lootmaps;
|
||||
}
|
||||
|
||||
lootmap.insert(lootmap.end(), lootmap_weapon.begin(), lootmap_weapon.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_killstreak.begin(), lootmap_killstreak.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_consumable.begin(), lootmap_consumable.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_attachments.begin(), lootmap_cosmetic_attachments.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_calling_cards.begin(), lootmap_cosmetic_calling_cards.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_camos.begin(), lootmap_cosmetic_camos.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_emblems.begin(), lootmap_cosmetic_emblems.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_emotes.begin(), lootmap_cosmetic_emotes.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_heroes.begin(), lootmap_cosmetic_heroes.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_reticles.begin(), lootmap_cosmetic_reticles.end());
|
||||
lootmap.insert(lootmap.end(), lootmap_cosmetic_rigs.begin(), lootmap_cosmetic_rigs.end());
|
||||
return lootmap;
|
||||
}
|
||||
|
||||
std::vector<std::uint32_t> get_all_lootmaps()
|
||||
{
|
||||
cache_loot();
|
||||
|
||||
std::vector<std::uint32_t> lootmap = combine_mp_lootmaps();
|
||||
lootmap.insert(lootmap.end(), lootmap_zombiefatefortune.begin(), lootmap_zombiefatefortune.end());
|
||||
return lootmap;
|
||||
}
|
||||
|
||||
std::vector<Item> all_loot;
|
||||
std::vector<Item> get_all_loot()
|
||||
{
|
||||
if (!all_loot.empty())
|
||||
{
|
||||
return all_loot;
|
||||
}
|
||||
|
||||
std::vector<Item>& items = all_loot;
|
||||
auto lootmap = get_all_lootmaps();
|
||||
for (size_t i = 0; i < lootmap.size(); i++)
|
||||
{
|
||||
items.push_back(get_loot(lootmap[i]));
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
std::vector<Item> get_all_loot_owned()
|
||||
{
|
||||
auto lootmap = get_all_lootmaps();
|
||||
std::vector<Item> items{};
|
||||
for (size_t i = 0; i < lootmap.size(); i++)
|
||||
{
|
||||
if (get_item_balance(lootmap[i]))
|
||||
{
|
||||
items.push_back(get_loot(lootmap[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
Item get_loot(const std::uint32_t item_id)
|
||||
{
|
||||
if (m_lootmap.contains(item_id))
|
||||
{
|
||||
return m_lootmap[item_id];
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<Item> get_random_loot_CommonCrate(const float scale = 1.0f, std::uint32_t quality = 0)
|
||||
{
|
||||
std::vector<std::uint32_t> lootmap = combine_mp_lootmaps();
|
||||
|
||||
return get_random_loot_from_map(lootmap, 3, scale, quality);
|
||||
}
|
||||
|
||||
std::vector<Item> get_random_loot_RareCrate()
|
||||
{
|
||||
return get_random_loot_CommonCrate(0.34f, 2);
|
||||
}
|
||||
|
||||
std::vector<Item> get_random_loot_ZombieCrate(const float scale = 1.0f, std::uint32_t quality = 0)
|
||||
{
|
||||
std::vector<std::uint32_t> lootmap = combine_mp_lootmaps();
|
||||
|
||||
auto mp = get_random_loot_from_map(lootmap, 2, scale);
|
||||
auto cp = get_random_loot_from_map(lootmap_zombiefatefortune, 1, scale);
|
||||
|
||||
std::vector<Item> items;
|
||||
items.push_back(mp[0]);
|
||||
items.push_back(mp[1]);
|
||||
items.push_back(cp[0]);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
std::vector<Item> get_random_loot_ZombieRareCrate()
|
||||
{
|
||||
return get_random_loot_ZombieCrate(0.34f, 2);
|
||||
}
|
||||
|
||||
std::vector<Item> get_random_loot_ZombieCardPack(const float scale = 1.0f, std::uint32_t quality = 0)
|
||||
{
|
||||
return get_random_loot_from_map(lootmap_zombiefatefortune, 3, scale, quality);
|
||||
}
|
||||
|
||||
std::vector<Item> get_random_loot_ZombieRareCardPack()
|
||||
{
|
||||
return get_random_loot_ZombieCardPack(0.34f, 2);
|
||||
}
|
||||
|
||||
std::vector<Item> get_random_loot(const std::uint32_t lootbox_id)
|
||||
{
|
||||
cache_loot();
|
||||
|
||||
switch (lootbox_id)
|
||||
{
|
||||
case 70000: // CommonCrate
|
||||
return get_random_loot_CommonCrate();
|
||||
case 70001: // RareCrate
|
||||
return get_random_loot_RareCrate();
|
||||
case 70002: // ZombieCrate
|
||||
return get_random_loot_ZombieCrate();
|
||||
case 70003: // ZombieRareCrate
|
||||
return get_random_loot_ZombieRareCrate();
|
||||
case 70004: // ZombieCardPack
|
||||
return get_random_loot_ZombieCardPack();
|
||||
case 70005: // ZombieRareCardPack
|
||||
return get_random_loot_ZombieRareCardPack();
|
||||
default:
|
||||
printf("[DW]: Missing LootCrate logic for %d, using CommonCrate\n", lootbox_id);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t get_lootcrate_cost(const std::uint32_t id, const std::uint32_t type)
|
||||
{
|
||||
if (lootcrates.contains(id))
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case CurrencyType::keys:
|
||||
return lootcrates[id].cost;
|
||||
break;
|
||||
case CurrencyType::codpoints:
|
||||
return lootcrates[id].premiumCost;
|
||||
break;
|
||||
case CurrencyType::salvage:
|
||||
return lootcrates[id].salvageCost;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T> void json_put(nlohmann::json& field, T value)
|
||||
{
|
||||
field = value;
|
||||
}
|
||||
|
||||
template <typename T> void json_add(nlohmann::json& field, T value)
|
||||
{
|
||||
if (!field.is_null())
|
||||
{
|
||||
field = field.get<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
field = value;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> T json_read(nlohmann::json& field)
|
||||
{
|
||||
if (!field.is_null())
|
||||
{
|
||||
return field.get<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
}
|
||||
|
||||
void save_json_data()
|
||||
{
|
||||
auto dump = json_buffer.dump(4);
|
||||
utils::io::write_file(json_data_path, dump);
|
||||
}
|
||||
|
||||
void read_json_data()
|
||||
{
|
||||
if (!json_buffer.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (utils::io::file_exists(json_data_path))
|
||||
{
|
||||
auto data = utils::io::read_file(json_data_path);
|
||||
json_buffer = nlohmann::json::parse(data);
|
||||
return;
|
||||
}
|
||||
|
||||
json_buffer = {};
|
||||
|
||||
set_currency_balance(CurrencyType::keys, 9999999);
|
||||
set_currency_balance(CurrencyType::salvage, 9999);
|
||||
set_currency_balance(CurrencyType::codpoints, 99999);
|
||||
save_json_data();
|
||||
}
|
||||
|
||||
void set_item_balance(const std::uint32_t item_id, const std::uint32_t amount)
|
||||
{
|
||||
json_put(json_buffer["Loot"][std::to_string(item_id)]["Balance"], amount);
|
||||
}
|
||||
|
||||
std::uint32_t get_item_balance(const std::uint32_t item_id)
|
||||
{
|
||||
read_json_data();
|
||||
return json_read<std::uint32_t>(json_buffer["Loot"][std::to_string(item_id)]["Balance"]);
|
||||
}
|
||||
|
||||
void set_currency_balance(const std::uint32_t currency_id, const std::uint32_t amount)
|
||||
{
|
||||
json_put(json_buffer["Currency"][std::to_string(currency_id)]["Balance"], amount);
|
||||
}
|
||||
|
||||
std::uint32_t get_currency_balance(const std::uint32_t currency_id)
|
||||
{
|
||||
read_json_data();
|
||||
return json_read<std::uint32_t>(json_buffer["Currency"][std::to_string(currency_id)]["Balance"]);
|
||||
}
|
||||
|
||||
void save()
|
||||
{
|
||||
save_json_data();
|
||||
}
|
||||
}
|
||||
}
|
42
src/client/game/demonware/loot/loot.hpp
Normal file
42
src/client/game/demonware/loot/loot.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
namespace loot
|
||||
{
|
||||
struct Item
|
||||
{
|
||||
std::uint32_t id;
|
||||
std::uint32_t quality;
|
||||
std::uint32_t salvageReturned;
|
||||
std::uint32_t cost;
|
||||
|
||||
// Define equality operator for Item
|
||||
bool operator==(const Item& other) const {
|
||||
return id == other.id && quality == other.quality && salvageReturned == other.salvageReturned && cost == other.cost;
|
||||
}
|
||||
};
|
||||
|
||||
enum CurrencyType
|
||||
{
|
||||
keys = 11,
|
||||
salvage = 12,
|
||||
codpoints = 20,
|
||||
};
|
||||
|
||||
std::vector<Item> get_random_loot(const std::uint32_t lootbox_id);
|
||||
std::vector<Item> get_all_loot();
|
||||
std::vector<Item> get_all_loot_owned();
|
||||
Item get_loot(const std::uint32_t item_id);
|
||||
|
||||
std::uint32_t get_lootcrate_cost(const std::uint32_t id, const std::uint32_t type);
|
||||
|
||||
void set_item_balance(const std::uint32_t item_id, const std::uint32_t amount);
|
||||
std::uint32_t get_item_balance(const std::uint32_t item_id);
|
||||
|
||||
void set_currency_balance(const std::uint32_t currency_id, const std::uint32_t amount);
|
||||
std::uint32_t get_currency_balance(const std::uint32_t currency_id);
|
||||
|
||||
void save();
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
uint64_t service_reply::transaction_id = 0;
|
||||
|
||||
std::string unencrypted_reply::data()
|
||||
{
|
||||
byte_buffer result;
|
||||
|
@ -99,10 +99,11 @@ namespace demonware
|
||||
{
|
||||
}
|
||||
|
||||
static uint64_t transaction_id;
|
||||
|
||||
uint64_t send()
|
||||
{
|
||||
static uint64_t id = 0x0000000000000000;
|
||||
const auto transaction_id = ++id;
|
||||
transaction_id++;
|
||||
|
||||
byte_buffer buffer;
|
||||
buffer.write_uint64(transaction_id);
|
||||
@ -133,6 +134,36 @@ namespace demonware
|
||||
return transaction_id;
|
||||
}
|
||||
|
||||
uint64_t send_struct()
|
||||
{
|
||||
transaction_id++;
|
||||
|
||||
byte_buffer buffer;
|
||||
buffer.write_uint64(transaction_id);
|
||||
buffer.write_uint32(this->error_);
|
||||
buffer.write_ubyte(this->type_);
|
||||
|
||||
if (!this->error_)
|
||||
{
|
||||
if (!this->objects_.empty())
|
||||
{
|
||||
for (auto& object : this->objects_)
|
||||
{
|
||||
object->serialize(&buffer);
|
||||
}
|
||||
|
||||
this->objects_.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.write_uint64(transaction_id);
|
||||
}
|
||||
|
||||
this->reply_.send(&buffer, true);
|
||||
return transaction_id;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void add(std::unique_ptr<T>& object)
|
||||
{
|
||||
@ -140,6 +171,11 @@ namespace demonware
|
||||
this->objects_.emplace_back(std::move(object));
|
||||
}
|
||||
|
||||
void set_error(uint32_t err)
|
||||
{
|
||||
this->error_ = err;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t type_;
|
||||
uint32_t error_;
|
||||
|
@ -53,7 +53,7 @@ namespace demonware
|
||||
if (it != this->tasks_.end())
|
||||
{
|
||||
#ifdef DW_DEBUG
|
||||
printf("[DW] %s: executing task '%d'\n", name_.data(), this->task_id_);
|
||||
printf("[DW] %s: executing task '%d' (transaction ID: %llu)\n", name_.data(), this->task_id_, service_reply::transaction_id + 1);
|
||||
#endif
|
||||
|
||||
it->second(server, &buffer);
|
||||
|
@ -7,28 +7,65 @@ namespace demonware
|
||||
{
|
||||
bdMarketingComms::bdMarketingComms() : service(104, "bdMarketingComms")
|
||||
{
|
||||
this->register_task(1, &bdMarketingComms::getMessages);
|
||||
this->register_task(4, &bdMarketingComms::reportFullMessagesViewed);
|
||||
this->register_task(6, &bdMarketingComms::unk6);
|
||||
this->register_task(6, &bdMarketingComms::getMessages);
|
||||
}
|
||||
|
||||
void bdMarketingComms::getMessages(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdMarketingComms::reportFullMessagesViewed(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketingComms::reportFullMessagesViewed(service_server* server, byte_buffer* /*buffer*/) const
|
||||
#pragma pack(push, 1)
|
||||
struct bdCommsGetMessagesRequest
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
}
|
||||
char __pad0[23];
|
||||
}; static_assert(sizeof(bdCommsGetMessagesRequest) == 23);
|
||||
|
||||
void bdMarketingComms::unk6(service_server* server, byte_buffer* /*buffer*/) const
|
||||
struct unk_s
|
||||
{
|
||||
// TODO:
|
||||
server->create_reply(this->task_id(), BD_NO_FILE).send();
|
||||
char __pad0[17];
|
||||
unsigned char unk;
|
||||
};
|
||||
|
||||
struct bdCommsGetMessagesResponse
|
||||
{
|
||||
unk_s unk[1];
|
||||
}; //static_assert(sizeof(bdCommsGetMessagesResponse) == 180);
|
||||
#pragma pack(pop)
|
||||
|
||||
void bdMarketingComms::getMessages(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
bdCommsGetMessagesRequest request{};
|
||||
|
||||
class bdCommsGetMessagesResult final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
bdCommsGetMessagesResponse response;
|
||||
|
||||
void serialize(byte_buffer* data) override
|
||||
{
|
||||
data->write_struct(&response, sizeof(bdCommsGetMessagesResponse));
|
||||
}
|
||||
};
|
||||
|
||||
//buffer->read_struct(&request, sizeof(bdCommsGetMessagesRequest));
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
|
||||
auto info = std::make_unique<bdCommsGetMessagesResult>();
|
||||
|
||||
unsigned char unk[18]{ 0x0A, 0x10, 0x08, 0x00, 0x12, 0x00, 0x1A, 0x00, 0x22, 0x00, 0x2A, 0x00, 0x32, 0x00, 0x38, 0x00, 0x40, 0x01 };
|
||||
for (auto i = 0; i < 1; i++)
|
||||
{
|
||||
memcpy(info->response.unk[i].__pad0, unk, 17);
|
||||
}
|
||||
info->response.unk[0].unk = 0x01;
|
||||
|
||||
reply.add(info);
|
||||
|
||||
reply.send_struct();
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ namespace demonware
|
||||
bdMarketingComms();
|
||||
|
||||
private:
|
||||
void getMessages(service_server* server, byte_buffer* buffer) const;
|
||||
void reportFullMessagesViewed(service_server* server, byte_buffer* buffer) const;
|
||||
void unk6(service_server* server, byte_buffer* buffer) const;
|
||||
void getMessages(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
#include <utils/io.hpp>
|
||||
|
||||
#include "steam/steam.hpp"
|
||||
|
||||
#include "utils/json.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdMarketplace::bdMarketplace() : service(80, "bdMarketplace")
|
||||
@ -14,26 +18,72 @@ namespace demonware
|
||||
this->register_task(58, &bdMarketplace::validateInventoryItemsToken);
|
||||
this->register_task(60, &bdMarketplace::steamProcessDurable);
|
||||
this->register_task(85, &bdMarketplace::steamProcessDurableV2);
|
||||
this->register_task(122, &bdMarketplace::purchaseSkus);
|
||||
this->register_task(106, &bdMarketplace::purchaseSkus);
|
||||
this->register_task(130, &bdMarketplace::getBalance);
|
||||
this->register_task(132, &bdMarketplace::getBalanceV2);
|
||||
this->register_task(165, &bdMarketplace::getInventoryPaginated);
|
||||
this->register_task(193, &bdMarketplace::putPlayersInventoryItems);
|
||||
this->register_task(199, &bdMarketplace::pawnItems);
|
||||
this->register_task(232, &bdMarketplace::getEntitlements);
|
||||
}
|
||||
|
||||
void bdMarketplace::startExchangeTransaction(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdMarketplace::startExchangeTransaction(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
class bdStartExchangeTransactionResult final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
std::string m_exchangeTransactionId;
|
||||
|
||||
void serialize(byte_buffer* data) override
|
||||
{
|
||||
data->write_string(m_exchangeTransactionId);
|
||||
}
|
||||
};
|
||||
|
||||
std::string platform;
|
||||
buffer->read_string(&platform);
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
auto info = std::make_unique<bdStartExchangeTransactionResult>();
|
||||
info->m_exchangeTransactionId = std::to_string(service_reply::transaction_id);
|
||||
reply.add(info);
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketplace::purchaseOnSteamInitialize(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdMarketplace::purchaseOnSteamInitialize(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
/*class bdPurchaseInitializeResult final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
std::uint64_t m_orderId;
|
||||
|
||||
void serialize(byte_buffer* data) override
|
||||
{
|
||||
data->write_uint64(m_orderId);
|
||||
}
|
||||
};
|
||||
|
||||
std::string platform;
|
||||
std::string m_exchangeTransactionId;
|
||||
std::uint32_t skuId;
|
||||
std::string language;
|
||||
std::uint64_t userID;
|
||||
std::string contextUser;
|
||||
|
||||
buffer->read_string(&platform);
|
||||
buffer->read_string(&m_exchangeTransactionId);
|
||||
buffer->read_uint32(&skuId);
|
||||
buffer->read_string(&language);
|
||||
buffer->read_uint64(&userID);
|
||||
buffer->read_string(&contextUser);
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
auto info = std::make_unique<bdPurchaseInitializeResult>();
|
||||
info->m_orderId = 0; // would need to emulate steam microtransaction stuff...
|
||||
reply.add(info);
|
||||
reply.send();*/
|
||||
|
||||
server->create_reply(this->task_id(), BD_MARKETPLACE_STEAM_NOT_APPROVED).send();
|
||||
}
|
||||
|
||||
void bdMarketplace::purchaseOnSteamFinalize(service_server* server, byte_buffer* /*buffer*/) const
|
||||
@ -64,18 +114,133 @@ namespace demonware
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketplace::steamProcessDurableV2(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdMarketplace::steamProcessDurableV2(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string platform;
|
||||
buffer->read_string(&platform);
|
||||
|
||||
std::string unk1;
|
||||
buffer->read_string(&unk1);
|
||||
|
||||
std::uint32_t unk2;
|
||||
buffer->read_uint32(&unk2);
|
||||
|
||||
std::uint64_t unk3;
|
||||
buffer->read_uint64(&unk3);
|
||||
|
||||
std::string unk4;
|
||||
buffer->read_string(&unk4);
|
||||
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketplace::purchaseSkus(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdMarketplace::purchaseSkus(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
std::string platform, clientTransactionId;
|
||||
uint32_t numSkuIds;
|
||||
uint32_t skuIds[4]{};
|
||||
uint32_t numQuanities;
|
||||
uint32_t skuQuanities[4]{};
|
||||
uint32_t numMaxResults;
|
||||
uint32_t numDiscounts;
|
||||
uint32_t skuDiscounts[4]{};
|
||||
uint32_t numCouponRecipients;
|
||||
// coupon data here
|
||||
uint32_t numCouponMetadata;
|
||||
// coupon metadata here
|
||||
uint8_t customSourceType;
|
||||
bool ignoreEntitlements;
|
||||
|
||||
buffer->read_string(&platform);
|
||||
buffer->read_string(&clientTransactionId);
|
||||
|
||||
buffer->read_uint32(&numSkuIds);
|
||||
assert(numSkuIds < 4);
|
||||
|
||||
for (auto i = 0u; i < numSkuIds; i++)
|
||||
{
|
||||
buffer->read_uint32(&skuIds[i]);
|
||||
}
|
||||
|
||||
buffer->read_uint32(&numQuanities);
|
||||
assert(numQuanities < 4);
|
||||
|
||||
for (auto i = 0u; i < numQuanities; i++)
|
||||
{
|
||||
buffer->read_uint32(&skuQuanities[i]);
|
||||
}
|
||||
|
||||
buffer->read_uint32(&numMaxResults);
|
||||
|
||||
buffer->read_uint32(&numDiscounts);
|
||||
assert(numDiscounts < 4);
|
||||
|
||||
for (auto i = 0u; i < numDiscounts; i++)
|
||||
{
|
||||
buffer->read_uint32(&skuDiscounts[i]);
|
||||
}
|
||||
|
||||
buffer->read_uint32(&numCouponRecipients);
|
||||
assert(numCouponRecipients == 0);
|
||||
|
||||
buffer->read_uint32(&numCouponMetadata);
|
||||
assert(numCouponMetadata == 0);
|
||||
|
||||
buffer->read_ubyte(&customSourceType);
|
||||
buffer->read_bool(&ignoreEntitlements);
|
||||
|
||||
assert(numSkuIds == 1);
|
||||
|
||||
auto id = skuIds[0];
|
||||
auto num = skuQuanities[0];
|
||||
|
||||
// schematic buy comes through here
|
||||
if (id < 70000 || id > 75223)
|
||||
{
|
||||
const auto item = loot::get_loot(id);
|
||||
const auto cost = item.cost;
|
||||
const auto item_balance = loot::get_item_balance(id);
|
||||
const auto currency_balance = loot::get_currency_balance(loot::CurrencyType::salvage);
|
||||
|
||||
if (cost > currency_balance)
|
||||
{
|
||||
server->create_reply(this->task_id(), BD_MARKETPLACE_ERROR).send();
|
||||
return;
|
||||
}
|
||||
|
||||
loot::set_currency_balance(loot::CurrencyType::salvage, currency_balance - cost);
|
||||
loot::set_item_balance(id, item_balance + num);
|
||||
|
||||
loot::save();
|
||||
|
||||
server->create_reply(this->task_id(), BD_NO_ERROR).send();
|
||||
return;
|
||||
}
|
||||
|
||||
int currency_id = loot::CurrencyType::keys;
|
||||
if (id > 70000 && (id - 5000) >= 70000)
|
||||
{
|
||||
id = id - 5000;
|
||||
currency_id = loot::CurrencyType::codpoints;
|
||||
}
|
||||
|
||||
const auto current_balance = loot::get_currency_balance(currency_id);
|
||||
const auto cost = loot::get_lootcrate_cost(id, currency_id);
|
||||
|
||||
if (cost > current_balance)
|
||||
{
|
||||
server->create_reply(this->task_id(), BD_MARKETPLACE_ERROR).send();
|
||||
return;
|
||||
}
|
||||
|
||||
loot::set_currency_balance(currency_id, current_balance - cost);
|
||||
loot::set_item_balance(id, loot::get_item_balance(id) + num);
|
||||
|
||||
loot::save();
|
||||
|
||||
server->create_reply(this->task_id(), BD_NO_ERROR).send();
|
||||
}
|
||||
|
||||
void bdMarketplace::getBalance(service_server* server, byte_buffer* /*buffer*/) const
|
||||
@ -85,17 +250,83 @@ namespace demonware
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketplace::getBalanceV2(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdMarketplace::getBalanceV2(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
std::string platform;
|
||||
buffer->read_string(&platform);
|
||||
|
||||
std::uint32_t maxNumResults;
|
||||
buffer->read_uint32(&maxNumResults);
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
|
||||
std::uint32_t numResults = 0;
|
||||
|
||||
auto add_result = [&](std::uint8_t id, std::uint32_t value)
|
||||
{
|
||||
if (numResults >= maxNumResults) return;
|
||||
auto info = std::make_unique<bdMarketplaceCurrency>();
|
||||
info->m_currencyId = id;
|
||||
info->m_value = value;
|
||||
reply.add(info);
|
||||
numResults++;
|
||||
};
|
||||
|
||||
add_result(loot::CurrencyType::keys, loot::get_currency_balance(loot::CurrencyType::keys));
|
||||
add_result(loot::CurrencyType::salvage, loot::get_currency_balance(loot::CurrencyType::salvage));
|
||||
add_result(loot::CurrencyType::codpoints, loot::get_currency_balance(loot::CurrencyType::codpoints));
|
||||
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketplace::getInventoryPaginated(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdMarketplace::getInventoryPaginated(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
std::string platform;
|
||||
std::uint32_t itemsPerPage, pageNum;
|
||||
|
||||
buffer->read_string(&platform);
|
||||
buffer->read_uint32(&pageNum);
|
||||
buffer->read_uint32(&itemsPerPage);
|
||||
|
||||
assert(itemsPerPage);
|
||||
|
||||
static unsigned int paginated_index = 0;
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
|
||||
auto all_loot = loot::get_all_loot_owned();
|
||||
|
||||
const unsigned int index = paginated_index;
|
||||
for (size_t i = 0; i < all_loot.size() - index; i++)
|
||||
{
|
||||
const auto loot = all_loot[paginated_index];
|
||||
const auto balance = loot::get_item_balance(loot.id);
|
||||
assert(balance);
|
||||
|
||||
auto info = std::make_unique<bdMarketplaceInventory>();
|
||||
|
||||
info->m_playerId = steam::SteamUser()->GetSteamID().bits;
|
||||
info->unk = "";
|
||||
info->m_itemId = loot.id;
|
||||
info->m_itemQuantity = balance;
|
||||
info->m_itemXp = 0;
|
||||
info->m_itemData = "";
|
||||
info->m_expireDateTime = 0;
|
||||
info->m_expiryDuration = 0;
|
||||
info->m_collisionField = 0;
|
||||
info->m_modDateTime = 0;
|
||||
|
||||
reply.add(info);
|
||||
|
||||
paginated_index++;
|
||||
if (i >= itemsPerPage - 1)
|
||||
{
|
||||
reply.send();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
paginated_index = 0;
|
||||
reply.send();
|
||||
}
|
||||
|
||||
@ -106,6 +337,48 @@ namespace demonware
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketplace::pawnItems(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string platform, clientTransactionId;
|
||||
std::uint32_t numItemsToPawn;
|
||||
|
||||
buffer->read_string(&platform);
|
||||
buffer->read_string(&clientTransactionId);
|
||||
|
||||
auto currency = loot::get_currency_balance(loot::CurrencyType::salvage);
|
||||
|
||||
buffer->read_uint32(&numItemsToPawn);
|
||||
for (auto i = 0u; i < numItemsToPawn; i++)
|
||||
{
|
||||
std::uint32_t id, nextBalance;
|
||||
std::uint16_t unk2; // collision?
|
||||
|
||||
buffer->read_uint32(&id);
|
||||
buffer->read_uint32(&nextBalance);
|
||||
buffer->read_uint16(&unk2);
|
||||
|
||||
const auto loot = loot::get_loot(id);
|
||||
const auto amount = loot::get_item_balance(loot.id);
|
||||
|
||||
if (amount == 1) // why are you trying to pawn when we only have 1...
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
loot::set_item_balance(loot.id, nextBalance);
|
||||
currency += loot.salvageReturned;
|
||||
|
||||
#ifdef DW_DEBUG
|
||||
printf("[DW]: pawning %d for %d salvage\n", loot.id, loot.salvageReturned);
|
||||
#endif
|
||||
}
|
||||
loot::set_currency_balance(loot::CurrencyType::salvage, currency);
|
||||
loot::save();
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdMarketplace::getEntitlements(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
|
@ -20,6 +20,7 @@ namespace demonware
|
||||
void getBalanceV2(service_server* server, byte_buffer* buffer) const;
|
||||
void getInventoryPaginated(service_server* server, byte_buffer* buffer) const;
|
||||
void putPlayersInventoryItems(service_server* server, byte_buffer* buffer) const;
|
||||
void pawnItems(service_server* server, byte_buffer* buffer) const;
|
||||
void getEntitlements(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace demonware
|
||||
{
|
||||
auto result = std::make_unique<bdPerformanceValue>();
|
||||
result->user_id = steam::SteamUser()->GetSteamID().bits;
|
||||
result->performance = 10;
|
||||
result->performance = 10.0f;
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.add(result);
|
||||
|
@ -1,6 +1,13 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../dw_include.hpp"
|
||||
|
||||
#include "steam/steam.hpp"
|
||||
|
||||
#include "utils/json.hpp"
|
||||
#include "../loot/loot.hpp"
|
||||
|
||||
//#define VERIFY_CRATE_AMOUNT
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdReward::bdReward() : service(139, "bdReward")
|
||||
@ -32,10 +39,200 @@ namespace demonware
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdReward::reportRewardEvents(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdReward::reportRewardEvents(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
std::string platform;
|
||||
unsigned short numEvents;
|
||||
std::int32_t rewardEventType;
|
||||
|
||||
std::string json_buffer;
|
||||
|
||||
buffer->read_string(&platform);
|
||||
buffer->read_uint16(&numEvents);
|
||||
buffer->read_int32(&rewardEventType); // none 0, json 1
|
||||
|
||||
assert(numEvents == 1);
|
||||
|
||||
buffer->read_string(&json_buffer);
|
||||
|
||||
const auto send = [&](nlohmann::json& json_reply)
|
||||
{
|
||||
auto result = std::make_unique<bdRewardEvent>();
|
||||
|
||||
result->push_type = BD_REWARD_EVENT_MESSAGE;
|
||||
result->r2 = 1;
|
||||
result->user_id = steam::SteamUser()->GetSteamID().bits;
|
||||
result->platform1 = "steam";
|
||||
result->platform2 = platform;
|
||||
result->rewardEventType = rewardEventType;
|
||||
result->r7 = 1;
|
||||
result->r8 = 1;
|
||||
result->json_buffer = json_reply.dump(0);
|
||||
|
||||
byte_buffer reply_buffer;
|
||||
result->serialize(&reply_buffer);
|
||||
|
||||
auto reply = server->create_message(BD_LOBBY_SERVICE_PUSH_MESSAGE);
|
||||
reply.send(&reply_buffer, true);
|
||||
};
|
||||
|
||||
nlohmann::json json;
|
||||
json = json.parse(json_buffer);
|
||||
|
||||
const auto action = json["Action"].get<std::string>();
|
||||
if (action == "DailyLogin")
|
||||
{
|
||||
#ifdef DW_DEBUG
|
||||
printf("[DW]: daily login requested...\n");
|
||||
#endif
|
||||
|
||||
nlohmann::json json_reply;
|
||||
json_reply["Action"] = "DailyLoginResponse";
|
||||
|
||||
json_reply["LoginDayCountSP"] = -1;
|
||||
json_reply["FirstTimeTodaySP"] = false;
|
||||
json_reply["LoginDayCount"] = 1;
|
||||
json_reply["FirstTimeToday"] = false;
|
||||
|
||||
// Packs
|
||||
json_reply["BasicPacks"] = nlohmann::json::value_type::array();
|
||||
json_reply["BasicPacks"][0]["Currencies"] = nlohmann::json::value_type::object();
|
||||
json_reply["BasicPacks"][0]["Currencies"]["11"] = 0;
|
||||
json_reply["BasicPacks"][0]["Currencies"]["12"] = 0;
|
||||
json_reply["BasicPacks"][0]["Currencies"]["20"] = 0;
|
||||
json_reply["BasicPacks"][0]["Items"] = nlohmann::json::value_type::array();
|
||||
json_reply["BasicPacks"][0]["Id"] = 200018;
|
||||
json_reply["SeasonPassPacks"] = nlohmann::json::value_type::array();
|
||||
|
||||
// Extra Items
|
||||
json_reply["ExtraItems"] = nlohmann::json::value_type::array();
|
||||
|
||||
// Items
|
||||
json_reply["Items"] = nlohmann::json::value_type::array();
|
||||
|
||||
// mp/loot/iw7_loot_crate_loot_master.csv
|
||||
json_reply["Items"][0]["ItemId"] = 70005; // ZombieRareCardPack
|
||||
json_reply["Items"][0]["Collision"] = 0; // not sure what this does
|
||||
json_reply["Items"][0]["Balance"] = 999;
|
||||
loot::set_item_balance(70005, 999);
|
||||
|
||||
// Currencies
|
||||
json_reply["Currencies"] = nlohmann::json::value_type::array();
|
||||
|
||||
// Keys
|
||||
json_reply["Currencies"][0]["CurrencyId"] = loot::CurrencyType::keys;
|
||||
json_reply["Currencies"][0]["Balance"] = loot::get_currency_balance(loot::CurrencyType::keys);
|
||||
|
||||
// Salvage
|
||||
json_reply["Currencies"][1]["CurrencyId"] = loot::CurrencyType::salvage;
|
||||
json_reply["Currencies"][1]["Balance"] = loot::get_currency_balance(loot::CurrencyType::salvage);
|
||||
|
||||
// CodPoints
|
||||
json_reply["Currencies"][2]["CurrencyId"] = loot::CurrencyType::codpoints;
|
||||
json_reply["Currencies"][2]["Balance"] = loot::get_currency_balance(loot::CurrencyType::codpoints);
|
||||
|
||||
json_reply["ClientTx"] = json["ClientTx"];
|
||||
|
||||
send(json_reply);
|
||||
}
|
||||
else if (action == "ClaimLootCrates")
|
||||
{
|
||||
#ifdef DW_DEBUG
|
||||
printf("[DW]: supply drop open requested...\n");
|
||||
#endif
|
||||
|
||||
nlohmann::json json_reply;
|
||||
json_reply["Action"] = "ClaimLootCratesResponse";
|
||||
|
||||
json_reply["Packs"] = nlohmann::json::value_type::array();
|
||||
json_reply["Items"] = nlohmann::json::value_type::array();
|
||||
json_reply["Currencies"] = nlohmann::json::value_type::array();
|
||||
|
||||
// Items, Packs
|
||||
|
||||
const auto rule_id = json["RuleId"].is_number_integer() ? json["RuleId"].get<int>() : 0;
|
||||
const auto crate_id = 70000 + rule_id;
|
||||
|
||||
int itemidx = 0;
|
||||
|
||||
auto crate_balance = loot::get_item_balance(crate_id);
|
||||
#ifdef VERIFY_CRATE_AMOUNT
|
||||
if (!crate_balance)
|
||||
{
|
||||
server->create_reply(this->task_id(), BD_MARKETPLACE_ERROR).send();
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!crate_balance)
|
||||
{
|
||||
crate_balance = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
const auto new_crate_balance = crate_balance - 1;
|
||||
|
||||
json_reply["Items"][itemidx]["ItemId"] = crate_id;
|
||||
json_reply["Items"][itemidx]["Collision"] = 0; // not sure what this does
|
||||
json_reply["Items"][itemidx]["Balance"] = new_crate_balance;
|
||||
itemidx++;
|
||||
|
||||
loot::set_item_balance(crate_id, new_crate_balance);
|
||||
|
||||
auto loot = loot::get_random_loot(crate_id);
|
||||
|
||||
for (auto i = 0; i < loot.size(); i++)
|
||||
{
|
||||
const auto item_id = loot[i].id;
|
||||
|
||||
json_reply["Packs"][i] = item_id;
|
||||
|
||||
const auto balance = loot::get_item_balance(item_id) + 1;
|
||||
loot::set_item_balance(item_id, balance);
|
||||
|
||||
json_reply["Items"][i + itemidx]["ItemId"] = item_id;
|
||||
json_reply["Items"][i + itemidx]["Collision"] = 0;
|
||||
json_reply["Items"][i + itemidx]["Balance"] = balance;
|
||||
|
||||
#ifdef DW_DEBUG
|
||||
printf("[DW]: loot %d\n", item_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
loot::save();
|
||||
|
||||
json_reply["Error"] = "";
|
||||
json_reply["ClientTx"] = json["ClientTx"];
|
||||
|
||||
send(json_reply);
|
||||
}
|
||||
else if (action == "StartMission")
|
||||
{
|
||||
printf("%s\n", json_buffer.data());
|
||||
//const auto match_id = json["MatchId"].get<int>();
|
||||
//const auto mission_set_instance_id = json["MissionSetInstanceId"].get<unsigned int>();
|
||||
}
|
||||
else if (action == "StartMissionSet")
|
||||
{
|
||||
printf("%s\n", json_buffer.data());
|
||||
//const auto mission_set_id = json["MissionSetId"].get<unsigned int>();
|
||||
}
|
||||
else if (action == "EndMission")
|
||||
{
|
||||
printf("%s\n", json_buffer.data());
|
||||
}
|
||||
else if (action == "EndMissionSet")
|
||||
{
|
||||
printf("%s\n", json_buffer.data());
|
||||
}
|
||||
else if (action == "ResetMissions")
|
||||
{
|
||||
printf("%s\n", json_buffer.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[DW]: unhandled reward action \"%s\"...\n", action.data());
|
||||
}
|
||||
|
||||
server->create_reply(this->task_id(), BD_NO_ERROR).send();
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace demonware
|
||||
this->register_task(14, &bdStats::writeServerValidatedStats);
|
||||
}
|
||||
|
||||
void bdStats::writeStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdStats::writeStats(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
@ -104,8 +104,11 @@ namespace demonware
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void bdStats::writeServerValidatedStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
void bdStats::writeServerValidatedStats(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string blob;
|
||||
buffer->read_blob(&blob);
|
||||
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply.send();
|
||||
|
@ -21,6 +21,125 @@ namespace game::demonware
|
||||
DW_NET_STARTED_ONLINE = 0x6,
|
||||
};
|
||||
|
||||
enum bdEventType
|
||||
{
|
||||
BD_NEW_NOTIFICATION = 0x1,
|
||||
BD_FRIENDSHIP_PROPOSAL = 0x2,
|
||||
BD_TEAM_PROPOSAL = 0x3,
|
||||
BD_FRIEND_CONNECTED = 0x4,
|
||||
BD_FRIEND_DISCONNECTED = 0x5,
|
||||
BD_SESSION_INVITATION = 0x6,
|
||||
BD_CHANNEL_CHAT_BROADCAST_MSG = 0x7,
|
||||
BD_CHANNEL_CHAT_WHISPER_MSG = 0x8,
|
||||
BD_CHANNEL_USER_SUBSCRIBED = 0x9,
|
||||
BD_CHANNEL_USER_UNSUBSCRIBED = 0xA,
|
||||
BD_TEAMMEMBER_CONNECTED = 0xB,
|
||||
BD_TEAMMEMBER_DISCONNECTED = 0xC,
|
||||
BD_FRIEND_RICH_PRESENCE_UPDATED = 0xD,
|
||||
BD_FRIEND_CHAT_MSG = 0xF,
|
||||
BD_TEAM_CHAT_MSG = 0x10,
|
||||
BD_NOTIFY_LEAVE = 0x11,
|
||||
BD_NEW_MAIL = 0x12,
|
||||
BD_CHALLENGES_RECEIVED = 0x13,
|
||||
BD_ASYNCHRONOUS_RESULT = 0x14,
|
||||
BD_GLOBAL_INSTANT_MESSAGE = 0x15,
|
||||
BD_CHANNEL_CHAT_BROADCAST_MSG_V2 = 0x16,
|
||||
BD_CHANNEL_CHAT_WHISPER_MSG_V2 = 0x17,
|
||||
BD_CHANNEL_USER_SUBSCRIBED_V2 = 0x18,
|
||||
BD_CHANNEL_USER_UNSUBSCRIBED_V2 = 0x19,
|
||||
BD_CHANNEL_USER_MUTED_V2 = 0x1A,
|
||||
BD_CHANNEL_USER_PROMOTED_V2 = 0x1B,
|
||||
BD_CHANNEL_USER_KICKED_V2 = 0x1C,
|
||||
BD_MULTIPLE_LOGONS = 0x1D,
|
||||
BD_PLAYER_BANNED = 0x1E,
|
||||
BD_CHANNEL_USER_PROMOTED = 0x1F,
|
||||
BD_CHANNEL_USER_KICKED = 0x20,
|
||||
BD_FEATURE_BAN = 0x21,
|
||||
BD_GMSG_GROUP_MESSAGE = 0x22,
|
||||
BD_GMSG_BROADCAST = 0x23,
|
||||
BD_TENCENT_AAS_RECORD = 0x24,
|
||||
BD_NOT_WHITE_LISTED = 0x26,
|
||||
BD_CHANNEL_USER_MUTED = 0x27,
|
||||
BD_STABILISED = 0x28,
|
||||
BD_CONSOLE_BANNED = 0x29,
|
||||
BD_MULTIPLE_LINKED_ACCOUNT_LOGONS = 0x2A,
|
||||
BD_LINKED_ACCOUNT_STATUS_CHANGE = 0x2B,
|
||||
BD_QUEUED_MATCHING_DATA = 0x2C,
|
||||
BD_EVENT_LOG_FILTERED_CATEGORIES = 0x2D,
|
||||
BD_MARKETPLACE_COUPONS_GRANTED = 0x2E,
|
||||
BD_TOTP_CHALLENGE = 0x2F,
|
||||
BD_MARKETPLACE_ITEMS_EXPIRED = 0x30,
|
||||
BD_MARKETPLACE_ITEMS_UPDATED = 0x31,
|
||||
BD_MARKETPLACE_COUPONS_UPDATED = 0x32,
|
||||
BD_REWARD_ACHIEVEMENT_CLAIMED = 0x33,
|
||||
BD_MARKETPLACE_BALANCE_UPDATED = 0x34,
|
||||
BD_MARKETPLACE_DEPOSIT_GRANTED = 0x35,
|
||||
BD_MARKETPLACE_ITEMS_GRANTED = 0x36,
|
||||
BD_MARKETPLACE_ENTITLEMENTS_GRANTED = 0x37,
|
||||
BD_STORAGE_WEBSERVICE_WRITE = 0x38,
|
||||
BD_REWARD_EVENT_MESSAGE = 0x39,
|
||||
BD_MARKETING_COMMS_ASSIGNMENTS_AVAILABLE = 0x3A,
|
||||
BD_PUBLISHER_VARIABLES_UPDATE_MESSAGE = 0x3B,
|
||||
BD_MARKETPLACE_COUPONS_UPDATED_V2 = 0x3C,
|
||||
BD_MARKETPLACE_ITEMS_GRANTED_WITH_INVENTORY_QUANTITY = 0x3D,
|
||||
BD_USER_PRIVATE_PROFILE_UPDATED = 0x3E,
|
||||
BD_TEAM_MEMBER_RICH_PRESENCE_UPDATED = 0x3F,
|
||||
BD_TITLE_VERSION_DISABLED = 0x40,
|
||||
BD_TEAM_MEMBER_USER_NAME_UPDATED = 0x41,
|
||||
BD_MARKETPLACE_COUPONS_UPDATED_V3 = 0x42,
|
||||
BD_REWARD_ACHIEVEMENT_MESSAGE = 0x43,
|
||||
BD_PLAYER_DISCONNECTED = 0x44,
|
||||
BD_CODO_TEAM_MARKETPLACE_LEVEL_CHANGED = 0x45,
|
||||
BD_SUBSCRIBED_RICH_PRESENCE_UPDATED = 0x46,
|
||||
BD_PLAYER_LOGON_TIME_PROHIBITED = 0x47,
|
||||
BD_PLAYER_LOGON_TIME_PROHIBITED_WARNING = 0x48,
|
||||
BD_MARKETPLACE_COUPONS_UPDATED_V4 = 0x49,
|
||||
BD_NOT_WHITE_LISTED_WITH_MESSAGE = 0x4A,
|
||||
BD_ACHIEVEMENTS_UPDATED = 0x4B,
|
||||
BD_MARKETPLACE_BALANCE_UPDATED_V2 = 0x4C,
|
||||
BD_MW4_CLANS_MEMBERSHIP_PROPOSAL = 0x4D,
|
||||
BD_MW4_CLANS_MEMBER_ADDED = 0x4E,
|
||||
BD_MW4_CLANS_PROPOSAL_REMOVED = 0x4F,
|
||||
BD_MW4_CLANS_MEMBER_REMOVED = 0x50,
|
||||
BD_MW4_CLANS_GROUP_DISBANDED = 0x51,
|
||||
BD_MW4_CLANS_ACTIVE_GROUP_CHANGED = 0x52,
|
||||
BD_MW4_CLANS_GROUP_UPDATED = 0x53,
|
||||
BD_MW4_CLANS_MEMBER_UPDATED = 0x54,
|
||||
BD_DEMONATA_PUSH_MESSAGE = 0xC7,
|
||||
BD_DEMONATA_PROTOBUF_PUSH_MESSAGE = 0xC8,
|
||||
BD_TENCENT_ANTIBOT_DATA = 0x3E9,
|
||||
BD_TENCENT_ANTIBOT_PUNISH = 0x3EA,
|
||||
BD_TENCENT_REWARD = 0x3EB,
|
||||
BD_TENCENT_ANTIBOT_SERVER_READY = 0x3EC,
|
||||
BD_TENCENT_NAME_CHANGED = 0x3ED,
|
||||
BD_TENCENT_USER_LEAVE_REASON = 0x3EE,
|
||||
BD_TENCENT_LOUDSPEAKER_MESSAGE = 0x3EF,
|
||||
BD_TENCENT_NO_REWARD = 0x3F0,
|
||||
BD_TENCENT_SECURITY_RATING = 0x3F1,
|
||||
BD_QOS_HOSTS = 0x7D0,
|
||||
BD_JOIN_LOBBY = 0x7D1,
|
||||
BD_LOBBY_DISBANDED = 0x7D2,
|
||||
BD_MATCHMAKING_SEARCH_STATUS = 0x7D3,
|
||||
BD_LOBBY_NOT_FOUND = 0x7D4,
|
||||
BD_CREATE_NEW_LOBBY = 0x7D5,
|
||||
BD_UPDATED_LOBBY_DOCUMENT = 0x7D6,
|
||||
BD_EXPECT_GAME = 0x7D7,
|
||||
BD_MERGE_INTO_LOBBY = 0x7D8,
|
||||
BD_JOIN_TOURNAMENT = 0x7D9,
|
||||
BD_UPDATE_TOURNAMENT = 0x7DA,
|
||||
BD_TOURNAMENT_FORMATION_LOBBY_DISBANDED = 0x7DB,
|
||||
BD_TOURNAMENT_DISBANDED = 0x7DC,
|
||||
};
|
||||
|
||||
enum bdLobbyServiceType : std::int32_t
|
||||
{
|
||||
BD_LOBBY_SERVICE_TASK_REPLY = 1,
|
||||
BD_LOBBY_SERVICE_PUSH_MESSAGE = 2,
|
||||
BD_LSG_SERVICE_ERROR = 3,
|
||||
BD_LSG_SERVICE_CONNECTION = 4,
|
||||
BD_LSG_SERVICE_TASK_REPLY = 5,
|
||||
};
|
||||
|
||||
enum bdLobbyErrorCode : std::int32_t
|
||||
{
|
||||
BD_NO_ERROR = 0x0,
|
||||
|
@ -74,8 +74,11 @@
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <variant>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
|
||||
#include <gsl/gsl>
|
||||
#include <udis86.h>
|
||||
|
Loading…
Reference in New Issue
Block a user