@j03fr0st/pubg-ts
Version:
A comprehensive TypeScript wrapper for the PUBG API
478 lines • 18.6 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.assetManager = exports.AssetManager = void 0;
// Import the synced asset data and types
const fuse_js_1 = __importDefault(require("fuse.js"));
const damage_causer_name_json_1 = __importDefault(require("../assets/dictionaries/damage-causer-name.json"));
const damage_type_category_json_1 = __importDefault(require("../assets/dictionaries/damage-type-category.json"));
const game_mode_json_1 = __importDefault(require("../assets/dictionaries/game-mode.json"));
const item_id_json_1 = __importDefault(require("../assets/dictionaries/item-id.json"));
const map_name_json_1 = __importDefault(require("../assets/dictionaries/map-name.json"));
const vehicle_id_json_1 = __importDefault(require("../assets/dictionaries/vehicle-id.json"));
// Import the JSON files directly
const seasons_json_1 = __importDefault(require("../assets/seasons.json"));
const survival_titles_json_1 = __importDefault(require("../assets/survival-titles.json"));
const errors_1 = require("../errors");
const logger_1 = require("./logger");
class AssetManager {
constructor(config = {}) {
this.cache = new Map();
this.itemCache = new Map();
this.vehicleCache = new Map();
this.seasonCache = new Map();
this.validateConfig(config);
this.config = {
baseUrl: 'https://raw.githubusercontent.com/pubg/api-assets/master',
version: 'latest',
cacheAssets: true,
useLocalData: true, // Default to using local synced data
...config,
};
// Build search indexes
const allItems = Object.keys(item_id_json_1.default).map((id) => this.getItemInfo(id));
this.itemSearchIndex = new fuse_js_1.default(allItems, {
keys: ['name', 'category', 'subcategory', 'description'],
includeScore: true,
threshold: 0.4,
});
logger_1.logger.client('AssetManager initialized with search indexes', {
config: this.config,
usingLocalData: this.config.useLocalData,
});
}
/**
* Get user-friendly item name with type safety
*/
getItemName(itemId) {
if (this.config.useLocalData) {
return item_id_json_1.default[itemId] || this.humanizeItemId(itemId);
}
// Legacy network fallback - would need async version
return this.humanizeItemId(itemId);
}
/**
* Get detailed item information with enhanced metadata
*/
getItemInfo(itemId) {
if (!itemId || typeof itemId !== 'string') {
throw new errors_1.PubgAssetError('Invalid item ID provided', itemId || 'undefined', 'item', {
operation: 'get_item_info',
metadata: { providedId: itemId },
});
}
if (this.itemCache.has(itemId)) {
return this.itemCache.get(itemId);
}
const name = this.getItemName(itemId);
if (name === this.humanizeItemId(itemId) && !(itemId in item_id_json_1.default)) {
return null; // Item doesn't exist in official data
}
const info = {
id: itemId,
name,
category: this.categorizeItem(itemId),
subcategory: this.subcategorizeItem(itemId),
description: name,
};
this.itemCache.set(itemId, info);
return info;
}
/**
* Get all items by category with type safety
*/
getItemsByCategory(category) {
const items = [];
for (const itemId of Object.keys(item_id_json_1.default)) {
const info = this.getItemInfo(itemId);
if (info && info.category === category) {
items.push(info);
}
}
return items.sort((a, b) => a.name.localeCompare(b.name));
}
/**
* Search items by name using fuzzy search.
* @param query The search query.
* @returns An array of item information, sorted by relevance.
*/
searchItems(query) {
if (query.length < 2) {
return [];
}
const results = this.itemSearchIndex.search(query);
return results.map((result) => result.item);
}
/**
* Get user-friendly vehicle name with type safety
*/
getVehicleName(vehicleId) {
if (this.config.useLocalData) {
return (vehicle_id_json_1.default[vehicleId] || this.humanizeVehicleId(vehicleId));
}
return this.humanizeVehicleId(vehicleId);
}
/**
* Get detailed vehicle information
*/
getVehicleInfo(vehicleId) {
if (!vehicleId || typeof vehicleId !== 'string') {
throw new errors_1.PubgAssetError('Invalid vehicle ID provided', vehicleId || 'undefined', 'vehicle', {
operation: 'get_vehicle_info',
metadata: { providedId: vehicleId },
});
}
if (this.vehicleCache.has(vehicleId)) {
return this.vehicleCache.get(vehicleId);
}
const name = this.getVehicleName(vehicleId);
if (name === this.humanizeVehicleId(vehicleId) && !(vehicleId in vehicle_id_json_1.default)) {
return null;
}
const info = {
id: vehicleId,
name,
type: this.categorizeVehicle(vehicleId),
category: 'vehicle',
description: name,
};
this.vehicleCache.set(vehicleId, info);
return info;
}
/**
* Get user-friendly map name with type safety
*/
getMapName(mapId) {
if (this.config.useLocalData) {
return map_name_json_1.default[mapId] || this.humanizeMapId(mapId);
}
return this.humanizeMapId(mapId);
}
/**
* Get all available maps
*/
getAllMaps() {
return Object.entries(map_name_json_1.default).map(([id, name]) => ({
id,
name,
}));
}
/**
* Get season information by platform
*/
getSeasonsByPlatform(platform) {
const validPlatforms = ['PC', 'XBOX', 'PS4', 'Stadia'];
if (!validPlatforms.includes(platform)) {
throw new errors_1.PubgConfigurationError(`Invalid platform '${platform}'. Valid platforms are: ${validPlatforms.join(', ')}`, 'platform', 'Platform', platform);
}
if (this.seasonCache.has(platform)) {
return this.seasonCache.get(platform);
}
const platformSeasons = seasons_json_1.default[platform] || [];
const enhancedSeasons = platformSeasons.map((season) => ({
id: season.id,
platform,
name: this.humanizeSeasonId(season.id),
startDate: season.attributes.startDate,
endDate: season.attributes.endDate,
isActive: this.isSeasonActive(season.attributes.startDate, season.attributes.endDate),
isOffseason: season.attributes.endDate === '00-00-0000',
}));
this.seasonCache.set(platform, enhancedSeasons);
return enhancedSeasons;
}
/**
* Get current active season for a platform
*/
getCurrentSeason(platform = 'PC') {
if (!platform || typeof platform !== 'string') {
throw new errors_1.PubgConfigurationError('Invalid platform provided', 'platform', 'Platform', platform);
}
const seasons = this.getSeasonsByPlatform(platform);
return seasons.find((s) => s.isActive) || null;
}
/**
* Get survival title information
*/
getSurvivalTitle(rating) {
if (typeof rating !== 'number' || rating < 0 || !Number.isFinite(rating)) {
throw new errors_1.PubgAssetError('Invalid survival rating provided', String(rating), 'survival_title', { operation: 'get_survival_title', metadata: { providedRating: rating } });
}
const titles = survival_titles_json_1.default;
// Find the appropriate title based on rating
for (const [titleName, titleData] of Object.entries(titles)) {
if (typeof titleData === 'object' && titleData !== null && titleData.levels) {
const levels = titleData.levels;
for (const levelInfo of levels) {
if (this.isRatingInRange(rating, levelInfo.survivalPoints)) {
return {
title: titleName,
level: levelInfo.level,
pointsRequired: levelInfo.survivalPoints,
description: `${titleName} Level ${levelInfo.level}`,
};
}
}
}
}
return null;
}
/**
* Get damage causer name
*/
getDamageCauserName(causerId) {
return damage_causer_name_json_1.default[causerId] || causerId;
}
/**
* Get damage type category
*/
getDamageTypeCategory(damageType) {
return damage_type_category_json_1.default[damageType] || damageType;
}
/**
* Get game mode name
*/
getGameModeName(gameModeId) {
return game_mode_json_1.default[gameModeId] || gameModeId;
}
// Legacy async methods for backward compatibility
/**
* @deprecated Use getSeasonsByPlatform('PC') for better performance with local data.
* This method will be removed in v2.0.0.
*
* @example
* // Instead of:
* const seasons = await assetManager.getSeasons();
*
* // Use:
* const seasons = assetManager.getSeasonsByPlatform('PC');
*/
async getSeasons() {
if (process.env.NODE_ENV !== 'test') {
console.warn('[DEPRECATION WARNING] AssetManager.getSeasons() is deprecated. ' +
'Use getSeasonsByPlatform() for better performance with local data. ' +
'This method will be removed in v2.0.0.');
}
return this.getSeasonsByPlatform('PC');
}
/**
* Get asset URL for items, weapons, vehicles, etc.
*/
getAssetUrl(category, itemId, type = 'icon') {
const cleanId = this.cleanItemId(itemId);
return `${this.config.baseUrl}/assets/${category}/${type}s/${cleanId}.png`;
}
/**
* Get weapon asset URL with type safety
*/
getWeaponAssetUrl(weaponId, type = 'icon') {
return this.getAssetUrl('weapons', weaponId, type);
}
/**
* Get equipment asset URL with type safety
*/
getEquipmentAssetUrl(equipmentId, type = 'icon') {
return this.getAssetUrl('equipment', equipmentId, type);
}
/**
* Get vehicle asset URL with type safety
*/
getVehicleAssetUrl(vehicleId, type = 'icon') {
return this.getAssetUrl('vehicles', vehicleId, type);
}
/**
* Get statistics about the asset data
*/
getAssetStats() {
const items = Object.keys(item_id_json_1.default);
const categoryCounts = {};
for (const itemId of items) {
const category = this.categorizeItem(itemId);
categoryCounts[category] = (categoryCounts[category] || 0) + 1;
}
return {
totalItems: items.length,
totalVehicles: Object.keys(vehicle_id_json_1.default).length,
totalMaps: Object.keys(map_name_json_1.default).length,
categoryCounts,
};
}
/**
* Clear asset cache
*/
clearCache() {
try {
this.cache.clear();
this.itemCache.clear();
this.vehicleCache.clear();
this.seasonCache.clear();
logger_1.logger.cache('All asset caches cleared');
}
catch (error) {
throw new errors_1.PubgCacheError('Failed to clear asset caches', 'all_caches', 'cleanup', {
metadata: { originalError: error },
});
}
}
// Private helper methods
categorizeItem(itemId) {
if (itemId.includes('Weapon'))
return 'weapon';
if (itemId.includes('Heal') || itemId.includes('Boost'))
return 'consumable';
if (itemId.includes('Attach'))
return 'attachment';
if (itemId.includes('Armor') || itemId.includes('Back'))
return 'equipment';
if (itemId.includes('Ammo'))
return 'ammunition';
return 'other';
}
subcategorizeItem(itemId) {
// Weapons
if (itemId.includes('AR') ||
itemId.includes('AK') ||
itemId.includes('M416') ||
itemId.includes('SCAR'))
return 'assault_rifle';
if (itemId.includes('SMG') || itemId.includes('UMP') || itemId.includes('Vector'))
return 'smg';
if (itemId.includes('SR') || itemId.includes('Kar98') || itemId.includes('AWM'))
return 'sniper_rifle';
if (itemId.includes('Shotgun') || itemId.includes('S686') || itemId.includes('S1897'))
return 'shotgun';
if (itemId.includes('Pistol') || itemId.includes('P92') || itemId.includes('P1911'))
return 'pistol';
// Healing
if (itemId.includes('Bandage'))
return 'healing';
if (itemId.includes('FirstAid'))
return 'healing';
if (itemId.includes('MedKit'))
return 'healing';
if (itemId.includes('Drink') || itemId.includes('Pill'))
return 'boost';
// Attachments
if (itemId.includes('Upper'))
return 'sight';
if (itemId.includes('Lower'))
return 'grip';
if (itemId.includes('Muzzle'))
return 'muzzle';
if (itemId.includes('Magazine'))
return 'magazine';
return 'general';
}
categorizeVehicle(vehicleId) {
if (vehicleId.includes('Motorbike') || vehicleId.includes('Motorcycle'))
return 'two_wheeler';
if (vehicleId.includes('Car') || vehicleId.includes('Pickup') || vehicleId.includes('Van'))
return 'four_wheeler';
if (vehicleId.includes('Boat') || vehicleId.includes('Ship'))
return 'watercraft';
if (vehicleId.includes('Plane') || vehicleId.includes('Glider'))
return 'aircraft';
return 'unknown';
}
humanizeItemId(itemId) {
return itemId
.replace(/^Item_/, '')
.replace(/_C$/, '')
.replace(/_/g, ' ')
.replace(/\b\w/g, (l) => l.toUpperCase());
}
humanizeVehicleId(vehicleId) {
return vehicleId
.replace(/^BP_/, '')
.replace(/_\d+_C$/, '')
.replace(/_/g, ' ')
.replace(/\b\w/g, (l) => l.toUpperCase());
}
humanizeMapId(mapId) {
return mapId.replace(/([A-Z])/g, ' $1').trim();
}
humanizeSeasonId(seasonId) {
// Extract season info from ID like "division.bro.official.pc-2018-01"
const parts = seasonId.split('.');
const lastPart = parts[parts.length - 1];
const match = lastPart.match(/(\w+)-(\d{4})-(\d{2})/);
if (match) {
const [, platform, year, season] = match;
return `${platform.toUpperCase()} Season ${parseInt(season)} (${year})`;
}
return seasonId;
}
isSeasonActive(startDate, endDate) {
if (endDate === '00-00-0000')
return true; // Ongoing season
const now = new Date();
const start = this.parseDate(startDate);
const end = this.parseDate(endDate);
return start <= now && now <= end;
}
parseDate(dateStr) {
if (!dateStr || typeof dateStr !== 'string') {
throw new errors_1.PubgValidationError('Invalid date string provided', {
operation: 'parse_date',
metadata: { providedDate: dateStr },
});
}
// Handle MM-DD-YYYY format
const parts = dateStr.split('-');
if (parts.length !== 3) {
throw new errors_1.PubgValidationError(`Invalid date format '${dateStr}'. Expected MM-DD-YYYY format`, { operation: 'parse_date', metadata: { providedDate: dateStr, format: 'MM-DD-YYYY' } });
}
const [month, day, year] = parts.map(Number);
if (Number.isNaN(month) || Number.isNaN(day) || Number.isNaN(year)) {
throw new errors_1.PubgValidationError(`Invalid date components in '${dateStr}'. All parts must be numeric`, { operation: 'parse_date', metadata: { month, day, year } });
}
return new Date(year, month - 1, day);
}
isRatingInRange(rating, range) {
const rangeStr = String(range);
if (rangeStr.includes('+')) {
const minRating = parseInt(rangeStr.replace('+', ''));
return rating >= minRating;
}
if (rangeStr.includes('-')) {
const [min, max] = rangeStr.split('-').map(Number);
return rating >= min && rating <= max;
}
// Handle exact number matches
const exactNumber = parseInt(rangeStr);
if (!Number.isNaN(exactNumber)) {
return rating === exactNumber;
}
return false;
}
cleanItemId(itemId) {
return itemId
.replace(/^Item_/, '')
.replace(/^BP_/, '')
.replace(/_\d+_C$/, '')
.replace(/_C$/, '');
}
/**
* Validate configuration object
*/
validateConfig(config) {
if (config.baseUrl && typeof config.baseUrl !== 'string') {
throw new errors_1.PubgConfigurationError('baseUrl must be a string', 'baseUrl', 'string', config.baseUrl);
}
if (config.version && typeof config.version !== 'string') {
throw new errors_1.PubgConfigurationError('version must be a string', 'version', 'string', config.version);
}
if (config.cacheAssets !== undefined && typeof config.cacheAssets !== 'boolean') {
throw new errors_1.PubgConfigurationError('cacheAssets must be a boolean', 'cacheAssets', 'boolean', config.cacheAssets);
}
if (config.useLocalData !== undefined && typeof config.useLocalData !== 'boolean') {
throw new errors_1.PubgConfigurationError('useLocalData must be a boolean', 'useLocalData', 'boolean', config.useLocalData);
}
}
}
exports.AssetManager = AssetManager;
// Export a default instance
exports.assetManager = new AssetManager();
//# sourceMappingURL=assets.js.map