Files
achmad 6d95836d11 feat: replace all user-facing Russian strings with English
Empty Russian and Chinese locale files so English is used regardless
of client language. Translate all CustomGameEventManager error messages,
SendCustomMessage calls, and deck/card UI strings to English.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 04:24:20 +07:00

1787 lines
83 KiB
Lua

local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local Map = ____lualib.Map
local __TS__New = ____lualib.__TS__New
local __TS__ArrayIsArray = ____lualib.__TS__ArrayIsArray
local __TS__TypeOf = ____lualib.__TS__TypeOf
local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys
local __TS__ArrayJoin = ____lualib.__TS__ArrayJoin
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local __TS__ArraySort = ____lualib.__TS__ArraySort
local __TS__ObjectValues = ____lualib.__TS__ObjectValues
local __TS__ArraySome = ____lualib.__TS__ArraySome
local __TS__ArrayPushArray = ____lualib.__TS__ArrayPushArray
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
local Set = ____lualib.Set
local __TS__ArrayIndexOf = ____lualib.__TS__ArrayIndexOf
local ____exports = {}
local ____server_config = require("server_config")
local SERVER_CONFIG = ____server_config.SERVER_CONFIG
local ____api_helper = require("api_helper")
local setApiHeaders = ____api_helper.setApiHeaders
local setApiHeadersLong = ____api_helper.setApiHeadersLong
local ____store_manager = require("store_manager")
local StoreManager = ____store_manager.StoreManager
local ____hero_list_table = require("tables.hero_list_table")
local HERO_LIST_TABLE = ____hero_list_table.HERO_LIST_TABLE
local function rawPrintFn(____, ...)
_G:print(...)
end
local ENABLE_VERBOSE_MINI_PROFILE_LOGS = false
local ____print = ENABLE_VERBOSE_MINI_PROFILE_LOGS and rawPrintFn or (function(____, ...) return nil end)
____exports.MiniProfileServer = __TS__Class()
local MiniProfileServer = ____exports.MiniProfileServer
MiniProfileServer.name = "MiniProfileServer"
MiniProfileServer.____file_path = "scripts/vscripts/mini_profile_server.lua"
function MiniProfileServer.prototype.____constructor(self)
self.serverUrl = SERVER_CONFIG.API_URL
self.grantedProfileRewardsInSession = __TS__New(Map)
self.grantedHeroRankRewardsInSession = __TS__New(Map)
self.profileLevelRewards = {
{level = 5, freeCurrency = 100},
{level = 10, freeCurrency = 200},
{level = 15, freeCurrency = 350},
{level = 20, freeCurrency = 500},
{level = 25, freeCurrency = 700},
{level = 30, freeCurrency = 900},
{level = 40, freeCurrency = 1400},
{level = 50, freeCurrency = 2000},
{level = 75, freeCurrency = 3500},
{level = 100, freeCurrency = 5000},
{level = 150, freeCurrency = 5500},
{level = 200, freeCurrency = 6000},
{level = 300, freeCurrency = 7000},
{level = 400, freeCurrency = 8000},
{level = 500, freeCurrency = 9000},
{level = 600, freeCurrency = 10000},
{level = 700, freeCurrency = 11000},
{level = 800, freeCurrency = 12500},
{level = 900, freeCurrency = 14000},
{level = 1000, freeCurrency = 16000}
}
self:setupEventListeners()
end
function MiniProfileServer.getInstance(self)
if not ____exports.MiniProfileServer.instance then
____exports.MiniProfileServer.instance = __TS__New(____exports.MiniProfileServer)
end
return ____exports.MiniProfileServer.instance
end
function MiniProfileServer.prototype.setupEventListeners(self)
CustomGameEventManager:RegisterListener(
"request_player_profile",
function(source, event)
local playerId = event.PlayerID
local playerName = event.player_name
local requestedSteamId = event.steam_id
local requestedSteamId64 = event.steam_id_64
local steamId
local steamId64
if requestedSteamId and requestedSteamId ~= "" then
steamId = tostring(requestedSteamId)
if requestedSteamId64 and requestedSteamId64 ~= "" and requestedSteamId64 ~= "null" then
steamId64 = tostring(requestedSteamId64)
local steamIdStr = tostring(steamId)
local steamIdPrefix = string.sub(steamIdStr, 1, 7)
if string.len(steamIdStr) > 10 and steamIdPrefix == "7656119" then
local base64Str = "76561197960265728"
local steamId64Str = steamIdStr
local accountId = self:subtractBigInts(steamId64Str, base64Str)
steamId = accountId
____print(nil, (("[MiniProfileServer] Using provided Steam ID64: " .. steamId64) .. ", converted to Account ID: ") .. steamId)
else
____print(nil, (("[MiniProfileServer] Using provided Steam ID32: " .. steamId) .. ", Steam ID64: ") .. steamId64)
end
else
local steamIdStr = tostring(steamId)
local steamIdPrefix = string.sub(steamIdStr, 1, 7)
if string.len(steamIdStr) > 10 and steamIdPrefix == "7656119" then
steamId64 = steamIdStr
local base64Str = "76561197960265728"
local accountId = self:subtractBigInts(steamIdStr, base64Str)
steamId = accountId
____print(nil, (("[MiniProfileServer] Steam ID64 detected: " .. steamId64) .. ", converted to Account ID: ") .. steamId)
else
local accountIdNum = tonumber(steamId)
if accountIdNum then
local base64Str = "76561197960265728"
local accountIdStr = tostring(accountIdNum)
local steamId64Str = self:addBigInts(accountIdStr, base64Str)
steamId64 = steamId64Str
____print(nil, (("[MiniProfileServer] Account ID detected: " .. steamId) .. ", converted to Steam ID64: ") .. steamId64)
else
if playerId ~= -1 and PlayerResource:GetPlayer(playerId) then
steamId64 = tostring(PlayerResource:GetSteamID(playerId))
else
steamId64 = steamId
end
end
end
end
else
steamId = tostring(PlayerResource:GetSteamAccountID(playerId))
steamId64 = tostring(PlayerResource:GetSteamID(playerId))
end
local requestingPlayer = EntIndexToHScript(source)
local requestingPlayerId = requestingPlayer ~= nil and requestingPlayer ~= nil and requestingPlayer:GetPlayerID() or playerId
local requesterSteamId = tostring(PlayerResource:GetSteamAccountID(requestingPlayerId))
local isOwnProfileRequest = requesterSteamId == steamId
self:loadPlayerProfileFromServer(
requestingPlayerId,
steamId,
playerName,
steamId64,
isOwnProfileRequest
)
end
)
CustomGameEventManager:RegisterListener(
"request_match_players",
function(source, event)
local requestingPlayer = EntIndexToHScript(source)
if not requestingPlayer then
return
end
local matchIdRaw = event.match_id or event.game_id or event.id
local matchId = tonumber(tostring(matchIdRaw)) or 0
local rowId = tonumber(tostring(event.row_id or 0)) or 0
local steamId = tostring(event.steam_id or "")
if matchId <= 0 then
CustomGameEventManager:Send_ServerToPlayer(requestingPlayer, "match_players_data", {error = "Invalid match ID", match_id = 0, players = {}})
return
end
self:loadMatchPlayersFromServer(requestingPlayer, matchId, rowId, steamId)
end
)
CustomGameEventManager:RegisterListener(
"request_store_currency",
function(source, event)
local playerId = event.PlayerID
if playerId == nil or playerId == nil or not PlayerResource:IsValidPlayerID(playerId) then
return
end
self:syncHeroRankRewardsForPlayer(playerId)
end
)
end
function MiniProfileServer.prototype.syncHeroRankRewardsForPlayer(self, playerId)
local steamId = tostring(PlayerResource:GetSteamAccountID(playerId))
if not steamId or steamId == "0" then
return
end
self:loadHeroAchievementsForProfile(
steamId,
playerId,
true,
function(____, _heroAchievementsObject, grantedNow)
local grantedCount = #self:normalizeArrayLike(grantedNow)
if grantedCount > 0 then
____print(
nil,
(("[MiniProfileServer] Store-trigger reward sync: player=" .. tostring(playerId)) .. ", granted=") .. tostring(grantedCount)
)
end
end
)
end
function MiniProfileServer.prototype.createPlayerProfile(self, playerId, steamId, playerName)
local request = CreateHTTPRequestScriptVM("POST", self.serverUrl .. "/player")
setApiHeadersLong(nil, request)
request:SetHTTPRequestRawPostBody(
"application/json",
json.encode({steam_id = steamId, player_name = playerName})
)
request:Send(function(result)
local player = PlayerResource:GetPlayer(playerId)
if not player then
return
end
if result.StatusCode >= 200 and result.StatusCode < 300 then
do
pcall(function()
local decoded = {json.decode(result.Body)}
local responseData = nil
if __TS__ArrayIsArray(decoded) and #decoded > 0 then
responseData = decoded[1]
elseif decoded and type(decoded) == "table" then
responseData = decoded
end
if responseData then
StoreManager:getInstance():handleLoginPlayerApiResponse(playerId, responseData)
end
end)
end
self:loadPlayerProfileFromServer(playerId, steamId, playerName)
else
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {error = "Failed to create profile", steam_id = steamId, player_name = playerName})
end
end)
end
function MiniProfileServer.prototype.loadPlayerProfileFromServer(self, playerId, steamId, playerName, steamId64, shouldGrantLevelRewards)
if shouldGrantLevelRewards == nil then
shouldGrantLevelRewards = false
end
local steamIdStr = tostring(steamId)
local steamIdNum = tonumber(steamIdStr)
if steamIdNum and steamIdNum > 1000000000000 then
local base64 = 76561197960265730
local accountId = math.floor(steamIdNum - base64)
steamIdStr = tostring(accountId)
____print(nil, (("[MiniProfileServer] Converted 64-bit Steam ID " .. steamId) .. " to 32-bit Account ID ") .. steamIdStr)
end
____print(nil, (("[MiniProfileServer] Загрузка профиля: steam_id=" .. steamIdStr) .. ", player=") .. playerName)
local request = CreateHTTPRequestScriptVM("GET", (self.serverUrl .. "/player/") .. steamIdStr)
setApiHeaders(nil, request)
request:Send(function(result)
do
local function ____catch(____error)
local player = PlayerResource:GetPlayer(playerId)
if player then
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {error = "Data processing error", steam_id = steamId, player_name = playerName})
end
end
local ____try, ____hasReturned, ____returnValue = pcall(function()
local player = PlayerResource:GetPlayer(playerId)
if not player then
return true
end
if result.StatusCode == 0 then
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {error = "Server unavailable", steam_id = steamId, player_name = playerName})
return true
end
if result.StatusCode >= 200 and result.StatusCode < 300 then
do
local function ____catch(e)
____print(
nil,
"[MiniProfileServer] Ошибка обработки данных профиля: " .. tostring(e)
)
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {error = "Profile data processing error", steam_id = steamId, player_name = playerName})
end
local ____try, ____hasReturned, ____returnValue = pcall(function()
local responseBodyStr = tostring(result.Body or "")
local responseBodyPreview = string.len(responseBodyStr) > 1000 and string.sub(responseBodyStr, 1, 1000) .. "... [truncated]" or responseBodyStr
____print(nil, "[MiniProfileServer] Response Body (preview): " .. responseBodyPreview)
local responseData = self:decodeJsonSafe(result.Body)
if responseData == nil then
____print(
nil,
"[MiniProfileServer] Ошибка JSON профиля: body_length=" .. tostring(string.len(responseBodyStr))
)
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {error = "JSON parsing error", steam_id = steamId, player_name = playerName})
return true
end
local responseDataAny = responseData
____print(
nil,
(("[MiniProfileServer] Decoded response type: " .. __TS__TypeOf(responseData)) .. ", isArray: ") .. tostring(__TS__ArrayIsArray(responseData))
)
____print(
nil,
"[MiniProfileServer] Decoded response keys: " .. (type(responseData) == "table" and __TS__ArrayJoin(
__TS__ObjectKeys(responseData),
", "
) or "N/A")
)
local data = nil
local responseItems = {}
local topLevelObjects = {}
if responseDataAny and type(responseDataAny) == "table" then
for k in pairs(responseDataAny) do
local v = responseDataAny[k]
if v and type(v) == "table" then
topLevelObjects[#topLevelObjects + 1] = v
end
end
end
local looksLikeProfilePayload = responseDataAny and type(responseDataAny) == "table" and (responseDataAny.profile ~= nil or responseDataAny.stats ~= nil or responseDataAny.recentGames ~= nil or responseDataAny.recent_games ~= nil or responseDataAny.games ~= nil or responseDataAny.history ~= nil)
if looksLikeProfilePayload then
data = responseDataAny
____print(nil, "[MiniProfileServer] Using profile payload object directly")
elseif __TS__ArrayIsArray(responseDataAny) then
local reconstructed = {}
local reconstructedCount = 0
__TS__ArrayForEach(
topLevelObjects,
function(____, obj)
local objAny = obj
local keyNamed = tostring(objAny.key or "")
local valueNamed = objAny.value
local keyIndexed = tostring(objAny[1] or objAny["1"] or "")
local ____temp_0
if objAny[2] ~= nil then
____temp_0 = objAny[2]
else
____temp_0 = objAny["2"]
end
local valueIndexed = ____temp_0
local finalKey = keyNamed ~= "" and keyNamed or keyIndexed
local ____temp_1
if keyNamed ~= "" then
____temp_1 = valueNamed
else
____temp_1 = valueIndexed
end
local finalValue = ____temp_1
if finalKey ~= "" and finalValue ~= nil then
reconstructed[finalKey] = finalValue
reconstructedCount = reconstructedCount + 1
end
end
)
if reconstructedCount > 0 then
data = reconstructed
____print(
nil,
"[MiniProfileServer] Reconstructed object from key/value pairs, keys=" .. table.concat(
__TS__ObjectKeys(reconstructed),
", "
)
)
elseif #topLevelObjects > 0 then
local sample = topLevelObjects[1]
local sampleKeys = {}
for k in pairs(sample) do
sampleKeys[#sampleKeys + 1] = tostring(k)
end
local ____temp_10 = ("[MiniProfileServer] array-like sample keys=" .. table.concat(sampleKeys, ", ")) .. " "
local ____tostring_5 = tostring
local ____opt_result_4
if sample ~= nil then
____opt_result_4 = sample.key
end
local ____tostring_5_result_9 = ____tostring_5(____opt_result_4)
local ____opt_result_8
if sample ~= nil then
____opt_result_8 = sample.value
end
local ____temp_27 = ____temp_10 .. ((("key=" .. ____tostring_5_result_9) .. " value_type=") .. __TS__TypeOf(____opt_result_8)) .. " "
local ____tostring_18 = tostring
local ____opt_result_13
if sample ~= nil then
____opt_result_13 = sample[1]
end
local ____opt_result_13_17 = ____opt_result_13
if not ____opt_result_13_17 then
local ____opt_result_16
if sample ~= nil then
____opt_result_16 = sample["1"]
end
____opt_result_13_17 = ____opt_result_16
end
local ____tostring_18_result_26 = ____tostring_18(____opt_result_13_17)
local ____opt_result_21
if sample ~= nil then
____opt_result_21 = sample[2]
end
local ____opt_result_21_25 = ____opt_result_21
if ____opt_result_21_25 == nil then
local ____opt_result_24
if sample ~= nil then
____opt_result_24 = sample["2"]
end
____opt_result_21_25 = ____opt_result_24
end
____print(
nil,
____temp_27 .. (("idx1=" .. ____tostring_18_result_26) .. " idx2_type=") .. __TS__TypeOf(____opt_result_21_25)
)
end
if not data then
for ____, obj in ipairs(topLevelObjects) do
if obj and type(obj) == "table" and (obj.profile ~= nil or obj.stats ~= nil or obj.recentGames ~= nil or obj.recent_games ~= nil or obj.games ~= nil or obj.history ~= nil) then
data = obj
____print(nil, "[MiniProfileServer] Found payload object inside array-like response")
break
end
end
end
if not data then
responseItems = self:normalizeArrayLike(responseDataAny)
if #responseItems > 0 then
data = responseItems[1]
____print(
nil,
"[MiniProfileServer] Using array-like response, items=" .. tostring(#responseItems)
)
end
end
elseif responseDataAny and type(responseDataAny) == "table" and responseDataAny.value ~= nil then
data = responseDataAny.value
____print(nil, "[MiniProfileServer] Using responseData.value as data")
elseif responseDataAny and type(responseDataAny) == "table" then
data = responseDataAny
____print(nil, "[MiniProfileServer] Using object directly as data")
else
____print(nil, "[MiniProfileServer] Failed to decode response")
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {error = "Data decode error", steam_id = steamId, player_name = playerName})
return true
end
if data then
local function collectObjectKeys(____, obj)
local keys = {}
if not obj or type(obj) ~= "table" then
return keys
end
for key in pairs(obj) do
keys[#keys + 1] = tostring(key)
end
return keys
end
if not data or type(data) ~= "table" then
for ____, item in ipairs(responseItems) do
if item and type(item) == "table" then
data = item
break
end
end
end
if not data or type(data) ~= "table" then
____print(nil, "[MiniProfileServer] ❌ Некорректный формат данных профиля (data is not object)")
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {error = "Invalid profile data format", steam_id = steamId, player_name = playerName})
return true
end
____print(
nil,
"[MiniProfileServer] Data keys: " .. table.concat(
collectObjectKeys(nil, data),
", "
)
)
____print(
nil,
"[MiniProfileServer] data.recentGames exists: " .. tostring(data.recentGames ~= nil)
)
____print(
nil,
(("[MiniProfileServer] data.recentGames type: " .. __TS__TypeOf(data.recentGames)) .. ", isArray: ") .. tostring(__TS__ArrayIsArray(data.recentGames))
)
if data.recentGames then
local ____Array_isArray_result_28
if __TS__ArrayIsArray(data.recentGames) then
____Array_isArray_result_28 = data.recentGames.length
else
____Array_isArray_result_28 = "N/A"
end
____print(
nil,
"[MiniProfileServer] data.recentGames length: " .. tostring(____Array_isArray_result_28)
)
end
local profileData = data.profile or data
if #responseItems > 0 then
for ____, item in ipairs(responseItems) do
if item and type(item) == "table" and item.profile and type(item.profile) == "table" then
profileData = item.profile
break
end
end
end
local nameFromDB = profileData.name or playerName
local ____tostring_32 = tostring
local ____opt_result_31
if profileData ~= nil then
____opt_result_31 = profileData.name
end
local ____tostring_32_result_37 = ____tostring_32(____opt_result_31)
local ____tostring_36 = tostring
local ____opt_result_35
if profileData ~= nil then
____opt_result_35 = profileData.level
end
local ____temp_47 = ((("[MiniProfileServer] profileData name=" .. ____tostring_32_result_37) .. " level=") .. ____tostring_36(____opt_result_35)) .. " "
local ____tostring_41 = tostring
local ____opt_result_40
if profileData ~= nil then
____opt_result_40 = profileData.free_currency
end
local ____tostring_41_result_46 = ____tostring_41(____opt_result_40)
local ____tostring_45 = tostring
local ____opt_result_44
if profileData ~= nil then
____opt_result_44 = profileData.donate_currency
end
____print(
nil,
____temp_47 .. (("free_currency=" .. ____tostring_41_result_46) .. " donate_currency=") .. ____tostring_45(____opt_result_44)
)
local grantedLevelRewardsNow = {}
if shouldGrantLevelRewards then
do
local function ____catch(grantError)
____print(
nil,
"[MiniProfileServer] Ошибка выдачи наград профиля: " .. tostring(grantError)
)
grantedLevelRewardsNow = {}
end
local ____try, ____hasReturned = pcall(function()
local profileLevel = tonumber(profileData.level) or 1
grantedLevelRewardsNow = self:grantPendingProfileLevelRewards(playerId, profileLevel)
end)
if not ____try then
____catch(____hasReturned)
end
end
end
local grantedLevelRewardsObject = {}
__TS__ArrayForEach(
grantedLevelRewardsNow,
function(____, reward, index)
grantedLevelRewardsObject[tostring(index)] = reward
end
)
local recentGames = data.recentGames or data.recent_games or data.games or data.history or data.match_history or data.stats and (data.stats.recentGames or data.stats.recent_games or data.stats.games or data.stats.history) or data.profile and (data.profile.recentGames or data.profile.recent_games or data.profile.games or data.profile.history or data.profile.match_history)
local function collectObjectValues(____, obj)
local out = {}
if not obj or type(obj) ~= "table" then
return out
end
for key in pairs(obj) do
out[#out + 1] = obj[key]
end
return out
end
local isRecentGamesEmptyObject = recentGames and type(recentGames) == "table" and not __TS__ArrayIsArray(recentGames) and #collectObjectKeys(nil, recentGames) == 0
if (not recentGames or isRecentGamesEmptyObject) and #responseItems > 0 then
for ____, item in ipairs(responseItems) do
do
if not item or type(item) ~= "table" then
goto __continue93
end
local candidate = item.recentGames or item.recent_games or item.games or item.history or item.match_history or item.stats and (item.stats.recentGames or item.stats.recent_games or item.stats.games or item.stats.history) or item.profile and (item.profile.recentGames or item.profile.recent_games or item.profile.games or item.profile.history or item.profile.match_history)
if not candidate then
goto __continue93
end
if __TS__ArrayIsArray(candidate) then
if #collectObjectValues(nil, candidate) > 0 then
recentGames = candidate
break
end
elseif type(candidate) == "table" and #collectObjectKeys(nil, candidate) > 0 then
recentGames = candidate
break
end
end
::__continue93::
end
end
local extractGamesArray
extractGamesArray = function(____, source)
if not source then
return {}
end
if type(source) == "string" then
do
local function ____catch(e)
return true, {}
end
local ____try, ____hasReturned, ____returnValue = pcall(function()
local decoded = {json.decode(source)}
return true, extractGamesArray(nil, decoded)
end)
if not ____try then
____hasReturned, ____returnValue = ____catch(____hasReturned)
end
if ____hasReturned then
return ____returnValue
end
end
end
if __TS__ArrayIsArray(source) then
local values = collectObjectValues(nil, source)
if #values > 0 then
return __TS__ArrayFilter(
values,
function(____, item) return item and type(item) == "table" end
)
end
return {}
end
if type(source) == "table" then
local directValues = __TS__ArrayFilter(
collectObjectValues(nil, source),
function(____, item) return item and type(item) == "table" end
)
if #directValues > 0 then
return directValues
end
local nested = source.items or source.data or source.rows or source.matches or source.history or source.recentGames or source.recent_games
if nested then
return extractGamesArray(nil, nested)
end
end
return {}
end
local gamesExtracted = extractGamesArray(nil, recentGames)
do
local function ____catch(sortError)
____print(
nil,
"[MiniProfileServer] Не удалось отсортировать recentGames: " .. tostring(sortError)
)
end
local ____try, ____hasReturned = pcall(function()
if type(Date) == "function" then
__TS__ArraySort(
gamesExtracted,
function(____, a, b)
local dateA = __TS__New(Date, a.game_start or a.gameStart or a.created_at or 0):getTime()
local dateB = __TS__New(Date, b.game_start or b.gameStart or b.created_at or 0):getTime()
return dateB - dateA
end
)
end
end)
if not ____try then
____catch(____hasReturned)
end
end
recentGames = gamesExtracted
____print(
nil,
"[MiniProfileServer] Extracted games: " .. tostring(#gamesExtracted)
)
____print(
nil,
(("[MiniProfileServer] Profile loaded for " .. tostring(nameFromDB)) .. ", recentGames count: ") .. tostring(__TS__ArrayIsArray(recentGames) and #recentGames or "not an array")
)
____print(
nil,
(("[MiniProfileServer] recentGames type: " .. __TS__TypeOf(recentGames)) .. ", isArray: ") .. tostring(__TS__ArrayIsArray(recentGames))
)
if not recentGames or type(recentGames) == "table" and #collectObjectKeys(nil, recentGames) == 0 then
____print(
nil,
(("[MiniProfileServer] recentGames пустой. Data keys=" .. table.concat(
collectObjectKeys(nil, data),
", "
)) .. ", profile keys=") .. (profileData and type(profileData) == "table" and table.concat(
collectObjectKeys(nil, profileData),
", "
) or "N/A")
)
end
local gamesToSend = {}
if __TS__ArrayIsArray(recentGames) then
gamesToSend = self:normalizeArrayLike(recentGames)
elseif recentGames and type(recentGames) == "table" then
gamesToSend = __TS__ArrayFilter(
collectObjectValues(nil, recentGames),
function(____, item) return item and type(item) == "table" end
)
end
if #gamesToSend == 0 then
____print(nil, "[MiniProfileServer] recentGames пустой в /player. Пробуем fallback /player/:id/history")
self:loadRecentGamesFallback(
player,
steamIdStr,
profileData,
data.stats or data,
nameFromDB,
steamId64 or steamId,
grantedLevelRewardsObject
)
return true
end
self:loadHeroAchievementsForProfile(
steamIdStr,
playerId,
shouldGrantLevelRewards,
function(____, heroAchievementsObject, grantedHeroRankRewardsObject)
self:sendProfileToClient(
player,
profileData,
data.stats or data,
gamesToSend,
steamId,
nameFromDB,
steamId64 or steamId,
grantedLevelRewardsObject,
heroAchievementsObject,
grantedHeroRankRewardsObject
)
end
)
end
end)
if not ____try then
____hasReturned, ____returnValue = ____catch(____hasReturned)
end
if ____hasReturned then
return true, ____returnValue
end
end
elseif result.StatusCode == 404 then
self:createPlayerProfile(playerId, steamId, playerName)
else
CustomGameEventManager:Send_ServerToPlayer(
player,
"player_profile_data",
{
error = "Server error: " .. tostring(result.StatusCode),
steam_id = steamId,
player_name = playerName
}
)
end
end)
if not ____try then
____hasReturned, ____returnValue = ____catch(____hasReturned)
end
if ____hasReturned then
return ____returnValue
end
end
end)
end
function MiniProfileServer.prototype.normalizeArrayLike(self, input)
if not input then
return {}
end
local function hasGameFields(____, obj)
if not obj or type(obj) ~= "table" then
return false
end
return not not (obj.hero or obj.hero_name or obj.heroName or obj.result or obj.match_result or obj.difficulty or obj.difficulty_name or obj.mode)
end
local unwrapKnownContainers
unwrapKnownContainers = function(____, value)
if not value or type(value) ~= "table" then
return value
end
local containerKeys = {
"history",
"recentGames",
"games",
"items",
"rows",
"data",
"result",
"payload"
}
for ____, key in ipairs(containerKeys) do
local nested = value[key]
if nested and type(nested) == "table" then
if key == "data" and type(nested) == "table" then
local deep = unwrapKnownContainers(nil, nested)
if deep ~= nested or __TS__ArrayIsArray(deep) then
return deep
end
end
if __TS__ArrayIsArray(nested) then
return nested
end
if hasGameFields(nil, nested) then
return {nested}
end
local nestedValues = __TS__ArrayFilter(
__TS__ObjectValues(nested),
function(____, v) return v and type(v) == "table" end
)
if #nestedValues > 0 then
return nested
end
end
end
return value
end
local unwrapped = unwrapKnownContainers(nil, input)
if unwrapped ~= input then
return self:normalizeArrayLike(unwrapped)
end
if __TS__ArrayIsArray(input) then
local arr = input
local len = #arr
if type(len) == "number" and len > 0 then
if __TS__ArraySome(
arr,
function(____, item) return hasGameFields(nil, item) end
) then
return __TS__ArrayFilter(
arr,
function(____, item) return item and type(item) == "table" end
)
end
local expanded = {}
__TS__ArrayForEach(
arr,
function(____, item)
local normalized = self:normalizeArrayLike(item)
if #normalized > 0 then
__TS__ArrayPushArray(expanded, normalized)
end
end
)
if #expanded > 0 then
return expanded
end
return __TS__ArrayFilter(
arr,
function(____, item) return item and type(item) == "table" end
)
end
end
local numericEntries = {}
local otherValues = {}
if type(input) == "table" then
for key in pairs(input) do
if not input.hasOwnProperty or rawget(input, key) ~= nil then
local value = input[key]
local numericKey = tonumber(tostring(key))
if numericKey ~= nil and numericKey ~= nil then
numericEntries[#numericEntries + 1] = {idx = numericKey, value = value}
else
otherValues[#otherValues + 1] = value
end
end
end
end
if #numericEntries > 0 then
__TS__ArraySort(
numericEntries,
function(____, a, b) return a.idx - b.idx end
)
return __TS__ArrayFilter(
__TS__ArrayMap(
numericEntries,
function(____, entry) return entry.value end
),
function(____, item) return item and type(item) == "table" end
)
end
if hasGameFields(nil, input) then
return {input}
end
local flattened = {}
__TS__ArrayForEach(
__TS__ArrayFilter(
otherValues,
function(____, item) return item and type(item) == "table" end
),
function(____, item)
local normalized = self:normalizeArrayLike(item)
if #normalized > 0 then
__TS__ArrayPushArray(flattened, normalized)
else
flattened[#flattened + 1] = item
end
end
)
return flattened
end
function MiniProfileServer.prototype.loadRecentGamesFallback(self, player, steamId, profileData, statsData, playerName, steamId64, grantedLevelRewardsObject)
if grantedLevelRewardsObject == nil then
grantedLevelRewardsObject = {}
end
local fallbackRequest = CreateHTTPRequestScriptVM("GET", ((self.serverUrl .. "/player/") .. steamId) .. "/history?limit=10&offset=0")
setApiHeaders(nil, fallbackRequest)
fallbackRequest:Send(function(result)
if result.StatusCode >= 200 and result.StatusCode < 300 then
do
local function ____catch(e)
____print(nil, "[MiniProfileServer] Fallback history parse error")
end
local ____try, ____hasReturned, ____returnValue = pcall(function()
local decoded = {json.decode(result.Body)}
local games = self:normalizeArrayLike(decoded)
____print(
nil,
("[MiniProfileServer] Fallback history loaded: " .. tostring(#games)) .. " games"
)
self:loadHeroAchievementsForProfile(
steamId,
player:GetPlayerID(),
false,
function(____, heroAchievementsObject, grantedHeroRankRewardsObject)
self:sendProfileToClient(
player,
profileData,
statsData,
games,
steamId,
playerName,
steamId64,
grantedLevelRewardsObject,
heroAchievementsObject,
grantedHeroRankRewardsObject
)
end
)
return true
end)
if not ____try then
____hasReturned, ____returnValue = ____catch(____hasReturned)
end
if ____hasReturned then
return ____returnValue
end
end
else
____print(
nil,
"[MiniProfileServer] Fallback history HTTP " .. tostring(result.StatusCode)
)
end
self:loadHeroAchievementsForProfile(
steamId,
player:GetPlayerID(),
false,
function(____, heroAchievementsObject, grantedHeroRankRewardsObject)
self:sendProfileToClient(
player,
profileData,
statsData,
{},
steamId,
playerName,
steamId64,
grantedLevelRewardsObject,
heroAchievementsObject,
grantedHeroRankRewardsObject
)
end
)
end)
end
function MiniProfileServer.prototype.sendProfileToClient(self, player, profileData, statsData, gamesToSend, steamId, playerName, steamId64, grantedLevelRewardsObject, heroAchievementsObject, grantedHeroRankRewardsObject)
if grantedLevelRewardsObject == nil then
grantedLevelRewardsObject = {}
end
if heroAchievementsObject == nil then
heroAchievementsObject = {}
end
if grantedHeroRankRewardsObject == nil then
grantedHeroRankRewardsObject = {}
end
____print(
nil,
(("[MiniProfileServer] Профиль отправлен: games=" .. tostring(#gamesToSend)) .. ", steam64=") .. steamId64
)
local gamesObject = {}
__TS__ArrayForEach(
gamesToSend,
function(____, game, index)
gamesObject[tostring(index)] = game
end
)
CustomGameEventManager:Send_ServerToPlayer(player, "player_profile_data", {
profile = profileData,
stats = statsData,
recentGames = gamesObject,
steam_id = steamId,
player_name = playerName,
player_steamid = steamId64,
profile_level_rewards_granted = grantedLevelRewardsObject,
hero_achievements = heroAchievementsObject,
hero_rank_rewards_granted = grantedHeroRankRewardsObject
})
end
function MiniProfileServer.prototype.loadHeroAchievementsForProfile(self, steamId, playerId, shouldGrantRankRewards, callback)
local allHeroes = self:getAllAvailableHeroes(playerId)
local request = CreateHTTPRequestScriptVM("GET", ((self.serverUrl .. "/player/") .. steamId) .. "/history?limit=5000&offset=0")
setApiHeaders(nil, request)
request:Send(function(result)
____print(
nil,
(("[MiniProfileServer] /history status=" .. tostring(result.StatusCode)) .. " steam_id=") .. steamId
)
if result.StatusCode < 200 or result.StatusCode >= 300 then
callback(
nil,
self:buildHeroAchievementsObject(allHeroes, {}),
{}
)
return
end
do
local function ____catch(e)
callback(
nil,
self:buildHeroAchievementsObject(allHeroes, {}),
{}
)
end
local ____try, ____hasReturned = pcall(function()
local decoded = self:decodeJsonSafe(result.Body)
local games = self:normalizeArrayLike(decoded)
____print(
nil,
"[MiniProfileServer] history entries=" .. tostring(#games)
)
do
local i = 0
while i < math.min(5, #games) do
local g = games[i + 1]
local ____i_60 = i
local ____tostring_59 = tostring
local ____opt_result_50
if g ~= nil then
____opt_result_50 = g.hero
end
local ____opt_result_50_54 = ____opt_result_50
if not ____opt_result_50_54 then
local ____opt_result_53
if g ~= nil then
____opt_result_53 = g.hero_name
end
____opt_result_50_54 = ____opt_result_53
end
local ____opt_result_50_54_58 = ____opt_result_50_54
if not ____opt_result_50_54_58 then
local ____opt_result_57
if g ~= nil then
____opt_result_57 = g.heroName
end
____opt_result_50_54_58 = ____opt_result_57
end
local ____temp_69 = (("[MiniProfileServer] raw[" .. tostring(____i_60)) .. "] hero=") .. ____tostring_59(____opt_result_50_54_58 or "")
local ____tostring_68 = tostring
local ____opt_result_63
if g ~= nil then
____opt_result_63 = g.result
end
local ____opt_result_63_67 = ____opt_result_63
if not ____opt_result_63_67 then
local ____opt_result_66
if g ~= nil then
____opt_result_66 = g.match_result
end
____opt_result_63_67 = ____opt_result_66
end
local ____temp_74 = ____temp_69 .. " result=" .. ____tostring_68(____opt_result_63_67 or "")
local ____tostring_73 = tostring
local ____opt_result_72
if g ~= nil then
____opt_result_72 = g.is_win
end
local ____temp_91 = ____temp_74 .. " is_win=" .. ____tostring_73(____opt_result_72)
local ____tostring_90 = tostring
local ____opt_result_77
if g ~= nil then
____opt_result_77 = g.difficulty
end
local ____opt_result_77_81 = ____opt_result_77
if not ____opt_result_77_81 then
local ____opt_result_80
if g ~= nil then
____opt_result_80 = g.difficulty_name
end
____opt_result_77_81 = ____opt_result_80
end
local ____opt_result_77_81_85 = ____opt_result_77_81
if not ____opt_result_77_81_85 then
local ____opt_result_84
if g ~= nil then
____opt_result_84 = g.mode
end
____opt_result_77_81_85 = ____opt_result_84
end
local ____opt_result_77_81_85_89 = ____opt_result_77_81_85
if not ____opt_result_77_81_85_89 then
local ____opt_result_88
if g ~= nil then
____opt_result_88 = g.game_mode
end
____opt_result_77_81_85_89 = ____opt_result_88
end
____print(
nil,
____temp_91 .. " difficulty=" .. ____tostring_90(____opt_result_77_81_85_89 or "")
)
i = i + 1
end
end
local aggregated = self:aggregateHeroAchievements(games)
local heroAchievementsObject = self:buildHeroAchievementsObject(allHeroes, aggregated)
local grantedHeroRankRewardsObject = {}
if shouldGrantRankRewards then
grantedHeroRankRewardsObject = self:grantPendingHeroRankRewards(playerId, heroAchievementsObject)
end
callback(nil, heroAchievementsObject, grantedHeroRankRewardsObject)
end)
if not ____try then
____catch(____hasReturned)
end
end
end)
end
function MiniProfileServer.prototype.getAllAvailableHeroes(self, playerId)
local heroes = {}
local storeManager = StoreManager:getInstance()
local enabledHeroes = self:getEnabledHeroesFromHeroList()
for heroName in pairs(enabledHeroes) do
do
local heroInfo = HERO_LIST_TABLE[heroName]
local isDonateHero = (heroInfo and heroInfo.isDonate) == true
if isDonateHero and not storeManager:hasUnlockedHero(
playerId,
tostring(heroName),
heroInfo.storeItemId
) then
goto __continue185
end
heroes[#heroes + 1] = tostring(heroName)
end
::__continue185::
end
__TS__ArraySort(
heroes,
function(____, a, b) return a < b and -1 or (a > b and 1 or 0) end
)
return heroes
end
function MiniProfileServer.prototype.getEnabledHeroesFromHeroList(self)
local enabledHeroes = {}
local rawKv = LoadKeyValues("scripts/npc/herolist.txt")
local ____temp_96 = rawKv and rawKv.CustomHeroList
if ____temp_96 == nil then
____temp_96 = rawKv
end
local heroList = ____temp_96
if heroList then
for heroName in pairs(heroList) do
local count = tonumber(tostring(heroList[heroName])) or 0
if count > 0 or count == -1 then
enabledHeroes[tostring(heroName)] = true
end
end
end
if #__TS__ObjectKeys(enabledHeroes) == 0 then
for heroName in pairs(HERO_LIST_TABLE) do
enabledHeroes[tostring(heroName)] = true
end
end
return enabledHeroes
end
function MiniProfileServer.prototype.aggregateHeroAchievements(self, games)
local stats = {}
local enabledHeroes = self:getEnabledHeroesFromHeroList()
local function normalizeDifficultyKey(____, rawDifficulty)
local key = string.lower(tostring(rawDifficulty or "normal"))
if key == "easy" or key == "difficulty_easy" or key == "лёгкая" or key == "легкая" then
return "easy"
end
if key == "normal" or key == "difficulty_normal" or key == "обычная" or key == "normal_mode" then
return "normal"
end
if key == "hard" or key == "difficulty_hard" or key == "сложная" then
return "hard"
end
if key == "impossible" or key == "difficulty_impossible" or key == "невозможная" or key == "imposible" then
return "impossible"
end
if key == "death_sentence" or key == "difficulty_death_sentence" or key == "смертельный приговор" or key == "deathsentence" then
return "death_sentence"
end
return "normal"
end
local function getRankByDifficulty(____, difficulty)
local key = normalizeDifficultyKey(nil, difficulty)
if key == "easy" then
return 1
end
if key == "normal" then
return 3
end
if key == "hard" then
return 6
end
if key == "impossible" then
return 8
end
if key == "death_sentence" then
return 10
end
return 0
end
local function isWinResult(____, game)
local ____opt_result_99
if game ~= nil then
____opt_result_99 = game.is_win
end
local directWin = ____opt_result_99
if directWin == true or directWin == 1 or tostring(directWin) == "1" then
return true
end
local ____tonumber_103 = tonumber
local ____opt_result_102
if game ~= nil then
____opt_result_102 = game.result
end
local numericResult = ____tonumber_103(____opt_result_102)
if numericResult == 1 then
return true
end
local ____tostring_111 = tostring
local ____opt_result_106
if game ~= nil then
____opt_result_106 = game.result
end
local ____opt_result_106_110 = ____opt_result_106
if not ____opt_result_106_110 then
local ____opt_result_109
if game ~= nil then
____opt_result_109 = game.match_result
end
____opt_result_106_110 = ____opt_result_109
end
local key = string.lower(____tostring_111(____opt_result_106_110 or ""))
return key == "win" or key == "victory" or key == "won" or key == "radiant_win" or key == "dire_win" or key == "success"
end
local function normalizeHeroName(____, rawHero)
local base = tostring(rawHero or "")
if base == "" then
return ""
end
if string.sub(base, 1, 14) == "npc_dota_hero_" then
return base
end
local normalized = "npc_dota_hero_" .. base
if enabledHeroes[normalized] ~= nil then
return normalized
end
return base
end
__TS__ArrayForEach(
games,
function(____, game, index)
if not game or type(game) ~= "table" then
return
end
local hero = normalizeHeroName(nil, game.hero or game.hero_name or game.heroName)
if hero == "" or string.sub(hero, 1, 14) ~= "npc_dota_hero_" then
return
end
if not (enabledHeroes[hero] ~= nil) then
return
end
if not (stats[hero] ~= nil) then
stats[hero] = {games = 0, wins = 0, impossibleWins = 0, bestRank = 0}
end
local heroStats = stats[hero]
heroStats.games = heroStats.games + 1
local difficulty = normalizeDifficultyKey(nil, game.difficulty or game.difficulty_name or game.mode or game.game_mode)
local win = isWinResult(nil, game)
if index < 8 then
local ____temp_125 = (((((("[MiniProfileServer] normalized[" .. tostring(index)) .. "] hero=") .. hero) .. " difficulty=") .. difficulty) .. " win=") .. tostring(win)
local ____tostring_119 = tostring
local ____opt_result_114
if game ~= nil then
____opt_result_114 = game.result
end
local ____opt_result_114_118 = ____opt_result_114
if not ____opt_result_114_118 then
local ____opt_result_117
if game ~= nil then
____opt_result_117 = game.match_result
end
____opt_result_114_118 = ____opt_result_117
end
local ____tostring_119_result_124 = ____tostring_119(____opt_result_114_118 or "")
local ____tostring_123 = tostring
local ____opt_result_122
if game ~= nil then
____opt_result_122 = game.is_win
end
____print(
nil,
____temp_125 .. ((" raw_result=" .. ____tostring_119_result_124) .. " raw_is_win=") .. ____tostring_123(____opt_result_122)
)
end
if win then
heroStats.wins = heroStats.wins + 1
heroStats.bestRank = math.max(
heroStats.bestRank,
getRankByDifficulty(nil, difficulty)
)
if difficulty == "impossible" then
heroStats.impossibleWins = heroStats.impossibleWins + 1
end
end
end
)
local keys = __TS__ObjectKeys(stats)
____print(
nil,
"[MiniProfileServer] aggregated heroes=" .. tostring(#keys)
)
__TS__ArrayForEach(
keys,
function(____, heroName, idx)
if idx >= 8 then
return
end
local s = stats[heroName]
____print(
nil,
((((("[MiniProfileServer] stats[" .. heroName) .. "] games=") .. tostring(s.games)) .. " wins=") .. tostring(s.wins)) .. ((" best_rank=" .. tostring(s.bestRank)) .. " impossible_wins=") .. tostring(s.impossibleWins)
)
end
)
return stats
end
function MiniProfileServer.prototype.buildHeroAchievementsObject(self, allHeroes, aggregated)
local out = {}
__TS__ArrayForEach(
allHeroes,
function(____, heroName, index)
local heroStats = aggregated[heroName] or ({games = 0, wins = 0, impossibleWins = 0, bestRank = 0})
local games = heroStats.games
local wins = heroStats.wins
local impossibleWins = heroStats.impossibleWins
local winRate = games > 0 and math.floor(wins / games * 1000) / 10 or 0
out[tostring(index)] = {
hero = heroName,
games = games,
wins = wins,
win_rate = winRate,
best_rank = heroStats.bestRank,
impossible_wins = impossibleWins
}
end
)
return out
end
function MiniProfileServer.prototype.getHeroRankRewardAmount(self, tier)
if tier == "rank1" then
return 100
end
if tier == "rank3" then
return 200
end
if tier == "rank6" then
return 400
end
if tier == "rank8a" then
return 800
end
if tier == "rank8b" then
return 1200
end
if tier == "rank8c" then
return 2000
end
return 0
end
function MiniProfileServer.prototype.getHeroAchievementTier(self, bestRank, impossibleWins)
if bestRank >= 8 then
if impossibleWins >= 100 then
return "rank8c"
end
if impossibleWins >= 10 then
return "rank8b"
end
return "rank8a"
end
if bestRank >= 6 then
return "rank6"
end
if bestRank >= 3 then
return "rank3"
end
if bestRank >= 1 then
return "rank1"
end
return "rank0"
end
function MiniProfileServer.prototype.grantPendingHeroRankRewards(self, playerId, heroAchievementsObject)
local storeManager = StoreManager:getInstance()
if not self.grantedHeroRankRewardsInSession:has(playerId) then
self.grantedHeroRankRewardsInSession:set(
playerId,
__TS__New(Set)
)
end
local sessionGranted = self.grantedHeroRankRewardsInSession:get(playerId)
local grantedNow = {}
local rewardsToCheck = {
"rank1",
"rank3",
"rank6",
"rank8a",
"rank8b",
"rank8c"
}
local achievementsArray = self:normalizeArrayLike(heroAchievementsObject)
local grantedIndex = 0
__TS__ArrayForEach(
achievementsArray,
function(____, entry)
local hero = tostring(entry.hero or "")
if hero == "" then
return
end
local bestRank = tonumber(entry.best_rank) or 0
local impossibleWins = tonumber(entry.impossible_wins) or 0
local currentTier = self:getHeroAchievementTier(bestRank, impossibleWins)
local currentTierIndex = __TS__ArrayIndexOf(rewardsToCheck, currentTier)
if currentTierIndex < 0 then
return
end
do
local i = 0
while i <= currentTierIndex do
do
local tier = rewardsToCheck[i + 1]
local amount = self:getHeroRankRewardAmount(tier)
if amount <= 0 then
goto __continue248
end
local rewardItemId = (("hero_rank_reward_" .. hero) .. "_") .. tier
if sessionGranted:has(rewardItemId) then
____print(nil, "[MiniProfileServer] reward skip (session) " .. rewardItemId)
goto __continue248
end
if storeManager:hasPurchasedItem(playerId, rewardItemId) then
____print(nil, "[MiniProfileServer] reward skip (already purchased) " .. rewardItemId)
sessionGranted:add(rewardItemId)
goto __continue248
end
local added = storeManager:addFreeCurrency(playerId, amount)
if not added then
____print(
nil,
(("[MiniProfileServer] reward addFreeCurrency failed " .. rewardItemId) .. " amount=") .. tostring(amount)
)
goto __continue248
end
storeManager:savePurchaseToServer(playerId, rewardItemId, "hero_rank_reward")
____print(
nil,
(("[MiniProfileServer] reward granted " .. rewardItemId) .. " amount=") .. tostring(amount)
)
sessionGranted:add(rewardItemId)
grantedNow[tostring(grantedIndex)] = {hero = hero, tier = tier, freeCurrency = amount}
grantedIndex = grantedIndex + 1
end
::__continue248::
i = i + 1
end
end
end
)
return grantedNow
end
function MiniProfileServer.prototype.loadMatchPlayersFromServer(self, player, matchId, rowId, steamId)
if rowId == nil then
rowId = 0
end
if steamId == nil then
steamId = ""
end
local idsToTry = {}
local function addId(____, value)
if value > 0 and __TS__ArrayIndexOf(idsToTry, value) == -1 then
idsToTry[#idsToTry + 1] = value
end
end
addId(nil, matchId)
addId(nil, rowId)
local endpoints = {}
__TS__ArrayForEach(
idsToTry,
function(____, id)
endpoints[#endpoints + 1] = ((self.serverUrl .. "/game/") .. tostring(id)) .. "/players"
end
)
if steamId ~= "" then
__TS__ArrayForEach(
idsToTry,
function(____, id)
endpoints[#endpoints + 1] = ((((self.serverUrl .. "/player/") .. steamId) .. "/history?match_id=") .. tostring(id)) .. "&limit=10&offset=0"
endpoints[#endpoints + 1] = ((((self.serverUrl .. "/player/") .. steamId) .. "/history?game_id=") .. tostring(id)) .. "&limit=10&offset=0"
endpoints[#endpoints + 1] = ((((self.serverUrl .. "/player/") .. steamId) .. "/history?id=") .. tostring(id)) .. "&limit=10&offset=0"
end
)
end
local function collectObjectValues(____, obj)
local out = {}
if not obj or type(obj) ~= "table" then
return out
end
for key in pairs(obj) do
out[#out + 1] = obj[key]
end
return out
end
local extractPlayers
extractPlayers = function(____, source)
if not source then
return {}
end
if __TS__ArrayIsArray(source) then
local normalizedArray = __TS__ArrayFilter(
self:normalizeArrayLike(source),
function(____, item) return item and type(item) == "table" end
)
local playersFromParty = {}
__TS__ArrayForEach(
normalizedArray,
function(____, item)
local nestedParty = item.party_players or item.partyPlayers or item.players or item.participants or item.match_players
if nestedParty then
local nested = extractPlayers(nil, nestedParty)
__TS__ArrayForEach(
nested,
function(____, p)
local ____temp_126 = #playersFromParty + 1
playersFromParty[____temp_126] = p
return ____temp_126
end
)
end
end
)
if #playersFromParty > 0 then
return playersFromParty
end
return normalizedArray
end
if type(source) == "table" then
local directPlayers = source.players or source.participants or source.match_players or source.party_players or source.partyPlayers or source.items or source.rows or source.data
if directPlayers then
return extractPlayers(nil, directPlayers)
end
return __TS__ArrayFilter(
collectObjectValues(nil, source),
function(____, item) return item and type(item) == "table" end
)
end
return {}
end
local tryRequest
tryRequest = function(____, index)
if index >= #endpoints then
CustomGameEventManager:Send_ServerToPlayer(player, "match_players_data", {error = "Failed to load match participants", match_id = matchId, players = {}})
return
end
local request = CreateHTTPRequestScriptVM("GET", endpoints[index + 1])
setApiHeaders(nil, request)
request:Send(function(result)
if result.StatusCode < 200 or result.StatusCode >= 300 then
____print(
nil,
(("[MiniProfileServer] match players endpoint failed: " .. endpoints[index + 1]) .. " status=") .. tostring(result.StatusCode)
)
tryRequest(nil, index + 1)
return
end
local decoded = self:decodeJsonSafe(result.Body)
if decoded == nil then
____print(nil, "[MiniProfileServer] match players decode failed: " .. endpoints[index + 1])
tryRequest(nil, index + 1)
return
end
local players = extractPlayers(nil, decoded)
if #players == 0 and index < #endpoints - 1 then
____print(nil, ("[MiniProfileServer] Endpoint " .. endpoints[index + 1]) .. " returned 0 players, trying next")
tryRequest(nil, index + 1)
return
end
local playersObject = {}
__TS__ArrayForEach(
players,
function(____, item, idx)
playersObject[tostring(idx)] = item
end
)
CustomGameEventManager:Send_ServerToPlayer(player, "match_players_data", {match_id = matchId, players = playersObject})
end)
end
tryRequest(nil, 0)
end
function MiniProfileServer.prototype.addBigInts(self, a, b)
local maxLen = math.max(
string.len(a),
string.len(b)
)
a = string.rep(
"0",
maxLen - string.len(a)
) .. a
b = string.rep(
"0",
maxLen - string.len(b)
) .. b
local result = ""
local carry = 0
do
local i = maxLen
while i >= 1 do
local digitA = tonumber(string.sub(a, i, i)) or 0
local digitB = tonumber(string.sub(b, i, i)) or 0
local sum = digitA + digitB + carry
result = tostring(sum % 10) .. result
carry = math.floor(sum / 10)
i = i - 1
end
end
if carry > 0 then
result = tostring(carry) .. result
end
return result
end
function MiniProfileServer.prototype.subtractBigInts(self, a, b)
local maxLen = math.max(
string.len(a),
string.len(b)
)
a = string.rep(
"0",
maxLen - string.len(a)
) .. a
b = string.rep(
"0",
maxLen - string.len(b)
) .. b
local result = ""
local borrow = 0
do
local i = maxLen
while i >= 1 do
local digitA = tonumber(string.sub(a, i, i)) or 0
local digitB = tonumber(string.sub(b, i, i)) or 0
local diff = digitA - digitB - borrow
if diff < 0 then
diff = diff + 10
borrow = 1
else
borrow = 0
end
result = tostring(diff) .. result
i = i - 1
end
end
result = (string.gsub(result, "^0+", ""))
if result == "" then
result = "0"
end
return result
end
function MiniProfileServer.prototype.decodeJsonSafe(self, rawBody)
do
local function ____catch(e)
local body = tostring(rawBody)
local firstObj = {string.find(body, "{", 1, true)}
local firstArr = {string.find(body, "[", 1, true)}
local first = nil
if firstObj ~= nil and firstArr ~= nil then
first = math.min(firstObj[1], firstArr[1])
elseif firstObj ~= nil then
first = firstObj[1]
elseif firstArr ~= nil then
first = firstArr[1]
end
if first == nil then
return true, nil
end
local lastObj = {string.find(body, "}", -1, true)}
local lastArr = {string.find(body, "]", -1, true)}
local last = nil
if lastObj ~= nil and lastArr ~= nil then
last = math.max(lastObj[1], lastArr[1])
elseif lastObj ~= nil then
last = lastObj[1]
elseif lastArr ~= nil then
last = lastArr[1]
end
if last == nil or last < first then
return true, nil
end
local sliced = string.sub(body, first, last)
do
local function ____catch(e2)
return true, nil
end
local ____try, ____hasReturned, ____returnValue = pcall(function()
return true, {json.decode(sliced)}
end)
if not ____try then
____hasReturned, ____returnValue = ____catch(____hasReturned)
end
if ____hasReturned then
return true, ____returnValue
end
end
end
local ____try, ____hasReturned, ____returnValue = pcall(function()
return true, {json.decode(rawBody)}
end)
if not ____try then
____hasReturned, ____returnValue = ____catch(____hasReturned)
end
if ____hasReturned then
return ____returnValue
end
end
end
function MiniProfileServer.prototype.grantPendingProfileLevelRewards(self, playerId, profileLevel)
if profileLevel <= 0 then
return {}
end
local storeManager = StoreManager:getInstance()
if not self.grantedProfileRewardsInSession:has(playerId) then
self.grantedProfileRewardsInSession:set(
playerId,
__TS__New(Set)
)
end
local sessionGrantedSet = self.grantedProfileRewardsInSession:get(playerId)
local grantedNow = {}
__TS__ArrayForEach(
self.profileLevelRewards,
function(____, reward)
if reward.level > profileLevel then
return
end
local rewardItemId = "profile_level_reward_" .. tostring(reward.level)
if sessionGrantedSet:has(rewardItemId) then
return
end
if storeManager:hasPurchasedItem(playerId, rewardItemId) then
sessionGrantedSet:add(rewardItemId)
return
end
local added = storeManager:addFreeCurrency(playerId, reward.freeCurrency)
if not added then
return
end
storeManager:savePurchaseToServer(playerId, rewardItemId, "profile_level_reward")
sessionGrantedSet:add(rewardItemId)
grantedNow[#grantedNow + 1] = {level = reward.level, freeCurrency = reward.freeCurrency}
____print(
nil,
(((("[MiniProfileServer] Выдана награда за уровень " .. tostring(reward.level)) .. ": +") .. tostring(reward.freeCurrency)) .. " осколков игроку ") .. tostring(playerId)
)
end
)
return grantedNow
end
if IsServer() then
(function()
Timers:CreateTimer(
1,
function()
do
local function ____catch(____error)
return true, nil
end
local ____try, ____hasReturned, ____returnValue = pcall(function()
local miniProfileServer = ____exports.MiniProfileServer:getInstance()
return true, nil
end)
if not ____try then
____hasReturned, ____returnValue = ____catch(____hasReturned)
end
if ____hasReturned then
return ____returnValue
end
end
end
)
end)(nil)
end
return ____exports