diff --git a/cli/lib/main.dart b/cli/lib/main.dart index 6a48004..40b6a8d 100644 --- a/cli/lib/main.dart +++ b/cli/lib/main.dart @@ -1,60 +1,95 @@ -import 'package:interact/interact.dart'; -import 'package:reboot_cli/cli.dart'; -import 'package:tint/tint.dart'; +import 'dart:io'; +import 'dart:isolate'; +import 'package:interact_cli/interact_cli.dart'; +import 'package:reboot_cli/src/controller/config.dart'; +import 'package:reboot_cli/src/util/console.dart'; +import 'package:reboot_cli/src/util/extensions.dart'; +import 'package:reboot_common/common.dart'; +import 'package:tint/tint.dart'; +import 'package:version/version.dart'; + +const Command _buildList = Command(name: 'list', parameters: [], subCommands: []); const Command _buildImport = Command(name: 'import', parameters: ['version', 'path'], subCommands: []); const Command _buildDownload = Command(name: 'download', parameters: ['version', 'path'], subCommands: []); -const Command _build = Command(name: 'build', parameters: [], subCommands: [_buildImport, _buildDownload]); +const Command _build = Command(name: 'versions', parameters: [], subCommands: [_buildList, _buildImport, _buildDownload]); const Command _play = Command(name: 'play', parameters: [], subCommands: []); const Command _host = Command(name: 'host', parameters: [], subCommands: []); const Command _backend = Command(name: 'backend', parameters: [], subCommands: []); +final List _versions = downloadableBuilds.map((build) => build.version.toString()).toList(growable: false); -void main(List args) { - _welcome(); +void main(List args) async { + enableLoggingToConsole = false; + useDefaultPath = true; - final parser = Parser(commands: [_build, _play, _host, _backend]); + print(""" +🎮 Reboot Launcher +🔥 Launch, manage, and play Fortnite using Project Reboot! +🚀 Developed by Auties00 - Version 10.0.7 +""".green()); + + final parser = ConsoleParser( + commands: [ + _build, + _play, + _host, + _backend + ] + ); final command = parser.parse(args); - print(command); - _handleRootCommand(command); + await _handleRootCommand(command); } -void _handleRootCommand(CommandCall? call) { - switch(call == null ? null : call.name) { - case 'build': - _handleBuildCommand(call?.subCall); +Future _handleRootCommand(CommandCall? command) async { + if(command == null) { + await _askRootCommand(); + return; + } + + switch (command.name) { + case 'versions': + await _handleBuildCommand(command.subCall); break; case 'play': - _handleBuildCommand(call?.subCall); + _handlePlayCommand(command.subCall); break; case 'host': - _handleBuildCommand(call?.subCall); + _handleHostCommand(command.subCall); break; case 'backend': - _handleBuildCommand(call?.subCall); + _handleBackendCommand(command.subCall); break; default: - _askRootCommand(); + await _askRootCommand(); break; } } -void _askRootCommand() { +Future _askRootCommand() async { final commands = [_build.name, _play.name, _host.name, _backend.name]; final commandSelector = Select.withTheme( prompt: ' Select a command:', options: commands, - theme: Theme.colorfulTheme.copyWith(inputPrefix: '❓', inputSuffix: '') + theme: Theme.colorfulTheme.copyWith(inputPrefix: '❓', inputSuffix: '', successSuffix: '', errorPrefix: '❌') ); - _handleRootCommand(CommandCall(name: commands[commandSelector.interact()])); + await _handleRootCommand(CommandCall(name: commands[commandSelector.interact()])); } -void _handleBuildCommand(CommandCall? call) { - switch(call == null ? null : call.name) { +Future _handleBuildCommand(CommandCall? call) async { + if(call == null) { + _askBuildCommand(); + return; + } + + switch(call.name) { case 'import': - _handleBuildImportCommand(call!); + await _handleBuildImportCommand(call); break; case 'download': - _handleBuildDownloadCommand(call!); + _handleBuildDownloadCommand(call); + break; + case 'list': + _handleBuildListCommand(call); break; default: _askBuildCommand(); @@ -62,23 +97,283 @@ void _handleBuildCommand(CommandCall? call) { } } -void _handleBuildImportCommand(CommandCall call) { - final version = call.parameters['path']; - final path = call.parameters['path']; - print(version); - print(path); +void _handleBuildListCommand(CommandCall commandCall) { + final versions = readVersions(); + final versionSelector = Select.withTheme( + prompt: ' Select a version:', + options: versions.map((version) => version.content.toString()).toList(growable: false), + theme: Theme.colorfulTheme.copyWith(inputPrefix: '❓', inputSuffix: '', successSuffix: '', errorPrefix: '❌') + ); + final version = versions[versionSelector.interact()]; + final actionSelector = Select.withTheme( + prompt: ' Select an action:', + options: ['Play', 'Host', 'Delete', 'Open in Explorer'], + theme: Theme.colorfulTheme.copyWith(inputPrefix: '❓', inputSuffix: '', successSuffix: '', errorPrefix: '❌') + ); + actionSelector.interact(); } -void _handleBuildDownloadCommand(CommandCall call) { +Future _handleBuildImportCommand(CommandCall call) async { + final version = _getOrPromptVersion(call); + if(version == null) { + return; + } + final path = await _getOrPromptPath(call, true); + if(path == null) { + return; + } + + final fortniteVersion = FortniteVersion( + name: "dummy", + content: Version.parse(version), + location: Directory(path) + ); + writeVersion(fortniteVersion); + print(''); + print('✅ Imported build: ${version.green()}'); +} + +String? _getOrPromptVersion(CommandCall call) { + final version = call.parameters['version']; + if(version != null) { + final result = version.trim(); + if (_versions.contains(result)) { + return result; + } + + print(''); + print("❌ Unknown version: $result"); + return null; + } + + stdout.write('❓ Type a version: '); + final result = runAutoComplete(_autocompleteVersion).trim(); + if(_versions.contains(result)) { + print('✅ Type a version: ${result.green()}'); + return result; + } + + print(''); + print("❌ Unknown version: $version"); + return null; +} + +Future _getOrPromptPath(CommandCall call, bool existing) async { + var path = call.parameters['path']; + if(path != null) { + final result = path.trim(); + final check = await _checkBuildPath(result, existing); + if(!check) { + return null; + } + + return result; + } + + stdout.write('❓ Type a path: '); + final result = runAutoComplete(_autocompletePath).trim(); + final check = await _checkBuildPath(result, existing); + if(!check) { + return null; + } + + print('✅ Type a path: ${result.green()}'); + return result; +} + +Future _checkBuildPath(String path, bool existing) async { + final directory = Directory(path); + if(!directory.existsSync()) { + if(existing) { + print(''); + print("❌ Unknown path: $path"); + return false; + }else { + directory.createSync(recursive: true); + } + } + + if (existing) { + final checker = Spinner.withTheme( + icon: '✅', + rightPrompt: (status) => status != SpinnerStateType.inProgress ? 'Finished looking for FortniteClient-Win64-Shipping.exe' : 'Looking for FortniteClient-Win64-Shipping.exe...', + theme: Theme.colorfulTheme.copyWith(successSuffix: '', errorPrefix: '❌', spinners: '🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚 🕛'.split(' ')) + ).interact(); + final result = await Future.wait([ + Future.delayed(const Duration(seconds: 1)).then((_) => true), + Isolate.run(() => FortniteVersionExtension.findFiles(directory, "FortniteClient-Win64-Shipping.exe") != null) + ]).then((values) => values.reduce((first, second) => first && second)); + checker.done(); + if(!result) { + print("❌ Cannot find FortniteClient-Win64-Shipping.exe: $path"); + return false; + } + } + + return true; +} + +String? _autocompleteVersion(String input) => input.isEmpty ? null : _versions.firstWhereOrNull((version) => version.toLowerCase().startsWith(input.toLowerCase())); + +String? _autocompletePath(String path) { + try { + if (path.isEmpty) { + return null; + } + + final String separator = Platform.isWindows ? '\\' : '/'; + path = path.replaceAll('\\', separator); + + if (FileSystemEntity.isFileSync(path)) { + return null; + } + + if(FileSystemEntity.isDirectorySync(path)) { + return path.endsWith(separator) ? null : path + separator; + } + + final lastSeparatorIndex = path.lastIndexOf(separator); + String directoryPath; + String partialName; + String prefixPath; + if (lastSeparatorIndex == -1) { + directoryPath = ''; + partialName = path; + prefixPath = ''; + } else { + directoryPath = path.substring(0, lastSeparatorIndex); + partialName = path.substring(lastSeparatorIndex + 1); + prefixPath = path.substring(0, lastSeparatorIndex + 1); + if (directoryPath.isEmpty && lastSeparatorIndex == 0) { + directoryPath = separator; + } else if (directoryPath.isEmpty) { + directoryPath = '.'; + } + } + + final dir = Directory(directoryPath); + if (!dir.existsSync()) { + return null; + } + + final entries = dir.listSync(); + final matches = []; + for (var entry in entries) { + final name = entry.path.split(separator).last; + if (name.startsWith(partialName)) { + matches.add(entry); + } + } + + if (matches.isEmpty) { + return null; + } + + matches.sort((a, b) { + final aIsDir = a is Directory; + final bIsDir = b is Directory; + + if (aIsDir != bIsDir) { + return aIsDir ? -1 : 1; + } + + final aName = a.path.split(separator).last; + final bName = b.path.split(separator).last; + + if (aName.length != bName.length) { + return aName.length - bName.length; + } + + return aName.compareTo(bName); + }); + + final bestMatch = matches.first; + final bestMatchName = bestMatch.path.split(separator).last; + + var result = prefixPath + bestMatchName; + if (bestMatch is Directory) { + result = result.endsWith(separator) ? result : result + separator; + } + return result; + } catch (_) { + return null; + } +} + + +Future _handleBuildDownloadCommand(CommandCall call) async { + final version = _getOrPromptVersion(call); + if(version == null) { + return; + } + + final parsedVersion = Version.parse(version); + final build = downloadableBuilds.firstWhereOrNull((build) => build.version == parsedVersion); + if(build == null) { + print(''); + print("❌ Cannot find mirror for version: $parsedVersion"); + return; + } + + final path = await _getOrPromptPath(call, false); + if(path == null) { + return; + } + + double progress = 0; + bool extracting = false; + final downloader = Spinner.withTheme( + icon: '✅', + rightPrompt: (status) => status != SpinnerStateType.inProgress ? 'Finished ${extracting ? 'extracting' : 'downloading'} ${parsedVersion.toString()}' : '${extracting ? 'Extracting' : 'Downloading'} ${parsedVersion.toString()} (${progress.round()}%)...', + theme: Theme.colorfulTheme.copyWith(successSuffix: '', errorPrefix: '❌', spinners: '🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚 🕛'.split(' ')) + ).interact(); + final parsedDirectory = Directory(path); + final receivePort = ReceivePort(); + SendPort? sendPort; + receivePort.listen((message) { + if(message is FortniteBuildDownloadProgress) { + if(message.progress >= 100) { + sendPort?.send(kStopBuildDownloadSignal); + stopDownloadServer(); + downloader.done(); + receivePort.close(); + final fortniteVersion = FortniteVersion( + name: "dummy", + content: parsedVersion, + location: parsedDirectory + ); + writeVersion(fortniteVersion); + print(''); + print('✅ Downloaded build: ${version.green()}'); + }else { + progress = message.progress; + extracting = message.extracting; + } + }else if(message is SendPort) { + sendPort = message; + }else { + sendPort?.send(kStopBuildDownloadSignal); + stopDownloadServer(); + downloader.done(); + receivePort.close(); + print("❌ Cannot download build: $message"); + } + }); + final options = FortniteBuildDownloadOptions( + build, + parsedDirectory, + receivePort.sendPort + ); + await downloadArchiveBuild(options); } void _askBuildCommand() { - final commands = [_buildImport.name, _buildDownload.name]; + final commands = [_buildList.name, _buildImport.name, _buildDownload.name]; final commandSelector = Select.withTheme( - prompt: ' Select a build command:', + prompt: ' Select a version command:', options: commands, - theme: Theme.colorfulTheme.copyWith(inputPrefix: '❓', inputSuffix: '') + theme: Theme.colorfulTheme.copyWith(inputPrefix: '❓', inputSuffix: '', successSuffix: '', errorPrefix: '❌') ); _handleBuildCommand(CommandCall(name: commands[commandSelector.interact()])); } @@ -93,10 +388,4 @@ void _handleHostCommand(CommandCall? call) { void _handleBackendCommand(CommandCall? call) { -} - -void _welcome() => print(""" -🎮 Reboot Launcher -🔥 Launch, manage, and play Fortnite using Project Reboot! -🚀 Developed by Auties00 - Version 10.0.7 -""".green()); \ No newline at end of file +} \ No newline at end of file diff --git a/cli/lib/src/command/backend.dart b/cli/lib/src/command/backend.dart new file mode 100644 index 0000000..e69de29 diff --git a/cli/lib/src/command/commands.dart b/cli/lib/src/command/commands.dart new file mode 100644 index 0000000..e69de29 diff --git a/cli/lib/src/command/config.dart b/cli/lib/src/command/config.dart new file mode 100644 index 0000000..e69de29 diff --git a/cli/lib/src/command/host.dart b/cli/lib/src/command/host.dart new file mode 100644 index 0000000..e69de29 diff --git a/cli/lib/src/command/play.dart b/cli/lib/src/command/play.dart new file mode 100644 index 0000000..e69de29 diff --git a/cli/lib/src/command/versions.dart b/cli/lib/src/command/versions.dart new file mode 100644 index 0000000..e69de29 diff --git a/cli/lib/src/controller/config.dart b/cli/lib/src/controller/config.dart new file mode 100644 index 0000000..405f5b2 --- /dev/null +++ b/cli/lib/src/controller/config.dart @@ -0,0 +1,24 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:reboot_common/common.dart'; + +List readVersions() { + final file = _versionsFile; + if(!file.existsSync()) { + return []; + } + + Iterable decodedVersionsJson = jsonDecode(file.readAsStringSync()); + return decodedVersionsJson + .map((entry) => FortniteVersion.fromJson(entry)) + .toList(); +} + +void writeVersion(FortniteVersion version) { + final versions = readVersions(); + versions.add(version); + _versionsFile.writeAsString(jsonEncode(versions.map((version) => version.toJson()).toList())); +} + +File get _versionsFile => File('${installationDirectory.path}/versions.json'); \ No newline at end of file diff --git a/cli/lib/cli.dart b/cli/lib/src/util/console.dart similarity index 51% rename from cli/lib/cli.dart rename to cli/lib/src/util/console.dart index bab2faf..2d2ffc6 100644 --- a/cli/lib/cli.dart +++ b/cli/lib/src/util/console.dart @@ -1,9 +1,12 @@ -import 'dart:collection'; +import 'dart:io'; +import 'package:dart_console/dart_console.dart'; -class Parser { +typedef AutoComplete = String? Function(String); + +class ConsoleParser { final List commands; - Parser({required this.commands}); + ConsoleParser({required this.commands}); CommandCall? parse(List args) { var position = 0; @@ -86,4 +89,72 @@ class CommandCall { @override String toString() => 'CommandCall{name: $name, parameters: $parameters, subCall: $subCall}'; -} \ No newline at end of file +} + +String runAutoComplete(AutoComplete completion) { + final console = Console(); + console.rawMode = true; + final position = console.cursorPosition!; + + var currentInput = ''; + var running = true; + var result = ''; + + while (running) { + final key = console.readKey(); + switch (key.controlChar) { + case ControlCharacter.ctrlC: + running = false; + break; + case ControlCharacter.enter: + _eraseUntil(console, position); + console.write(currentInput); + console.writeLine(); + result = currentInput; + running = false; + break; + case ControlCharacter.tab: + final suggestion = completion(currentInput); + if (suggestion != null) { + _eraseUntil(console, position); + currentInput = suggestion; + console.write(currentInput); + } + break; + case ControlCharacter.backspace: + if (currentInput.isNotEmpty) { + currentInput = currentInput.substring(0, currentInput.length - 1); + _eraseUntil(console, position); + console.write(currentInput); + _showSuggestion(console, position, currentInput, completion); + } + break; + default: + currentInput += key.char; + console.write(key.char); + _showSuggestion(console, position, currentInput, completion); + } + } + + return result; +} + +void _eraseUntil(Console console, Coordinate position) { + console.cursorPosition = position; + stdout.write('\x1b[K'); +} + +void _showSuggestion(Console console, Coordinate position, String input, AutoComplete completion) { + final suggestion = completion(input); + if(suggestion == null) { + _eraseUntil(console, position); + console.write(input); + }else if(suggestion.length > input.length) { + final remaining = suggestion.substring(input.length); + final cursorPosition = console.cursorPosition; + console.setForegroundColor(ConsoleColor.brightBlack); + console.write(remaining); + console.resetColorAttributes(); + console.cursorPosition = cursorPosition; + } +} diff --git a/cli/lib/src/util/extensions.dart b/cli/lib/src/util/extensions.dart new file mode 100644 index 0000000..baa2fa1 --- /dev/null +++ b/cli/lib/src/util/extensions.dart @@ -0,0 +1,10 @@ +extension IterableExtension on Iterable { + E? firstWhereOrNull(bool test(E element)) { + for (final element in this) { + if (test(element)) { + return element; + } + } + return null; + } +} \ No newline at end of file diff --git a/cli/pubspec.yaml b/cli/pubspec.yaml index ff6acc5..dc42cb5 100644 --- a/cli/pubspec.yaml +++ b/cli/pubspec.yaml @@ -5,14 +5,15 @@ version: "10.0.7" publish_to: 'none' environment: - sdk: ">=2.19.0 <=3.5.3" + sdk: ">=3.0.0 <=3.5.3" dependencies: reboot_common: path: ./../common tint: ^2.0.1 - interact: ^2.2.0 + interact_cli: ^2.4.0 args: ^2.6.0 + version: ^3.0.2 dependency_overrides: xml: ^6.3.0 diff --git a/common/lib/common.dart b/common/lib/common.dart index 89662b6..9456e7c 100644 --- a/common/lib/common.dart +++ b/common/lib/common.dart @@ -1,7 +1,6 @@ export 'package:reboot_common/src/constant/backend.dart'; export 'package:reboot_common/src/constant/game.dart'; export 'package:reboot_common/src/constant/supabase.dart'; -export 'package:reboot_common/src/extension/path.dart'; export 'package:reboot_common/src/extension/process.dart'; export 'package:reboot_common/src/model/fortnite_build.dart'; export 'package:reboot_common/src/model/fortnite_version.dart'; @@ -13,10 +12,7 @@ export 'package:reboot_common/src/model/update_timer.dart'; export 'package:reboot_common/src/model/fortnite_server.dart'; export 'package:reboot_common/src/model/dll.dart'; export 'package:reboot_common/src/util/backend.dart'; -export 'package:reboot_common/src/util/build.dart'; -export 'package:reboot_common/src/util/dll.dart'; -export 'package:reboot_common/src/util/network.dart'; -export 'package:reboot_common/src/util/patcher.dart'; -export 'package:reboot_common/src/util/path.dart'; -export 'package:reboot_common/src/util/process.dart'; -export 'package:reboot_common/src/util/log.dart'; \ No newline at end of file +export 'package:reboot_common/src/util/downloader.dart'; +export 'package:reboot_common/src/util/os.dart'; +export 'package:reboot_common/src/util/log.dart'; +export 'package:reboot_common/src/util/game.dart'; \ No newline at end of file diff --git a/common/lib/src/constant/game.dart b/common/lib/src/constant/game.dart index 9d4537d..5b3bc01 100644 --- a/common/lib/src/constant/game.dart +++ b/common/lib/src/constant/game.dart @@ -1,3 +1,5 @@ +import 'package:version/version.dart'; + const String kDefaultPlayerName = "Player"; const String kDefaultHostName = "Host"; const String kDefaultGameServerHost = "127.0.0.1"; @@ -21,6 +23,10 @@ const List kCannotConnectErrors = [ "Network failure when attempting to check platform restrictions", "UOnlineAccountCommon::ForceLogout" ]; -const String kGameFinishedLine = "PlayersLeft: 1"; +const String kGameFinishedLine = "TeamsLeft: 1"; const String kDisplayLine = "Display"; -const String kDisplayInitializedLine = "Initialized"; \ No newline at end of file +const String kDisplayInitializedLine = "Initialized"; +const String kShippingExe = "FortniteClient-Win64-Shipping.exe"; +const String kLauncherExe = "FortniteLauncher.exe"; +const String kEacExe = "FortniteClient-Win64-Shipping_EAC.exe"; +final Version kMaxAllowedVersion = Version.parse("30.10"); \ No newline at end of file diff --git a/common/lib/src/extension/path.dart b/common/lib/src/extension/path.dart deleted file mode 100644 index 9959744..0000000 --- a/common/lib/src/extension/path.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'dart:io'; -import 'dart:isolate'; - -import 'package:path/path.dart' as path; -import 'package:reboot_common/common.dart'; - -extension FortniteVersionExtension on FortniteVersion { - static String _marker = "FortniteClient.mod"; - - static File? findFile(Directory directory, String name) { - try{ - for(final child in directory.listSync()) { - if(child is Directory) { - if(!path.basename(child.path).startsWith("\.")) { - final result = findFile(child, name); - if(result != null) { - return result; - } - } - }else if(child is File) { - if(path.basename(child.path) == name) { - return child; - } - } - } - - return null; - }catch(_){ - return null; - } - } - - Future get shippingExecutable async { - final result = findFile(location, "FortniteClient-Win64-Shipping.exe"); - if(result == null) { - return null; - } - - final marker = findFile(location, _marker); - if(marker != null) { - return result; - } - - await Isolate.run(() => patchHeadless(result)); - await File("${location.path}\\$_marker").create(); - return result; - } - - File? get launcherExecutable => findFile(location, "FortniteLauncher.exe"); - - File? get eacExecutable => findFile(location, "FortniteClient-Win64-Shipping_EAC.exe"); - - File? get splashBitmap => findFile(location, "Splash.bmp"); -} \ No newline at end of file diff --git a/common/lib/src/model/fortnite_build.dart b/common/lib/src/model/fortnite_build.dart index 3371c59..19277f1 100644 --- a/common/lib/src/model/fortnite_build.dart +++ b/common/lib/src/model/fortnite_build.dart @@ -1,15 +1,13 @@ import 'dart:io'; import 'dart:isolate'; -import 'package:version/version.dart'; - class FortniteBuild { - final Version version; + final String gameVersion; final String link; final bool available; FortniteBuild({ - required this.version, + required this.gameVersion, required this.link, required this.available }); diff --git a/common/lib/src/model/fortnite_version.dart b/common/lib/src/model/fortnite_version.dart index 65a4847..f658ab7 100644 --- a/common/lib/src/model/fortnite_version.dart +++ b/common/lib/src/model/fortnite_version.dart @@ -1,22 +1,20 @@ import 'dart:io'; -import 'package:version/version.dart'; - class FortniteVersion { - Version content; + String name; + String gameVersion; Directory location; FortniteVersion.fromJson(json) - : content = Version.parse(json["content"]), + : name = json["name"], + gameVersion = json["gameVersion"], location = Directory(json["location"]); - FortniteVersion({required this.content, required this.location}); + FortniteVersion({required this.name, required this.gameVersion, required this.location}); Map toJson() => { - 'content': content.toString(), + 'name': name, + 'gameVersion': gameVersion, 'location': location.path }; - - @override - bool operator ==(Object other) => other is FortniteVersion && this.content == other.content; } \ No newline at end of file diff --git a/common/lib/src/model/game_instance.dart b/common/lib/src/model/game_instance.dart index 6bb11d6..f3f9844 100644 --- a/common/lib/src/model/game_instance.dart +++ b/common/lib/src/model/game_instance.dart @@ -5,14 +5,13 @@ import 'package:version/version.dart'; class GameInstance { - final Version version; + final String version; final int gamePid; final int? launcherPid; final int? eacPid; final List injectedDlls; - final GameServerType? serverType; + final bool headless; bool launched; - bool movedToVirtualDesktop; bool tokenError; bool killed; GameInstance? child; @@ -22,9 +21,9 @@ class GameInstance { required this.gamePid, required this.launcherPid, required this.eacPid, - required this.serverType, + required this.headless, required this.child - }): tokenError = false, killed = false, launched = false, movedToVirtualDesktop = false, injectedDlls = []; + }): tokenError = false, killed = false, launched = false, injectedDlls = []; void kill() { GameInstance? child = this; @@ -35,20 +34,16 @@ class GameInstance { } void _kill() { - launched = true; - killed = true; - Process.killPid(gamePid, ProcessSignal.sigabrt); - if(launcherPid != null) { - Process.killPid(launcherPid!, ProcessSignal.sigabrt); - } - if(eacPid != null) { - Process.killPid(eacPid!, ProcessSignal.sigabrt); + if(!killed) { + launched = true; + killed = true; + Process.killPid(gamePid, ProcessSignal.sigabrt); + if (launcherPid != null) { + Process.killPid(launcherPid!, ProcessSignal.sigabrt); + } + if (eacPid != null) { + Process.killPid(eacPid!, ProcessSignal.sigabrt); + } } } -} - -enum GameServerType { - headless, - virtualWindow, - window } \ No newline at end of file diff --git a/common/lib/src/util/backend.dart b/common/lib/src/util/backend.dart index 8f620aa..0c4b36c 100644 --- a/common/lib/src/util/backend.dart +++ b/common/lib/src/util/backend.dart @@ -137,9 +137,14 @@ Future startEmbeddedBackend(bool detached, {void Function(String)? onEr window: detached, ); process.stdOutput.listen((message) => log("[BACKEND] Message: $message")); + var killed = false; process.stdError.listen((error) { - log("[BACKEND] Error: $error"); - onError?.call(error); + if(!killed) { + log("[BACKEND] Error: $error"); + killed = true; + process.kill(ProcessSignal.sigterm); + onError?.call(error); + } }); if(!detached) { process.exitCode.then((exitCode) => log("[BACKEND] Exit code: $exitCode")); diff --git a/common/lib/src/util/build.dart b/common/lib/src/util/build.dart deleted file mode 100644 index 4db15c4..0000000 --- a/common/lib/src/util/build.dart +++ /dev/null @@ -1,464 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:isolate'; - -import 'package:path/path.dart' as path; -import 'package:reboot_common/common.dart'; -import 'package:reboot_common/src/extension/types.dart'; -import 'package:uuid/uuid.dart'; -import 'package:version/version.dart'; - -import 'package:http/http.dart' as http; - -const String kStopBuildDownloadSignal = "kill"; - -final int _ariaPort = 6800; -final Uri _ariaEndpoint = Uri.parse('http://localhost:$_ariaPort/jsonrpc'); -final Duration _ariaMaxSpawnTime = const Duration(seconds: 10); -final String _ariaSecret = "RebootLauncher"; -final RegExp _rarProgressRegex = RegExp("^((100)|(\\d{1,2}(.\\d*)?))%\$"); -final List downloadableBuilds = [ - FortniteBuild(version: Version.parse("1.7.2"), link: "https://public.simplyblk.xyz/1.7.2.zip", available: true), - FortniteBuild(version: Version.parse("1.8"), link: "https://public.simplyblk.xyz/1.8.rar", available: true), - FortniteBuild(version: Version.parse("1.8.1"), link: "https://public.simplyblk.xyz/1.8.1.rar", available: true), - FortniteBuild(version: Version.parse("1.8.2"), link: "https://public.simplyblk.xyz/1.8.2.rar", available: true), - FortniteBuild(version: Version.parse("1.9"), link: "https://public.simplyblk.xyz/1.9.rar", available: true), - FortniteBuild(version: Version.parse("1.9.1"), link: "https://public.simplyblk.xyz/1.9.1.rar", available: true), - FortniteBuild(version: Version.parse("1.10"), link: "https://public.simplyblk.xyz/1.10.rar", available: true), - FortniteBuild(version: Version.parse("1.11"), link: "https://public.simplyblk.xyz/1.11.zip", available: true), - FortniteBuild(version: Version.parse("2.1.0"), link: "https://public.simplyblk.xyz/2.1.0.zip", available: true), - FortniteBuild(version: Version.parse("2.2.0"), link: "https://public.simplyblk.xyz/2.2.0.rar", available: true), - FortniteBuild(version: Version.parse("2.3"), link: "https://public.simplyblk.xyz/2.3.rar", available: true), - FortniteBuild(version: Version.parse("2.4.0"), link: "https://public.simplyblk.xyz/2.4.0.zip", available: true), - FortniteBuild(version: Version.parse("2.4.2"), link: "https://public.simplyblk.xyz/2.4.2.zip", available: true), - FortniteBuild(version: Version.parse("2.5.0"), link: "https://public.simplyblk.xyz/2.5.0.rar", available: true), - FortniteBuild(version: Version.parse("3.0"), link: "https://public.simplyblk.xyz/3.0.zip", available: true), - FortniteBuild(version: Version.parse("3.1"), link: "https://public.simplyblk.xyz/3.1.rar", available: true), - FortniteBuild(version: Version.parse("3.1.1"), link: "https://public.simplyblk.xyz/3.1.1.zip", available: true), - FortniteBuild(version: Version.parse("3.2"), link: "https://public.simplyblk.xyz/3.2.zip", available: true), - FortniteBuild(version: Version.parse("3.3"), link: "https://public.simplyblk.xyz/3.3.rar", available: true), - FortniteBuild(version: Version.parse("3.5"), link: "https://public.simplyblk.xyz/3.5.rar", available: true), - FortniteBuild(version: Version.parse("3.6"), link: "https://public.simplyblk.xyz/3.6.zip", available: true), - FortniteBuild(version: Version.parse("4.0"), link: "https://public.simplyblk.xyz/4.0.zip", available: true), - FortniteBuild(version: Version.parse("4.1"), link: "https://public.simplyblk.xyz/4.1.zip", available: true), - FortniteBuild(version: Version.parse("4.2"), link: "https://public.simplyblk.xyz/4.2.zip", available: true), - FortniteBuild(version: Version.parse("4.4"), link: "https://public.simplyblk.xyz/4.4.rar", available: true), - FortniteBuild(version: Version.parse("4.5"), link: "https://public.simplyblk.xyz/4.5.rar", available: true), - FortniteBuild(version: Version.parse("5.00"), link: "https://public.simplyblk.xyz/5.00.rar", available: true), - FortniteBuild(version: Version.parse("5.0.1"), link: "https://public.simplyblk.xyz/5.0.1.rar", available: true), - FortniteBuild(version: Version.parse("5.10"), link: "https://public.simplyblk.xyz/5.10.rar", available: true), - FortniteBuild(version: Version.parse("5.21"), link: "https://public.simplyblk.xyz/5.21.rar", available: true), - FortniteBuild(version: Version.parse("5.30"), link: "https://public.simplyblk.xyz/5.30.rar", available: true), - FortniteBuild(version: Version.parse("5.40"), link: "https://public.simplyblk.xyz/5.40.rar", available: true), - FortniteBuild(version: Version.parse("6.00"), link: "https://public.simplyblk.xyz/6.00.rar", available: true), - FortniteBuild(version: Version.parse("6.01"), link: "https://public.simplyblk.xyz/6.01.rar", available: true), - FortniteBuild(version: Version.parse("6.1.1"), link: "https://public.simplyblk.xyz/6.1.1.rar", available: true), - FortniteBuild(version: Version.parse("6.02"), link: "https://public.simplyblk.xyz/6.02.rar", available: true), - FortniteBuild(version: Version.parse("6.2.1"), link: "https://public.simplyblk.xyz/6.2.1.rar", available: true), - FortniteBuild(version: Version.parse("6.10"), link: "https://public.simplyblk.xyz/6.10.rar", available: true), - FortniteBuild(version: Version.parse("6.10.1"), link: "https://public.simplyblk.xyz/6.10.1.rar", available: true), - FortniteBuild(version: Version.parse("6.10.2"), link: "https://public.simplyblk.xyz/6.10.2.rar", available: true), - FortniteBuild(version: Version.parse("6.21"), link: "https://public.simplyblk.xyz/6.21.rar", available: true), - FortniteBuild(version: Version.parse("6.22"), link: "https://public.simplyblk.xyz/6.22.rar", available: true), - FortniteBuild(version: Version.parse("6.30"), link: "https://public.simplyblk.xyz/6.30.rar", available: true), - FortniteBuild(version: Version.parse("6.31"), link: "https://public.simplyblk.xyz/6.31.rar", available: true), - FortniteBuild(version: Version.parse("7.00"), link: "https://public.simplyblk.xyz/7.00.rar", available: true), - FortniteBuild(version: Version.parse("7.10"), link: "https://public.simplyblk.xyz/7.10.rar", available: true), - FortniteBuild(version: Version.parse("7.20"), link: "https://public.simplyblk.xyz/7.20.rar", available: true), - FortniteBuild(version: Version.parse("7.30"), link: "https://public.simplyblk.xyz/7.30.zip", available: true), - FortniteBuild(version: Version.parse("7.40"), link: "https://public.simplyblk.xyz/7.40.rar", available: true), - FortniteBuild(version: Version.parse("8.00"), link: "https://public.simplyblk.xyz/8.00.zip", available: true), - FortniteBuild(version: Version.parse("8.20"), link: "https://public.simplyblk.xyz/8.20.rar", available: true), - FortniteBuild(version: Version.parse("8.30"), link: "https://public.simplyblk.xyz/8.30.rar", available: true), - FortniteBuild(version: Version.parse("8.40"), link: "https://public.simplyblk.xyz/8.40.zip", available: true), - FortniteBuild(version: Version.parse("8.50"), link: "https://public.simplyblk.xyz/8.50.zip", available: true), - FortniteBuild(version: Version.parse("8.51"), link: "https://public.simplyblk.xyz/8.51.rar", available: true), - FortniteBuild(version: Version.parse("9.00"), link: "https://public.simplyblk.xyz/9.00.zip", available: true), - FortniteBuild(version: Version.parse("9.01"), link: "https://public.simplyblk.xyz/9.01.zip", available: true), - FortniteBuild(version: Version.parse("9.10"), link: "https://public.simplyblk.xyz/9.10.rar", available: true), - FortniteBuild(version: Version.parse("9.21"), link: "https://public.simplyblk.xyz/9.21.zip", available: true), - FortniteBuild(version: Version.parse("9.30"), link: "https://public.simplyblk.xyz/9.30.zip", available: true), - FortniteBuild(version: Version.parse("9.40"), link: "https://public.simplyblk.xyz/9.40.zip", available: true), - FortniteBuild(version: Version.parse("9.41"), link: "https://public.simplyblk.xyz/9.41.rar", available: true), - FortniteBuild(version: Version.parse("10.00"), link: "https://public.simplyblk.xyz/10.00.zip", available: true), - FortniteBuild(version: Version.parse("10.10"), link: "https://public.simplyblk.xyz/10.10.zip", available: true), - FortniteBuild(version: Version.parse("10.20"), link: "https://public.simplyblk.xyz/10.20.zip", available: true), - FortniteBuild(version: Version.parse("10.31"), link: "https://public.simplyblk.xyz/10.31.zip", available: true), - FortniteBuild(version: Version.parse("10.40"), link: "https://public.simplyblk.xyz/10.40.rar", available: true), - FortniteBuild(version: Version.parse("11.00"), link: "https://public.simplyblk.xyz/11.00.zip", available: true), - FortniteBuild(version: Version.parse("11.31"), link: "https://public.simplyblk.xyz/11.31.rar", available: true), - FortniteBuild(version: Version.parse("12.00"), link: "https://public.simplyblk.xyz/12.00.rar", available: true), - FortniteBuild(version: Version.parse("12.21"), link: "https://public.simplyblk.xyz/12.21.zip", available: true), - FortniteBuild(version: Version.parse("12.50"), link: "https://public.simplyblk.xyz/12.50.zip", available: true), - FortniteBuild(version: Version.parse("12.61"), link: "https://public.simplyblk.xyz/12.61.zip", available: true), - FortniteBuild(version: Version.parse("13.00"), link: "https://public.simplyblk.xyz/13.00.rar", available: true), - FortniteBuild(version: Version.parse("13.40"), link: "https://public.simplyblk.xyz/13.40.zip", available: true), - FortniteBuild(version: Version.parse("14.00"), link: "https://public.simplyblk.xyz/14.00.rar", available: true), - FortniteBuild(version: Version.parse("14.40"), link: "https://public.simplyblk.xyz/14.40.rar", available: true), - FortniteBuild(version: Version.parse("14.60"), link: "https://public.simplyblk.xyz/14.60.rar", available: true), - FortniteBuild(version: Version.parse("15.30"), link: "https://public.simplyblk.xyz/15.30.rar", available: true), - FortniteBuild(version: Version.parse("16.40"), link: "https://public.simplyblk.xyz/16.40.rar", available: true), - FortniteBuild(version: Version.parse("17.30"), link: "https://public.simplyblk.xyz/17.30.zip", available: true), - FortniteBuild(version: Version.parse("17.50"), link: "https://public.simplyblk.xyz/17.50.zip", available: true), - FortniteBuild(version: Version.parse("18.40"), link: "https://public.simplyblk.xyz/18.40.zip", available: true), - FortniteBuild(version: Version.parse("19.10"), link: "https://public.simplyblk.xyz/19.10.rar", available: true), - FortniteBuild(version: Version.parse("20.40"), link: "https://public.simplyblk.xyz/20.40.zip", available: true), -]; - - -Future downloadArchiveBuild(FortniteBuildDownloadOptions options) async { - final fileName = options.build.link.substring(options.build.link.lastIndexOf("/") + 1); - final outputFile = File("${options.destination.path}\\.build\\$fileName"); - try { - final stopped = _setupLifecycle(options); - await outputFile.parent.create(recursive: true); - - final downloadItemCompleter = Completer(); - - await _startAriaServer(); - final downloadId = await _startAriaDownload(options, outputFile); - Timer.periodic(const Duration(seconds: 5), (Timer timer) async { - try { - final statusRequestId = Uuid().toString().replaceAll("-", ""); - final statusRequest = { - "jsonrcp": "2.0", - "id": statusRequestId, - "method": "aria2.tellStatus", - "params": [ - "token:${_ariaSecret}", - downloadId - ] - }; - final statusResponse = await http.post(_ariaEndpoint, body: jsonEncode(statusRequest)); - final statusResponseJson = jsonDecode(statusResponse.body) as Map?; - if(statusResponseJson == null) { - downloadItemCompleter.completeError("Invalid download status (invalid JSON)"); - timer.cancel(); - return; - } - - final result = statusResponseJson["result"]; - final files = result["files"] as List?; - if(files == null || files.isEmpty) { - downloadItemCompleter.completeError("Download aborted"); - timer.cancel(); - return; - } - - final error = result["errorCode"]; - if(error != null) { - final errorCode = int.tryParse(error); - if(errorCode == 0) { - final path = File(files[0]["path"]); - downloadItemCompleter.complete(path); - }else if(errorCode == 3) { - downloadItemCompleter.completeError("This build is not available yet"); - }else { - final errorMessage = result["errorMessage"]; - downloadItemCompleter.completeError("$errorMessage (error code $errorCode)"); - } - - timer.cancel(); - return; - } - - final speed = int.parse(result["downloadSpeed"] ?? "0"); - final completedLength = int.parse(files[0]["completedLength"] ?? "0"); - final totalLength = int.parse(files[0]["length"] ?? "0"); - - final percentage = completedLength * 100 / totalLength; - final minutesLeft = speed == 0 ? -1 : ((totalLength - completedLength) / speed / 60).round(); - _onProgress( - options.port, - percentage, - speed, - minutesLeft, - false - ); - }catch(error) { - throw "Invalid download status (${error})"; - } - }); - - await Future.any([stopped.future, downloadItemCompleter.future]); - if(!stopped.isCompleted) { - final extension = path.extension(fileName); - await _extractArchive(stopped, extension, await downloadItemCompleter.future, options); - }else { - await _stopAriaDownload(downloadId); - } - }catch(error) { - _onError(error, options); - }finally { - delete(outputFile); - } -} - -Future _startAriaServer() async { - await stopDownloadServer(); - final aria2c = File("${assetsDirectory.path}\\build\\aria2c.exe"); - if(!aria2c.existsSync()) { - throw "Missing aria2c.exe"; - } - - final process = await startProcess( - executable: aria2c, - args: [ - "--max-connection-per-server=${Platform.numberOfProcessors}", - "--split=${Platform.numberOfProcessors}", - "--enable-rpc", - "--rpc-listen-all=true", - "--rpc-allow-origin-all", - "--rpc-secret=$_ariaSecret", - "--rpc-listen-port=$_ariaPort", - "--file-allocation=none", - "--check-certificate=false" - ], - window: false - ); - process.stdOutput.listen((message) => log("[ARIA] Message: $message")); - process.stdError.listen((error) => log("[ARIA] Error: $error")); - process.exitCode.then((exitCode) => log("[ARIA] Exit code: $exitCode")); - for(var i = 0; i < _ariaMaxSpawnTime.inSeconds; i++) { - if(await _isAriaRunning()) { - return; - } - await Future.delayed(const Duration(seconds: 1)); - } - throw "cannot start download server (timeout exceeded)"; -} - -Future _isAriaRunning() async { - try { - final statusRequestId = Uuid().toString().replaceAll("-", ""); - final statusRequest = { - "jsonrcp": "2.0", - "id": statusRequestId, - "method": "aria2.getVersion", - "params": [ - "token:${_ariaSecret}" - ] - }; - final response = await http.post(_ariaEndpoint, body: jsonEncode(statusRequest)); - return response.statusCode == 200; - }catch(_) { - return false; - } -} - -Future _startAriaDownload(FortniteBuildDownloadOptions options, File outputFile) async { - http.Response? addDownloadResponse; - try { - final addDownloadRequestId = Uuid().toString().replaceAll("-", ""); - final addDownloadRequest = { - "jsonrcp": "2.0", - "id": addDownloadRequestId, - "method": "aria2.addUri", - "params": [ - "token:${_ariaSecret}", - [options.build.link], - { - "dir": outputFile.parent.path, - "out": path.basename(outputFile.path) - } - ] - }; - addDownloadResponse = await http.post(_ariaEndpoint, body: jsonEncode(addDownloadRequest)); - final addDownloadResponseJson = jsonDecode(addDownloadResponse.body); - final downloadId = addDownloadResponseJson is Map ? addDownloadResponseJson['result'] : null; - if(downloadId == null) { - throw "Start failed (${addDownloadResponse.body})"; - } - - return downloadId; - }catch(error) { - throw "Start failed (${addDownloadResponse?.body ?? error})"; - } -} - -Future _stopAriaDownload(String downloadId) async { - try { - final addDownloadRequestId = Uuid().toString().replaceAll("-", ""); - final addDownloadRequest = { - "jsonrcp": "2.0", - "id": addDownloadRequestId, - "method": "aria2.forceRemove", - "params": [ - "token:${_ariaSecret}", - downloadId - ] - }; - await http.post(_ariaEndpoint, body: jsonEncode(addDownloadRequest)); - stopDownloadServer(); - }catch(error) { - throw "Stop failed (${error})"; - } -} - -Future stopDownloadServer() async { - await killProcessByPort(_ariaPort); -} - - -Future _extractArchive(Completer stopped, String extension, File tempFile, FortniteBuildDownloadOptions options) async { - Process? process; - switch (extension.toLowerCase()) { - case ".zip": - final sevenZip = File("${assetsDirectory.path}\\build\\7zip.exe"); - if(!sevenZip.existsSync()) { - throw "Missing 7zip.exe"; - } - - process = await startProcess( - executable: sevenZip, - args: [ - "x", - "-bsp1", - '-o"${options.destination.path}"', - "-y", - '"${tempFile.path}"' - ], - ); - var completed = false; - process.stdOutput.listen((data) { - if(data.toLowerCase().contains("everything is ok")) { - completed = true; - _onProgress( - options.port, - 100, - 0, - -1, - true - ); - process?.kill(ProcessSignal.sigabrt); - return; - } - - final element = data.trim().split(" ")[0]; - if(!element.endsWith("%")) { - return; - } - - final percentage = int.parse(element.substring(0, element.length - 1)).toDouble(); - _onProgress( - options.port, - percentage, - 0, - -1, - true - ); - }); - process.stdError.listen((data) { - if(!data.isBlank) { - _onError(data, options); - } - }); - process.exitCode.then((_) { - if(!completed) { - _onError("Corrupted zip archive", options); - } - }); - break; - case ".rar": - final winrar = File("${assetsDirectory.path}\\build\\winrar.exe"); - if(!winrar.existsSync()) { - throw "Missing winrar.exe"; - } - - process = await startProcess( - executable: winrar, - args: [ - "x", - "-o+", - '"${tempFile.path}"', - "*.*", - '"${options.destination.path}"' - ] - ); - var completed = false; - process.stdOutput.listen((data) { - data = data.replaceAll("\r", "").replaceAll("\b", "").trim(); - if(data == "All OK") { - completed = true; - _onProgress( - options.port, - 100, - 0, - -1, - true - ); - process?.kill(ProcessSignal.sigabrt); - return; - } - - final element = _rarProgressRegex.firstMatch(data)?.group(1); - if(element == null) { - return; - } - - final percentage = int.parse(element).toDouble(); - _onProgress( - options.port, - percentage, - 0, - -1, - true - ); - }); - process.stdError.listen((data) { - if(!data.isBlank) { - _onError(data, options); - } - }); - process.exitCode.then((_) { - if(!completed) { - _onError("Corrupted rar archive", options); - } - }); - break; - default: - throw ArgumentError("Unexpected file extension: $extension}"); - } - - await Future.any([stopped.future, process.exitCode]); - process.kill(ProcessSignal.sigabrt); -} - -void _onProgress(SendPort port, double percentage, int speed, int minutesLeft, bool extracting) { - if(percentage == 0) { - port.send(FortniteBuildDownloadProgress( - progress: percentage, - extracting: extracting, - timeLeft: null, - speed: speed - )); - return; - } - - port.send(FortniteBuildDownloadProgress( - progress: percentage, - extracting: extracting, - timeLeft: minutesLeft, - speed: speed - )); -} - -void _onError(Object? error, FortniteBuildDownloadOptions options) { - if(error != null) { - options.port.send(error.toString()); - } -} - -Completer _setupLifecycle(FortniteBuildDownloadOptions options) { - var stopped = Completer(); - var lifecyclePort = ReceivePort(); - lifecyclePort.listen((message) { - if(message == kStopBuildDownloadSignal && !stopped.isCompleted) { - stopped.complete(); - } - }); - options.port.send(lifecyclePort.sendPort); - return stopped; -} - diff --git a/common/lib/src/util/dll.dart b/common/lib/src/util/dll.dart deleted file mode 100644 index 7a4de11..0000000 --- a/common/lib/src/util/dll.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'dart:io'; - -import 'package:archive/archive_io.dart'; -import 'package:http/http.dart' as http; -import 'package:path/path.dart' as path; -import 'package:reboot_common/common.dart'; - -final File rebootBeforeS20DllFile = File("${dllsDirectory.path}\\reboot.dll"); -final File rebootAboveS20DllFile = File("${dllsDirectory.path}\\rebootS20.dll"); - -const String kRebootBelowS20DownloadUrl = - "https://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/Reboot.zip"; -const String kRebootAboveS20DownloadUrl = - "https://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/RebootS20.zip"; - -const String _kRebootBelowS20FallbackDownloadUrl = - "https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootFallback.zip"; -const String _kRebootAboveS20FallbackDownloadUrl = - "https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootS20Fallback.zip"; - -Future hasRebootDllUpdate(int? lastUpdateMs, {int hours = 24, bool force = false}) async { - final lastUpdate = await _getLastUpdate(lastUpdateMs); - final exists = await rebootBeforeS20DllFile.exists() && await rebootAboveS20DllFile.exists(); - final now = DateTime.now(); - return force || !exists || (hours > 0 && lastUpdate != null && now.difference(lastUpdate).inHours > hours); -} - -Future downloadDependency(InjectableDll dll, String outputPath) async { - String? name; - switch(dll) { - case InjectableDll.console: - name = "console.dll"; - case InjectableDll.auth: - name = "cobalt.dll"; - case InjectableDll.memoryLeak: - name = "memory.dll"; - case InjectableDll.gameServer: - name = null; - } - if(name == null) { - return; - } - - final response = await http.get(Uri.parse("https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/$name")); - if(response.statusCode != 200) { - throw Exception("Cannot download $name: status code ${response.statusCode}"); - } - - final output = File(outputPath); - await output.parent.create(recursive: true); - await output.writeAsBytes(response.bodyBytes, flush: true); -} - -Future downloadRebootDll(File file, String url, bool aboveS20) async { - Directory? outputDir; - try { - var response = await http.get(Uri.parse(url)); - if(response.statusCode != 200) { - response = await http.get(Uri.parse(aboveS20 ? _kRebootAboveS20FallbackDownloadUrl : _kRebootBelowS20FallbackDownloadUrl)); - if(response.statusCode != 200) { - throw Exception("status code ${response.statusCode}"); - } - } - - outputDir = await installationDirectory.createTemp("reboot_out"); - final tempZip = File("${outputDir.path}\\reboot.zip"); - await tempZip.writeAsBytes(response.bodyBytes, flush: true); - await extractFileToDisk(tempZip.path, outputDir.path); - final rebootDll = File(outputDir.listSync().firstWhere((element) => path.extension(element.path) == ".dll").path); - await file.writeAsBytes(await rebootDll.readAsBytes(), flush: true); - } finally{ - if(outputDir != null) { - delete(outputDir); - } - } -} - -Future _getLastUpdate(int? lastUpdateMs) async { - return lastUpdateMs != null - ? DateTime.fromMillisecondsSinceEpoch(lastUpdateMs) - : null; -} \ No newline at end of file diff --git a/common/lib/src/util/downloader.dart b/common/lib/src/util/downloader.dart new file mode 100644 index 0000000..5dd2f32 --- /dev/null +++ b/common/lib/src/util/downloader.dart @@ -0,0 +1,546 @@ +import 'dart:io'; + +import 'package:archive/archive_io.dart'; +import 'package:http/http.dart' as http; +import 'package:path/path.dart' as path; +import 'package:reboot_common/common.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'dart:isolate'; + +import 'package:reboot_common/src/extension/types.dart'; +import 'package:uuid/uuid.dart'; + + +final File rebootBeforeS20DllFile = File("${dllsDirectory.path}\\reboot.dll"); +final File rebootAboveS20DllFile = File("${dllsDirectory.path}\\rebootS20.dll"); + +const String kRebootBelowS20DownloadUrl = + "https://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/Reboot.zip"; +const String kRebootAboveS20DownloadUrl = + "https://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/RebootS20.zip"; + +const String _kRebootBelowS20FallbackDownloadUrl = + "https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootFallback.zip"; +const String _kRebootAboveS20FallbackDownloadUrl = + "https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootS20Fallback.zip"; + +const String kStopBuildDownloadSignal = "kill"; + +final int _ariaPort = 6800; +final Uri _ariaEndpoint = Uri.parse('http://localhost:$_ariaPort/jsonrpc'); +final Duration _ariaMaxSpawnTime = const Duration(seconds: 10); +final RegExp _rarProgressRegex = RegExp("^((100)|(\\d{1,2}(.\\d*)?))%\$"); +final List downloadableBuilds = [ + FortniteBuild(gameVersion: "1.7.2", link: "https://public.simplyblk.xyz/1.7.2.zip", available: true), + FortniteBuild(gameVersion: "1.8", link: "https://public.simplyblk.xyz/1.8.rar", available: true), + FortniteBuild(gameVersion: "1.8.1", link: "https://public.simplyblk.xyz/1.8.1.rar", available: true), + FortniteBuild(gameVersion: "1.8.2", link: "https://public.simplyblk.xyz/1.8.2.rar", available: true), + FortniteBuild(gameVersion: "1.9", link: "https://public.simplyblk.xyz/1.9.rar", available: true), + FortniteBuild(gameVersion: "1.9.1", link: "https://public.simplyblk.xyz/1.9.1.rar", available: true), + FortniteBuild(gameVersion: "1.10", link: "https://public.simplyblk.xyz/1.10.rar", available: true), + FortniteBuild(gameVersion: "1.11", link: "https://public.simplyblk.xyz/1.11.zip", available: true), + FortniteBuild(gameVersion: "2.1.0", link: "https://public.simplyblk.xyz/2.1.0.zip", available: true), + FortniteBuild(gameVersion: "2.2.0", link: "https://public.simplyblk.xyz/2.2.0.rar", available: true), + FortniteBuild(gameVersion: "2.3", link: "https://public.simplyblk.xyz/2.3.rar", available: true), + FortniteBuild(gameVersion: "2.4.0", link: "https://public.simplyblk.xyz/2.4.0.zip", available: true), + FortniteBuild(gameVersion: "2.4.2", link: "https://public.simplyblk.xyz/2.4.2.zip", available: true), + FortniteBuild(gameVersion: "2.5.0", link: "https://public.simplyblk.xyz/2.5.0.rar", available: true), + FortniteBuild(gameVersion: "3.0", link: "https://public.simplyblk.xyz/3.0.zip", available: true), + FortniteBuild(gameVersion: "3.1", link: "https://public.simplyblk.xyz/3.1.rar", available: true), + FortniteBuild(gameVersion: "3.1.1", link: "https://public.simplyblk.xyz/3.1.1.zip", available: true), + FortniteBuild(gameVersion: "3.2", link: "https://public.simplyblk.xyz/3.2.zip", available: true), + FortniteBuild(gameVersion: "3.3", link: "https://public.simplyblk.xyz/3.3.rar", available: true), + FortniteBuild(gameVersion: "3.5", link: "https://public.simplyblk.xyz/3.5.rar", available: true), + FortniteBuild(gameVersion: "3.6", link: "https://public.simplyblk.xyz/3.6.zip", available: true), + FortniteBuild(gameVersion: "4.0", link: "https://public.simplyblk.xyz/4.0.zip", available: true), + FortniteBuild(gameVersion: "4.1", link: "https://public.simplyblk.xyz/4.1.zip", available: true), + FortniteBuild(gameVersion: "4.2", link: "https://public.simplyblk.xyz/4.2.zip", available: true), + FortniteBuild(gameVersion: "4.4", link: "https://public.simplyblk.xyz/4.4.rar", available: true), + FortniteBuild(gameVersion: "4.5", link: "https://public.simplyblk.xyz/4.5.rar", available: true), + FortniteBuild(gameVersion: "5.00", link: "https://public.simplyblk.xyz/5.00.rar", available: true), + FortniteBuild(gameVersion: "5.0.1", link: "https://public.simplyblk.xyz/5.0.1.rar", available: true), + FortniteBuild(gameVersion: "5.10", link: "https://public.simplyblk.xyz/5.10.rar", available: true), + FortniteBuild(gameVersion: "5.21", link: "https://public.simplyblk.xyz/5.21.rar", available: true), + FortniteBuild(gameVersion: "5.30", link: "https://public.simplyblk.xyz/5.30.rar", available: true), + FortniteBuild(gameVersion: "5.40", link: "https://public.simplyblk.xyz/5.40.rar", available: true), + FortniteBuild(gameVersion: "6.00", link: "https://public.simplyblk.xyz/6.00.rar", available: true), + FortniteBuild(gameVersion: "6.01", link: "https://public.simplyblk.xyz/6.01.rar", available: true), + FortniteBuild(gameVersion: "6.1.1", link: "https://public.simplyblk.xyz/6.1.1.rar", available: true), + FortniteBuild(gameVersion: "6.02", link: "https://public.simplyblk.xyz/6.02.rar", available: true), + FortniteBuild(gameVersion: "6.2.1", link: "https://public.simplyblk.xyz/6.2.1.rar", available: true), + FortniteBuild(gameVersion: "6.10", link: "https://public.simplyblk.xyz/6.10.rar", available: true), + FortniteBuild(gameVersion: "6.10.1", link: "https://public.simplyblk.xyz/6.10.1.rar", available: true), + FortniteBuild(gameVersion: "6.10.2", link: "https://public.simplyblk.xyz/6.10.2.rar", available: true), + FortniteBuild(gameVersion: "6.21", link: "https://public.simplyblk.xyz/6.21.rar", available: true), + FortniteBuild(gameVersion: "6.22", link: "https://public.simplyblk.xyz/6.22.rar", available: true), + FortniteBuild(gameVersion: "6.30", link: "https://public.simplyblk.xyz/6.30.rar", available: true), + FortniteBuild(gameVersion: "6.31", link: "https://public.simplyblk.xyz/6.31.rar", available: true), + FortniteBuild(gameVersion: "7.00", link: "https://public.simplyblk.xyz/7.00.rar", available: true), + FortniteBuild(gameVersion: "7.10", link: "https://public.simplyblk.xyz/7.10.rar", available: true), + FortniteBuild(gameVersion: "7.20", link: "https://public.simplyblk.xyz/7.20.rar", available: true), + FortniteBuild(gameVersion: "7.30", link: "https://public.simplyblk.xyz/7.30.zip", available: true), + FortniteBuild(gameVersion: "7.40", link: "https://public.simplyblk.xyz/7.40.rar", available: true), + FortniteBuild(gameVersion: "8.00", link: "https://public.simplyblk.xyz/8.00.zip", available: true), + FortniteBuild(gameVersion: "8.20", link: "https://public.simplyblk.xyz/8.20.rar", available: true), + FortniteBuild(gameVersion: "8.30", link: "https://public.simplyblk.xyz/8.30.rar", available: true), + FortniteBuild(gameVersion: "8.40", link: "https://public.simplyblk.xyz/8.40.zip", available: true), + FortniteBuild(gameVersion: "8.50", link: "https://public.simplyblk.xyz/8.50.zip", available: true), + FortniteBuild(gameVersion: "8.51", link: "https://public.simplyblk.xyz/8.51.rar", available: true), + FortniteBuild(gameVersion: "9.00", link: "https://public.simplyblk.xyz/9.00.zip", available: true), + FortniteBuild(gameVersion: "9.01", link: "https://public.simplyblk.xyz/9.01.zip", available: true), + FortniteBuild(gameVersion: "9.10", link: "https://public.simplyblk.xyz/9.10.rar", available: true), + FortniteBuild(gameVersion: "9.21", link: "https://public.simplyblk.xyz/9.21.zip", available: true), + FortniteBuild(gameVersion: "9.30", link: "https://public.simplyblk.xyz/9.30.zip", available: true), + FortniteBuild(gameVersion: "9.40", link: "https://public.simplyblk.xyz/9.40.zip", available: true), + FortniteBuild(gameVersion: "9.41", link: "https://public.simplyblk.xyz/9.41.rar", available: true), + FortniteBuild(gameVersion: "10.00", link: "https://public.simplyblk.xyz/10.00.zip", available: true), + FortniteBuild(gameVersion: "10.10", link: "https://public.simplyblk.xyz/10.10.zip", available: true), + FortniteBuild(gameVersion: "10.20", link: "https://public.simplyblk.xyz/10.20.zip", available: true), + FortniteBuild(gameVersion: "10.31", link: "https://public.simplyblk.xyz/10.31.zip", available: true), + FortniteBuild(gameVersion: "10.40", link: "https://public.simplyblk.xyz/10.40.rar", available: true), + FortniteBuild(gameVersion: "11.00", link: "https://public.simplyblk.xyz/11.00.zip", available: true), + FortniteBuild(gameVersion: "11.31", link: "https://public.simplyblk.xyz/11.31.rar", available: true), + FortniteBuild(gameVersion: "12.00", link: "https://public.simplyblk.xyz/12.00.rar", available: true), + FortniteBuild(gameVersion: "12.21", link: "https://public.simplyblk.xyz/12.21.zip", available: true), + FortniteBuild(gameVersion: "12.50", link: "https://public.simplyblk.xyz/12.50.zip", available: true), + FortniteBuild(gameVersion: "12.61", link: "https://public.simplyblk.xyz/12.61.zip", available: true), + FortniteBuild(gameVersion: "13.00", link: "https://public.simplyblk.xyz/13.00.rar", available: true), + FortniteBuild(gameVersion: "13.40", link: "https://public.simplyblk.xyz/13.40.zip", available: true), + FortniteBuild(gameVersion: "14.00", link: "https://public.simplyblk.xyz/14.00.rar", available: true), + FortniteBuild(gameVersion: "14.40", link: "https://public.simplyblk.xyz/14.40.rar", available: true), + FortniteBuild(gameVersion: "14.60", link: "https://public.simplyblk.xyz/14.60.rar", available: true), + FortniteBuild(gameVersion: "15.30", link: "https://public.simplyblk.xyz/15.30.rar", available: true), + FortniteBuild(gameVersion: "16.40", link: "https://public.simplyblk.xyz/16.40.rar", available: true), + FortniteBuild(gameVersion: "17.30", link: "https://public.simplyblk.xyz/17.30.zip", available: true), + FortniteBuild(gameVersion: "17.50", link: "https://public.simplyblk.xyz/17.50.zip", available: true), + FortniteBuild(gameVersion: "18.40", link: "https://public.simplyblk.xyz/18.40.zip", available: true), + FortniteBuild(gameVersion: "19.10", link: "https://public.simplyblk.xyz/19.10.rar", available: true), + FortniteBuild(gameVersion: "20.40", link: "https://public.simplyblk.xyz/20.40.zip", available: true), +]; + + +Future downloadArchiveBuild(FortniteBuildDownloadOptions options) async { + final fileName = options.build.link.substring(options.build.link.lastIndexOf("/") + 1); + final outputFile = File("${options.destination.path}\\.build\\$fileName"); + Timer? timer; + try { + final stopped = _setupLifecycle(options); + await outputFile.parent.create(recursive: true); + + final downloadItemCompleter = Completer(); + + await _startAriaServer(); + final downloadId = await _startAriaDownload(options, outputFile); + timer = Timer.periodic(const Duration(seconds: 5), (Timer timer) async { + try { + final statusRequestId = Uuid().toString().replaceAll("-", ""); + final statusRequest = { + "jsonrcp": "2.0", + "id": statusRequestId, + "method": "aria2.tellStatus", + "params": [ + downloadId + ] + }; + final statusResponse = await http.post(_ariaEndpoint, body: jsonEncode(statusRequest)); + final statusResponseJson = jsonDecode(statusResponse.body) as Map?; + if(statusResponseJson == null) { + downloadItemCompleter.completeError("Invalid download status (invalid JSON)"); + timer.cancel(); + return; + } + + final result = statusResponseJson["result"]; + final files = result["files"] as List?; + if(files == null || files.isEmpty) { + downloadItemCompleter.completeError("Download aborted"); + timer.cancel(); + return; + } + + final error = result["errorCode"]; + if(error != null) { + final errorCode = int.tryParse(error); + if(errorCode == 0) { + final path = File(files[0]["path"]); + downloadItemCompleter.complete(path); + }else if(errorCode == 3) { + downloadItemCompleter.completeError("This build is not available yet"); + }else { + final errorMessage = result["errorMessage"]; + downloadItemCompleter.completeError("$errorMessage (error code $errorCode)"); + } + + timer.cancel(); + return; + } + + final speed = int.parse(result["downloadSpeed"] ?? "0"); + final completedLength = int.parse(files[0]["completedLength"] ?? "0"); + final totalLength = int.parse(files[0]["length"] ?? "0"); + + final percentage = completedLength * 100 / totalLength; + final minutesLeft = speed == 0 ? -1 : ((totalLength - completedLength) / speed / 60).round(); + _onProgress( + options.port, + percentage, + speed, + minutesLeft, + false + ); + }catch(error) { + throw "Invalid download status (${error})"; + } + }); + + await Future.any([stopped.future, downloadItemCompleter.future]); + if(!stopped.isCompleted) { + final extension = path.extension(fileName); + await _extractArchive(stopped, extension, await downloadItemCompleter.future, options); + }else { + await _stopAriaDownload(downloadId); + } + }catch(error) { + _onError(error, options); + }finally { + delete(outputFile); + timer?.cancel(); + } +} + +Future _startAriaServer() async { + await stopDownloadServer(); + final aria2c = File("${assetsDirectory.path}\\build\\aria2c.exe"); + if(!aria2c.existsSync()) { + throw "Missing aria2c.exe at ${aria2c.path}"; + } + + final process = await startProcess( + executable: aria2c, + args: [ + "--max-connection-per-server=${Platform.numberOfProcessors}", + "--split=${Platform.numberOfProcessors}", + "--enable-rpc", + "--rpc-listen-all=true", + "--rpc-allow-origin-all", + "--rpc-listen-port=$_ariaPort", + "--file-allocation=none", + "--check-certificate=false" + ], + window: false + ); + process.stdOutput.listen((message) => log("[ARIA] Message: $message")); + process.stdError.listen((error) => log("[ARIA] Error: $error")); + process.exitCode.then((exitCode) => log("[ARIA] Exit code: $exitCode")); + for(var i = 0; i < _ariaMaxSpawnTime.inSeconds; i++) { + if(await _isAriaRunning()) { + return; + } + await Future.delayed(const Duration(seconds: 1)); + } + throw "cannot start download server (timeout exceeded)"; +} + +Future _isAriaRunning() async { + try { + final statusRequestId = Uuid().toString().replaceAll("-", ""); + final statusRequest = { + "jsonrcp": "2.0", + "id": statusRequestId, + "method": "aria2.getVersion", + "params": [ + + ] + }; + final response = await http.post(_ariaEndpoint, body: jsonEncode(statusRequest)); + return response.statusCode == 200; + }catch(_) { + return false; + } +} + +Future _startAriaDownload(FortniteBuildDownloadOptions options, File outputFile) async { + http.Response? addDownloadResponse; + try { + final addDownloadRequestId = Uuid().toString().replaceAll("-", ""); + final addDownloadRequest = { + "jsonrcp": "2.0", + "id": addDownloadRequestId, + "method": "aria2.addUri", + "params": [ + [options.build.link], + { + "dir": outputFile.parent.path, + "out": path.basename(outputFile.path) + } + ] + }; + addDownloadResponse = await http.post(_ariaEndpoint, body: jsonEncode(addDownloadRequest)); + final addDownloadResponseJson = jsonDecode(addDownloadResponse.body); + final downloadId = addDownloadResponseJson is Map ? addDownloadResponseJson['result'] : null; + if(downloadId == null) { + throw "Start failed (${addDownloadResponse.body})"; + } + + return downloadId; + }catch(error) { + throw "Start failed (${addDownloadResponse?.body ?? error})"; + } +} + +Future _stopAriaDownload(String downloadId) async { + try { + final addDownloadRequestId = Uuid().toString().replaceAll("-", ""); + final addDownloadRequest = { + "jsonrcp": "2.0", + "id": addDownloadRequestId, + "method": "aria2.forceRemove", + "params": [ + downloadId + ] + }; + await http.post(_ariaEndpoint, body: jsonEncode(addDownloadRequest)); + stopDownloadServer(); + }catch(error) { + throw "Stop failed (${error})"; + } +} + +Future stopDownloadServer() async { + await killProcessByPort(_ariaPort); +} + + +Future _extractArchive(Completer stopped, String extension, File tempFile, FortniteBuildDownloadOptions options) async { + Process? process; + switch (extension.toLowerCase()) { + case ".zip": + final sevenZip = File("${assetsDirectory.path}\\build\\7zip.exe"); + if(!sevenZip.existsSync()) { + throw "Missing 7zip.exe"; + } + + process = await startProcess( + executable: sevenZip, + args: [ + "x", + "-bsp1", + '-o"${options.destination.path}"', + "-y", + '"${tempFile.path}"' + ], + ); + var completed = false; + process.stdOutput.listen((data) { + if(data.toLowerCase().contains("everything is ok")) { + completed = true; + _onProgress( + options.port, + 100, + 0, + -1, + true + ); + process?.kill(ProcessSignal.sigabrt); + return; + } + + final element = data.trim().split(" ")[0]; + if(!element.endsWith("%")) { + return; + } + + final percentage = int.parse(element.substring(0, element.length - 1)).toDouble(); + _onProgress( + options.port, + percentage, + 0, + -1, + true + ); + }); + process.stdError.listen((data) { + if(!data.isBlank) { + _onError(data, options); + } + }); + process.exitCode.then((_) { + if(!completed) { + _onError("Corrupted zip archive", options); + } + }); + break; + case ".rar": + final winrar = File("${assetsDirectory.path}\\build\\winrar.exe"); + if(!winrar.existsSync()) { + throw "Missing winrar.exe"; + } + + process = await startProcess( + executable: winrar, + args: [ + "x", + "-o+", + '"${tempFile.path}"', + "*.*", + '"${options.destination.path}"' + ] + ); + var completed = false; + process.stdOutput.listen((data) { + data = data.replaceAll("\r", "").replaceAll("\b", "").trim(); + if(data == "All OK") { + completed = true; + _onProgress( + options.port, + 100, + 0, + -1, + true + ); + process?.kill(ProcessSignal.sigabrt); + return; + } + + final element = _rarProgressRegex.firstMatch(data)?.group(1); + if(element == null) { + return; + } + + final percentage = int.parse(element).toDouble(); + _onProgress( + options.port, + percentage, + 0, + -1, + true + ); + }); + process.stdError.listen((data) { + if(!data.isBlank) { + _onError(data, options); + } + }); + process.exitCode.then((_) { + if(!completed) { + _onError("Corrupted rar archive", options); + } + }); + break; + default: + throw ArgumentError("Unexpected file extension: $extension}"); + } + + await Future.any([stopped.future, process.exitCode]); + process.kill(ProcessSignal.sigabrt); +} + +void _onProgress(SendPort port, double percentage, int speed, int minutesLeft, bool extracting) { + if(percentage == 0) { + port.send(FortniteBuildDownloadProgress( + progress: percentage, + extracting: extracting, + timeLeft: null, + speed: speed + )); + return; + } + + port.send(FortniteBuildDownloadProgress( + progress: percentage, + extracting: extracting, + timeLeft: minutesLeft, + speed: speed + )); +} + +void _onError(Object? error, FortniteBuildDownloadOptions options) { + if(error != null) { + options.port.send(error.toString()); + } +} + +Completer _setupLifecycle(FortniteBuildDownloadOptions options) { + var stopped = Completer(); + var lifecyclePort = ReceivePort(); + lifecyclePort.listen((message) { + if(message == kStopBuildDownloadSignal && !stopped.isCompleted) { + lifecyclePort.close(); + stopped.complete(); + } + }); + options.port.send(lifecyclePort.sendPort); + return stopped; +} + + + +Future hasRebootDllUpdate(int? lastUpdateMs, {int hours = 24, bool force = false}) async { + final lastUpdate = await _getLastUpdate(lastUpdateMs); + final exists = await rebootBeforeS20DllFile.exists() && await rebootAboveS20DllFile.exists(); + final now = DateTime.now(); + return force || !exists || (hours > 0 && lastUpdate != null && now.difference(lastUpdate).inHours > hours); +} + +Future downloadDependency(InjectableDll dll, String outputPath) async { + String? name; + switch(dll) { + case InjectableDll.console: + name = "console.dll"; + case InjectableDll.auth: + name = "cobalt.dll"; + case InjectableDll.memoryLeak: + name = "memory.dll"; + case InjectableDll.gameServer: + name = null; + } + if(name == null) { + return false; + } + + final response = await http.get(Uri.parse("https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/$name")); + if(response.statusCode != 200) { + throw Exception("Cannot download $name: status code ${response.statusCode}"); + } + + final output = File(outputPath); + await output.parent.create(recursive: true); + await output.writeAsBytes(response.bodyBytes, flush: true); + try { + await output.readAsBytes(); + return true; + }catch(_) { + return false; + } +} + +Future downloadRebootDll(File file, String url, bool aboveS20) async { + Directory? outputDir; + try { + var response = await http.get(Uri.parse(url)); + if(response.statusCode != 200) { + response = await http.get(Uri.parse(aboveS20 ? _kRebootAboveS20FallbackDownloadUrl : _kRebootBelowS20FallbackDownloadUrl)); + if(response.statusCode != 200) { + throw Exception("status code ${response.statusCode}"); + } + } + + outputDir = await installationDirectory.createTemp("reboot_out"); + final tempZip = File("${outputDir.path}\\reboot.zip"); + await tempZip.writeAsBytes(response.bodyBytes, flush: true); + await extractFileToDisk(tempZip.path, outputDir.path); + final rebootDll = File(outputDir.listSync().firstWhere((element) => path.extension(element.path) == ".dll").path); + await file.writeAsBytes(await rebootDll.readAsBytes(), flush: true); + } finally{ + if(outputDir != null) { + delete(outputDir); + } + } +} + +Future _getLastUpdate(int? lastUpdateMs) async { + return lastUpdateMs != null + ? DateTime.fromMillisecondsSinceEpoch(lastUpdateMs) + : null; +} \ No newline at end of file diff --git a/common/lib/src/util/game.dart b/common/lib/src/util/game.dart new file mode 100644 index 0000000..cb313e8 --- /dev/null +++ b/common/lib/src/util/game.dart @@ -0,0 +1,276 @@ +import 'dart:collection'; +import 'dart:ffi'; +import 'dart:io'; +import 'dart:isolate'; +import 'dart:typed_data'; +import 'package:ffi/ffi.dart'; +import 'package:reboot_common/common.dart'; +import 'package:win32/win32.dart'; + +final DynamicLibrary _shell32 = DynamicLibrary.open('shell32.dll'); +final SHGetPropertyStoreFromParsingName = +_shell32.lookupFunction< + Int32 Function(Pointer pszPath, Pointer pbc, Uint32 flags, + Pointer riid, Pointer> ppv), + int Function(Pointer pszPath, Pointer pbc, int flags, + Pointer riid, Pointer> ppv)>('SHGetPropertyStoreFromParsingName'); + +final Uint8List _originalHeadless = Uint8List.fromList([ + 45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 115, 0, 101, 0, 115, 0, 115, 0, 105, 0, 111, 0, 110, 0, 32, 0, 45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 102, 0, 114, 0, 111, 0, 109, 0, 32, 0, 45, 0, 112, 0, 97, 0, 114, 0, 116, 0, 121, 0, 95, 0, 106, 0, 111, 0, 105, 0, 110, 0, 105, 0, 110, 0, 102, 0, 111, 0, 95, 0, 116, 0, 111, 0, 107, 0, 101, 0, 110, 0, 32, 0, 45, 0, 114, 0, 101, 0, 112, 0, 108, 0, 97, 0, 121, 0 +]); + +final Uint8List _patchedHeadless = Uint8List.fromList([ + 45, 0, 108, 0, 111, 0, 103, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 112, 0, 108, 0, 97, 0, 115, 0, 104, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 111, 0, 117, 0, 110, 0, 100, 0, 32, 0, 45, 0, 110, 0, 117, 0, 108, 0, 108, 0, 114, 0, 104, 0, 105, 0, 32, 0, 45, 0, 117, 0, 115, 0, 101, 0, 111, 0, 108, 0, 100, 0, 105, 0, 116, 0, 101, 0, 109, 0, 99, 0, 97, 0, 114, 0, 100, 0, 115, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0 +]); + +// Not used right now +final Uint8List _originalMatchmaking = Uint8List.fromList([ + 63, 0, 69, 0, 110, 0, 99, 0, 114, 0, 121, 0, 112, 0, 116, 0, 105, 0, 111, 0, 110, 0, 84, 0, 111, 0, 107, 0, 101, 0, 110, 0, 61 +]); + +final Uint8List _patchedMatchmaking = Uint8List.fromList([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +]); + +Future patchHeadless(File file) async => + await _patch(file, _originalHeadless, _patchedHeadless); + +Future patchMatchmaking(File file) async => + await _patch(file, _originalMatchmaking, _patchedMatchmaking); + +Future _patch(File file, Uint8List original, Uint8List patched) async => Isolate.run(() async { + try { + if(original.length != patched.length){ + throw Exception("Cannot mutate length of binary file"); + } + + final source = await file.readAsBytes(); + var readOffset = 0; + var patchOffset = -1; + var patchCount = 0; + while(readOffset < source.length){ + if(source[readOffset] == original[patchCount]){ + if(patchOffset == -1) { + patchOffset = readOffset; + } + + if(readOffset - patchOffset + 1 == original.length) { + break; + } + + patchCount++; + }else { + patchOffset = -1; + patchCount = 0; + } + + readOffset++; + } + + if(patchOffset == -1) { + return false; + } + + for(var i = 0; i < patched.length; i++) { + source[patchOffset + i] = patched[i]; + } + + await file.writeAsBytes(source, flush: true); + return true; + }catch(_){ + return false; + } +}); + +List createRebootArgs(String username, String password, bool host, bool headless, bool logging, String additionalArgs) { + log("[PROCESS] Generating reboot args"); + if(password.isEmpty) { + username = '${_parseUsername(username, host)}@projectreboot.dev'; + } + + password = password.isNotEmpty ? password : "Rebooted"; + final args = LinkedHashMap( + equals: (a, b) => a.toUpperCase() == b.toUpperCase(), + hashCode: (a) => a.toUpperCase().hashCode + ); + args.addAll({ + "-epicapp": "Fortnite", + "-epicenv": "Prod", + "-epiclocale": "en-us", + "-epicportal": "", + "-skippatchcheck": "", + "-nobe": "", + "-fromfl": "eac", + "-fltoken": "3db3ba5dcbd2e16703f3978d", + "-caldera": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50X2lkIjoiYmU5ZGE1YzJmYmVhNDQwN2IyZjQwZWJhYWQ4NTlhZDQiLCJnZW5lcmF0ZWQiOjE2Mzg3MTcyNzgsImNhbGRlcmFHdWlkIjoiMzgxMGI4NjMtMmE2NS00NDU3LTliNTgtNGRhYjNiNDgyYTg2IiwiYWNQcm92aWRlciI6IkVhc3lBbnRpQ2hlYXQiLCJub3RlcyI6IiIsImZhbGxiYWNrIjpmYWxzZX0.VAWQB67RTxhiWOxx7DBjnzDnXyyEnX7OljJm-j2d88G_WgwQ9wrE6lwMEHZHjBd1ISJdUO1UVUqkfLdU5nofBQ", + "-AUTH_LOGIN": username, + "-AUTH_PASSWORD": password.isNotEmpty ? password : "Rebooted", + "-AUTH_TYPE": "epic" + }); + + if(logging) { + args["-log"] = ""; + } + + if(host) { + args["-nosplash"] = ""; + args["-nosound"] = ""; + if(headless){ + args["-nullrhi"] = ""; + } + } + + log("[PROCESS] Default args: $args"); + log("[PROCESS] Adding custom args: $additionalArgs"); + for(final additionalArg in additionalArgs.split(" ")) { + log("[PROCESS] Processing custom arg: $additionalArg"); + final separatorIndex = additionalArg.indexOf("="); + final argName = separatorIndex == -1 ? additionalArg : additionalArg.substring(0, separatorIndex); + log("[PROCESS] Custom arg key: $argName"); + final argValue = separatorIndex == -1 || separatorIndex + 1 >= additionalArg.length ? "" : additionalArg.substring(separatorIndex + 1); + log("[PROCESS] Custom arg value: $argValue"); + args[argName] = argValue; + log("[PROCESS] Updated args: $args"); + } + + log("[PROCESS] Final args result: $args"); + return args.entries + .map((entry) => entry.value.isEmpty ? entry.key : "${entry.key}=${entry.value}") + .toList(); +} + +void handleGameOutput({ + required String line, + required bool host, + required void Function() onLoggedIn, + required void Function() onMatchEnd, + required void Function() onShutdown, + required void Function() onTokenError, + required void Function() onBuildCorrupted, +}) { + if (line.contains(kShutdownLine)) { + log("[FORTNITE_OUTPUT_HANDLER] Detected shutdown: $line"); + onShutdown(); + }else if(kCorruptedBuildErrors.any((element) => line.contains(element))){ + log("[FORTNITE_OUTPUT_HANDLER] Detected corrupt build: $line"); + onBuildCorrupted(); + }else if(kCannotConnectErrors.any((element) => line.contains(element))){ + log("[FORTNITE_OUTPUT_HANDLER] Detected cannot connect error: $line"); + onTokenError(); + }else if(kLoggedInLines.every((entry) => line.contains(entry))) { + log("[FORTNITE_OUTPUT_HANDLER] Detected logged in: $line"); + onLoggedIn(); + }else if(line.contains(kGameFinishedLine) && host) { + log("[FORTNITE_OUTPUT_HANDLER] Detected match end: $line"); + onMatchEnd(); + } +} + +String _parseUsername(String username, bool host) { + if (username.isEmpty) { + return kDefaultPlayerName; + } + + username = username.replaceAll(RegExp("[^A-Za-z0-9]"), "").trim(); + if(username.isEmpty){ + return kDefaultPlayerName; + } + + return username; +} + +Future extractGameVersion(String filePath, String defaultGameVersion) => Isolate.run(() { + final filePathPtr = filePath.toNativeUtf16(); + final pPropertyStore = calloc(); + final iidPropertyStore = GUIDFromString(IID_IPropertyStore); + final ret = SHGetPropertyStoreFromParsingName( + filePathPtr, + nullptr, + GETPROPERTYSTOREFLAGS.GPS_DEFAULT, + iidPropertyStore, + pPropertyStore.cast() + ); + + calloc.free(filePathPtr); + calloc.free(iidPropertyStore); + + if (FAILED(ret)) { + calloc.free(pPropertyStore); + throw WindowsException(ret); + } + + final propertyStore = IPropertyStore(pPropertyStore); + + final countPtr = calloc(); + final hrCount = propertyStore.getCount(countPtr); + final count = countPtr.value; + calloc.free(countPtr); + if (FAILED(hrCount)) { + throw WindowsException(hrCount); + } + + for (var i = 0; i < count; i++) { + final pKey = calloc(); + final hrKey = propertyStore.getAt(i, pKey); + if (FAILED(hrKey)) { + calloc.free(pKey); + continue; + } + + final pv = calloc(); + final hrValue = propertyStore.getValue(pKey, pv); + if (!FAILED(hrValue)) { + if (pv.ref.vt == VARENUM.VT_LPWSTR) { + final valueStr = pv.ref.pwszVal.toDartString(); + if (valueStr.contains("+++Fortnite")) { + var gameVersion = valueStr.substring(valueStr.lastIndexOf("-") + 1); + if(gameVersion == "Cert") { + final engineVersion = valueStr.substring(0, valueStr.indexOf("+")); + final engineVersionParts = engineVersion.split("-"); + final engineVersionBuild = int.parse(engineVersionParts[1]); + switch (engineVersionBuild) { + case 2870186: + gameVersion = "OT6.5"; + break; + case 3700114: + gameVersion = "1.7.2"; + break; + case 3724489: + gameVersion = "1.8.0"; + break; + case 3729133: + gameVersion = "1.8.1"; + break; + case 3741772: + gameVersion = "1.8.2"; + break; + case 3757339: + gameVersion = "1.9"; + break; + case 3775276: + gameVersion = "1.9.1"; + break; + case 3790078: + gameVersion = "1.10"; + break; + case 3807424: + gameVersion = "1.11"; + break; + case 3825894: + gameVersion = "2.1"; + break; + default: + gameVersion = defaultGameVersion; + break; + } + } + return gameVersion; + } + } + } + calloc.free(pKey); + calloc.free(pv); + } + + return defaultGameVersion; +}); \ No newline at end of file diff --git a/common/lib/src/util/log.dart b/common/lib/src/util/log.dart index d44bb16..f299e48 100644 --- a/common/lib/src/util/log.dart +++ b/common/lib/src/util/log.dart @@ -5,6 +5,7 @@ import 'package:sync/semaphore.dart'; final File launcherLogFile = _createLoggingFile(); final Semaphore _semaphore = Semaphore(1); +bool enableLoggingToConsole = true; File _createLoggingFile() { final file = File("${installationDirectory.path}\\launcher.log"); @@ -19,7 +20,9 @@ File _createLoggingFile() { void log(String message) async { try { await _semaphore.acquire(); - print(message); + if(enableLoggingToConsole) { + print(message); + } await launcherLogFile.writeAsString("$message\n", mode: FileMode.append, flush: true); }catch(error) { print("[LOGGER_ERROR] An error occurred while logging: $error"); diff --git a/common/lib/src/util/network.dart b/common/lib/src/util/network.dart deleted file mode 100644 index 64fb74a..0000000 --- a/common/lib/src/util/network.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; -import 'package:win32/win32.dart'; - -const _AF_INET = 2; -const _TCP_TABLE_OWNER_PID_LISTENER = 3; - -final _getExtendedTcpTable = DynamicLibrary.open('iphlpapi.dll').lookupFunction< - Int32 Function(Pointer, Pointer, Int32, Int32, Int32, Int32), - int Function(Pointer, Pointer, int, int, int, int)>('GetExtendedTcpTable'); - -final class _MIB_TCPROW_OWNER_PID extends Struct { - @Uint32() - external int dwState; - - @Uint32() - external int dwLocalAddr; - - @Uint32() - external int dwLocalPort; - - @Uint32() - external int dwRemoteAddr; - - @Uint32() - external int dwRemotePort; - - @Uint32() - external int dwOwningPid; -} - -final class _MIB_TCPTABLE_OWNER_PID extends Struct { - @Uint32() - external int dwNumEntries; - - @Array(512) - external Array<_MIB_TCPROW_OWNER_PID> table; -} - - -bool isLocalHost(String host) => host.trim() == "127.0.0.1" - || host.trim().toLowerCase() == "localhost" - || host.trim() == "0.0.0.0"; - -bool killProcessByPort(int port) { - var pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>(); - final dwSize = calloc(); - dwSize.value = 0; - int result = _getExtendedTcpTable( - nullptr, - dwSize, - FALSE, - _AF_INET, - _TCP_TABLE_OWNER_PID_LISTENER, - 0 - ); - if (result == ERROR_INSUFFICIENT_BUFFER) { - free(pTcpTable); - pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>(dwSize.value); - result = _getExtendedTcpTable( - pTcpTable, - dwSize, - FALSE, - _AF_INET, - _TCP_TABLE_OWNER_PID_LISTENER, - 0 - ); - } - - if (result == NO_ERROR) { - final table = pTcpTable.ref; - for (int i = 0; i < table.dwNumEntries; i++) { - final row = table.table[i]; - final localPort = _htons(row.dwLocalPort); - if (localPort == port) { - final pid = row.dwOwningPid; - calloc.free(pTcpTable); - calloc.free(dwSize); - final hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); - if (hProcess != NULL) { - final result = TerminateProcess(hProcess, 0); - CloseHandle(hProcess); - return result != 0; - } - return false; - } - } - } - - calloc.free(pTcpTable); - calloc.free(dwSize); - return false; -} - -int _htons(int port) => ((port & 0xFF) << 8) | ((port >> 8) & 0xFF); \ No newline at end of file diff --git a/common/lib/src/util/os.dart b/common/lib/src/util/os.dart new file mode 100644 index 0000000..3ff9eef --- /dev/null +++ b/common/lib/src/util/os.dart @@ -0,0 +1,468 @@ +import 'dart:async'; +import 'dart:ffi'; +import 'dart:io'; +import 'dart:isolate'; +import 'dart:typed_data'; + +import 'package:ffi/ffi.dart'; +import 'package:reboot_common/common.dart'; +import 'package:win32/win32.dart'; +import 'package:path/path.dart' as path; + +bool useDefaultPath = false; + +Directory get installationDirectory { + if(useDefaultPath) { + final dir = Directory('$_home/Reboot Launcher'); + dir.createSync(recursive: true); + return dir; + }else { + return File(Platform.resolvedExecutable).parent; + } +} + + +String get _home { + if (Platform.isMacOS) { + return Platform.environment['HOME'] ?? '.'; + } else if (Platform.isLinux) { + return Platform.environment['HOME'] ?? '.'; + } else if (Platform.isWindows) { + return Platform.environment['UserProfile'] ?? '.'; + }else { + return '.'; + } +} + +String? get antiVirusName { + final pLoc = calloc(); + final rclsid = GUIDFromString(CLSID_WbemLocator); + final riid = GUIDFromString(IID_IWbemLocator); + final hr = CoCreateInstance( + rclsid, + nullptr, + CLSCTX.CLSCTX_INPROC_SERVER, + riid, + pLoc.cast(), + ); + + calloc.free(rclsid); + calloc.free(riid); + + if (FAILED(hr)) { + return null; + } + + final locator = IWbemLocator(pLoc); + + final pSvc = calloc(); + final scope = 'ROOT\\SecurityCenter2'.toNativeUtf16(); + + final hr2 = locator.connectServer( + scope, + nullptr, + nullptr, + nullptr, + 0, + nullptr, + nullptr, + pSvc.cast() + ); + + calloc.free(scope); + + if (FAILED(hr2)) { + return null; + } + + final service = IWbemServices(pSvc); + + final pEnumerator = calloc(); + final wql = 'WQL'.toNativeUtf16(); + final query = 'SELECT * FROM AntiVirusProduct'.toNativeUtf16(); + + final hr3 = service.execQuery( + wql, + query, + WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_FORWARD_ONLY | WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY, + nullptr, + pEnumerator.cast(), + ); + + calloc.free(wql); + calloc.free(query); + + if (FAILED(hr3)) { + return null; + } + + final enumerator = IEnumWbemClassObject(pEnumerator); + + final uReturn = calloc(); + final pClsObj = calloc(); + + final hr4 = enumerator.next( + WBEM_INFINITE, + 1, + pClsObj.cast(), + uReturn, + ); + + String? result; + if (SUCCEEDED(hr4) && uReturn.value > 0) { + final clsObj = IWbemClassObject(pClsObj); + + final vtProp = calloc(); + final propName = 'displayName'.toNativeUtf16(); + + final hr5 = clsObj.get( + propName, + 0, + vtProp, + nullptr, + nullptr, + ); + + calloc.free(propName); + + if (SUCCEEDED(hr5) && vtProp.ref.vt == VARENUM.VT_BSTR) { + final bstr = vtProp.ref.bstrVal; + result = bstr.toDartString(); + } + + calloc.free(vtProp); + } + + calloc.free(uReturn); + + return result; +} + +String get defaultAntiVirusName => "Windows Defender"; + +Directory get dllsDirectory => Directory("${installationDirectory.path}\\dlls"); + +Directory get assetsDirectory { + final directory = Directory("${installationDirectory.path}\\data\\flutter_assets\\assets"); + if(directory.existsSync()) { + return directory; + } + + return installationDirectory; +} + +Directory get settingsDirectory => + Directory("${installationDirectory.path}\\settings"); + +Directory get tempDirectory => + Directory(Platform.environment["Temp"]!); + +Future delete(FileSystemEntity file) async { + try { + await file.delete(recursive: true); + return true; + }catch(_){ + return Future.delayed(const Duration(seconds: 5)).then((value) async { + try { + await file.delete(recursive: true); + return true; + }catch(_){ + return false; + } + }); + } +} + +const _AF_INET = 2; +const _TCP_TABLE_OWNER_PID_LISTENER = 3; + +final _getExtendedTcpTable = DynamicLibrary.open('iphlpapi.dll').lookupFunction< + Int32 Function(Pointer, Pointer, Int32, Int32, Int32, Int32), + int Function(Pointer, Pointer, int, int, int, int)>('GetExtendedTcpTable'); + +final class _MIB_TCPROW_OWNER_PID extends Struct { + @Uint32() + external int dwState; + + @Uint32() + external int dwLocalAddr; + + @Uint32() + external int dwLocalPort; + + @Uint32() + external int dwRemoteAddr; + + @Uint32() + external int dwRemotePort; + + @Uint32() + external int dwOwningPid; +} + +final class _MIB_TCPTABLE_OWNER_PID extends Struct { + @Uint32() + external int dwNumEntries; + + @Array(512) + external Array<_MIB_TCPROW_OWNER_PID> table; +} + + +bool isLocalHost(String host) => host.trim() == "127.0.0.1" + || host.trim().toLowerCase() == "localhost" + || host.trim() == "0.0.0.0"; + +bool killProcessByPort(int port) { + var pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>(); + final dwSize = calloc(); + dwSize.value = 0; + int result = _getExtendedTcpTable( + nullptr, + dwSize, + FALSE, + _AF_INET, + _TCP_TABLE_OWNER_PID_LISTENER, + 0 + ); + if (result == WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER) { + calloc.free(pTcpTable); + pTcpTable = calloc<_MIB_TCPTABLE_OWNER_PID>(dwSize.value); + result = _getExtendedTcpTable( + pTcpTable, + dwSize, + FALSE, + _AF_INET, + _TCP_TABLE_OWNER_PID_LISTENER, + 0 + ); + } + + if (result == NO_ERROR) { + final table = pTcpTable.ref; + for (int i = 0; i < table.dwNumEntries; i++) { + final row = table.table[i]; + final localPort = _htons(row.dwLocalPort); + if (localPort == port) { + final pid = row.dwOwningPid; + calloc.free(pTcpTable); + calloc.free(dwSize); + final hProcess = OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_TERMINATE, FALSE, pid); + if (hProcess != NULL) { + final result = TerminateProcess(hProcess, 0); + CloseHandle(hProcess); + return result != 0; + } + return false; + } + } + } + + calloc.free(pTcpTable); + calloc.free(dwSize); + return false; +} + +int _htons(int port) => ((port & 0xFF) << 8) | ((port >> 8) & 0xFF); + +final _kernel32 = DynamicLibrary.open('kernel32.dll'); +final _CreateRemoteThread = _kernel32.lookupFunction< + IntPtr Function( + IntPtr hProcess, + Pointer lpThreadAttributes, + IntPtr dwStackSize, + Pointer loadLibraryAddress, + Pointer lpParameter, + Uint32 dwCreationFlags, + Pointer lpThreadId), + int Function( + int hProcess, + Pointer lpThreadAttributes, + int dwStackSize, + Pointer loadLibraryAddress, + Pointer lpParameter, + int dwCreationFlags, + Pointer lpThreadId)>('CreateRemoteThread'); + +Future injectDll(int pid, File file) async { + try { + await file.readAsBytes(); + }catch(_) { + throw "${path.basename(file.path)} is not accessible"; + } + + final process = OpenProcess(0x43A, FALSE, pid); + + final processAddress = GetProcAddress( + GetModuleHandle("KERNEL32".toNativeUtf16()), + "LoadLibraryA".toNativeUtf8() + ); + + if (processAddress == nullptr) { + throw "Cannot get process address for pid $pid"; + } + + final dllAddress = VirtualAllocEx( + process, + nullptr, + file.path.length + 1, + 0x3000, + 0x4 + ); + if(dllAddress == 0) { + throw "Cannot allocate memory for dll"; + } + + final writeMemoryResult = WriteProcessMemory( + process, + dllAddress, + file.path.toNativeUtf8(), + file.path.length, + nullptr + ); + if (writeMemoryResult != 1) { + throw "Memory write failed"; + } + + final createThreadResult = _CreateRemoteThread( + process, + nullptr, + 0, + processAddress, + dllAddress, + 0, + nullptr + ); + + if (createThreadResult == -1) { + throw "Thread creation failed"; + } + + CloseHandle(process); +} + +Future startElevatedProcess({required String executable, required String args, bool window = false}) async { + var shellInput = calloc(); + shellInput.ref.lpFile = executable.toNativeUtf16(); + shellInput.ref.lpParameters = args.toNativeUtf16(); + shellInput.ref.nShow = window ? SHOW_WINDOW_CMD.SW_SHOWNORMAL : SHOW_WINDOW_CMD.SW_HIDE; + shellInput.ref.fMask = EXECUTION_STATE.ES_AWAYMODE_REQUIRED; + shellInput.ref.lpVerb = "runas".toNativeUtf16(); + shellInput.ref.cbSize = sizeOf(); + return ShellExecuteEx(shellInput) == 1; +} + +Future startProcess({required File executable, List? args, bool useTempBatch = true, bool window = false, String? name, Map? environment}) async { + log("[PROCESS] Starting process on ${executable.path} with $args (useTempBatch: $useTempBatch, window: $window, name: $name, environment: $environment)"); + final argsOrEmpty = args ?? []; + final workingDirectory = _getWorkingDirectory(executable); + if(useTempBatch) { + final tempScriptDirectory = await tempDirectory.createTemp("reboot_launcher_process"); + final tempScriptFile = File("${tempScriptDirectory.path}\\process.bat"); + final command = window ? 'cmd.exe /k ""${executable.path}" ${argsOrEmpty.join(" ")}"' : '"${executable.path}" ${argsOrEmpty.join(" ")}'; + await tempScriptFile.writeAsString(command, flush: true); + final process = await Process.start( + tempScriptFile.path, + [], + workingDirectory: workingDirectory, + environment: environment, + mode: window ? ProcessStartMode.detachedWithStdio : ProcessStartMode.normal, + runInShell: window + ); + return _ExtendedProcess(process, true); + } + + final process = await Process.start( + executable.path, + args ?? [], + workingDirectory: workingDirectory, + mode: window ? ProcessStartMode.detachedWithStdio : ProcessStartMode.normal, + runInShell: window + ); + return _ExtendedProcess(process, true); +} + +String? _getWorkingDirectory(File executable) { + try { + log("[PROCESS] Calculating working directory for $executable"); + final workingDirectory = executable.parent.resolveSymbolicLinksSync(); + log("[PROCESS] Using working directory: $workingDirectory"); + return workingDirectory; + }catch(error) { + log("[PROCESS] Cannot infer working directory: $error"); + return null; + } +} + +final _ntdll = DynamicLibrary.open('ntdll.dll'); +final _NtResumeProcess = _ntdll.lookupFunction('NtResumeProcess'); + +final _NtSuspendProcess = _ntdll.lookupFunction('NtSuspendProcess'); + +bool suspend(int pid) { + final processHandle = OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_SUSPEND_RESUME, FALSE, pid); + try { + return _NtSuspendProcess(processHandle) == 0; + } finally { + CloseHandle(processHandle); + } +} + +bool resume(int pid) { + final processHandle = OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_SUSPEND_RESUME, FALSE, pid); + try { + return _NtResumeProcess(processHandle) == 0; + } finally { + CloseHandle(processHandle); + } +} + +final class _ExtendedProcess implements Process { + final Process _delegate; + final Stream>? _stdout; + final Stream>? _stderr; + _ExtendedProcess(Process delegate, bool attached) : + _delegate = delegate, + _stdout = attached ? delegate.stdout.asBroadcastStream() : null, + _stderr = attached ? delegate.stderr.asBroadcastStream() : null; + + @override + Future get exitCode => _delegate.exitCode; + + @override + bool kill([ProcessSignal signal = ProcessSignal.sigterm]) => _delegate.kill(signal); + + @override + int get pid => _delegate.pid; + + @override + IOSink get stdin => _delegate.stdin; + + @override + Stream> get stdout { + final out = _stdout; + if(out == null) { + throw StateError("Output is not attached"); + } + + return out; + } + + @override + Stream> get stderr { + final err = _stderr; + if(err == null) { + throw StateError("Output is not attached"); + } + + return err; + } +} + +Future> findFiles(Directory directory, String name) => Isolate.run(() => directory.list(recursive: true, followLinks: true) + .handleError((_) {}) + .where((event) => event is File && path.basename(event.path) == name) + .map((event) => event as File) + .toList()); \ No newline at end of file diff --git a/common/lib/src/util/patcher.dart b/common/lib/src/util/patcher.dart deleted file mode 100644 index 07868c4..0000000 --- a/common/lib/src/util/patcher.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; - -final Uint8List _originalHeadless = Uint8List.fromList([ - 45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 115, 0, 101, 0, 115, 0, 115, 0, 105, 0, 111, 0, 110, 0, 32, 0, 45, 0, 105, 0, 110, 0, 118, 0, 105, 0, 116, 0, 101, 0, 102, 0, 114, 0, 111, 0, 109, 0, 32, 0, 45, 0, 112, 0, 97, 0, 114, 0, 116, 0, 121, 0, 95, 0, 106, 0, 111, 0, 105, 0, 110, 0, 105, 0, 110, 0, 102, 0, 111, 0, 95, 0, 116, 0, 111, 0, 107, 0, 101, 0, 110, 0, 32, 0, 45, 0, 114, 0, 101, 0, 112, 0, 108, 0, 97, 0, 121, 0 -]); - -final Uint8List _patchedHeadless = Uint8List.fromList([ - 45, 0, 108, 0, 111, 0, 103, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 112, 0, 108, 0, 97, 0, 115, 0, 104, 0, 32, 0, 45, 0, 110, 0, 111, 0, 115, 0, 111, 0, 117, 0, 110, 0, 100, 0, 32, 0, 45, 0, 110, 0, 117, 0, 108, 0, 108, 0, 114, 0, 104, 0, 105, 0, 32, 0, 45, 0, 117, 0, 115, 0, 101, 0, 111, 0, 108, 0, 100, 0, 105, 0, 116, 0, 101, 0, 109, 0, 99, 0, 97, 0, 114, 0, 100, 0, 115, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0, 32, 0 -]); - -// Not used right now -final Uint8List _originalMatchmaking = Uint8List.fromList([ - 63, 0, 69, 0, 110, 0, 99, 0, 114, 0, 121, 0, 112, 0, 116, 0, 105, 0, 111, 0, 110, 0, 84, 0, 111, 0, 107, 0, 101, 0, 110, 0, 61 -]); - -final Uint8List _patchedMatchmaking = Uint8List.fromList([ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -]); - -Future patchHeadless(File file) async => - await _patch(file, _originalHeadless, _patchedHeadless); - -Future patchMatchmaking(File file) async => - await _patch(file, _originalMatchmaking, _patchedMatchmaking); - -Future _patch(File file, Uint8List original, Uint8List patched) async { - try { - if(original.length != patched.length){ - throw Exception("Cannot mutate length of binary file"); - } - - final source = await file.readAsBytes(); - var readOffset = 0; - var patchOffset = -1; - var patchCount = 0; - while(readOffset < source.length){ - if(source[readOffset] == original[patchCount]){ - if(patchOffset == -1) { - patchOffset = readOffset; - } - - if(readOffset - patchOffset + 1 == original.length) { - break; - } - - patchCount++; - }else { - patchOffset = -1; - patchCount = 0; - } - - readOffset++; - } - - if(patchOffset == -1) { - return false; - } - - for(var i = 0; i < patched.length; i++) { - source[patchOffset + i] = patched[i]; - } - - await file.writeAsBytes(source, flush: true); - return true; - }catch(_){ - return false; - } -} \ No newline at end of file diff --git a/common/lib/src/util/path.dart b/common/lib/src/util/path.dart deleted file mode 100644 index ff1f90a..0000000 --- a/common/lib/src/util/path.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'dart:io'; - -Directory get installationDirectory => - File(Platform.resolvedExecutable).parent; - -Directory get dllsDirectory => Directory("${installationDirectory.path}\\dlls"); - -Directory get assetsDirectory { - final directory = Directory("${installationDirectory.path}\\data\\flutter_assets\\assets"); - if(directory.existsSync()) { - return directory; - } - - return installationDirectory; -} - -Directory get settingsDirectory => - Directory("${installationDirectory.path}\\settings"); - -Directory get tempDirectory => - Directory(Platform.environment["Temp"]!); - -Future delete(FileSystemEntity file) async { - try { - await file.delete(recursive: true); - return true; - }catch(_){ - return Future.delayed(const Duration(seconds: 5)).then((value) async { - try { - await file.delete(recursive: true); - return true; - }catch(_){ - return false; - } - }); - } -} \ No newline at end of file diff --git a/common/lib/src/util/process.dart b/common/lib/src/util/process.dart deleted file mode 100644 index ad881c2..0000000 --- a/common/lib/src/util/process.dart +++ /dev/null @@ -1,312 +0,0 @@ -// ignore_for_file: non_constant_identifier_names - -import 'dart:async'; -import 'dart:collection'; -import 'dart:ffi'; -import 'dart:io'; -import 'dart:isolate'; -import 'dart:math'; - -import 'package:ffi/ffi.dart'; -import 'package:reboot_common/common.dart'; -import 'package:win32/win32.dart'; - -final _ntdll = DynamicLibrary.open('ntdll.dll'); -final _kernel32 = DynamicLibrary.open('kernel32.dll'); -final _CreateRemoteThread = _kernel32.lookupFunction< - IntPtr Function( - IntPtr hProcess, - Pointer lpThreadAttributes, - IntPtr dwStackSize, - Pointer loadLibraryAddress, - Pointer lpParameter, - Uint32 dwCreationFlags, - Pointer lpThreadId), - int Function( - int hProcess, - Pointer lpThreadAttributes, - int dwStackSize, - Pointer loadLibraryAddress, - Pointer lpParameter, - int dwCreationFlags, - Pointer lpThreadId)>('CreateRemoteThread'); -const chunkSize = 1024; - -Future injectDll(int pid, File dll) async { - // Get the path to the file - final dllPath = dll.path; - - final process = OpenProcess( - 0x43A, - 0, - pid - ); - - final processAddress = GetProcAddress( - GetModuleHandle("KERNEL32".toNativeUtf16()), - "LoadLibraryA".toNativeUtf8() - ); - - if (processAddress == nullptr) { - throw Exception("Cannot get process address for pid $pid"); - } - - final dllAddress = VirtualAllocEx( - process, - nullptr, - dllPath.length + 1, - 0x3000, - 0x4 - ); - - final writeMemoryResult = WriteProcessMemory( - process, - dllAddress, - dllPath.toNativeUtf8(), - dllPath.length, - nullptr - ); - - if (writeMemoryResult != 1) { - throw Exception("Memory write failed"); - } - - final createThreadResult = _CreateRemoteThread( - process, - nullptr, - 0, - processAddress, - dllAddress, - 0, - nullptr - ); - - if (createThreadResult == -1) { - throw Exception("Thread creation failed"); - } - - final closeResult = CloseHandle(process); - if(closeResult != 1){ - throw Exception("Cannot close handle"); - } -} - -Future startElevatedProcess({required String executable, required String args, bool window = false}) async { - var shellInput = calloc(); - shellInput.ref.lpFile = executable.toNativeUtf16(); - shellInput.ref.lpParameters = args.toNativeUtf16(); - shellInput.ref.nShow = window ? SHOW_WINDOW_CMD.SW_SHOWNORMAL : SHOW_WINDOW_CMD.SW_HIDE; - shellInput.ref.fMask = EXECUTION_STATE.ES_AWAYMODE_REQUIRED; - shellInput.ref.lpVerb = "runas".toNativeUtf16(); - shellInput.ref.cbSize = sizeOf(); - return ShellExecuteEx(shellInput) == 1; -} - -Future startProcess({required File executable, List? args, bool useTempBatch = true, bool window = false, String? name, Map? environment}) async { - log("[PROCESS] Starting process on ${executable.path} with $args (useTempBatch: $useTempBatch, window: $window, name: $name, environment: $environment)"); - final argsOrEmpty = args ?? []; - final workingDirectory = _getWorkingDirectory(executable); - if(useTempBatch) { - final tempScriptDirectory = await tempDirectory.createTemp("reboot_launcher_process"); - final tempScriptFile = File("${tempScriptDirectory.path}\\process.bat"); - final command = window ? 'cmd.exe /k ""${executable.path}" ${argsOrEmpty.join(" ")}"' : '"${executable.path}" ${argsOrEmpty.join(" ")}'; - await tempScriptFile.writeAsString(command, flush: true); - final process = await Process.start( - tempScriptFile.path, - [], - workingDirectory: workingDirectory, - environment: environment, - mode: window ? ProcessStartMode.detachedWithStdio : ProcessStartMode.normal, - runInShell: window - ); - return _ExtendedProcess(process, true); - } - - final process = await Process.start( - executable.path, - args ?? [], - workingDirectory: workingDirectory, - mode: window ? ProcessStartMode.detachedWithStdio : ProcessStartMode.normal, - runInShell: window - ); - return _ExtendedProcess(process, true); -} - -String? _getWorkingDirectory(File executable) { - try { - log("[PROCESS] Calculating working directory for $executable"); - final workingDirectory = executable.parent.resolveSymbolicLinksSync(); - log("[PROCESS] Using working directory: $workingDirectory"); - return workingDirectory; - }catch(error) { - log("[PROCESS] Cannot infer working directory: $error"); - return null; - } -} - -final _NtResumeProcess = _ntdll.lookupFunction('NtResumeProcess'); - -final _NtSuspendProcess = _ntdll.lookupFunction('NtSuspendProcess'); - -bool suspend(int pid) { - final processHandle = OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_SUSPEND_RESUME, FALSE, pid); - try { - return _NtSuspendProcess(processHandle) == 0; - } finally { - CloseHandle(processHandle); - } -} - -bool resume(int pid) { - final processHandle = OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_SUSPEND_RESUME, FALSE, pid); - try { - return _NtResumeProcess(processHandle) == 0; - } finally { - CloseHandle(processHandle); - } -} - -List createRebootArgs(String username, String password, bool host, GameServerType hostType, bool logging, String additionalArgs) { - log("[PROCESS] Generating reboot args"); - if(password.isEmpty) { - username = '${_parseUsername(username, host)}@projectreboot.dev'; - } - - password = password.isNotEmpty ? password : "Rebooted"; - final args = LinkedHashMap( - equals: (a, b) => a.toUpperCase() == b.toUpperCase(), - hashCode: (a) => a.toUpperCase().hashCode - ); - args.addAll({ - "-epicapp": "Fortnite", - "-epicenv": "Prod", - "-epiclocale": "en-us", - "-epicportal": "", - "-skippatchcheck": "", - "-nobe": "", - "-fromfl": "eac", - "-fltoken": "3db3ba5dcbd2e16703f3978d", - "-caldera": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50X2lkIjoiYmU5ZGE1YzJmYmVhNDQwN2IyZjQwZWJhYWQ4NTlhZDQiLCJnZW5lcmF0ZWQiOjE2Mzg3MTcyNzgsImNhbGRlcmFHdWlkIjoiMzgxMGI4NjMtMmE2NS00NDU3LTliNTgtNGRhYjNiNDgyYTg2IiwiYWNQcm92aWRlciI6IkVhc3lBbnRpQ2hlYXQiLCJub3RlcyI6IiIsImZhbGxiYWNrIjpmYWxzZX0.VAWQB67RTxhiWOxx7DBjnzDnXyyEnX7OljJm-j2d88G_WgwQ9wrE6lwMEHZHjBd1ISJdUO1UVUqkfLdU5nofBQ", - "-AUTH_LOGIN": username, - "-AUTH_PASSWORD": password.isNotEmpty ? password : "Rebooted", - "-AUTH_TYPE": "epic" - }); - - if(logging) { - args["-log"] = ""; - } - - if(host) { - args["-nosplash"] = ""; - args["-nosound"] = ""; - if(hostType == GameServerType.headless){ - args["-nullrhi"] = ""; - } - } - - log("[PROCESS] Default args: $args"); - log("[PROCESS] Adding custom args: $additionalArgs"); - for(final additionalArg in additionalArgs.split(" ")) { - log("[PROCESS] Processing custom arg: $additionalArg"); - final separatorIndex = additionalArg.indexOf("="); - final argName = separatorIndex == -1 ? additionalArg : additionalArg.substring(0, separatorIndex); - log("[PROCESS] Custom arg key: $argName"); - final argValue = separatorIndex == -1 || separatorIndex + 1 >= additionalArg.length ? "" : additionalArg.substring(separatorIndex + 1); - log("[PROCESS] Custom arg value: $argValue"); - args[argName] = argValue; - log("[PROCESS] Updated args: $args"); - } - - log("[PROCESS] Final args result: $args"); - return args.entries - .map((entry) => entry.value.isEmpty ? entry.key : "${entry.key}=${entry.value}") - .toList(); -} - -void handleGameOutput({ - required String line, - required bool host, - required void Function() onDisplayAttached, - required void Function() onLoggedIn, - required void Function() onMatchEnd, - required void Function() onShutdown, - required void Function() onTokenError, - required void Function() onBuildCorrupted, -}) { - if (line.contains(kShutdownLine)) { - log("[FORTNITE_OUTPUT_HANDLER] Detected shutdown: $line"); - onShutdown(); - }else if(kCorruptedBuildErrors.any((element) => line.contains(element))){ - log("[FORTNITE_OUTPUT_HANDLER] Detected corrupt build: $line"); - onBuildCorrupted(); - }else if(kCannotConnectErrors.any((element) => line.contains(element))){ - log("[FORTNITE_OUTPUT_HANDLER] Detected cannot connect error: $line"); - onTokenError(); - }else if(kLoggedInLines.every((entry) => line.contains(entry))) { - log("[FORTNITE_OUTPUT_HANDLER] Detected logged in: $line"); - onLoggedIn(); - }else if(line.contains(kGameFinishedLine) && host) { - log("[FORTNITE_OUTPUT_HANDLER] Detected match end: $line"); - onMatchEnd(); - }else if(line.contains(kDisplayLine) && line.contains(kDisplayInitializedLine) && host) { - log("[FORTNITE_OUTPUT_HANDLER] Detected display attach: $line"); - onDisplayAttached(); - } -} - -String _parseUsername(String username, bool host) { - if (username.isEmpty) { - return kDefaultPlayerName; - } - - username = username.replaceAll(RegExp("[^A-Za-z0-9]"), "").trim(); - if(username.isEmpty){ - return kDefaultPlayerName; - } - - return username; -} - -final class _ExtendedProcess implements Process { - final Process _delegate; - final Stream>? _stdout; - final Stream>? _stderr; - _ExtendedProcess(Process delegate, bool attached) : - _delegate = delegate, - _stdout = attached ? delegate.stdout.asBroadcastStream() : null, - _stderr = attached ? delegate.stderr.asBroadcastStream() : null; - - @override - Future get exitCode => _delegate.exitCode; - - @override - bool kill([ProcessSignal signal = ProcessSignal.sigterm]) => _delegate.kill(signal); - - @override - int get pid => _delegate.pid; - - @override - IOSink get stdin => _delegate.stdin; - - @override - Stream> get stdout { - final out = _stdout; - if(out == null) { - throw StateError("Output is not attached"); - } - - return out; - } - - @override - Stream> get stderr { - final err = _stderr; - if(err == null) { - throw StateError("Output is not attached"); - } - - return err; - } -} \ No newline at end of file diff --git a/gui/assets/backend/CloudStorage/DefaultEngine.ini b/gui/assets/backend/CloudStorage/DefaultEngine.ini index 895948c..a479bc0 100644 --- a/gui/assets/backend/CloudStorage/DefaultEngine.ini +++ b/gui/assets/backend/CloudStorage/DefaultEngine.ini @@ -2,13 +2,13 @@ [OnlineSubsystemMcp.Xmpp] bUseSSL=false ServerAddr="ws://127.0.0.1" -ServerPort=80 +ServerPort=8080 # Do not remove/change, this redirects epicgames xmpp to lawinserver xmpp [OnlineSubsystemMcp.Xmpp Prod] bUseSSL=false ServerAddr="ws://127.0.0.1" -ServerPort=80 +ServerPort=8080 # Forces fortnite to use the v1 party system to support lawinserver xmpp [OnlineSubsystemMcp] diff --git a/gui/assets/backend/lawinserver.exe b/gui/assets/backend/lawinserver.exe index 22f7377..169a823 100644 Binary files a/gui/assets/backend/lawinserver.exe and b/gui/assets/backend/lawinserver.exe differ diff --git a/gui/assets/backend/profiles/athena.json b/gui/assets/backend/profiles/athena.json index ba24a29..97424d8 100644 --- a/gui/assets/backend/profiles/athena.json +++ b/gui/assets/backend/profiles/athena.json @@ -2,7 +2,7 @@ "_id": "LawinServer", "created": "0001-01-01T00:00:00.000Z", "updated": "0001-01-01T00:00:00.000Z", - "rvn": 10, + "rvn": 23, "wipeNumber": 1, "accountId": "LawinServer", "profileId": "athena", @@ -131951,1117 +131951,759 @@ }, "quantity": 1 }, - "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule": { - "templateId": "ChallengeBundleSchedule:Season3_Challenge_Schedule", + "99e2e58c-6260-4757-a10e-dcc7b60ec351": { + "templateId": "Quest:AthenaDailyQuest_InteractAmmoCrate", "attributes": { - "unlock_epoch": "2024-05-23T20:05:30.124Z", + "creation_time": "2024-05-31T19:09:53.495Z", + "level": -1, + "item_seen": false, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-05-31T19:09:53.495Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_athena_daily_loot_ammobox_v2": 0 + }, + "quantity": 1 + }, + "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule": { + "templateId": "ChallengeBundleSchedule:Season4_Challenge_Schedule", + "attributes": { + "unlock_epoch": "2024-06-24T20:17:00.089Z", "max_level_bonus": 0, "level": 1, "item_seen": true, "xp": 0, "favorite": false, "granted_bundles": [ - "S3-ChallengeBundle:S3_Week1_QuestBundle", - "S3-ChallengeBundle:S3_Week2_QuestBundle", - "S3-ChallengeBundle:S3_Week3_QuestBundle", - "S3-ChallengeBundle:S3_Week4_QuestBundle", - "S3-ChallengeBundle:S3_Week5_QuestBundle", - "S3-ChallengeBundle:S3_Week6_QuestBundle", - "S3-ChallengeBundle:S3_Week7_QuestBundle", - "S3-ChallengeBundle:S3_Week8_QuestBundle", - "S3-ChallengeBundle:S3_Week9_QuestBundle", - "S3-ChallengeBundle:S3_Week10_QuestBundle" + "S4-ChallengeBundle:QuestBundle_S4_Cumulative", + "S4-ChallengeBundle:QuestBundle_S4_ProgressiveA", + "S4-ChallengeBundle:QuestBundle_S4_Week_001", + "S4-ChallengeBundle:QuestBundle_S4_Week_002", + "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "S4-ChallengeBundle:QuestBundle_S4_Week_006", + "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "S4-ChallengeBundle:QuestBundle_S4_Week_010" ] }, "quantity": 1 }, - "S3-ChallengeBundleSchedule:Season3_Tier_100_Schedule": { - "templateId": "ChallengeBundleSchedule:Season3_Tier_100_Schedule", + "S4-ChallengeBundleSchedule:Season4_ProgressiveB_Schedule": { + "templateId": "ChallengeBundleSchedule:Season4_ProgressiveB_Schedule", "attributes": { - "unlock_epoch": "2024-05-23T20:05:30.124Z", + "unlock_epoch": "2024-06-24T20:17:00.089Z", "max_level_bonus": 0, "level": 1, "item_seen": true, "xp": 0, "favorite": false, "granted_bundles": [ - "S3-ChallengeBundle:S3_Tier_100_QuestBundle" + "S4-ChallengeBundle:QuestBundle_S4_ProgressiveB" ] }, "quantity": 1 }, - "S3-ChallengeBundleSchedule:Season3_Tier_2_Schedule": { - "templateId": "ChallengeBundleSchedule:Season3_Tier_2_Schedule", + "S4-ChallengeBundleSchedule:Season4_StarterChallenge_Schedule": { + "templateId": "ChallengeBundleSchedule:Season4_StarterChallenge_Schedule", "attributes": { - "unlock_epoch": "2024-05-23T20:05:30.124Z", + "unlock_epoch": "2024-06-24T20:17:00.089Z", "max_level_bonus": 0, "level": 1, "item_seen": true, "xp": 0, "favorite": false, "granted_bundles": [ - "S3-ChallengeBundle:S3_Tier_2_QuestBundle" + "S4-ChallengeBundle:QuestBundle_S4_Starter" ] }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week10_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week10_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Cumulative": { + "templateId": "ChallengeBundle:QuestBundle_S4_Cumulative", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Interact_Chests_Location_FatalFields", - "S3-Quest:Quest_BR_Damage_Headshot", - "S3-Quest:Quest_BR_Interact_Chests_Locations_Different", - "S3-Quest:Quest_BR_Skydive_Rings", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_04", - "S3-Quest:Quest_BR_Eliminate", - "S3-Quest:Quest_BR_Eliminate_Location_PleasantPark" + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_01", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_02", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_03", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_04", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_05", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_06", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_07" ], "item_seen": true, "max_allowed_bundle_level": 0, "num_granted_bundle_quests": 7, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week1_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week1_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_ProgressiveA": { + "templateId": "ChallengeBundle:QuestBundle_S4_ProgressiveA", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Damage_Pistol", - "S3-Quest:Quest_BR_Interact_Chests_Location_PleasantPark", - "S3-Quest:Quest_BR_Revive", - "S3-Quest:Quest_BR_Visit_ScavengerHunt_LlamaFoxCrab", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_01", - "S3-Quest:Quest_BR_Eliminate_Weapon_SniperRifle", - "S3-Quest:Quest_BR_Eliminate_Location_FatalFields" + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_01", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_02", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_03", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_04", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_05" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 5, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week2_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week2_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_001": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_001", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Use_Launchpad", - "S3-Quest:Quest_BR_Damage_AssaultRifle", - "S3-Quest:Quest_BR_Interact_Chests_Location_WailingWoods", - "S3-Quest:Quest_BR_Dance_ScavengerHunt_Forbidden", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_01", - "S3-Quest:Quest_BR_Eliminate_Weapon_SMG", - "S3-Quest:Quest_BR_Eliminate_Location_GreasyGrove" + "S4-Quest:Quest_BR_Damage_SniperRifle", + "S4-Quest:Quest_BR_Interact_Chests_Location_HauntedHills", + "S4-Quest:Quest_BR_Use_PortaFort", + "S4-Quest:Quest_BR_Interact_FORTNITE", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_01", + "S4-Quest:Quest_BR_Eliminate_Weapon_Pistol", + "S4-Quest:Quest_BR_Eliminate_Location_FlushFactory", + "S4-Quest:Quest_BR_S4W1_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week3_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week3_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_002": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_002", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Collect_BuildingResources", - "S3-Quest:Quest_BR_Damage_SuppressedWeapon", - "S3-Quest:Quest_BR_Interact_Chests_Location_JunkJunction", - "S3-Quest:Quest_BR_Land_Bulleyes_Different", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_02", - "S3-Quest:Quest_BR_Eliminate_Weapon_Crossbow", - "S3-Quest:Quest_BR_Eliminate_Location_SaltySprings" + "S4-Quest:Quest_BR_Interact_Chests_Location_GreasyGrove", + "S4-Quest:Quest_BR_Interact_GravityStones", + "S4-Quest:Quest_BR_Damage_SuppressedWeapon", + "S4-Quest:Quest_BR_Dance_ScavengerHunt_Cameras", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_01", + "S4-Quest:Quest_BR_Eliminate_ExplosiveWeapon", + "S4-Quest:Quest_BR_Eliminate_Location_TomatoTown", + "S4-Quest:Quest_BR_S4W2_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week4_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week4_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_003": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_003", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Damage_SniperRifle", - "S3-Quest:Quest_BR_Interact_Chests_Location_FlushFactory", - "S3-Quest:Quest_BR_Interact_SupplyDrops", - "S3-Quest:Quest_BR_Visit_IceCreamTrucks_Different", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_02", - "S3-Quest:Quest_BR_Eliminate_Trap", - "S3-Quest:Quest_BR_Eliminate_Location_TomatoTown" + "S4-Quest:Quest_BR_Revive", + "S4-Quest:Quest_BR_Damage_Pistol", + "S4-Quest:Quest_BR_Interact_Chests_Location_LonelyLodge", + "S4-Quest:Quest_BR_Interact_RubberDuckies", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_02", + "S4-Quest:Quest_BR_Eliminate_Weapon_SniperRifle", + "S4-Quest:Quest_BR_Eliminate_Location_TiltedTowers", + "S4-Quest:Quest_BR_S4W3_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week5_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week5_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_004": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_004", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Use_Bush", - "S3-Quest:Quest_BR_Interact_Chests_Location_MoistyMire", - "S3-Quest:Quest_BR_Damage_Pickaxe", - "S3-Quest:Quest_BR_Visit_GasStations_SingleMatch", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_03", - "S3-Quest:Quest_BR_Eliminate_Weapon_Pistol", - "S3-Quest:Quest_BR_Eliminate_Location_TiltedTowers" + "S4-Quest:Quest_BR_Damage_AssaultRifle", + "S4-Quest:Quest_BR_Interact_Chests_Location_WailingWoods", + "S4-Quest:Quest_BR_Interact_AmmoBoxes_SingleMatch", + "S4-Quest:Quest_BR_Visit_ScavengerHunt_StormCircles", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_02", + "S4-Quest:Quest_BR_Eliminate_Trap", + "S4-Quest:Quest_BR_Eliminate_Location_SnobbyShores", + "S4-Quest:Quest_BR_S4W4_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week6_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week6_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_005": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_005", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Damage_SMG", - "S3-Quest:Quest_BR_Interact_Chests_Location_AnarchyAcres", - "S3-Quest:Quest_BR_Use_CozyCampfire", - "S3-Quest:Quest_BR_Visit_MountainPeaks", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_03", - "S3-Quest:Quest_BR_Eliminate_ExplosiveWeapon", - "S3-Quest:Quest_BR_Eliminate_Location_RetailRow" + "S4-Quest:Quest_BR_Damage_SMG", + "S4-Quest:Quest_BR_Interact_Chests_Location_DustyDivot", + "S4-Quest:Quest_BR_Use_VendingMachine", + "S4-Quest:Quest_BR_Dance_ScavengerHunt_Platforms", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_03", + "S4-Quest:Quest_BR_Eliminate_Weapon_MinigunLMG", + "S4-Quest:Quest_BR_Eliminate_Location_LuckyLanding", + "S4-Quest:Quest_BR_S4W5_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week7_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week7_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_006": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_006", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Interact_Chests_Location_LonelyLodge", - "S3-Quest:Quest_BR_Damage_Shotgun", - "S3-Quest:Quest_BR_Interact_ChestAmmoBoxSupplyDrop_SingleMatch", - "S3-Quest:Quest_BR_Interact_GniceGnomes", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_04", - "S3-Quest:Quest_BR_Eliminate_SuppressedWeapon", - "S3-Quest:Quest_BR_Eliminate_Location_ShiftyShafts" + "S4-Quest:Quest_BR_Interact_SupplyDrops", + "S4-Quest:Quest_BR_Damage_Shotgun", + "S4-Quest:Quest_BR_Interact_Chests_Location_LootLake", + "S4-Quest:Quest_BR_Spray_SpecificTargets", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_03", + "S4-Quest:Quest_BR_Eliminate_Weapon_SMG", + "S4-Quest:Quest_BR_Eliminate_Location_RetailRow", + "S4-Quest:Quest_BR_S4W6_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week8_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week8_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_007": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_007", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Use_VendingMachine", - "S3-Quest:Quest_BR_Damage_ExplosiveWeapon", - "S3-Quest:Quest_BR_Interact_Chests_Location_SnobbyShores", - "S3-Quest:Quest_BR_Dance_ScavengerHunt_DanceFloors", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_05", - "S3-Quest:Quest_BR_Eliminate_Weapon_AssaultRifle", - "S3-Quest:Quest_BR_Eliminate_Location_DustyDepot" + "S4-Quest:Quest_BR_Damage_Pickaxe", + "S4-Quest:Quest_BR_Interact_Chests_Location_RiskyReels", + "S4-Quest:Quest_BR_Interact_ForagedItems", + "S4-Quest:Quest_BR_Score_Goals", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_04", + "S4-Quest:Quest_BR_Eliminate_Weapon_AssaultRifle", + "S4-Quest:Quest_BR_Eliminate_Location_ShiftyShafts", + "S4-Quest:Quest_BR_S4W7_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Week9_QuestBundle": { - "templateId": "ChallengeBundle:S3_Week9_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_008": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_008", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Damage_Enemy_Buildings", - "S3-Quest:Quest_BR_Interact_Chests_Location_HauntedHills", - "S3-Quest:Quest_BR_Build_Structures", - "S3-Quest:Quest_BR_Visit_TacoShops_SingleMatch", - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_05", - "S3-Quest:Quest_BR_Eliminate_Weapon_Shotgun", - "S3-Quest:Quest_BR_Eliminate_Location_LuckyLanding" + "S4-Quest:Quest_BR_Damage_Headshot", + "S4-Quest:Quest_BR_Interact_Chests_Location_SaltySprings", + "S4-Quest:Quest_BR_Interact_Chests_SingleMatch", + "S4-Quest:Quest_BR_Interact_GniceGnomes", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_04", + "S4-Quest:Quest_BR_Eliminate_SuppressedWeapon", + "S4-Quest:Quest_BR_Eliminate_Location_PleasantPark", + "S4-Quest:Quest_BR_S4W8_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Challenge_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Tier_100_QuestBundle": { - "templateId": "ChallengeBundle:S3_Tier_100_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_009": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_009", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Interact_Chests_SingleMatch", - "S3-Quest:Quest_BR_Play_Min1Elimination", - "S3-Quest:Quest_BR_Damage_SingleMatch", - "S3-Quest:Quest_BR_Eliminate_Weapon_Pickaxe", - "S3-Quest:Quest_BR_Eliminate_Singel_Match_Elemeinations", - "S3-Quest:Quest_BR_Place_Top10_Solo", - "S3-Quest:Quest_BR_Place_Top3_Squad" + "S4-Quest:Quest_BR_Damage_ExplosiveWeapon", + "S4-Quest:Quest_BR_Interact_Chests_Location_MoistyMire", + "S4-Quest:Quest_BR_Use_ShoppingCart", + "S4-Quest:Quest_BR_Visit_NamedLocations_SingleMatch", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_05", + "S4-Quest:Quest_BR_Eliminate_Weapon_Shotgun", + "S4-Quest:Quest_BR_Eliminate_Location_AnarchyAcres", + "S4-Quest:Quest_BR_S4W9_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Tier_100_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-ChallengeBundle:S3_Tier_2_QuestBundle": { - "templateId": "ChallengeBundle:S3_Tier_2_QuestBundle", + "S4-ChallengeBundle:QuestBundle_S4_Week_010": { + "templateId": "ChallengeBundle:QuestBundle_S4_Week_010", "attributes": { "has_unlock_by_completion": false, "num_quests_completed": 0, "level": 0, "grantedquestinstanceids": [ - "S3-Quest:Quest_BR_Outlive", - "S3-Quest:Quest_BR_Play_Min1Friend", - "S3-Quest:Quest_BR_Damage", - "S3-Quest:Quest_BR_Land_Locations_Different", - "S3-Quest:Quest_BR_Play", - "S3-Quest:Quest_BR_LevelUp_SeasonLevel_25", - "S3-Quest:Quest_BR_Place_Win" + "S4-Quest:Quest_BR_Interact_Chests_Location_JunkJunction", + "S4-Quest:Quest_BR_Damage_Enemy_Buildings", + "S4-Quest:Quest_BR_Interact_ChestAmmoBoxSupplyDrop_SingleMatch", + "S4-Quest:Quest_BR_Skydive_Rings", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_05", + "S4-Quest:Quest_BR_Eliminate", + "S4-Quest:Quest_BR_Eliminate_Location_FatalFields", + "S4-Quest:Quest_BR_S4W10_Cumulative_CompleteAll" ], "item_seen": true, "max_allowed_bundle_level": 0, - "num_granted_bundle_quests": 7, + "num_granted_bundle_quests": 8, "max_level_bonus": 0, - "challenge_bundle_schedule_id": "S3-ChallengeBundleSchedule:Season3_Tier_2_Schedule", + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_Challenge_Schedule", "num_progress_quests_completed": 0, "xp": 0, "favorite": false }, "quantity": 1 }, - "S3-Quest:Quest_BR_Damage_Headshot": { - "templateId": "Quest:Quest_BR_Damage_Headshot", + "S4-ChallengeBundle:QuestBundle_S4_ProgressiveB": { + "templateId": "ChallengeBundle:QuestBundle_S4_ProgressiveB", "attributes": { - "creation_time": "2024-05-23T20:05:30.124Z", + "has_unlock_by_completion": false, + "num_quests_completed": 0, + "level": 0, + "grantedquestinstanceids": [ + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_01", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_02", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_03", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_04", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_05" + ], + "item_seen": true, + "max_allowed_bundle_level": 0, + "num_granted_bundle_quests": 5, + "max_level_bonus": 0, + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_ProgressiveB_Schedule", + "num_progress_quests_completed": 0, + "xp": 0, + "favorite": false + }, + "quantity": 1 + }, + "S4-ChallengeBundle:QuestBundle_S4_Starter": { + "templateId": "ChallengeBundle:QuestBundle_S4_Starter", + "attributes": { + "has_unlock_by_completion": false, + "num_quests_completed": 0, + "level": 0, + "grantedquestinstanceids": [ + "S4-Quest:Quest_BR_Outlive", + "S4-Quest:Quest_BR_Play_Min1Friend", + "S4-Quest:Quest_BR_Damage", + "S4-Quest:Quest_BR_Land_Locations_Different", + "S4-Quest:Quest_BR_Play", + "S4-Quest:Quest_BR_Play_Min1Elimination", + "S4-Quest:Quest_BR_Place_Win" + ], + "item_seen": true, + "max_allowed_bundle_level": 0, + "num_granted_bundle_quests": 7, + "max_level_bonus": 0, + "challenge_bundle_schedule_id": "S4-ChallengeBundleSchedule:Season4_StarterChallenge_Schedule", + "num_progress_quests_completed": 0, + "xp": 0, + "favorite": false + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_01": { + "templateId": "Quest:Quest_BR_S4_Cumulative_CollectTokens_01", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week10_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Cumulative", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.124Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_damage_athena_player_head_shots": 0 + "completion_battlepass_cumulative_token1": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate": { - "templateId": "Quest:Quest_BR_Eliminate", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_02": { + "templateId": "Quest:Quest_BR_S4_Cumulative_CollectTokens_02", "attributes": { - "creation_time": "2024-05-23T20:05:30.124Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week10_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Cumulative", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.124Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_players": 0 + "completion_battlepass_cumulative_token2": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Location_PleasantPark": { - "templateId": "Quest:Quest_BR_Eliminate_Location_PleasantPark", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_03": { + "templateId": "Quest:Quest_BR_S4_Cumulative_CollectTokens_03", "attributes": { - "creation_time": "2024-05-23T20:05:30.124Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week10_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Cumulative", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.124Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_pleasantpark": 0 + "completion_battlepass_cumulative_token3": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_Chests_Locations_Different": { - "templateId": "Quest:Quest_BR_Interact_Chests_Locations_Different", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_04": { + "templateId": "Quest:Quest_BR_S4_Cumulative_CollectTokens_04", "attributes": { - "creation_time": "2024-05-23T20:05:30.124Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week10_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Cumulative", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.124Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_chest_athena_location_different_anarchyacres": 0, - "completion_battlepass_interact_chest_athena_location_different_dustydepot": 0, - "completion_battlepass_interact_chest_athena_location_different_fatalfields": 0, - "completion_battlepass_interact_chest_athena_location_different_flushfactory": 0, - "completion_battlepass_interact_chest_athena_location_different_greasygrove": 0, - "completion_battlepass_interact_chest_athena_location_different_hauntedhills": 0, - "completion_battlepass_interact_chest_athena_location_different_junkjunction": 0, - "completion_battlepass_interact_chest_athena_location_different_luckylanding": 0, - "completion_battlepass_interact_chest_athena_location_different_lonelylodge": 0, - "completion_battlepass_interact_chest_athena_location_different_lootlake": 0, - "completion_battlepass_interact_chest_athena_location_different_moistymire": 0, - "completion_battlepass_interact_chest_athena_location_different_pleasantpark": 0, - "completion_battlepass_interact_chest_athena_location_different_retailrow": 0, - "completion_battlepass_interact_chest_athena_location_different_shiftyshafts": 0, - "completion_battlepass_interact_chest_athena_location_different_saltysprings": 0, - "completion_battlepass_interact_chest_athena_location_different_snobbyshores": 0, - "completion_battlepass_interact_chest_athena_location_different_tiltedtowers": 0, - "completion_battlepass_interact_chest_athena_location_different_tomatotown": 0, - "completion_battlepass_interact_chest_athena_location_different_wailingwoods": 0 + "completion_battlepass_cumulative_token4": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_Chests_Location_FatalFields": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_FatalFields", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_05": { + "templateId": "Quest:Quest_BR_S4_Cumulative_CollectTokens_05", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week10_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Cumulative", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_treasurechest_fatalfields": 0 + "completion_battlepass_cumulative_token5": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_04": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_04", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_06": { + "templateId": "Quest:Quest_BR_S4_Cumulative_CollectTokens_06", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week10_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Cumulative", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_hidden_star_08": 0 + "completion_battlepass_cumulative_token6": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Skydive_Rings": { - "templateId": "Quest:Quest_BR_Skydive_Rings", + "S4-Quest:Quest_BR_S4_Cumulative_CollectTokens_07": { + "templateId": "Quest:Quest_BR_S4_Cumulative_CollectTokens_07", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week10_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Cumulative", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_skydive_athena_rings": 0 + "completion_battlepass_cumulative_token7": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Damage_Pistol": { - "templateId": "Quest:Quest_BR_Damage_Pistol", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_01": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_01", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week1_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveA", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_damage_athena_player_pistol": 0 + "completion_athena_season_levelup_progressive_a_01": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Location_FatalFields": { - "templateId": "Quest:Quest_BR_Eliminate_Location_FatalFields", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_02": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_02", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week1_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveA", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_fatalfields": 0 + "completion_athena_season_levelup_progressive_a_02": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Weapon_SniperRifle": { - "templateId": "Quest:Quest_BR_Eliminate_Weapon_SniperRifle", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_03": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_03", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week1_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveA", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_sniper": 0 + "completion_athena_season_levelup_progressive_a_03": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_Chests_Location_PleasantPark": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_PleasantPark", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_04": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_04", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week1_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveA", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_treasurechest_pleasantpark": 0 + "completion_athena_season_levelup_progressive_a_04": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_01": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_01", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_05": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveA_05", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week1_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveA", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_hidden_star_01": 0 + "completion_athena_season_levelup_progressive_a_05": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Revive": { - "templateId": "Quest:Quest_BR_Revive", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week1_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_athena_revive_player": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Visit_ScavengerHunt_LlamaFoxCrab": { - "templateId": "Quest:Quest_BR_Visit_ScavengerHunt_LlamaFoxCrab", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week1_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_visit_location_crab": 0, - "completion_battlepass_visit_location_fox": 0, - "completion_battlepass_visit_location_llama": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Damage_AssaultRifle": { - "templateId": "Quest:Quest_BR_Damage_AssaultRifle", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_damage_athena_player_asssult": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Dance_ScavengerHunt_Forbidden": { - "templateId": "Quest:Quest_BR_Dance_ScavengerHunt_Forbidden", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_dance_athena_location_forbidden_01": 0, - "completion_battlepass_dance_athena_location_forbidden_02": 0, - "completion_battlepass_dance_athena_location_forbidden_03": 0, - "completion_battlepass_dance_athena_location_forbidden_04": 0, - "completion_battlepass_dance_athena_location_forbidden_05": 0, - "completion_battlepass_dance_athena_location_forbidden_06": 0, - "completion_battlepass_dance_athena_location_forbidden_07": 0, - "completion_battlepass_dance_athena_location_forbidden_08": 0, - "completion_battlepass_dance_athena_location_forbidden_09": 0, - "completion_battlepass_dance_athena_location_forbidden_10": 0, - "completion_battlepass_dance_athena_location_forbidden_11": 0, - "completion_battlepass_dance_athena_location_forbidden_12": 0, - "completion_battlepass_dance_athena_location_forbidden_13": 0, - "completion_battlepass_dance_athena_location_forbidden_14": 0, - "completion_battlepass_dance_athena_location_forbidden_15": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Location_GreasyGrove": { - "templateId": "Quest:Quest_BR_Eliminate_Location_GreasyGrove", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_greasygrove": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Weapon_SMG": { - "templateId": "Quest:Quest_BR_Eliminate_Weapon_SMG", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_smg": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_Chests_Location_WailingWoods": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_WailingWoods", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_treasurechest_walingwoods": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_01": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_01", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_hidden_star_02": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Use_Launchpad": { - "templateId": "Quest:Quest_BR_Use_Launchpad", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_jumppad": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Collect_BuildingResources": { - "templateId": "Quest:Quest_BR_Collect_BuildingResources", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week3_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_collect_building_resources": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Damage_SuppressedWeapon": { - "templateId": "Quest:Quest_BR_Damage_SuppressedWeapon", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week3_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_damage_athena_player_suppressed_weapon": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Location_SaltySprings": { - "templateId": "Quest:Quest_BR_Eliminate_Location_SaltySprings", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week3_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_saltysprings": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Weapon_Crossbow": { - "templateId": "Quest:Quest_BR_Eliminate_Weapon_Crossbow", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week3_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_crossbow": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_Chests_Location_JunkJunction": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_JunkJunction", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week3_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_treasurechest_junkjunction": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_02": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_02", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week3_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_hidden_star_03": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Land_Bulleyes_Different": { - "templateId": "Quest:Quest_BR_Land_Bulleyes_Different", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week3_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_athena_land_location_bullseye_01": 0, - "completion_battlepass_athena_land_location_bullseye_02": 0, - "completion_battlepass_athena_land_location_bullseye_03": 0, - "completion_battlepass_athena_land_location_bullseye_04": 0, - "completion_battlepass_athena_land_location_bullseye_05": 0, - "completion_battlepass_athena_land_location_bullseye_06": 0, - "completion_battlepass_athena_land_location_bullseye_07": 0, - "completion_battlepass_athena_land_location_bullseye_08": 0, - "completion_battlepass_athena_land_location_bullseye_09": 0, - "completion_battlepass_athena_land_location_bullseye_10": 0, - "completion_battlepass_athena_land_location_bullseye_11": 0, - "completion_battlepass_athena_land_location_bullseye_12": 0, - "completion_battlepass_athena_land_location_bullseye_13": 0, - "completion_battlepass_athena_land_location_bullseye_14": 0, - "completion_battlepass_athena_land_location_bullseye_15": 0, - "completion_battlepass_athena_land_location_bullseye_16": 0, - "completion_battlepass_athena_land_location_bullseye_17": 0, - "completion_battlepass_athena_land_location_bullseye_18": 0, - "completion_battlepass_athena_land_location_bullseye_19": 0, - "completion_battlepass_athena_land_location_bullseye_20": 0, - "completion_battlepass_athena_land_location_bullseye_21": 0, - "completion_battlepass_athena_land_location_bullseye_22": 0, - "completion_battlepass_athena_land_location_bullseye_23": 0, - "completion_battlepass_athena_land_location_bullseye_24": 0, - "completion_battlepass_athena_land_location_bullseye_25": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Damage_SniperRifle": { + "S4-Quest:Quest_BR_Damage_SniperRifle": { "templateId": "Quest:Quest_BR_Damage_SniperRifle", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week4_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133071,227 +132713,45 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Location_TomatoTown": { - "templateId": "Quest:Quest_BR_Eliminate_Location_TomatoTown", + "S4-Quest:Quest_BR_Eliminate_Location_FlushFactory": { + "templateId": "Quest:Quest_BR_Eliminate_Location_FlushFactory", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week4_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_tomatotown": 0 + "completion_battlepass_killingblow_athena_player_flushfactory": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Trap": { - "templateId": "Quest:Quest_BR_Eliminate_Trap", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week4_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_with_trap": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_Chests_Location_FlushFactory": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_FlushFactory", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week4_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_treasurechest_flushfactory": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_02": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_02", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week4_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_hidden_star_04": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_SupplyDrops": { - "templateId": "Quest:Quest_BR_Interact_SupplyDrops", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week4_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_supply_drop": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Visit_IceCreamTrucks_Different": { - "templateId": "Quest:Quest_BR_Visit_IceCreamTrucks_Different", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week4_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_visit_athena_location_icream_01": 0, - "completion_battlepass_visit_athena_location_icream_02": 0, - "completion_battlepass_visit_athena_location_icream_03": 0, - "completion_battlepass_visit_athena_location_icream_04": 0, - "completion_battlepass_visit_athena_location_icream_05": 0, - "completion_battlepass_visit_athena_location_icream_06": 0, - "completion_battlepass_visit_athena_location_icream_07": 0, - "completion_battlepass_visit_athena_location_icream_08": 0, - "completion_battlepass_visit_athena_location_icream_09": 0, - "completion_battlepass_visit_athena_location_icream_10": 0, - "completion_battlepass_visit_athena_location_icream_11": 0, - "completion_battlepass_visit_athena_location_icream_12": 0, - "completion_battlepass_visit_athena_location_icream_13": 0, - "completion_battlepass_visit_athena_location_icream_14": 0, - "completion_battlepass_visit_athena_location_icream_15": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Damage_Pickaxe": { - "templateId": "Quest:Quest_BR_Damage_Pickaxe", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week5_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_damage_athena_player_pickaxe": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Location_TiltedTowers": { - "templateId": "Quest:Quest_BR_Eliminate_Location_TiltedTowers", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week5_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_tiltedtowers": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Weapon_Pistol": { + "S4-Quest:Quest_BR_Eliminate_Weapon_Pistol": { "templateId": "Quest:Quest_BR_Eliminate_Weapon_Pistol", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week5_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133301,150 +132761,224 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_Chests_Location_MoistyMire": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_MoistyMire", + "S4-Quest:Quest_BR_Interact_Chests_Location_HauntedHills": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_HauntedHills", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week5_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_treasurechest_moistymire": 0 + "completion_battlepass_interact_athena_treasurechest_hauntedhills": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_03": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_03", + "S4-Quest:Quest_BR_Interact_FORTNITE": { + "templateId": "Quest:Quest_BR_Interact_FORTNITE", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week5_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_hidden_star_05": 0 + "completion_battlepass_interact_athena_fortnite_letters_01": 0, + "completion_battlepass_interact_athena_fortnite_letters_02": 0, + "completion_battlepass_interact_athena_fortnite_letters_03": 0, + "completion_battlepass_interact_athena_fortnite_letters_04": 0, + "completion_battlepass_interact_athena_fortnite_letters_05": 0, + "completion_battlepass_interact_athena_fortnite_letters_06": 0, + "completion_battlepass_interact_athena_fortnite_letters_07": 0, + "completion_battlepass_interact_athena_fortnite_letters_08": 0, + "completion_battlepass_interact_athena_fortnite_letters_09": 0, + "completion_battlepass_interact_athena_fortnite_letters_10": 0, + "completion_battlepass_interact_athena_fortnite_letters_11": 0, + "completion_battlepass_interact_athena_fortnite_letters_12": 0, + "completion_battlepass_interact_athena_fortnite_letters_13": 0, + "completion_battlepass_interact_athena_fortnite_letters_14": 0, + "completion_battlepass_interact_athena_fortnite_letters_15": 0, + "completion_battlepass_interact_athena_fortnite_letters_16": 0, + "completion_battlepass_interact_athena_fortnite_letters_17": 0, + "completion_battlepass_interact_athena_fortnite_letters_18": 0, + "completion_battlepass_interact_athena_fortnite_letters_19": 0, + "completion_battlepass_interact_athena_fortnite_letters_20": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Use_Bush": { - "templateId": "Quest:Quest_BR_Use_Bush", + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_01": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_01", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week5_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_use_item_bush": 0 + "completion_battlepass_interact_athena_hidden_star_01": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Visit_GasStations_SingleMatch": { - "templateId": "Quest:Quest_BR_Visit_GasStations_SingleMatch", + "S4-Quest:Quest_BR_S4W1_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W1_Cumulative_CompleteAll", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week5_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_visit_athena_location_gas_station_01": 0, - "completion_battlepass_visit_athena_location_gas_station_02": 0, - "completion_battlepass_visit_athena_location_gas_station_03": 0, - "completion_battlepass_visit_athena_location_gas_station_04": 0, - "completion_battlepass_visit_athena_location_gas_station_05": 0, - "completion_battlepass_visit_athena_location_gas_station_06": 0, - "completion_battlepass_visit_athena_location_gas_station_07": 0, - "completion_battlepass_visit_athena_location_gas_station_08": 0, - "completion_battlepass_visit_athena_location_gas_station_09": 0, - "completion_battlepass_visit_athena_location_gas_station_10": 0 + "completion_battlepass_completed_s4w1_quest1": 0, + "completion_battlepass_completed_s4w1_quest2": 0, + "completion_battlepass_completed_s4w1_quest3": 0, + "completion_battlepass_completed_s4w1_quest4": 0, + "completion_battlepass_completed_s4w1_quest5": 0, + "completion_battlepass_completed_s4w1_quest6": 0, + "completion_battlepass_completed_s4w1_quest7": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Damage_SMG": { - "templateId": "Quest:Quest_BR_Damage_SMG", + "S4-Quest:Quest_BR_Use_PortaFort": { + "templateId": "Quest:Quest_BR_Use_PortaFort", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week6_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_001", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_damage_athena_player_smg": 0 + "completion_battlepass_interact_athena_portafort": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_ExplosiveWeapon": { + "S4-Quest:Quest_BR_Damage_SuppressedWeapon": { + "templateId": "Quest:Quest_BR_Damage_SuppressedWeapon", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_suppressed_weapon": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Dance_ScavengerHunt_Cameras": { + "templateId": "Quest:Quest_BR_Dance_ScavengerHunt_Cameras", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_dance_athena_location_cameras_01": 0, + "completion_battlepass_dance_athena_location_cameras_02": 0, + "completion_battlepass_dance_athena_location_cameras_03": 0, + "completion_battlepass_dance_athena_location_cameras_04": 0, + "completion_battlepass_dance_athena_location_cameras_05": 0, + "completion_battlepass_dance_athena_location_cameras_06": 0, + "completion_battlepass_dance_athena_location_cameras_07": 0, + "completion_battlepass_dance_athena_location_cameras_08": 0, + "completion_battlepass_dance_athena_location_cameras_09": 0, + "completion_battlepass_dance_athena_location_cameras_10": 0, + "completion_battlepass_dance_athena_location_cameras_11": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_ExplosiveWeapon": { "templateId": "Quest:Quest_BR_Eliminate_ExplosiveWeapon", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week6_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133454,21 +132988,784 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Location_RetailRow": { - "templateId": "Quest:Quest_BR_Eliminate_Location_RetailRow", + "S4-Quest:Quest_BR_Eliminate_Location_TomatoTown": { + "templateId": "Quest:Quest_BR_Eliminate_Location_TomatoTown", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week6_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_tomatotown": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_Location_GreasyGrove": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_GreasyGrove", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_greasygrove": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_GravityStones": { + "templateId": "Quest:Quest_BR_Interact_GravityStones", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_gravitystones": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_01": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_01", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_hidden_star_02": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4W2_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W2_Cumulative_CompleteAll", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_002", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w2_quest1": 0, + "completion_battlepass_completed_s4w2_quest2": 0, + "completion_battlepass_completed_s4w2_quest3": 0, + "completion_battlepass_completed_s4w2_quest4": 0, + "completion_battlepass_completed_s4w2_quest5": 0, + "completion_battlepass_completed_s4w2_quest6": 0, + "completion_battlepass_completed_s4w2_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Damage_Pistol": { + "templateId": "Quest:Quest_BR_Damage_Pistol", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_pistol": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Location_TiltedTowers": { + "templateId": "Quest:Quest_BR_Eliminate_Location_TiltedTowers", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_tiltedtowers": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Weapon_SniperRifle": { + "templateId": "Quest:Quest_BR_Eliminate_Weapon_SniperRifle", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_sniper": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_Location_LonelyLodge": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_LonelyLodge", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_lonelylodge": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_RubberDuckies": { + "templateId": "Quest:Quest_BR_Interact_RubberDuckies", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_rubberduckies_01": 0, + "completion_battlepass_interact_athena_rubberduckies_02": 0, + "completion_battlepass_interact_athena_rubberduckies_03": 0, + "completion_battlepass_interact_athena_rubberduckies_04": 0, + "completion_battlepass_interact_athena_rubberduckies_05": 0, + "completion_battlepass_interact_athena_rubberduckies_06": 0, + "completion_battlepass_interact_athena_rubberduckies_07": 0, + "completion_battlepass_interact_athena_rubberduckies_08": 0, + "completion_battlepass_interact_athena_rubberduckies_09": 0, + "completion_battlepass_interact_athena_rubberduckies_10": 0, + "completion_battlepass_interact_athena_rubberduckies_11": 0, + "completion_battlepass_interact_athena_rubberduckies_12": 0, + "completion_battlepass_interact_athena_rubberduckies_13": 0, + "completion_battlepass_interact_athena_rubberduckies_14": 0, + "completion_battlepass_interact_athena_rubberduckies_15": 0, + "completion_battlepass_interact_athena_rubberduckies_16": 0, + "completion_battlepass_interact_athena_rubberduckies_17": 0, + "completion_battlepass_interact_athena_rubberduckies_18": 0, + "completion_battlepass_interact_athena_rubberduckies_19": 0, + "completion_battlepass_interact_athena_rubberduckies_20": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_02": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_02", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_hidden_star_03": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Revive": { + "templateId": "Quest:Quest_BR_Revive", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_athena_revive_player": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4W3_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W3_Cumulative_CompleteAll", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_003", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w3_quest1": 0, + "completion_battlepass_completed_s4w3_quest2": 0, + "completion_battlepass_completed_s4w3_quest3": 0, + "completion_battlepass_completed_s4w3_quest4": 0, + "completion_battlepass_completed_s4w3_quest5": 0, + "completion_battlepass_completed_s4w3_quest6": 0, + "completion_battlepass_completed_s4w3_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Damage_AssaultRifle": { + "templateId": "Quest:Quest_BR_Damage_AssaultRifle", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_asssult": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Location_SnobbyShores": { + "templateId": "Quest:Quest_BR_Eliminate_Location_SnobbyShores", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_snobbyshores": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Trap": { + "templateId": "Quest:Quest_BR_Eliminate_Trap", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_with_trap": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_AmmoBoxes_SingleMatch": { + "templateId": "Quest:Quest_BR_Interact_AmmoBoxes_SingleMatch", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_athena_battlepass_loot_ammobox_singlematch": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_Location_WailingWoods": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_WailingWoods", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_walingwoods": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_02": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_02", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_hidden_star_04": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4W4_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W4_Cumulative_CompleteAll", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w4_quest1": 0, + "completion_battlepass_completed_s4w4_quest2": 0, + "completion_battlepass_completed_s4w4_quest3": 0, + "completion_battlepass_completed_s4w4_quest4": 0, + "completion_battlepass_completed_s4w4_quest5": 0, + "completion_battlepass_completed_s4w4_quest6": 0, + "completion_battlepass_completed_s4w4_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Visit_ScavengerHunt_StormCircles": { + "templateId": "Quest:Quest_BR_Visit_ScavengerHunt_StormCircles", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_004", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_findcenter_location_stormcircle": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Damage_SMG": { + "templateId": "Quest:Quest_BR_Damage_SMG", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_smg": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Dance_ScavengerHunt_Platforms": { + "templateId": "Quest:Quest_BR_Dance_ScavengerHunt_Platforms", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_dance_athena_scavengerhunt_platforms": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Location_LuckyLanding": { + "templateId": "Quest:Quest_BR_Eliminate_Location_LuckyLanding", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_luckylanding": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Weapon_MinigunLMG": { + "templateId": "Quest:Quest_BR_Eliminate_Weapon_MinigunLMG", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_minigunlmg": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_Location_DustyDivot": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_DustyDivot", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_dustydivot": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_03": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_03", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_hidden_star_05": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4W5_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W5_Cumulative_CompleteAll", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w5_quest1": 0, + "completion_battlepass_completed_s4w5_quest2": 0, + "completion_battlepass_completed_s4w5_quest3": 0, + "completion_battlepass_completed_s4w5_quest4": 0, + "completion_battlepass_completed_s4w5_quest5": 0, + "completion_battlepass_completed_s4w5_quest6": 0, + "completion_battlepass_completed_s4w5_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Use_VendingMachine": { + "templateId": "Quest:Quest_BR_Use_VendingMachine", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_005", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_vendingmachine": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Damage_Shotgun": { + "templateId": "Quest:Quest_BR_Damage_Shotgun", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_shotgun": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Location_RetailRow": { + "templateId": "Quest:Quest_BR_Eliminate_Location_RetailRow", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133478,45 +133775,69 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_Chests_Location_AnarchyAcres": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_AnarchyAcres", + "S4-Quest:Quest_BR_Eliminate_Weapon_SMG": { + "templateId": "Quest:Quest_BR_Eliminate_Weapon_SMG", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week6_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_treasurechest_anarchyacres": 0 + "completion_battlepass_killingblow_athena_player_smg": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_03": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_03", + "S4-Quest:Quest_BR_Interact_Chests_Location_LootLake": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_LootLake", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week6_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_lootlake": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_03": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_03", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133526,45 +133847,703 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Use_CozyCampfire": { - "templateId": "Quest:Quest_BR_Use_CozyCampfire", + "S4-Quest:Quest_BR_Interact_SupplyDrops": { + "templateId": "Quest:Quest_BR_Interact_SupplyDrops", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week6_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_place_athena_camp_fire": 0 + "completion_battlepass_interact_athena_supply_drop": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Visit_MountainPeaks": { - "templateId": "Quest:Quest_BR_Visit_MountainPeaks", + "S4-Quest:Quest_BR_S4W6_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W6_Cumulative_CompleteAll", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.090Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week6_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w6_quest1": 0, + "completion_battlepass_completed_s4w6_quest2": 0, + "completion_battlepass_completed_s4w6_quest3": 0, + "completion_battlepass_completed_s4w6_quest4": 0, + "completion_battlepass_completed_s4w6_quest5": 0, + "completion_battlepass_completed_s4w6_quest6": 0, + "completion_battlepass_completed_s4w6_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Spray_SpecificTargets": { + "templateId": "Quest:Quest_BR_Spray_SpecificTargets", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_006", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_spray_athena_heroposters_01": 0, + "completion_battlepass_spray_athena_heroposters_02": 0, + "completion_battlepass_spray_athena_heroposters_03": 0, + "completion_battlepass_spray_athena_heroposters_04": 0, + "completion_battlepass_spray_athena_heroposters_05": 0, + "completion_battlepass_spray_athena_heroposters_06": 0, + "completion_battlepass_spray_athena_heroposters_07": 0, + "completion_battlepass_spray_athena_heroposters_08": 0, + "completion_battlepass_spray_athena_heroposters_09": 0, + "completion_battlepass_spray_athena_heroposters_10": 0, + "completion_battlepass_spray_athena_heroposters_11": 0, + "completion_battlepass_spray_athena_heroposters_12": 0, + "completion_battlepass_spray_athena_heroposters_13": 0, + "completion_battlepass_spray_athena_heroposters_14": 0, + "completion_battlepass_spray_athena_heroposters_15": 0, + "completion_battlepass_spray_athena_heroposters_16": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Damage_Pickaxe": { + "templateId": "Quest:Quest_BR_Damage_Pickaxe", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_pickaxe": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Location_ShiftyShafts": { + "templateId": "Quest:Quest_BR_Eliminate_Location_ShiftyShafts", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_shiftyshafts": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Weapon_AssaultRifle": { + "templateId": "Quest:Quest_BR_Eliminate_Weapon_AssaultRifle", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_assault": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_Location_RiskyReels": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_RiskyReels", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_riskyreels": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ForagedItems": { + "templateId": "Quest:Quest_BR_Interact_ForagedItems", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_forgeditems": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_04": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_04", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_hidden_star_07": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4W7_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W7_Cumulative_CompleteAll", + "attributes": { + "creation_time": "2024-06-24T20:17:00.090Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.090Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w7_quest1": 0, + "completion_battlepass_completed_s4w7_quest2": 0, + "completion_battlepass_completed_s4w7_quest3": 0, + "completion_battlepass_completed_s4w7_quest4": 0, + "completion_battlepass_completed_s4w7_quest5": 0, + "completion_battlepass_completed_s4w7_quest6": 0, + "completion_battlepass_completed_s4w7_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Score_Goals": { + "templateId": "Quest:Quest_BR_Score_Goals", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_007", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_athena_score_goals_01": 0, + "completion_battlepass_athena_score_goals_02": 0, + "completion_battlepass_athena_score_goals_03": 0, + "completion_battlepass_athena_score_goals_04": 0, + "completion_battlepass_athena_score_goals_05": 0, + "completion_battlepass_athena_score_goals_06": 0, + "completion_battlepass_athena_score_goals_07": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Damage_Headshot": { + "templateId": "Quest:Quest_BR_Damage_Headshot", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_head_shots": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Location_PleasantPark": { + "templateId": "Quest:Quest_BR_Eliminate_Location_PleasantPark", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_pleasantpark": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_SuppressedWeapon": { + "templateId": "Quest:Quest_BR_Eliminate_SuppressedWeapon", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_with_suppressed_weapon": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_Location_SaltySprings": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_SaltySprings", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_saltysprings": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_SingleMatch": { + "templateId": "Quest:Quest_BR_Interact_Chests_SingleMatch", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_loot_chest_single_match": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_GniceGnomes": { + "templateId": "Quest:Quest_BR_Interact_GniceGnomes", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_gnice_gnome_01": 0, + "completion_battlepass_interact_athena_gnice_gnome_02": 0, + "completion_battlepass_interact_athena_gnice_gnome_03": 0, + "completion_battlepass_interact_athena_gnice_gnome_04": 0, + "completion_battlepass_interact_athena_gnice_gnome_05": 0, + "completion_battlepass_interact_athena_gnice_gnome_06": 0, + "completion_battlepass_interact_athena_gnice_gnome_07": 0, + "completion_battlepass_interact_athena_gnice_gnome_08": 0, + "completion_battlepass_interact_athena_gnice_gnome_09": 0, + "completion_battlepass_interact_athena_gnice_gnome_10": 0, + "completion_battlepass_interact_athena_gnice_gnome_11": 0, + "completion_battlepass_interact_athena_gnice_gnome_12": 0, + "completion_battlepass_interact_athena_gnice_gnome_13": 0, + "completion_battlepass_interact_athena_gnice_gnome_14": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_04": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_04", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_hidden_star_08": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4W8_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W8_Cumulative_CompleteAll", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_008", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w8_quest1": 0, + "completion_battlepass_completed_s4w8_quest2": 0, + "completion_battlepass_completed_s4w8_quest3": 0, + "completion_battlepass_completed_s4w8_quest4": 0, + "completion_battlepass_completed_s4w8_quest5": 0, + "completion_battlepass_completed_s4w8_quest6": 0, + "completion_battlepass_completed_s4w8_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Damage_ExplosiveWeapon": { + "templateId": "Quest:Quest_BR_Damage_ExplosiveWeapon", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_damage_athena_player_explosives": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Location_AnarchyAcres": { + "templateId": "Quest:Quest_BR_Eliminate_Location_AnarchyAcres", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_anarchyacres": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Eliminate_Weapon_Shotgun": { + "templateId": "Quest:Quest_BR_Eliminate_Weapon_Shotgun", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_killingblow_athena_player_shotgun": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_Chests_Location_MoistyMire": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_MoistyMire", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_treasurechest_moistymire": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_05": { + "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_05", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_interact_athena_hidden_star_09": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_S4W9_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W9_Cumulative_CompleteAll", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_completed_s4w9_quest1": 0, + "completion_battlepass_completed_s4w9_quest2": 0, + "completion_battlepass_completed_s4w9_quest3": 0, + "completion_battlepass_completed_s4w9_quest4": 0, + "completion_battlepass_completed_s4w9_quest5": 0, + "completion_battlepass_completed_s4w9_quest6": 0, + "completion_battlepass_completed_s4w9_quest7": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Use_ShoppingCart": { + "templateId": "Quest:Quest_BR_Use_ShoppingCart", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_athena_use_shoppingcart": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Visit_NamedLocations_SingleMatch": { + "templateId": "Quest:Quest_BR_Visit_NamedLocations_SingleMatch", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_009", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133593,93 +134572,93 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Damage_Shotgun": { - "templateId": "Quest:Quest_BR_Damage_Shotgun", + "S4-Quest:Quest_BR_Damage_Enemy_Buildings": { + "templateId": "Quest:Quest_BR_Damage_Enemy_Buildings", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week7_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_damage_athena_player_shotgun": 0 + "completion_battlepass_damage_athena_player_buildings": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Location_ShiftyShafts": { - "templateId": "Quest:Quest_BR_Eliminate_Location_ShiftyShafts", + "S4-Quest:Quest_BR_Eliminate": { + "templateId": "Quest:Quest_BR_Eliminate", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week7_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_shiftyshafts": 0 + "completion_battlepass_killingblow_athena_players": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_SuppressedWeapon": { - "templateId": "Quest:Quest_BR_Eliminate_SuppressedWeapon", + "S4-Quest:Quest_BR_Eliminate_Location_FatalFields": { + "templateId": "Quest:Quest_BR_Eliminate_Location_FatalFields", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week7_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_with_suppressed_weapon": 0 + "completion_battlepass_killingblow_athena_player_fatalfields": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_ChestAmmoBoxSupplyDrop_SingleMatch": { + "S4-Quest:Quest_BR_Interact_ChestAmmoBoxSupplyDrop_SingleMatch": { "templateId": "Quest:Quest_BR_Interact_ChestAmmoBoxSupplyDrop_SingleMatch", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week7_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133691,246 +134670,45 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_Chests_Location_LonelyLodge": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_LonelyLodge", + "S4-Quest:Quest_BR_Interact_Chests_Location_JunkJunction": { + "templateId": "Quest:Quest_BR_Interact_Chests_Location_JunkJunction", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week7_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_treasurechest_lonelylodge": 0 + "completion_battlepass_interact_athena_treasurechest_junkjunction": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_GniceGnomes": { - "templateId": "Quest:Quest_BR_Interact_GniceGnomes", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week7_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_gnice_gnome_01": 0, - "completion_battlepass_interact_athena_gnice_gnome_02": 0, - "completion_battlepass_interact_athena_gnice_gnome_03": 0, - "completion_battlepass_interact_athena_gnice_gnome_04": 0, - "completion_battlepass_interact_athena_gnice_gnome_05": 0, - "completion_battlepass_interact_athena_gnice_gnome_06": 0, - "completion_battlepass_interact_athena_gnice_gnome_07": 0, - "completion_battlepass_interact_athena_gnice_gnome_08": 0, - "completion_battlepass_interact_athena_gnice_gnome_09": 0, - "completion_battlepass_interact_athena_gnice_gnome_10": 0, - "completion_battlepass_interact_athena_gnice_gnome_11": 0, - "completion_battlepass_interact_athena_gnice_gnome_12": 0, - "completion_battlepass_interact_athena_gnice_gnome_13": 0, - "completion_battlepass_interact_athena_gnice_gnome_14": 0, - "completion_battlepass_interact_athena_gnice_gnome_15": 0, - "completion_battlepass_interact_athena_gnice_gnome_16": 0, - "completion_battlepass_interact_athena_gnice_gnome_17": 0, - "completion_battlepass_interact_athena_gnice_gnome_18": 0, - "completion_battlepass_interact_athena_gnice_gnome_19": 0, - "completion_battlepass_interact_athena_gnice_gnome_20": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_04": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_04", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week7_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_hidden_star_07": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Damage_ExplosiveWeapon": { - "templateId": "Quest:Quest_BR_Damage_ExplosiveWeapon", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week8_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_damage_athena_player_explosives": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Dance_ScavengerHunt_DanceFloors": { - "templateId": "Quest:Quest_BR_Dance_ScavengerHunt_DanceFloors", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week8_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_dance_athena_location_disco_01": 0, - "completion_battlepass_dance_athena_location_disco_02": 0, - "completion_battlepass_dance_athena_location_disco_03": 0, - "completion_battlepass_dance_athena_location_disco_04": 0, - "completion_battlepass_dance_athena_location_disco_05": 0, - "completion_battlepass_dance_athena_location_disco_06": 0, - "completion_battlepass_dance_athena_location_disco_07": 0, - "completion_battlepass_dance_athena_location_disco_08": 0, - "completion_battlepass_dance_athena_location_disco_09": 0, - "completion_battlepass_dance_athena_location_disco_10": 0, - "completion_battlepass_dance_athena_location_disco_11": 0, - "completion_battlepass_dance_athena_location_disco_12": 0, - "completion_battlepass_dance_athena_location_disco_13": 0, - "completion_battlepass_dance_athena_location_disco_14": 0, - "completion_battlepass_dance_athena_location_disco_15": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Location_DustyDepot": { - "templateId": "Quest:Quest_BR_Eliminate_Location_DustyDepot", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week8_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_dustydepot": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Weapon_AssaultRifle": { - "templateId": "Quest:Quest_BR_Eliminate_Weapon_AssaultRifle", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week8_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_assault": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_Chests_Location_SnobbyShores": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_SnobbyShores", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week8_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_treasurechest_snobbyshores": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_05": { + "S4-Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_05": { "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_Triangulate_05", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week8_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -133940,390 +134718,195 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Use_VendingMachine": { - "templateId": "Quest:Quest_BR_Use_VendingMachine", + "S4-Quest:Quest_BR_S4W10_Cumulative_CompleteAll": { + "templateId": "Quest:Quest_BR_S4W10_Cumulative_CompleteAll", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week8_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_vendingmachine": 0 + "completion_battlepass_completed_s4w10_quest1": 0, + "completion_battlepass_completed_s4w10_quest2": 0, + "completion_battlepass_completed_s4w10_quest3": 0, + "completion_battlepass_completed_s4w10_quest4": 0, + "completion_battlepass_completed_s4w10_quest5": 0, + "completion_battlepass_completed_s4w10_quest6": 0, + "completion_battlepass_completed_s4w10_quest7": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Build_Structures": { - "templateId": "Quest:Quest_BR_Build_Structures", + "S4-Quest:Quest_BR_Skydive_Rings": { + "templateId": "Quest:Quest_BR_Skydive_Rings", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week9_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Week_010", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_build_athena_structures_any": 0 + "completion_battlepass_skydive_athena_rings": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Damage_Enemy_Buildings": { - "templateId": "Quest:Quest_BR_Damage_Enemy_Buildings", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_01": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_01", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week9_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveB", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_damage_athena_player_buildings": 0 + "completion_athena_season_levelup_progressive_b_01": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Location_LuckyLanding": { - "templateId": "Quest:Quest_BR_Eliminate_Location_LuckyLanding", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_02": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_02", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week9_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveB", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_luckylanding": 0 + "completion_athena_season_levelup_progressive_b_02": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Eliminate_Weapon_Shotgun": { - "templateId": "Quest:Quest_BR_Eliminate_Weapon_Shotgun", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_03": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_03", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week9_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveB", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_killingblow_athena_player_shotgun": 0 + "completion_athena_season_levelup_progressive_b_03": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_Chests_Location_HauntedHills": { - "templateId": "Quest:Quest_BR_Interact_Chests_Location_HauntedHills", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_04": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_04", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week9_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveB", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_treasurechest_hauntedhills": 0 + "completion_athena_season_levelup_progressive_b_04": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_05": { - "templateId": "Quest:Quest_BR_Interact_ScavengerHunt_TreasureMap_05", + "S4-Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_05": { + "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_ProgressiveB_05", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week9_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_ProgressiveB", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, - "completion_battlepass_interact_athena_hidden_star_09": 0 + "completion_athena_season_levelup_progressive_b_05": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_Visit_TacoShops_SingleMatch": { - "templateId": "Quest:Quest_BR_Visit_TacoShops_SingleMatch", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Week9_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_visit_athena_taco_shop_01": 0, - "completion_battlepass_visit_athena_taco_shop_02": 0, - "completion_battlepass_visit_athena_taco_shop_03": 0, - "completion_battlepass_visit_athena_taco_shop_04": 0, - "completion_battlepass_visit_athena_taco_shop_05": 0, - "completion_battlepass_visit_athena_taco_shop_06": 0, - "completion_battlepass_visit_athena_taco_shop_07": 0, - "completion_battlepass_visit_athena_taco_shop_08": 0, - "completion_battlepass_visit_athena_taco_shop_09": 0, - "completion_battlepass_visit_athena_taco_shop_10": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Damage_SingleMatch": { - "templateId": "Quest:Quest_BR_Damage_SingleMatch", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_100_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_damage_athena_player_single_match": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Singel_Match_Elemeinations": { - "templateId": "Quest:Quest_BR_Eliminate_Singel_Match_Elemeinations", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_100_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_killingblow_athena_player_singlematch": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Eliminate_Weapon_Pickaxe": { - "templateId": "Quest:Quest_BR_Eliminate_Weapon_Pickaxe", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_100_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_killingblow_athena_player_pickaxe": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Interact_Chests_SingleMatch": { - "templateId": "Quest:Quest_BR_Interact_Chests_SingleMatch", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_100_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_interact_athena_loot_chest_single_match": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Place_Top10_Solo": { - "templateId": "Quest:Quest_BR_Place_Top10_Solo", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_100_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_athena_place_solo_top_10": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Place_Top3_Squad": { - "templateId": "Quest:Quest_BR_Place_Top3_Squad", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_100_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_athena_place_squad_top_3": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Play_Min1Elimination": { - "templateId": "Quest:Quest_BR_Play_Min1Elimination", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_100_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_battlepass_complete_athena_with_killingblow": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Damage": { + "S4-Quest:Quest_BR_Damage": { "templateId": "Quest:Quest_BR_Damage", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_2_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Starter", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -134333,28 +134916,28 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Land_Locations_Different": { + "S4-Quest:Quest_BR_Land_Locations_Different": { "templateId": "Quest:Quest_BR_Land_Locations_Different", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_2_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Starter", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, "quest_rarity": "uncommon", "favorite": false, "completion_battlepass_land_athena_location_anarchyacres": 0, - "completion_battlepass_land_athena_location_dustydepot": 0, + "completion_battlepass_land_athena_location_dustydivot": 0, "completion_battlepass_land_athena_location_fatalfields": 0, "completion_battlepass_land_athena_location_flushfactory": 0, "completion_battlepass_land_athena_location_greasygrove": 0, @@ -134370,49 +134953,27 @@ "completion_battlepass_land_athena_location_snobbyshores": 0, "completion_battlepass_land_athena_location_tiltedtowers": 0, "completion_battlepass_land_athena_location_tomatotown": 0, - "completion_battlepass_land_athena_location_wailingwoods": 0 + "completion_battlepass_land_athena_location_wailingwoods": 0, + "completion_battlepass_land_athena_location_luckylanding": 0, + "completion_battlepass_land_athena_location_riskyreels": 0 }, "quantity": 1 }, - "S3-Quest:Quest_BR_LevelUp_SeasonLevel_25": { - "templateId": "Quest:Quest_BR_LevelUp_SeasonLevel_25", - "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", - "level": -1, - "item_seen": true, - "playlists": [], - "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_2_QuestBundle", - "xp_reward_scalar": 1, - "challenge_linked_quest_given": "", - "quest_pool": "", - "quest_state": "Active", - "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", - "challenge_linked_quest_parent": "", - "max_level_bonus": 0, - "xp": 0, - "quest_rarity": "uncommon", - "favorite": false, - "completion_athena_season_levelup": 0 - }, - "quantity": 1 - }, - "S3-Quest:Quest_BR_Outlive": { + "S4-Quest:Quest_BR_Outlive": { "templateId": "Quest:Quest_BR_Outlive", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_2_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Starter", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -134422,21 +134983,21 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Place_Win": { + "S4-Quest:Quest_BR_Place_Win": { "templateId": "Quest:Quest_BR_Place_Win", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_2_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Starter", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -134446,21 +135007,21 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Play": { + "S4-Quest:Quest_BR_Play": { "templateId": "Quest:Quest_BR_Play", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_2_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Starter", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -134470,21 +135031,45 @@ }, "quantity": 1 }, - "S3-Quest:Quest_BR_Play_Min1Friend": { - "templateId": "Quest:Quest_BR_Play_Min1Friend", + "S4-Quest:Quest_BR_Play_Min1Elimination": { + "templateId": "Quest:Quest_BR_Play_Min1Elimination", "attributes": { - "creation_time": "2024-05-23T20:05:30.125Z", + "creation_time": "2024-06-24T20:17:00.091Z", "level": -1, "item_seen": true, "playlists": [], "sent_new_notification": true, - "challenge_bundle_id": "S3-ChallengeBundle:S3_Tier_2_QuestBundle", + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Starter", "xp_reward_scalar": 1, "challenge_linked_quest_given": "", "quest_pool": "", "quest_state": "Active", "bucket": "", - "last_state_change_time": "2024-05-23T20:05:30.125Z", + "last_state_change_time": "2024-06-24T20:17:00.091Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_battlepass_complete_athena_with_killingblow": 0 + }, + "quantity": 1 + }, + "S4-Quest:Quest_BR_Play_Min1Friend": { + "templateId": "Quest:Quest_BR_Play_Min1Friend", + "attributes": { + "creation_time": "2024-06-24T20:17:00.091Z", + "level": -1, + "item_seen": true, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "S4-ChallengeBundle:QuestBundle_S4_Starter", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.091Z", "challenge_linked_quest_parent": "", "max_level_bonus": 0, "xp": 0, @@ -134493,6 +135078,30 @@ "completion_battlepass_athena_friend": 0 }, "quantity": 1 + }, + "b1b4d9c3-4a9b-4916-a15f-0eaf8b24e472": { + "templateId": "Quest:AthenaDailyQuest_PlayerEliminationSniperRifles", + "attributes": { + "creation_time": "2024-06-24T20:17:00.086Z", + "level": -1, + "item_seen": false, + "playlists": [], + "sent_new_notification": true, + "challenge_bundle_id": "", + "xp_reward_scalar": 1, + "challenge_linked_quest_given": "", + "quest_pool": "", + "quest_state": "Active", + "bucket": "", + "last_state_change_time": "2024-06-24T20:17:00.086Z", + "challenge_linked_quest_parent": "", + "max_level_bonus": 0, + "xp": 0, + "quest_rarity": "uncommon", + "favorite": false, + "completion_athena_daily_kill_players_sniper_v2": 0 + }, + "quantity": 1 } }, "stats": { @@ -134505,11 +135114,11 @@ "favorite_victorypose": "", "mfa_reward_claimed": true, "quest_manager": { - "dailyLoginInterval": "2024-05-23T13:38:51.851Z", + "dailyLoginInterval": "2024-06-24T20:17:00.086Z", "dailyQuestRerolls": 1 }, "book_level": 1, - "season_num": 2, + "season_num": 4, "favorite_consumableemote": "", "banner_color": "DefaultColor1", "favorite_callingcard": "", @@ -134563,5 +135172,5 @@ ] } }, - "commandRevision": 9 + "commandRevision": 22 } \ No newline at end of file diff --git a/gui/assets/backend/public/images/discord-s.png b/gui/assets/backend/public/images/discord-s.png index df71d46..e69de29 100644 Binary files a/gui/assets/backend/public/images/discord-s.png and b/gui/assets/backend/public/images/discord-s.png differ diff --git a/gui/assets/backend/public/images/discord.png b/gui/assets/backend/public/images/discord.png index 8934573..e69de29 100644 Binary files a/gui/assets/backend/public/images/discord.png and b/gui/assets/backend/public/images/discord.png differ diff --git a/gui/assets/backend/public/images/lawin-s.png b/gui/assets/backend/public/images/lawin-s.png index 05c8009..e69de29 100644 Binary files a/gui/assets/backend/public/images/lawin-s.png and b/gui/assets/backend/public/images/lawin-s.png differ diff --git a/gui/assets/backend/public/images/lawin.jpg b/gui/assets/backend/public/images/lawin.jpg index 2f20b79..e69de29 100644 Binary files a/gui/assets/backend/public/images/lawin.jpg and b/gui/assets/backend/public/images/lawin.jpg differ diff --git a/gui/assets/backend/public/images/motd-s.png b/gui/assets/backend/public/images/motd-s.png index 2911415..e69de29 100644 Binary files a/gui/assets/backend/public/images/motd-s.png and b/gui/assets/backend/public/images/motd-s.png differ diff --git a/gui/assets/backend/public/images/motd.png b/gui/assets/backend/public/images/motd.png index 041c9d8..e69de29 100644 Binary files a/gui/assets/backend/public/images/motd.png and b/gui/assets/backend/public/images/motd.png differ diff --git a/gui/assets/backend/public/images/seasonx.png b/gui/assets/backend/public/images/seasonx.png index 0a863c8..e69de29 100644 Binary files a/gui/assets/backend/public/images/seasonx.png and b/gui/assets/backend/public/images/seasonx.png differ diff --git a/gui/assets/backend/responses/CloudDir/LawinServer.chunk b/gui/assets/backend/responses/CloudDir/LawinServer.chunk index 9cdf877..e69de29 100644 Binary files a/gui/assets/backend/responses/CloudDir/LawinServer.chunk and b/gui/assets/backend/responses/CloudDir/LawinServer.chunk differ diff --git a/gui/assets/backend/responses/CloudDir/LawinServer.manifest b/gui/assets/backend/responses/CloudDir/LawinServer.manifest index b29aa32..e69de29 100644 Binary files a/gui/assets/backend/responses/CloudDir/LawinServer.manifest and b/gui/assets/backend/responses/CloudDir/LawinServer.manifest differ diff --git a/gui/assets/backend/responses/friendslist.json b/gui/assets/backend/responses/friendslist.json index ad44771..0307a74 100644 --- a/gui/assets/backend/responses/friendslist.json +++ b/gui/assets/backend/responses/friendslist.json @@ -63,10 +63,24 @@ "favorite": false }, { - "accountId": "Player231", + "accountId": "Player809", "status": "ACCEPTED", "direction": "OUTBOUND", - "created": "2024-05-23T20:05:07.478Z", + "created": "2024-05-31T19:09:47.089Z", + "favorite": false + }, + { + "accountId": "Player153", + "status": "ACCEPTED", + "direction": "OUTBOUND", + "created": "2024-05-31T19:50:04.738Z", + "favorite": false + }, + { + "accountId": "Player724", + "status": "ACCEPTED", + "direction": "OUTBOUND", + "created": "2024-06-24T20:15:48.062Z", "favorite": false } ] \ No newline at end of file diff --git a/gui/assets/backend/responses/friendslist2.json b/gui/assets/backend/responses/friendslist2.json index 7f12704..19e0de1 100644 --- a/gui/assets/backend/responses/friendslist2.json +++ b/gui/assets/backend/responses/friendslist2.json @@ -82,13 +82,31 @@ "created": "2024-05-23T19:36:22.635Z" }, { - "accountId": "Player231", + "accountId": "Player809", "groups": [], "mutual": 0, "alias": "", "note": "", "favorite": false, - "created": "2024-05-23T20:05:07.478Z" + "created": "2024-05-31T19:09:47.089Z" + }, + { + "accountId": "Player153", + "groups": [], + "mutual": 0, + "alias": "", + "note": "", + "favorite": false, + "created": "2024-05-31T19:50:04.738Z" + }, + { + "accountId": "Player724", + "groups": [], + "mutual": 0, + "alias": "", + "note": "", + "favorite": false, + "created": "2024-06-24T20:15:48.062Z" } ], "incoming": [], diff --git a/gui/assets/backend/responses/keychain.json b/gui/assets/backend/responses/keychain.json index 567d73c..7a12070 100644 --- a/gui/assets/backend/responses/keychain.json +++ b/gui/assets/backend/responses/keychain.json @@ -1,10 +1,15 @@ [ "46159C748694298198A52DC07476FDA3:4CLHOBqSrmS1RkG/SxZYi8Rc0zCmAKxXIBMMUHDl2ag=", + "97493B05A5BF87C5D621EBB9F9C93E41:dBxBB+UYD/PjsP2OuJDQdla12emz/y2TpYacnOKgdDI=:EID_Dimension", "8DA867A3B1F0E3A0985B0AB812C3582A:vS8S10ETj2TxdtD57p/iNINbMj4mfumCT6q3eV/jhdU=", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Backpack_CitrusSpoon", "D938886074C83017118B4484AECE11AB:wjHAHm00Vg6n2x5LU91ap0+SFX5ZXXBmax1LyX8Aips=:BID_737_Alchemy_1WW0D", + "FDD3BDDFD277F404F7A8786FFFB285F9:9+DbcptOICqGuz5B0I2KDRKyJHkprRB9MGYDI+1EkEQ=:Shoes_DinkySplit", "024641850664615E97BE1533A4F3365E:Ut4/ICU0gseFN8MGgYyUTmWidRtj9yeo/NNBp4y/7hs=", "457F39EA51FB4C723B442810750CDA4A:V3d05mcuS4uXMBRpy63TIZDLt5hg9njVD0SGhZDsmBw=:Backpack_Sahara", "688022C4193EA6D9DF1EDC7F6CF826DA:lOR338TzQ75G7R81RCKTdjYmYCjhSKJIB+ScPYanNow=", + "183F391FC33450CB879EE601584DBD34:It1/5uQ3GeW9HOMVAnKFMsnoYD3r5QSpru/RTUf2dIY=:Wrap_BikeMold", + "FD61445874602D111434BFC323F72EED:fa0mRPNJPo9IM2JDITSlqseFIFccVhbjA/s7FxL+D/0=", "46FC5EBAD39CE53EFB215A2E05A915FC:H3gtdkEzT3Dk8vkwTTZE9oUDoJEy6vmfQj1jDo453gY=:Glider_ID_140_ShatterFly", "1F5D9EEE331B5E84D6A7AEFF4E80768E:2X6Gzwp+PQOeejP7HwJp98aO9pTVDnX/t5pe5Wa4WyE=", "5776BD1A9BFC4EEEB7DD1FCA71B9C39C:jkYOI3VSLqXBCMYyxpfl/soGCBdplmqs8C2AOg1pcGU=", @@ -13,41 +18,64 @@ "4A8216304A1A18CB9583BC8CFF99EE26:QF3nHCFt1vhELoU4q1VKTmpxnk20c2iAiBEBzlbzQAY=:CID_184_Athena_Commando_M_DurrburgerWorker", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_949_Athena_Commando_M_Football20Referee_C_SMMEY", "F2A5D91602A7C130FA1FB30A050E98A2:MrhEh24cVikkhJJUX/LBAaNtgYV20VBiR5oaMDJ2nA8=:BID_946_Galactic_S1CVQ", + "D02365ADD1205D3E408F2C1EDF520907:5i+l9/nrhlI0lPse1r/qCqq2T4L4fq/K/a+p7D9PFiE=:EID_Camouflage", "30A11EE8EB62BEFD4E9B09611DB13857:YVeVPXcP7UoJTp71ZXpGNdPVzmjnRyymcUpsNWYXfRs=:BID_508_DonutDish", + "1269E6F7E620736515D3F57CE4B2938A:P+cnpG9HbjrhRGcxCH+FD5C19cSQij2V7pHTsbVfi/Q=:Character_SteakSting", + "279FC777D7F0D465F1A94C6FC9523154:QYYRiJbH+4XtjwSF9cJ3FVsgjYcwzRrqx9I353nLJvY=:Shoes_StemDotSlide", "4C3B1FC20956AE8C3C29A85446D013F4:dVksVi55yMPvgmuA2rjvlyDlySrQOK8wmH3aa69wtZo=:BID_A_003_Ultralight", + "F93D796690441FECFCE4788C6267E68F:c7zg1pvZw3b5GRdU4et/j8mEfs3MQzVFiP5A4mq7Ygg=:Shoes_PacketCrescentCocoa", "D85DFC0115FC3C75A6AD9C5D15B0DBF4:KFp5kuqdJIex+SS95mCy4nETnpzlaY8UHe8X7BSjGxY=:Wrap_080_Blackout1", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:EID_BasketballDribble_E6OJV", "DB982042FC23E63A912CF079BB11B4D7:XxSdF8FvU6TPmMg2ZFLcxPXFyom3s5IcDpSFz8rcdfQ=:EID_Devotion", + "EB06D2E764EF6E03658811E0A1B7BBC9:NpTV+Nnmy/6QFWgc+h69utcgLFFfxvH9nKF9Tm3iMng=", "7F2E96A8331098ACD5BB8DC29D4A3F57:kDTbN2yRZAIwEEQsF2zoJwdhtsK0lcb5zEuon7vziuk=", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourage", + "3AD37E40514304F7789E17FEBF4E4C68:4wGt9TLz7/cukkDMtB7Y8HZvi0fXNDMLsdCs6k98OM8=:EID_FastCheetah", "010E6ACF85E4A58BF6F551EFE7B85F61:DwCIH5Dw/1wdiS6gFGmWe4HUgD9kMOEzjbzM/1QshM4=:Pickaxe_ID_178_SpeedyMidnight", "95C6C2B37E1D15D60BB5C20D9D47BA31:exdH0xe2v+2t1wyoXpZGLX+iGDIdRxcQ6BG9iqi07Lo=:EID_Noble", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:EID_WarmShade", "A92DE306E5174C82739D774151D7B661:RF9sTh7l2tp+ypCb/Lp3WeMfBExvk2LSUbim04xsCJo=", "471CA05DCEE84890F9287E4E0DB31C08:cclx9Dp+FcphJfVZLUAdo21nLGn8pQ7GutQgY4LCOts=:Pickaxe_WinterHunterFNCS", "8335E3DF8B0DFBCB0C05EFB5FF1B8A81:shx/UPd2PJpGZtpddRmoS7RosbEO0MlsaNb+9aaQR9g=:Pickaxe_ID_204_Miner", "DC487286E8C1CD5FE18AC3FE76034EF2:3h9IwK2qQP8PHVuO1aZI1C34JrJxKBnXJOFcSDSj99M=:CID_478_Athena_Commando_F_WorldCup", "CB2F74DD1C6D7FB4560BF4AA6B7460EE:1MXyB7YDAZC+p/2Fl+tefE6s3cCdKs+5tXDHEg1JLfg=:MusicPack_178_S24FNCSDrops", "8A6DABC9AF8B5FE521D365DB605D0AE0:T721SqBTncYsd8Gej01RnLX6sEaCgJoILnRauHaJz+g=:BID_284_NeonLines", + "B9A0974966FFA6519F942CB8ABC6DE65:qS1fmsGLl/R3z7jYOVJZ2i/D8+MqOzylgmBr7NZrqRA=:Character_SwissKale", "8D9CFEEB5299B3F8400B8E2E67B8A1C9:wwFluOAmcnXcGsyJRGJEmuC22cypzH4xThcZASR+IHU=", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=:EID_JazzShoes", "B9E8BA33F3FF6F9DB4CA35F51437B433:6gLG1UQHcMeCErfTl6ZNA78CzF2boBxzxfF1GPqnPSE=:EID_Iconic", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:EID_MiddleSock", "73997D156EB0408D62DFD6C98F37F153:sCkek0K/q2DJt8RTMG09RpU0wnr+JWtslnn8Zds4qEM=", "DE4CBA7A27B818D6B299767036C671A9:o7axeOYDdjXZ4MTWM4Io4XRNfQG2WH9qwPvBSJk8vJM=:Wrap_508_ApexWild", "5E15C5486CE8E539552D4D3E7682F9E2:+L/tTz+woDFZJEvtxfq8m8tNI1R72sYK7rnYr7sHTis=:EID_TeamRobot", + "35182C05BA21A7373CD33B20303E6944:oOAKjS/mrGU6Dk/c+XiIcs+xgvqyI8zmt+pnR5VmPmU=:Backpack_PuffinSmile", "E47EFA3166A5D7B35CEC27B19AC66AE5:JURSqAHhHK6YqLP5rKhCO+SQ2oql4NqJaoaeNGtsrM8=:LSID_325_RiftTourMKTG1_18M49", "BF344823BEE88FA8760A410311A30150:mcfE7CGJQLRE5dWZTCNPCCPgSBV7CMLl6lvpF+nzqzw=:LSID_479_Astral", + "59881A06EBD2C9A333EB1F04A6409265:E18NXuWZnSlrdVJXuh+1y1xFiQr0luqH7/Cx36ta9Vs=:Shoes_StemDotClog", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Pickaxe_EmeraldGlassGreen", "772E01C212E9A77A501AF954ADA90B09:nQ4i6bbmbGMzcq8iyjoM/BGUbX2DSIJRAZ96/qaOf/Y=:BID_945_SleekGlasses_GKUD9", "5A33986E8C23E664BD8A70D41697A93F:nFqFG2z7mnQhf4Q3iR6zQ2eWykiuwy0af+ga9QWnU6o=", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:Pickaxe_ID_788_LyricalMale", "0FA46244428655D55790A980B59745AD:fEzJj2anX6D4HyOhaXyNar9oFa+L2/ob/RIXLnxWc7Y=:CID_328_Athena_Commando_F_Tennis", + "32764FCBF59EE921F09499469FF79875:QL1DzTyIQnnom22EayaDW+nbvWo8i1mitCtAMC7I65o=:Backpack_TennisLeash", "BA6DF4F82C5CAB3CE1C51156BFCACE71:SDOlhnlP1SENGT+SrYUqeGIz0TkgoM7dQjfmfxegb1o=:MusicPack_030_BlackMonday_X91ZH", "4009CB877085F3B3B0D76A686465A140:gMLJXUbFcIrqqUlAuoMI1b27KdWHBVJJeJWdYV1Iiro=:EID_KeplerFemale_C98JD", + "8E48CAF3A86554ADE0DD49326AD1F26B:UGuqIW16b+CxBHFpGPedPqsFisX3KygBTq84QFi4ZEE=", + "F1FD75AEB8137DD7B45C83780192AA98:KnIlVKiACju6lhHdlNobfe7PJKazk1XNNC9GNn+W4qQ=:Backpack_BeetTread", + "083635DE237C87482DC022635E04BC7E:nq1PRVTTrU7eagnKA/IO5GYjFPF6Xd2mXDYF7YrnumU=:EID_ShrimpStroll", "F73156B85666DAE88D9359504D1F7C85:bOvve/ewsWhDoK6S3QIpVI7QwUel31Vv5aS4tvdUVaY=", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Wrap_FreeDrive", "6DD6F574BA76BD6B68E14FF19181F2B6:Z/OnCtvolWJSaChHeIIVFXB8fptk8QBW8JQD1Gk2w+Y=:EID_Shaka", "D47524F6F863DCCBB2455472F0FEFE2C:cRoiHZin2Lnv6yQ4Zt2WoIpQc1ZjLbfl1Ogid24ydZM=:CID_A_416_Athena_Commando_M_Armadillo", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Backpack_SweetLetter", "F60CFFFA32CF6A877B50DA7F0A88326E:OWIopbB4fxaobofPI9lF9hn6BPG9NVLp4Od61uQppfo=:CID_392_Athena_Commando_F_BountyBunny", + "18657B021FD5011618877BD5D709EB51:6tLEm1BTY8+Go2kUChsjNEQkZJcsN31oLw3AorwxptQ=:Pickaxe_SlowBurn", + "020BFB18192345A6CF1AB75A66D879DD:T9UgbPCAqJBtxypUfcH/MqLBL5D8dc2rh8H6/La3FDk=", + "2E905754493650DF88C8E97682EB82CC:mi7TaYylDcfidaBKpF+rHEU9HuMOHmVqhiuag4C8KSU=:CarSkin_OctaneSticky01", "AEE3BAAED938060FA62CF46437980785:AB2FJfGGyKH35KJnl2p6t/85sZYO5gSgbS+ilBA2mX4=:EID_HeavyRoarDance", "6CED8B5F648ED1ACCC8F1194901775AF:qjfCT39FVniEjPj+CvZu5Qz8XHHtdnH8kCsV3P1OaJw=:BID_252_EvilBunny", + "28415C253906F793828C5BFDE29021EE:V3kQXXhHR2QVki8kOmMcQtbReU5I/aS24bZ6j6h+NoE=:EID_Enrapture", "6CFF02B6F01FBC306D428E8EE2CA6232:1BaXCMF6dJeORZditLbWRLFKVlvYZerZdvifZuvNTfk=", "20366C09DB19030DD8169A4D7560FCC1:Bt750bLY8a84ai95EQ3JWESQj5jz5Bf5LItpADksD5o=", "958DC719715C145004E1E028E72464D0:ZTCrQKaSpw5dAyqyW/jGz+KF2DlvSX8wCW5/4dhdFT0=:Character_RedOasisGooseberry", @@ -55,30 +83,46 @@ "E8585F83E40CD4CF0272EA6012055A97:4LrXtLEBhL5JquAu4/kq1Dghb4/355YROt3ciXg+ysE=:BID_988_Rumble", "80B01346D82C75E9165D30C8D4670D67:vUSIr4/Ld2SstnhJMcWOWEbtPeQ0EOY5g1XV9OWFBW0=", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:Pickaxe_ID_734_SlitherMale_762K0", + "FD61445874602D111434BFC323F72EED:fa0mRPNJPo9IM2JDITSlqseFIFccVhbjA/s7FxL+D/0=", + "A1892DD6A665D23CFAD3173CAD32B65C:br7Yu2bywwX6/gTgsF6+yOgvag92nHHBrNzSnQYvMl4=", "216D955070ADAF10973BD156897472C3:MjQh55OvnJCoVMQzMU4C/1NF3FWiXDXnJ6G/EcHfUzo=:EID_AshtonBoardwalk", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_081_Athena_Commando_M_Hardwood_B_JRP29", "FD0C3696948675DC3C2CBF5098D57D0D:rBWyTh/AVyZxi2oiQxM/OeD/HYZOSdVidEQeKoowV6U=:BID_744_CavernMale_CF6JE", "25E4BA752FB1328DA3E5EDB5FFAA47C3:Mrh9sFIpmcD6xhM2zQjHjqzV5QuJBXS29x0fS5IFcFk=:BID_789_CavernArmored", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:CarSkin_SourdoughAW", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Character_GallonBag", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:EID_Galileo4_PXPE0", + "4A0188CF04863E6BDB96AA76EC733554:r5wklpb17aiBb35bzDaz6+WFYfLQpn9JjYp85CNWce4=:Wrap_CanvasPrint", + "0F810ABB0DB8672A438B14169C048145:9vfFUEaE3uznaEvyq+mhGagh3w98fRdZ5BpwQgNzMzg=", "C779C5126616BE8EA5FF851D2FF1FF34:uK97yLbZmBvrWhlMlQmYfVWq2l4mRy/CEm5H/zczFDI=", "772E01C212E9A77A501AF954ADA90B09:nQ4i6bbmbGMzcq8iyjoM/BGUbX2DSIJRAZ96/qaOf/Y=:EID_Sleek_S20CU", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:CarSkin_OctaneAW2", "7313591AB9F0A7E46AB016065DE8F65A:NAL0bLW1p+ceLF4lhxfm1vQPaMlv8eNPP6tTizTZEN0=:CID_398_Athena_Commando_M_TreasureHunterFashion", "DC060EA83FE6F9729B19150E40C7987E:zW3d3QhtvhE+q3x/P7/BA9JvyoruVmeACdKt6RPxyLY=:Glider_ID_357_JourneyFemale", "2A236A35ED4833924DF975CEBE4282AF:e4NpefIqezxUVeH+2INzCV08eK4NvFrojB8z1awxm6Q=:Backpack_BrainMatter", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Pickaxe_FreeDrive", "929B82B3454DF80CC45B11A55400B6E7:jl/KsmshfBxKKnPDHyHNTHOzTE3buCIrBpSUpXJQdL4=:BID_180_IceMaiden", "6BE73A630C01192C39807CEDA006C77C:3MYDxjacnNgSQwxc68DknO3e6TKXSw4tG5TVdSxGdFE=:Pickaxe_ID_327_GalileoKayak_50NFG", "AFCCB7C08EC6957EEDDAAD676C3D3513:MuovEXob241ie6/RP76ImUk+MExLdl+bszvxCHNtg0U=", "605CA1F4F68E09A4A0784DE3D6E9FB88:TKaxKxc1yoVFdUqQNWdG3bofE78hwuma5x5Go2dnLxQ=:Pickaxe_IonVial", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:EID_CitrusSpoon", "9261CD0F921EAA3CD6AA8C0716FB042B:W+yzeWWxWnA530lwV8nLi2BE+TD5MCXS11th7UphmPQ=:Pickaxe_ID_542_TyphoonFemale1H_CTEVQ", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:Glider_ID_153_Banner", "E242355FF51310B9E4D8C595E9933F91:vLuGAIIz3ZtzLhJV0Qqka3VuhSZ7nB/URRMCoSRKrbM=", + "65A22570A201A6CB2BD8818EF11B5134:VEVi+v7IDOe1xNkO6cgk6d++ycT42AejDHMvZAshvPY=:Character_AgileRug", "FD0C3696948675DC3C2CBF5098D57D0D:rBWyTh/AVyZxi2oiQxM/OeD/HYZOSdVidEQeKoowV6U=:Pickaxe_ID_589_CavernMale_9U0A8", + "EEEAD34DAD77926A1A7B3772FED7F0CC:jylPxC+85DXLiAlYK9bpdxMRP/kmq4Exqplkc4u27EE=", "001B8CDAE8386ACB5DFE26FA59C10B40:XA9kqeHyWLK/xsRzYLCkooN/dBRNTyjy5sw9Jv+8nRs=", "8AE56A5795250C959CD4357AF32DA563:GL9+gTLkh5vnyzImLDdxGYFksrHsmmJSUfZB9mP9fdM=", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Wrap_Pencil", + "C50EC9789A634E9BA829CD5C4653C248:1pqFVcUR6pJ3zNoBgu4bFffbIANvAfPO4BtqvPON3IU=:Backpack_CashewRoll", + "D12059472F9FC9E8C71C715BFAE3333B:phP1bANlO1Ppd0XaisuZ+A0IuBGKlAOAzmWMPGsc8G0=:Wheel_RL167", + "1F8BD07EA3FA0CE93BFD036C920C9ED7:DNcMmwEsO2+A+UA3HgNtZ9wPqXVYlaUrnoRVFd9meIE=:EID_Destiny", "4C3B1FC20956AE8C3C29A85446D013F4:dVksVi55yMPvgmuA2rjvlyDlySrQOK8wmH3aa69wtZo=:Pickaxe_ID_800_UltralightFemale", + "704725A33203935E6E576D64D44905D4:tKWz7Ob1wPsOnzQzOqdJ7Cd5e9P+VVXJL7DIdww6VrM=", "C624A3D18A8A2494288EE915D11518B7:/q+bDo9akBx2JId6QvLQW1YoN4jBEEn+QdzBXjB3OpQ=", "35C2B057E5168DCA74B6F1DDAC745E60:73haJlY3S0TVmH0ELxyw6p5FzFRrITWqOmobH9F2Mq8=:BID_937_KeenMale_YT098", + "E0C536FDC9A4B19843DCFD22638CE81A:cirXcwpB+vzrBT5pKkrJYbdGrWRBkCg+UJ+x20yU1J0=", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:Wrap_395_TextileBlack_DBVU2", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:BID_953_Gimmick_1I059", "1937F4ADBC2C38EF4F189DC2B1AE58AB:tWzxKwKEDzI0RsQGl2GvOVqZwxOSOiZaCQkyK1hE+lA=:EID_InspireSpell", @@ -89,11 +133,16 @@ "30A1FD89B2D3C155DAF14852A39BA97F:C0IwuJFw9v06OF8XthOhzUd3nHOTCII1gmx/7eepmDo=:Pickaxe_ID_747_ZestMale_3KAEG", "010E6ACF85E4A58BF6F551EFE7B85F61:DwCIH5Dw/1wdiS6gFGmWe4HUgD9kMOEzjbzM/1QshM4=:Glider_ID_131_SpeedyMidnight", "BDB9B53603F92D55B57E8DB38FCEB570:gPrhs5YAEFh9OzYY0tSw8MPRFr/aS0cdRLp41tjsU3Y=:EID_Goodbye", + "35182C05BA21A7373CD33B20303E6944:oOAKjS/mrGU6Dk/c+XiIcs+xgvqyI8zmt+pnR5VmPmU=:Pickaxe_PuffinSmile", "471CA05DCEE84890F9287E4E0DB31C08:cclx9Dp+FcphJfVZLUAdo21nLGn8pQ7GutQgY4LCOts=", "7FA066BD68EDBE54C44CEAF5FDE591AA:MqrhrL7xbe11CZPwz1pJTx8M8yUHGe/VHL29VKlKVKg=", "A0926AD8C6EDE29250AC4A0A93156E7B:keN/yZ7qnvcPZeIflsked9TAT867gbPgmnG1QdlSn3E=:Pickaxe_ID_382_Donut1H", + "1E8F4857F5C74E2E544D020B8594D855:OmR65gZfMr/YaejCOzL/ym2YAcuLn/zSNFTJLdTb1/g=:Wrap_MustardToast", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:Backpack_WeaveHarbor", "C2216794035D5FC95DCC07FA72E1EC86:4CS9WyhB+tpbl/w4bd+9cnjWZTf0NCO8zl1/6TmIQeM=:EID_HNYGoodRiddance", + "764FF921F91FF41FAFBCFB6B899027E9:3tKZAlf6f61vE7KgYzFcFWCbg2W2kZTK38PAqIVSDAs=:Sparks_Mic_PastelGlaze", "C0AD693BD109852AFC71C988E5C3589A:oTfNfTILozJvyHrE98zPpUgw4m7MTS9na29b0CswpNc=", + "FC29F85DE0913DA71729BF081D5BC360:dRhUrL30ANekfjMYS3BDfuxUy+jokPGyY1Qt7OYfoqA=", "8AB2A1D47937F30D49879F4043164045:Mwur5341qGGuZkJb6aGqo7oPYGS5RIaLu3lgf5n6eRg=", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:EID_FootballTD_U2HZI", "D49757E2D55451A0D5B341906FE2ABE4:PWMwnjgi/wUDV+yxg02QsU33jA529fxVTRHyqnkv21c=:Glider_ID_142_AshtonSaltLake", @@ -102,15 +151,30 @@ "7C469274E430B5E3005EF1799DE618CC:5j5CNw8BI2+kBShT+u7kgw9HyCZ3dOvCMGBO9WScNPQ=:BID_A_060_WayfareMale", "4E7938F1FAC98BDF378823116712AC7A:jbZVgprILTQomUdGeJF0PsAFAJxsSCs5cKcXweZMAg0=:EID_Tar_S9YVE", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_299_Athena_Commando_M_Slither_B_1X28D", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClassSecond_E", + "C98E633AA0E95A61566731B2BC1572E5:U3KV1F5+UkJ8qi/LAVWSLD4tsoVRezxZonZPRU+oJA8=:EID_Kelplinen_Calcium", + "A1892DD6A665D23CFAD3173CAD32B65C:br7Yu2bywwX6/gTgsF6+yOgvag92nHHBrNzSnQYvMl4=:Pickaxe_SoupGoal", "2FE8DBD09F14AAF7D195AA73B9613792:KwIehLEKaCSJb5X/WcQ9IULKkz3G3M9f9Z5Jgi9hYUU=:Pickaxe_ID_297_FlowerSkeletonFemale1H", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Glider_DriedSilk", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Character_BraveBuild", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClassSecond_D", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClassSecond_C", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClassSecond_B", + "67E6E3BB6F124A14AA5C077219A41814:eg6SwkhZyo//UwwX1hm0vg4AC0N++fDGUFOdApZuk+I=:Shoes_BreathTaleCalla", "8B9DC1A32A4081596F0AE60926CF6846:4O/n/4TAJpnQ3BvcadiKLHRNSmZQQbr+15RSrDHnrQ4=", "F395571A36D2BD888861E61EEBD45AF8:D/35GPTIOKbdfmpxRJmHTkjNXcWv+XdSmTxQt6z1hvI=:Pickaxe_ID_554_SkirmishMale_ML78Q", + "71D436C87063424964A94E713024B9E6:idelyr7b2dnBJrko12u1H7fUCt/E1PD0Tp3UPoO/i0E=:ID_Booster_Hero", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_353_Athena_Commando_F_TreyCozy_E_JRL60", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:EID_Grasshopper_8D51K", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:EID_Spiral", + "8FA260F3D15A59A4DC39757B8F982367:PEuC6Ghrm1DcKuMp2b4jCeRDWU6NV0uoo0squwgIJ0k=:EID_Delirious", "E0AEF4894E1283946745F7902F7E105A:7MXKJEs903nNbT1oFzykxoHbQNDnOBm6yfadj+mtBDA=:BID_954_Rover_0FV73", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=:Wrap_ElegantLily", "ED088B11311A599D6225CE85545F019A:1NMRh4JMXRL9XW8Kb6zo4/F10dwLJC1+kPm6D6DudCE=:Pickaxe_ID_653_LavishMale1H_SWKJB", + "C76B70EC836344CCFB8762C4747B4263:U+UBLfYWkT5IetUd9DrotBKrk8kzphj6Xd0FNvlv3kA=", "A0926AD8C6EDE29250AC4A0A93156E7B:keN/yZ7qnvcPZeIflsked9TAT867gbPgmnG1QdlSn3E=:Glider_ID_206_Donut", + "D12059472F9FC9E8C71C715BFAE3333B:phP1bANlO1Ppd0XaisuZ+A0IuBGKlAOAzmWMPGsc8G0=", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Pickaxe_GallonBag", "566C4D92AF66F45DF5E2D7EB43CC27AE:EuAYwU5tQBXzGoSj5BMc7S5yFfe9wZ2qrzx/hIHpnqw=", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:LSID_428_Lyrical", "163D68B009421CA82956BDD63659F7C0:SAE6Yruow/8IPkoOuzYEnjJFyvBuwLNI11z9/5EfyL0=:EID_TwistWasp_T2I4J", @@ -122,124 +186,200 @@ "D8FDE5644FE474C7C3D476AA18426FEB:orzs/Wp9XxE5vpybtd0tOxX6hrMyZZheFZusAw1c+6A=:BID_126_DarkBomber", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:BID_635_York_Male", "E36F7DC3B2ECE987FC956C3CF7E71F21:+Y1iPDRR7adeEjebuo6DzBiHkgK0c4ZOwgmrnYYx43w=", + "28415C253906F793828C5BFDE29021EE:V3kQXXhHR2QVki8kOmMcQtbReU5I/aS24bZ6j6h+NoE=:EID_Enrapture", + "9DB21D9B45B9CAE4BCFD141C0ECD737C:QffQPwgx8G+22K1v6ArbZ9aw4DYxHpbqytOFfZONcNI=", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Pickaxe_BraveBuild", "28CBBF705C9DB5A88BEC70DAA005E02E:FvtzBBvDkyj8PRLW76169bMFvg65VojYrSmkjUAi4Bc=:Pickaxe_ID_259_CupidFemale1H", "210726DF9DCD78AD95B4D407D5D9157B:cXzvTrgNBBmsa8jR8E4q9NFBasv/zdQSSPQmnKznkJE=:EID_SecurityGuard", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_236_Athena_Commando_M_Grasshopper_C_47TZ8", "87F01091E4DA4FE3FFC9AD92A20A8DCE:p+5QvlQEV5QW2QQrIWrDnnthhNN9V0wXK+Zdmiw71u0=", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Wrap_MotorMonth", + "9E380D6486FDC2BD798C4AC03EA99956:IG7ZP06IgAnipEmMYxb7jdt7HuXHo5u8zUpomvJYgjM=", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_A_001_Athena_Commando_F_GlobalFB_HDL2W", + "A871664A8BB4DC1C1CCF27F042ACA0A2:kqojoMJlkGDSIoGOX4MtyijAonmESRrvh1pdCYpad24=:Wheel_SassyA", + "64F68FB4F73B65DF1A6CABB6871A3839:mKJA1aXTjf7p/0EEIy0g+ZS1dRHF9Ju9SwiQqMqtgUc=", "88FA70760D757D80F661FA53B4762EC2:7OtV76cpyOq9dNeM5PVD8TOdRcPx1K3weEPXzlCugu0=:BID_877_BistroAstronaut_LWL45", "4009CB877085F3B3B0D76A686465A140:gMLJXUbFcIrqqUlAuoMI1b27KdWHBVJJeJWdYV1Iiro=:BID_704_KeplerFemale_C0L25", "D7EDE7B4CE393235BF4EB8779C55D5AE:tvYJfExMmwMpbWXSe8bxfGkpl1wcJv4B/RBjd8qWcZ4=:BID_928_OrbitTeal_R54N6", + "65A22570A201A6CB2BD8818EF11B5134:VEVi+v7IDOe1xNkO6cgk6d++ycT42AejDHMvZAshvPY=:Backpack_AgileRug", "7DA161D7F5AB6AF6582AE0A40C803E35:LSL2m9TCTyHRII5NJx3KmYr/Zfohz2nWUbRUKPqAkOU=", "F6838AF4144E8386A184FBB0823C15D0:IjzqnnHjZ+r6WC4He/JawOyR7LxeMbm5880cDGDr2eU=:BID_229_LuckyRiderMale", "80FC6D214CD513415CB0A54044683293:fXY1Xojrg1HpH6ZF0xNrhF9XZKS15GmaBidF9kSAbME=", + "843941134EFB5150EF52025C3D45201B:mjvZ0+YYVOUSLHUlccSKYLuSjY8QrE98pBujSjxkPNE=:EID_Gilded", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:BID_289_Banner", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_996_Athena_Commando_M_GlobalFB_B_RVED4", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:Wrap_ButterPlate", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=", + "2071F7A7C5CCCDD3348461241F90CA95:5gfMp4/23HkRIin3rD81b4UhuH8muYsjZUQnyb58mg0=:Shoes_StemDotTwirl", "FAE51F5AC49A240384D5B57EA08B1F90:oesTf9AVGgX4FVwWzgm++nQEO0aARyuU5rZa1f6hoFs=:Backpack_InstantGravel", "EBA3BC7F0023BE91CE5EFB7E1BC001A8:MdKbawNIe4qCuGaB4q7+4cy8keyDnJnxZLa7HLC0W4A=:EID_Feral", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:Character_RelayStickBounty", "C5188047D9661347FC4483CCB04ACD4C:TlesZ5LgoEoJqkJaz7N2QB43zNWIJdOpx8rOpsbGC48=", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Pickaxe_SatinCheddar", "C76299772B1BE272260BF3396F83FC1E:uiBDMtwYhdxktbqTrhYkzEZErlBp5gBtkLM+QFDouT4=:Pickaxe_ID_668_ClashVMale1H_5TA18", "C76299772B1BE272260BF3396F83FC1E:uiBDMtwYhdxktbqTrhYkzEZErlBp5gBtkLM+QFDouT4=:Glider_ID_317_VertigoMale_E3F81", "E0FB7B394449CE6450EA90C93D710EB8:NrXwNX6lKuu/kyQuvE74+6Uo04FODoV4ZqxToj/jS6I=:Pickaxe_ID_230_Drift1H", "9078B5331B187C32C649D4B1E5530EEC:l1U0jw2fdShRIHGNl1NYmG8YDAJEUSIfhI46nJgSt30=", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_911_Athena_Commando_F_York_B", "1655272875DB718493BB6B09032657D7:xQLpNTDeYJCcQOUQS2ICyfByvhPU3nC5cfJRbPSugdY=:EID_Survivorsault_NJ7WC", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:EID_RelayStick_Plume", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:Pickaxe_ID_675_TextilePupMale_96JZF", + "202E50F5991EBFA0EEC41A2029847D41:W4RAP4/mEzaF3RTCVuf68agi1gJaiyA7GZ1g/ACkZ+E=:Wheel_HeavyA", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Pear", "545B9777127F4BE242F802C627356B7E:RNI/KvLEXcGoGnk3/AKaYbyJmXMtQl9Zmvl8ErePB4g=:Pickaxe_ID_691_RelishMale_FVCA7", "4EFDA950DA6AA1E6422D2FBF6B89DE85:HDEI+ufmAF1VN2+mYiOFFFDjPVAfkEcmrnyTQh85dmo=:LoadingScreen_Sunburst_KeyArt", "C7623A35411F3D5FBDE2688C7E4A69EB:qAi49mUKsB2dbfbtJWDf3yO2DfRStA+Ed9XgDjC8Zaw=:Glider_ID_109_StreetGoth", + "9E7468047D1781BCB546D5AE215B5073:EYWQj4jWQQnEZ6i1eKfW47bvGqK0ZNt7KFzQO1P6FU8=:Sparks_Drum_TimeSquare", "ECC8CCC7C241C9B739143FE703D69DDA:AvNIyTB6kImt6X7YtGzzIBC3mPIZNXcMn8B9U2B/dx0=:EID_Hoist", "4755D9C0E2D1DE1C09B77DEA8B830471:9tUO5yVhvp+/sp7icZaEDw05nMAdS6bYAWYyfQNsxBc=:Pickaxe_ID_387_DonutCup", "D938886074C83017118B4484AECE11AB:wjHAHm00Vg6n2x5LU91ap0+SFX5ZXXBmax1LyX8Aips=:LSID_294_Alchemy_09U3R", + "764FF921F91FF41FAFBCFB6B899027E9:3tKZAlf6f61vE7KgYzFcFWCbg2W2kZTK38PAqIVSDAs=:Backpack_PastelGlazeGrain", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=", "2E03F4DA95202509D578A5960D35A8A3:UrLxBerp5zeoMJHaXjYqAevNSNP2Jce8sG2zqnvO+NQ=:EID_OilPaint", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:CarSkin_OctaneAW2", "545B9777127F4BE242F802C627356B7E:RNI/KvLEXcGoGnk3/AKaYbyJmXMtQl9Zmvl8ErePB4g=:Pickaxe_ID_690_RelishFemale_DC74M", "7F0F5EB44D49E7563DD5A196121D49E1:CBIvm8gTJLCz6sD05GKbQo6u/Nk4Poni/7wlp724KWc=:BID_146_AnimalJacketsFemale", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=:Wrap_JazzShoes", "D14FDB2BB2FB7746797F25470913BFF1:CQDgIxcNnAoUboQnjafZAYvV7UqX+NefGTXFd3m+oFc=:Glider_ID_327_NucleusMale_55HFK", "D83FAFF508200C47DF03BDFF2F801FEC:s9P7AOkoCuPm/506hyAKzuRaIh0xzV9YZON4oDs7GoY=:BID_665_Jupiter_XD7AK", + "083635DE237C87482DC022635E04BC7E:nq1PRVTTrU7eagnKA/IO5GYjFPF6Xd2mXDYF7YrnumU=:Sparks_Guitar_ShrimpStroll", + "205E83E941E613D6DDF175294CD7B508:W/HdfArXSwvG+c+pTX+3aNoJawu4lPsB+cPWpnMBnZA=:Pickaxe_FreshWave", "B76B4F80113A2C0EBD320FC79DE5F441:Kyys3PlFyTng4GWryKbiN1BQ2eIaJK7dI/ZMNn5LRYE=:EID_Interstellar", "EB16EA013B751792698E05435797C1ED:y9JgD812Io4mbaJ5i533Ts5SSfyXaGM4JyoimjP+i4M=:Pickaxe_ID_183_BaseballBat2018", + "97493B05A5BF87C5D621EBB9F9C93E41:dBxBB+UYD/PjsP2OuJDQdla12emz/y2TpYacnOKgdDI=", + "5E30C7403A702908F7E67AFC6C9C5BF4:idycKoAyRb5uU8ZMsni1k54gQ0Q89xGl4xvp1gyk3ZA=:Pickaxe_FeatherMudLounge", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClass_B", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_A_003_Athena_Commando_F_GlobalFB_C_J4H5J", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:EID_CraneAnchor", + "19FDB99E0C353A75CAF1D0159A566939:s+zGkNSkgLHoJYLtagHc0L5TTyTYcMvb2Yq/Nooq3vM=:Backpack_CoconutShell", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClass_C", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClass_D", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClass_E", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:Pickaxe_ID_696_Grasshopper_Male_24OGH", "56FE93367C8B62ADE2A8A1653077C98B:OevQYyBvnT5vwQhOJhu74k5TNwE6pe4gu6okYYBepGc=:BID_989_CroissantMale", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Wrap_DriedSilk", "8566FD040AC2B245597E11D1F85DB4E5:SEoqoweofxmXfxu848wKn1UJhwU7oQ2w2F0lBst+FnU=:Pickaxe_ID_508_HistorianMale_6BQSW", "738C0E8B5DAB633906DC77FE4C4E48F9:qr1ZfbWRp+uqwBMvEhY1XBj7Sr7SxRsWHN7jqYPaZfU=", "A92DE306E5174C82739D774151D7B661:RF9sTh7l2tp+ypCb/Lp3WeMfBExvk2LSUbim04xsCJo=:LSID_374_GuavaKey_IY0H9", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Backpack_EmeraldGlassStandAlone", + "92034B55AFBF9B8D79879A805EA50D70:P/SfT3IbWKQS5QIE00cDT/qR5omam1FlCNEbmK44Yuo=:Wrap_ElbowChat", + "E9EB23F83112E35700E8BC975D74BADE:y8vbtF2zLfv0NnutlW7lsNrXWQNpEmuEiYb34AYgUQw=:EID_ArmyBunny", "1BEED2926C38652D7287878CB2724D6D:njsOPcs6lEFCruh/YjfHTdcoUJRtIh2hnzHwdkAYQFA=:EID_Viral", "7C469274E430B5E3005EF1799DE618CC:5j5CNw8BI2+kBShT+u7kgw9HyCZ3dOvCMGBO9WScNPQ=:EID_Wayfare", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=", "3E89561331A72D226FBF962DA29DBB82:qzWv2zubDSSrpTt3tKc4ZsReqR3QBKjhU1cGzVe7KH4=:CID_387_Athena_Commando_F_Golf", "B3D2793477E5D467475BE403774360E5:HNj5inGk1/2h9f0r4+SGPPY9t69eOwS6w0XGxpTVOTM=", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_300_Athena_Commando_M_Slither_C_IJ94B", + "C73DB27E321E8B5D3747E2209CED62F2:sL+26G+2SaePYEPgaTi+UwMkAr9RfmVl3QK3fsLfd30=:Pickaxe_CraftGlue", "78FA1DF9C04F25EC129AA57492626563:AZT1/Asa4CuxdTtvLrw9nlEcxfOuoTnLbSLztfs7QQ4=", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:BID_653_Football20_1BS75", "276E65E4041C467319534B14EAEA338A:Ib7KJMP8Q9if+P6x2bYZ0dC538B4LL3J1TcIy3rBlHk=", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_242_Athena_Commando_F_Grasshopper_D_EIQ7X", "96FD474CBA52137DC5ABF658BE17C792:ZLWvbUR7Xow1GUNjC9Mxg7DHVoJAnBr4b9gSzmyFcxU=:BID_862_BigBucksBattleship_1JA5G", + "86ED92FA0E4776D8D3B60F8259B393A9:JOIq5LeFGyI67axw4UZ71Xnjyfw4sPyRVCBoAmy0InM=:Pickaxe_PageTruffle", "BB26302A83A2B42228EF6A731E598360:q6GH+OJutjEXL5wKuJnbLKAan9V/AXRxIkqg6WgSzUU=:Wrap_084_4thofJuly", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Mango", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:Glider_ID_349_GimmickMale_MC92O", + "524E3ABF1DD30667B36C83F283B05195:psHqDFvyUISUa4Vm+z+e8kpQ/bxTybJYkpijcvRjHiY=:Backpack_CafeStove", + "6F9CD990050CE04CE577325C3A6FFC81:eOl/oWxQfbcYxQtjjEyB7SKXGNJLGwrWVT4JgglASZY=:EID_Chorus", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=:Character_ElegantLilyCharm", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_239_Athena_Commando_F_Grasshopper_H6LB7", "204D49F063979C3AF87EF896D074D1CF:SaYFk+GEE7mL4dsgs0v0VGR5ER4TwH8uTNX5XqSglu8=", + "8E48CAF3A86554ADE0DD49326AD1F26B:UGuqIW16b+CxBHFpGPedPqsFisX3KygBTq84QFi4ZEE=", "7F0F5EB44D49E7563DD5A196121D49E1:CBIvm8gTJLCz6sD05GKbQo6u/Nk4Poni/7wlp724KWc=:CID_265_Athena_Commando_F_AnimalJackets", "0A43BFE2D06B46248FC6598C0371D5EC:+U/nWLs0mNQue0yVc9tTaRF+2qrvzdKZyxUR+MzTvMc=:Glider_ID_347_PeachMale", "545BD59335CA43AC4481A621226B4E81:4lYAxO0wSzKarpiMl4b+bWQOjDkXdJKactoCetH65WY=", "419008D696C27533DFEDB08BE4F6C8F8:5I7VZNrdz8oZdzk1TTNCKkZXokilbXLFy7dQPPPlpuo=", + "61BE5430F67E7F312C135EA28BA97B0A:MO50yia4tJE3evToeDO4Z9Hmi0smpo7hPwC6ye+3mbk=:EID_Blacklight", "91C415954BF27B6E43970FB8A75FE8BB:YhHyxIA+Ru33r3pThiWqKNYdvDbL05yXSxKarRuMSxw=:BID_176_NautilusMale", "8566FD040AC2B245597E11D1F85DB4E5:SEoqoweofxmXfxu848wKn1UJhwU7oQ2w2F0lBst+FnU=:Glider_ID_257_Historian_VS0BJ", "22B8405FC3BE153C8148422C3F2D3A8A:d/ATMDztVZxwHLUCwOcJWP1/7oPKKGqbBWUBRNZ6dnM=:BID_837_Dragonfruit_0IZM3", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Backpack_CitrusSpoon", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_942_Athena_Commando_F_Football20_YQUPK", "32F8552040D83320E998654666873931:izPPgPIvrxfBXPaI/LJzO5lxOZtzjOXQJBuk9kPdKe0=:BID_338_StarWalker", + "190EE0858B5F6B5C09F029BCEA7DA1AA:s9BgWW/XUvjz8cZX5mD1tno+F+O/c2SL1w+yYuPOzqI=:Backpack_ApplePound", "7F863227B67DD0D99A7A4BBEE0682666:29bfvaQcZUswF3vrHMntLKfmknWKDf65FCbxbJghisg=", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Backpack_EmeraldGlassPink", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Backpack_GallonBag", "57D2C065461284F546C48C971A44C6D0:EOfb/g0hZdMhd5biYOZR69B/mqPU7X+sgQQrp2gQ/s0=:BID_178_Angel", "AC86B4636DC6A3B6D2DF6DA8B5632796:VHknYzsodjamhC3oVkulL7sMpsRkw9ZcCcSguv9bZSM=", "E4873B9E0B86905E8654D93E9279743E:4xhNKoSupk5mLXYkktaWYWM3NIl1s1iSdmfVIwy9Me0=", + "E0C536FDC9A4B19843DCFD22638CE81A:cirXcwpB+vzrBT5pKkrJYbdGrWRBkCg+UJ+x20yU1J0=", "23213D7D8F739DE37BCA56557073DA51:hmmf08PTLeIAJgxwHIFI131jzcy1SbirW6EzJtm1teM=:BID_979_CactusRockerFemale_IF1QA", "514364A06F8C12C3398C5F63D909EF7D:D8/bj3etFg8eJOVZ26L+pMrsdlTusbgvR2CL4WqKl3E=", "8E1887D55A60F69B33B234242FF49653:YofZaW+CRl0jhVhkp9z2CQWhTPwyjQ6dbHtISkLDfVU=:Glider_ID_367_AlfredoMale", + "B3A4B83DA3274522D4B9F117DCF9A0B3:y5n7vfr0uucr+psZzb2F3g45pWUsv3i3j/M6bl78Z9A=", "DE4CBA7A27B818D6B299767036C671A9:o7axeOYDdjXZ4MTWM4Io4XRNfQG2WH9qwPvBSJk8vJM=:BID_A_064_ApexWild_RedMale", + "083635DE237C87482DC022635E04BC7E:nq1PRVTTrU7eagnKA/IO5GYjFPF6Xd2mXDYF7YrnumU=:EID_ShrimpStroll", + "1779D69116EC781A474EAD25440F4688:ld5vNZx7VDC5TOeZLfSgf1e9d6w9EC5j21Kakv5IOWo=:Shoes_PacketCrescentFrost", "E28AF2E3BB7EBBB69D962A15879E696E:hJE3fnZPwRmG8XIw+RJvVsCh9dOHDD82VAhvMbi+nvs=:Character_DualParadox", "34DD24ED0CE62244E7FFD27EF4C29EB5:jTgMUc1ciLKwXF/PqyFJl6s9Iw5SXYHKiSThOQhG5TE=:Pickaxe_ID_735_FoeMale_2T3KB", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Wrap_OliveStomp", "8E1887D55A60F69B33B234242FF49653:YofZaW+CRl0jhVhkp9z2CQWhTPwyjQ6dbHtISkLDfVU=:EID_Alfredo", + "C76B70EC836344CCFB8762C4747B4263:U+UBLfYWkT5IetUd9DrotBKrk8kzphj6Xd0FNvlv3kA=:EID_Dignified", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_306_Athena_Commando_F_Slither_D_I6D2O", + "769BE2DF780774E9A97E451EFB71A763:yJu5g5LuK4O/vlTfqxzKhMNFtPNu8AfHz7/KzEOIHXY=", "A9AFB4A346420DB1399A2FB2065528F5:Zjzo+CaLNmCygplzQo2wUL4LT33DEiL6qZWE2R0EYMg=", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:Pickaxe_ID_720_RustyBoltMale_UZ5E5", "3F21B0363A2CF6D94F7D789118D73595:Eq7VViwD0CoHAE0Y2grOZ/FZ5xGPjC8g78EpaH0385w=", "1AABA3FE6C5410551302A08A3787F5AA:o7Dsys2BQuUgASRBM63wL29ULpkCEp5Q5JNgzvoKl1w=", "919FDAB2FDB531820404333B27DC7B06:W9Csp0y6agsgcQXlRGvYUpPGPImNdFfBsZ8yQoUEdGg=:BID_296_Sarong", "A7D34E80FA70CDD2F367DBEF93B98467:KVErbMXsQqx7dxrZp5Ara4OVlA17pc29E2SZlFNipPU=:BID_283_StormSoldier", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=", "6D85E82539341B90944E84FFAAD872FB:mAiBk7KbE2Dnr+yVFyJK1yAwv2eWb+yANFH0z2krQkw=:BID_299_BriteBomberSummer", + "1EFA43A2FEDB492EA32BB6AF50E8B0CA:ukW+ECABl8sv9qFUdpckdqW6IRsZAPnPEWSu6bsbCYs=:Pickaxe_AccentWall", "8D44654E9EA2AAC35E489476B1948E58:Dwb/irSIIGd3tLLPEP5OqJY1D4KfjdP4+uP4+Ht4YOo=:Wrap_ShinyStar", "2FF619685EC983B800018ECBFF377ABB:Dn5ZlXEhBAhXP0RbkDskEQwOK4RUKTwAIls6cvVOr0g=:EID_SpeedRun", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_303_Athena_Commando_F_Slither_D0YX9", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:Backpack_AvocadoSeal", + "2DCF5899864B58847F7721F5BC6CC7B2:0p6RYJMTG+ET3tlmONyr92cZnYnz+AV01JZgOtcemS0=:Wheel_AventurineAnimated", "4C3B1FC20956AE8C3C29A85446D013F4:dVksVi55yMPvgmuA2rjvlyDlySrQOK8wmH3aa69wtZo=:LSID_432_SCRN_Ultralight", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:CID_446_Athena_Commando_M_BannerA", "23213D7D8F739DE37BCA56557073DA51:hmmf08PTLeIAJgxwHIFI131jzcy1SbirW6EzJtm1teM=:Pickaxe_ID_777_CactusRockerFemale", "54FD9ABD65879452DCB8CE11C1D7F1AF:nV0Vm4NCBl+MkGX8wiqfFrg0viDriL3I2xc4KS7n7fg=:CID_421_Athena_Commando_M_MaskedWarrior", + "083635DE237C87482DC022635E04BC7E:nq1PRVTTrU7eagnKA/IO5GYjFPF6Xd2mXDYF7YrnumU=:Character_ShrimpStroll", "958DC719715C145004E1E028E72464D0:ZTCrQKaSpw5dAyqyW/jGz+KF2DlvSX8wCW5/4dhdFT0=:Backpack_RedOasis", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:EID_WarmShade", "E1B1A5908EF6377D7FB29F776486A6A0:qaZB3Q+6kKTtlO4aGWBsnjSxCwX3kmr8oOF/2QDZ2qc=:EID_BasilStrong", "3E89561331A72D226FBF962DA29DBB82:qzWv2zubDSSrpTt3tKc4ZsReqR3QBKjhU1cGzVe7KH4=:Pickaxe_ID_190_GolfClub", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Sparks_Keytar_MotorMonth", "726DD9BDA97CE92DFF162668027518BE:/QdzaWcoVhInSz0Oa0qk+NV3XxRt9WlXwcAu766Y6aY=", "AF3080C00CB8CB301C167B00E9671CD4:wLmQDoGeYBN8Og/IMDoGxuuQNy7M+RQkKtajSZiOebE=:BID_710_SmallFry_GDE1J", + "ABA511C2F9B2E385A7D190A7E0C16DE4:KB/3eQhFSphHTwbPcSL+2ZZUJjbZcmIHssO8nNxe6oQ=:Wheel_RL168", "AF3080C00CB8CB301C167B00E9671CD4:wLmQDoGeYBN8Og/IMDoGxuuQNy7M+RQkKtajSZiOebE=:Pickaxe_ID_558_SmallFryMale_YBD34", + "467EBA8364CE2AA18ADFBF79DB7BE920:7HxCMh46wI/zn/MJiV2iOTobl6zqkEc7OYKECW+FyNY=:Pickaxe_StoneLion", + "190EE0858B5F6B5C09F029BCEA7DA1AA:s9BgWW/XUvjz8cZX5mD1tno+F+O/c2SL1w+yYuPOzqI=:Pickaxe_WormChalk", + "0A6F8755332638E42FC052470B3BD065:OGqX2AuHNDfNO1iagEg6fwOr3Ib0s8/5iOBLnDc0vSE=:CID_A_227_Athena_Commando_F_BistroAstronaut_JJLK5", "59AF6C46ABB214024067564F69D6EA37:NtUgzeFVvkbyZQGRVdteWV61HjED9MXquqlVKHo3c/M=:Glider_ID_238_Soy_RWO5D", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Backpack_ClayPlug", "4009CB877085F3B3B0D76A686465A140:gMLJXUbFcIrqqUlAuoMI1b27KdWHBVJJeJWdYV1Iiro=:Glider_ID_276_Kepler_BEUUP", "C811FB0357FAC2A923E8DE46507A2D92:IjM7BWHvhr+4YcndrbmbTh96802H/CWrs364yB1Mg7w=", "B229884F839295B4B9EDC380B045C64B:SVmPvZenzQ5Si17i8daUFyKoOGDtaH4YZtsF1s2XkxE=:BID_745_BuffCatComic_AB1AX", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:Backpack_WeaveHarbor", + "BE857852220784849F13E1F3B6448051:Sc+vT6GLgKXPYnqJdDMF+iJf3GDMq4Sz4x1lxfD9B04=:EID_Enchant", + "8207433B768D45F10DF899C58D4DA5A8:yz6MZM2DXTWBVTZSpjjtaaAk2yI3A5Ivtb9alGEMUZA=:EID_AlmondSplash", + "BE20AAF89FE897368E52AAA193DEEB53:jHRZho9v4IKzFzk51RD0nAVFCZ27vIwcstPkdQeSupc=", "0242DBD83576CC7E4A6F228D02216147:Yfycn3jciR/FCYQx42W2GMzMp3pA3rgbL6WnVmJStxQ=:EID_Tonal_51QI9", "B0894F58B3D7DEA37D3432AB32B78EB4:gKD8R847p9z0mbZ/euClocy1Z9Gg1daZjk/gDqc34a4=:BID_950_Solstice_APTB0", "01FC97F8787B82E027EC64661E0D36AB:Mh1l2LJ3YrgaZtg7sRTd8XeBkVcyA3i089gZKkTr1gM=:Wrap_466_CactusDancer_A", + "F1149C7FD94E0FDD1D3F42659E99D52D:mO7GpfM8ZBOjTIwAjtvwDL2s7yhIi0lK9ICP4B03elI=:EID_Metronome", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Character_WarmShadeWagon", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Apple", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Character_CraneAnchor", + "691EE5E7D12D2AAB8094DC5C5C3294EA:HfnFjC+/ESL7w3qqsV7lXe+/SGQARJInAJ2xHXZvHJA=:CarSkin_NerdBig01", + "9E7468047D1781BCB546D5AE215B5073:EYWQj4jWQQnEZ6i1eKfW47bvGqK0ZNt7KFzQO1P6FU8=:Sparks_Guitar_TimeSquare", "DFE6C0504C061EEF0E77A43EE3B613E6:ympNAeN/2VbM7CJbFyVv2stK9oBU4htW//P5CMAMIu8=", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:MusicPack_212_WeaveHarbor", "EDF724493161095DB54E9613C243A355:Yp7dsOYO778G7uRZNYhGag2diT70vhu2hAWvkzvtHjg=:BID_A_002_IndigoMale", "C97E930BC95DC795F4416A7B93E3B9CC:KxRPbXqD3ytwLLbZMbZmn+G+gjwOUljg/7HPjj8xP0o=", "713D64294CD1C40F60DEEB805E3A2D87:CJOOHtEX7q4CELcZ96oZjrmSZd7pyJ2fMaFX912GDl8=:BID_193_TeriyakiFishMale", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_085_Athena_Commando_F_Hardwood_K7ZZ1", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=:EID_JazzShoes", + "06381A8251E28744D95CD28E6C038AFB:8bDBEnhD2eZ9h8j8E/dfJ0ZSH8DVB0Dm+rZdVMYivlE=:Character_SnailAisle", "599668A98461E4D89196E0189C32C4D2:8MqQjC52vWK/VwX4SfYC1wu9eiUTXdqq/xWODcW9dQ4=:CID_468_Athena_Commando_F_TennisWhite", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:Wrap_WeaveHarbor", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Wrap_SweetLetter", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_088_Athena_Commando_F_Hardwood_D_WPHX2", "4EFDA950DA6AA1E6422D2FBF6B89DE85:HDEI+ufmAF1VN2+mYiOFFFDjPVAfkEcmrnyTQh85dmo=:Wrap_SunBurst", "44DB36B2D2B3854669780458D2FE48C4:gtl0smAMRKg8d9TdDH47lUOYCygKzbAPA6/HaXLWy94=:Season17_Magesty_Backbling_Schedule", @@ -248,6 +388,7 @@ "BC3890EAABBF03778EE82AD7DD4F9C12:RvtEdiKkxLJDnXKUaUK933vzLK04veYzbdp8yN8wmxY=:BID_A_034_ChiselMale", "5B26536B2ACB973C651C0D1A285C0E37:n4j7xWZ1HfwSGb9ixE7YMFyRsTjl3gjJVDZJj7Wy4rs=:CID_397_Athena_Commando_F_TreasureHunterFashion", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_083_Athena_Commando_M_Hardwood_D_7S0PN", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:ID_Booster_AW", "F33B69585B65C333655C545A038BCEE5:0+gUoAUkiBbY5uqO9rIehUDkvrr/PY3vBY16AMHQASw=", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_084_Athena_Commando_M_Hardwood_E_II9YS", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:BID_A_031_EnsembleFemale", @@ -257,23 +398,37 @@ "B0ACC6254D42350D124727B035C9CE55:ZDFVEa7yau61hc1ba5xNGtYdZ+yif7XgE79BBWIlPJ0=:CID_299_Athena_Commando_M_SnowNinja", "B229884F839295B4B9EDC380B045C64B:SVmPvZenzQ5Si17i8daUFyKoOGDtaH4YZtsF1s2XkxE=:LSID_287_BuffCatComic_JBE9O", "F71D60AE5231E90CEA7F53D90DC4F007:ver8B06IS0up7tNYy03zkhCl+CrTl3czgmXPYYONcM8=", + "9286B7920158C7D54CF5E6E01EA9266F:NMUdgZEcMNkbtpUJVfIHo8YgwMSNqIqbYFrNyK87Glk=:EID_Ordinary", + "7852B2522C39A15D1933661727D2D795:T4Nv2SmLOJrEymfXuD4o2cirnHSImxd/7y3u/q9S8ho=", "8DCAE39C7D9690E19F52655F02C613B2:ZZHbiVsbXquLlrtNVHtryLS3Vd1Ego8/8tlDpeUCgfc=:Pickaxe_ID_252_MascotMilitiaTomato", "59AF6C46ABB214024067564F69D6EA37:NtUgzeFVvkbyZQGRVdteWV61HjED9MXquqlVKHo3c/M=", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:EID_WeaveHarbor", + "205E83E941E613D6DDF175294CD7B508:W/HdfArXSwvG+c+pTX+3aNoJawu4lPsB+cPWpnMBnZA=:Pickaxe_FreshWave", "9261CD0F921EAA3CD6AA8C0716FB042B:W+yzeWWxWnA530lwV8nLi2BE+TD5MCXS11th7UphmPQ=:BID_689_TyphoonRobot_SMLZ7", "91C415954BF27B6E43970FB8A75FE8BB:YhHyxIA+Ru33r3pThiWqKNYdvDbL05yXSxKarRuMSxw=:Pickaxe_ID_131_Nautilus", "BA490514EFDA436A2679E381BD558AA3:3KBKxBOi/52H0feJ/ijKxRHk+lF1zID0uIpjd0T7/Bc=:EID_Haste1_T98Z9", + "19FDB99E0C353A75CAF1D0159A566939:s+zGkNSkgLHoJYLtagHc0L5TTyTYcMvb2Yq/Nooq3vM=:EID_CoconutShell", + "8BCF8182A37A4EE321F5078954A75122:wLfDsgM7jhjuvKHr3zFxWs4pDn12nRiG4RVQfuNSTuM=", "32F8552040D83320E998654666873931:izPPgPIvrxfBXPaI/LJzO5lxOZtzjOXQJBuk9kPdKe0=:Pickaxe_ID_253_StarWalker", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:Pickaxe_AvocadoSeal", "5581F333809DD14FA591F17B6C071687:/gEEJhUVQMVyFP7JR0jT4RM99Wj7hnIp2ZitAVdwAYc=", "45261C72DCA170BBF0BDB129B9FC0BAF:5db2NWibvzXoFGVIbg//HklLwxuGUFWO7tKGPStOM2U=:EID_SecretSplit_7FOGY", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:EID_ClayPlug_Graffiti", "DC060EA83FE6F9729B19150E40C7987E:zW3d3QhtvhE+q3x/P7/BA9JvyoruVmeACdKt6RPxyLY=:LSID_421_SCRN_JourneyMentor", "A7FAF0883F9147F93079F3A40413A83C:+wNde9ex5o3zvdjqgJUGhqcxmecYiQW3W1QuO00NUbc=", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Pickaxe_GallonBag", "5A1170F589134C4D68AAA2B5AA6EDA69:bfro7s6Qtde/H7C4zc6MJdpua1mhem8HywLluxBLDrg=", + "F1FD75AEB8137DD7B45C83780192AA98:KnIlVKiACju6lhHdlNobfe7PJKazk1XNNC9GNn+W4qQ=:Pickaxe_BeetTread", "E4C183B0EF31ADF061F175068046568E:AF+fNwseLnjCsPKzbFkYDkZE4gyYfGEaifyJjdsMjp0=", + "276D93712D1C6092C442D170B8956002:1TvCuSDu3VMY50mtOZcxQbN5AuHOE9v+omoAz4p7hpw=:EID_Exquisite", "65000C27C3BC5B9B904A0D20050D6B36:JFwQi7tWgJDr+E4GzYU/rgasjjk+1BKRB/N88e7rVvI=", "9A3C083767A87B837556F6F97B75999C:NsRKnsTck7rKidUd4YH7UXflwaxXSN6RlIOGqAdoV5k=:Backpack_GalaxyLevel", + "2830AEF5C09E976B74EE1E194E3B988B:UduuLiZnBhH43ymHQqejG91JFUIoYCydpUpQ6SWBWgY=", "99B0F5AFB03FFA1BC3B8AFF75267CAD2:d4GffGn7ENqL9SpO5wnhKZzqzpr8S/4LQS2P+QD2wy4=", + "47F6751F0EE3E8716C1B9DBC9796AAE7:1WNIILYMO4iCo2qkjP68IKxdCJNLjf1D98y3Ke/c9Gw=:EID_Reverie", "457F39EA51FB4C723B442810750CDA4A:V3d05mcuS4uXMBRpy63TIZDLt5hg9njVD0SGhZDsmBw=:EID_Sahara", "63722D44ECCA0F4178B85F5A6BC4C31B:j42UL0bmfBkli6Aj92wWABwFby5rAplP/Ac6nh9kRvA=:EID_Vivid_I434X", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=:Backpack_JazzShoes", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_938_Athena_Commando_M_Football20_B_I18W6", "0D8B24BCF7F9C0293FFE1264A5D05613:v1sCSrsgI0QbNZ+4v5lllwW1n7M9dagX4GsxY7/oR/4=:Backpack_SpeedDialBattle", "44DB36B2D2B3854669780458D2FE48C4:gtl0smAMRKg8d9TdDH47lUOYCygKzbAPA6/HaXLWy94=:EID_Majesty_49JWY", @@ -281,127 +436,209 @@ "59AF6C46ABB214024067564F69D6EA37:NtUgzeFVvkbyZQGRVdteWV61HjED9MXquqlVKHo3c/M=:Pickaxe_ID_462_Soy_4CW52", "36351B933FFCFF1746737649E9806CF9:2ZtfFqHREh2sKsMYN23yW+2Sd0OSNN5CHGd/qlXVd7k=:LoadingScreen_TigerRoot", "F3A99CD0D4F58EECEEB0D112506AD846:ZZtCRPcKk6itVryDavp7uZFIXiZF5CW0O9b+8Zt2Oag=:LSID_328_Quarrel_K4C12", + "1269E6F7E620736515D3F57CE4B2938A:P+cnpG9HbjrhRGcxCH+FD5C19cSQij2V7pHTsbVfi/Q=:Character_SteakSting", + "2E905754493650DF88C8E97682EB82CC:mi7TaYylDcfidaBKpF+rHEU9HuMOHmVqhiuag4C8KSU=:CarSkin_OctaneSticky01", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:Glider_ID_316_TextileMale_3S90R", "02421097082555483CA9524F79EF7687:e9wZT5/2KHmpbw6KjR8u4uo3iG00O92+PAZMbk09a3w=:BID_545_RenegadeRaiderFire", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Character_BraveBuildSuper", + "52366B48F1048E512A4ADB69B1830522:4/yBC527LoHOBvjPVZZOG3vqIFRZMYJKlKuD1OgYK9Q=", "2981826DE79FF29E18E71842E259C429:8ZvDzw8wgo2ogkeqTm4pYe6fh7ghrOxdZXEwkpaPGOU=", "D49757E2D55451A0D5B341906FE2ABE4:PWMwnjgi/wUDV+yxg02QsU33jA529fxVTRHyqnkv21c=:EID_AshtonSaltLake", "02743CF33556232CE2CDE4BAAE108E2B:fEeB1cPrmwILnnMkELOaIMVfGJXixlOZSzby0xhKPHk=", "B1B800E199A6D4649287C11AE89F67CA:3udFXffIw3c7eM5hljF5mJQA36FbW2PeF8Gx1TcD1vc=:Pickaxe_ID_201_Swashbuckler", "F2E3A44428F24B0E4F481938A8E3D8EE:Vgb58eI7kGPp+Ecr8lhE2RMoKeCLFG0sWAEugWV295A=:LSID_305_Downpour_CHB8O", + "D0707546203A02CE99300D9F13D18EF7:fNZJ7mGTDauIUjs13TDKcb0dXoFo77oArVEGU/nuM08=:EID_Fantasy", "23280A6FC0902B6420BB82522AE16D2C:C7o6m2vJJY+XWKd0t1YLBPVLYCMgNbt10d/itx5Wjnc=", + "183F391FC33450CB879EE601584DBD34:It1/5uQ3GeW9HOMVAnKFMsnoYD3r5QSpru/RTUf2dIY=:Backpack_BikeMold", "6782F1D85E7DFD1D835C9B7B2A461001:zwni3LZXkLjSCnwE43DH3DqME9Z3zpCt2XOnx0VCOg0=:Pickaxe_LastVoiceSteel", "DC953387B24FC2DCBECCD2CCF61BB973:GT4tz78+PbkMtjcHnlkhmwLG7lQAr7EwMEWIgn59PV0=", "BF344823BEE88FA8760A410311A30150:mcfE7CGJQLRE5dWZTCNPCCPgSBV7CMLl6lvpF+nzqzw=:EID_Astral", + "2BEE5F951D6A3AA790943B18CE43C474:fgujz2DrxsPG/SILcUFj8zQtKe4AQcKuKUqxX3VXbBw=:EID_Disband", + "AB2F922860753269B1C2335CE5C0DD5D:/gjkRNAVhMsWlhPkX61LzAkKFMqdPyc9nNGgu+ahHd8=", + "87F5E8CBD1402EA8F4F60FD1458198A4:MkgYnN8uV3YhMqTVYpCvc1SuQ2AGuOBMv/9mrICBjQY=:EID_Scrolls", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=AthenaCharacter:JazzShoes", "8AE930B0D623C1C2B3926C52ECF6250B:uwtZv87e9DU/Z1ZvYB7Pv4TdRQ4/ZRT9nYJCwYSmlbI=", "CBFF239A1792F25920D863F223368B54:J3N3cUH3M0R3uyzkE0qVK/SouxC/X6VEswcoWb6ViL8=:Pickaxe_ID_215_Pug", "95C6C2B37E1D15D60BB5C20D9D47BA31:exdH0xe2v+2t1wyoXpZGLX+iGDIdRxcQ6BG9iqi07Lo=:Pickaxe_ID_808_NobleMale", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_235_Athena_Commando_M_Grasshopper_B_RHQUY", "6838E4BB35C0449D4F66F7E92A960D1F:KOKH3JA+OMliB+f17Pd8OFEtooaCZjehz3CvfqaSbtU=", "389F29133F5BF2F060F614459FB40A33:QJeT6Tn8kANHABraLv3bT4U+4DU9axx8n7AjG97WvbE=:EID_PrivateJet", + "0C81D16F6CF41C862D0B097DBE5E624A:qIzymfmYIWAQbAhalU2MQOR6vwmj42xHgtW41rhIev4=", + "681CB2E1E19D79D2FF4B67F5B42777F8:I40wNxVWn0cEVK0JlL+G+g9YdcsHNZvDQnsCtSyZzzc=:EID_Meander", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Wrap_SweetLetter", + "ABA511C2F9B2E385A7D190A7E0C16DE4:KB/3eQhFSphHTwbPcSL+2ZZUJjbZcmIHssO8nNxe6oQ=:CarBody_Wurst", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=:Sparks_Mic_ElegantLily_Plush", "54746F2A874802B87CC5E9307EA76399:nOaYcOb6cOggqwc+mRiJ7LJEs0qvaiMhxH/yWXou+Q4=:EID_LimaBean", "AC74E15ED1B7D4C09EE43D611C96282F:AE5miomI93bx4PzortiojpqTb928k7cf1PqC6YPjvz4=:EID_Prance", "CCFB247DE6ED8DB4856E039A5AE681B8:Z8ixoqcCEiFqUH1qec+yUNQTP1+D1xQjYw6FDpUQa9c=:EID_RhymeLock_5B2Y3", + "691EE5E7D12D2AAB8094DC5C5C3294EA:HfnFjC+/ESL7w3qqsV7lXe+/SGQARJInAJ2xHXZvHJA=:Wheel_RL176", "B7E28BEF6DBEF8710E68B66900B42430:sHtuRWXH9yrWnwjLhWISF+7+FWXyahhu96R9nTbjlSw=:EID_BankNotes", "82669F5A2F9B703D1A6BEA3BCB922D7D:Leu9rrDPaqZd3izIU+IKpFcP/NNcqSncLkV2lapQL6k=", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_BreathTaleFreesia", "772E01C212E9A77A501AF954ADA90B09:nQ4i6bbmbGMzcq8iyjoM/BGUbX2DSIJRAZ96/qaOf/Y=:Pickaxe_ID_744_SleekGlassesMale_ID69U", "7EE5B905919FC30BA533A9B72266C37D:kAD28wIO613FRtg5cfGz+jb0Ofed2l3NonVGSmeqCAU=", "F33B69585B65C333655C545A038BCEE5:0+gUoAUkiBbY5uqO9rIehUDkvrr/PY3vBY16AMHQASw=:Glider_StallionSmoke", "476EE53C2EAA24FD1950A9875FB4CF59:LQMwgWwsoSqGyYbBouYaMaN8NZ38Vy5r3Tqa7KA71oQ=:Backpack_FallValleyBlink", "605CA1F4F68E09A4A0784DE3D6E9FB88:TKaxKxc1yoVFdUqQNWdG3bofE78hwuma5x5Go2dnLxQ=:Character_IonVial", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Character_FreeDrive", "566C4D92AF66F45DF5E2D7EB43CC27AE:EuAYwU5tQBXzGoSj5BMc7S5yFfe9wZ2qrzx/hIHpnqw=:Pickaxe_ID_479_LunchBox1H", "EBFE6788D367D741AF0A4FD098CDFD39:FAeJTGyT49P+dQOmKx+lMYVAxu7qtIPlqSaLAR85zqI=:EID_AssassinVest", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:BID_428_GalileoFerry_28UZ3", "907E8D93213A838738E26D30AE3A5DCB:Is1Z/2TjgM6jWr9R/zd1E4bjKhDnWmae7rjW+UIU5Yc=", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Lime", + "EBE32FA2FA482E04BAAA6F78C6A15AAB:dkUSQryp9BwJsGiQtQEIn5JJ3wQyBwxlsKtLxx9GKOQ=:EID_Harmony", "FA393ED7DFD20657B9C8659CB0295F64:G5wmtVhL0E8/+gpxHPK3HGJJ5RvfoWyeYrLJ3Awm9f4=", + "5F65B98450A9DB7EAD3BD81AFC3B9247:YA6EKCKE+TIHonXuvS4D3sEGCXfyaDTCsWBM10VADL4=:EID_Affection", + "C3199640B42F4B786E91D715E3EE5B33:ClDViabpHKcVhqBRrZTgcPMg9jZ9d2+coyfba7ARySY=", "3DFEA395156D835B86EB22801411ED08:cG8Q2VOqa9d+9J4QEvdBWe5hjbIayC4HtRp7svIWZ9g=", "4F365EB12B55EB9A6BDD99DFC3D02E61:JFApzAook6DV1rLMngEwoo0pprP17X6gjpNc79NQ43A=", + "1398A4C2E6C3954EDDC49F85C5AB251B:qF0+04jSaU0kgws/RigbWpwnyPQMDnK+4Vf4G0tmTns=", "6A2047910081947B9A5DCF542A9AEBE5:V/jMTWL+zbqeIlKCE9+SM3+X69aYbt/cN0+G1D0GBQU=", "23213D7D8F739DE37BCA56557073DA51:hmmf08PTLeIAJgxwHIFI131jzcy1SbirW6EzJtm1teM=:Wrap_460_CactusRocker_92JZ7", "E3D0A604B93651DDC6779B14F21D0FDA:8gPR3gZwEJxfkZBkXk0QAlpnJ7q5mXzVc0DN3lzpJ5k=:Pickaxe_ID_114_BadassCowboyCowSkull", "A6130F4077B928D41D298463C61C0F34:oW3GkVlIb8uiNl0CzqrwVZeGfnEujp2O3O3tnw2zFOs=:Wrap_094_Watermelon", "772E01C212E9A77A501AF954ADA90B09:nQ4i6bbmbGMzcq8iyjoM/BGUbX2DSIJRAZ96/qaOf/Y=:Pickaxe_ID_745_SleekMale_ECRL0", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=", + "8B57E50789D21E269BDBE46184F88FA0:G4bUrNa7X6RXd3/vvJyRLQr7dhSiPo2+yuKrp24RXN0=", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:BID_A_030_EnsembleMaskMale", "91C415954BF27B6E43970FB8A75FE8BB:YhHyxIA+Ru33r3pThiWqKNYdvDbL05yXSxKarRuMSxw=:BID_177_NautilusFemale", + "738B025296E10AD69AE5FDA250CE65FF:2UmzdDepl8Noo+LAWkt/i7be+QvJTIsusqDRZsx8N9I=:EID_Outburst", + "B6CDA53BEEC38B55A44684D55878317A:aewwsijzR75hG3vv58c/qYtIOrEExOdlB0OKcCQzAGg=:EID_Reveal", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:EID_CraneAnchor", "4E7938F1FAC98BDF378823116712AC7A:jbZVgprILTQomUdGeJF0PsAFAJxsSCs5cKcXweZMAg0=:LSID_273_Tar_ITJ9S", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:EID_CattleJar", "44DB36B2D2B3854669780458D2FE48C4:gtl0smAMRKg8d9TdDH47lUOYCygKzbAPA6/HaXLWy94=", "D49757E2D55451A0D5B341906FE2ABE4:PWMwnjgi/wUDV+yxg02QsU33jA529fxVTRHyqnkv21c=:Pickaxe_ID_203_AshtonSaltLake", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:Glider_ID_186_GalileoFerry_48L4V", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:BID_429_GalileoRocket_ZD0AF", "F3A99CD0D4F58EECEEB0D112506AD846:ZZtCRPcKk6itVryDavp7uZFIXiZF5CW0O9b+8Zt2Oag=:Glider_ID_305_QuarrelMale_ZTHTQ", + "3B1AD83235D86EC02FA1651C22F2B35D:qHAbjz5DR0EmtQ14jpR7NZVEwyZEBSUQwDvOOHYM2xs=:EID_Apollo", + "EB06D2E764EF6E03658811E0A1B7BBC9:NpTV+Nnmy/6QFWgc+h69utcgLFFfxvH9nKF9Tm3iMng=:EID_Canine", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:BID_955_Trey_18FU6", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_909_Athena_Commando_M_York_E", + "58B5E58B5C848D31BC6A2F3F3514879E:feweaybOhbdoBVX5cGTOqlx4jf3GdPmKanEfcm3tuUM=", "14AADCCB14231F83A0FF5E13EEF676AD:E3AdIm3VavVg7FwK7HBEFr6e3sE52IUL6rZjGFm9QCo=:EID_Nimble", "510BE1093533EDED92752C0B90A80895:vaI8rYMUPwx+M61tvfJ0pf+dMK/96pnzKOQluAPmjU0=:CID_424_Athena_Commando_M_Vigilante", "4C3B1FC20956AE8C3C29A85446D013F4:dVksVi55yMPvgmuA2rjvlyDlySrQOK8wmH3aa69wtZo=:EID_Ultralight", "45261C72DCA170BBF0BDB129B9FC0BAF:5db2NWibvzXoFGVIbg//HklLwxuGUFWO7tKGPStOM2U=:EID_SecretSlash_UJT33", "F60CFFFA32CF6A877B50DA7F0A88326E:OWIopbB4fxaobofPI9lF9hn6BPG9NVLp4Od61uQppfo=:Pickaxe_ID_198_BountyBunny", + "38520288A2C9F2B156356BC34A111E4A:Jb3sLKsxsJwin+lQ4U7r7N9lOFN6zAUiCso7mMS5s+Q=:Wheel_RL160Red", "B4BE2A5487426AFF06CB7089EA9B75BE:w7Hbt5PsQ4MDg9EjvOU8WdtL/BrWxZNp9NM2UrHSjRg=", "7C469274E430B5E3005EF1799DE618CC:5j5CNw8BI2+kBShT+u7kgw9HyCZ3dOvCMGBO9WScNPQ=:Pickaxe_ID_848_WayfareFemale", + "73D899AB236474741E0B023F2B00FD88:CkZQjqgV2rS+Uwf/00TbN+o74EkwHmOdhjWxRLLbAqY=:Wrap_HydroBottle", + "06381A8251E28744D95CD28E6C038AFB:8bDBEnhD2eZ9h8j8E/dfJ0ZSH8DVB0Dm+rZdVMYivlE=:Pickaxe_SnailAisle", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:ID_Booster_AW", "E3D0A604B93651DDC6779B14F21D0FDA:8gPR3gZwEJxfkZBkXk0QAlpnJ7q5mXzVc0DN3lzpJ5k=:BID_329_WildWestFemale", "6EA156BE3D18E1D649D7D4B3F8C0FACA:qAKD9oM8u4IvUcKbReHTMaLg7GtHLBcnmz8++vwwB6o=", "F33B69585B65C333655C545A038BCEE5:0+gUoAUkiBbY5uqO9rIehUDkvrr/PY3vBY16AMHQASw=:LoadingScreen_Stallion", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=", + "705A823F504C8403CEDC4051093E32DF:aJco7vRYJ1b6DeNVS3RWtS9w333O6L+4RK0iU+zYRM8=:EID_Soar", + "6204514DD102F27477CE0D7A811CBBE5:oCjlylDEodHnTy9bxZ1KT99Dfbkhsjw839ymo1O91uU=:EID_Distraught", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:EID_ClayPlug", "63516700C5CFA6F1BE71B29214957E33:eR9Otw83jJyrj808CkqElVYzlXztuc14/u2pDtPtooQ=:Glider_ID_155_Jellyfish", + "003C8A31FF60E8C3BDBF4FB76A7CC4B8:LAKZR/gRSm44vZpNg9z39srsStFM7n68AVmC/yYDNSM=:CarSkin_OctaneKitty", "44DB36B2D2B3854669780458D2FE48C4:gtl0smAMRKg8d9TdDH47lUOYCygKzbAPA6/HaXLWy94=:BID_801_MajestyTaco_FFH31", + "19FDB99E0C353A75CAF1D0159A566939:s+zGkNSkgLHoJYLtagHc0L5TTyTYcMvb2Yq/Nooq3vM=:Pickaxe_FineCheek", "34DD24ED0CE62244E7FFD27EF4C29EB5:jTgMUc1ciLKwXF/PqyFJl6s9Iw5SXYHKiSThOQhG5TE=:Glider_ID_341_FoeMale_P8JE8", + "605624BEED560EAFCF45CAD7E2FB4E48:kfYhFrpDNLuCuE016d+F3Oh0NAcQl+TJbb/TFRfEjy4=", + "C4982170B633DB6D2FE340A488EE425B:1XxlJtR4sc6vP0MpkwKrwCrHHTAi+GP2Pu5Az7yftcs=", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Sparks_Keytar_MotorMonth", "5E15C5486CE8E539552D4D3E7682F9E2:+L/tTz+woDFZJEvtxfq8m8tNI1R72sYK7rnYr7sHTis=:BID_311_Multibot", + "9B4BD31E84E9FBD35CF3A63A1FD4B57A:OAG5UzEWtlrNZE+mjpZbHFtFs61OdIrgsdeiQYbUZsM=:EID_Trajectory", + "5F74F41AAAD2E45F585927189BFC6797:Cs/gvSZBhTpl66f9JMuxraYVIHgClmDD0h9E56GwSLw=:EID_BeachBreak", + "18657B021FD5011618877BD5D709EB51:6tLEm1BTY8+Go2kUChsjNEQkZJcsN31oLw3AorwxptQ=:Backpack_SlowBurn", "2A12750AF48FB5468105F255DC537CC1:lKjAansupIjoXjT3/0vH9XeOzVp9S+fBGtyP90Gve60=", + "205E83E941E613D6DDF175294CD7B508:W/HdfArXSwvG+c+pTX+3aNoJawu4lPsB+cPWpnMBnZA=:EID_FlowerVase", + "C4982170B633DB6D2FE340A488EE425B:1XxlJtR4sc6vP0MpkwKrwCrHHTAi+GP2Pu5Az7yftcs=", "2F426D86C7E7EDE779E8D62108AB49F4:zVh0R7wazvQUgucmS9AYYNnN2g+oFYv8ZMlhD3WnH0U=:EID_Hurrah", + "1E8F4857F5C74E2E544D020B8594D855:OmR65gZfMr/YaejCOzL/ym2YAcuLn/zSNFTJLdTb1/g=:Pickaxe_MustardToast", "591DF838AC4B3A6350E40E026B26D5C0:MBvGoHxJQBTxCm2V82s2yHqRWPsYdFyj8xKUhFsUkyE=:CID_745_Athena_Commando_M_RavenQuill", + "CB64FB9BB49C7D49609F8594DE9AD1FE:h3S6sbZxMEdZ/JUmV1CTsbHgYDXBEYEH+9UH2KyKt00=:EID_Bewilder", "7E9FAC0F2BFC4AE3A2ED4C87D1A57DBF:xaR/8qp7kFAbILx9i6ANnoam0rZ/tP8Xy3yysuqt8BA=:Pickaxe_ID_231_Flamingo2", + "738B025296E10AD69AE5FDA250CE65FF:2UmzdDepl8Noo+LAWkt/i7be+QvJTIsusqDRZsx8N9I=:EID_Outburst", + "8B57E50789D21E269BDBE46184F88FA0:G4bUrNa7X6RXd3/vvJyRLQr7dhSiPo2+yuKrp24RXN0=", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=:Wrap_CoyoteTrail", "1D02A6E14FDF53655E818CEF9E57B1BF:ekG/6DFEYOaCYi5hruGoY/o1KzC/O5+9hJbdMyti8Gk=", + "35182C05BA21A7373CD33B20303E6944:oOAKjS/mrGU6Dk/c+XiIcs+xgvqyI8zmt+pnR5VmPmU=:Character_PuffinSmile", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:Pickaxe_WeaveHarbor", + "9E7468047D1781BCB546D5AE215B5073:EYWQj4jWQQnEZ6i1eKfW47bvGqK0ZNt7KFzQO1P6FU8=:Character_TimeSquare", "3FCDA1185C56B6A5FDC57AF760566A51:9I7HsUJTcd0EMjpuwQmyno0jbrJon+nZePI6IuQBmtk=:BID_983_ScrawlDino_AD541", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Raspberry", + "95E3B6C026DC5455DCF2CEFE2C20C998:rs3xOv5ypDx9Mbus6zG0QDD+jNEXO7ulpa6AZrp1qPE=:EID_Encounter", "E0FB7B394449CE6450EA90C93D710EB8:NrXwNX6lKuu/kyQuvE74+6Uo04FODoV4ZqxToj/jS6I=:Glider_ID_157_Drift", "1234642F4676A00CE54CA7B32D78AF0C:Nd8vhYp296C+C0TqSIGxu0nBYOFGQ5xBNK5MFjHS8IA=:Glider_ID_115_SnowNinja", "E48EFA857D8E6914B2505B05AADFB193:4AUdytefPzWNT8c11iGtU4xcGNWEgzpMJbxTjUq3NS0=:Pickaxe_ID_465_BackspinMale1H_R40E7", "958DC719715C145004E1E028E72464D0:ZTCrQKaSpw5dAyqyW/jGz+KF2DlvSX8wCW5/4dhdFT0=:Character_RedOasisJackfruit", + "9DB21D9B45B9CAE4BCFD141C0ECD737C:QffQPwgx8G+22K1v6ArbZ9aw4DYxHpbqytOFfZONcNI=:Backpack_ChessBoard", "A31042B93988941EE77BC1E2DA6AA05E:pDUufUGsOVTv3LuXoq56xwz8HRnzlrHTvTLWbzBaPcU=", + "26021F66A417204C4528397FC89B4FD7:BKxmQzj5fNtYyWMW/ujKawoJq1Y/VTAY64GOLBK1Nbg=:Pickaxe_CordSyrup", "715D5B8D89F01C804C2ED33648157A6C:GbMcQmdpv3ju/P36UQIlDFZ0Q5jr0he7O2oTJ702McY=:BID_446_Barefoot", "0D8B24BCF7F9C0293FFE1264A5D05613:v1sCSrsgI0QbNZ+4v5lllwW1n7M9dagX4GsxY7/oR/4=:Character_SpeedDialBattle", "286270CA017B478C6FF6B5B815428F93:OUbNW00OmQLCd9iLA13soMU4wYtd0RTc+lEkoPdvF4U=", + "2D7CC66E132AF5D216B481F2D0B56EB7:1OB3Dm0UQSumE4qrNw5lpTWgx1bjEqOFE3+s3Xo4Vu4=:Shoes_LungeStreamForte", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Character_MiddleSock", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:EID_Slither_DAXD6", "7C13D9408B7434500647EEDFE55A63D9:vea6GIIHMHtDB/mVGTp1bTW3tfCM6tLlpI9LiP3bxTo=", "053E7EE2FE8B6EB117A01D1E0AF82AD1:SDqBD0e/4fAyf3WCPqwUQD/gDhMWPtbdTZt5j/p3M2A=", + "EEEAD34DAD77926A1A7B3772FED7F0CC:jylPxC+85DXLiAlYK9bpdxMRP/kmq4Exqplkc4u27EE=", "5AD068EB1D56D87706E44EEB3198CF1B:o9Gp08KD/vgq3RTrUbfGJk7rlfUqZMxoRKPiwvdVkXY=:EID_LogarithmKick_NJVD8", "35C2B057E5168DCA74B6F1DDAC745E60:73haJlY3S0TVmH0ELxyw6p5FzFRrITWqOmobH9F2Mq8=:Glider_ID_343_KeenMale_97P8M", "F8E2B9191F948DBBEC6F6688BBA7DB41:0Rv3StsHC9OvC6UDR+L+CLgz63E+qGme+zw6sebd2uc=:EID_Swish", + "CD71F014D32872D388A7AF01D94B1C15:pifX7cuvn/ZnSBqBxwG+v0cdGB9YiDoZrkNP7TkkCq8=:EID_Streamline", "CE9D023C0D7DBF7634F2AEF6200BDB36:JyhTmjJnosQmLeGMQXhCtkl/auX+mde5P11MsWEwIqw=", "F33B69585B65C333655C545A038BCEE5:0+gUoAUkiBbY5uqO9rIehUDkvrr/PY3vBY16AMHQASw=:EID_Stallion", "91BEC79063CD316E69E79215E0CE6437:uE56sTOQozw4kZfj70CQIEFqQOFORE1+mZhMhccG1z4=:EID_ModerateAmount_9LUN1", "71BEC74046C6920A467E57B69FA3835A:q6m1xB4+mCmXL3g7eRGykDO6ZKrXS8M7m8SqbqIKzkI=:BID_201_WavyManMale", "E6CB9B5FE721FB85529A6558D32987CA:aKSiHv73+80I2NZ8lFAbV7CRyRGO4LN9J7a6gjh51b4=", "72CC2893A6B672F3854F36629B770774:0BgQgKZRRuPFEoqn7CxZVhLBOfpCE3qLKGQlZc+SA80=", + "E0632A3499001FD204066071F9E44663:ye/jHjXfZ+2r2qhri+iiy3BBHoR59aQ1cpexo9dhWSU=:EID_Disconnect", "22B8405FC3BE153C8148422C3F2D3A8A:d/ATMDztVZxwHLUCwOcJWP1/7oPKKGqbBWUBRNZ6dnM=:Pickaxe_ID_664_DragonfruitMale1H_4BIXL", + "2BA50BEC5CD27BD07670D7A014FE98BC:u9XKnFIiDDHG2eDMvUJoGUlO+9ZAEVSGyh0V71bjCwg=:EID_Whisk", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Glider_OliveStomp", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:EID_MiddleSock", "23280A6FC0902B6420BB82522AE16D2C:C7o6m2vJJY+XWKd0t1YLBPVLYCMgNbt10d/itx5Wjnc=:LSID_367_Paperbag_3WGO8", + "15AA9676F80B50171D3C21E3020906B3:dxtfRaBfeVi5P6F3NAUQBa1lJK8ed+8HKeUNI8zYNBE=", "E59B013651F078E718F08ECF9E1559EE:rTGy9at5kTfQtu8EwVrUihfzuN8vkFPl3XNyGvqbZX4=:Pickaxe_ID_194_TheBomb", + "99F93AEDE16EDDD2D43F8FFFED3A4126:43GiNG6gw/2MctgKJG7QkA52E1HBAGcdxIY9f+7OGZc=:EID_Ringer", "D2FAE1D098B2B4695EB59FAAD504798D:ZUDIqDvGVcpCVuA3h67vdkVbZwLuC0Z1zX33JLyi5xE=:Pickaxe_ID_727_LateralFemale_D9XJG", + "2D7CC66E132AF5D216B481F2D0B56EB7:1OB3Dm0UQSumE4qrNw5lpTWgx1bjEqOFE3+s3Xo4Vu4=:Shoes_LungeStreamTenor", "3D9634EBDF17C26278CDFE91EF0130E8:tVvwjIulbvPLmBKlFhBwKSOGqzCu5yu9CqdH5008u5U=:Backpack_FNCS26", "EDF724493161095DB54E9613C243A355:Yp7dsOYO778G7uRZNYhGag2diT70vhu2hAWvkzvtHjg=:EID_Indigo", + "0C8FB41BED80602548CCB764A876CE40:05zgxQ6Q4m+LULvuKwRlaPiSa7wZBN2fy6sG+rxR3Ng=:Shoes_ToeBean", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:EID_Lyrical", "8D578CF915DB851F9BE73C937D3565E4:Xk8kUK9cut4tXr0VQjufZdoepp+TzGmlDA7fzYA1rAc=", + "C6870C1BBEDEBE42C5F6DAD9A0C7F02E:A2bcroUj2SFFzUdnU5RKQiwbxrziOkdRW36vEByxWbw=", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:EID_AvocadoSeal", "17F31F416B1B0A73F14F0A7973DDBD76:+hUk8/wD736u5sylQPXcKKREoo5vSPaWPG+3xxT5nFM=:BID_207_DumplingMan", "1A9B01B59F609C0D7E9EF7887DA23087:EkQdXhPD9Je6Bp7dlwZdlkX2S0har6vqUOjMIF9ndfc=", + "8E86BC326698EE02BF7B17C5C59B7D49:W+Z9L0RRkFzJTo6jyegWGj3hOUySrTHZKYPtp5fCR4g=", + "279FC777D7F0D465F1A94C6FC9523154:QYYRiJbH+4XtjwSF9cJ3FVsgjYcwzRrqx9I353nLJvY=:Shoes_TunaCabinTallow", "682BB8BC5B0BBE6318CF2164E074E7E8:NA4nCwFqo95pvsqkLXWO2WDdLY+MQGcj97N6t881BQE=:EID_Socks_XA9HM", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:CID_447_Athena_Commando_M_BannerB", "B3A4B83DA3274522D4B9F117DCF9A0B3:y5n7vfr0uucr+psZzb2F3g45pWUsv3i3j/M6bl78Z9A=", "010E6ACF85E4A58BF6F551EFE7B85F61:DwCIH5Dw/1wdiS6gFGmWe4HUgD9kMOEzjbzM/1QshM4=:CID_371_Athena_Commando_M_SpeedyMidnight", "488F01C34A9A24115776EA801A6E7E1B:WB1TFXsB2Cywzb16hZ2HdBc8X1FsTVqzlDwhyJO8Pcc=", + "D12059472F9FC9E8C71C715BFAE3333B:phP1bANlO1Ppd0XaisuZ+A0IuBGKlAOAzmWMPGsc8G0=:CarBody_Bullet", + "D71B95B305E6875284CDF3F28DBDC2AF:kK88qPTK/QH3MhsXnueQR9liR/XAeFhyNEkWAFOLvzM=", + "7857ECCA6B0B91759DC87671F8DCCC62:LHh5NcObng4VN3hrWEvrRQfF/3H6InEOXOlwyJ+O6Rw=", "B66A53100DFB8F33CD5D55E2F66FE10E:wz7DApgadJnBQyHgJCqTiXYQARH8NWpaIT8zSJiIJUg=", "D01F7B7A687A459D3F28B8A3BD96E31D:siHFCRzefGjIJSV1g3Iw6At3HdCRf6ZbtgZyNVQXPq8=", "1937F4ADBC2C38EF4F189DC2B1AE58AB:tWzxKwKEDzI0RsQGl2GvOVqZwxOSOiZaCQkyK1hE+lA=:Pickaxe_InspireSpell", + "A76470952FE7FC15145AE4E1EB9D85A7:0VhPrkcCrAX0GuW8LVplYGG3GcAT5foNc02I/p97H2g=:CarBody_Seba", "E7D27A42770632B7A50BED813D9B1696:bxADNk9dmPNeKEuSvJl44teif6sHvs36yBZ55E9fhwQ=:Glider_ID_363_SnowfallFemale", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:EID_WeaveHarbor", "DC060EA83FE6F9729B19150E40C7987E:zW3d3QhtvhE+q3x/P7/BA9JvyoruVmeACdKt6RPxyLY=", "B1EB196DD39D0736E7E08F99B07D8B9A:1fDhBY8uhi++l6QQPL2YtxZgUv04OZoMGBrH+yN8yKM=:EID_JanuaryBop", "6B0D17A04F83AAF1E4EC1D0D481D7B03:fgSAnECppKmZD1eolFEZOuOpUDPbt1MmvGroMQ0sPFU=:EID_CrabDance", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_941_Athena_Commando_M_Football20_E_KNWUY", "E1B1A5908EF6377D7FB29F776486A6A0:qaZB3Q+6kKTtlO4aGWBsnjSxCwX3kmr8oOF/2QDZ2qc=:Spray_BasilStrong_Pickaxe", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Pickaxe_HeavyRoar", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Sparks_Guitar_OliveStomp", + "EEA28D2A16458D0B2ACBF1ECC12E2D33:5JlAGAfApUEeXSCLziIg71JeDc4jByiO9316qxyGK5E=:Shoes_TunaCabinCanola", + "A1892DD6A665D23CFAD3173CAD32B65C:br7Yu2bywwX6/gTgsF6+yOgvag92nHHBrNzSnQYvMl4=:Character_DoughDisk", "BE2C3EF59AB81D812AF5B8153325998F:W7NoICLZt9L2d7XZ5dT9gtI80MyOizk7uA9LtwA/Edw=:Pickaxe_ID_687_GiggleMale_YCQ4S", "C5E60B749B12EE642D011809C151C105:3beN3XlxtcpmaTa1O6669UmAZ7HHs8UFOzUQSAOSWv4=:EID_SunMelt", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Pickaxe_CitrusSpoon", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:LSID_457_Ensemble_Characters", "8E1887D55A60F69B33B234242FF49653:YofZaW+CRl0jhVhkp9z2CQWhTPwyjQ6dbHtISkLDfVU=:AlfredoSet", "4ECF5AAA0161B01630EC04541290F986:BkEPlQ7bCZooSwt1HIbGXIm7LyhVkEd4zg4WUGJvaT4=:Backpack_PowerFarmer", @@ -417,10 +654,13 @@ "FAE51F5AC49A240384D5B57EA08B1F90:oesTf9AVGgX4FVwWzgm++nQEO0aARyuU5rZa1f6hoFs=:Wrap_InstantGravel", "58388BA7BD1643A85EFD49BF26EF5912:Aru327JJHsGKCD2YlQT+Ejy63//vly9ChTdKsfgL75o=", "BA490514EFDA436A2679E381BD558AA3:3KBKxBOi/52H0feJ/ijKxRHk+lF1zID0uIpjd0T7/Bc=", + "6024CDC6A7AD11D34A4357B928F4C340:sEB5STe61IRm4fuo2Ai8GIrwGYUbsJq0NQE3GqPNyNs=:EID_Depart", "1A10A7700C3780E2B1A03037D64E1EE5:IvQikWqraVuMzt8eP1B0cxW5Dcaiv7njo2QHFfZFmY8=:Trails_ID_081_MissingLink", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:BID_850_TextileRamFemale_2R9WR", "AE9F7B3419C7FBD2414D72E2E1C8A7BA:kpIotniLp60tWfbBitDUrjw6gmJ2Swl+YT3QAkecpRA=:EID_ProVisitorProtest", + "E436CFD103805186E3B21D8F07408A01:u0IsiGhPPB2b7xxq+qWxhSZbXTJcp+uppzwaDeZzFqI=", "F395571A36D2BD888861E61EEBD45AF8:D/35GPTIOKbdfmpxRJmHTkjNXcWv+XdSmTxQt6z1hvI=:BID_701_SkirmishMale_5LH4I", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Pickaxe_CraneAnchor", "91181AD6BCB9443F7F6479DA8BA9B7A4:ckv0KEQuDpca5cP5JLUH8K1f+tVYvZptoMsGYR7fxDU=", "027FFBB49E4285146DA1C5238EBB7DB3:yjcsOd6x9bWnX36cFx2Q3/zgHrCrnuWwiuZexrdcM8s=:BID_939_Uproar_8Q6E0", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_906_Athena_Commando_M_York_B", @@ -429,59 +669,92 @@ "E0AEF4894E1283946745F7902F7E105A:7MXKJEs903nNbT1oFzykxoHbQNDnOBm6yfadj+mtBDA=:EID_Rover_98BFX", "A25DFB2C9EBAECE22F893DAA48A7138F:d5KZse0g/v9xySiDWLhNw3kCvlWXZKWMKUjDzW8/SIg=:Pickaxe_ID_435_TeriyakiAtlantisMale1H", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:Wrap_495_Ensemble", + "9DB21D9B45B9CAE4BCFD141C0ECD737C:QffQPwgx8G+22K1v6ArbZ9aw4DYxHpbqytOFfZONcNI=:Wrap_Chessboard", "4009CB877085F3B3B0D76A686465A140:gMLJXUbFcIrqqUlAuoMI1b27KdWHBVJJeJWdYV1Iiro=:BID_703_KeplerMale_ZTFJU", "7ADE21079D27D9CA3931F676358A0F72:jWtbxcYHNph24P0SKVvPEuGDIdFpq+wZAEIlGXhSpj4=", + "C76B70EC836344CCFB8762C4747B4263:U+UBLfYWkT5IetUd9DrotBKrk8kzphj6Xd0FNvlv3kA=:EID_Dignified", "488F01C34A9A24115776EA801A6E7E1B:WB1TFXsB2Cywzb16hZ2HdBc8X1FsTVqzlDwhyJO8Pcc=:Pickaxe_ID_538_GrilledCheeseMale_Z7YMW", "F60CFFFA32CF6A877B50DA7F0A88326E:OWIopbB4fxaobofPI9lF9hn6BPG9NVLp4Od61uQppfo=:Wrap_048_Bunny2", + "704725A33203935E6E576D64D44905D4:tKWz7Ob1wPsOnzQzOqdJ7Cd5e9P+VVXJL7DIdww6VrM=", "30A1FD89B2D3C155DAF14852A39BA97F:C0IwuJFw9v06OF8XthOhzUd3nHOTCII1gmx/7eepmDo=:EID_Zest_Q1K5V", "027FFBB49E4285146DA1C5238EBB7DB3:yjcsOd6x9bWnX36cFx2Q3/zgHrCrnuWwiuZexrdcM8s=:EID_Uproar_496SC", + "2E8C63FEDFFE6B835126B6FF7CB47062:B/uSSHdC8IsSccWS2rt8Cg0lBjG3+k+Ncu2p/qtB81Q=:Wheel_Melonpanb", "4ECF5AAA0161B01630EC04541290F986:BkEPlQ7bCZooSwt1HIbGXIm7LyhVkEd4zg4WUGJvaT4=", "8D336ADD3E862004534F4D310F0A681F:Oh4kuy+66NB6gPNkix+oKng0QTO1Dju8k6SxT3HXxe0=", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=:Pickaxe_ID_693_SunriseCastle1H_5XE1U", "EBB742679C34C9D4E056A5EAADF325B9:ousld0RIkeu9L9aTDwr9aNCIt+wOwB7KxGPY9BTfQ7s=", "6ED300E6401C02B19FDF5F82D945C661:OVr0GWPGv86nzWikKzrw2SC4aS+4ApgKKLvQ7d0Nkn0=:CID_336_Athena_Commando_M_DragonMask", "0A16F03E8DD9C4DAE4F04B2C5D6F829F:5o23YPFPMqv+KS4E4/ybDC25GkBt8ZU52xW7WF4tZbY=:EID_Bulletproof", + "2DCF5899864B58847F7721F5BC6CC7B2:0p6RYJMTG+ET3tlmONyr92cZnYnz+AV01JZgOtcemS0=:ID_Body_Squash", "5D6562F1EAD89513C82C2F37A24E7F82:I2c+SQCdDvJpC6z1xniRT+k41KAp0pla+o/H68oXFLQ=:Wrap_179_HolidayPJs", "9E9072AA036FB1FF6B2AAD7BEFE7BF17:ORHgZOt4Zrtc8dLSx6jCsWZ3Z6AwPJiSiFAkZRMK3kM=:Pickaxe_ID_649_AntiquePalMale1H_GBT24", "63B2E664F9DEE5B42299191174C3B3C3:U1GOSBqPUDAFq3pjEdJg8nHb321IH6571dkhF0nEMss=", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Character_MotorMonth", "4C8D53A32D85124D08A3DCE6D3474A30:gam5sVciLPzKr+wmWOoctLo5HFqBvBLKKcxh6ZV1kn0=:Pickaxe_ID_533_WombatMale_L7QPQ", + "94F0275E19262EC468597A23FB4D6194:bJYuld8Z7lc2rtAWDKmNwnBPv15hbhUt764mohKBNqA=:EID_Princess", "C7623A35411F3D5FBDE2688C7E4A69EB:qAi49mUKsB2dbfbtJWDf3yO2DfRStA+Ed9XgDjC8Zaw=:BID_189_StreetGothMale", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Sparks_Bass_DriedSilk", + "9858EA640CD5F38627E83497187A327D:mQ1EuH/9E2/tpUCZJeJc9gSY7ClR5G5cOCbIa9kR71o=", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_240_Athena_Commando_F_Grasshopper_B_9RSI1", + "1779D69116EC781A474EAD25440F4688:ld5vNZx7VDC5TOeZLfSgf1e9d6w9EC5j21Kakv5IOWo=:Shoes_PacketCrescentAmber", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:BID_917_RustyBoltMale_1DGTV", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_953_Athena_Commando_F_Football20Referee_B_5SV7Q", "9904FE82E1630F9BF753E5AA195B4E1E:ScugOdDnT2N47PETOZ8B3MoDlg9elYb+ePzsZGA3ryI=:BID_A_027_SpectacleWebMale", "F6E92DDBC70C8184E837D31905B2F2A7:UCSPatT+yv3YH2x0Ks+2GSXhSSu+3ZvZs6Lai3oOi0Y=:BID_826_RuckusMini_4EP8L", "A6E44EB3DA45A5323BF1FEB33C6421F6:l9NQzTVH+MNDjQ8Z2gSvxDnNFyvECNwp61JOHFAWWvc=", + "EE1B544782238B556744A68B8AB52CD7:PGQPn8LVr8FLUROgBSOsmYcFi/BmNVWoBQ+kAl3uuIw=", + "5E30C7403A702908F7E67AFC6C9C5BF4:idycKoAyRb5uU8ZMsni1k54gQ0Q89xGl4xvp1gyk3ZA=:EID_FeatherMud", "FBAC0AD8C03AAB2DC3BC077597517179:5oj8B4R53plPxRictMN6QkQ741CibMbmzRJYIDIQ5iM=", + "299C16019D64B4942BC10988AD3B82A0:jTs56Mt7WtAkJ6p14hizw/FPE7pQ60QW9mKQa2ugnjU=", "A10B1E27AF53CDC331BF4797C97B6B9B:fy5fTzL7HXpOBRg49CHm/E8Iptd4X12eYNBAeSa5CY4=", "BAEF248980269F569C6E1FFF2B885DF6:2b6DQGIcab1r7zsw5j3MR84iDmt0g1XBquxJVR/8GxM=:EID_TourBus", + "647BB55310F2041CF6D0EAB8DE19C90A:dtooBxypbYpyd0MCxWQgnDoW8RSDnAfdYRNQk5daCk8=:EID_SuperNova", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:EID_RustyBolt_ZMR13", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Wrap_TireSwing", + "8734362B2A2A8B0FBC9EDE6160627E1D:8ZsoLeTeezxjoIxnNfUrNf61XfqMEKfnyTb3u4o/X6g=", + "C50EC9789A634E9BA829CD5C4653C248:1pqFVcUR6pJ3zNoBgu4bFffbIANvAfPO4BtqvPON3IU=:Backpack_KettlePress", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_945_Athena_Commando_F_Football20_D_G1UYT", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=:Character_ElegantLilyCharm", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:Glider_ID_333_RustyBolt_13IXR", + "190EE0858B5F6B5C09F029BCEA7DA1AA:s9BgWW/XUvjz8cZX5mD1tno+F+O/c2SL1w+yYuPOzqI=:EID_PigeonChart", "BAEF248980269F569C6E1FFF2B885DF6:2b6DQGIcab1r7zsw5j3MR84iDmt0g1XBquxJVR/8GxM=", + "EEA28D2A16458D0B2ACBF1ECC12E2D33:5JlAGAfApUEeXSCLziIg71JeDc4jByiO9316qxyGK5E=:Shoes_TunaCabinOmega", "E5C19AD4D84758F8B943DA9A9D608712:qYxz7kOHjgf5SSa18F5bcIL1nLD0n6MD1vUE1+SwP08=:EID_Bargain_Y5KHN", + "0EBAD64EEBF8F23CD123EE324606E44B:7GyRVJ82OD0rlvVWbbcbdUZ5Ui7CfrYP3HYdB+awZ2Q=:EID_Tailor", + "174B492A98CE7D4047C016C29EF7D86D:URAvdRkx1DkQvA2t91joRtT7PzM8OFP9KwoMnD0YJt8=:EID_Snippet", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:CID_443_Athena_Commando_F_BannerB", "335BDA9AA7DA27137CB7F1DA56FA2E6B:GJEyHEl3Q+8h2k2Cbe5sfG1lNLmXHSts3n+0QYH4Kjg=", + "CD9A2158EBA8DEC4F51A16F0F19D0F06:HKidNu7ZYT9Gsckip7xIrqxKC4lIeQ0kLGkljdqj1kE=", + "CF159FCCE55868D72C8E66DE0F96A409:aE11RIixkH44CGQx/6v6/VWXAttVJERE8uFnyOHkF1E=", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Backpack_WarmShadeWagon", "BC3890EAABBF03778EE82AD7DD4F9C12:RvtEdiKkxLJDnXKUaUK933vzLK04veYzbdp8yN8wmxY=:Wrap_496_Chisel", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_089_Athena_Commando_F_Hardwood_E_4TDWH", "4EFDA950DA6AA1E6422D2FBF6B89DE85:HDEI+ufmAF1VN2+mYiOFFFDjPVAfkEcmrnyTQh85dmo=:EID_SunBurstHeart", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Backpack_SweetLetter", "7A8E25F664219ED6CCF3AB1658D0E557:TV+yyWpI3iHJoaK3o1t6+/uhN/sFZ1OixoAx0n7MtjM=:Wrap_118_AstronautEvil", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Backpack_CraneAnchor", "A6855B699FE10FE50301AFE1A4FA74CB:fKXFbKW6dUWHLSC8M4KLAg1elVXH+wYouFbpvvtiIcY=", "E4143E437DE7481237AFAB40C59D96E6:a35NCp3zTY2AhSsZWy09BJaXJDU0LMJbiiP1u0dOl0Q=", "4755D9C0E2D1DE1C09B77DEA8B830471:9tUO5yVhvp+/sp7icZaEDw05nMAdS6bYAWYyfQNsxBc=:Pickaxe_ID_388_DonutDish1H", "099F6A310406E06EEE5B011F57E8ADC5:eN0n2GvhVfW8LKPVA+LvlegACOXLQLyOxt24wFERaio=:EID_OverUnder_K3T0G", + "D427D67AD5777D1B1B4F1767FA4B20F1:usaLfjFT9fTbvIbFvHr9GMFI/MPF4iYldSmsrADdzn8=:Shoes_StemDotPasse", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_345_Athena_Commando_M_TreyCozy_B_4EP38", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_238_Athena_Commando_M_Grasshopper_E_Q14K1", "1C8FA86241B2E4D084F7548529629CF6:pmXOfd+NEXcLhZX5YqDLjHu8/yzZoo4dWPcCM8ccXoI=:Glider_ID_118_Squishy", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:CID_442_Athena_Commando_F_BannerA", "B7D9219AF6290146AAFF711E464C5849:iwGv47bJtl/Tm8oJGdnta9aDA86nY0IyjDmJWjQYdQo=:EID_TrophyCelebration", + "BF54C54672DEFBD71B744A72053E4168:TL25+NVV64p19Xu6A7+VVMfNwEseRZiEZ8J0QBfIkWs=", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:Pickaxe_ID_721_RustyBoltSliceMale_V3A4N", "E7D27A42770632B7A50BED813D9B1696:bxADNk9dmPNeKEuSvJl44teif6sHvs36yBZ55E9fhwQ=:BID_977_SnowfallFemale_VRIU0", + "92034B55AFBF9B8D79879A805EA50D70:P/SfT3IbWKQS5QIE00cDT/qR5omam1FlCNEbmK44Yuo=:Pickaxe_ElbowChat", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_908_Athena_Commando_M_York_D", "CCFB247DE6ED8DB4856E039A5AE681B8:Z8ixoqcCEiFqUH1qec+yUNQTP1+D1xQjYw6FDpUQa9c=", "9E9072AA036FB1FF6B2AAD7BEFE7BF17:ORHgZOt4Zrtc8dLSx6jCsWZ3Z6AwPJiSiFAkZRMK3kM=:BID_827_AntiquePal_BL5ER", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:Wrap_CattleJar", "F7CAA8D040108722FFA35FAA63DFD63E:WNwYWakPoe/BGxI8+xsB446zHv4R9A1krz8SK2y8Pmc=:BID_164_SnowmanMale", + "C6870C1BBEDEBE42C5F6DAD9A0C7F02E:A2bcroUj2SFFzUdnU5RKQiwbxrziOkdRW36vEByxWbw=", "D938886074C83017118B4484AECE11AB:wjHAHm00Vg6n2x5LU91ap0+SFX5ZXXBmax1LyX8Aips=", + "F93D796690441FECFCE4788C6267E68F:c7zg1pvZw3b5GRdU4et/j8mEfs3MQzVFiP5A4mq7Ygg=:Shoes_PacketCrescentAqua", "D7EDE7B4CE393235BF4EB8779C55D5AE:tvYJfExMmwMpbWXSe8bxfGkpl1wcJv4B/RBjd8qWcZ4=:Glider_ID_336_OrbitTealMale_VCPM0", "E45BD1CD4B6669367E57AFB5DC2B4478:EXfrtfslMES/Z2M/wWCEYeQoWzI1GTRaElXhaHBw8YM=:CID_229_Athena_Commando_F_DarkBomber", "204D49F063979C3AF87EF896D074D1CF:SaYFk+GEE7mL4dsgs0v0VGR5ER4TwH8uTNX5XqSglu8=:BID_643_Tapdance", @@ -490,11 +763,18 @@ "D47524F6F863DCCBB2455472F0FEFE2C:cRoiHZin2Lnv6yQ4Zt2WoIpQc1ZjLbfl1Ogid24ydZM=:CID_A_417_Athena_Commando_F_Armadillo", "7FE6E196D4EF15F90CF5FCD812543E7C:hAr9lKRtiDVeJSn5j/kXuFTGiKYTIEHwhe6VzS5FnYs=", "457F39EA51FB4C723B442810750CDA4A:V3d05mcuS4uXMBRpy63TIZDLt5hg9njVD0SGhZDsmBw=", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=", + "F4242EAC57C7B6ED79960A59D7978A67:ayEznxBID1ZaAY5bTwauUXOMDyKhyErG/QZgdnFX+iw=:EID_Farewell", "1937F4ADBC2C38EF4F189DC2B1AE58AB:tWzxKwKEDzI0RsQGl2GvOVqZwxOSOiZaCQkyK1hE+lA=", + "B8AFF95FE7104F5FCFB26E4F57694E6E:5/Q+ybOtveUjDrLVuKvQN0zfmPBxJ5hhcMawDDg0v80=", "D938886074C83017118B4484AECE11AB:wjHAHm00Vg6n2x5LU91ap0+SFX5ZXXBmax1LyX8Aips=:Pickaxe_ID_581_Alchemy_HKAS0", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:Pickaxe_ID_719_RustyBoltFemale_0VJ7J", "27D6556F776B2BDA97B480C1141DDDCA:uvUqb5LuwRFWQnA4oCRW3LNdorYcGtOmJ8PvBeCwBKg=:CID_467_Athena_Commando_M_WeirdObjectsPolice", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Backpack_MotorMonth", "A93064DA8BDA456CADD2CD316BE64EE5:nziBPQTfuEl4IRK6pOaovQpqQC6nsMQZFTx+DEg62q4=:EID_Bunnyhop", + "58D945630DF6E1016889F47B16EED803:zQ/4osJ36W0V1DFXswf8JSStDMBTZPQ8oFcMrDqS7BM=", + "7E3B0175F4929DD5C6C8A2D889B24F81:BOiNpViUgeXK2U6iFe7NS5c5fgHayrpHnNMaR2Ha7xw=:Character_ThickWatch", + "FBB56B6E711D7FC3CA29B46F712AA3A5:wtIigakPrMzOC6ZZ4Am7gJa+CNEhe7DPAr1ZOE/WZZ8=", "3AC8A6B5089F55E17E00AAD8AC3C6406:TlUSkJe3y85fW83rHMy+XuqcZxQduXcB8yftpPoiDvo=:EID_Loofah", "6EA156BE3D18E1D649D7D4B3F8C0FACA:qAKD9oM8u4IvUcKbReHTMaLg7GtHLBcnmz8++vwwB6o=:BID_906_GrandeurMale_4JIZO", "E47EFA3166A5D7B35CEC27B19AC66AE5:JURSqAHhHK6YqLP5rKhCO+SQ2oql4NqJaoaeNGtsrM8=:Glider_ID_304_BuffetFemale_AOF61", @@ -505,55 +785,90 @@ "110D116208C62834812C2EDF2F305E49:MwuF5zX7GpQCGL2w+CwkPmGzH3q05YUoLo5udhVMNPg=:BID_488_LuckyHero", "40E9F547033360DFC0DD09743229B87C:x0/WK54ohwsadmVGHIisJNyHC8MqlU8bg2H+BsaEBtc=:EID_Kilo_VD0PK", "2E539CD42E0594ED4D217ABE4E2B616F:9zdoLMrIZomTGmvDId1RMEGSfktV9gBGgcD2diSSMw4=:EID_NeverGonna", + "32AA2546A88B1797C12F9C35A8492CD2:XBMYQphlCk+dBFuZtBzrIwLNnpmxl4gKEsysFoJ3yao=:Shoes_StemDotWaltz", + "D9A43D5EF8EC6AC2DADE89B7B345B4A9:bVA8oGmtb/UeCydeqdLdk6lf2uoO4qLvGE7KwOyKS/Q=:EID_Crosswalk", "5AD8A96807B87D5E2D91EF7714A5432A:FHE540WbcHsqROMXt1E3RQIbKEguG+TVTdOr4IGSslo=:EID_Cottontail", "EB16EA013B751792698E05435797C1ED:y9JgD812Io4mbaJ5i533Ts5SSfyXaGM4JyoimjP+i4M=:Glider_ID_135_Baseball", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:Wrap_394_TextileSilver_ZUH63", "488F01C34A9A24115776EA801A6E7E1B:WB1TFXsB2Cywzb16hZ2HdBc8X1FsTVqzlDwhyJO8Pcc=:EID_GrilledCheese_N31C9", + "BA2A14985A7E28544995069FC9359C81:lIJvTL75n/NrsjEe4Nd+L4UQCiPcYvHaDbc5q7xJVbM=", + "38520288A2C9F2B156356BC34A111E4A:Jb3sLKsxsJwin+lQ4U7r7N9lOFN6zAUiCso7mMS5s+Q=:CarBody_Jam", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_237_Athena_Commando_M_Grasshopper_D_5OEIK", "E7D27A42770632B7A50BED813D9B1696:bxADNk9dmPNeKEuSvJl44teif6sHvs36yBZ55E9fhwQ=", + "1269E6F7E620736515D3F57CE4B2938A:P+cnpG9HbjrhRGcxCH+FD5C19cSQij2V7pHTsbVfi/Q=:Backpack_SteakSting", "47668DCAEC0AE101E0402B6105A6DDF5:rSOpMue5liEBVSvy/0JZZGTPsP2QeA7Yw9GdicJHs7Y=:EID_Macaroon_45LHE", + "C8622C1038D4A1CE0A2FC89863C52899:V0cZyuTcsYqvD7P/3LkWM6F5WUXog2UUaUU0Y8hb4vM=", "13F1DD5EC796B357B6085D50BBDA3C18:7NRW9FQONfoNEwOJARayC1upKkjg3obxAWICvcXfUWs=:BID_426_GalileoKayak_NS67T", "E7C565B86445735863B8080B9BE651F7:7M3P/+is0y8muF7/0N2dJo96J3P/k991Vast/lb7Xec=", + "A7F859B562B3AB262A2876C962C79A78:Uf4yi3l8KFClAdp5ed1frgZo3HbpXXrwiIuIm1j4alA=", "BE9040B1851D0A64B7F061CB66EA9203:5MNas9JBbj90Lqq6RcfyUEE3lZjfXZhiDzn/FCcLiSY=:EID_FlipIt", "6DEBEC4266A3BC248F8A8FD4B76878BF:wjCAJ9VaThgTfbvUetCEWQFii5GmdfPwFCvxLv5ip/g=:EID_Eerie_8WGYK", + "D80CDC979BC760ECC941D3E40C7B6CD2:zTGtyTYXzGUyXItI6QOo4oRr3Bq50412adBrYt4Jm3c=:Character_BestDressedFNCS", "2E5F91AEF58F310AE2044EA39C43BB81:pNy1GtfVzymqacOqXRY14EZEvI5ZSVD5AFxlhxXC5qk=:BID_870_CritterManiac_8Y8KK", + "F4F783537F2D2C107AE36A4A35E9CFFC:3kM0mWU4SkAJoA08DAFifrTnFDwRu1reRK2WczH3rDY=:ID_DriftTrail_Daikon", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=:Sparks_Mic_ElegantLily_Plush", + "2BEE5F951D6A3AA790943B18CE43C474:fgujz2DrxsPG/SILcUFj8zQtKe4AQcKuKUqxX3VXbBw=:EID_Disband", "F2A5D91602A7C130FA1FB30A050E98A2:MrhEh24cVikkhJJUX/LBAaNtgYV20VBiR5oaMDJ2nA8=:Glider_ID_346_GalacticFemale_LXRL3", + "0AA41354BC261BF44EE59CBB903A1672:vSYFVpavcoosC319I0XmmzhcwCeJFhat5rcJYatQvks=:EID_Cadaver", "6CED8B5F648ED1ACCC8F1194901775AF:qjfCT39FVniEjPj+CvZu5Qz8XHHtdnH8kCsV3P1OaJw=:Pickaxe_ID_196_EvilBunny", + "BA2A14985A7E28544995069FC9359C81:lIJvTL75n/NrsjEe4Nd+L4UQCiPcYvHaDbc5q7xJVbM=", "488F01C34A9A24115776EA801A6E7E1B:WB1TFXsB2Cywzb16hZ2HdBc8X1FsTVqzlDwhyJO8Pcc=:BID_687_GrilledCheese_C9FB6", "BFE1F518C16A9F061B140D829ADDB0ED:bHkPYjXd71vacoJ4IisL//zEyVLFh+Di8MUqV9KkpFU=:CID_A_138_Athena_Commando_F_Foray_YQPB0", + "CB64FB9BB49C7D49609F8594DE9AD1FE:h3S6sbZxMEdZ/JUmV1CTsbHgYDXBEYEH+9UH2KyKt00=:EID_Bewilder", + "9DB808E8A3748C92F9B2836D97F12E43:8/7CEcgqMxbP0Njwt+FfkrpLL0re3J/cSvasQ9DuVAo=:Backpack_FNCS_S29", + "505B0CFC5F0C2722538390A1B86CD96B:+e0wS4upHWWgE2ptrA/0C5a17sPALvW+mHthRVTZP3Y=:EID_Thrash", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:Pickaxe_RelayStick", "57C0A809F1C608D62307954035E3DFCD:FuMI1S1xM1U7UrdX4qZhPq77674JV+EV4HWsn59bmbE=", "F395571A36D2BD888861E61EEBD45AF8:D/35GPTIOKbdfmpxRJmHTkjNXcWv+XdSmTxQt6z1hvI=:Pickaxe_ID_553_SkirmishFemale_J2JXX", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:Backpack_SodaMug", "CB3D84444FF0E551D18939AA7226B17F:U4GIAd4fGYWy9tySw3iVb92+6ZX3rQ3FsiBCXMT4TSo=:Glider_ID_108_Krampus", "2DCD2E2A9A816AA9035999F8E6F85F6E:6xM4ZYt0UAylyuIgFrmOgq4fYVH2ChEzQNcl8KGQF0o=:Pickaxe_ID_406_HardcoreSportzFemale", "6EA156BE3D18E1D649D7D4B3F8C0FACA:qAKD9oM8u4IvUcKbReHTMaLg7GtHLBcnmz8++vwwB6o=:LSID_372_Grandeur_UOK4E", "A0C6985E7B2D24E0A3F68456F221258F:CI8iRftaQe7Ncch+18hxD3hcd0CFGOA9QvEszAAsFMs=", + "38D31B8D75B45FE43423A479A2A76E16:MG3fgkXOZi8aGnPU8VsP4W82CvZjHv7tEPQR8lZdYvQ=", "975414A2AAC78A3710C3A47A8E3B7A57:LQWa9K05LB13Fn7Brzi8R3vsMRmFcNyJaoAcmBFZNjg=", + "0A6F8755332638E42FC052470B3BD065:OGqX2AuHNDfNO1iagEg6fwOr3Ib0s8/5iOBLnDc0vSE=:Backpack_RareDelight", + "59881A06EBD2C9A333EB1F04A6409265:E18NXuWZnSlrdVJXuh+1y1xFiQr0luqH7/Cx36ta9Vs=:Shoes_LungeStreamTreble", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:Pickaxe_ID_328_GalileoRocket_SNC0L", + "E9EB23F83112E35700E8BC975D74BADE:y8vbtF2zLfv0NnutlW7lsNrXWQNpEmuEiYb34AYgUQw=:EID_ArmyBunny", "4C838738CDC4946786DD7BE341AB05DD:eyjCm9OcFQSvVRVBZizNVyF+8kb9OlNFrvDy8d1QDfo=:Pickaxe_ID_197_HoppityHeist", + "3BD3EA919AEA03B242CD5BAF46E30D02:pu83SeAxLED2/7MYHEJiWmwXAvmggha6jtpAEeBY4g4=", + "23DEA89BDC537501407CE442F9D7488B:MBhNDIgF/lTCfsqwj8VvjD1WBYdv1MvrwT+k8MCyDzg=", "2A236A35ED4833924DF975CEBE4282AF:e4NpefIqezxUVeH+2INzCV08eK4NvFrojB8z1awxm6Q=:Pickaxe_BrainMatter", + "37EBEF32D39E164FC25A2C913454C2F2:ct+ozS+yI2X6H+Mq6fmTH3pKQ5Au5vvVMGz/9ESOva4=", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_995_Athena_Commando_M_GlobalFB_H5OIJ", "B66EED5CA4F4ED75170872E30B9B0E23:rHT8/uzcZZ0ENxU9dxKpr+cdAajZ5L5U0geHt6NoZhI=:EID_Fireworks_WKX2W", "36351B933FFCFF1746737649E9806CF9:2ZtfFqHREh2sKsMYN23yW+2Sd0OSNN5CHGd/qlXVd7k=:Pickaxe_TigerRootFame", + "5F74F41AAAD2E45F585927189BFC6797:Cs/gvSZBhTpl66f9JMuxraYVIHgClmDD0h9E56GwSLw=:EID_BeachBreak", "6A3F6093DECACCD1F78CF802DE7AFF84:Skd0CfmqkmJAUqDFE6Qy/adL2MSN4IuAndXZ0SepEXw=", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Pickaxe_WarmShadeWeasel", "7E9FAC0F2BFC4AE3A2ED4C87D1A57DBF:xaR/8qp7kFAbILx9i6ANnoam0rZ/tP8Xy3yysuqt8BA=:CID_464_Athena_Commando_M_Flamingo", "4E7938F1FAC98BDF378823116712AC7A:jbZVgprILTQomUdGeJF0PsAFAJxsSCs5cKcXweZMAg0=:Pickaxe_ID_548_TarMale_8X3BY", "F44BDB2A36AC4B617C7F6421713C656E:SgzCqior1619O71w2yToU+h1Qakb9PXHXYIQN/2UIgc=", + "C73DB27E321E8B5D3747E2209CED62F2:sL+26G+2SaePYEPgaTi+UwMkAr9RfmVl3QK3fsLfd30=:Pickaxe_EarthLane", "01FC97F8787B82E027EC64661E0D36AB:Mh1l2LJ3YrgaZtg7sRTd8XeBkVcyA3i089gZKkTr1gM=:BID_986_CactusDancerFemale", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:BID_991_LyricalFemale", + "8E00C7A2A21FA7B4E700B07C507A41BE:dyBmgCC7TleC1mjUEngOJl5amz6OBzdx/wejiv2MrZc=:Pickaxe_DomeRoof", "3D9634EBDF17C26278CDFE91EF0130E8:tVvwjIulbvPLmBKlFhBwKSOGqzCu5yu9CqdH5008u5U=", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:Sparks_Keytar_RelayStick", + "9AEA6E7C6885D6E9A1E71E1C1D660FE6:RMnbqblRiA6+JXyNmN/z1yqMbdKCkLnupMvsm1cpoSc=:EID_Resonant", "56FE93367C8B62ADE2A8A1653077C98B:OevQYyBvnT5vwQhOJhu74k5TNwE6pe4gu6okYYBepGc=:Pickaxe_ID_784_CroissantMale", "B4D5B451ED92972585CC2F14FBD89BEA:W5OvELdQtcX+ob61JryiUFRMmKWphagg20Z84qg4auc=", "63516700C5CFA6F1BE71B29214957E33:eR9Otw83jJyrj808CkqElVYzlXztuc14/u2pDtPtooQ=:BID_295_Jellyfish", "1CE4B8636E40B4AF8858511CE01A98E3:+vewfAbMTec/enBaWVzzCxiHw8WLTJvfAWzFmcOJT4Y=:EID_TheShow", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Character_HeavyRoar", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_086_Athena_Commando_F_Hardwood_B_B7ZQA", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:Pickaxe_ID_821_EnsembleFemale", "2CB7CC414F921DD774957AAF4AD5F8FE:vi2xluuUw+pFj/tqqfvh7cS9Qnr8gQPEGX0IHyjZVp4=:BID_185_GnomeMale", "476EE53C2EAA24FD1950A9875FB4CF59:LQMwgWwsoSqGyYbBouYaMaN8NZ38Vy5r3Tqa7KA71oQ=:Pickaxe_FallValleyCharge", "9A3C083767A87B837556F6F97B75999C:NsRKnsTck7rKidUd4YH7UXflwaxXSN6RlIOGqAdoV5k=:Spray_GalaxyLevel", + "D41994CD334E94E006779079C2B900AF:mReRdgy/92d/henxH3XkFqyuCsf9qemZLXVvNnH17xs=", + "38C1A63C9EDBD8ADA477345EE890FD7B:ybsGbNtM7f1qvGO2FpNdhjiYf/ZQuRAXpUoikfNIwts=:EID_Sherwood", "6782F1D85E7DFD1D835C9B7B2A461001:zwni3LZXkLjSCnwE43DH3DqME9Z3zpCt2XOnx0VCOg0=:Pickaxe_LastVoiceDive", "B229884F839295B4B9EDC380B045C64B:SVmPvZenzQ5Si17i8daUFyKoOGDtaH4YZtsF1s2XkxE=:MusicPack_084_BuffCatComic_5JC9Y", "5950552B5A52A97A433715A1FF107BC4:p9RBdPmk5295pRSg0+Ybfwy/kqY6HBYiJEAkvy650O4=:BID_171_Rhino", "7AEE99564551FF8EE98E6887410AE8E2:Cumd3/0knsdwt4bl7zNQw8MKmmIuC/4wYVfVtQq5d2o=", + "F0B824739EC4211794DDC5EF2BCAFC9B:LXBvnxBXfdFlqcr8jBqbnblCnh3kvedCvkfJjIi/lEI=", "23213D7D8F739DE37BCA56557073DA51:hmmf08PTLeIAJgxwHIFI131jzcy1SbirW6EzJtm1teM=:BID_980_CactusRockerMale_7FLSJ", "E48EFA857D8E6914B2505B05AADFB193:4AUdytefPzWNT8c11iGtU4xcGNWEgzpMJbxTjUq3NS0=:Glider_ID_241_BackspinMale_97LM4", "E47EFA3166A5D7B35CEC27B19AC66AE5:JURSqAHhHK6YqLP5rKhCO+SQ2oql4NqJaoaeNGtsrM8=:Pickaxe_ID_644_BuffetFemale_TOH8A", @@ -561,41 +876,64 @@ "59299ADA0CB5BE70955E952C119CAFA1:MgFBow48P8D6E6wpzAu6Wk04y5ZYsYlZ0V9FK3hIQBM=:EID_Alliteration", "F395571A36D2BD888861E61EEBD45AF8:D/35GPTIOKbdfmpxRJmHTkjNXcWv+XdSmTxQt6z1hvI=:LSID_274_Skirmish_PJ9TZ", "1B8A454D42FF2E63D828ABF3B4A303C1:mWm/IpMJQylR4iuTbfEyjjj3TvMNGvPpLNVd1RGrHHI=:MusicPack_139_BG", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:EID_CattleJar", + "3AD37E40514304F7789E17FEBF4E4C68:4wGt9TLz7/cukkDMtB7Y8HZvi0fXNDMLsdCs6k98OM8=:Backpack_FastCheetah", "DE4CBA7A27B818D6B299767036C671A9:o7axeOYDdjXZ4MTWM4Io4XRNfQG2WH9qwPvBSJk8vJM=:Pickaxe_ID_841_ApexWildMale", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClassSecond", "7FA066BD68EDBE54C44CEAF5FDE591AA:MqrhrL7xbe11CZPwz1pJTx8M8yUHGe/VHL29VKlKVKg=:Pickaxe_ID_771_LittleEggFemale", "0EC19805A48534C8892FA21C75024971:WcebSI5r6bMgSAbNd8Ob187rYmIJFJciobdyQciRiSc=:Pickaxe_ID_268_ToxicKitty1H", + "5E30C7403A702908F7E67AFC6C9C5BF4:idycKoAyRb5uU8ZMsni1k54gQ0Q89xGl4xvp1gyk3ZA=:Pickaxe_FeatherMudGlance", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=:BID_876_SunrisePalace_7JPK6", "BA6DF4F82C5CAB3CE1C51156BFCACE71:SDOlhnlP1SENGT+SrYUqeGIz0TkgoM7dQjfmfxegb1o=:Glider_ID_176_BlackMondayCape_4P79K", + "1E8F4857F5C74E2E544D020B8594D855:OmR65gZfMr/YaejCOzL/ym2YAcuLn/zSNFTJLdTb1/g=:Backpack_MustardToast", + "FE4831E9E7D7012FEE138782AFA1109A:VoS2hBjPp+T+uFx1EfTAuvB6gjlEd2eA8yoh53VsjAA=", "F6838AF4144E8386A184FBB0823C15D0:IjzqnnHjZ+r6WC4He/JawOyR7LxeMbm5880cDGDr2eU=:Pickaxe_ID_174_LuckyRider", + "C624A3D18A8A2494288EE915D11518B7:/q+bDo9akBx2JId6QvLQW1YoN4jBEEn+QdzBXjB3OpQ=", + "5E30C7403A702908F7E67AFC6C9C5BF4:idycKoAyRb5uU8ZMsni1k54gQ0Q89xGl4xvp1gyk3ZA=:Backpack_FeatherMudGlance", "B8F307A56B6EEFACD6250B2E60A24A4C:ayYSM667dKzMIvm8ZUY0F+FNlvNsg4G2RMIgi2fPf8k=", "09D84C411F2EFF940F5D462000CA5BE0:6Djlf6/XCCTMpI4KbNEHN4X6prgcnfQtru+z+RTHs2s=:BID_736_DayTrader_QS4PD", "C6F7AEC922E28FB25AFBC50442F57877:qJNZNWzxSxvlrklYDsNkZek9OD8kGV6lI+Hfmm+k0gE=:EID_BluePhoto_JSG4D", + "DAAD9ACDD8C3690CE4D11DA2D7663DFB:OL1/ndG9SEBobBCmm/+Aqy67S8A6sebpFV4we3HFjoI=", "552DB214510DE1E24F08920F80B0AEC5:GP2CYv9xYYDf6bOnpgm0fnOXa3iI0acXH02ZIaHAElg=:Glider_ID_306_StereoFemale_0ZZCF", + "524E3ABF1DD30667B36C83F283B05195:psHqDFvyUISUa4Vm+z+e8kpQ/bxTybJYkpijcvRjHiY=:Wrap_SureBamboo", + "FEE2FF88D47ACD4788C23A72025AE3CB:cUGhkqZYUbnXJ4uNhMKeuDMmpzO/QqyQJXIW7d1X4mU=", "F0257C3CA050371B68517D5B0476A24D:EPU6cULjz63viMmdjtRwy6TagWogzeVnVX5nsa/leLw=:EID_Punctual", "36351B933FFCFF1746737649E9806CF9:2ZtfFqHREh2sKsMYN23yW+2Sd0OSNN5CHGd/qlXVd7k=:Wrap_TigerRootHue", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:Pickaxe_ID_326_GalileoFerry1H_F5IUA", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:Character_CattleJar", + "CD0AD2786C8ED5931FF0499050A273CC:VZIjLndy10Iw5/2y10V2EOA4Itr2jOgxB6cUUffVCDU=", "16FC688AE41A3E3C518F4DD9F9612EE7:Jd7nRLx/FoonA2dUjtbvJVk3nJoNq9LTedk3u4EdFS8=:Wrap_044_BattlePlane", + "A1892DD6A665D23CFAD3173CAD32B65C:br7Yu2bywwX6/gTgsF6+yOgvag92nHHBrNzSnQYvMl4=:Pickaxe_DoughDisk", "D517F2A448CCB9B47E5004894BC62ACF:qOdQUR91sysqDRELOgz/YVZ7Piae8hqcrnYW90fXtvU=:Pickaxe_ID_680_TomcatMale_LOSMX", "7B1151E3094646DFFD37B6492B117FDB:4WxNHdTgHDEpGjzIV2XIjGO41kyiwggFQpdq8y+o1jY=:Pickaxe_ID_577_TheGoldenSkeletonFemale1H_Y6VJG", "8D9CFEEB5299B3F8400B8E2E67B8A1C9:wwFluOAmcnXcGsyJRGJEmuC22cypzH4xThcZASR+IHU=:EID_Fishbowl", "57199980522FCA9E80C75A826BEA92ED:aR3U2OO9uGBqAYnJeTrUBFk6Q+OkpdmBavBU26DP0m0=", "6686344942A2886FC4FD4D3763A4890D:CphngqSvpV+b2+WsrC6THVlHtrbln/Gmei4th7IO6VU=", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:EID_FirstClass", "FAE51F5AC49A240384D5B57EA08B1F90:oesTf9AVGgX4FVwWzgm++nQEO0aARyuU5rZa1f6hoFs=:Pickaxe_InstantGravelNoble", "E1B1A5908EF6377D7FB29F776486A6A0:qaZB3Q+6kKTtlO4aGWBsnjSxCwX3kmr8oOF/2QDZ2qc=:Backpack_Basil", + "9AB2CF1E3AE8201C3815E433580D23F7:jHztEpUk14GSfxVNSQydmlFI6YqsrR56wZJTPP5HNf0=:EID_Obstruct", + "605624BEED560EAFCF45CAD7E2FB4E48:kfYhFrpDNLuCuE016d+F3Oh0NAcQl+TJbb/TFRfEjy4=", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_950_Athena_Commando_M_Football20Referee_D_MIHME", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_944_Athena_Commando_F_Football20_C_FO6IY", "98BA4AE4D7202053DB73B55D8DE72248:6UYqlPIbGSNPZBQWhHR4xZ/l3mJCnJ2O/7SEqRRInLY=", "DC953387B24FC2DCBECCD2CCF61BB973:GT4tz78+PbkMtjcHnlkhmwLG7lQAr7EwMEWIgn59PV0=:Pickaxe_RollerBlade", "5738A14C7E45E1B405CEF920829CB255:xZHlPTz/dxNahrp9IqTZ+tjOZSYMxQb9KZFXlg9N638=:Pickaxe_ID_330_HolidayTimeMale", "4C546A04EB0E91B7EB4449B672B63900:RhtdrUqq3N21E77X7YatI4oX3wLYyvFH5Wm+eaUX8+w=", + "431FB998877020823CAE2A8E617FC6F4:nt8uLFOjfjulunNPUZnCyrsdqPZxle2XNKZAlXZY9QE=:EID_SequinPie", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Character_BraveBuildSuper", "A0926AD8C6EDE29250AC4A0A93156E7B:keN/yZ7qnvcPZeIflsked9TAT867gbPgmnG1QdlSn3E=:EID_Donut1", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=:Pickaxe_CoyoteTrailDark", + "C73DB27E321E8B5D3747E2209CED62F2:sL+26G+2SaePYEPgaTi+UwMkAr9RfmVl3QK3fsLfd30=:Pickaxe_TwiceBaked", "A0926AD8C6EDE29250AC4A0A93156E7B:keN/yZ7qnvcPZeIflsked9TAT867gbPgmnG1QdlSn3E=:EID_Donut2", + "C4110935D0C729ED5C9C6DEFC3B339D2:1iYdY1JUa2XS/UHvjpQB+etsURaIAGX351sKopLNDr4=", "F4729DF9DB149229267F9389E3C95851:DCXGOUUTWG8jFuEryO+32mXKJsQgQe+Fp82u7mHiYFU=", "36126C339CEBD31F23562CDCC5DFDD4D:cuLUN7oD/p5BSxuk6pKGY6KtlhGInVti36sV6zSv1n4=", "EDF724493161095DB54E9613C243A355:Yp7dsOYO778G7uRZNYhGag2diT70vhu2hAWvkzvtHjg=:Pickaxe_ID_796_IndigoMale", "8C4383893F90632D5516AD37E0CD5173:JUTInt9XDGH6gUbZ040d4ptJRsuhNppIKKIw+IiYo8k=", + "524E3ABF1DD30667B36C83F283B05195:psHqDFvyUISUa4Vm+z+e8kpQ/bxTybJYkpijcvRjHiY=:Pickaxe_CafeStove", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourageOwl_C", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Spray_FirstClass_Raven", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourageOwl_D", "566C4D92AF66F45DF5E2D7EB43CC27AE:EuAYwU5tQBXzGoSj5BMc7S5yFfe9wZ2qrzx/hIHpnqw=:BID_629_LunchBox", @@ -603,43 +941,72 @@ "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourageOwl_E", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:BID_427_GalileoSled_ZDWOV", "BF344823BEE88FA8760A410311A30150:mcfE7CGJQLRE5dWZTCNPCCPgSBV7CMLl6lvpF+nzqzw=:Pickaxe_ID_851_AstralFemale", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Wrap_WarmShade", "F6E92DDBC70C8184E837D31905B2F2A7:UCSPatT+yv3YH2x0Ks+2GSXhSSu+3ZvZs6Lai3oOi0Y=:EID_RuckusMini_HW9YF", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_234_Athena_Commando_M_Grasshopper_A_57ARK", "020DE538FBEA2DA5CB1242DDBE527264:N8vfE8tdV6D+CX+hVEPFmOqM82o3lA3k/I/LhZHOh0I=", "5A1170F589134C4D68AAA2B5AA6EDA69:bfro7s6Qtde/H7C4zc6MJdpua1mhem8HywLluxBLDrg=:Wrap_298_Embers", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Pickaxe_TireSwing", "BE2C3EF59AB81D812AF5B8153325998F:W7NoICLZt9L2d7XZ5dT9gtI80MyOizk7uA9LtwA/Edw=", "958DC719715C145004E1E028E72464D0:ZTCrQKaSpw5dAyqyW/jGz+KF2DlvSX8wCW5/4dhdFT0=:Character_RedOasisBlackberry", "10B79AACE97810A1DD02E8A0E6093294:mgf5coTA3W8a87B7ZbnK8dMcRwToBBDjOH4qZoWLw9s=:EID_Adoration", "919FDAB2FDB531820404333B27DC7B06:W9Csp0y6agsgcQXlRGvYUpPGPImNdFfBsZ8yQoUEdGg=:Wrap_092_Sarong", + "EE1B544782238B556744A68B8AB52CD7:PGQPn8LVr8FLUROgBSOsmYcFi/BmNVWoBQ+kAl3uuIw=", "28C5CD0467F2271365DA8AC4DE122672:I1ujTTKWOz0A5LcFiCwKJXQl9bnMpW9yhvY13UaWo1Y=", "BFE1F518C16A9F061B140D829ADDB0ED:bHkPYjXd71vacoJ4IisL//zEyVLFh+Di8MUqV9KkpFU=:CID_A_139_Athena_Commando_M_Foray_SD8AA", + "47F6751F0EE3E8716C1B9DBC9796AAE7:1WNIILYMO4iCo2qkjP68IKxdCJNLjf1D98y3Ke/c9Gw=:EID_Reverie", "C348806ECD35F176A5C50306B0A07DB9:x8+m/v+Cn55R+CIZrsqqSKxa5JpkQyQGeLVTJ8evrpw=", "0DD695EB05DDF1067D46B2F758160F3E:H8eacvW3rgmZFvWGGwXfojcIBMrQUL+FJQ1x3dzzVm0=", + "CD0AD2786C8ED5931FF0499050A273CC:VZIjLndy10Iw5/2y10V2EOA4Itr2jOgxB6cUUffVCDU=:EID_Asteroid", + "8D578CF915DB851F9BE73C937D3565E4:Xk8kUK9cut4tXr0VQjufZdoepp+TzGmlDA7fzYA1rAc=", "857A238C0BA80D892571ACE78CD3187C:eLLEqOAgRjz78Z4YT6dLxL3DetAW1c2BM4oTPp912ak=", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourage_B", "3064E7FF7FD15A1F40230918DF236352:mMcGmrZBjxlJBFmWKqZHgcrcRvZKcHDIn9ampMMA9R4=:EID_Jockey", + "EE02264B5DA4FA57A4C708F9DD615A87:DjEzloaeCgNBk0f3zT6m7+6TNrxu7EAolqvbsNykcuw=", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourage_D", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourage_C", + "BA02A6A5604CB94ED9B9D7A197670870:OuvUXdw7gThaUToKPCUt6lZBJfOgKYgS8+fzL9cZZ5U=:EID_Incantation", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Character_DriedSilk", + "615ABCE79E307A611C31DAB9B5877EA9:zobIJOnXDLklPuQBNzoqQyAHSHAJV8RpHVvD7dxPFaA=:EID_Sublime", "BAEF248980269F569C6E1FFF2B885DF6:2b6DQGIcab1r7zsw5j3MR84iDmt0g1XBquxJVR/8GxM=:Pickaxe_ID_302_TourBus1H", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourage_E", "D47DF51158673BE6CD4D32E84C91DF7F:+EzQK4ojNk1DqxceQeArAGZhQPQyuQBKX4gVuGEqSxM=:CID_632_Athena_Commando_F_GalileoZeppelin_SJKPW", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Pickaxe_MotorMonth", + "1779D69116EC781A474EAD25440F4688:ld5vNZx7VDC5TOeZLfSgf1e9d6w9EC5j21Kakv5IOWo=:Shoes_PacketCrescentMauve", "6537263AA4E53B6A7B7D4AE3DE12826C:6WOQR0kXJWBJ4miykyUSj/hcH4u5JTSFpBTwaIeIFxQ=", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Cherry", + "97493B05A5BF87C5D621EBB9F9C93E41:dBxBB+UYD/PjsP2OuJDQdla12emz/y2TpYacnOKgdDI=:EID_Dimension", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_955_Athena_Commando_F_Football20Referee_D_OFZIL", "172B237342C2165A212FEEAC80584DD5:7bGmK+J89yojl49SMoQKA+Zf7ZZ0W3OatE6KZYlGPnU=:CID_254_Athena_Commando_M_Zombie", "504BC0A80EE72DFEEF9CB7EE3FFCE163:eToIGihi0lTVTcHietksl1e6cHBf5h30aYO5YXpWXY4=", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:EID_RelayStick_Carmine", + "FDD3BDDFD277F404F7A8786FFFB285F9:9+DbcptOICqGuz5B0I2KDRKyJHkprRB9MGYDI+1EkEQ=:Shoes_TunaCabinSuet", + "4744CB522E987917912D3EBE55FCCDD5:BFGkHDsAwzOlBSItXyryOVhlhUCsILkSxXHFys5JwSw=:Sparks_Keytar_DerbySwarm", "E003ABE22717994943D06FA3F41D1CB1:Z0MoyJ24D89oC5rAOJK09jo5/TLV30z2f+IwDeJ/4GQ=", + "92034B55AFBF9B8D79879A805EA50D70:P/SfT3IbWKQS5QIE00cDT/qR5omam1FlCNEbmK44Yuo=:Backpack_ElbowChatUniversal", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Character_BraveBuild", + "59881A06EBD2C9A333EB1F04A6409265:E18NXuWZnSlrdVJXuh+1y1xFiQr0luqH7/Cx36ta9Vs=:Shoes_StemDotShimmy", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:LSID_404_Gimmick_GXP4P", "CBFF239A1792F25920D863F223368B54:J3N3cUH3M0R3uyzkE0qVK/SouxC/X6VEswcoWb6ViL8=:Wrap_071_Pug", + "73424C54CA2C14ED412BBB7BFD7A8E6C:+diHC1ZDFACOa/hy4nEP4CZlHcGOSrcClWY2hCMKdVI=", "ED088B11311A599D6225CE85545F019A:1NMRh4JMXRL9XW8Kb6zo4/F10dwLJC1+kPm6D6DudCE=:BID_832_Lavish_TV630", + "0F1A245C2EF5E1635F88A4612C7118CB:yb0A6Tudez3ki6hoyqT4kUQnI/AZ5SRBNeVOxskvFtM=:KelpLinenMagnesium", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_StrandModePeach", + "205E83E941E613D6DDF175294CD7B508:W/HdfArXSwvG+c+pTX+3aNoJawu4lPsB+cPWpnMBnZA=:Pickaxe_MistressSombre", "8ED082067AC31EE587FE16E5507E95D3:/uvcdfyt+d1foHxwO3zz+Y0PUr5Jzz/yES0FyaLelc4=", + "35182C05BA21A7373CD33B20303E6944:oOAKjS/mrGU6Dk/c+XiIcs+xgvqyI8zmt+pnR5VmPmU=:Backpack_ShakeCrunch", "03DFE957E1454D5A0486358ED5DE9C56:xz1aeE5HU0Ej/4kp/WXnsZhLBh7+z+aWVz0G1xOrTB8=:EID_Promenade", + "216BD226A5871096D185626C0C8D9AC8:drRYu8RzkumLbGMOX72zbTl1UxT3NaooaCZjzyVMchU=:Sparks_Guitar_UrchinQuota", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=", "36351B933FFCFF1746737649E9806CF9:2ZtfFqHREh2sKsMYN23yW+2Sd0OSNN5CHGd/qlXVd7k=:Backpack_TigerRootFame", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Backpack_FreeDrive", + "AB2F922860753269B1C2335CE5C0DD5D:/gjkRNAVhMsWlhPkX61LzAkKFMqdPyc9nNGgu+ahHd8=:EID_Melody", "D47DF51158673BE6CD4D32E84C91DF7F:+EzQK4ojNk1DqxceQeArAGZhQPQyuQBKX4gVuGEqSxM=:Glider_ID_189_GalileoZeppelinFemale_353IC", + "EE02264B5DA4FA57A4C708F9DD615A87:DjEzloaeCgNBk0f3zT6m7+6TNrxu7EAolqvbsNykcuw=", + "F0B824739EC4211794DDC5EF2BCAFC9B:LXBvnxBXfdFlqcr8jBqbnblCnh3kvedCvkfJjIi/lEI=", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Backpack_EmeraldGlassGreen", "5D6562F1EAD89513C82C2F37A24E7F82:I2c+SQCdDvJpC6z1xniRT+k41KAp0pla+o/H68oXFLQ=:CID_649_Athena_Commando_F_HolidayPJ", + "003C8A31FF60E8C3BDBF4FB76A7CC4B8:LAKZR/gRSm44vZpNg9z39srsStFM7n68AVmC/yYDNSM=:CarSkin_OctaneKitty", "BC3890EAABBF03778EE82AD7DD4F9C12:RvtEdiKkxLJDnXKUaUK933vzLK04veYzbdp8yN8wmxY=:Glider_ID_376_ChiselMale", "5950552B5A52A97A433715A1FF107BC4:p9RBdPmk5295pRSg0+Ybfwy/kqY6HBYiJEAkvy650O4=:Glider_ID_102_Rhino", "E7D27A42770632B7A50BED813D9B1696:bxADNk9dmPNeKEuSvJl44teif6sHvs36yBZ55E9fhwQ=:Pickaxe_ID_775_SnowfallFemale", @@ -647,64 +1014,99 @@ "F395571A36D2BD888861E61EEBD45AF8:D/35GPTIOKbdfmpxRJmHTkjNXcWv+XdSmTxQt6z1hvI=:BID_702_SkirmishFemale_P9FE3", "DC060EA83FE6F9729B19150E40C7987E:zW3d3QhtvhE+q3x/P7/BA9JvyoruVmeACdKt6RPxyLY=:Pickaxe_ID_769_JourneyMentorFemale", "8D9CFEEB5299B3F8400B8E2E67B8A1C9:wwFluOAmcnXcGsyJRGJEmuC22cypzH4xThcZASR+IHU=:Pickaxe_FishBowl", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:EID_SatinCheddar", "9E6F84C908A6CEE29032FB050FBC2EBA:GXZFI6Jhfg/HnSTK1cqbpa5Ay1GzLco5sYtY5RPTcfM=", "7F5ACEFE3F67BC0CCEB59A4E8EB82BAF:iDG2HB2LypEtzw5/EjKVpJmQ1o30BE3nVv01rOTyq64=", + "92034B55AFBF9B8D79879A805EA50D70:P/SfT3IbWKQS5QIE00cDT/qR5omam1FlCNEbmK44Yuo=:Backpack_ElbowChatUniversal", + "205E83E941E613D6DDF175294CD7B508:W/HdfArXSwvG+c+pTX+3aNoJawu4lPsB+cPWpnMBnZA=", "63722D44ECCA0F4178B85F5A6BC4C31B:j42UL0bmfBkli6Aj92wWABwFby5rAplP/Ac6nh9kRvA=:Pickaxe_ID_661_VividMale1H_ZN6Q0", + "856E286187F84C14D7808F68B4F04154:2pDSaP8YgyGgqluL0t52LStcOf5O2qQ/bA9Y2EwpJNM=", "EBFE6788D367D741AF0A4FD098CDFD39:FAeJTGyT49P+dQOmKx+lMYVAxu7qtIPlqSaLAR85zqI=:EID_AssassinSalute", "3AC8A6B5089F55E17E00AAD8AC3C6406:TlUSkJe3y85fW83rHMy+XuqcZxQduXcB8yftpPoiDvo=:Pickaxe_ID_399_LoofahFemale1H", "1A9B01B59F609C0D7E9EF7887DA23087:EkQdXhPD9Je6Bp7dlwZdlkX2S0har6vqUOjMIF9ndfc=:EID_Ohana", + "36A1455D04820E3D498C146613F97D3A:1wqflYVZsPsUy4tkHkNgFNj7CC5lyh0fUAFJT1UskiI=", + "0A6F8755332638E42FC052470B3BD065:OGqX2AuHNDfNO1iagEg6fwOr3Ib0s8/5iOBLnDc0vSE=:Backpack_RareDelight", "ECE91B4E506E33C16FA440F4B4313824:dGr4XbhLD3sf28Y3Tawke4Gr/TpwEA5xPOjhgi+ZAKk=", "8DCAE39C7D9690E19F52655F02C613B2:ZZHbiVsbXquLlrtNVHtryLS3Vd1Ego8/8tlDpeUCgfc=:BID_336_MascotMilitiaBurger", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:CarSkin_SourdoughAW", "06B9F77E165673FD1C5FF5099F43D1F3:Bvw6h4GKOLjC/wFgHQsiLePbBZhtPiNhtr5keDBse70=:BID_421_TeriyakiWarrior", + "67E6E3BB6F124A14AA5C077219A41814:eg6SwkhZyo//UwwX1hm0vg4AC0N++fDGUFOdApZuk+I=:Shoes_BreathTaleYarrow", + "BA02A6A5604CB94ED9B9D7A197670870:OuvUXdw7gThaUToKPCUt6lZBJfOgKYgS8+fzL9cZZ5U=:Character_HeavyRoar", + "615ABCE79E307A611C31DAB9B5877EA9:zobIJOnXDLklPuQBNzoqQyAHSHAJV8RpHVvD7dxPFaA=:EID_Sublime", + "F51C8301B1C9BE9D4C4F48ED2C0FE067:+MsgNTH4cF1Mr4mjNVZVgsf3GBgjSjYn2yRZn2fE70A=", + "691EE5E7D12D2AAB8094DC5C5C3294EA:HfnFjC+/ESL7w3qqsV7lXe+/SGQARJInAJ2xHXZvHJA=:ID_Booster_Big", "FF5A507BCC4519B928075C3DF4603E8E:EVv5b8WFOYZlDUGRqb8YUS1WbIbbT8TjgoBWEQr65zs=", "09BC93B3441ECBAC30FA23BBEF59CF89:3CHInj+JfLspiVCNDY/GTZ4Pn52nWFeA4qYI0SJv2dM=:CID_302_Athena_Commando_F_Nutcracker", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=", "CB34283BE466D2421549051C400A9E52:rTmyRzx7oSiBWRv52itbCbAFlLIy7W6dZoDcfyTMmyo=", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Backpack_FirstClass", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:SPID_403_Lyrical_BoomBox", "74AF07F9A2908BB2C32C9B07BC998560:V0Oqo/JGdPq3K1fX3JQRzwjCQMK7bV4QoyqQQFsIf0k=:Glider_ID_158_Hairy", "464F39FB64FAF4AB6843449EDD0BE3BE:0yYMEXLHteghUwUW+SThzKXltdNzvA42CssFpAXgxFA=", "ECC9E1F04B18E523B2681C2037A17B56:AoeVhWzK5zFpeJ2yqYKkTaRw4vo9162/EuipYvC+jxA=:CID_602_Athena_Commando_M_NanaSplit", + "1E8F4857F5C74E2E544D020B8594D855:OmR65gZfMr/YaejCOzL/ym2YAcuLn/zSNFTJLdTb1/g=:Sparks_Guitar_MustardToast", + "875A2044382363BB04B7E1B02DB7F905:2YtCtIxaCocZA54jyloILrq30zwBJx3UTRVykYiVy3k=", + "FC29F85DE0913DA71729BF081D5BC360:dRhUrL30ANekfjMYS3BDfuxUy+jokPGyY1Qt7OYfoqA=:EID_Caffeine", "4182D3E699CA4C6022FC4CC2C1E6FB90:to8QORwARsWs8Ox6EmJj9V6DvB4yWqTYHlLuNKAawss=:EID_Malleable", "32E8846645441197B80CF8B1C86B01A1:cwJgOQhsrscdiFfLHzS9WudnE9mBMH/C/SAyX81B2fM=:CID_311_Athena_Commando_M_Reindeer", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Kiwi", + "FDBD57427BDE16DE844378F86FCB0A68:hMBzcobszznKSG38eDbd58S+IqotV6qURXgpshGDmnY=:EID_Lowrider", "FAE51F5AC49A240384D5B57EA08B1F90:oesTf9AVGgX4FVwWzgm++nQEO0aARyuU5rZa1f6hoFs=:Character_InstantGravelNoble", "B9E5ABB4D4F783F13E7A32B971597F03:HGWfy8LBJu12s5HZeYTZDqP2EI3dJqPXupxd2AzYdUI=", "C7623A35411F3D5FBDE2688C7E4A69EB:qAi49mUKsB2dbfbtJWDf3yO2DfRStA+Ed9XgDjC8Zaw=:BID_190_StreetGothFemale", "234D1D3D37EFF3322E44B31200C1ACEA:T3lGoZ3JIVg7vasMQCr3hjyRo8x+HS1Arh43XvdUKss=", + "11A2A4F6D2D907D8718A91CB05AF99F0:psD4DdrmKRTtrbaAkoDjTtrC0zZAclPsWm93aw/e6hA=", "CBAC886CCED55EEAEDC0D4BED9588035:+5bLkb9JJIJBPrVxzvfhb0CkKU4ITf8SJRRG14UzyfI=", "BA490514EFDA436A2679E381BD558AA3:3KBKxBOi/52H0feJ/ijKxRHk+lF1zID0uIpjd0T7/Bc=:Season18_Haste_TrickShotStyle1_Schedule", "35C2B057E5168DCA74B6F1DDAC745E60:73haJlY3S0TVmH0ELxyw6p5FzFRrITWqOmobH9F2Mq8=:BID_936_KeenFemale_90W2B", "F33B69585B65C333655C545A038BCEE5:0+gUoAUkiBbY5uqO9rIehUDkvrr/PY3vBY16AMHQASw=:Pickaxe_StallionSmoke", + "8F7AAC929AED8C9231EA30CEC0A2A75D:1HeufgQ+oYCTosTR/ILGHFnypvS+udjy1Tsyffya+qs=", "D14FDB2BB2FB7746797F25470913BFF1:CQDgIxcNnAoUboQnjafZAYvV7UqX+NefGTXFd3m+oFc=:BID_907_Nucleus_J147F", + "D427D67AD5777D1B1B4F1767FA4B20F1:usaLfjFT9fTbvIbFvHr9GMFI/MPF4iYldSmsrADdzn8=:Shoes_LungeStreamChord", "DE4CBA7A27B818D6B299767036C671A9:o7axeOYDdjXZ4MTWM4Io4XRNfQG2WH9qwPvBSJk8vJM=:EID_ApexWild", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_A_004_Athena_Commando_F_GlobalFB_D_62OZ5", "36351B933FFCFF1746737649E9806CF9:2ZtfFqHREh2sKsMYN23yW+2Sd0OSNN5CHGd/qlXVd7k=:Pickaxe_TigerRootHype", + "1AAE4EC52903C3E43A4EFF4C124A23B3:sJi1b1Bj+nNygVSKfw27CS/HQQQ6JBnIWYh7VXJK6CM=:Backpack_TofuResort", "D82BF0194AE18598B8B08491E2256E16:3ENJiAAhBVgbroE9WbkjWK5YqL8vzJ0sFKhadRKcQjk=:CID_255_Athena_Commando_F_HalloweenBunny", "E46E6578D28965DB74B642E1CB239A5D:Dg3Oqkcno7QuLDGdi4N4VWSMSAd8bILyJT8Gh0PYjj8=:BID_758_Broccoli_TK4HH", "F3A99CD0D4F58EECEEB0D112506AD846:ZZtCRPcKk6itVryDavp7uZFIXiZF5CW0O9b+8Zt2Oag=:BID_820_QuarrelFemale_7CW31", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=", "772E01C212E9A77A501AF954ADA90B09:nQ4i6bbmbGMzcq8iyjoM/BGUbX2DSIJRAZ96/qaOf/Y=", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:Pickaxe_ID_733_SlitherFemale_M1YCL", "0CAB99F6E84D4E4C616B895E243F3B67:DWU31IKjnLsEt8sBBDfWQ3DPbZzpJ2JmfbxYdQ8QPZI=", + "F418C01DC7E0766DCA8D731E61DE5748:aJhBCl7XcguoBT4iKwe6EuEX/3fZs++b3wFl5QUWp40=:EID_Rotisserie", "61D055FFB6523C2E6B09EEEF500F82EC:mD5hivRGMT21lNyWjRs7eYriBFTVlzoINDBB9DSFPAA=:EID_Clamor", + "955C5EA2C28764221AF554097C5CE9E6:jzkT7NbAZpMlRIC/qnSOUAcAz6CXh00ZF3EK+GfWbGQ=", "8DF1F1277DF980247E3117412EEBC87D:zkBSgRftUEdB3dqaelLwaFIxyVv3AwDbdcwc5hsg++k=:EID_DoubleTake", "3D9634EBDF17C26278CDFE91EF0130E8:tVvwjIulbvPLmBKlFhBwKSOGqzCu5yu9CqdH5008u5U=:Character_StarWalkerFNCS", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_350_Athena_Commando_F_TreyCozy_B_8TH8C", "FC4FC301558D3E9321A55180263EB17B:OXujupiNRNT6+b1g1dg2IXPtdQyfoNPUuvtgqfXnlEY=", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Pickaxe_MotorMonth", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:CID_445_Athena_Commando_F_BannerD", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Backpack_MotorMonth", "E7D27A42770632B7A50BED813D9B1696:bxADNk9dmPNeKEuSvJl44teif6sHvs36yBZ55E9fhwQ=:EID_Snowfall_H6LU9", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:Backpack_ButterPlate", "C23FA9BDE9342B508B8AABBEEA6699A2:3mRtSSu9PTBlC3NpGAQcFent660Ptni4HbGX+Zj1KIA=:Wrap_404_CritterFrenzy_SNXC0", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=", "72CC2893A6B672F3854F36629B770774:0BgQgKZRRuPFEoqn7CxZVhLBOfpCE3qLKGQlZc+SA80=:MusicPack_112_Uproar_59WME", + "527F2B6C4F2C5163258E0DB828A68B6B:esxPRVcugQm0txRgx2TKdd5eX/bC1+oprtZTI7/wC/8=:Wrap_ElegantLily", + "CBDFCC904B6577B868E32565F7F4605C:X9reH4gk76iPpnKnYAsl809qJrERyvIjFZq4H8JElOw=:EID_PastelGlaze", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_StrandModeAcai", "63516700C5CFA6F1BE71B29214957E33:eR9Otw83jJyrj808CkqElVYzlXztuc14/u2pDtPtooQ=:Pickaxe_ID_223_Jellyfish", "5C0BC5E8819B8968CF25C60885F0CB5E:E52Ld2gtMzMFUMkdMpjNWmEHEgr1qnH+iliH2ha27dQ=:Pickaxe_ID_275_Traveler", "419008D696C27533DFEDB08BE4F6C8F8:5I7VZNrdz8oZdzk1TTNCKkZXokilbXLFy7dQPPPlpuo=:CID_A_314_Athena_Commando_F_NightCapsule_TAK2P", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_352_Athena_Commando_F_TreyCozy_D_2CLR3", "77C937AE673A9DBFDFA373E0FD928533:JGgyzNZT3oLg4LqA0W+d/caWWhqIpiXNOyYtzSeZ4po=", "7F2E96A8331098ACD5BB8DC29D4A3F57:kDTbN2yRZAIwEEQsF2zoJwdhtsK0lcb5zEuon7vziuk=:Backpack_FolkEveningSheath", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=:Backpack_JazzShoes", "258AB620A71C14508FB6614003DCD34E:fjPUuwSZbKfHlvSh8RMyVjR2SVTcVrGNpWvyjNVQ8Xw=", "C66F354B49A4389E7636C1BF53CE8D97:BisMzLIPd3AuIv431ryh7DE1h1HYe/NdhBC0wkLq/zQ=:BID_204_TennisFemale", + "C4110935D0C729ED5C9C6DEFC3B339D2:1iYdY1JUa2XS/UHvjpQB+etsURaIAGX351sKopLNDr4=:EID_Perish", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_307_Athena_Commando_F_Slither_E_CSPZ8", "1162D72490AB6D040106B276D14B20D2:UoybfdmMPLyXmLpTKBZB0sqSOvXnKHabF/nv5olkuoQ=", "6EDDE286471D1369B09E65A6B02686CF:2MDxhxeBxx/dN+Q/lwCG+poxzpStEQLDM0L80CoaEG8=:Pickaxe_ID_152_DragonMask", "88E5DC354F07186FFE1EA93D874832A6:6FGm7/RIAkq2nYksl+dkuTvBSzgmz/DxPQ4iskMBwns=:EID_Coping", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=", "E8585F83E40CD4CF0272EA6012055A97:4LrXtLEBhL5JquAu4/kq1Dghb4/355YROt3ciXg+ysE=:LSID_429_Rumble", "5D6562F1EAD89513C82C2F37A24E7F82:I2c+SQCdDvJpC6z1xniRT+k41KAp0pla+o/H68oXFLQ=:CID_650_Athena_Commando_F_HolidayPJ_B", "E66DF3CF1BFE84F0B1966967210DD6D9:DGLD/iFbdLvaiZnAfWrHIW5yJ5SfsQQyjeW2IBQe+zw=", @@ -712,24 +1114,42 @@ "6B91F0DFD2780364EC6FC5E531665208:sBhYta4JrxcssCLVBkFXeJpKa7gQKHepqu9840vo6h4=", "01FC97F8787B82E027EC64661E0D36AB:Mh1l2LJ3YrgaZtg7sRTd8XeBkVcyA3i089gZKkTr1gM=:Pickaxe_ID_783_CactusDancerMale", "0D8B24BCF7F9C0293FFE1264A5D05613:v1sCSrsgI0QbNZ+4v5lllwW1n7M9dagX4GsxY7/oR/4=:EID_SpeedDial", + "737D758CBCCFF589BCDA9236930EDA52:KToMoMliD/DoJnxL11MpgqgCsHHUJFhJxj8nkixIKiw=", "5332028CC33C98BF747EEF82B0384D8C:QxdEIZba2DLRx0jYKm8UpIk/K6eKuclfvDSTllMLLrk=", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:EID_Galileo1_B3EX6", "A758D2324A07ED9DE9E0818F6856693A:ZpzBR4QHXooKIZ6RXd8kp7WBPvsY8PQfKPE4bRfkGks=", "BA6DF4F82C5CAB3CE1C51156BFCACE71:SDOlhnlP1SENGT+SrYUqeGIz0TkgoM7dQjfmfxegb1o=:EID_BlackMondayMale_E0VSB", "623074E0279E883B3D226528E72C540E:V4BT7BTnF+UsutYrHzcE2k49K6nNASWtF7HLYA+doyg=:Character_GelatoCourageOwl", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Pickaxe_NutmegMayo", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:BannerToken_015_GalileoA_0W6VH", "72FCE9EE6B90885970CBD74AA2992B68:UvFcOwG78Bx6kVWWHd3NsSarAeWZAht32WLeqs0Opoo=:BannerToken_003_2019WorldCup", + "2071F7A7C5CCCDD3348461241F90CA95:5gfMp4/23HkRIin3rD81b4UhuH8muYsjZUQnyb58mg0=:Shoes_StemDotTempo", + "020BFB18192345A6CF1AB75A66D879DD:T9UgbPCAqJBtxypUfcH/MqLBL5D8dc2rh8H6/La3FDk=", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:Pickaxe_CattleJar", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Sparks_Guitar_MiddleSock", "BC3890EAABBF03778EE82AD7DD4F9C12:RvtEdiKkxLJDnXKUaUK933vzLK04veYzbdp8yN8wmxY=", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Character_WarmShadeWagon", + "92034B55AFBF9B8D79879A805EA50D70:P/SfT3IbWKQS5QIE00cDT/qR5omam1FlCNEbmK44Yuo=:Wrap_ElbowChat", "476EE53C2EAA24FD1950A9875FB4CF59:LQMwgWwsoSqGyYbBouYaMaN8NZ38Vy5r3Tqa7KA71oQ=:Pickaxe_FallValleyBlink", + "1AAE4EC52903C3E43A4EFF4C124A23B3:sJi1b1Bj+nNygVSKfw27CS/HQQQ6JBnIWYh7VXJK6CM=:Pickaxe_TofuResort", "82669F5A2F9B703D1A6BEA3BCB922D7D:Leu9rrDPaqZd3izIU+IKpFcP/NNcqSncLkV2lapQL6k=:Pickaxe_ID_221_SkullBriteEclipse", "A6E8A0C1D732A1D028B92BE981E0B8E5:3u9E2vAzuE3Vl8sOG4jzX2RiiA+GFyukOLeOakVOf3I=", + "9FF6F385935B70741BCE31AD20DC71E3:ppSFNf1khIjuH1ke7/AqweruSJw8WgP2Ly3CAiaRGqE=", "3988E0693BAEB40EB8FB796CF560C182:KjMkLsAOZrfb9xvTWaNmqqceJQz5RSIJwC+1md9kMs0=", + "540DEA2C5E3510D32704C41A4B323118:GWPcu+VRPtu1WCOiRCJHR5adSzIp/4ndXT7TLZ8uDb4=:Shoes_LungeStreamMezzo", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:Wheel_Law", "08788A9DA34F4164ADA4F09FBF698CC3:DlhRrdBGDNADUAMRj4oAUwwR2j33Nr2ZNg2CU3i1/Pg=:EID_Quantity_39X5D", "36351B933FFCFF1746737649E9806CF9:2ZtfFqHREh2sKsMYN23yW+2Sd0OSNN5CHGd/qlXVd7k=", + "C50EC9789A634E9BA829CD5C4653C248:1pqFVcUR6pJ3zNoBgu4bFffbIANvAfPO4BtqvPON3IU=:Backpack_CashewRoll", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_349_Athena_Commando_F_TreyCozy_Y4D2W", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_347_Athena_Commando_M_TreyCozy_D_OKJU9", "BE2C3EF59AB81D812AF5B8153325998F:W7NoICLZt9L2d7XZ5dT9gtI80MyOizk7uA9LtwA/Edw=:BID_872_Giggle_LN5LR", "9944BE1C4E9D73E4FA195380EF0B7BBB:LQxoRi0ktKvKMLk6hauL2Gzs6zf5bcEk3mgfX0We/uc=:Glider_ID_122_Valentines", + "01BFE5778953E6E4310E890657496793:Dc+/7D98AEx9/R2kcOfmRxINEF47v7JzU9VahKdGVC8=:EID_IcedTea", + "2DCF5899864B58847F7721F5BC6CC7B2:0p6RYJMTG+ET3tlmONyr92cZnYnz+AV01JZgOtcemS0=:CarSkin_SquashAventurine02", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Pickaxe_SweetLetter", + "0B41D34A225C92221083EE4627031631:Jtsu/YOCRrqB4dvLeKEzb1O8ZD0xfZUbp8WEhIrVPN0=:GameFeaturePlugin_Kiln", + "67E6E3BB6F124A14AA5C077219A41814:eg6SwkhZyo//UwwX1hm0vg4AC0N++fDGUFOdApZuk+I=:Shoes_CleverBite", "340C0957F37B985956E74242A9487B5A:CiISJuNPymcbI3tJAxIaNfGCcHBr1ttSFr++4c5DQx0=", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:TOY_Basketball_Hookshot_LUWQ6", "9A3C083767A87B837556F6F97B75999C:NsRKnsTck7rKidUd4YH7UXflwaxXSN6RlIOGqAdoV5k=:EID_GalaxyLevel", @@ -740,51 +1160,91 @@ "30A11EE8EB62BEFD4E9B09611DB13857:YVeVPXcP7UoJTp71ZXpGNdPVzmjnRyymcUpsNWYXfRs=:BID_506_DonutCup", "30B53CD6A14D4EE40C71C60E9EE0DD93:RFvcbS74Q3YPnQpxUbhafzeiqVYKv6Fxukfi77h2TdI=", "29DCC9CAE821CAF43197545BAFB9CDE1:i9A5h7EdSe56nquoLOHdmUB6HKB50OzHpQMLXDjSQkM=", + "083635DE237C87482DC022635E04BC7E:nq1PRVTTrU7eagnKA/IO5GYjFPF6Xd2mXDYF7YrnumU=:Sparks_Guitar_ShrimpStroll", + "52366B48F1048E512A4ADB69B1830522:4/yBC527LoHOBvjPVZZOG3vqIFRZMYJKlKuD1OgYK9Q=", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:BID_851_TextileKnightMale_MIPJ6", "604C6242EB2BF301BB5D4BC6E3AC5A8C:Y7c2+dviThEDuVsG9kIOjMfnLdJUnPMbdaY5gKiVki0=", "1050DE04C393D98D22D50388175B4834:aFzCQrL5V9QxBU7hrblnr3x8oWjKs7MjQrua/tyBEQI=", "419008D696C27533DFEDB08BE4F6C8F8:5I7VZNrdz8oZdzk1TTNCKkZXokilbXLFy7dQPPPlpuo=:CID_A_315_Athena_Commando_M_NightCapsule_B31L1", + "15AA9676F80B50171D3C21E3020906B3:dxtfRaBfeVi5P6F3NAUQBa1lJK8ed+8HKeUNI8zYNBE=:CarSkin_OctaneMurk", "027FFBB49E4285146DA1C5238EBB7DB3:yjcsOd6x9bWnX36cFx2Q3/zgHrCrnuWwiuZexrdcM8s=:LSID_398_UproarVI_5KIXU", + "A871664A8BB4DC1C1CCF27F042ACA0A2:kqojoMJlkGDSIoGOX4MtyijAonmESRrvh1pdCYpad24=:Wheel_SassyA", "7FA066BD68EDBE54C44CEAF5FDE591AA:MqrhrL7xbe11CZPwz1pJTx8M8yUHGe/VHL29VKlKVKg=:BID_976_LittleEgg_Female_4EJ99", + "15AA9676F80B50171D3C21E3020906B3:dxtfRaBfeVi5P6F3NAUQBa1lJK8ed+8HKeUNI8zYNBE=:CarSkin_OctaneMurk", + "E102B1E06DF6DE4271AA258E901BB96B:Dp6C96jATrF6zgIpThdGahFFFeWkoBw72w8EvxmtGN4=", "FD0C3696948675DC3C2CBF5098D57D0D:rBWyTh/AVyZxi2oiQxM/OeD/HYZOSdVidEQeKoowV6U=", + "18657B021FD5011618877BD5D709EB51:6tLEm1BTY8+Go2kUChsjNEQkZJcsN31oLw3AorwxptQ=", + "2764E12E58C474C6AC7F5035A80A78A2:IoFlZq1ZK8Z/q1LHzNxRujov0bxn1r5mRyW6UtNmzF0=:EID_mesmerize", "545B9777127F4BE242F802C627356B7E:RNI/KvLEXcGoGnk3/AKaYbyJmXMtQl9Zmvl8ErePB4g=:LSID_360_Relish_FRX3N", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:Backpack_RelayStick", + "11F0730066B941C7A4E9255EA2FE23F1:/3vLdT+H+32W0x68sm7cVpBYK1amMPmcVTviVyM25dY=:EID_Memory", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Backpack_TireSwing", "4F53A11AB9CD08FA18D603BF29415366:mq1giTyk7GAqrpXphg9STetDQnhFBS5M1SYEHM7uYqk=:BID_251_SpaceBunny", "B229884F839295B4B9EDC380B045C64B:SVmPvZenzQ5Si17i8daUFyKoOGDtaH4YZtsF1s2XkxE=:Pickaxe_ID_588_BuffCatComicMale_12ZAD", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:Pickaxe_ID_491_YorkMale", + "6A2047910081947B9A5DCF542A9AEBE5:V/jMTWL+zbqeIlKCE9+SM3+X69aYbt/cN0+G1D0GBQU=", "545B9777127F4BE242F802C627356B7E:RNI/KvLEXcGoGnk3/AKaYbyJmXMtQl9Zmvl8ErePB4g=:BID_873_RelishMale_0Q8D9", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=:Glider_ID_324_SunriseCastleMale_2R4Q3", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Wrap_FreeDrive", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Pickaxe_FirstClass", "768A95DE7B657B7B23D5A0DE283EB49F:JLLAz46a7wo2rADQvCkbp4IbKexr7J5bBr6d6toSn50=:Wrap_049_PajamaPartyGreen", "F07BE27DCEFDF52818EE7BA2CD9CA504:lc47A/VahaBWJLQY4V1YyjzJPI5xVErInDaqdwPjv2g=:BID_255_MoonlightAssassin", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_BreathTaleLinea", "2CEE3C1783B9E41EB66238BAD32EFF23:udlTL9abg8LIGytWpERMGVEpPrj9io23R2HbINHtF3o=", "794E59D9FCF36814F264C9A5938124E5:uHr4c9XJ/zNCUImzwZpzrUfQRcZ2j19dLN3CTnKy1Vk=", "E28AF2E3BB7EBBB69D962A15879E696E:hJE3fnZPwRmG8XIw+RJvVsCh9dOHDD82VAhvMbi+nvs=:Pickaxe_DualParadoxGold", "86588ED13DD870C5FDBF91B3C739D156:HFqg2udb5qqasLf+D2jzfRahu3HgBZWZN2AvnSUIIzs=:BannerToken_002_Doggus", + "E102B1E06DF6DE4271AA258E901BB96B:Dp6C96jATrF6zgIpThdGahFFFeWkoBw72w8EvxmtGN4=", "CBFF239A1792F25920D863F223368B54:J3N3cUH3M0R3uyzkE0qVK/SouxC/X6VEswcoWb6ViL8=:BID_276_Pug", + "B9A0974966FFA6519F942CB8ABC6DE65:qS1fmsGLl/R3z7jYOVJZ2i/D8+MqOzylgmBr7NZrqRA=:Backpack_SwissKale", "E46E6578D28965DB74B642E1CB239A5D:Dg3Oqkcno7QuLDGdi4N4VWSMSAd8bILyJT8Gh0PYjj8=:Pickaxe_ID_597_BroccoliMale_GMZ6W", + "64F68FB4F73B65DF1A6CABB6871A3839:mKJA1aXTjf7p/0EEIy0g+ZS1dRHF9Ju9SwiQqMqtgUc=", + "0C8FB41BED80602548CCB764A876CE40:05zgxQ6Q4m+LULvuKwRlaPiSa7wZBN2fy6sG+rxR3Ng=:Shoes_StrandModeGuava", "16FC688AE41A3E3C518F4DD9F9612EE7:Jd7nRLx/FoonA2dUjtbvJVk3nJoNq9LTedk3u4EdFS8=:Wrap_024_StealthBlack", + "D71B95B305E6875284CDF3F28DBDC2AF:kK88qPTK/QH3MhsXnueQR9liR/XAeFhyNEkWAFOLvzM=", "A2A3968C8EF4EA9F7979BC1FC57B871D:xVURN9OBgLtbyK0ZR4bqMgsZpL/SJjlIXf1WGEpfd6I=:Glider_ID_139_EarthDay", "545B9777127F4BE242F802C627356B7E:RNI/KvLEXcGoGnk3/AKaYbyJmXMtQl9Zmvl8ErePB4g=:EID_Relish_TNPZI", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:EID_Gimmick_Male_8ZFCA", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:BID_952_Gimmick_Female_KM10U", "5BAB7539D98938E909D3541E69214830:IgABlZz2+aRehC7vxw4p63pXUZOZFwdATQWkTfTYP30=:EID_SpectacleWeb", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=", "9A3C083767A87B837556F6F97B75999C:NsRKnsTck7rKidUd4YH7UXflwaxXSN6RlIOGqAdoV5k=:Pickaxe_GalaxyLevel", "5AD068EB1D56D87706E44EEB3198CF1B:o9Gp08KD/vgq3RTrUbfGJk7rlfUqZMxoRKPiwvdVkXY=:Wrap_431_Logarithm_F8CWD", "E0AEF4894E1283946745F7902F7E105A:7MXKJEs903nNbT1oFzykxoHbQNDnOBm6yfadj+mtBDA=:CID_A_342_Athena_Commando_M_Rover_WKA61", + "E8D9A4BC39C0DCD0F8C24184D1AE73E4:tDt18ykBuH9tLtEvM9r6yl2j9T852yQo92n4Tgpwfck=:EID_SherwoodForest", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Backpack_TireSwing", "604C6242EB2BF301BB5D4BC6E3AC5A8C:Y7c2+dviThEDuVsG9kIOjMfnLdJUnPMbdaY5gKiVki0=:BID_772_Lasso_Polo_BL4WE", + "0C2DFF3432352A23684E05B0794DFFC7:FG55cmgdBnszsr5pS0aBC44NVl7OyI+AuOXxALyaNKA=", + "C4CF3F4B73862D7CA4AD87ADEB4D073F:hPF2H1xHMyX4NRGMyy7tSpS1yf2NHs1vStN/Wq7T6aA=", "266410C2B17584B4A472878EB88D6892:jLd9anMumGE0jIIBSf8XuqTu729JfnYTesywpeOgksw=", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Backpack_PencilCherry", + "5E30C7403A702908F7E67AFC6C9C5BF4:idycKoAyRb5uU8ZMsni1k54gQ0Q89xGl4xvp1gyk3ZA=:Backpack_FeatherMudLounge", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:CID_444_Athena_Commando_F_BannerC", "C1C31115267D6802AD699472D2621F25:zAyelFy6RcyGIW/9z9IvgEbmRW9pdAytvgBIPb1/kdk=", + "FEE2FF88D47ACD4788C23A72025AE3CB:cUGhkqZYUbnXJ4uNhMKeuDMmpzO/QqyQJXIW7d1X4mU=", "21F8DE4A4818E3B01693DF33566A179F:5AoumGhlrt+oAo6XUdRDSGHIp3ndAWOf9JGbBZResfk=", + "9DB21D9B45B9CAE4BCFD141C0ECD737C:QffQPwgx8G+22K1v6ArbZ9aw4DYxHpbqytOFfZONcNI=:Pickaxe_CarrotCake", + "4538F6D411E3A548ED65FC9F04FE46DE:0KzY2q6K9y5eN0H6WHdY6XtEDHgMI9hGgCwFfTKjslQ=", + "23DEA89BDC537501407CE442F9D7488B:MBhNDIgF/lTCfsqwj8VvjD1WBYdv1MvrwT+k8MCyDzg=", "D7EDE7B4CE393235BF4EB8779C55D5AE:tvYJfExMmwMpbWXSe8bxfGkpl1wcJv4B/RBjd8qWcZ4=:Pickaxe_ID_728_OrbitTealMale_3NIST", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:EID_CitrusSpoon", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_951_Athena_Commando_M_Football20Referee_E_QBIBA", "DC953387B24FC2DCBECCD2CCF61BB973:GT4tz78+PbkMtjcHnlkhmwLG7lQAr7EwMEWIgn59PV0=:EID_RollerBlade", + "190EE0858B5F6B5C09F029BCEA7DA1AA:s9BgWW/XUvjz8cZX5mD1tno+F+O/c2SL1w+yYuPOzqI=:Wrap_PigeonChart", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:Wheel_Law", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:Pickaxe_ButterPlate", "958DC719715C145004E1E028E72464D0:ZTCrQKaSpw5dAyqyW/jGz+KF2DlvSX8wCW5/4dhdFT0=:Character_RedOasisApricot", + "3AD37E40514304F7789E17FEBF4E4C68:4wGt9TLz7/cukkDMtB7Y8HZvi0fXNDMLsdCs6k98OM8=:Pickaxe_FastCheetah", "34DD24ED0CE62244E7FFD27EF4C29EB5:jTgMUc1ciLKwXF/PqyFJl6s9Iw5SXYHKiSThOQhG5TE=:EID_Foe_4EWJV", "C76299772B1BE272260BF3396F83FC1E:uiBDMtwYhdxktbqTrhYkzEZErlBp5gBtkLM+QFDouT4=:Trails_ID_102_HightowerVertigo_G63FW", "480888CBDD75E7F40261A1902989FFF6:l9EB5w/gi/KDjut4Izk3Y4MPLaHP5VbV6iPYsQxsB0U=", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=", "60D2163642133A71A78B16544C01474F:VJuOsZCmZAJ5VMpnkBng02DcQx3oj6Lup2eM4PxA85g=:EID_Cherish", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Backpack_EmeraldGlassRebel", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Pickaxe_FreeDrive", + "C50EC9789A634E9BA829CD5C4653C248:1pqFVcUR6pJ3zNoBgu4bFffbIANvAfPO4BtqvPON3IU=:Backpack_KettlePress", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Wrap_TireSwing", + "183F391FC33450CB879EE601584DBD34:It1/5uQ3GeW9HOMVAnKFMsnoYD3r5QSpru/RTUf2dIY=:Wrap_BikeMold", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=:Pickaxe_ID_694_SunrisePalace1H_SDI6M", "63722D44ECCA0F4178B85F5A6BC4C31B:j42UL0bmfBkli6Aj92wWABwFby5rAplP/Ac6nh9kRvA=:Glider_ID_308_VividMale_H8JAS", "0DE6839DE97A78F987D7A34D644BB3AD:ZKZ1+Eb+7CpzfLHMqihYVN9+gVQobqBYQW5mh8I1KpA=", @@ -792,36 +1252,64 @@ "35DDA69DABF1DE5826348A3CCD0DFE5E:CfhL+/n+phBF7TV4Qpw4Qhqrd6g3S/Gq2sU5n0FiH6A=:Trails_ID_059_Sony2", "854D0D9F4EF33FB4410CB98340952245:wYzInzYpL5IB6dN+rCo6196KgGGo3E/rNeOf7Paizz4=:CID_304_Athena_Commando_M_Gnome", "E50209164841E1829F672AB1B33D069F:1EMTmCTA4cO1QMoLu+RWAGd8Rw4FQdAONKvDwfQeNV8=:CID_333_Athena_Commando_M_Squishy", + "875A2044382363BB04B7E1B02DB7F905:2YtCtIxaCocZA54jyloILrq30zwBJx3UTRVykYiVy3k=", "552DB214510DE1E24F08920F80B0AEC5:GP2CYv9xYYDf6bOnpgm0fnOXa3iI0acXH02ZIaHAElg=:BID_819_Stereo_TE8RC", + "90ABE984619A1CC48646BC37CAF2D4E1:YBkrmsvvNBrx+nFpQ4y7U0dfzD7K79RT6VfeTPjjom0=", "216D955070ADAF10973BD156897472C3:MjQh55OvnJCoVMQzMU4C/1NF3FWiXDXnJ6G/EcHfUzo=:Pickaxe_ID_202_AshtonBoardwalk", "E8585F83E40CD4CF0272EA6012055A97:4LrXtLEBhL5JquAu4/kq1Dghb4/355YROt3ciXg+ysE=:Pickaxe_ID_791_RumbleFemale", "B1B800E199A6D4649287C11AE89F67CA:3udFXffIw3c7eM5hljF5mJQA36FbW2PeF8Gx1TcD1vc=:BID_257_Swashbuckler", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=", "41BDA9510489C841C335EBFA5E233CF0:NceSf4zJLAR1Clh17nKGtBrw62kDRE7tJrodbJYMbU0=:Pickaxe_ID_193_HotDog", "DC912741D5C6F75E4B0FEE33D7E3ECB5:0J6tWhEx0Nxw49VokIyykSs5sL5aFPgk2QJn9b5bAi8=:EID_LetsBegin", "06B9F77E165673FD1C5FF5099F43D1F3:Bvw6h4GKOLjC/wFgHQsiLePbBZhtPiNhtr5keDBse70=:Wrap_176_TeriyakiWarrior", "AC44D9C67B1FB24E70D94C827FC465AE:VrHcqJ9hMMqZicx3kS+qFfNXexXR/QA1/1bM+DwgqMw=", + "824E9EFFEB0EBD1CF7039D36C4C50E63:84b/QaGkGZxbNBHiYFMCd7AfkhDf1GqiJpyPQ47fFEE=", "EFF73F810AF0A5536912C24E91399CBC:vlBHa/jN2WecgWXwAEROAGpwbobQfMtBU24wD7+gM7k=", "30A1FD89B2D3C155DAF14852A39BA97F:C0IwuJFw9v06OF8XthOhzUd3nHOTCII1gmx/7eepmDo=", + "737D758CBCCFF589BCDA9236930EDA52:KToMoMliD/DoJnxL11MpgqgCsHHUJFhJxj8nkixIKiw=", "CD6B95C728B11810F8EE4C396D02EFCA:Fulo/BAgbJwmOju1xu/05XnxLDbenI4bDEb2rUyf5hw=:EID_Psychic_7SO2Z", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=", "8A6DABC9AF8B5FE521D365DB605D0AE0:T721SqBTncYsd8Gej01RnLX6sEaCgJoILnRauHaJz+g=:CID_429_Athena_Commando_F_NeonLines", "1A9B01B59F609C0D7E9EF7887DA23087:EkQdXhPD9Je6Bp7dlwZdlkX2S0har6vqUOjMIF9ndfc=:BID_A_043_OhanaMale", "1DF43E667862B117F72B5F39E750853A:Bhjx3mmVxhvadK5bkT+W9RJ0XAaMHawCnf8MfXIpABw=:Glider_ID_150_TechOpsBlue", "6D85E82539341B90944E84FFAAD872FB:mAiBk7KbE2Dnr+yVFyJK1yAwv2eWb+yANFH0z2krQkw=:Glider_ID_156_SummerBomber", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:Wrap_WeaveHarbor", + "F71D60AE5231E90CEA7F53D90DC4F007:ver8B06IS0up7tNYy03zkhCl+CrTl3czgmXPYYONcM8=", "AFCCB7C08EC6957EEDDAAD676C3D3513:MuovEXob241ie6/RP76ImUk+MExLdl+bszvxCHNtg0U=:EID_TwistDaytona", + "FC29F85DE0913DA71729BF081D5BC360:dRhUrL30ANekfjMYS3BDfuxUy+jokPGyY1Qt7OYfoqA=:EID_Caffeine", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:Character_AvocadoSeal", "0001859EA7AF69EF10A6F7921DD4DD9A:3M92MlWo2b1V04mxizc7cHB6TDP/UInspfWR4yT7K3g=", "7E9E6546A8C7109E9966F9C010D794A7:/hJU9SIxIewJ7taimArAwTbbuGG/4THrKvMElcTMzI0=:EID_BurgerFlipping", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:EID_WarmShadeWagon", + "71D436C87063424964A94E713024B9E6:idelyr7b2dnBJrko12u1H7fUCt/E1PD0Tp3UPoO/i0E=:Wheel_161Hero", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=", + "C60475E046D0F0FBCFE6DE6F9E040E0E:Wc6IzWuqnm7EHqcSx14i6KwXwl4+PmQq180ESMdR+08=", "AE9F7B3419C7FBD2414D72E2E1C8A7BA:kpIotniLp60tWfbBitDUrjw6gmJ2Swl+YT3QAkecpRA=:EID_AntiVisitorProtest", "5D6562F1EAD89513C82C2F37A24E7F82:I2c+SQCdDvJpC6z1xniRT+k41KAp0pla+o/H68oXFLQ=:BID_441_HolidayPJ", + "95E3B6C026DC5455DCF2CEFE2C20C998:rs3xOv5ypDx9Mbus6zG0QDD+jNEXO7ulpa6AZrp1qPE=", + "6204514DD102F27477CE0D7A811CBBE5:oCjlylDEodHnTy9bxZ1KT99Dfbkhsjw839ymo1O91uU=:EID_Distraught", "23213D7D8F739DE37BCA56557073DA51:hmmf08PTLeIAJgxwHIFI131jzcy1SbirW6EzJtm1teM=:Pickaxe_ID_778_CactusRockerMale", + "C50EC9789A634E9BA829CD5C4653C248:1pqFVcUR6pJ3zNoBgu4bFffbIANvAfPO4BtqvPON3IU=:Pickaxe_YogaPatio", + "202E50F5991EBFA0EEC41A2029847D41:W4RAP4/mEzaF3RTCVuf68agi1gJaiyA7GZ1g/ACkZ+E=:CarSkin_SourdoughHeavy", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Wrap_DriedSilk", + "2DCF5899864B58847F7721F5BC6CC7B2:0p6RYJMTG+ET3tlmONyr92cZnYnz+AV01JZgOtcemS0=:Wheel_Aventurine01", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Glider_MiddleSock", "E1B1A5908EF6377D7FB29F776486A6A0:qaZB3Q+6kKTtlO4aGWBsnjSxCwX3kmr8oOF/2QDZ2qc=", + "CD0AD2786C8ED5931FF0499050A273CC:VZIjLndy10Iw5/2y10V2EOA4Itr2jOgxB6cUUffVCDU=:EID_Asteroid", "F6E92DDBC70C8184E837D31905B2F2A7:UCSPatT+yv3YH2x0Ks+2GSXhSSu+3ZvZs6Lai3oOi0Y=:Wrap_387_RuckusMini_6I5DM", "0EC19805A48534C8892FA21C75024971:WcebSI5r6bMgSAbNd8Ob187rYmIJFJciobdyQciRiSc=:BID_345_ToxicKitty", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_BreathTaleCrocus", + "2E8C63FEDFFE6B835126B6FF7CB47062:B/uSSHdC8IsSccWS2rt8Cg0lBjG3+k+Ncu2p/qtB81Q=", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Pickaxe_EmeraldGlassTransform", + "190EE0858B5F6B5C09F029BCEA7DA1AA:s9BgWW/XUvjz8cZX5mD1tno+F+O/c2SL1w+yYuPOzqI=:Character_ApplePound", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_913_Athena_Commando_F_York_D", "1AFD764881D1E33FDAA65707010712AD:cbKyY3ux6wrdiWz2dXJq18KJaAYmUgBZ2aZsfz1UE3M=", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Character_SweetLetter", "7B1151E3094646DFFD37B6492B117FDB:4WxNHdTgHDEpGjzIV2XIjGO41kyiwggFQpdq8y+o1jY=:Wrap_356_GoldenSkeletonF_FT0B3", + "40B325F1EBCD65F9B8AA3E5F27EAA4FE:NSejpmJhzFwD65Zzt6habPR6vlesovU2DlEo5lyVM8M=", "5E2A3EE7CE3884E31F58D83485D8B122:U++ePc5N62iMtEbjrJGSwNCaWeR6UoNMtWS85zJHwns=", + "6024CDC6A7AD11D34A4357B928F4C340:sEB5STe61IRm4fuo2Ai8GIrwGYUbsJq0NQE3GqPNyNs=:EID_Depart", + "202E50F5991EBFA0EEC41A2029847D41:W4RAP4/mEzaF3RTCVuf68agi1gJaiyA7GZ1g/ACkZ+E=:CarSkin_SourdoughHeavy", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_241_Athena_Commando_F_Grasshopper_C_QGV1I", "958DC719715C145004E1E028E72464D0:ZTCrQKaSpw5dAyqyW/jGz+KF2DlvSX8wCW5/4dhdFT0=", "F00E08CB606091AEFAB37D9B0A01B833:uEmoAK5xdbd8KefVf9o7uJiGcGTYk2r9QevsGe4vBII=", @@ -830,53 +1318,88 @@ "00EEB0CEB7585E8C69F90EF8534CA428:gSddavzl1D9mSi3KgCoXjX3eb5Dg9Rqh2C1pt6rD5rk=:EID_MyEffort_BT5Z0", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_346_Athena_Commando_M_TreyCozy_C_7P9HU", "C97E930BC95DC795F4416A7B93E3B9CC:KxRPbXqD3ytwLLbZMbZmn+G+gjwOUljg/7HPjj8xP0o=:Pickaxe_OceanBreeze", + "9DB21D9B45B9CAE4BCFD141C0ECD737C:QffQPwgx8G+22K1v6ArbZ9aw4DYxHpbqytOFfZONcNI=:Backpack_CarrotCake", + "F1FD75AEB8137DD7B45C83780192AA98:KnIlVKiACju6lhHdlNobfe7PJKazk1XNNC9GNn+W4qQ=:Wrap_BeetTread", + "32764FCBF59EE921F09499469FF79875:QL1DzTyIQnnom22EayaDW+nbvWo8i1mitCtAMC7I65o=:EID_TennisLeash", "4ECF5AAA0161B01630EC04541290F986:BkEPlQ7bCZooSwt1HIbGXIm7LyhVkEd4zg4WUGJvaT4=:Glider_PowerFarmer", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Character_DriedSilk", + "38D31B8D75B45FE43423A479A2A76E16:MG3fgkXOZi8aGnPU8VsP4W82CvZjHv7tEPQR8lZdYvQ=:GameFeaturePlugin_BrickSoupPastelGlaze", + "AB8487812A4604F9FC59CA9BA2C6C2A6:NU3/1f+LToY9Q32OAh7aDnBlnR7Wljlj/PbYdVibtso=:EID_Lineage", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_A_005_Athena_Commando_F_GlobalFB_E_GTH5I", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:SPID_333_RustyBoltCreature_ZGF9S", "0D8B24BCF7F9C0293FFE1264A5D05613:v1sCSrsgI0QbNZ+4v5lllwW1n7M9dagX4GsxY7/oR/4=:Pickaxe_SpeedDial", "77B485EBF8E72CC8CD19F8646A6D0491:SXUHJQDuxBGv0PzDtuVsDxNyubG/pgH9s9FMvimS0YQ=:EID_Noodles_X6R9E", + "F4242EAC57C7B6ED79960A59D7978A67:ayEznxBID1ZaAY5bTwauUXOMDyKhyErG/QZgdnFX+iw=:EID_Farewell", "EB16EA013B751792698E05435797C1ED:y9JgD812Io4mbaJ5i533Ts5SSfyXaGM4JyoimjP+i4M=:BID_246_BaseballKitbashMale", + "2764E12E58C474C6AC7F5035A80A78A2:IoFlZq1ZK8Z/q1LHzNxRujov0bxn1r5mRyW6UtNmzF0=:EID_mesmerize", + "3D738885316A0BCFE38A3B60108D4195:YLO9yjKeTcOxmcWaxW5QCru/ol2msVR+/A9nAbkE+OE=:Wrap_AvocadoSeal", "97D5F3D0A78B050F427B5B300FC03EB5:Be+eZS6KqUc5Lc2iF4YAcLEe+S78nuLCK45HF/dDGDU=", "5C0BC5E8819B8968CF25C60885F0CB5E:E52Ld2gtMzMFUMkdMpjNWmEHEgr1qnH+iliH2ha27dQ=:EID_AlienSupport", "000A05AF03AE10ABB2059F29ACBF7D4B:3KrmPu2Ha/X0oy/MWd0a4O8JhJWli5MdtfG4XzeB248=", "5950552B5A52A97A433715A1FF107BC4:p9RBdPmk5295pRSg0+Ybfwy/kqY6HBYiJEAkvy650O4=:Pickaxe_ID_127_Rhino", "88FA70760D757D80F661FA53B4762EC2:7OtV76cpyOq9dNeM5PVD8TOdRcPx1K3weEPXzlCugu0=:Glider_ID_319_BistroAstronautFemale_A4839", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Pickaxe_WarmShadeWagon", "A3254C97AE656A9B7301225E06E6B58F:tnv0g+8KyEy6IGYAl1ssmNI0uYT2fEP2twZkRnbIhbY=", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_940_Athena_Commando_M_Football20_D_ZID7Q", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_BreathTaleMargot", "5BAB7539D98938E909D3541E69214830:IgABlZz2+aRehC7vxw4p63pXUZOZFwdATQWkTfTYP30=:Pickaxe_ID_820_SpectacleWebMale", "F6838AF4144E8386A184FBB0823C15D0:IjzqnnHjZ+r6WC4He/JawOyR7LxeMbm5880cDGDr2eU=:BID_232_Leprechaun", + "202E50F5991EBFA0EEC41A2029847D41:W4RAP4/mEzaF3RTCVuf68agi1gJaiyA7GZ1g/ACkZ+E=:Wheel_HeavyA", "2FE8DBD09F14AAF7D195AA73B9613792:KwIehLEKaCSJb5X/WcQ9IULKkz3G3M9f9Z5Jgi9hYUU=", "2B245B0F4DDB6AE9929DEDA081BEA512:lVz6HM71lNhCrT167xXv2wjekx+NqrJcy15i2+w3FdE=:Pickaxe_ID_152_DragonMask", "A7D34E80FA70CDD2F367DBEF93B98467:KVErbMXsQqx7dxrZp5Ara4OVlA17pc29E2SZlFNipPU=:Pickaxe_ID_218_StormSoldier", + "5AF3DCF487A866620466420D51E86C1B:eKk4AUtIxEAGxULWFKLnVkb4Hj5pw4GK0UM/xLVRfx4=:Sparks_Drum_TuckBeetle", "315315A3A02AD685390B8D5878BE527B:Te5Ku+QdVzpXNd0B8XN7T/e1YaV5PyR04Z9yhfMFatc=:CID_465_Athena_Commando_M_PuffyVest", + "2071F7A7C5CCCDD3348461241F90CA95:5gfMp4/23HkRIin3rD81b4UhuH8muYsjZUQnyb58mg0=:Shoes_JoyJingle", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=", "D50ABA0F48BD66E4044616BDC40F4AD6:GNzmjA0ytPrD6J//HSbVF0qypflabpJ3guKTdX4ZStE=:BID_115_DieselpunkMale", "0690C12E471B0A42CD02549ADA662D64:Ntgy1QBz7O7CswgzsqOYwoMahjG3hGmk6/Qh4/rs+dM=:CID_273_Athena_Commando_F_HornedMask", + "524E3ABF1DD30667B36C83F283B05195:psHqDFvyUISUa4Vm+z+e8kpQ/bxTybJYkpijcvRjHiY=:EID_SureBamboo", "EE0C67580F774526D46A64757F5DE77E:qRq1DPp8GnsFZSUYR1PJKeKm5YXAg3Kyd5Y+pjtXZyU=", "2301C91045828DBFCDD966BE1AFE22F7:zS44RFNKoS6+WDSfin7CebOMjLH763+OGG5wjTrCosc=:Glider_ID_097_Feathers", "9944BE1C4E9D73E4FA195380EF0B7BBB:LQxoRi0ktKvKMLk6hauL2Gzs6zf5bcEk3mgfX0We/uc=:BID_214_LoveLlama", + "BE857852220784849F13E1F3B6448051:Sc+vT6GLgKXPYnqJdDMF+iJf3GDMq4Sz4x1lxfD9B04=", + "7F2F547752CC7BEE86E81B09A1562A34:NnQ2B4g96ki2j08pY3+J+68o2rsMhNnOWm9Hm+6q+Iw=:GameFeaturePlugin_SourFork", "90641BE26C6A325EB05DA1FF911EEE87:zDYeE/nTlO8I38ziKo/q/ssv3w2fHkWnDNn6mw0ZENM=:EID_Reign", "D24B0606E503B97BFEB8EF12C6F1340B:wCF6GzuxQSxUX9I6eFwGJL34gU7YEPTKrZOOL3sPL3o=", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Pickaxe_SatinCheddar", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:Pickaxe_PotteryWheel", "E8585F83E40CD4CF0272EA6012055A97:4LrXtLEBhL5JquAu4/kq1Dghb4/355YROt3ciXg+ysE=:Pickaxe_ID_792_RumbleMale", + "EB06D2E764EF6E03658811E0A1B7BBC9:NpTV+Nnmy/6QFWgc+h69utcgLFFfxvH9nKF9Tm3iMng=:EID_Canine", "5E15C5486CE8E539552D4D3E7682F9E2:+L/tTz+woDFZJEvtxfq8m8tNI1R72sYK7rnYr7sHTis=:EID_TeamMonster", + "BA02A6A5604CB94ED9B9D7A197670870:OuvUXdw7gThaUToKPCUt6lZBJfOgKYgS8+fzL9cZZ5U=:Character_HeavyRoar", + "843941134EFB5150EF52025C3D45201B:mjvZ0+YYVOUSLHUlccSKYLuSjY8QrE98pBujSjxkPNE=:EID_Gilded", + "4A0188CF04863E6BDB96AA76EC733554:r5wklpb17aiBb35bzDaz6+WFYfLQpn9JjYp85CNWce4=", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:CID_A_433_Athena_Commando_M_EnsembleSnake", "E582349045884D5CD6A5518608336738:EuwTH/5P/6QUfbA3n5kc0wUYy+sI56+mNDYhIqheL4E=:BID_142_SamuraiUltra", "F6E92DDBC70C8184E837D31905B2F2A7:UCSPatT+yv3YH2x0Ks+2GSXhSSu+3ZvZs6Lai3oOi0Y=:Pickaxe_ID_659_RuckusMini_O051M", + "8E86BC326698EE02BF7B17C5C59B7D49:W+Z9L0RRkFzJTo6jyegWGj3hOUySrTHZKYPtp5fCR4g=", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Glider_DriedSilk", "D517F2A448CCB9B47E5004894BC62ACF:qOdQUR91sysqDRELOgz/YVZ7Piae8hqcrnYW90fXtvU=:BID_863_Tomcat_5V2TZ", + "CF159FCCE55868D72C8E66DE0F96A409:aE11RIixkH44CGQx/6v6/VWXAttVJERE8uFnyOHkF1E=", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_302_Athena_Commando_M_Slither_E_U47BK", "BA6DF4F82C5CAB3CE1C51156BFCACE71:SDOlhnlP1SENGT+SrYUqeGIz0TkgoM7dQjfmfxegb1o=:EID_BlackMondayFemale_6HO4L", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Character_HeavyRoar", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_351_Athena_Commando_F_TreyCozy_C_A9Q45", + "40B325F1EBCD65F9B8AA3E5F27EAA4FE:NSejpmJhzFwD65Zzt6habPR6vlesovU2DlEo5lyVM8M=", + "A1892DD6A665D23CFAD3173CAD32B65C:br7Yu2bywwX6/gTgsF6+yOgvag92nHHBrNzSnQYvMl4=:Character_DoughDisk", "0882DAEC4F7823551C4955BA25B8AAC4:kGljCDpbMnCIfeo0YBLpBKDhX6nLlCaZRe62mSYSPTs=:BID_918_RustyBoltFemale_J4JW1", "E47EFA3166A5D7B35CEC27B19AC66AE5:JURSqAHhHK6YqLP5rKhCO+SQ2oql4NqJaoaeNGtsrM8=:Wrap_383_Buffet_KGN3R", + "205E83E941E613D6DDF175294CD7B508:W/HdfArXSwvG+c+pTX+3aNoJawu4lPsB+cPWpnMBnZA=:EID_FlowerVase", "8566FD040AC2B245597E11D1F85DB4E5:SEoqoweofxmXfxu848wKn1UJhwU7oQ2w2F0lBst+FnU=:BID_658_Historian_4RCG3", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=:Spray_CoyoteTrail", "FAE51F5AC49A240384D5B57EA08B1F90:oesTf9AVGgX4FVwWzgm++nQEO0aARyuU5rZa1f6hoFs=:Character_InstantGravel", + "067A969CF775754BBFE2E44B015E62FA:nEbEvfuaSpoAbL26ItFWDnm8LozNZwHwRjHqkEA22ak=", + "71C3BFE2AF0BC8DE7BC3735614CE6263:hNLsvUTUw0cw1WrfOEjm7oSGPfpEZer6R0G7F2El6Q0=", "A398C07C0A77D834038E7192FAB52B4B:/+4taU8TYRe14OhUt2cevoUqUOh6ado2hWu45FJ+7yA=:Backpack_FearlessFlightHero", "57F31C09F360B5B96F6BF142E1E6A094:wkWZW9rtBPZSew3DP593yPFWKUNRXVwVl5wUGh+rLB0=:EID_Spectacular", "A34195EF9068F0DD323EA0B07305EA47:eYcw2YEjssIAsJMgaWYPQQCBFcRvvkj9WoRVV+P3cBo=:EID_DontSneeze", "29B68199D0CD6E019BA8175561F4F076:aA+14qhwCm5cu/+LEzB+tLlZtccgX7H3N25Ky41Me3s=:EID_Chew", "BA6DF4F82C5CAB3CE1C51156BFCACE71:SDOlhnlP1SENGT+SrYUqeGIz0TkgoM7dQjfmfxegb1o=:Pickaxe_ID_276_BlackMondayFemale1H_1V4HE", "46FC5EBAD39CE53EFB215A2E05A915FC:H3gtdkEzT3Dk8vkwTTZE9oUDoJEy6vmfQj1jDo453gY=:Wrap_051_ShatterFly", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Pickaxe_CitrusSpoon", "4969808C5315EFB4839F94626ECD600C:rdEEmKdvnm0+EXCNE8AaL3XOvVWfLdMVOfZYKj4Kzwg=:MusicPack_131_MC", + "A69F223BF8EAC85B7968C06A3A8748C7:B3whIp+BEDU1HOaNIXWNi4ksCHWBqfA9UsEyRAVjzhM=:EID_Polarity", "8AE930B0D623C1C2B3926C52ECF6250B:uwtZv87e9DU/Z1ZvYB7Pv4TdRQ4/ZRT9nYJCwYSmlbI=:Pickaxe_ID_605_GrimMale_8GT61", "D938886074C83017118B4484AECE11AB:wjHAHm00Vg6n2x5LU91ap0+SFX5ZXXBmax1LyX8Aips=:Glider_ID_287_Alchemy_W87KL", "2301C91045828DBFCDD966BE1AFE22F7:zS44RFNKoS6+WDSfin7CebOMjLH763+OGG5wjTrCosc=:BID_154_Feathers", @@ -884,97 +1407,165 @@ "1609BAEA4AD6B664847EB5AACEAAD2AF:m2Yg+p6NDPR/POAPoG7bUCPabLTxGc/h8nrOEIwDx7k=:BID_130_VampireMale02", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Backpack_HeavyRoar", "486AE200BAEBA71EB6C477BE323066E9:3vS6pm2ep50Ab5lzNnGMluM0KYJFiUbp2MuBcahuiFQ=", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Character_FirstClass", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=:Backpack_CoyoteTrailDark", "D2016D80822A26E49A7365FE575FC8B3:DphK7hbrbnvQGCGhhNfCpe+bDPl5q1w1DsaD4OvJgOc=:EID_Deceiver", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=:Wrap_JazzShoes", "3D9634EBDF17C26278CDFE91EF0130E8:tVvwjIulbvPLmBKlFhBwKSOGqzCu5yu9CqdH5008u5U=:Character_GreenJacketFNCS", "B77D921A94CDDAA841609065AE4C7BC0:SLDMLjxWpK+h1P4WNnqlixpWwujuV8OUZw+NoufV7sA=", + "067A969CF775754BBFE2E44B015E62FA:nEbEvfuaSpoAbL26ItFWDnm8LozNZwHwRjHqkEA22ak=", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Character_CraneAnchor", "CD6B95C728B11810F8EE4C396D02EFCA:Fulo/BAgbJwmOju1xu/05XnxLDbenI4bDEb2rUyf5hw=", "6261EE20A79577BE9F3CAED16BE29CF8:539o4DrU0Wfl7SNWEO2im8/ZYoL7CBJOvz+3hN0cc5A=:EID_JumpingJoy_WKPG4", + "A1892DD6A665D23CFAD3173CAD32B65C:br7Yu2bywwX6/gTgsF6+yOgvag92nHHBrNzSnQYvMl4=:Pickaxe_SoupGoal", "59AF6C46ABB214024067564F69D6EA37:NtUgzeFVvkbyZQGRVdteWV61HjED9MXquqlVKHo3c/M=:BID_605_Soy_Y0DW7", + "2DCF5899864B58847F7721F5BC6CC7B2:0p6RYJMTG+ET3tlmONyr92cZnYnz+AV01JZgOtcemS0=:Wheel_Aventurine02", "8A154454D5B98503B341742F927C2457:grJh5qYNlPy1eMO4+to3Moy+a6NCMnXyGSAFUKKWY5E=:EID_Downward_8GZUA", "95C6C2B37E1D15D60BB5C20D9D47BA31:exdH0xe2v+2t1wyoXpZGLX+iGDIdRxcQ6BG9iqi07Lo=:Glider_ID_368_NobleMale", "F395571A36D2BD888861E61EEBD45AF8:D/35GPTIOKbdfmpxRJmHTkjNXcWv+XdSmTxQt6z1hvI=:Glider_ID_277_Skirmish_9KK2W", "BA6DF4F82C5CAB3CE1C51156BFCACE71:SDOlhnlP1SENGT+SrYUqeGIz0TkgoM7dQjfmfxegb1o=", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=", + "1C6FDB12D706D59E15399DB8FD1EFD85:39JQsqlpGBC1xEz4qeYUYT8Nta0ZkYb3GvjEumq+bAM=", "A5A71DA2F913ED0FD001BBCEC58F97FF:gFC4LJXINTgSLc8Gd6tYuSmuLHP+4AthS6eF52C93M0=:EID_GasStation_104FQ", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Backpack_CraneAnchor", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:MusicPack_212_WeaveHarbor", + "B9A0974966FFA6519F942CB8ABC6DE65:qS1fmsGLl/R3z7jYOVJZ2i/D8+MqOzylgmBr7NZrqRA=:EID_SwissKale", "01FC97F8787B82E027EC64661E0D36AB:Mh1l2LJ3YrgaZtg7sRTd8XeBkVcyA3i089gZKkTr1gM=:LSID_431_Cactus", "03FBE2522823B14E3BD161BBCDAE4A85:kvHfxKURiw97DzzEt5xAUxVMFfxGya3Xw3kI7ORGEgM=", "2BFECCEDD463D908C63438FD751529BE:u3hXyyjFecUwcUQIugiOjqwSJhnhy/cluvLBwlUhSC4=:CID_401_Athena_Commando_M_Miner", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:Pickaxe_ID_222_Banner", "F33B69585B65C333655C545A038BCEE5:0+gUoAUkiBbY5uqO9rIehUDkvrr/PY3vBY16AMHQASw=:Pickaxe_StallionAviator", + "9AC78A87102681DA9D49DE0DF70149AC:KB83Xg43Gu5sv+0qlqvvmfySycArKgAu5uGHmMu3dUs=:EID_Affluent", + "856E286187F84C14D7808F68B4F04154:2pDSaP8YgyGgqluL0t52LStcOf5O2qQ/bA9Y2EwpJNM=", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Sparks_Guitar_OliveStomp", "A062151202F2D5FCAD103D17B9300CE2:JiiR0xFNh20CRLDWN/tfjaeoo2ybApd1hQB364/iuTc=", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Sparks_Guitar_MiddleSock", "D14FDB2BB2FB7746797F25470913BFF1:CQDgIxcNnAoUboQnjafZAYvV7UqX+NefGTXFd3m+oFc=:LSID_373_Nucleus_TZ5C1", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:Pickaxe_CattleJar", + "205E83E941E613D6DDF175294CD7B508:W/HdfArXSwvG+c+pTX+3aNoJawu4lPsB+cPWpnMBnZA=:Pickaxe_MistressSombre", + "9972857939D69D9799D6800D0D70ACE4:J5NKMyEoVZ2zBlCiTGN65eKAAHStaOO+bVGbJfsFI/k=", + "86ED92FA0E4776D8D3B60F8259B393A9:JOIq5LeFGyI67axw4UZ71Xnjyfw4sPyRVCBoAmy0InM=:Character_PageTruffle", "9481CF79929F97F77D8F7D2607B42A6C:E28flW2DKtXyXBh2I7qs7VFKBFSkpgjkEDWIruQfVL8=:BannerToken_001_Cattus", "BB59BEF60B72A241855EEC0FD63154D9:ZAQI6o6tkjRB6mh7VwOsf0x9DGyEAbGZ8qlUxS1fVm4=", + "FDD3BDDFD277F404F7A8786FFFB285F9:9+DbcptOICqGuz5B0I2KDRKyJHkprRB9MGYDI+1EkEQ=:Shoes_TunaCabinGhee", "FD0C3696948675DC3C2CBF5098D57D0D:rBWyTh/AVyZxi2oiQxM/OeD/HYZOSdVidEQeKoowV6U=:LSID_296_Cavern_60EXF", "134343D31031634B122471F73F611CBC:zqtMGKxH4+Ydcx+1mHOb5DIMYxctpm2nKqXp8c5hH/0=:Wrap_076_CyberRunner", "8DCAE39C7D9690E19F52655F02C613B2:ZZHbiVsbXquLlrtNVHtryLS3Vd1Ego8/8tlDpeUCgfc=:Pickaxe_ID_251_MascotMilitiaBurger", "3B908C605D83AEC6E8E0F9BF6ABA828C:IyB7RIUMz4fcBekrFspRvR3QIuCPJIY2vrDmsIm6Sf4=:EID_BlueApparel", "F3A99CD0D4F58EECEEB0D112506AD846:ZZtCRPcKk6itVryDavp7uZFIXiZF5CW0O9b+8Zt2Oag=", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Pickaxe_WarmShadeWagon", "CE9D023C0D7DBF7634F2AEF6200BDB36:JyhTmjJnosQmLeGMQXhCtkl/auX+mde5P11MsWEwIqw=:Backpack_DarkAzalea", "E04FBD38CB934DB1363EF57C85E48F9F:E+/j7zhGIdHODfCdH2vh4rgGRYSssFpT/s6dlus9Csc=", + "7DD96358E6FCB34A5221D2E77087D23D:1H4kxS6zepB460v5K2/w2lyuCdj4Qsni15F1qSSPVdQ=", "57EC154062C75464BD8A087D89732317:5AEwoCp79njYci8QYF+sLMkGpjDnFCYLSCtz4LD9D78=:EID_Galileo2_2VYEJ", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:BID_852_TextileSparkleFemale_X8KOH", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Backpack_GallonBag", + "92034B55AFBF9B8D79879A805EA50D70:P/SfT3IbWKQS5QIE00cDT/qR5omam1FlCNEbmK44Yuo=:Pickaxe_ElbowChat", + "2179A819ED5DE6D18069080913457904:cyWtGVJoSif35u8e7hznp1JYHRzqhYdC6frWTHDZCZk=", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=:LSID_358_Sunrise_1Q2KG", + "183F391FC33450CB879EE601584DBD34:It1/5uQ3GeW9HOMVAnKFMsnoYD3r5QSpru/RTUf2dIY=:Pickaxe_BikeMold", + "F7591219D2C7DE5F225F0DCF06F27FE9:0FmL0FiUHR5HTCgqnB/52ELbq5rAiaRJPR827SwOsQU=:EID_Inspect", "1A9B01B59F609C0D7E9EF7887DA23087:EkQdXhPD9Je6Bp7dlwZdlkX2S0har6vqUOjMIF9ndfc=:Pickaxe_ID_832_OhanaMale", "0E32ED911D1D1D67115812FB22317555:4qQbE3qtFL+oTEzvxYIwl2H6AsG7z1/3zNO9JEdHOd8=", + "EEA28D2A16458D0B2ACBF1ECC12E2D33:5JlAGAfApUEeXSCLziIg71JeDc4jByiO9316qxyGK5E=:Shoes_TunaCabinSchmaltz", "687E53607C7004988B05C9EE1BA99AFD:jYmAGdz5vAvDRIhrcVdrcCNIPEmkJg8L1vWs/HZ5Kr0=:EID_SmallFry_KFFA1", "C182F32A4B301086F8EE1E49B34C502D:g4VO8e/8Xk1+S55wpg/gmymEAYj6N38qXnvWSaYtER8=:EID_Shimmy", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=", + "4A0188CF04863E6BDB96AA76EC733554:r5wklpb17aiBb35bzDaz6+WFYfLQpn9JjYp85CNWce4=:Wrap_CanvasPrint", "498A4AB4BC3BFA9B055CDBE833C51670:67ndB88hm7gomLYiklekB5rGWrcr8RJ6K+no9DTP87M=:Pickaxe_ID_372_StreetFashionEmeraldFemale1H", "CDCC968B6DEB5D05990F5D530A4B19D0:gAiLmJxr4FbEf/L10sgHjOLE8DEy7kYdtk7DJcgjPRM=", + "53A406F15B4250D281B5A3664B6530E9:T/g188KteyL89/E/pKHLGKb21nzG5BboHB22Pzh/OXk=", "FF5A507BCC4519B928075C3DF4603E8E:EVv5b8WFOYZlDUGRqb8YUS1WbIbbT8TjgoBWEQr65zs=:EID_IndigoApple", + "0B41D34A225C92221083EE4627031631:Jtsu/YOCRrqB4dvLeKEzb1O8ZD0xfZUbp8WEhIrVPN0=", "0D8B24BCF7F9C0293FFE1264A5D05613:v1sCSrsgI0QbNZ+4v5lllwW1n7M9dagX4GsxY7/oR/4=:Character_SpeedDial", + "2830AEF5C09E976B74EE1E194E3B988B:UduuLiZnBhH43ymHQqejG91JFUIoYCydpUpQ6SWBWgY=", + "A504A381A11922EACD522BAB09F60577:Fyrj+mT6zQCfA2tvIqzm1lNM2dmN8xtvZs/Airz9ZDg=:EID_Undead", "AB10C0F1C99E5A6E4E477300FBD5D170:tLrb56vTjn3uiZIRhHU+RYygmirLzGglmEdI4DqfK4M=", + "67E6E3BB6F124A14AA5C077219A41814:eg6SwkhZyo//UwwX1hm0vg4AC0N++fDGUFOdApZuk+I=:Shoes_BreathTalePetunia", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=", "F62A404ADA885AF5A67C30DE1F03BBD6:zAm4CsxXpE6vMhsqKwj2Cce+asNmSAv0IOo/pWVySmE=", "2E1C06DB5781755F3F06D95B6612BB3E:aTN33nTPI+qQ+osYxcMa4FjlyajAzhIxRzEcoAr8iAI=:Pickaxe_ID_546_MainframeMale_XW9S6", "8D44654E9EA2AAC35E489476B1948E58:Dwb/irSIIGd3tLLPEP5OqJY1D4KfjdP4+uP4+Ht4YOo=:Glider_Elevate", "B0030ECDA329A8B589D249F794EA90B3:BfF0FYJQJ71DMUBmClT0DppsOy+1Syn8fGu6qNtTgXE=", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Character_MotorMonth", "F51F080981F8DC32B09FC3C62A977363:NqX2i8P3ayVe/mUk8aAqzUg5tvMEDWt1URv6xc4fUkY=", "28CBBF705C9DB5A88BEC70DAA005E02E:FvtzBBvDkyj8PRLW76169bMFvg65VojYrSmkjUAi4Bc=:BID_352_CupidFemale", + "524E3ABF1DD30667B36C83F283B05195:psHqDFvyUISUa4Vm+z+e8kpQ/bxTybJYkpijcvRjHiY=:Pickaxe_YamPowder", + "FBB56B6E711D7FC3CA29B46F712AA3A5:wtIigakPrMzOC6ZZ4Am7gJa+CNEhe7DPAr1ZOE/WZZ8=", + "F7591219D2C7DE5F225F0DCF06F27FE9:0FmL0FiUHR5HTCgqnB/52ELbq5rAiaRJPR827SwOsQU=:EID_Inspect", "B16BF216C9085E63B70056FF0459F87A:xKQqQkkw6VWwT0pk7eKzepG9HM9kzi2ZPwSbdLWtpwI=", "AC424209DFAB55305097B2050E16E2E9:efXu+MoloNbSOOHz8X4ipvD2MhSMWpRCaEOVNcdLPrY=", + "190EE0858B5F6B5C09F029BCEA7DA1AA:s9BgWW/XUvjz8cZX5mD1tno+F+O/c2SL1w+yYuPOzqI=:Backpack_PigeonChart", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Backpack_NutmegMayo", "CE9D023C0D7DBF7634F2AEF6200BDB36:JyhTmjJnosQmLeGMQXhCtkl/auX+mde5P11MsWEwIqw=:Pickaxe_DarkAzalea", "44DB36B2D2B3854669780458D2FE48C4:gtl0smAMRKg8d9TdDH47lUOYCygKzbAPA6/HaXLWy94=:LSID_323_Majesty_0P2RG", "3CE25AC56856D0E10426276F61265547:NEtVDXR0qoOfW9lgdS4AuA8dkfd/1I9degcRI9UnvUo=", "54FD9ABD65879452DCB8CE11C1D7F1AF:nV0Vm4NCBl+MkGX8wiqfFrg0viDriL3I2xc4KS7n7fg=:Wrap_070_MaskedWarrior", "7A8E25F664219ED6CCF3AB1658D0E557:TV+yyWpI3iHJoaK3o1t6+/uhN/sFZ1OixoAx0n7MtjM=:BID_330_AstronautEvilUpgrade", "F60CFFFA32CF6A877B50DA7F0A88326E:OWIopbB4fxaobofPI9lF9hn6BPG9NVLp4Od61uQppfo=:Wrap_047_Bunny", + "FDD3BDDFD277F404F7A8786FFFB285F9:9+DbcptOICqGuz5B0I2KDRKyJHkprRB9MGYDI+1EkEQ=:Shoes_TunaCabinFlax", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Guava", + "26021F66A417204C4528397FC89B4FD7:BKxmQzj5fNtYyWMW/ujKawoJq1Y/VTAY64GOLBK1Nbg=:Character_CordSyrup", "71BEC74046C6920A467E57B69FA3835A:q6m1xB4+mCmXL3g7eRGykDO6ZKrXS8M7m8SqbqIKzkI=:BID_202_WavyManFemale", + "174B492A98CE7D4047C016C29EF7D86D:URAvdRkx1DkQvA2t91joRtT7PzM8OFP9KwoMnD0YJt8=", + "D825771F72189E14464845D8BD1AB447:gY+Eq3AUYqA6Hhv7OmY6uPEe9PJ76I1goAxX/Y3bALY=:EID_Darling", + "0A6F8755332638E42FC052470B3BD065:OGqX2AuHNDfNO1iagEg6fwOr3Ib0s8/5iOBLnDc0vSE=:CID_A_227_Athena_Commando_F_BistroAstronaut_JJLK5", "3AC281E7A5EAA2765CFE02AC98B04FC8:R/hWNn8BcRRovJE/L7h15VDrJ0H4VqBBVt6XVvq2Ebw=", + "90ABE984619A1CC48646BC37CAF2D4E1:YBkrmsvvNBrx+nFpQ4y7U0dfzD7K79RT6VfeTPjjom0=", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=:Glider_CoyoteTrail", "D2FAE1D098B2B4695EB59FAAD504798D:ZUDIqDvGVcpCVuA3h67vdkVbZwLuC0Z1zX33JLyi5xE=", "204D49F063979C3AF87EF896D074D1CF:SaYFk+GEE7mL4dsgs0v0VGR5ER4TwH8uTNX5XqSglu8=:Glider_ID_251_TapDanceFemale", "A69EA08281B5018543EC525AC7716B70:1W0iCKEIuEfDSOaJfl4gQEpenDKjLQGAovP3LWc/FTw=", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Sparks_Bass_DriedSilk", "BE6386E7E95BB83F727A5282D4E1FF37:FsEC/J/Y3POX7wa0/+SonLUCp+u+MH7dktA25PEYLns=", "419567181C57991B12DA9A9AEADAE6DB:nWZ+G2GG0PvarQUg/U/kRpWaJkA2YmmCgixEy4No+7Q=:CID_706_Athena_Commando_M_HenchmanBad_34LVU", "37B3D2284CB3924E6592C2D1D11451E4:CMJclyQ1I9iY+VkDiajhGxxYQmZGHrTAlEl/wtlT+pk=", "D938886074C83017118B4484AECE11AB:wjHAHm00Vg6n2x5LU91ap0+SFX5ZXXBmax1LyX8Aips=:Wrap_348_Alchemy_FYA4I", "D14FDB2BB2FB7746797F25470913BFF1:CQDgIxcNnAoUboQnjafZAYvV7UqX+NefGTXFd3m+oFc=:Pickaxe_ID_708_NucleusMale_72W2J", + "0C8FB41BED80602548CCB764A876CE40:05zgxQ6Q4m+LULvuKwRlaPiSa7wZBN2fy6sG+rxR3Ng=:Shoes_StrandModePear", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Wrap_MiddleSock", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Wrap_OliveStomp", "216D955070ADAF10973BD156897472C3:MjQh55OvnJCoVMQzMU4C/1NF3FWiXDXnJ6G/EcHfUzo=:BID_258_AshtonBoardwalk", "DC8B99FB6774F84C4C0AA8DF768B758F:Rt+er5PzLdkCFk6oyu/T7AjMhYb8JT78rqtXXk9bIDU=:EID_Aloha_C82XX", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:Glider_ID_377_EnsembleMaroonMale", + "E047757EE42F321629ACB70579AFFE3B:eauxuNcCdAJbMmFHfEg72JCi+tYj+3ajvhyS4pzPAY8=:EID_Stumble", "768A95DE7B657B7B23D5A0DE283EB49F:JLLAz46a7wo2rADQvCkbp4IbKexr7J5bBr6d6toSn50=:Wrap_050_PajamaPartyRed", "8CB3CD29BF1611B7CA90D1C635859415:s7gVGQuQz2CDwqNda6dXQRqH9mpV6NUFu1zaoDihQYU=:EID_ChickenLeg_TDJ0O", + "73424C54CA2C14ED412BBB7BFD7A8E6C:+diHC1ZDFACOa/hy4nEP4CZlHcGOSrcClWY2hCMKdVI=", + "19FDB99E0C353A75CAF1D0159A566939:s+zGkNSkgLHoJYLtagHc0L5TTyTYcMvb2Yq/Nooq3vM=:Pickaxe_CoconutShell", "419567181C57991B12DA9A9AEADAE6DB:nWZ+G2GG0PvarQUg/U/kRpWaJkA2YmmCgixEy4No+7Q=:CID_707_Athena_Commando_M_HenchmanGood_9OBH6", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=:EID_Sunrise_RPZ6M", "8022BB6AFCA2733E261C32590EA86E9B:HzKZXV9sQfjsDuGuGRfpabHawomJhu82FeOaEQDg1lM=", + "279FC777D7F0D465F1A94C6FC9523154:QYYRiJbH+4XtjwSF9cJ3FVsgjYcwzRrqx9I353nLJvY=:Shoes_TunaCabinLard", "E7D27A42770632B7A50BED813D9B1696:bxADNk9dmPNeKEuSvJl44teif6sHvs36yBZ55E9fhwQ=:LSID_420_SCRN_Snowfall", + "CDEC0DDD7FBB9465CA1B5C0FE67C36AC:tBWLPUzHBjzieUTAFdO5T5D5saCWqEs2zxz7rBTju7Q=", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Character_BraveBuildSuper", + "C98E633AA0E95A61566731B2BC1572E5:U3KV1F5+UkJ8qi/LAVWSLD4tsoVRezxZonZPRU+oJA8=:Contrail_KelpLinen", "AC6F67B037F362174DD4DCEF7522D107:s4kP8pRC49WsLsc5Nlh7se3l3x57R3KrldkoTK2L8PU=:BID_301_HeistSummer", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:EID_SatinCheddar", "D49757E2D55451A0D5B341906FE2ABE4:PWMwnjgi/wUDV+yxg02QsU33jA529fxVTRHyqnkv21c=:BID_259_Ashton_SaltLake", "591DF838AC4B3A6350E40E026B26D5C0:MBvGoHxJQBTxCm2V82s2yHqRWPsYdFyj8xKUhFsUkyE=:CID_746_Athena_Commando_F_FuzzyBear", "72CC2893A6B672F3854F36629B770774:0BgQgKZRRuPFEoqn7CxZVhLBOfpCE3qLKGQlZc+SA80=:SPID_325_UproarGraffiti_QFE4O", + "37B3D2284CB3924E6592C2D1D11451E4:CMJclyQ1I9iY+VkDiajhGxxYQmZGHrTAlEl/wtlT+pk=", "8E1887D55A60F69B33B234242FF49653:YofZaW+CRl0jhVhkp9z2CQWhTPwyjQ6dbHtISkLDfVU=:Pickaxe_ID_801_AlfredoMale", "4BA0D73B76DE3321A47EC0AD052C1F7A:7kyz8UATQKwRKVdDwe8RbhYYeJPQsKLGdN9pl4MOosE=:EID_Marionette", "4E7938F1FAC98BDF378823116712AC7A:jbZVgprILTQomUdGeJF0PsAFAJxsSCs5cKcXweZMAg0=", "452BEE39B4C18C93D6B185B565ACA1CA:Be2Oll2p0qIXmiJMi4Y/wyePY+WefMmJyCzjgjrzkhc=:BID_233_DevilRock", "72CC2893A6B672F3854F36629B770774:0BgQgKZRRuPFEoqn7CxZVhLBOfpCE3qLKGQlZc+SA80=:Pickaxe_ID_699_UproarBraidsFemale_LY5GM", + "6F9CD990050CE04CE577325C3A6FFC81:eOl/oWxQfbcYxQtjjEyB7SKXGNJLGwrWVT4JgglASZY=:EID_Chorus", "2DCD2E2A9A816AA9035999F8E6F85F6E:6xM4ZYt0UAylyuIgFrmOgq4fYVH2ChEzQNcl8KGQF0o=:BID_532_HardcoreSportzMale", + "2D7CC66E132AF5D216B481F2D0B56EB7:1OB3Dm0UQSumE4qrNw5lpTWgx1bjEqOFE3+s3Xo4Vu4=:Shoes_LungeStreamClef", "310CAA852300A8ED2B74754EF027C823:CbrsdQ2vpkgVe0Oc5HlGFLVkV9arQn928vHSnPpSxbk=:EID_MakeItPlantain", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:Wheel_BasicAW", + "F4242EAC57C7B6ED79960A59D7978A67:ayEznxBID1ZaAY5bTwauUXOMDyKhyErG/QZgdnFX+iw=", "AE04BC41397F3D492390E60E59B39CAC:xC3e/4BfPQ5/xQqEKnB+EgmzrOcLiOCqiQCuZB6V9Ac=", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:Pickaxe_ID_749_GimmickMale_5C033", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:EID_Scribe", "A02E08C8CE48D4D8676358FF7BE55533:d9wA4snpl4I4B4zZFxWyu9cL9zSkXqy9+vTw9PUhHlw=", + "35182C05BA21A7373CD33B20303E6944:oOAKjS/mrGU6Dk/c+XiIcs+xgvqyI8zmt+pnR5VmPmU=:Pickaxe_IntenseCello", + "083635DE237C87482DC022635E04BC7E:nq1PRVTTrU7eagnKA/IO5GYjFPF6Xd2mXDYF7YrnumU=:Character_ShrimpStroll", + "0A6F8755332638E42FC052470B3BD065:OGqX2AuHNDfNO1iagEg6fwOr3Ib0s8/5iOBLnDc0vSE=:CID_A_158_Athena_Commando_F_Buffet_YC20H", + "6F6C4D2FDC4CE08C906A1D23BE9271F3:WNtAGhNL7Ja5uCRMuSQO74TV7vMwkbSMSeXyE/CmOyw=:EID_Takeout", "498A4AB4BC3BFA9B055CDBE833C51670:67ndB88hm7gomLYiklekB5rGWrcr8RJ6K+no9DTP87M=:BID_494_StreetFashionEmerald", "F707FA321C9644351C5F87893C16580F:bOW0W1Al3NZZGbPupvIlLl7wWgBA2jPtH6SZO/fjdy0=", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_905_Athena_Commando_M_York", @@ -988,40 +1579,61 @@ "34DD24ED0CE62244E7FFD27EF4C29EB5:jTgMUc1ciLKwXF/PqyFJl6s9Iw5SXYHKiSThOQhG5TE=:LSID_399_Foe_AN5QC", "97E91E4F436B598D654592793B595536:Pj0lxheibz4Db/C4ehhHGlOalLQAxFCS+2NYkHRbjyQ=", "0A43BFE2D06B46248FC6598C0371D5EC:+U/nWLs0mNQue0yVc9tTaRF+2qrvzdKZyxUR+MzTvMc=", + "47CCB9DF0EE91BDE66F94F73D0F7C9D3:fY0+vtL1vN5Rq6dy1c4SwU4p/It/4BsPZqBXOKsZwIs=:GameFeaturePlugin_SourForkSupplyDrop", "35C2B057E5168DCA74B6F1DDAC745E60:73haJlY3S0TVmH0ELxyw6p5FzFRrITWqOmobH9F2Mq8=:LSID_400_Keen_T56WF", + "32764FCBF59EE921F09499469FF79875:QL1DzTyIQnnom22EayaDW+nbvWo8i1mitCtAMC7I65o=:Pickaxe_TennisLeash", "9904FE82E1630F9BF753E5AA195B4E1E:ScugOdDnT2N47PETOZ8B3MoDlg9elYb+ePzsZGA3ryI=", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=", "F9AF8CDE150D2D1E65B64710D70C23A7:3SpHToTu2E//Qe8Dhu4I3kG5fLqEemMiL+2NxRVKdOc=:EID_DuckTeacher_9IPLU", "99E94152C1F777A1D8519A532741EE40:3TCGPeLF3mnH0j8LE9oLwYiXHMve97rw7Vw1OQcnczQ=:Pickaxe_ID_762_LurkFemale", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Character_HeavyRoar", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Backpack_ClayPlug", "552DB214510DE1E24F08920F80B0AEC5:GP2CYv9xYYDf6bOnpgm0fnOXa3iI0acXH02ZIaHAElg=:Pickaxe_ID_648_StereoFemale_0DTZ9", + "C04C5C304930D43E84F58FF9AB79B9FD:RRfEBTNlpOk2fL5mAawO31suKVB+B6AiUB8vwxlLX64=:Wrap_MotorMonth", "4ECF5AAA0161B01630EC04541290F986:BkEPlQ7bCZooSwt1HIbGXIm7LyhVkEd4zg4WUGJvaT4=:EID_PowerFarmer", "E0FB7B394449CE6450EA90C93D710EB8:NrXwNX6lKuu/kyQuvE74+6Uo04FODoV4ZqxToj/jS6I=:BID_300_DriftSummer", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_912_Athena_Commando_F_York_C", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:Pickaxe_SodaMug", "74245D2573276B4C9ECCF61B23367A72:I5LtJ72UAlZ9XIupxkzRJKiRnSEkEvEc5D8+Ss4u2Ik=", + "2DCF5899864B58847F7721F5BC6CC7B2:0p6RYJMTG+ET3tlmONyr92cZnYnz+AV01JZgOtcemS0=:ID_Booster_Aventurine", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Glider_MiddleSock", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_298_Athena_Commando_M_Slither_EJ6DB", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Backpack_HeavyRoarCarton", "2301C91045828DBFCDD966BE1AFE22F7:zS44RFNKoS6+WDSfin7CebOMjLH763+OGG5wjTrCosc=:CID_274_Athena_Commando_M_Feathers", + "E8555D6A18160009C6FE750CDADD8BFF:bA2hQL8SlphJtKbmPBEMR9lDu+8EV4HFnIb+2XcNNsU=:Pickaxe_WeaveHarbor", "30A1FD89B2D3C155DAF14852A39BA97F:C0IwuJFw9v06OF8XthOhzUd3nHOTCII1gmx/7eepmDo=:Pickaxe_ID_746_ZestFemale_4Y9TG", + "1EFA43A2FEDB492EA32BB6AF50E8B0CA:ukW+ECABl8sv9qFUdpckdqW6IRsZAPnPEWSu6bsbCYs=:EID_AccentWall", + "1269E6F7E620736515D3F57CE4B2938A:P+cnpG9HbjrhRGcxCH+FD5C19cSQij2V7pHTsbVfi/Q=:Backpack_SteakSting", "958DC719715C145004E1E028E72464D0:ZTCrQKaSpw5dAyqyW/jGz+KF2DlvSX8wCW5/4dhdFT0=:Character_RedOasisPomegranate", "3ECF85734CD277EE10524DA249C5D0D8:4NtGfZpXGCuoEqpaN7C2kInVtLVwQ9Zp3zj4vtwxtv8=:BID_211_SkullBrite", "E47EFA3166A5D7B35CEC27B19AC66AE5:JURSqAHhHK6YqLP5rKhCO+SQ2oql4NqJaoaeNGtsrM8=:CID_A_173_Athena_Commando_F_PartyTrooperBuffet_55Z8G", + "174B492A98CE7D4047C016C29EF7D86D:URAvdRkx1DkQvA2t91joRtT7PzM8OFP9KwoMnD0YJt8=:EID_Snippet", + "8BCF8182A37A4EE321F5078954A75122:wLfDsgM7jhjuvKHr3zFxWs4pDn12nRiG4RVQfuNSTuM=", "925BD833E71FF05FB73136BF57189C5C:WsXZpM/1+PT+xzorL685J5XB1dpvv8IOpOeeA2Rl1zE=", "D24667CC40ED6564CE26A31E63E327BA:OnghWyLG/IQEx45PtmEcmqAHuViWUsTSDQ31EgRhyZM=", "2E5F91AEF58F310AE2044EA39C43BB81:pNy1GtfVzymqacOqXRY14EZEvI5ZSVD5AFxlhxXC5qk=:Pickaxe_ID_683_CritterManiacMale_S4I63", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:Pickaxe_ID_822_EnsembleSnakeMale", + "9E380D6486FDC2BD798C4AC03EA99956:IG7ZP06IgAnipEmMYxb7jdt7HuXHo5u8zUpomvJYgjM=:", "54FD9ABD65879452DCB8CE11C1D7F1AF:nV0Vm4NCBl+MkGX8wiqfFrg0viDriL3I2xc4KS7n7fg=:Trails_ID_027_Sands", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_A_002_Athena_Commando_F_GlobalFB_B_0CH64", "46FC5EBAD39CE53EFB215A2E05A915FC:H3gtdkEzT3Dk8vkwTTZE9oUDoJEy6vmfQj1jDo453gY=:BID_256_ShatterFly", "9A3C083767A87B837556F6F97B75999C:NsRKnsTck7rKidUd4YH7UXflwaxXSN6RlIOGqAdoV5k=", "258D945630DF6E1016889F47B16EED80:zQ/4osJ36W0V1DFXswf8JSStDMBTZPQ8oFcMrDqS7BM=", + "9DB21D9B45B9CAE4BCFD141C0ECD737C:QffQPwgx8G+22K1v6ArbZ9aw4DYxHpbqytOFfZONcNI=:EID_CarrotCake", + "7E3B0175F4929DD5C6C8A2D889B24F81:BOiNpViUgeXK2U6iFe7NS5c5fgHayrpHnNMaR2Ha7xw=:Backpack_ThickWatch", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_947_Athena_Commando_M_Football20Referee_IN7EY", "D83FAFF508200C47DF03BDFF2F801FEC:s9P7AOkoCuPm/506hyAKzuRaIh0xzV9YZON4oDs7GoY=:EID_Jupiter_7JZ9R", "0CD312F730BA9C3FD6CD67420EDDACF7:nXBDxcWYx2VtjMeRCDfSak9+f9aSOgrcxp8GKeUiId4=", "BE20AAF89FE897368E52AAA193DEEB53:jHRZho9v4IKzFzk51RD0nAVFCZ27vIwcstPkdQeSupc=", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Pickaxe_EmeraldGlassRebel", + "183F391FC33450CB879EE601584DBD34:It1/5uQ3GeW9HOMVAnKFMsnoYD3r5QSpru/RTUf2dIY=:Pickaxe_BikeMold", + "79F7D9C856E8CF354109D3298F076C06:Ak3TOM0i0Mq/KYxd7SDlSuS7o55USaf+urL6WqnmalY=", + "1E8F4857F5C74E2E544D020B8594D855:OmR65gZfMr/YaejCOzL/ym2YAcuLn/zSNFTJLdTb1/g=:Character_MustardToast", "9CDB7E60150C8A93BF60EF4983D2A9FC:ZMGOYjalLZw3m4wFDi959WW6vlbIAQDqcnRVgylEej4=", + "D12059472F9FC9E8C71C715BFAE3333B:phP1bANlO1Ppd0XaisuZ+A0IuBGKlAOAzmWMPGsc8G0=:Wheel_RL167", + "65A22570A201A6CB2BD8818EF11B5134:VEVi+v7IDOe1xNkO6cgk6d++ycT42AejDHMvZAshvPY=", "ED61A5415E40BB0A188CDB1DA91F22D2:wGuFJQg1ldthApzow1drpoq6i40AzOsoODCI5I/6JSA=", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Character_MiddleSock", "359567C8D8F146C8D08FEF2B24AFC9D0:yMWg8m0Eh+0UGV6CgIWrXsJMPT/Ww8/Qa3RlYPo/bGQ=:EID_BeHere_8070H", "91C415954BF27B6E43970FB8A75FE8BB:YhHyxIA+Ru33r3pThiWqKNYdvDbL05yXSxKarRuMSxw=:Glider_ID_103_Nautilus", "C015FB76A9E7912825A5F9CA69671961:4zfC1uF8ll4CkTBctitVmwjHsazAiz2LXPHIPj4ef98=", @@ -1030,6 +1642,7 @@ "3DB93E023E700ACD0C78072ED4787D37:aePdzcjsQvnpefA3P/cKfnZrVspZ5QVSsAc+Rui20pM=", "E50209164841E1829F672AB1B33D069F:1EMTmCTA4cO1QMoLu+RWAGd8Rw4FQdAONKvDwfQeNV8=:Glider_ID_118_Squishy", "360CD59F6F7B68A441DDED9DB5FD13D7:G6pVAf/ul1HPYh6s2M1l8G4hn62jdwkcbegeLoxL7Y0=:LSID_364_Ashes_0XBPK", + "7857ECCA6B0B91759DC87671F8DCCC62:LHh5NcObng4VN3hrWEvrRQfF/3H6InEOXOlwyJ+O6Rw=:Character_FreightCalf", "2DCD2E2A9A816AA9035999F8E6F85F6E:6xM4ZYt0UAylyuIgFrmOgq4fYVH2ChEzQNcl8KGQF0o=:BID_531_HardcoreSportzFemale", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:LoadingScreen_PencilSet", "06E3CB03E94C4D850CE185166706E868:jDuRIbxnZBnAH/hUrfRX3qnGyIogSWUHrK6nq7Et3pk=", @@ -1037,17 +1650,22 @@ "89D641BBEFFD9A227200861A01807ECF:rXDTm9JS6HhLBHIDXPRRF/eERp1DkUhV46QPxevqMWA=:EID_Comrade_6O5AK", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:Pickaxe_EmeraldGlassPink", "3AC8A6B5089F55E17E00AAD8AC3C6406:TlUSkJe3y85fW83rHMy+XuqcZxQduXcB8yftpPoiDvo=", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Pickaxe_SweetLetter", + "505B0CFC5F0C2722538390A1B86CD96B:+e0wS4upHWWgE2ptrA/0C5a17sPALvW+mHthRVTZP3Y=:EID_Thrash", "06672238D711A4FD743978B86CB0E0C7:c8ILo8LfAtcO6tUoX1BdrnptTcPhKbiZ069jkvq4UjI=", "44DB36B2D2B3854669780458D2FE48C4:gtl0smAMRKg8d9TdDH47lUOYCygKzbAPA6/HaXLWy94=:Season17_Magesty_Glider_Schedule", "35C2B057E5168DCA74B6F1DDAC745E60:73haJlY3S0TVmH0ELxyw6p5FzFRrITWqOmobH9F2Mq8=:Pickaxe_ID_737_KeenMale_07J9U", "71C3BFE2AF0BC8DE7BC3735614CE6263:hNLsvUTUw0cw1WrfOEjm7oSGPfpEZer6R0G7F2El6Q0=", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:Character_RelayStick", "01BCAD21B42507D45972A0E634D3BF68:LFzYKDNwUHYxLThhPKfnzmnADCwCZFjZybIL9TaGBkw=:EID_Deflated_6POAZ", "96FD474CBA52137DC5ABF658BE17C792:ZLWvbUR7Xow1GUNjC9Mxg7DHVoJAnBr4b9gSzmyFcxU=", + "D12059472F9FC9E8C71C715BFAE3333B:phP1bANlO1Ppd0XaisuZ+A0IuBGKlAOAzmWMPGsc8G0=:CarBody_Bullet", "552DB214510DE1E24F08920F80B0AEC5:GP2CYv9xYYDf6bOnpgm0fnOXa3iI0acXH02ZIaHAElg=", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_082_Athena_Commando_M_Hardwood_C_YS5XC", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:BID_922_SlitherMetal_ZO68K", "EBFE6788D367D741AF0A4FD098CDFD39:FAeJTGyT49P+dQOmKx+lMYVAxu7qtIPlqSaLAR85zqI=:Pickaxe_ID_213_AssassinSuitSledgehammer", "922A62BF1FB397B890EADCC9ED9E6F90:OvZzqErOUkh5FciEJD8JI+lu4X5NmK5TtzvCK6F5RM4=", + "2071F7A7C5CCCDD3348461241F90CA95:5gfMp4/23HkRIin3rD81b4UhuH8muYsjZUQnyb58mg0=:Shoes_StemDotBallet", "7C469274E430B5E3005EF1799DE618CC:5j5CNw8BI2+kBShT+u7kgw9HyCZ3dOvCMGBO9WScNPQ=", "99F8F15A893B9B4BAC2E12BFDCE251B9:1OMIfAluyzGr5kvv03niOQMXp/D+M1s/f/mHTv52Prk=", "C17D1F224DBE7ACE1D1D998F9EC974B4:lKF1wmYGidWP6J4irSLvW13QbAIwHPOeO8b7LtP88t8=:CID_303_Athena_Commando_F_SnowFairy", @@ -1060,53 +1678,81 @@ "452BEE39B4C18C93D6B185B565ACA1CA:Be2Oll2p0qIXmiJMi4Y/wyePY+WefMmJyCzjgjrzkhc=:Pickaxe_ID_176_DevilRock", "204D49F063979C3AF87EF896D074D1CF:SaYFk+GEE7mL4dsgs0v0VGR5ER4TwH8uTNX5XqSglu8=:Pickaxe_ID_500_TapDanceFemale1H", "793D221E5331282DD7F3681100944880:B5R64E9EZQD1lHmmyUV+9a1XUEOcYfdopJ3avEIcVxE=:EID_TwistFire_I2VTA", + "C4CF3F4B73862D7CA4AD87ADEB4D073F:hPF2H1xHMyX4NRGMyy7tSpS1yf2NHs1vStN/Wq7T6aA=", + "A9AFB4A346420DB1399A2FB2065528F5:Zjzo+CaLNmCygplzQo2wUL4LT33DEiL6qZWE2R0EYMg=", + "D41994CD334E94E006779079C2B900AF:mReRdgy/92d/henxH3XkFqyuCsf9qemZLXVvNnH17xs=", "73FDB8F2BDCCF4518225CB3E28DD9C0A:MBo/DO8mLebMquZPCgeE/FgUdJOXASKVjIJ1H+IEPac=", + "456073B2B8FECC95083FD5C9C86ABC13:Aay13OiHLmgTZgGmgOkfwUAFR/6RK1GsKNazgJ3AIMI=:EID_Factual", "00BD73648F7CD05EDE0B2D4C33B499BD:0D3XSX1KGIR/UWBELcxKxJp06xbU96TetFY2Rz9R614=", "BDB776E27E5002716EFCCF94F23D1B19:UkCfjAV4SKCBjTvgHIbHc8U/uAWI63ysU1ST/sy64+4=", "FAE51F5AC49A240384D5B57EA08B1F90:oesTf9AVGgX4FVwWzgm++nQEO0aARyuU5rZa1f6hoFs=:EID_InstantGravel", + "9E7468047D1781BCB546D5AE215B5073:EYWQj4jWQQnEZ6i1eKfW47bvGqK0ZNt7KFzQO1P6FU8=:Backpack_TimeSquare", "B9C9B09F29DF6BC9DA94C36184CECFFF:1/E0M5TV90UjL3PR+sqOzaRiMRpF8ByTmfVayVEL/Ig=", + "C73DB27E321E8B5D3747E2209CED62F2:sL+26G+2SaePYEPgaTi+UwMkAr9RfmVl3QK3fsLfd30=:EID_TwiceBaked", "1CFA91F4317CA2724E2AD9A098B2888B:op+720ix4L4JmxKqwXbOt+T5Xwqhcva7c6lETmEVCbY=:EID_Shindig_8W1AW", "4D896B93DC5B2D18AA2949EA7B67B4EA:0V70x6p0zRRV9bV6P+sq62lM0CdW4rvUgip6/65GWzc=", "2648ACDF6B7E55495928F2319101BB8A:tKha+iiFKUamRIWCxq0gOtbN/G1B5J5eOIElAx9T3rc=", "4C838738CDC4946786DD7BE341AB05DD:eyjCm9OcFQSvVRVBZizNVyF+8kb9OlNFrvDy8d1QDfo=:BID_253_HoppityHeist", + "8C623F6A49CFF9ADC7895A466CA1C896:kLmYdLi+jOBs2k+B/UxrCcPSdvuNYTha0xl9+SvUzJU=", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:Pickaxe_ID_787_LyricalFemale", "A9823E3BC8FF6814492A2DE0334F124B:wyyFD2WOtsgHbGC4RNkEvLFNgbZWhRmcu8lQHg0UBFM=:EID_Concentrate_0W5GY", "8680408E4982495D8EC65D930CE902F3:ZIoca9gNSMll2u3zmmEsMFSAp2pTmsvWIPWwz2b0FsE=:BID_188_FortniteDJFemale", + "BE857852220784849F13E1F3B6448051:Sc+vT6GLgKXPYnqJdDMF+iJf3GDMq4Sz4x1lxfD9B04=:EID_Enchant", "3D8D56FDB72DACCA7E656FBC0F125916:gMX76nmLV2caz28Ro/i3FatCU4tdi1jHgJSPbdnLTUc=", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_937_Athena_Commando_M_Football20_UIC2Q", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:Wrap_RelayStick", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:Pickaxe_ID_748_GimmickFemale_2W2M2", "A398C07C0A77D834038E7192FAB52B4B:/+4taU8TYRe14OhUt2cevoUqUOh6ado2hWu45FJ+7yA=:LoadingScreen_FearlessFlight", "2D24182706636A7BD3E96AD37605BAD6:jEZJE+EAU7VDo6p6Y84e4+p3AHxYBWin144H4MhzaSQ=:BID_553_Seaweed_NIS9V", + "CED82F0AF09F2650E043A0B9CFD1BE98:ZHNIVGxs07Yus1Jm6EhAiZmpUsil0HusHS2HH0vvo+8=", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:Glider_ID_348_GimmickFemale_D76Z0", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:Glider_ID_364_LyricalFemale", "91DE2263000EF60E067F04C5505104C0:J72L3sJQnakH4GQrYgBz7QIAmI4aC1sde+iB7zErKG4=", "DD07D332EE51C9C9585F5249FD62A45A:8Fv7jA8ISZ3iOlNCeaeeGh9rmRV6QvL7sbsx5wYTvnc=:CID_A_223_Athena_Commando_M_Glitz_MJ5WQ", + "A1892DD6A665D23CFAD3173CAD32B65C:br7Yu2bywwX6/gTgsF6+yOgvag92nHHBrNzSnQYvMl4=:Pickaxe_DoughDisk", "19CAB803EB00118FB3E6B3E5ABA7B234:tRM77TfQWWJ38hNsFLjt7jMNoSOozxqi9PF9/9H3rmU=:BID_373_HauntLensFlare", + "02A94B6E1D64352BBF332D801395069C:EGuHDE8YxhdRAXiRNDGUPVKCkJOAX0rBUXFiB/HVR4s=", "5A03216B7495CB52261D6E0D74DC62CB:tYFoxNFq/lu5imPTcSk5vAX7ZfPNBwi8INXf2hU+YyU=:CID_A_159_Athena_Commando_M_Cashier_7K3F0", "3306D0A65AE55FE016FD38AF43E062DD:KY9nJfkoLlV8GIZTJyctUb96ihEreBHYF3Wc3SfnHkw=", "3D9634EBDF17C26278CDFE91EF0130E8:tVvwjIulbvPLmBKlFhBwKSOGqzCu5yu9CqdH5008u5U=:EID_Victorious", + "9DB21D9B45B9CAE4BCFD141C0ECD737C:QffQPwgx8G+22K1v6ArbZ9aw4DYxHpbqytOFfZONcNI=:Pickaxe_ChessBoard", "B8C17AF9BC0DF3113AC6C498DF3325C2:iElxozD4UvK0+tPt0pPLg0gBoSkwLwByJiE4ucKHU7U=:Wrap_085_Beach", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Backpack_WarmShadeWagon", "7A59383C41DD998408A74BC37C7D6887:nSrruhpHV3ZEPPECeqWkMh/6mBFzQD8yEFKZS6oJeu8=:CID_A_080_Athena_Commando_M_Hardwood_I15AL", "4EFDA950DA6AA1E6422D2FBF6B89DE85:HDEI+ufmAF1VN2+mYiOFFFDjPVAfkEcmrnyTQh85dmo=:Pickaxe_SunBurstAlt", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_956_Athena_Commando_F_Football20Referee_E_DQTP6", "471CA05DCEE84890F9287E4E0DB31C08:cclx9Dp+FcphJfVZLUAdo21nLGn8pQ7GutQgY4LCOts=:Backpack_WinterHunterFNCS", "D83FAFF508200C47DF03BDFF2F801FEC:s9P7AOkoCuPm/506hyAKzuRaIh0xzV9YZON4oDs7GoY=:Glider_ID_258_JupiterMale_LB0TE", + "9FF6F385935B70741BCE31AD20DC71E3:ppSFNf1khIjuH1ke7/AqweruSJw8WgP2Ly3CAiaRGqE=", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Pickaxe_TireSwing", "457F39EA51FB4C723B442810750CDA4A:V3d05mcuS4uXMBRpy63TIZDLt5hg9njVD0SGhZDsmBw=:Pickaxe_SaharaMale", "2DCD2E2A9A816AA9035999F8E6F85F6E:6xM4ZYt0UAylyuIgFrmOgq4fYVH2ChEzQNcl8KGQF0o=:Glider_ID_216_HardcoreSportz", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Backpack_BraveBuild", + "7F5ACEFE3F67BC0CCEB59A4E8EB82BAF:iDG2HB2LypEtzw5/EjKVpJmQ1o30BE3nVv01rOTyq64=", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_StrandModeLychee", + "C11DB2552EF4F3974E331EC72026EFBA:/Wa2Umvi1eof4lgNx3TaDEi5uJfQQhoYDr82V3V5m1k=:EID_Medicinal", + "59881A06EBD2C9A333EB1F04A6409265:E18NXuWZnSlrdVJXuh+1y1xFiQr0luqH7/Cx36ta9Vs=:Shoes_StemDotHinge", "1609BAEA4AD6B664847EB5AACEAAD2AF:m2Yg+p6NDPR/POAPoG7bUCPabLTxGc/h8nrOEIwDx7k=:CID_228_Athena_Commando_M_Vampire", "134343D31031634B122471F73F611CBC:zqtMGKxH4+Ydcx+1mHOb5DIMYxctpm2nKqXp8c5hH/0=:BID_279_CyberRunner", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Wrap_CraneAnchor", "2E5F91AEF58F310AE2044EA39C43BB81:pNy1GtfVzymqacOqXRY14EZEvI5ZSVD5AFxlhxXC5qk=", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=", + "083635DE237C87482DC022635E04BC7E:nq1PRVTTrU7eagnKA/IO5GYjFPF6Xd2mXDYF7YrnumU=", "D517F2A448CCB9B47E5004894BC62ACF:qOdQUR91sysqDRELOgz/YVZ7Piae8hqcrnYW90fXtvU=:Glider_ID_318_Wombat_1MQMN", "F8D604C6FA9156F47356B54E1E442A97:EcmOKEqNv/9U+rw3oLZb7e+z4gaKWlfRIpdQwODvOKw=", + "26021F66A417204C4528397FC89B4FD7:BKxmQzj5fNtYyWMW/ujKawoJq1Y/VTAY64GOLBK1Nbg=:Backpack_CordSyrup", "72CC2893A6B672F3854F36629B770774:0BgQgKZRRuPFEoqn7CxZVhLBOfpCE3qLKGQlZc+SA80=:BID_890_UproarBraids_EF68P", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_943_Athena_Commando_F_Football20_B_GR3WN", + "D48BB37F98A9EDC6639CD34F0F277359:DuO9M4Czd0IIf2jSYsk9oooSGKNK/r4XX0fA9d6j8F8=:Spray_FirstClass_Raven", "F32262244DE021E18BF22F9BF7594474:08HErdKvBV58StDIjB9wvtY67peu7ZK3BsMpBMKvSrM=:CID_280_Athena_Commando_M_Snowman", "4ECF5AAA0161B01630EC04541290F986:BkEPlQ7bCZooSwt1HIbGXIm7LyhVkEd4zg4WUGJvaT4=:Pickaxe_PowerFarmer", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:EID_SaladDressing", "71EC943F69634C4E436D461E06D88193:aW38AAbm6/PX66vrSXaMTOOb0nydoEEhRphBbDZObmI=", "30B98E694C38C868A4EDB892F3FF1940:3biPX66md7tSkYYCBkYrshj9OJIo1B4CWV33LnL1kds=:BID_195_FunkOpsFemale", "F3A99CD0D4F58EECEEB0D112506AD846:ZZtCRPcKk6itVryDavp7uZFIXiZF5CW0O9b+8Zt2Oag=:BID_821_QuarrelMale_IKIS8", + "FFA545CC9145A22C3945CD5850E69A8F:PhpxNvhqVWcF2gTssuXy+Dg5g1Tm1OyKtt0CWGrUcnA=:EID_Macintosh", + "1EC3010F39DA0C13B7232CB98575B7F9:LqmHEehKTTI2IsaKqLHpIwM5YTy6/uAlrcdFfA8JvF8=", + "32764FCBF59EE921F09499469FF79875:QL1DzTyIQnnom22EayaDW+nbvWo8i1mitCtAMC7I65o=:Wrap_TennisLeash", "71BEC74046C6920A467E57B69FA3835A:q6m1xB4+mCmXL3g7eRGykDO6ZKrXS8M7m8SqbqIKzkI=:EID_WackyWavy", "E47EFA3166A5D7B35CEC27B19AC66AE5:JURSqAHhHK6YqLP5rKhCO+SQ2oql4NqJaoaeNGtsrM8=:BID_818_Buffet_XRF7H", "09BC93B3441ECBAC30FA23BBEF59CF89:3CHInj+JfLspiVCNDY/GTZ4Pn52nWFeA4qYI0SJv2dM=:BID_183_NutcrackerFemale", @@ -1115,25 +1761,50 @@ "C76299772B1BE272260BF3396F83FC1E:uiBDMtwYhdxktbqTrhYkzEZErlBp5gBtkLM+QFDouT4=:Emoji_S18_ClashV_I1DF9", "7BF9CA82EA29E080F7106C60B645B76F:D1NrMwnfRG8tf9LF7B4r7rQ53M2nCtPv25qjw22T9MQ=:EID_Skeemote_K5J4J", "5738A14C7E45E1B405CEF920829CB255:xZHlPTz/dxNahrp9IqTZ+tjOZSYMxQb9KZFXlg9N638=:BID_423_HolidayTime", + "EEA28D2A16458D0B2ACBF1ECC12E2D33:5JlAGAfApUEeXSCLziIg71JeDc4jByiO9316qxyGK5E=:Shoes_TunaCabinAlgae", + "C50EC9789A634E9BA829CD5C4653C248:1pqFVcUR6pJ3zNoBgu4bFffbIANvAfPO4BtqvPON3IU=:Pickaxe_YogaPatio", "A08F80FECB766B071C66017C5902DBD1:Q4sRGzjjbRTMZ3HwAmiC6a6+017KgXUsLapzs71OWEs=", "713D64294CD1C40F60DEEB805E3A2D87:CJOOHtEX7q4CELcZ96oZjrmSZd7pyJ2fMaFX912GDl8=:Glider_ID_110_TeriyakiFish", + "F00E08CB606091AEFAB37D9B0A01B833:uEmoAK5xdbd8KefVf9o7uJiGcGTYk2r9QevsGe4vBII=", "9261CD0F921EAA3CD6AA8C0716FB042B:W+yzeWWxWnA530lwV8nLi2BE+TD5MCXS11th7UphmPQ=:Pickaxe_ID_543_TyphoonRobotMale_S4B4M", + "1E8F4857F5C74E2E544D020B8594D855:OmR65gZfMr/YaejCOzL/ym2YAcuLn/zSNFTJLdTb1/g=:Backpack_FreightCalf", "6782F1D85E7DFD1D835C9B7B2A461001:zwni3LZXkLjSCnwE43DH3DqME9Z3zpCt2XOnx0VCOg0=:EID_LastVoice", + "0C8FB41BED80602548CCB764A876CE40:05zgxQ6Q4m+LULvuKwRlaPiSa7wZBN2fy6sG+rxR3Ng=:Shoes_StrandModeMango", + "1EFA43A2FEDB492EA32BB6AF50E8B0CA:ukW+ECABl8sv9qFUdpckdqW6IRsZAPnPEWSu6bsbCYs=:EID_AccentWall", + "CED82F0AF09F2650E043A0B9CFD1BE98:ZHNIVGxs07Yus1Jm6EhAiZmpUsil0HusHS2HH0vvo+8=", "E48EFA857D8E6914B2505B05AADFB193:4AUdytefPzWNT8c11iGtU4xcGNWEgzpMJbxTjUq3NS0=:EID_Backspin_R3NAI", + "32AA2546A88B1797C12F9C35A8492CD2:XBMYQphlCk+dBFuZtBzrIwLNnpmxl4gKEsysFoJ3yao=:Shoes_StemDotTrot", "4F463077C4B0260225A47547ABFDDEE3:jvXG7IisBPOlXz80kl6hZdn+jb6TV0Bvq1WafaHji44=", "5F55EB861A32231A4F36A5918A31256E:mPTr+gEXTqwhI36DN+qJITYpBR2D3aWqrn1lwnPDg6w=", + "988F75A036552441259F047F4DD6FDC8:udr6m6IzE0+CCPfAgZQp8CuhbKPWKFvJfpjOLTUZROY=:Sparks_Guitar_RelayStick", + "C4110935D0C729ED5C9C6DEFC3B339D2:1iYdY1JUa2XS/UHvjpQB+etsURaIAGX351sKopLNDr4=:EID_Perish", "E59B013651F078E718F08ECF9E1559EE:rTGy9at5kTfQtu8EwVrUihfzuN8vkFPl3XNyGvqbZX4=:BID_250_TheBomb", + "35182C05BA21A7373CD33B20303E6944:oOAKjS/mrGU6Dk/c+XiIcs+xgvqyI8zmt+pnR5VmPmU=:EID_Guitar_ShakeCrunch", "5A1170F589134C4D68AAA2B5AA6EDA69:bfro7s6Qtde/H7C4zc6MJdpua1mhem8HywLluxBLDrg=:BID_642_Embers", + "32AA2546A88B1797C12F9C35A8492CD2:XBMYQphlCk+dBFuZtBzrIwLNnpmxl4gKEsysFoJ3yao=:Shoes_StemDotDemi", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:EID_ClayPlug_Graffiti", "7C469274E430B5E3005EF1799DE618CC:5j5CNw8BI2+kBShT+u7kgw9HyCZ3dOvCMGBO9WScNPQ=:Pickaxe_ID_849_WayfareMale", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:BID_896_GrasshopperMale_BRT10", "16FC688AE41A3E3C518F4DD9F9612EE7:Jd7nRLx/FoonA2dUjtbvJVk3nJoNq9LTedk3u4EdFS8=:BID_248_Pilots", + "2BEE5F951D6A3AA790943B18CE43C474:fgujz2DrxsPG/SILcUFj8zQtKe4AQcKuKUqxX3VXbBw=", "21D9E3FA446D32EE85025841557C1E4C:KBL9ZqzocmLvcq5k3mwTCeoeeVfJdw9wjuQacUrg50w=:CID_A_243_Athena_Commando_F_Grasshopper_E_L6I24", + "50B2925BE94FDDD614E135A07311E0CD:sDzkZjmUugirOu1iVdBJFcodr3QAChXfoj1gXR2YQUM=:Sparks_Bass_SourWire", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:Pickaxe_SodaMug", + "1E8F4857F5C74E2E544D020B8594D855:OmR65gZfMr/YaejCOzL/ym2YAcuLn/zSNFTJLdTb1/g=:Pickaxe_FreightCalf", + "431FB998877020823CAE2A8E617FC6F4:nt8uLFOjfjulunNPUZnCyrsdqPZxle2XNKZAlXZY9QE=:Wrap_SequinPie", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_946_Athena_Commando_F_Football20_E_EFKP3", + "CBDFCC904B6577B868E32565F7F4605C:X9reH4gk76iPpnKnYAsl809qJrERyvIjFZq4H8JElOw=:Character_PastelGlazeGift", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_998_Athena_Commando_M_GlobalFB_D_UTIB8", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_348_Athena_Commando_M_TreyCozy_E_VH8P6", + "8E00C7A2A21FA7B4E700B07C507A41BE:dyBmgCC7TleC1mjUEngOJl5amz6OBzdx/wejiv2MrZc=:Pickaxe_DomeRoof", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=:BID_853_TextilePupMale_LFOE4", + "92034B55AFBF9B8D79879A805EA50D70:P/SfT3IbWKQS5QIE00cDT/qR5omam1FlCNEbmK44Yuo=", "0690C12E471B0A42CD02549ADA662D64:Ntgy1QBz7O7CswgzsqOYwoMahjG3hGmk6/Qh4/rs+dM=:BID_153_HornedMaskFemale", "BE2C3EF59AB81D812AF5B8153325998F:W7NoICLZt9L2d7XZ5dT9gtI80MyOizk7uA9LtwA/Edw=:Glider_ID_323_GiggleMale_XADT7", + "BE4F0BD53F53B4B8E570EEBF8829D35A:2e2jnt5igMSevc4fMunQFbu/EfR3NRoxNwULUtH91Dc=:EID_Repetition", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Pickaxe_WarmShadeWeasel", + "3BD3EA919AEA03B242CD5BAF46E30D02:pu83SeAxLED2/7MYHEJiWmwXAvmggha6jtpAEeBY4g4=", + "19FDB99E0C353A75CAF1D0159A566939:s+zGkNSkgLHoJYLtagHc0L5TTyTYcMvb2Yq/Nooq3vM=:LoadingScreen_Fluctuation", "D83FAFF508200C47DF03BDFF2F801FEC:s9P7AOkoCuPm/506hyAKzuRaIh0xzV9YZON4oDs7GoY=:Pickaxe_ID_510_JupiterMale_G035V", "1234642F4676A00CE54CA7B32D78AF0C:Nd8vhYp296C+C0TqSIGxu0nBYOFGQ5xBNK5MFjHS8IA=:BID_200_SnowNinjaFemale", "987329E3B70FEAD522EBF7435E5CA6DD:j4zyQQh25LYcjUO0HYDsBzmqLSXR5r98UKdC0xeTyHI=:EID_Boomer_N2RQT", @@ -1142,20 +1813,29 @@ "A398C07C0A77D834038E7192FAB52B4B:/+4taU8TYRe14OhUt2cevoUqUOh6ado2hWu45FJ+7yA=:Pickaxe_FearlessFlightMenaceUniversal", "F2C401EFDB4A6B5DD0B80C4E58D4A4A5:APir0jfGo2PAuoVtI+5tSahNavnxm7TFaRgTlx8tGrw=", "36351B933FFCFF1746737649E9806CF9:2ZtfFqHREh2sKsMYN23yW+2Sd0OSNN5CHGd/qlXVd7k=:Backpack_TigerRootHype", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Wrap_CraneAnchor", "3A122019FCD271A539EB71E952B32D60:CCYj89kHr2atYI9ZfLcisGTTnGy8GtGBKZ/arLp/tlY=:CID_A_344_Athena_Commando_M_TreyCozy_6ZK7H", + "95E3B6C026DC5455DCF2CEFE2C20C998:rs3xOv5ypDx9Mbus6zG0QDD+jNEXO7ulpa6AZrp1qPE=:EID_Encounter", "22B8405FC3BE153C8148422C3F2D3A8A:d/ATMDztVZxwHLUCwOcJWP1/7oPKKGqbBWUBRNZ6dnM=:Wrap_391_Dragonfruit_YVN1M", "5BAB7539D98938E909D3541E69214830:IgABlZz2+aRehC7vxw4p63pXUZOZFwdATQWkTfTYP30=", + "40F971FB92CABB4A1A3E8D087963C88D:YlgyGiyfD5E1yCbabHJALzDcLJz0/4ONzTcXUqDB+7Y=AthenaCharacter:JazzShoes", "CB3D84444FF0E551D18939AA7226B17F:U4GIAd4fGYWy9tySw3iVb92+6ZX3rQ3FsiBCXMT4TSo=:BID_194_Krampus", "35C2B057E5168DCA74B6F1DDAC745E60:73haJlY3S0TVmH0ELxyw6p5FzFRrITWqOmobH9F2Mq8=:Pickaxe_ID_736_KeenFemale_3LR4C", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=:Wrap_465_Lyrical", "E47EFA3166A5D7B35CEC27B19AC66AE5:JURSqAHhHK6YqLP5rKhCO+SQ2oql4NqJaoaeNGtsrM8=", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Pickaxe_PencilCherry", + "0B41D34A225C92221083EE4627031631:Jtsu/YOCRrqB4dvLeKEzb1O8ZD0xfZUbp8WEhIrVPN0=:GameFeaturePlugin_Kiln", "C23FA9BDE9342B508B8AABBEEA6699A2:3mRtSSu9PTBlC3NpGAQcFent660Ptni4HbGX+Zj1KIA=:BID_867_CritterFrenzy_3VYKQ", + "6F9CD990050CE04CE577325C3A6FFC81:eOl/oWxQfbcYxQtjjEyB7SKXGNJLGwrWVT4JgglASZY=", "578DA5D582A996DA819F409BE37C39DB:8KdrpLeI7JWcPozcUme7kvSVhgqxwmR0/ah4h+nCWLs=", "4009CB877085F3B3B0D76A686465A140:gMLJXUbFcIrqqUlAuoMI1b27KdWHBVJJeJWdYV1Iiro=:Pickaxe_ID_551_KeplerFemale_AOYI5", "308F587F46CB50450DCA9B9CFD50E120:2nvyeGrxnqL5SJjMPag1d9YiiXfdGYVkL/WJqWYnC2A=:BID_157_MothMale", "60CE6E28E6993C1DC1C58E839E7A7284:ZlOTwn6YbAK9HetjsiQo0AS1jwJQnLJY7NkR5i7o2/g=", + "7DD96358E6FCB34A5221D2E77087D23D:1H4kxS6zepB460v5K2/w2lyuCdj4Qsni15F1qSSPVdQ=", + "0C8FB41BED80602548CCB764A876CE40:05zgxQ6Q4m+LULvuKwRlaPiSa7wZBN2fy6sG+rxR3Ng=:Shoes_StrandModeMelon", "5D72DA16B064F87BCEB569EE9323FB67:cnMEvin1jKe2V34dFeq5nTKzXJCQiAnjJfXx1te8E2M=:EID_Competitor", + "8EAC5C7EBC5D4B2BE7AC223C88A7C8BD:CfJasRJ6JpLj0yBGbHihEx9+gcu/QFIX1qv3QddYmoc=", + "524E3ABF1DD30667B36C83F283B05195:psHqDFvyUISUa4Vm+z+e8kpQ/bxTybJYkpijcvRjHiY=:Pickaxe_SureBamboo", "1C8FA86241B2E4D084F7548529629CF6:pmXOfd+NEXcLhZX5YqDLjHu8/yzZoo4dWPcCM8ccXoI=:CID_333_Athena_Commando_M_Squishy", "D2FAE1D098B2B4695EB59FAAD504798D:ZUDIqDvGVcpCVuA3h67vdkVbZwLuC0Z1zX33JLyi5xE=:BID_925_LateralFemale_7RK0Z", "4027857851DDDDD81540A7A6B79134AA:VuQSvPVjqCjbln+FWNnnQ2RjoNjs2P8dD57qSDhhKx0=:EID_WrongWay_M47AL", @@ -1165,72 +1845,122 @@ "2F2804FC81CA638FC3DFEE5FB922987B:vz4MvtMQubNdmH1BO2E2FnNT3/vSvjbIn7HWNcWIYl8=:BID_272_AssassinSuitFemale", "522BADEC3C1B8FB686B355A760304BF9:4yejFeII+k2XIzKVEF1UPXPHjMamSlHIEljDToNlzvw=", "DE4CBA7A27B818D6B299767036C671A9:o7axeOYDdjXZ4MTWM4Io4XRNfQG2WH9qwPvBSJk8vJM=", + "FE4831E9E7D7012FEE138782AFA1109A:VoS2hBjPp+T+uFx1EfTAuvB6gjlEd2eA8yoh53VsjAA=", + "AB2F922860753269B1C2335CE5C0DD5D:/gjkRNAVhMsWlhPkX61LzAkKFMqdPyc9nNGgu+ahHd8=:EID_Melody", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=:BID_875_SunriseCastle_91J3L", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:BID_921_Slither_85LFG", "D1EBFA5EEFFAFC07E39EE2D9986CF8FB:jdM2xx6liOm1miOSVC7txNj6HvWF7/zCq4zxMYFYxug=", + "CD9A2158EBA8DEC4F51A16F0F19D0F06:HKidNu7ZYT9Gsckip7xIrqxKC4lIeQ0kLGkljdqj1kE=", + "E047757EE42F321629ACB70579AFFE3B:eauxuNcCdAJbMmFHfEg72JCi+tYj+3ajvhyS4pzPAY8=:EID_Stumble", "5D6562F1EAD89513C82C2F37A24E7F82:I2c+SQCdDvJpC6z1xniRT+k41KAp0pla+o/H68oXFLQ=:CID_651_Athena_Commando_F_HolidayPJ_C", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:EID_SaladDressing", "471CA05DCEE84890F9287E4E0DB31C08:cclx9Dp+FcphJfVZLUAdo21nLGn8pQ7GutQgY4LCOts=:Character_TreasureHunterFashionsFNCS", + "7B4FD16578D7BA2E89C3EC959266F335:hiU3wqMYteBnG9/uBa7ab9stf5oDInS/rYREIT9+Wjs=", "E098A699B1A5E20B03B5CBBCDB85D4E3:oKYx1AqjUax4YhKirSQDeyBSQNkSmEKDS7q+U/4KszU=", "BA4D882E7B09657A5E05773F702103CF:PjieN4lF3tRBNjQmWWUAyvZUaV0OrPGPYwrqNT8ZSus=:Wrap_045_Angel", + "A724F84D683BDA0424F8573492BEE2F9:NwXCEqmC8gDF+GNbhV1rvVbNkeFtOfjzBHvg1D2UJfU=:Sparks_Bass_HeadphoneJack", + "86ED92FA0E4776D8D3B60F8259B393A9:JOIq5LeFGyI67axw4UZ71Xnjyfw4sPyRVCBoAmy0InM=:Backpack_PageTruffle", "8E1887D55A60F69B33B234242FF49653:YofZaW+CRl0jhVhkp9z2CQWhTPwyjQ6dbHtISkLDfVU=:Wrap_476_Alfredo", + "0855EE21AA3E58786648810E4DEA78E5:wD8yk0v2pPNETRa9hPhJjJuMxHWJDF5FtxpPrd9ua4g=:Backpack_KeyChain", "EBFE6788D367D741AF0A4FD098CDFD39:FAeJTGyT49P+dQOmKx+lMYVAxu7qtIPlqSaLAR85zqI=:Wrap_066_AssassinSuit02", "1398A4C2E6C3954EDDC49F85C5AB251B:qF0+04jSaU0kgws/RigbWpwnyPQMDnK+4Vf4G0tmTns=", + "540DEA2C5E3510D32704C41A4B323118:GWPcu+VRPtu1WCOiRCJHR5adSzIp/4ndXT7TLZ8uDb4=:Shoes_LungeStreamPitch", "59A2ED9719A429D54A0527BD9EFDD2CB:uiAzgzDicrjHVlY+8a4i0p2f+7GkJ1kwmpT84nH6nsg=", "E0FB7B394449CE6450EA90C93D710EB8:NrXwNX6lKuu/kyQuvE74+6Uo04FODoV4ZqxToj/jS6I=:Wrap_088_DriftSummer", "01FC97F8787B82E027EC64661E0D36AB:Mh1l2LJ3YrgaZtg7sRTd8XeBkVcyA3i089gZKkTr1gM=:BID_985_CactusDancerMale", "7FA4F2374FFE075000BC209360056A5A:nywIiZlIL8AIMkwCZfrYoAkpHM3zCwddhfszh++6ejI=:CID_223_Athena_Commando_M_Dieselpunk", "5A1170F589134C4D68AAA2B5AA6EDA69:bfro7s6Qtde/H7C4zc6MJdpua1mhem8HywLluxBLDrg=:Pickaxe_ID_492_EmbersMale", + "CB7BF49198C9D5695AC69EDCE2448EF6:cWw+A9cc01w3ewCXbGg8L7ECPnUk6ky//jW0kDvE1B8=:Pickaxe_CraneAnchor", + "EA894BE3D14E66D4D1D86D9AE2EE9514:Tpl0r8Hy6cukvzcZVDoFMxZA5sFZOeuck4JENOfmLIQ=:EID_Vacant", + "35182C05BA21A7373CD33B20303E6944:oOAKjS/mrGU6Dk/c+XiIcs+xgvqyI8zmt+pnR5VmPmU=:Backpack_IntenseCello", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=:Pickaxe_CoyoteTrail", "C23FA9BDE9342B508B8AABBEEA6699A2:3mRtSSu9PTBlC3NpGAQcFent660Ptni4HbGX+Zj1KIA=:Pickaxe_ID_676_CritterFrenzyMale_B21OE", + "431FB998877020823CAE2A8E617FC6F4:nt8uLFOjfjulunNPUZnCyrsdqPZxle2XNKZAlXZY9QE=:Pickaxe_SequinPie", + "BF54C54672DEFBD71B744A72053E4168:TL25+NVV64p19Xu6A7+VVMfNwEseRZiEZ8J0QBfIkWs=", "CE60A61FBEAC33EBF231E79C6BBB3D19:y7XCzCCilb1Q+TlLtT2sQCAryt1gIZ9PPI2dtb5whik=:Character_FolkEvening", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:Wrap_CattleJar", + "467EBA8364CE2AA18ADFBF79DB7BE920:7HxCMh46wI/zn/MJiV2iOTobl6zqkEc7OYKECW+FyNY=:Pickaxe_StoneLion", "F3A99CD0D4F58EECEEB0D112506AD846:ZZtCRPcKk6itVryDavp7uZFIXiZF5CW0O9b+8Zt2Oag=:Pickaxe_ID_646_QuarrelMale_PTOBI", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_305_Athena_Commando_F_Slither_C_UE2Q9", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=", "A398C07C0A77D834038E7192FAB52B4B:/+4taU8TYRe14OhUt2cevoUqUOh6ado2hWu45FJ+7yA=:Backpack_FearlessFlightMenace", "BAEF248980269F569C6E1FFF2B885DF6:2b6DQGIcab1r7zsw5j3MR84iDmt0g1XBquxJVR/8GxM=:BID_402_TourBus", "E2A2B587160A4C443BF5455EDEC37D7E:+nH3Fe4U8akaQyEoy+g3b6IT6593VPY1PZjwP+d/ydk=", "BFE1F518C16A9F061B140D829ADDB0ED:bHkPYjXd71vacoJ4IisL//zEyVLFh+Di8MUqV9KkpFU=:BID_806_Foray_WG30D", "BF953D81273D8772F12F57646A49430E:JP2vQQulX3OGMjglMYW7PT3KMCMbia3rtHnuEsuEVxA=", "18E7A14F3D3A6501FCDCA85855F808CB:iYqOu2+M8QDG31cRJ8ZHQ7Z5eXpTOSTEvXcgfDSqVTg=:EID_Dreadful", + "19FDB99E0C353A75CAF1D0159A566939:s+zGkNSkgLHoJYLtagHc0L5TTyTYcMvb2Yq/Nooq3vM=:Backpack_FineCheek", "566C4D92AF66F45DF5E2D7EB43CC27AE:EuAYwU5tQBXzGoSj5BMc7S5yFfe9wZ2qrzx/hIHpnqw=:EID_LunchBox", + "8A0F9905F8676895B3E646F42214679B:/DYrfaUuX52rUQw+98JGYjS1vbe4BFRYFlrZUmh/9MY=", "476EE53C2EAA24FD1950A9875FB4CF59:LQMwgWwsoSqGyYbBouYaMaN8NZ38Vy5r3Tqa7KA71oQ=:Backpack_FallValleyCharge", "9B730D57F59135CF774023F0DC1A99E7:l2Jy2Q3X1MPar8qMDGSHWWhdsVsYQ7hsqEYFMA6D8fI=", + "BBF6A8617FF257E7E4E0A36D174F975F:97DhQiXgjEjGbXP4O9R2aIMoz26MNPr4uSJ3kHxpzt8=:Character_CattleJar", "6782F1D85E7DFD1D835C9B7B2A461001:zwni3LZXkLjSCnwE43DH3DqME9Z3zpCt2XOnx0VCOg0=:Glider_LastVoiceDive", + "F1DBEE1A4C88D59EBB63579C7163E7B6:7dSf2Qx4GGgM/q8Cvs54ANwQv6ZbPqjVrE1Fh1V0MSA=:EID_Hurtle", + "190EE0858B5F6B5C09F029BCEA7DA1AA:s9BgWW/XUvjz8cZX5mD1tno+F+O/c2SL1w+yYuPOzqI=:EID_WormChalk", "CB2F74DD1C6D7FB4560BF4AA6B7460EE:1MXyB7YDAZC+p/2Fl+tefE6s3cCdKs+5tXDHEg1JLfg=", "44DB36B2D2B3854669780458D2FE48C4:gtl0smAMRKg8d9TdDH47lUOYCygKzbAPA6/HaXLWy94=:Season17_Magesty_Pickaxe_Schedule", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_910_Athena_Commando_F_York", "A13ABC32168BF8FE80F667ACB4BD5AAF:WsXMYjk1W2VJ8o9Dj7FXsaKvHNeHydr2kJEiwPRIMwU=:EID_Triumphant", + "DD660E9B181B4FB3D8A9D263E3FA4B36:AUWp89XbGF2UVGaWxF/6iF29PT4/axTl3zbkG/w8Pfo=:Glider_OliveStomp", "9261CD0F921EAA3CD6AA8C0716FB042B:W+yzeWWxWnA530lwV8nLi2BE+TD5MCXS11th7UphmPQ=:EID_Typhoon_VO9OF", "EB16EA013B751792698E05435797C1ED:y9JgD812Io4mbaJ5i533Ts5SSfyXaGM4JyoimjP+i4M=:BID_245_BaseballKitbashFemale", "22AB4BDC10065AA49B38DE88522DF836:1L8L+oKtSOtIxbm1x0HbDtzquIH6CH8vu1PF4i8jU+w=:CID_449_Athena_Commando_M_BannerD", + "1EC3010F39DA0C13B7232CB98575B7F9:LqmHEehKTTI2IsaKqLHpIwM5YTy6/uAlrcdFfA8JvF8=", + "98742D3B15A7227BA2A55CBD8C3A56A1:Kvq/pUKqQb1OGD76rGoOd0odcSmRtej5KvG4r+ofOHY=", "7C04002177805455CCA13E61F418D117:cacqp05gISCHgiULNDksrFNlUbhz6NxeW7pEr+xp2FQ=:LoadingScreen_Genius", "ABBCFB5A5EEF4E14C2FB2A379152E402:ZRrlkrmu0l1tGZe5IyUOVa2mEJLbjuQCnoiGaDbmFXg=", + "0CD9ED7A97214AD457FA85684FE090B9:HvAI6wSJh8NY8RIJXivhOydCmh2ZDpV9COeaD1i1VYQ=:CarBody_Smoke", "AE9F7B3419C7FBD2414D72E2E1C8A7BA:kpIotniLp60tWfbBitDUrjw6gmJ2Swl+YT3QAkecpRA=:CID_547_Athena_Commando_F_Meteorwoman", "4BA767BD2DC06D215B435AC09A033437:QOfpKnEogmj0tTa5wf49SZH55Sy48QEGP02DbkSg218=:BID_A_009_Grapefruit", + "0A6F8755332638E42FC052470B3BD065:OGqX2AuHNDfNO1iagEg6fwOr3Ib0s8/5iOBLnDc0vSE=:CID_A_158_Athena_Commando_F_Buffet_YC20H", "929B82B3454DF80CC45B11A55400B6E7:jl/KsmshfBxKKnPDHyHNTHOzTE3buCIrBpSUpXJQdL4=:Glider_ID_107_IceMaiden", "5A1170F589134C4D68AAA2B5AA6EDA69:bfro7s6Qtde/H7C4zc6MJdpua1mhem8HywLluxBLDrg=:Glider_ID_250_EmbersMale", + "C8622C1038D4A1CE0A2FC89863C52899:V0cZyuTcsYqvD7P/3LkWM6F5WUXog2UUaUU0Y8hb4vM=", "98CAB76B2CB8406085C8CDF566FFF5DD:cucOYeadgsZAhkdKC7Klc4/BhUe0SnQtF2cwEScRBxw=", "F044853E82632E827ED91FB4AFBD28DF:LH1pXQ13KEoYfxxylALn8jaS0t/7IrVRVmO8UXieaVU=", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:Pickaxe_PotteryWheel", "5C25DC4FE406CC6DAAB47D5EBF222355:LH76FBWg3hkWPDgOmXcRY/YD33N/6E4qQxqKUvIp0oA=:EID_Ignite", "BB09F8C7991800CA61A7144E3A6219FA:o+Hvu5rCygQz66xIyk0SANceWaptKHLEls3vZaMW9oc=", "88FA70760D757D80F661FA53B4762EC2:7OtV76cpyOq9dNeM5PVD8TOdRcPx1K3weEPXzlCugu0=:Pickaxe_ID_682_BistroAstronautFemale_A3MD2", "7E5BFF3AFC483F87B5891536C0AF3DFD:dEBFRFQPYg4NndewaW9/rEDpW0N8VFh7srTZDn0aejE=", + "73794262E9FAA8543111C22668BFB4E5:2aV01MR1KWGjb4+zNwOKYcTekm5K+PdXPaN3XW7tz4k=", "312398E80AB6209B22CAA2EBAB2DB35B:QZ5uhBnQSeK4b+u9E6PTfw7j2scPMTPX4fFTOJWIwEM=:EID_Shorts", + "D979E822DB9DB03D1522C7B6C492BB2F:uB0mQnFz2a19zk2os8iIiyz4tQuXPvdrfcLKaIXil8Q=:Sparks_Guitar_BottlePhone", + "258D945630DF6E1016889F47B16EED80:zQ/4osJ36W0V1DFXswf8JSStDMBTZPQ8oFcMrDqS7BM=", + "36A1455D04820E3D498C146613F97D3A:1wqflYVZsPsUy4tkHkNgFNj7CC5lyh0fUAFJT1UskiI=", + "9CDC09A892C78780B6DF32091970A6E8:FLVM+9t9Iz18CutCTIaHONqsMCwfERIpJu14nXIUTHc=:Shoes_StrandModeFigs", "8D44654E9EA2AAC35E489476B1948E58:Dwb/irSIIGd3tLLPEP5OqJY1D4KfjdP4+uP4+Ht4YOo=:LoadingScreen_Elevate", + "67E6E3BB6F124A14AA5C077219A41814:eg6SwkhZyo//UwwX1hm0vg4AC0N++fDGUFOdApZuk+I=:EID_Cobbler", "63722D44ECCA0F4178B85F5A6BC4C31B:j42UL0bmfBkli6Aj92wWABwFby5rAplP/Ac6nh9kRvA=", + "1EFA43A2FEDB492EA32BB6AF50E8B0CA:ukW+ECABl8sv9qFUdpckdqW6IRsZAPnPEWSu6bsbCYs=:Pickaxe_AccentWall", + "2E905754493650DF88C8E97682EB82CC:mi7TaYylDcfidaBKpF+rHEU9HuMOHmVqhiuag4C8KSU=", "FAE51F5AC49A240384D5B57EA08B1F90:oesTf9AVGgX4FVwWzgm++nQEO0aARyuU5rZa1f6hoFs=", "79F7D9C856E8CF354109D3298F076C06:Ak3TOM0i0Mq/KYxd7SDlSuS7o55USaf+urL6WqnmalY=", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Fig", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Pickaxe_ClayPlug", "4E7938F1FAC98BDF378823116712AC7A:jbZVgprILTQomUdGeJF0PsAFAJxsSCs5cKcXweZMAg0=:BID_586_Tar_DIJGH", "25A2BE0115631B392E3C3217C645540B:GyQ18n64dldycxr5SPLRfWRNnxFB3eQFK07BbTgleUk=", + "1301F2838EB647C3D111CC1A61C7D8C3:OuEyyvjyHEYgHt7u8KA2UvKxsCBLlwmwq01D/ErBAWc=", + "FBAC0AD8C03AAB2DC3BC077597517179:5oj8B4R53plPxRictMN6QkQ741CibMbmzRJYIDIQ5iM=", + "E9E8A12CD60F5B7E5FCE97F43565BD4E:cCTmwC/MmQKzjDfE7lzZrTRAGGHqqWAbZ5HQ7KGhCw8=:GameFeaturePlugin_QuailPlaylist_v3", + "003C8A31FF60E8C3BDBF4FB76A7CC4B8:LAKZR/gRSm44vZpNg9z39srsStFM7n68AVmC/yYDNSM=", + "9DB808E8A3748C92F9B2836D97F12E43:8/7CEcgqMxbP0Njwt+FfkrpLL0re3J/cSvasQ9DuVAo=", "308F587F46CB50450DCA9B9CFD50E120:2nvyeGrxnqL5SJjMPag1d9YiiXfdGYVkL/WJqWYnC2A=:Glider_ID_099_Moth", "6D85E82539341B90944E84FFAAD872FB:mAiBk7KbE2Dnr+yVFyJK1yAwv2eWb+yANFH0z2krQkw=:Wrap_087_BriteBomberSummer", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_939_Athena_Commando_M_Football20_C_9OP0F", "89CD763ACF4C3672A0F74AC0F45C291F:vtcPbnTh2aDOt7LfYpJL+7aF1TaB8LDaLsMoQ47NZec=", "E4D8D083C49828F6BF310ECA74A84F98:NxjtZXHe49xC1zUVs+XKjHbeic3prkFOWmwkaQ1vOFw=", + "7C42ACB64B36D79BCA563A9EADA48FCE:pTxdc0fLo20cxQyRq70wLCAiFzPfYaPtq7VrxTawHKA=", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:EID_PotteryWheel", + "2071F7A7C5CCCDD3348461241F90CA95:5gfMp4/23HkRIin3rD81b4UhuH8muYsjZUQnyb58mg0=:Shoes_SurpriseStep", "8D44654E9EA2AAC35E489476B1948E58:Dwb/irSIIGd3tLLPEP5OqJY1D4KfjdP4+uP4+Ht4YOo=:Pickaxe_ShinyStar", + "73D899AB236474741E0B023F2B00FD88:CkZQjqgV2rS+Uwf/00TbN+o74EkwHmOdhjWxRLLbAqY=:Wrap_HydroBottle", "2A236A35ED4833924DF975CEBE4282AF:e4NpefIqezxUVeH+2INzCV08eK4NvFrojB8z1awxm6Q=", "D2FAE1D098B2B4695EB59FAAD504798D:ZUDIqDvGVcpCVuA3h67vdkVbZwLuC0Z1zX33JLyi5xE=:BID_924_LateralMale_Y2INS", + "764FF921F91FF41FAFBCFB6B899027E9:3tKZAlf6f61vE7KgYzFcFWCbg2W2kZTK38PAqIVSDAs=:Backpack_PastelGlazeGift", "010E6ACF85E4A58BF6F551EFE7B85F61:DwCIH5Dw/1wdiS6gFGmWe4HUgD9kMOEzjbzM/1QshM4=:BID_234_SpeedyMidnight", + "524E3ABF1DD30667B36C83F283B05195:psHqDFvyUISUa4Vm+z+e8kpQ/bxTybJYkpijcvRjHiY=:Backpack_YamPowder", "54FD9ABD65879452DCB8CE11C1D7F1AF:nV0Vm4NCBl+MkGX8wiqfFrg0viDriL3I2xc4KS7n7fg=:CID_422_Athena_Commando_F_MaskedWarrior", "929B82B3454DF80CC45B11A55400B6E7:jl/KsmshfBxKKnPDHyHNTHOzTE3buCIrBpSUpXJQdL4=:CID_298_Athena_Commando_F_IceMaiden", "7D4C5F196ECABABFD430C68C3FB04C0E:o27sbmbMHSSe9j8hpkaaObpYOnIVkZxtao6IDUUBa5s=:Glider_BraveBuild", @@ -1239,32 +1969,49 @@ "8D9CFEEB5299B3F8400B8E2E67B8A1C9:wwFluOAmcnXcGsyJRGJEmuC22cypzH4xThcZASR+IHU=:Backpack_FishBowlBone", "F07BE27DCEFDF52818EE7BA2CD9CA504:lc47A/VahaBWJLQY4V1YyjzJPI5xVErInDaqdwPjv2g=:Pickaxe_ID_200_MoonlightAssassin", "34DD24ED0CE62244E7FFD27EF4C29EB5:jTgMUc1ciLKwXF/PqyFJl6s9Iw5SXYHKiSThOQhG5TE=:BID_938_FoeMale_F4JVS", + "DAAD9ACDD8C3690CE4D11DA2D7663DFB:OL1/ndG9SEBobBCmm/+Aqy67S8A6sebpFV4we3HFjoI=", "9FD68EDC1A5A456225A1C14E1488C573:vfIZFBmmSWgvzSDG/l7N0EGIrANZpUKA7Ofqo+n4fBg=", "C8EDBD039269967B5BE92CCDD8A9D62F:8gR7wuE22djecHDkUAKfbBCtvwwWeVjZxSOBag9drI4=:EID_CoyoteTrail", "8DCAE39C7D9690E19F52655F02C613B2:ZZHbiVsbXquLlrtNVHtryLS3Vd1Ego8/8tlDpeUCgfc=:EID_ScoreCardBurger", "4EFDA950DA6AA1E6422D2FBF6B89DE85:HDEI+ufmAF1VN2+mYiOFFFDjPVAfkEcmrnyTQh85dmo=", "5098C0AED639B6C90A785C727F0DED4B:/YNq7WVNgAmtcY8eS20XBvoz00E1Z/1/Q0BZ8EluHf8=", "E8585F83E40CD4CF0272EA6012055A97:4LrXtLEBhL5JquAu4/kq1Dghb4/355YROt3ciXg+ysE=", + "11A2A4F6D2D907D8718A91CB05AF99F0:psD4DdrmKRTtrbaAkoDjTtrC0zZAclPsWm93aw/e6hA=", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Backpack_NutmegMayo", "1B1978CC0EC6D4D937800A9E1CA87CA0:OjIDp8UXlfFZCaVJ6GLnMM+98VabjD7EB3J7ahiRNk0=:EID_Gimmick_Female_6CMF4", "FCD2F65146D53215F92F558CBA418191:3cp//Ss4zbgQ6tnnNLBcaTy9fsz3IM6ddZmiQSkX43c=:CID_336_Athena_Commando_M_DragonMask", + "2E8C63FEDFFE6B835126B6FF7CB47062:B/uSSHdC8IsSccWS2rt8Cg0lBjG3+k+Ncu2p/qtB81Q=:Wheel_Melonpanb", + "11F0730066B941C7A4E9255EA2FE23F1:/3vLdT+H+32W0x68sm7cVpBYK1amMPmcVTviVyM25dY=:EID_Memory", + "EBE32FA2FA482E04BAAA6F78C6A15AAB:dkUSQryp9BwJsGiQtQEIn5JJ3wQyBwxlsKtLxx9GKOQ=:EID_Harmony", + "19FDB99E0C353A75CAF1D0159A566939:s+zGkNSkgLHoJYLtagHc0L5TTyTYcMvb2Yq/Nooq3vM=:Glider_CoconutShell", "06E3CB03E94C4D850CE185166706E868:jDuRIbxnZBnAH/hUrfRX3qnGyIogSWUHrK6nq7Et3pk=:BID_771_Lasso_ZN4VA", "19CAB803EB00118FB3E6B3E5ABA7B234:tRM77TfQWWJ38hNsFLjt7jMNoSOozxqi9PF9/9H3rmU=:Wrap_154_Haunt", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=", "A398C07C0A77D834038E7192FAB52B4B:/+4taU8TYRe14OhUt2cevoUqUOh6ado2hWu45FJ+7yA=", "C5C1E0742C0BFE4264242F3774C13B41:BO5aZnDZhvHsUFLsJD2vtYCQ6iYpX7Lhl565nDsBhaE=", "6AD4E900C2E9E785B0442E0A60E74C66:FbrGkaMoqjq/CaamdJrQUBz/PjBqtA0wFlGj1VOxH6A=:Glider_ID_378_EnsembleSnakeMale", + "7E3B0175F4929DD5C6C8A2D889B24F81:BOiNpViUgeXK2U6iFe7NS5c5fgHayrpHnNMaR2Ha7xw=:Pickaxe_ThickWatch", "B3BE1C036099F140800BB7D5FF1D9C49:bLt9+35t2O26OTgiEMuUCvH1kn+lGjTjhaEEoiz4CtE=:Pickaxe_ID_535_ConvoyTarantulaMale_GQ82N", + "00AD98CD646E51F9064470AF81753C60:hpnxeheofJRm7KP4G+CZE9/C/iVbil26OM89045T3/U=:EID_Prosper", "40E9F547033360DFC0DD09743229B87C:x0/WK54ohwsadmVGHIisJNyHC8MqlU8bg2H+BsaEBtc=", + "EC3A3B043274AFE81C98D457AA06DC81:mc0Pp+yPMQkSyPDjUE14s2q/cHuhybPBRwiMtJj7DVY=:Pickaxe_NutmegMayo", "56812D9CB607F72A9BDBADEE44ECCD21:pj9dMhJSaj6V2HsA0VWABE7Cs4+eEBz1Kex340gafK8=:Pickaxe_ID_199_ShinyHammer", "42FEDE262B530BFDC25D9E6B8684D1B7:bXloLJVoSi2uTe72cpdsB8pAmUPKzmxwPC2GPhHFVhk=:EID_Layers_BBZ49", "98BCB8B7136162178BF364D6105BB9B7:c1dhB+vWHWRw3YvWpsHRj9Ayj8JjdqYOLnyr0YImxVo=:CID_999_Athena_Commando_M_GlobalFB_E_OISU6", "AEC9FD29ACF48B274A1A573C9ECF4B06:7OT+zOUDq1RjYJKp8gQhbUnYz/qJ19It2X4HduP5y/g=:Pickaxe_ID_249_Squishy1H", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Character_FreeDrive", "110D116208C62834812C2EDF2F305E49:MwuF5zX7GpQCGL2w+CwkPmGzH3q05YUoLo5udhVMNPg=:CID_718_Athena_Commando_F_LuckyHero", "4EFDA950DA6AA1E6422D2FBF6B89DE85:HDEI+ufmAF1VN2+mYiOFFFDjPVAfkEcmrnyTQh85dmo=:Backpack_SunBurst", + "802F5EF63DFD75EFCF29ECB136B7F3DE:IaAlpO/Z+P6EOuyall1q/NvUD8OQhQvyYZRVHJrO1qc=:Wheel_BasicAW", + "11F0730066B941C7A4E9255EA2FE23F1:/3vLdT+H+32W0x68sm7cVpBYK1amMPmcVTviVyM25dY=", + "28415C253906F793828C5BFDE29021EE:V3kQXXhHR2QVki8kOmMcQtbReU5I/aS24bZ6j6h+NoE=", "EF7C5225BD60644B313ABEE69182A302:ITNJPJyUEyMw8YrBk89HfKwHTFV6jGJJHt4D8UmpaxI=", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:Wrap_WarmShade", "8C623F6A49CFF9ADC7895A466CA1C896:kLmYdLi+jOBs2k+B/UxrCcPSdvuNYTha0xl9+SvUzJU=", "56812D9CB607F72A9BDBADEE44ECCD21:pj9dMhJSaj6V2HsA0VWABE7Cs4+eEBz1Kex340gafK8=:BID_254_ShinyMale", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:Glider_ID_248_York", + "540DEA2C5E3510D32704C41A4B323118:GWPcu+VRPtu1WCOiRCJHR5adSzIp/4ndXT7TLZ8uDb4=:Shoes_LungeStreamAlto", + "32AA2546A88B1797C12F9C35A8492CD2:XBMYQphlCk+dBFuZtBzrIwLNnpmxl4gKEsysFoJ3yao=:Shoes_StemDotChaCha", "CE9D023C0D7DBF7634F2AEF6200BDB36:JyhTmjJnosQmLeGMQXhCtkl/auX+mde5P11MsWEwIqw=:Wrap_DarkAzeala", "8D9CFEEB5299B3F8400B8E2E67B8A1C9:wwFluOAmcnXcGsyJRGJEmuC22cypzH4xThcZASR+IHU=:Glider_HighBeam", "D938886074C83017118B4484AECE11AB:wjHAHm00Vg6n2x5LU91ap0+SFX5ZXXBmax1LyX8Aips=:EID_Alchemy_BZWS8", @@ -1275,21 +2022,38 @@ "DC487286E8C1CD5FE18AC3FE76034EF2:3h9IwK2qQP8PHVuO1aZI1C34JrJxKBnXJOFcSDSj99M=:Wrap_102_WorldCup2019", "C5C1E0742C0BFE4264242F3774C13B41:BO5aZnDZhvHsUFLsJD2vtYCQ6iYpX7Lhl565nDsBhaE=:EID_Martian_SK4J6", "376B77890B5057EBBE1C3D0CD97BF4C5:UYA853Oz4bzCHoXU73CELJzefJ4EE1VjwEUiXti8xns=:Character_Pencil_Grape", + "06381A8251E28744D95CD28E6C038AFB:8bDBEnhD2eZ9h8j8E/dfJ0ZSH8DVB0Dm+rZdVMYivlE=:Backpack_SnailAisle", "E0AEF4894E1283946745F7902F7E105A:7MXKJEs903nNbT1oFzykxoHbQNDnOBm6yfadj+mtBDA=:Pickaxe_ID_752_RoverMale_I98VZ", + "664AE10E66BFDC167AE20432295E8F7F:MA5EHgSc3+WIzYlG5t0Mfc4sosVF5TnVDCTKcG5KyL0=:Character_SweetLetter", "FE0FA56F4B280D2F0CB2AB899C645F3E:hYi0DrAf6wtw7Zi+PlUi7/vIlIB3psBzEb5piGLEW6s=:CID_220_Athena_Commando_F_Clown", "8DCAE39C7D9690E19F52655F02C613B2:ZZHbiVsbXquLlrtNVHtryLS3Vd1Ego8/8tlDpeUCgfc=:BID_337_MascotMilitiaTomato", "7C469274E430B5E3005EF1799DE618CC:5j5CNw8BI2+kBShT+u7kgw9HyCZ3dOvCMGBO9WScNPQ=:Pickaxe_ID_850_WayfareMaskFemale", "471CA05DCEE84890F9287E4E0DB31C08:cclx9Dp+FcphJfVZLUAdo21nLGn8pQ7GutQgY4LCOts=:Wrap_Comp24", + "86ED92FA0E4776D8D3B60F8259B393A9:JOIq5LeFGyI67axw4UZ71Xnjyfw4sPyRVCBoAmy0InM=:Backpack_PageTruffleBead", "5738A14C7E45E1B405CEF920829CB255:xZHlPTz/dxNahrp9IqTZ+tjOZSYMxQb9KZFXlg9N638=:Wrap_180_HolidayTime", + "5B7B9F3A14035E5B3984266770BD2CBA:9aCk7Ou+vDcwgqYaCZyvDFXNhizDGQhv5bkPfHk7oRo=:Wrap_MiddleSock", + "98742D3B15A7227BA2A55CBD8C3A56A1:Kvq/pUKqQb1OGD76rGoOd0odcSmRtej5KvG4r+ofOHY=", + "A76470952FE7FC15145AE4E1EB9D85A7:0VhPrkcCrAX0GuW8LVplYGG3GcAT5foNc02I/p97H2g=:Wheel_Seba", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:Backpack_SodaMug", "7B1151E3094646DFFD37B6492B117FDB:4WxNHdTgHDEpGjzIV2XIjGO41kyiwggFQpdq8y+o1jY=:BID_733_TheGoldenSkeletonFemale_SG4HF", + "3680306271445984B14C55F541805805:q8fDGIw6oD3NBh2qxjPcatTnsYJsREUK5M8U3AGQOGk=", + "D345D95CF72A6C367ED8F9E0A52F1C76:fmdbzNN8Mv1eax/HDrD+njt4pALWVrtiUwbFgmT0NzU=:EID_Goodbye_Upbeat", + "9BECF2F1BD7EEB85DBB2A7721E3FB8D2:PbU+OqDVwukbJo9ML8JYwZGC49QppuMksL4GmKpIFn0=", "B1EB196DD39D0736E7E08F99B07D8B9A:1fDhBY8uhi++l6QQPL2YtxZgUv04OZoMGBrH+yN8yKM=:EID_SandwichBop", "2E5F91AEF58F310AE2044EA39C43BB81:pNy1GtfVzymqacOqXRY14EZEvI5ZSVD5AFxlhxXC5qk=:Wrap_409_CritterManiac_1B4II", "7C469274E430B5E3005EF1799DE618CC:5j5CNw8BI2+kBShT+u7kgw9HyCZ3dOvCMGBO9WScNPQ=:BID_A_061_WayfareFemale", "01079D19DDDEC8BD51AF536A7106906F:QQQwnB63pdEdKEqLYP9QzAaJXakZ3w1Iuai7YU3A+Xs=:CID_A_304_Athena_Commando_F_Slither_B_MO4VZ", + "65A22570A201A6CB2BD8818EF11B5134:VEVi+v7IDOe1xNkO6cgk6d++ycT42AejDHMvZAshvPY=:Pickaxe_AgileRug", "F78569F2AD7950F870965BC647904647:e3+Nhzk8SBfmZWoQThFsZmnyJs2AoJ+LQDgMz45YAUE=:CID_952_Athena_Commando_F_Football20Referee_ZX4IC", "360CD59F6F7B68A441DDED9DB5FD13D7:G6pVAf/ul1HPYh6s2M1l8G4hn62jdwkcbegeLoxL7Y0=:EID_Ashes_MYQ8O", + "2D7CC66E132AF5D216B481F2D0B56EB7:1OB3Dm0UQSumE4qrNw5lpTWgx1bjEqOFE3+s3Xo4Vu4=:Shoes_FunnyBunny", + "EF0F3917780CD815EF15D46DED289E29:C9FqaY6b9Gwh7bUPBXxhZmNtVyJPxxv8lEsXPoXE3nI=:EID_Mirage", + "183F391FC33450CB879EE601584DBD34:It1/5uQ3GeW9HOMVAnKFMsnoYD3r5QSpru/RTUf2dIY=:Backpack_BikeMold", + "1269E6F7E620736515D3F57CE4B2938A:P+cnpG9HbjrhRGcxCH+FD5C19cSQij2V7pHTsbVfi/Q=", "1937F4ADBC2C38EF4F189DC2B1AE58AB:tWzxKwKEDzI0RsQGl2GvOVqZwxOSOiZaCQkyK1hE+lA=:Backpack_Inspire", "CE60A61FBEAC33EBF231E79C6BBB3D19:y7XCzCCilb1Q+TlLtT2sQCAryt1gIZ9PPI2dtb5whik=:Wrap_FolkEvening", + "9E7468047D1781BCB546D5AE215B5073:EYWQj4jWQQnEZ6i1eKfW47bvGqK0ZNt7KFzQO1P6FU8=:Backpack_TimeSquareBite", + "1B6D6B48DFCDB01B0CDB8AE49A8B2445:3DJghcvV/qBavlgT2JMumI49yQIz+5CMF7ke7sD+lx8=:EID_PotteryWheel", "2F1A5AFD22512A8B16494629CCA065B2:Un44BCuGtirrKab0E9TeOyDRnWC/Jh1h48+FOn4UrtA=", "457F39EA51FB4C723B442810750CDA4A:V3d05mcuS4uXMBRpy63TIZDLt5hg9njVD0SGhZDsmBw=:LoadingScreen_Sahara", "195439D6DD0FE44ADAE6BF7A44436519:kRCw7VFSPCYqhu7lJlA4kO4YmsqZUzxM6ARm7Ti8ntQ=", @@ -1298,17 +2062,29 @@ "F3A99CD0D4F58EECEEB0D112506AD846:ZZtCRPcKk6itVryDavp7uZFIXiZF5CW0O9b+8Zt2Oag=:Pickaxe_ID_645_QuarrelFemale_W3B7A", "C1E73246C58C0BAC3FF50B346684D278:lWvPsfsWVsNVDSOH7JpZULEgoQ+JKrWPuSqIw942mmo=:EID_Marvelous", "95C6C2B37E1D15D60BB5C20D9D47BA31:exdH0xe2v+2t1wyoXpZGLX+iGDIdRxcQ6BG9iqi07Lo=", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Character_BraveBuild", + "29F9F9F254AE395E6518C4E938FAD223:YHitqbGo/XcUnO3xcnaD8YpQU1gIZoCmpx+oboYJLTo=:Character_GallonBag", "5AEDD4DB5DA39071FCFC2404EEB3D02D:qaoe5DQrf1+HPEQRW5zls4KSe7DHbrxXO8OZMsFeo8Y=", "3D9634EBDF17C26278CDFE91EF0130E8:tVvwjIulbvPLmBKlFhBwKSOGqzCu5yu9CqdH5008u5U=:Pickaxe_SkeletonHunterFNCS", + "6204514DD102F27477CE0D7A811CBBE5:oCjlylDEodHnTy9bxZ1KT99Dfbkhsjw839ymo1O91uU=", "828B24CF7786DF74D8511CA89DEED8CF:nCahv7mQhidmYXSmKif6z7d6bQ60mdPQ7SrdZ7a3GaE=:CID_907_Athena_Commando_M_York_C", "30A1FD89B2D3C155DAF14852A39BA97F:C0IwuJFw9v06OF8XthOhzUd3nHOTCII1gmx/7eepmDo=:BID_947_ZestFemale_1KIDJ", + "E5DEC1C078C14E27A5FE8A9D0852A4C5:LigwbpAOIj6Fhmx26rH+b9j89G0/CDqk+4AiLiF+NLM=:Backpack_FreeDrive", "162FACA3B0E34C1BAF897ECD28D86C84:rKWv3Qcmp+oMK1Zbw7bhPrNSiFNoNZyIlXUW73ZrUnk=", + "BA02A6A5604CB94ED9B9D7A197670870:OuvUXdw7gThaUToKPCUt6lZBJfOgKYgS8+fzL9cZZ5U=:EID_Incantation", "E0AEF4894E1283946745F7902F7E105A:7MXKJEs903nNbT1oFzykxoHbQNDnOBm6yfadj+mtBDA=:Pickaxe_ID_751_RoverFemale_44TG1", "FC4E841A2B346A848784A3190B5D05B2:a4+ZHXPUacxXOJmJxoJlp4vzzEApO6fWJXvvUYW43yU=:EID_Beyond", "66B8D4B61985C510209FD18445953344:Vq1odf+xCxp2/WBssHZPvUUyI9ay71eVsuyoz/z9zdk=:EID_Spooky", + "1759015C47EAE151CF9C269B847F125A:2yD7LwG+g7S8pMkELhwcHXO9Z9l2+4UpwYZFq/fHSuw=:EID_WarmShadeWagon", + "EA894BE3D14E66D4D1D86D9AE2EE9514:Tpl0r8Hy6cukvzcZVDoFMxZA5sFZOeuck4JENOfmLIQ=:EID_Vacant", "8033BA4F3E1FB68ABADE271C9BE4EE42:XGwA8RWdavpeScQpqM/aFod3SGTB3PibdGE7iGKR4jg=", "D776CA2A40FD9EC1F8522E9E13E99031:uRYulzQ2zdGG9UisQw2wM9OOM/9JsSWFwFt5d/3okng=:Glider_ID_121_BriteBomberDeluxe", + "55E06C93E20E98E33AEDD3921554723E:NYB0Et4rpoCY0Z95vJH6CX1V8P4pEheqAzPDQVh3ABE=:Pickaxe_ClayPlug", "D7727B4696A62373E9EBD9803F705B3C:XEbXIzCpOuA88jMBtt+XuMt+NaOIWlvfpW9h7i/dFlM=:Wrap_036_EvilSuit", + "0C81D16F6CF41C862D0B097DBE5E624A:qIzymfmYIWAQbAhalU2MQOR6vwmj42xHgtW41rhIev4=", "6782F1D85E7DFD1D835C9B7B2A461001:zwni3LZXkLjSCnwE43DH3DqME9Z3zpCt2XOnx0VCOg0=:Spray_LastVoice", + "D8A7FC9D965E9DE5EB1D392DF5D316F2:9yFRWW4cQe7TPVkMbYS0BklRUsIQowHM3XvCV8NNwLc=:EID_Prelude", + "8F7AAC929AED8C9231EA30CEC0A2A75D:1HeufgQ+oYCTosTR/ILGHFnypvS+udjy1Tsyffya+qs=", + "F93D796690441FECFCE4788C6267E68F:c7zg1pvZw3b5GRdU4et/j8mEfs3MQzVFiP5A4mq7Ygg=:Shoes_PacketCrescentAlpine", "01FC97F8787B82E027EC64661E0D36AB:Mh1l2LJ3YrgaZtg7sRTd8XeBkVcyA3i089gZKkTr1gM=:Pickaxe_ID_782_CactusDancerFemale" -] \ No newline at end of file +] diff --git a/gui/dependencies/dlls/RebootFallback.zip b/gui/dependencies/dlls/RebootFallback.zip index 6026edf..f36c2e2 100644 Binary files a/gui/dependencies/dlls/RebootFallback.zip and b/gui/dependencies/dlls/RebootFallback.zip differ diff --git a/gui/dependencies/dlls/RebootS20Fallback.zip b/gui/dependencies/dlls/RebootS20Fallback.zip index df8b3be..1d72e10 100644 Binary files a/gui/dependencies/dlls/RebootS20Fallback.zip and b/gui/dependencies/dlls/RebootS20Fallback.zip differ diff --git a/gui/lib/l10n/reboot_en.arb b/gui/lib/l10n/reboot_en.arb index 7c57c8b..7f95747 100644 --- a/gui/lib/l10n/reboot_en.arb +++ b/gui/lib/l10n/reboot_en.arb @@ -128,10 +128,11 @@ "importVersionDescription": "Import a new version of Fortnite into the launcher", "addLocalBuildName": "Add a version from this PC's local storage", "addLocalBuildDescription": "Versions coming from your local disk are not guaranteed to work", - "addVersion": "New version", + "addVersion": "Import", "downloadBuildName": "Download any version from the cloud", "downloadBuildDescription": "Download any Fortnite build easily from the cloud", "downloadBuildContent": "Download build", + "downloadVersion": "Download", "cannotUpdateGameServer": "An error occurred while updating the game server: {error}", "launchFortnite": "Launch Fortnite", "closeFortnite": "Close Fortnite", @@ -146,9 +147,9 @@ "defaultServerName": "Reboot Game Server", "defaultServerDescription": "Just another server", "downloadingDll": "Downloading {name} dll...", - "dllAlreadyExists": "The {name} was already downloaded", "downloadDllSuccess": "The {name} dll was downloaded successfully", "downloadDllError": "An error occurred while downloading {name}: {error}", + "downloadDllAntivirus": "The {name} dll was deleted: your antivirus({antivirus}) might have flagged it", "downloadDllRetry": "Retry", "uncaughtErrorMessage": "An uncaught error was thrown: {error}", "launchingGameServer": "Launching the game server...", @@ -212,6 +213,7 @@ "selectBuild": "Select a fortnite version", "fetchingBuilds": "Fetching builds and disks...", "unknownError": "Unknown error", + "unknown": "unknown", "downloadVersionError": "Cannot download version: {error}", "downloadedVersion": "The download was completed successfully!", "download": "Download", @@ -258,7 +260,8 @@ "emptyURL": "Empty update URL", "missingVersionError": "Download or select a version before starting Fortnite", "missingExecutableError": "Missing Fortnite executable: usually this means that the installation was moved or deleted", - "corruptedVersionError": "Corrupted Fortnite installation: please download it again from the launcher or change version", + "multipleExecutablesError": "There must be only one executable named {name} in the game directory", + "corruptedVersionError": "Fortnite crashed while starting: either the game installation is corrupted or an injected dll({dlls}) tried to access memory illegally", "corruptedDllError": "Cannot inject dll: {error}", "missingCustomDllError": "The custom {dll}.dll doesn't exist: check your settings", "tokenError": "Cannot log in into Fortnite: authentication error (injected dlls: {dlls})", @@ -282,9 +285,9 @@ "infoVideoName": "Tutorial", "infoVideoDescription": "Show the tutorial again in the launcher", "infoVideoContent": "Start Tutorial", - "dllDeletedTitle": "A critical dll was deleted. If you didn't delete it, your Antivirus probably flagged it. This is a false positive: please disable your Antivirus and try again", + "dllDeletedTitle": "A critical dll was deleted and couldn't be reinstalled", "dllDeletedSecondaryAction": "Close", - "dllDeletedPrimaryAction": "Try again", + "dllDeletedPrimaryAction": "Disable Antivirus", "clickKey": "Waiting for a key to be registered", "settingsLogsName": "Export logs", "settingsLogsDescription": "Exports an archive containing all the logs produced by the launcher", @@ -306,11 +309,8 @@ "quizZeroTriesLeft": "zero tries", "quizOneTryLeft": "one try", "quizTwoTriesLeft": "two tries", - "gameServerTypeName": "Type", - "gameServerTypeDescription": "The type of game server to use", - "gameServerTypeHeadless": "Background process", - "gameServerTypeVirtualWindow": "Virtual window", - "gameServerTypeWindow": "Normal window", + "gameServerTypeName": "Headless", + "gameServerTypeDescription": "Disables game rendering to save resources", "localBuild": "This PC", "githubArchive": "Cloud archive", "all": "All", @@ -374,5 +374,10 @@ "gameResetDefaultsDescription": "Resets the game's settings to their default values", "gameResetDefaultsContent": "Reset", "selectFile": "Select a file", - "reset": "Reset" + "reset": "Reset", + "importingVersion": "Looking for Fortnite game files...", + "importedVersion": "Successfully imported version", + "importVersionMissingShippingExeError": "Cannot import version: {name} should exist in the directory", + "importVersionMultipleShippingExesError": "Cannot import version: only one {name} should exist in the directory", + "importVersionUnsupportedVersionError": "This version of Fortnite is not supported by the launcher" } diff --git a/gui/lib/src/controller/backend_controller.dart b/gui/lib/src/controller/backend_controller.dart index 1c4f983..e74ba43 100644 --- a/gui/lib/src/controller/backend_controller.dart +++ b/gui/lib/src/controller/backend_controller.dart @@ -21,8 +21,10 @@ import 'package:reboot_launcher/src/util/matchmaker.dart'; import 'package:reboot_launcher/src/util/translations.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'hosting_controller.dart'; + class BackendController extends GetxController { - static const String storageName = "v2_backend_storage"; + static const String storageName = "v3_backend_storage"; static const PhysicalKeyboardKey _kDefaultConsoleKey = PhysicalKeyboardKey(0x00070041); late final GetStorage? _storage; @@ -162,6 +164,14 @@ class BackendController extends GetxController { detached: detached.value, onError: (errorMessage) { stop(interactive: false); + Get.find() + .instance + .value + ?.kill(); + Get.find() + .instance + .value + ?.kill(); _showRebootInfoBar( translations.backendErrorMessage, severity: InfoBarSeverity.error, @@ -508,8 +518,7 @@ class BackendController extends GetxController { }else { FlutterClipboard.controlC(decryptedIp); } - Get.find() - .selectedVersion = version; + Get.find().selectedVersion.value = version; WidgetsBinding.instance.addPostFrameCallback((_) => _showRebootInfoBar( embedded ? translations.joinedServer(author) : translations.copiedIp, duration: infoBarLongDuration, diff --git a/gui/lib/src/controller/dll_controller.dart b/gui/lib/src/controller/dll_controller.dart index 06b25b1..1960d04 100644 --- a/gui/lib/src/controller/dll_controller.dart +++ b/gui/lib/src/controller/dll_controller.dart @@ -9,11 +9,14 @@ import 'package:reboot_common/common.dart'; import 'package:reboot_launcher/main.dart'; import 'package:reboot_launcher/src/messenger/info_bar.dart'; import 'package:reboot_launcher/src/util/translations.dart'; +import 'package:reboot_launcher/src/widget/page/settings_page.dart'; import 'package:version/version.dart'; import 'package:path/path.dart' as path; +import 'package:reboot_launcher/src/controller/game_controller.dart'; +import 'package:reboot_launcher/src/controller/hosting_controller.dart'; class DllController extends GetxController { - static const String storageName = "v2_dll_storage"; + static const String storageName = "v3_dll_storage"; late final GetStorage? _storage; late final TextEditingController customGameServerDll; @@ -27,6 +30,7 @@ class DllController extends GetxController { late final RxBool customGameServer; late final RxnInt timestamp; late final Rx status; + late final Map _subscriptions; DllController() { _storage = appWithNoStorage ? null : GetStorage(storageName); @@ -39,15 +43,16 @@ class DllController extends GetxController { final timerIndex = _storage?.read("timer"); timer = Rx(timerIndex == null ? UpdateTimer.hour : UpdateTimer.values.elementAt(timerIndex)); timer.listen((value) => _storage?.write("timer", value.index)); - beforeS20Mirror = TextEditingController(text: _storage?.read("update_url") ?? kRebootBelowS20DownloadUrl); - beforeS20Mirror.addListener(() => _storage?.write("update_url", beforeS20Mirror.text)); - aboveS20Mirror = TextEditingController(text: _storage?.read("old_update_url") ?? kRebootAboveS20DownloadUrl); - aboveS20Mirror.addListener(() => _storage?.write("new_update_url", aboveS20Mirror.text)); + beforeS20Mirror = TextEditingController(text: _storage?.read("before_s20_update_url") ?? kRebootBelowS20DownloadUrl); + beforeS20Mirror.addListener(() => _storage?.write("before_s20_update_url", beforeS20Mirror.text)); + aboveS20Mirror = TextEditingController(text: _storage?.read("after_s20_update_url") ?? kRebootAboveS20DownloadUrl); + aboveS20Mirror.addListener(() => _storage?.write("after_s20_update_url", aboveS20Mirror.text)); status = Rx(UpdateStatus.waiting); customGameServer = RxBool(_storage?.read("custom_game_server") ?? false); customGameServer.listen((value) => _storage?.write("custom_game_server", value)); timestamp = RxnInt(_storage?.read("ts")); timestamp.listen((value) => _storage?.write("ts", value)); + _subscriptions = {}; } TextEditingController _createController(String key, InjectableDll dll) { @@ -78,6 +83,7 @@ class DllController extends GetxController { try { if(customGameServer.value) { status.value = UpdateStatus.success; + _listenToFileEvents(InjectableDll.gameServer); return true; } @@ -88,6 +94,7 @@ class DllController extends GetxController { ); if(!needsUpdate) { status.value = UpdateStatus.success; + _listenToFileEvents(InjectableDll.gameServer); return true; } @@ -116,6 +123,7 @@ class DllController extends GetxController { duration: infoBarShortDuration ); } + _listenToFileEvents(InjectableDll.gameServer); return true; }catch(message) { infoBarEntry?.close(); @@ -123,26 +131,29 @@ class DllController extends GetxController { error = error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error; error = error.toLowerCase(); status.value = UpdateStatus.error; + final completer = Completer(); infoBarEntry = showRebootInfoBar( translations.downloadDllError(error.toString(), "reboot.dll"), duration: infoBarLongDuration, severity: InfoBarSeverity.error, + onDismissed: () => completer.complete(false), action: Button( onPressed: () async { infoBarEntry?.close(); - updateGameServerDll( + final result = updateGameServerDll( force: true, silent: silent ); + completer.complete(result); }, child: Text(translations.downloadDllRetry), ) ); - return false; + return completer.future; } } - (File, bool) getInjectableData(Version version, InjectableDll dll) { + (File, bool) getInjectableData(String version, InjectableDll dll) { final defaultPath = canonicalize(getDefaultDllPath(dll)); switch(dll){ case InjectableDll.gameServer: @@ -150,7 +161,7 @@ class DllController extends GetxController { return (File(customGameServerDll.text), true); } - return (version.major >= 20 ? rebootAboveS20DllFile : rebootBeforeS20DllFile, false); + return (_isS20(version) ? rebootAboveS20DllFile : rebootBeforeS20DllFile, false); case InjectableDll.console: final ue4ConsoleFile = File(unrealEngineConsoleDll.text); return (ue4ConsoleFile, canonicalize(ue4ConsoleFile.path) != defaultPath); @@ -163,6 +174,14 @@ class DllController extends GetxController { } } + bool _isS20(String version) { + try { + return Version.parse(version).major >= 20; + } on FormatException catch(_) { + return version.trim().startsWith("20."); + } + } + TextEditingController getDllEditingController(InjectableDll dll) { switch(dll) { case InjectableDll.console: @@ -177,16 +196,16 @@ class DllController extends GetxController { } String getDefaultDllPath(InjectableDll dll) { - switch(dll) { - case InjectableDll.console: - return "${dllsDirectory.path}\\console.dll"; - case InjectableDll.auth: - return "${dllsDirectory.path}\\cobalt.dll"; - case InjectableDll.gameServer: - return "${dllsDirectory.path}\\reboot.dll"; - case InjectableDll.memoryLeak: - return "${dllsDirectory.path}\\memory.dll"; - } + switch(dll) { + case InjectableDll.console: + return "${dllsDirectory.path}\\console.dll"; + case InjectableDll.auth: + return "${dllsDirectory.path}\\cobalt.dll"; + case InjectableDll.gameServer: + return "${dllsDirectory.path}\\reboot.dll"; + case InjectableDll.memoryLeak: + return "${dllsDirectory.path}\\memory.dll"; + } } Future download(InjectableDll dll, String filePath, {bool silent = false, bool force = false}) async { @@ -198,77 +217,136 @@ class DllController extends GetxController { } if(!force && File(filePath).existsSync()) { - log("[DLL] File already exists"); + log("[DLL] $dll already exists"); + _listenToFileEvents(dll); return true; } + log("[DLL] Downloading $dll..."); final fileNameWithoutExtension = basenameWithoutExtension(filePath); if(!silent) { + log("[DLL] Showing dialog while downloading $dll..."); entry = showRebootInfoBar( translations.downloadingDll(fileNameWithoutExtension), loading: true, duration: null ); + }else { + log("[DLL] Not showing dialog while downloading $dll..."); } - await downloadDependency(dll, filePath); + final result = await downloadDependency(dll, filePath); + if(!result) { + entry?.close(); + showRebootInfoBar( + translations.downloadDllAntivirus(antiVirusName ?? defaultAntiVirusName, dll.name), + duration: infoBarLongDuration, + severity: InfoBarSeverity.error + ); + return false; + } + log("[DLL] Downloaded $dll"); entry?.close(); if(!silent) { + log("[DLL] Showing success dialog for $dll"); entry = await showRebootInfoBar( translations.downloadDllSuccess(fileNameWithoutExtension), severity: InfoBarSeverity.success, duration: infoBarShortDuration ); + }else { + log("[DLL] Not showing success dialog for $dll"); } + _listenToFileEvents(dll); return true; }catch(message) { - log("[DLL] Error: $message"); + log("[DLL] An error occurred while downloading $dll: $message"); entry?.close(); var error = message.toString(); - error = - error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error; + error = error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error; error = error.toLowerCase(); - final completer = Completer(); + final completer = Completer(); await showRebootInfoBar( translations.downloadDllError(error.toString(), dll.name), duration: infoBarLongDuration, severity: InfoBarSeverity.error, - onDismissed: () => completer.complete(null), + onDismissed: () => completer.complete(false), action: Button( onPressed: () async { - await download(dll, filePath, silent: silent, force: force); - completer.complete(null); + final result = await download(dll, filePath, silent: silent, force: force); + completer.complete(result); }, child: Text(translations.downloadDllRetry), ) ); - await completer.future; - return false; + return completer.future; } } - void guardFiles() { + Future downloadAndGuardDependencies() async { for(final injectable in InjectableDll.values) { final controller = getDllEditingController(injectable); final defaultPath = getDefaultDllPath(injectable); - if (path.equals(controller.text, defaultPath)) { - download(injectable, controller.text); - } - controller.addListener(() async { - try { - if (!path.equals(controller.text, defaultPath)) { - return; - } - final filePath = controller.text; - await for(final event in File(filePath).parent.watch(events: FileSystemEvent.delete | FileSystemEvent.move)) { - if (path.equals(event.path, filePath)) { - await download(injectable, filePath); - } - } - } catch(_) { - // Ignore - } - }); + if(path.equals(controller.text, defaultPath)) { + await download(injectable, controller.text); + } + } + } + + void _listenToFileEvents(InjectableDll injectable) { + final controller = getDllEditingController(injectable); + final defaultPath = getDefaultDllPath(injectable); + + void onFileEvent(FileSystemEvent event, String filePath) { + if (!path.equals(event.path, filePath)) { + return; + } + + if(path.equals(filePath, defaultPath)) { + Get.find() + .instance + .value + ?.kill(); + Get.find() + .instance + .value + ?.kill(); + showRebootInfoBar( + translations.downloadDllAntivirus(antiVirusName ?? defaultAntiVirusName, injectable.name), + duration: infoBarLongDuration, + severity: InfoBarSeverity.error + ); + } + + _updateInput(injectable); + } + + StreamSubscription subscribe(String filePath) => File(filePath) + .parent + .watch(events: FileSystemEvent.delete | FileSystemEvent.move) + .listen((event) => onFileEvent(event, filePath)); + + controller.addListener(() { + _subscriptions[injectable]?.cancel(); + _subscriptions[injectable] = subscribe(controller.text); + }); + _subscriptions[injectable] = subscribe(controller.text); + } + + void _updateInput(InjectableDll injectable) { + switch(injectable) { + case InjectableDll.console: + settingsConsoleDllInputKey.currentState?.validate(); + break; + case InjectableDll.auth: + settingsAuthDllInputKey.currentState?.validate(); + break; + case InjectableDll.gameServer: + settingsGameServerDllInputKey.currentState?.validate(); + break; + case InjectableDll.memoryLeak: + settingsMemoryDllInputKey.currentState?.validate(); + break; } } } diff --git a/gui/lib/src/controller/game_controller.dart b/gui/lib/src/controller/game_controller.dart index 2a9350f..8d85aab 100644 --- a/gui/lib/src/controller/game_controller.dart +++ b/gui/lib/src/controller/game_controller.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:math'; import 'package:fluent_ui/fluent_ui.dart'; import 'package:get/get.dart'; @@ -8,14 +9,14 @@ import 'package:reboot_common/common.dart'; import 'package:reboot_launcher/main.dart'; class GameController extends GetxController { - static const String storageName = "v2_game_storage"; + static const String storageName = "v3_game_storage"; late final GetStorage? _storage; late final TextEditingController username; late final TextEditingController password; late final TextEditingController customLaunchArgs; late final Rx> versions; - late final Rxn _selectedVersion; + late final Rxn selectedVersion; late final RxBool started; late final Rxn instance; @@ -28,8 +29,8 @@ class GameController extends GetxController { versions = Rx(decodedVersions); versions.listen((data) => _saveVersions()); final decodedSelectedVersionName = _storage?.read("version"); - final decodedSelectedVersion = decodedVersions.firstWhereOrNull((element) => element.content.toString() == decodedSelectedVersionName); - _selectedVersion = Rxn(decodedSelectedVersion); + selectedVersion = Rxn(decodedVersions.firstWhereOrNull((element) => element.name == decodedSelectedVersionName)); + selectedVersion.listen((version) => _storage?.write("version", version?.name)); username = TextEditingController( text: _storage?.read("username") ?? kDefaultPlayerName); username.addListener(() => _storage?.write("username", username.text)); @@ -46,26 +47,27 @@ class GameController extends GetxController { password.text = ""; customLaunchArgs.text = ""; versions.value = []; - _selectedVersion.value = null; + selectedVersion.value = null; instance.value = null; } FortniteVersion? getVersionByName(String name) { - return versions.value.firstWhereOrNull((element) => element.content.toString() == name); + name = name.trim(); + return versions.value.firstWhereOrNull((element) => element.name == name); } void addVersion(FortniteVersion version) { - var empty = versions.value.isEmpty; versions.update((val) => val?.add(version)); - if(empty){ - selectedVersion = version; - } + selectedVersion.value = version; } void removeVersion(FortniteVersion version) { - versions.update((val) => val?.remove(version)); - if (selectedVersion == version || hasNoVersions) { - selectedVersion = null; + final index = versions.value.indexOf(version); + versions.update((val) => val?.removeAt(index)); + if(hasNoVersions) { + selectedVersion.value = null; + }else { + selectedVersion.value = versions.value.elementAt(max(0, index - 1)); } } @@ -78,14 +80,5 @@ class GameController extends GetxController { bool get hasNoVersions => versions.value.isEmpty; - FortniteVersion? get selectedVersion => _selectedVersion(); - - set selectedVersion(FortniteVersion? version) { - _selectedVersion.value = version; - _storage?.write("version", version?.content.toString()); - } - - void updateVersion(FortniteVersion version, Function(FortniteVersion) function) { - versions.update((val) => function(version)); - } + void updateVersion(FortniteVersion version, Function(FortniteVersion) function) => versions.update((val) => function(version)); } diff --git a/gui/lib/src/controller/hosting_controller.dart b/gui/lib/src/controller/hosting_controller.dart index b377887..d293294 100644 --- a/gui/lib/src/controller/hosting_controller.dart +++ b/gui/lib/src/controller/hosting_controller.dart @@ -12,7 +12,7 @@ import 'package:sync/semaphore.dart'; import 'package:uuid/uuid.dart'; class HostingController extends GetxController { - static const String storageName = "v2_hosting_storage"; + static const String storageName = "v3_hosting_storage"; late final GetStorage? _storage; late final String uuid; @@ -26,7 +26,7 @@ class HostingController extends GetxController { late final FocusNode passwordFocusNode; late final RxBool showPassword; late final RxBool discoverable; - late final Rx type; + late final RxBool headless; late final RxBool autoRestart; late final RxBool started; late final RxBool published; @@ -54,8 +54,8 @@ class HostingController extends GetxController { passwordFocusNode = FocusNode(); discoverable = RxBool(_storage?.read("discoverable") ?? false); discoverable.listen((value) => _storage?.write("discoverable", value)); - type = Rx(GameServerType.values.elementAt(_storage?.read("type") ?? GameServerType.headless.index)); - type.listen((value) => _storage?.write("type", value.index)); + headless = RxBool(_storage?.read("headless") ?? true); + headless.listen((value) => _storage?.write("headless", value)); autoRestart = RxBool(_storage?.read("auto_restart") ?? true); autoRestart.listen((value) => _storage?.write("auto_restart", value)); started = RxBool(false); @@ -165,7 +165,7 @@ class HostingController extends GetxController { showPassword.value = false; discoverable.value = false; instance.value = null; - type.value = GameServerType.headless; + headless.value = true; autoRestart.value = true; customLaunchArgs.text = ""; } diff --git a/gui/lib/src/controller/settings_controller.dart b/gui/lib/src/controller/settings_controller.dart index 1d4ef98..884edda 100644 --- a/gui/lib/src/controller/settings_controller.dart +++ b/gui/lib/src/controller/settings_controller.dart @@ -13,7 +13,7 @@ import 'package:version/version.dart'; import 'package:yaml/yaml.dart'; class SettingsController extends GetxController { - static const String storageName = "v2_settings_storage"; + static const String storageName = "v3_settings_storage"; late final GetStorage? _storage; late final RxString language; diff --git a/gui/lib/src/messenger/dialog.dart b/gui/lib/src/messenger/dialog.dart index 2e93ff2..8b58735 100644 --- a/gui/lib/src/messenger/dialog.dart +++ b/gui/lib/src/messenger/dialog.dart @@ -126,7 +126,7 @@ class ProgressDialog extends AbstractDialog { header: InfoLabel( label: text, child: Container( - padding: const EdgeInsets.only(bottom: 16.0), + padding: const EdgeInsets.symmetric(vertical: 16.0), width: double.infinity, child: const ProgressBar() ), diff --git a/gui/lib/src/util/os.dart b/gui/lib/src/util/os.dart index 89c6777..f0b2a3c 100644 --- a/gui/lib/src/util/os.dart +++ b/gui/lib/src/util/os.dart @@ -78,417 +78,6 @@ class _ServiceProvider10 extends IUnknown { } } -class IVirtualDesktop extends IUnknown { - static const String _CLSID = "{3F07F4BE-B107-441A-AF0F-39D82529072C}"; - - IVirtualDesktop._internal(super.ptr); - - String getName() { - final result = calloc(); - final code = (ptr.ref.vtable + 5) - .cast< - Pointer< - NativeFunction)>>>() - .value - .asFunction< - int Function(Pointer, Pointer)>()(ptr.ref.lpVtbl, result); - if (code != 0) { - free(result); - throw WindowsException(code); - } - - return _convertFromHString(result.value); - } -} - -class IApplicationView extends IUnknown { - // static const String _CLSID = "{372E1D3B-38D3-42E4-A15B-8AB2B178F513}"; - - IApplicationView._internal(super.ptr); -} - -class _IObjectArray extends IUnknown { - _IObjectArray(super.ptr); - - int getCount() { - final result = calloc(); - final code = (ptr.ref.vtable + 3) - .cast< - Pointer< - NativeFunction)>>>() - .value - .asFunction< - int Function(Pointer, Pointer)>()(ptr.ref.lpVtbl, result); - if (code != 0) { - free(result); - throw WindowsException(code); - } - - return result.value; - } - - Pointer getAt(int index, String guid) { - final result = calloc(); - final code = (ptr.ref.vtable + 4) - .cast< - Pointer< - NativeFunction< - HRESULT Function(Pointer, Int32 index, Pointer, - Pointer)>>>() - .value - .asFunction< - int Function( - Pointer, int index, Pointer, Pointer)>()( - ptr.ref.lpVtbl, index, GUIDFromString(guid), result); - if (code != 0) { - free(result); - throw WindowsException(code); - } - - return result; - } -} - -typedef _IObjectMapper = T Function(Pointer); - -class _IObjectArrayList extends ListBase { - final _IObjectArray _array; - final String _guid; - final _IObjectMapper _mapper; - - _IObjectArrayList( - {required _IObjectArray array, - required String guid, - required _IObjectMapper mapper}) - : _array = array, - _guid = guid, - _mapper = mapper; - - @override - int get length => _array.getCount(); - - @override - set length(int newLength) { - throw UnsupportedError("Immutable list"); - } - - @override - T operator [](int index) => _mapper(_array.getAt(index, _guid)); - - @override - void operator []=(int index, T value) { - throw UnsupportedError("Immutable list"); - } -} - -class _IVirtualDesktopManagerInternal extends IUnknown { - static const String _CLSID = "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}"; - static const String _IID_WIN10 = "{F31574D6-B682-4CDC-BD56-1827860ABEC6}"; - static const String _IID_WIN_21H2 = "{B2F925B9-5A0F-4D2E-9F4D-2B1507593C10}"; - static const String _IID_WIN_23H2 = "{A3175F2D-239C-4BD2-8AA0-EEBA8B0B138E}"; - static const String _IID_WIN_23H2_3085 = "{53F5CA0B-158F-4124-900C-057158060B27}"; - - _IVirtualDesktopManagerInternal._internal(super.ptr); - - int getDesktopsCount() { - final result = calloc(); - final code = (ptr.ref.vtable + 3) - .cast< - Pointer< - NativeFunction)>>>() - .value - .asFunction< - int Function(Pointer, Pointer)>()(ptr.ref.lpVtbl, result); - if (code != 0) { - free(result); - throw WindowsException(code); - } - - return result.value; - } - - List getDesktops() { - final result = calloc(); - final code = (ptr.ref.vtable + 7) - .cast< - Pointer< - NativeFunction< - HRESULT Function(Pointer, Pointer)>>>() - .value - .asFunction)>()( - ptr.ref.lpVtbl, result); - if (code != 0) { - free(result); - throw WindowsException(code); - } - - final array = _IObjectArray(result); - return _IObjectArrayList( - array: array, - guid: IVirtualDesktop._CLSID, - mapper: (comObject) => IVirtualDesktop._internal(comObject)); - } - - void moveWindowToDesktop(IApplicationView view, IVirtualDesktop desktop) { - final code = (ptr.ref.vtable + 4) - .cast< - Pointer< - NativeFunction< - Int32 Function(Pointer, COMObject, COMObject)>>>() - .value - .asFunction()( - ptr.ref.lpVtbl, view.ptr.ref, desktop.ptr.ref); - if (code != 0) { - throw WindowsException(code, message: "Cannot move window"); - } - } - - IVirtualDesktop createDesktop() { - final result = calloc(); - final code = (ptr.ref.vtable + 10) - .cast< - Pointer< - NativeFunction< - HRESULT Function(Pointer, Pointer)>>>() - .value - .asFunction)>()( - ptr.ref.lpVtbl, result); - if (code != 0) { - free(result); - throw WindowsException(code); - } - - return IVirtualDesktop._internal(result); - } - - void removeDesktop(IVirtualDesktop desktop, IVirtualDesktop fallback) { - final code = (ptr.ref.vtable + 12) - .cast< - Pointer< - NativeFunction< - HRESULT Function(Pointer, COMObject, COMObject)>>>() - .value - .asFunction()( - ptr.ref.lpVtbl, desktop.ptr.ref, fallback.ptr.ref); - if (code != 0) { - throw WindowsException(code); - } - } - - void setDesktopName(IVirtualDesktop desktop, String newName) { - final code = - (ptr.ref.vtable + 15) - .cast< - Pointer< - NativeFunction< - HRESULT Function(Pointer, COMObject, Int8)>>>() - .value - .asFunction()( - ptr.ref.lpVtbl, desktop.ptr.ref, _convertToHString(newName)); - if (code != 0) { - throw WindowsException(code); - } - } -} - -class _IApplicationViewCollection extends IUnknown { - static const String _CLSID = "{1841C6D7-4F9D-42C0-AF41-8747538F10E5}"; - static const String _IID = "{1841C6D7-4F9D-42C0-AF41-8747538F10E5}"; - - _IApplicationViewCollection._internal(super.ptr); - - IApplicationView? getViewForHWnd(int HWnd) { - final result = calloc(); - final code = - (ptr.ref.vtable + 6) - .cast< - Pointer< - NativeFunction< - HRESULT Function( - Pointer, IntPtr, Pointer)>>>() - .value - .asFunction)>()( - ptr.ref.lpVtbl, HWnd, result); - if (code != 0) { - free(result); - return null; - } - - return IApplicationView._internal(result); - } -} - -final class Win32Process extends Struct { - @Uint32() - external int pid; - - @Uint32() - external int HWndLength; - - external Pointer HWnd; - - external Pointer excluded; -} - -int _filter(int HWnd, int lParam) { - final structure = Pointer.fromAddress(lParam).cast(); - if(structure.ref.excluded != nullptr) { - final excludedWindowName = structure.ref.excluded.toDartString(); - final windowNameLength = GetWindowTextLength(HWnd); - if(windowNameLength > 0) { - final windowNamePointer = calloc(windowNameLength + 1).cast(); - GetWindowText(HWnd, windowNamePointer, windowNameLength); - final windowName = windowNamePointer.toDartString(length: windowNameLength); - if(windowName.toLowerCase().contains(excludedWindowName.toLowerCase())) { - return TRUE; - } - } - } - - final pidPointer = calloc(); - GetWindowThreadProcessId(HWnd, pidPointer); - final pid = pidPointer.value; - if (pid == structure.ref.pid) { - final length = structure.ref.HWndLength; - final newLength = length + 1; - final ptr = malloc.allocate(sizeOf() * newLength); - final list = structure.ref.HWnd.asTypedList(length); - for (var i = 0; i < list.length; i++) { - (ptr + i).value = list[i]; - } - ptr[list.length] = HWnd; - structure.ref.HWndLength = newLength; - free(structure.ref.HWnd); - structure.ref.HWnd = ptr; - } - - free(pidPointer); - return TRUE; -} - -List _getHWnds(int pid, String? excludedWindowName) { - final result = calloc(); - result.ref.pid = pid; - if(excludedWindowName != null) { - result.ref.excluded = excludedWindowName.toNativeUtf16(); - } - - EnumWindows(Pointer.fromFunction(_filter, TRUE), result.address); - final length = result.ref.HWndLength; - final HWndsPointer = result.ref.HWnd; - if(HWndsPointer == nullptr) { - calloc.free(result); - return []; - } - - final HWnds = HWndsPointer.asTypedList(length) - .toList(growable: false); - calloc.free(result); - return HWnds; -} - -class VirtualDesktopManager { - static VirtualDesktopManager? _instance; - - final _IVirtualDesktopManagerInternal windowManager; - final _IApplicationViewCollection applicationViewCollection; - - VirtualDesktopManager._internal(this.windowManager, this.applicationViewCollection); - - factory VirtualDesktopManager.getInstance() { - if (_instance != null) { - return _instance!; - } - - final hr = CoInitializeEx( - nullptr, COINIT.COINIT_APARTMENTTHREADED | COINIT.COINIT_DISABLE_OLE1DDE); - if (FAILED(hr)) { - throw WindowsException(hr); - } - - final shell = _ServiceProvider10.createInstance(); - final windowManager = _createWindowManager(shell); - final applicationViewCollection = _IApplicationViewCollection._internal( - shell.queryService(_IApplicationViewCollection._CLSID, - _IApplicationViewCollection._IID)); - return _instance = - VirtualDesktopManager._internal(windowManager, applicationViewCollection); - } - - static _IVirtualDesktopManagerInternal _createWindowManager(_ServiceProvider10 shell) { - final build = windowsBuild; - if(build == null || build < 19044) { - return _IVirtualDesktopManagerInternal._internal( - shell.queryService(_IVirtualDesktopManagerInternal._CLSID, - _IVirtualDesktopManagerInternal._IID_WIN10)); - }else if(build >= 19044 && build < 22631) { - return _IVirtualDesktopManagerInternal._internal( - shell.queryService(_IVirtualDesktopManagerInternal._CLSID, - _IVirtualDesktopManagerInternal._IID_WIN_21H2)); - }else if(build >= 22631 && build < 22631) { - return _IVirtualDesktopManagerInternal._internal( - shell.queryService(_IVirtualDesktopManagerInternal._CLSID, - _IVirtualDesktopManagerInternal._IID_WIN_23H2)); - }else { - return _IVirtualDesktopManagerInternal._internal( - shell.queryService(_IVirtualDesktopManagerInternal._CLSID, - _IVirtualDesktopManagerInternal._IID_WIN_23H2_3085)); - } - } - - int getDesktopsCount() => windowManager.getDesktopsCount(); - - List getDesktops() => windowManager.getDesktops(); - - Future moveWindowToDesktop(int pid, IVirtualDesktop desktop, {Duration pollTime = const Duration(seconds: 1), int remainingPolls = 10, String? excludedWindowName}) async { - for(final hWND in _getHWnds(pid, excludedWindowName)) { - final window = applicationViewCollection.getViewForHWnd(hWND); - if(window != null) { - windowManager.moveWindowToDesktop(window, desktop); - return true; - } - } - - if(remainingPolls <= 0) { - return false; - } - - await Future.delayed(pollTime); - return await moveWindowToDesktop( - pid, - desktop, - pollTime: pollTime, - remainingPolls: remainingPolls - 1 - ); - } - - IVirtualDesktop createDesktop() => windowManager.createDesktop(); - - void removeDesktop(IVirtualDesktop desktop, [IVirtualDesktop? fallback]) { - fallback ??= getDesktops().first; - return windowManager.removeDesktop(desktop, fallback); - } - - void setDesktopName(IVirtualDesktop desktop, String newName) => - windowManager.setDesktopName(desktop, newName); -} - -String _convertFromHString(int hstring) => - WindowsGetStringRawBuffer(hstring, nullptr).toDartString(); - -int _convertToHString(String string) { - final hString = calloc(); - final stringPtr = string.toNativeUtf16(); - try { - final hr = WindowsCreateString(stringPtr, string.length, hString); - if (FAILED(hr)) throw WindowsException(hr); - return hString.value; - } finally { - free(stringPtr); - free(hString); - } -} - extension WindowManagerExtension on WindowManager { Future maximizeOrRestore() async => await windowManager.isMaximized() ? windowManager.restore() : windowManager.maximize(); } diff --git a/gui/lib/src/util/translations.dart b/gui/lib/src/util/translations.dart index f301284..4a7638b 100644 --- a/gui/lib/src/util/translations.dart +++ b/gui/lib/src/util/translations.dart @@ -19,17 +19,4 @@ void loadTranslations(BuildContext context) { _init = true; } -String get currentLocale => Intl.getCurrentLocale().split("_")[0]; - -extension GameServerTypeExtension on GameServerType { - String get translatedName { - switch(this) { - case GameServerType.headless: - return translations.gameServerTypeHeadless; - case GameServerType.virtualWindow: - return translations.gameServerTypeVirtualWindow; - case GameServerType.window: - return translations.gameServerTypeWindow; - } - } -} +String get currentLocale => Intl.getCurrentLocale().split("_")[0]; \ No newline at end of file diff --git a/gui/lib/src/widget/file/file_selector.dart b/gui/lib/src/widget/file/file_selector.dart index 4c08b32..467c32f 100644 --- a/gui/lib/src/widget/file/file_selector.dart +++ b/gui/lib/src/widget/file/file_selector.dart @@ -1,28 +1,35 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter/foundation.dart'; +import 'package:reboot_launcher/main.dart'; import 'package:reboot_launcher/src/util/os.dart'; +typedef FileSelectorValidator = String? Function(String?); + class FileSelector extends StatefulWidget { final String placeholder; final String windowTitle; final bool allowNavigator; final TextEditingController controller; - final String? Function(String?) validator; + final FileSelectorValidator? validator; final AutovalidateMode? validatorMode; + final Key? validatorKey; final String? extension; final String? label; final bool folder; + final void Function(String)? onSelected; const FileSelector( {required this.placeholder, required this.windowTitle, required this.controller, - required this.validator, required this.folder, required this.allowNavigator, + this.validator, + this.validatorKey, this.label, this.extension, this.validatorMode, + this.onSelected, Key? key}) : assert(folder || extension != null, "Missing extension for file selector"), super(key: key); @@ -47,6 +54,7 @@ class _FileSelectorState extends State { placeholder: widget.placeholder, validator: widget.validator, autovalidateMode: widget.validatorMode ?? AutovalidateMode.onUserInteraction, + key: widget.validatorKey, suffix: !widget.allowNavigator ? null : Button( onPressed: _onPressed, child: const Icon(FluentIcons.open_folder_horizontal) @@ -72,6 +80,10 @@ class _FileSelectorState extends State { } void _updateText(String? value) { + if(value != null) { + widget.onSelected?.call(value); + } + var text = value ?? widget.controller.text; widget.controller.text = value ?? widget.controller.text; widget.controller.selection = TextSelection.collapsed(offset: text.length); diff --git a/gui/lib/src/widget/file/file_setting_tile.dart b/gui/lib/src/widget/file/file_setting_tile.dart index 5a36757..86a3651 100644 --- a/gui/lib/src/widget/file/file_setting_tile.dart +++ b/gui/lib/src/widget/file/file_setting_tile.dart @@ -13,10 +13,14 @@ import 'package:reboot_launcher/src/widget/fluent/setting_tile.dart'; const double _kButtonDimensions = 30; const double _kButtonSpacing = 8; -// FIXME: If the user clicks on the reset button, the text field checker won't be called -SettingTile createFileSetting({required String title, required String description, required TextEditingController controller, required void Function() onReset}) { - final obx = RxString(controller.text); - controller.addListener(() => obx.value = controller.text); +SettingTile createFileSetting({ + required GlobalKey key, + required String title, + required String description, + required TextEditingController controller, + required void Function() onReset +}) { + final obx = RxnString(); final selecting = RxBool(false); return SettingTile( icon: Icon( @@ -32,17 +36,23 @@ SettingTile createFileSetting({required String title, required String descriptio placeholder: translations.selectPathPlaceholder, windowTitle: translations.selectPathWindowTitle, controller: controller, - validator: _checkDll, + validator: (text) { + final result = _checkDll(text); + print("Called validator: $result"); + obx.value = result; + return result; + }, extension: "dll", folder: false, validatorMode: AutovalidateMode.always, allowNavigator: false, + validatorKey: key ), ), const SizedBox(width: _kButtonSpacing), Obx(() => Padding( padding: EdgeInsets.only( - bottom: _checkDll(obx.value) == null ? 0.0 : 20.0 + bottom: obx.value == null ? 0.0 : 20.0 ), child: Tooltip( message: translations.selectFile, @@ -63,7 +73,7 @@ SettingTile createFileSetting({required String title, required String descriptio const SizedBox(width: _kButtonSpacing), Obx(() => Padding( padding: EdgeInsets.only( - bottom: _checkDll(obx.value) == null ? 0.0 : 20.0 + bottom: obx.value == null ? 0.0 : 20.0 ), child: Tooltip( message: translations.reset, @@ -109,7 +119,9 @@ String? _checkDll(String? text) { } final file = File(text); - if (!file.existsSync()) { + try { + file.readAsBytesSync(); + }catch(_) { return translations.dllDoesNotExist; } diff --git a/gui/lib/src/widget/game/game_start_button.dart b/gui/lib/src/widget/game/game_start_button.dart index e3ca230..a7a8919 100644 --- a/gui/lib/src/widget/game/game_start_button.dart +++ b/gui/lib/src/widget/game/game_start_button.dart @@ -16,7 +16,6 @@ import 'package:reboot_launcher/src/messenger/dialog.dart'; import 'package:reboot_launcher/src/messenger/info_bar.dart'; import 'package:reboot_launcher/src/page/pages.dart'; import 'package:reboot_launcher/src/util/matchmaker.dart'; -import 'package:reboot_launcher/src/util/os.dart'; import 'package:reboot_launcher/src/util/translations.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -45,7 +44,6 @@ class _LaunchButtonState extends State { InfoBarEntry? _gameServerInfoBar; CancelableOperation? _operation; Completer? _pingOperation; - IVirtualDesktop? _virtualDesktop; @override Widget build(BuildContext context) => Align( @@ -73,17 +71,19 @@ class _LaunchButtonState extends State { if (host ? _hostingController.started() : _gameController.started()) { log("[${host ? 'HOST' : 'GAME'}] User asked to close the current instance"); _onStop( - reason: _StopReason.normal + reason: _StopReason.normal, + host: host ); return; } - final version = _gameController.selectedVersion; + final version = _gameController.selectedVersion.value; log("[${host ? 'HOST' : 'GAME'}] Version data: $version"); if(version == null){ log("[${host ? 'HOST' : 'GAME'}] No version selected"); _onStop( - reason: _StopReason.missingVersionError + reason: _StopReason.missingVersionError, + host: host ); return; } @@ -93,37 +93,28 @@ class _LaunchButtonState extends State { log("[${host ? 'HOST' : 'GAME'}] Set started"); log("[${host ? 'HOST' : 'GAME'}] Checking dlls: ${InjectableDll.values}"); for (final injectable in InjectableDll.values) { - if(await _getDllFileOrStop(version.content, injectable, host) == null) { + if(await _getDllFileOrStop(version.gameVersion, injectable, host) == null) { return; } } try { - final executable = await version.shippingExecutable; - if(executable == null){ - log("[${host ? 'HOST' : 'GAME'}] No executable found"); - _onStop( - reason: _StopReason.missingExecutableError, - error: version.location.path - ); - return; - } - log("[${host ? 'HOST' : 'GAME'}] Checking backend(port: ${_backendController.type.value.name}, type: ${_backendController.type.value.name})..."); final backendResult = _backendController.started() || await _backendController.toggle(); if(!backendResult){ log("[${host ? 'HOST' : 'GAME'}] Cannot start backend"); _onStop( - reason: _StopReason.backendError + reason: _StopReason.backendError, + host: host ); return; } log("[${host ? 'HOST' : 'GAME'}] Backend works"); - final serverType = _hostingController.type.value; - log("[${host ? 'HOST' : 'GAME'}] Implicit game server metadata: headless($serverType)"); - final linkedHostingInstance = await _startMatchMakingServer(version, host, serverType, false); + final headless = _hostingController.headless.value; + log("[${host ? 'HOST' : 'GAME'}] Implicit game server metadata: headless($headless)"); + final linkedHostingInstance = await _startMatchMakingServer(version, host, headless, false); log("[${host ? 'HOST' : 'GAME'}] Implicit game server result: $linkedHostingInstance"); - final result = await _startGameProcesses(version, host, serverType, linkedHostingInstance); + final result = await _startGameProcesses(version, host, headless, linkedHostingInstance); final started = host ? _hostingController.started() : _gameController.started(); if(!started) { result?.kill(); @@ -131,7 +122,7 @@ class _LaunchButtonState extends State { } if(!host) { - _showLaunchingGameClientWidget(version, serverType, linkedHostingInstance != null); + _showLaunchingGameClientWidget(version, headless, linkedHostingInstance != null); }else { _showLaunchingGameServerWidget(); } @@ -139,18 +130,20 @@ class _LaunchButtonState extends State { _onStop( reason: _StopReason.corruptedVersionError, error: exception.toString(), - stackTrace: stackTrace + stackTrace: stackTrace, + host: host ); } catch (exception, stackTrace) { _onStop( reason: _StopReason.unknownError, error: exception.toString(), - stackTrace: stackTrace + stackTrace: stackTrace, + host: host ); } } - Future _startMatchMakingServer(FortniteVersion version, bool host, GameServerType hostType, bool forceLinkedHosting) async { + Future _startMatchMakingServer(FortniteVersion version, bool host, bool headless, bool forceLinkedHosting) async { log("[${host ? 'HOST' : 'GAME'}] Checking if a server needs to be started automatically..."); if(host){ log("[${host ? 'HOST' : 'GAME'}] The user clicked on Start hosting, so it's not necessary"); @@ -174,7 +167,7 @@ class _LaunchButtonState extends State { } log("[${host ? 'HOST' : 'GAME'}] Starting implicit game server..."); - final instance = await _startGameProcesses(version, true, hostType, null); + final instance = await _startGameProcesses(version, true, headless, null); log("[${host ? 'HOST' : 'GAME'}] Started implicit game server..."); _setStarted(true, true); log("[${host ? 'HOST' : 'GAME'}] Set implicit game server as started"); @@ -184,7 +177,7 @@ class _LaunchButtonState extends State { Future _askForAutomaticGameServer(bool host) async { if (host ? !_hostingController.started() : !_gameController.started()) { log("[${host ? 'HOST' : 'GAME'}] User asked to close the current instance"); - _onStop(reason: _StopReason.normal); + _onStop(reason: _StopReason.normal, host: host); return false; } @@ -208,19 +201,10 @@ class _LaunchButtonState extends State { return result; } - Future _startGameProcesses(FortniteVersion version, bool host, GameServerType hostType, GameInstance? linkedHosting) async { - log("[${host ? 'HOST' : 'GAME'}] Starting game process..."); - log("[${host ? 'HOST' : 'GAME'}] Starting paused launcher..."); - final launcherProcess = await _createPausedProcess(version, version.launcherExecutable); - - log("[${host ? 'HOST' : 'GAME'}] Started paused launcher: $launcherProcess"); - log("[${host ? 'HOST' : 'GAME'}] Starting paused eac..."); - final eacProcess = await _createPausedProcess(version, version.eacExecutable); - - log("[${host ? 'HOST' : 'GAME'}] Started paused eac: $eacProcess"); - final executable = await version.shippingExecutable; - log("[${host ? 'HOST' : 'GAME'}] Using game path: ${executable?.path}"); - final gameProcess = await _createGameProcess(version, executable!, host, hostType, linkedHosting); + Future _startGameProcesses(FortniteVersion version, bool host, bool headless, GameInstance? linkedHosting) async { + final launcherProcess = await _createPausedProcess(version, host, kLauncherExe); + final eacProcess = await _createPausedProcess(version, host, kEacExe); + final gameProcess = await _createGameProcess(version, host, headless, linkedHosting); if(gameProcess == null) { log("[${host ? 'HOST' : 'GAME'}] No game process was created"); return null; @@ -228,11 +212,11 @@ class _LaunchButtonState extends State { log("[${host ? 'HOST' : 'GAME'}] Created game process: ${gameProcess}"); final instance = GameInstance( - version: version.content, + version: version.gameVersion, gamePid: gameProcess, launcherPid: launcherProcess, eacPid: eacProcess, - serverType: host ? hostType : null, + headless: host && headless, child: linkedHosting ); if(host){ @@ -246,22 +230,44 @@ class _LaunchButtonState extends State { return instance; } - Future _createGameProcess(FortniteVersion version, File executable, bool host, GameServerType hostType, GameInstance? linkedHosting) async { + Future _createGameProcess(FortniteVersion version, bool host, bool headless, GameInstance? linkedHosting) async { + log("[${host ? 'HOST' : 'GAME'}] Starting game process..."); + final shippingExecutables = await findFiles(version.location, kShippingExe); + if(shippingExecutables.isEmpty){ + log("[${host ? 'HOST' : 'GAME'}] No game executable found"); + _onStop( + reason: _StopReason.missingExecutableError, + error: kShippingExe, + host: host + ); + return null; + } + + if(shippingExecutables.length != 1) { + log("[${host ? 'HOST' : 'GAME'}] Too many game executables found"); + _onStop( + reason: _StopReason.multipleExecutablesError, + error: kShippingExe, + host: host + ); + return null; + } + log("[${host ? 'HOST' : 'GAME'}] Generating instance args..."); final gameArgs = createRebootArgs( host ? _hostingController.accountUsername.text : _gameController.username.text, host ? _hostingController.accountPassword.text : _gameController.password.text, host, - hostType, + headless, false, host ? _hostingController.customLaunchArgs.text : _gameController.customLaunchArgs.text ); log("[${host ? 'HOST' : 'GAME'}] Generated game args: ${gameArgs.join(" ")}"); final gameProcess = await startProcess( - executable: executable, + executable: shippingExecutables.first, args: gameArgs, useTempBatch: false, - name: "${version.content}-${host ? 'HOST' : 'GAME'}", + name: "${version.gameVersion}-${host ? 'HOST' : 'GAME'}", environment: { "OPENSSL_ia32cap": "~0x20000000" } @@ -272,26 +278,26 @@ class _LaunchButtonState extends State { handleGameOutput( line: line, host: host, - onShutdown: () => _onStop(reason: _StopReason.normal), - onTokenError: () => _onStop(reason: _StopReason.tokenError), + onShutdown: () => _onStop(reason: _StopReason.normal, host: host), + onTokenError: () => _onStop(reason: _StopReason.tokenError, host: host), onBuildCorrupted: () { if(instance == null) { return; }else if(!instance.launched) { - _onStop(reason: _StopReason.corruptedVersionError); + _onStop(reason: _StopReason.corruptedVersionError, host: host); }else { - _onStop(reason: _StopReason.crash); + _onStop(reason: _StopReason.crash, host: host); } }, onLoggedIn: () =>_onLoggedIn(host), - onMatchEnd: () => _onMatchEnd(version), - onDisplayAttached: () => _onDisplayAttached(host, hostType, version) + onMatchEnd: () => _onMatchEnd(version) ); } gameProcess.stdOutput.listen((line) => onGameOutput(line, false)); gameProcess.stdError.listen((line) => onGameOutput(line, true)); gameProcess.exitCode.then((_) async { final instance = host ? _hostingController.instance.value : _gameController.instance.value; + instance?.killed = true; log("[${host ? 'HOST' : 'GAME'}] Called exit code(launched: ${instance?.launched}): stop signal"); _onStop( reason: _StopReason.exitCode, @@ -301,60 +307,37 @@ class _LaunchButtonState extends State { return gameProcess.pid; } - Future _createPausedProcess(FortniteVersion version, File? file) async { - if (file == null) { + Future _createPausedProcess(FortniteVersion version, bool host, String executableName) async { + log("[${host ? 'HOST' : 'GAME'}] Starting $executableName..."); + final executables = await findFiles(version.location, executableName); + if(executables.isEmpty){ + return null; + } + + if(executables.length != 1) { + log("[${host ? 'HOST' : 'GAME'}] Too many $executableName found: $executables"); + _onStop( + reason: _StopReason.multipleExecutablesError, + error: executableName, + host: host + ); return null; } final process = await startProcess( - executable: file, + executable: executables.first, useTempBatch: false, - name: "${version.content}-${basenameWithoutExtension(file.path)}", + name: "${version.gameVersion}-${basenameWithoutExtension(executables.first.path)}", environment: { "OPENSSL_ia32cap": "~0x20000000" } ); + log("[${host ? 'HOST' : 'GAME'}] Started paused $executableName: $process"); final pid = process.pid; suspend(pid); return pid; } - Future _onDisplayAttached(bool host, GameServerType type, FortniteVersion version) async { - if(host && type == GameServerType.virtualWindow) { - final hostingInstance = _hostingController.instance.value; - if(hostingInstance != null && !hostingInstance.movedToVirtualDesktop) { - hostingInstance.movedToVirtualDesktop = true; - try { - final windowManager = VirtualDesktopManager.getInstance(); - _virtualDesktop = windowManager.createDesktop(); - windowManager.setDesktopName(_virtualDesktop!, "${version.content} Server (Reboot Launcher)"); - var success = false; - try { - success = await windowManager.moveWindowToDesktop( - hostingInstance.gamePid, - _virtualDesktop!, - excludedWindowName: "Reboot" - ); - }catch(error) { - log("[VIRTUAL_DESKTOP] $error"); - success = false; - } - if(!success) { - try { - windowManager.removeDesktop(_virtualDesktop!); - }catch(error) { - log("[VIRTUAL_DESKTOP] $error"); - }finally { - _virtualDesktop = null; - } - } - }catch(error) { - log("[VIRTUAL_DESKTOP] $error"); - } - } - } - } - void _onMatchEnd(FortniteVersion version) { if(_hostingController.autoRestart.value) { final notification = LocalNotification( @@ -397,7 +380,9 @@ class _LaunchButtonState extends State { if(instance != null && !instance.launched) { instance.launched = true; instance.tokenError = false; - await _injectOrShowError(InjectableDll.memoryLeak, host); + if(_isChapterOne(instance.version)) { + await _injectOrShowError(InjectableDll.memoryLeak, host); + } if(!host){ await _injectOrShowError(InjectableDll.console, host); _onGameClientInjected(); @@ -412,6 +397,14 @@ class _LaunchButtonState extends State { } } + bool _isChapterOne(String version) { + try { + return Version.parse(version).major < 10; + } on FormatException catch(_) { + return true; + } + } + void _onGameClientInjected() { _gameClientInfoBar?.close(); showRebootInfoBar( @@ -515,21 +508,20 @@ class _LaunchButtonState extends State { } } - Future _onStop({required _StopReason reason, bool? host, String? error, StackTrace? stackTrace}) async { - if(host == null) { + Future _onStop({required _StopReason reason, required bool host, String? error, StackTrace? stackTrace}) async { + if(host) { try { _pingOperation?.complete(false); - }catch(_) { + } catch (_) { // Ignore: might be running, don't bother checking } finally { _pingOperation = null; } - await _operation?.cancel(); - _operation = null; - _backendController.stop(interactive: false); } - host = host ?? widget.host; + await _operation?.cancel(); + _operation = null; + final instance = host ? _hostingController.instance.value : _gameController.instance.value; if(host){ @@ -538,15 +530,6 @@ class _LaunchButtonState extends State { _gameController.instance.value = null; } - if(_virtualDesktop != null) { - try { - final instance = VirtualDesktopManager.getInstance(); - instance.removeDesktop(_virtualDesktop!); - }catch(error) { - log("[VIRTUAL_DESKTOP] Cannot close virtual desktop: $error"); - } - } - log("[${host ? 'HOST' : 'GAME'}] Called stop with reason $reason, error data $error $stackTrace"); log("[${host ? 'HOST' : 'GAME'}] Caller: ${StackTrace.current}"); if(host) { @@ -562,7 +545,7 @@ class _LaunchButtonState extends State { if(child != null) { await _onStop( reason: reason, - host: child.serverType != null + host: host ); } @@ -594,10 +577,18 @@ class _LaunchButtonState extends State { duration: infoBarLongDuration, ); break; + case _StopReason.multipleExecutablesError: + showRebootInfoBar( + translations.multipleExecutablesError(error ?? translations.unknown), + severity: InfoBarSeverity.error, + duration: infoBarLongDuration, + ); + break; case _StopReason.exitCode: if(instance != null && !instance.launched) { + final injectedDlls = instance.injectedDlls; showRebootInfoBar( - translations.corruptedVersionError, + translations.corruptedVersionError(injectedDlls.isEmpty ? translations.none : injectedDlls.map((element) => element.name).join(", ")), severity: InfoBarSeverity.error, duration: infoBarLongDuration, ); @@ -630,8 +621,9 @@ class _LaunchButtonState extends State { break; case _StopReason.tokenError: _backendController.stop(interactive: false); + final injectedDlls = instance?.injectedDlls; showRebootInfoBar( - translations.tokenError(instance == null ? translations.none : instance.injectedDlls.map((element) => element.name).join(", ")), + translations.tokenError(injectedDlls == null || injectedDlls.isEmpty ? translations.none : injectedDlls.map((element) => element.name).join(", ")), severity: InfoBarSeverity.error, duration: infoBarLongDuration, action: Button( @@ -669,17 +661,13 @@ class _LaunchButtonState extends State { log("[${hosting ? 'HOST' : 'GAME'}] Injecting ${injectable.name} into process with pid $gameProcess"); final dllPath = await _getDllFileOrStop(instance.version, injectable, hosting); log("[${hosting ? 'HOST' : 'GAME'}] File to inject for ${injectable.name} at path $dllPath"); - if(dllPath == null) { + if (dllPath == null) { log("[${hosting ? 'HOST' : 'GAME'}] The file doesn't exist"); - _onStop( - reason: _StopReason.missingCustomDllError, - error: injectable.name, - host: hosting - ); return; } - log("[${hosting ? 'HOST' : 'GAME'}] Trying to inject ${injectable.name}..."); + log("[${hosting ? 'HOST' : 'GAME'}] Trying to inject ${injectable + .name}..."); await injectDll(gameProcess, dllPath); instance.injectedDlls.add(injectable); log("[${hosting ? 'HOST' : 'GAME'}] Injected ${injectable.name}"); @@ -694,13 +682,16 @@ class _LaunchButtonState extends State { } } - Future _getDllFileOrStop(Version version, InjectableDll injectable, bool host, [bool isRetry = false]) async { + Future _getDllFileOrStop(String version, InjectableDll injectable, bool host) async { log("[${host ? 'HOST' : 'GAME'}] Checking dll ${injectable}..."); final (file, customDll) = _dllController.getInjectableData(version, injectable); log("[${host ? 'HOST' : 'GAME'}] Path: ${file.path}, custom: $customDll"); - if(await file.exists()) { + try { + await file.readAsBytes(); log("[${host ? 'HOST' : 'GAME'}] Path exists"); return file; + }catch(_) { + } log("[${host ? 'HOST' : 'GAME'}] Path doesn't exist"); @@ -709,14 +700,20 @@ class _LaunchButtonState extends State { _onStop( reason: _StopReason.missingCustomDllError, error: injectable.name, + host: host ); return null; } log("[${host ? 'HOST' : 'GAME'}] Path does not exist, downloading critical dll again..."); - await _dllController.download(injectable, file.path, force: true); - log("[${host ? 'HOST' : 'GAME'}] Downloaded dll again, retrying check..."); - return _getDllFileOrStop(version, injectable, host, true); + final result = await _dllController.download(injectable, file.path, force: true); + if(result) { + log("[${host ? 'HOST' : 'GAME'}] Downloaded critical dll"); + return file; + } + + _onStop(reason: _StopReason.normal, host: host); + return null; } InfoBarEntry _showLaunchingGameServerWidget() => _gameServerInfoBar = showRebootInfoBar( @@ -725,7 +722,7 @@ class _LaunchButtonState extends State { duration: null ); - InfoBarEntry _showLaunchingGameClientWidget(FortniteVersion version, GameServerType hostType, bool linkedHosting) { + InfoBarEntry _showLaunchingGameClientWidget(FortniteVersion version, bool headless, bool linkedHosting) { return _gameClientInfoBar = showRebootInfoBar( linkedHosting ? translations.launchingGameClientAndServer : translations.launchingGameClientOnly, loading: true, @@ -743,9 +740,9 @@ class _LaunchButtonState extends State { onPressed: () async { _backendController.joinLocalhost(); if(!_hostingController.started.value) { - _gameController.instance.value?.child = await _startMatchMakingServer(version, false, hostType, true); + _gameController.instance.value?.child = await _startMatchMakingServer(version, false, headless, true); _gameClientInfoBar?.close(); - _showLaunchingGameClientWidget(version, hostType, true); + _showLaunchingGameClientWidget(version, headless, true); } }, child: Text(translations.startGameServer), @@ -760,6 +757,7 @@ enum _StopReason { normal, missingVersionError, missingExecutableError, + multipleExecutablesError, corruptedVersionError, missingCustomDllError, corruptedDllError, diff --git a/gui/lib/src/widget/message/dll.dart b/gui/lib/src/widget/message/dll.dart index 18a3b89..d65cadf 100644 --- a/gui/lib/src/widget/message/dll.dart +++ b/gui/lib/src/widget/message/dll.dart @@ -2,7 +2,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:reboot_launcher/src/messenger/dialog.dart'; import 'package:reboot_launcher/src/util/translations.dart'; -Future showDllDeletedDialog(Function() onConfirm) => showRebootDialog( +Future showDllDeletedDialog() => showRebootDialog( builder: (context) => InfoDialog( text: translations.dllDeletedTitle, buttons: [ @@ -15,7 +15,7 @@ Future showDllDeletedDialog(Function() onConfirm) => showRebootDialog( text: translations.dllDeletedPrimaryAction, onTap: () { Navigator.pop(context); - onConfirm(); + }, ), ], diff --git a/gui/lib/src/widget/page/home_page.dart b/gui/lib/src/widget/page/home_page.dart index 033a8af..54f8195 100644 --- a/gui/lib/src/widget/page/home_page.dart +++ b/gui/lib/src/widget/page/home_page.dart @@ -134,7 +134,7 @@ class _HomePageState extends State with WindowListener, AutomaticKeepA dllsDirectory.createSync(recursive: true); } - _dllController.guardFiles(); + _dllController.downloadAndGuardDependencies(); } @override diff --git a/gui/lib/src/widget/page/host_page.dart b/gui/lib/src/widget/page/host_page.dart index ca29fb9..2ac82b6 100644 --- a/gui/lib/src/widget/page/host_page.dart +++ b/gui/lib/src/widget/page/host_page.dart @@ -5,12 +5,10 @@ import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons; import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:reboot_common/common.dart'; import 'package:reboot_launcher/main.dart'; import 'package:reboot_launcher/src/controller/dll_controller.dart'; import 'package:reboot_launcher/src/controller/game_controller.dart'; import 'package:reboot_launcher/src/controller/hosting_controller.dart'; -import 'package:reboot_launcher/src/messenger/dialog.dart'; import 'package:reboot_launcher/src/messenger/info_bar.dart'; import 'package:reboot_launcher/src/messenger/overlay.dart'; import 'package:reboot_launcher/src/widget/message/data.dart'; @@ -19,7 +17,7 @@ import 'package:reboot_launcher/src/page/page_type.dart'; import 'package:reboot_launcher/src/util/translations.dart'; import 'package:reboot_launcher/src/widget/game/game_start_button.dart'; import 'package:reboot_launcher/src/widget/fluent/setting_tile.dart'; -import 'package:reboot_launcher/src/widget/version/version_selector_tile.dart'; +import 'package:reboot_launcher/src/widget/version/version_selector.dart'; final GlobalKey hostVersionOverlayTargetKey = GlobalKey(); final GlobalKey hostInfoOverlayTargetKey = GlobalKey(); @@ -78,7 +76,7 @@ class _HostingPageState extends RebootPageState { @override List get settings => [ _information, - buildVersionSelector( + VersionSelector.buildTile( key: hostVersionOverlayTargetKey ), _options, @@ -171,7 +169,7 @@ class _HostingPageState extends RebootPageState { contentWidth: null, content: Obx(() => Row( children: [ - Obx(() => Text( + Obx(() => Text( _hostingController.discoverable.value ? translations.on : translations.off )), const SizedBox( @@ -214,15 +212,21 @@ class _HostingPageState extends RebootPageState { ), title: Text(translations.gameServerTypeName), subtitle: Text(translations.gameServerTypeDescription), - content: Obx(() => DropDownButton( - onOpen: () => inDialog = true, - onClose: () => inDialog = false, - leading: Text(_hostingController.type.value.translatedName), - items: GameServerType.values.map((entry) => MenuFlyoutItem( - text: Text(entry.translatedName), - onPressed: () => _hostingController.type.value = entry - )).toList() - )), + contentWidth: null, + content: Row( + children: [ + Obx(() => Text( + _hostingController.headless.value ? translations.on : translations.off + )), + const SizedBox( + width: 16.0 + ), + Obx(() => ToggleSwitch( + checked: _hostingController.headless.value, + onChanged: (value) => _hostingController.headless.value = value + )), + ], + ), ), SettingTile( icon: Icon( diff --git a/gui/lib/src/widget/page/play_page.dart b/gui/lib/src/widget/page/play_page.dart index 6b779b0..1425898 100644 --- a/gui/lib/src/widget/page/play_page.dart +++ b/gui/lib/src/widget/page/play_page.dart @@ -10,7 +10,7 @@ import 'package:reboot_launcher/src/page/page_type.dart'; import 'package:reboot_launcher/src/util/translations.dart'; import 'package:reboot_launcher/src/widget/game/game_start_button.dart'; import 'package:reboot_launcher/src/widget/fluent/setting_tile.dart'; -import 'package:reboot_launcher/src/widget/version/version_selector_tile.dart'; +import 'package:reboot_launcher/src/widget/version/version_selector.dart'; final GlobalKey gameVersionOverlayTargetKey = GlobalKey(); @@ -46,7 +46,7 @@ class _PlayPageState extends RebootPageState { @override List get settings => [ - buildVersionSelector( + VersionSelector.buildTile( key: gameVersionOverlayTargetKey ), _options, diff --git a/gui/lib/src/widget/page/settings_page.dart b/gui/lib/src/widget/page/settings_page.dart index 29b5df3..f811e1a 100644 --- a/gui/lib/src/widget/page/settings_page.dart +++ b/gui/lib/src/widget/page/settings_page.dart @@ -17,6 +17,11 @@ import 'package:reboot_launcher/src/widget/file/file_setting_tile.dart'; import 'package:reboot_launcher/src/widget/fluent/setting_tile.dart'; import 'package:url_launcher/url_launcher.dart'; +final GlobalKey settingsConsoleDllInputKey = GlobalKey(); +final GlobalKey settingsAuthDllInputKey = GlobalKey(); +final GlobalKey settingsMemoryDllInputKey = GlobalKey(); +final GlobalKey settingsGameServerDllInputKey = GlobalKey(); + class SettingsPage extends RebootPage { const SettingsPage({Key? key}) : super(key: key); @@ -60,33 +65,39 @@ class _SettingsPageState extends RebootPageState { subtitle: Text(translations.settingsClientDescription), children: [ createFileSetting( + key: settingsConsoleDllInputKey, title: translations.settingsClientConsoleName, description: translations.settingsClientConsoleDescription, controller: _dllController.unrealEngineConsoleDll, - onReset: () { + onReset: () async { final path = _dllController.getDefaultDllPath(InjectableDll.console); _dllController.unrealEngineConsoleDll.text = path; - _dllController.download(InjectableDll.console, path, force: true); + await _dllController.download(InjectableDll.console, path, force: true); + settingsConsoleDllInputKey.currentState?.validate(); } ), createFileSetting( + key: settingsAuthDllInputKey, title: translations.settingsClientAuthName, description: translations.settingsClientAuthDescription, controller: _dllController.backendDll, - onReset: () { + onReset: () async { final path = _dllController.getDefaultDllPath(InjectableDll.auth); _dllController.backendDll.text = path; - _dllController.download(InjectableDll.auth, path, force: true); + await _dllController.download(InjectableDll.auth, path, force: true); + settingsAuthDllInputKey.currentState?.validate(); } ), createFileSetting( + key: settingsMemoryDllInputKey, title: translations.settingsClientMemoryName, description: translations.settingsClientMemoryDescription, controller: _dllController.memoryLeakDll, - onReset: () { + onReset: () async { final path = _dllController.getDefaultDllPath(InjectableDll.memoryLeak); _dllController.memoryLeakDll.text = path; - _dllController.download(InjectableDll.memoryLeak, path, force: true); + await _dllController.download(InjectableDll.memoryLeak, path, force: true); + settingsAuthDllInputKey.currentState?.validate(); } ), _internalFilesServerType, @@ -142,9 +153,9 @@ class _SettingsPageState extends RebootPageState { children: [ Expanded( child: TextFormBox( - placeholder: translations.settingsServerMirrorPlaceholder, - controller: _dllController.beforeS20Mirror, - onChanged: _scheduleMirrorDownload + placeholder: translations.settingsServerMirrorPlaceholder, + controller: _dllController.beforeS20Mirror, + onChanged: _scheduleMirrorDownload ), ), const SizedBox(width: 8.0), @@ -181,13 +192,15 @@ class _SettingsPageState extends RebootPageState { ); }else { return createFileSetting( + key: settingsGameServerDllInputKey, title: translations.settingsOldServerFileName, description: translations.settingsServerFileDescription, controller: _dllController.customGameServerDll, - onReset: () { + onReset: () async { final path = _dllController.getDefaultDllPath(InjectableDll.gameServer); _dllController.customGameServerDll.text = path; - _dllController.download(InjectableDll.gameServer, path); + await _dllController.download(InjectableDll.gameServer, path); + settingsGameServerDllInputKey.currentState?.validate(); } ); } @@ -224,9 +237,9 @@ class _SettingsPageState extends RebootPageState { children: [ Expanded( child: TextFormBox( - placeholder: translations.settingsServerMirrorPlaceholder, - controller: _dllController.aboveS20Mirror, - onChanged: _scheduleMirrorDownload + placeholder: translations.settingsServerMirrorPlaceholder, + controller: _dllController.aboveS20Mirror, + onChanged: _scheduleMirrorDownload ), ), const SizedBox(width: 8.0), @@ -337,7 +350,7 @@ class _SettingsPageState extends RebootPageState { )).toList() )) ); - + SettingTile get _installationDirectory => SettingTile( icon: Icon( FluentIcons.folder_24_regular diff --git a/gui/lib/src/widget/message/version.dart b/gui/lib/src/widget/version/download_version.dart similarity index 62% rename from gui/lib/src/widget/message/version.dart rename to gui/lib/src/widget/version/download_version.dart index 69262fb..c8df923 100644 --- a/gui/lib/src/widget/message/version.dart +++ b/gui/lib/src/widget/version/download_version.dart @@ -14,22 +14,22 @@ import 'package:reboot_launcher/src/util/types.dart'; import 'package:reboot_launcher/src/widget/file/file_selector.dart'; import 'package:windows_taskbar/windows_taskbar.dart'; -class AddVersionDialog extends StatefulWidget { +class DownloadVersionDialog extends StatefulWidget { final bool closable; - const AddVersionDialog({Key? key, required this.closable}) : super(key: key); + const DownloadVersionDialog({Key? key, required this.closable}) : super(key: key); @override - State createState() => _AddVersionDialogState(); + State createState() => _DownloadVersionDialogState(); } -class _AddVersionDialogState extends State { +class _DownloadVersionDialogState extends State { final GameController _gameController = Get.find(); + final TextEditingController _nameController = TextEditingController(); final TextEditingController _pathController = TextEditingController(); final GlobalKey _formKey = GlobalKey(); final GlobalKey _formFieldKey = GlobalKey(); final Rx<_DownloadStatus> _status = Rx(_DownloadStatus.form); - final Rx<_BuildSource> _source = Rx(_BuildSource.githubArchive); final Rxn _build = Rxn(); final RxnInt _timeLeft = RxnInt(); final Rxn _progress = Rxn(); @@ -46,6 +46,7 @@ class _AddVersionDialogState extends State { @override void dispose() { + _nameController.dispose(); _pathController.dispose(); _cancelDownload(); super.dispose(); @@ -63,10 +64,10 @@ class _AddVersionDialogState extends State { child: Obx(() { switch(_status.value){ case _DownloadStatus.form: - return Obx(() => FormDialog( - content: _buildFormBody(downloadableBuilds), + return FormDialog( + content: _formBody, buttons: _formButtons - )); + ); case _DownloadStatus.downloading: case _DownloadStatus.extracting: return GenericDialog( @@ -86,7 +87,7 @@ class _AddVersionDialogState extends State { ); case _DownloadStatus.done: return InfoDialog( - text: translations.downloadedVersion + text: translations.downloadedVersion ); } }) @@ -96,7 +97,7 @@ class _AddVersionDialogState extends State { if(widget.closable) DialogButton(type: ButtonType.secondary), DialogButton( - text: _source.value == _BuildSource.local ? translations.saveLocalVersion : translations.download, + text: translations.download, type: widget.closable ? ButtonType.primary : ButtonType.only, color: FluentTheme.of(context).accentColor, onTap: () => _startDownload(context), @@ -120,13 +121,6 @@ class _AddVersionDialogState extends State { return; } - final source = _source.value; - if(source == _BuildSource.local) { - Navigator.of(context).pop(); - _addFortniteVersion(build); - return; - } - _status.value = _DownloadStatus.downloading; final communicationPort = ReceivePort(); communicationPort.listen((message) { @@ -161,16 +155,22 @@ class _AddVersionDialogState extends State { return; } + final name = _nameController.text.trim(); + final location = Directory(_pathController.text); + final files = await findFiles(location, kShippingExe); + if(files.length == 1) { + await patchHeadless(files.first); + } + _status.value = _DownloadStatus.done; WindowsTaskbar.setProgressMode(TaskbarProgressMode.noProgress); - _addFortniteVersion(build); - } - void _addFortniteVersion(FortniteBuild build) { - WidgetsBinding.instance.addPostFrameCallback((_) => _gameController.addVersion(FortniteVersion( - content: build.version, - location: Directory(_pathController.text) - ))); + final version = FortniteVersion( + name: name, + gameVersion: build.gameVersion, + location: location + ); + _gameController.addVersion(version); } void _onDownloadError(Object? error, StackTrace? stackTrace) { @@ -269,25 +269,32 @@ class _AddVersionDialogState extends State { return translations.downloading; } - Widget _buildFormBody(List builds) { - return Column( + Widget get _formBody => Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildSourceSelector(), + InfoLabel( + label: translations.versionName, + child: TextFormBox( + controller: _nameController, + validator: _checkVersionName, + placeholder: translations.versionNameLabel, + autovalidateMode: AutovalidateMode.onUserInteraction + ), + ), const SizedBox( height: 16.0 ), - _buildBuildSelector(builds), + _buildSelector, FileSelector( label: translations.gameFolderTitle, - placeholder: _source.value == _BuildSource.local ? translations.gameFolderPlaceholder : translations.buildInstallationDirectoryPlaceholder, - windowTitle: _source.value == _BuildSource.local ? translations.gameFolderPlaceWindowTitle : translations.buildInstallationDirectoryWindowTitle, + placeholder: translations.buildInstallationDirectoryPlaceholder, + windowTitle: translations.buildInstallationDirectoryWindowTitle, controller: _pathController, - validator: _source.value == _BuildSource.local ? _checkGameFolder : _checkDownloadDestination, + validator: _checkDownloadDestination, folder: true, allowNavigator: true ), @@ -297,20 +304,14 @@ class _AddVersionDialogState extends State { ) ], ); - } - String? _checkGameFolder(text) { + String? _checkVersionName(text) { if (text == null || text.isEmpty) { - return translations.emptyGamePath; + return translations.emptyVersionName; } - final directory = Directory(text); - if (!directory.existsSync()) { - return translations.directoryDoesNotExist; - } - - if (FortniteVersionExtension.findFile(directory, "FortniteClient-Win64-Shipping.exe") == null) { - return translations.missingShippingExe; + if(_gameController.getVersionByName(text) != null) { + return translations.versionAlreadyExists; } return null; @@ -324,44 +325,46 @@ class _AddVersionDialogState extends State { return null; } - Widget _buildBuildSelector(List builds) => InfoLabel( + Widget get _buildSelector => InfoLabel( label: translations.build, child: FormField( key: _formFieldKey, validator: (data) => _checkBuild(data), builder: (formContext) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ComboBox( - placeholder: Text(translations.selectBuild), - isExpanded: true, - items: (_source.value == _BuildSource.local ? builds : builds.where((build) => build.available)).map((element) => _buildBuildItem(element)).toList(), - value: _build.value, - onChanged: (value) { - if(value == null){ - return; - } - - _build.value = value; - formContext.didChange(value); - formContext.validate(); - _updateFormDefaults(); + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ComboBox( + placeholder: Text(translations.selectBuild), + isExpanded: true, + items: downloadableBuilds.where((build) => build.available) + .map((element) => _buildBuildItem(element)) + .toList(), + value: _build.value, + onChanged: (value) { + if(value == null){ + return; } - ), - if(formContext.hasError) - const SizedBox(height: 4.0), - if(formContext.hasError) - Text( - formContext.errorText ?? "", - style: TextStyle( - color: Colors.red.defaultBrushFor(FluentTheme.of(context).brightness) - ), + + _build.value = value; + formContext.didChange(value); + formContext.validate(); + _updateFormDefaults(); + } + ), + if(formContext.hasError) + const SizedBox(height: 4.0), + if(formContext.hasError) + Text( + formContext.errorText ?? "", + style: TextStyle( + color: Colors.red.defaultBrushFor(FluentTheme.of(context).brightness) ), - SizedBox( - height: formContext.hasError ? 8.0 : 16.0 ), - ], - ) + SizedBox( + height: formContext.hasError ? 8.0 : 16.0 + ), + ], + ) ) ); @@ -370,40 +373,12 @@ class _AddVersionDialogState extends State { return translations.selectBuild; } - final versions = _gameController.versions.value; - if (versions.any((element) => data.version == element.content)) { - return translations.versionAlreadyExists; - } - return null; } ComboBoxItem _buildBuildItem(FortniteBuild element) => ComboBoxItem( value: element, - child: Text(element.version.toString()) - ); - - Widget _buildSourceSelector() => InfoLabel( - label: translations.source, - child: ComboBox<_BuildSource>( - placeholder: Text(translations.selectBuild), - isExpanded: true, - items: _BuildSource.values.map((entry) => _buildSourceItem(entry)).toList(), - value: _source.value, - onChanged: (value) { - if(value == null){ - return; - } - - _source.value = value; - _updateFormDefaults(); - } - ) - ); - - ComboBoxItem<_BuildSource> _buildSourceItem(_BuildSource element) => ComboBoxItem<_BuildSource>( - value: element, - child: Text(element.translatedName) + child: Text(element.gameVersion) ); @@ -415,21 +390,21 @@ class _AddVersionDialogState extends State { ]; Future _updateFormDefaults() async { - if(_source.value != _BuildSource.local && _build.value?.available != true) { + if(_build.value?.available != true) { _build.value = null; } - final disks = WindowsDisk.available(); - if(_source.value != _BuildSource.local && disks.isNotEmpty) { - final bestDisk = disks.reduce((first, second) => first.freeBytesAvailable > second.freeBytesAvailable ? first : second); - final build = _build.value; - if(build == null){ - return; + final build = _build.value; + if(build != null) { + _nameController.text = build.gameVersion; + _nameController.selection = TextSelection.collapsed(offset: build.gameVersion.length); + final disks = WindowsDisk.available(); + if(disks.isNotEmpty) { + final bestDisk = disks.reduce((first, second) => first.freeBytesAvailable > second.freeBytesAvailable ? first : second); + final pathText = "${bestDisk.path}FortniteBuilds\\${build.gameVersion}"; + _pathController.text = pathText; + _pathController.selection = TextSelection.collapsed(offset: pathText.length); } - - final pathText = "${bestDisk.path}FortniteBuilds\\${build.version}"; - _pathController.text = pathText; - _pathController.selection = TextSelection.collapsed(offset: pathText.length); } _formKey.currentState?.validate(); @@ -443,18 +418,3 @@ enum _DownloadStatus { error, done } - -enum _BuildSource { - local, - githubArchive; - - String get translatedName { - switch(this) { - case _BuildSource.local: - return translations.localBuild; - case _BuildSource.githubArchive: - return translations.githubArchive; - } - } -} - diff --git a/gui/lib/src/widget/version/import_version.dart b/gui/lib/src/widget/version/import_version.dart new file mode 100644 index 0000000..3f7d414 --- /dev/null +++ b/gui/lib/src/widget/version/import_version.dart @@ -0,0 +1,234 @@ +import 'dart:io'; + +import 'package:fluent_ui/fluent_ui.dart'; +import 'package:get/get.dart'; +import 'package:reboot_common/common.dart'; +import 'package:reboot_launcher/src/controller/game_controller.dart'; +import 'package:reboot_launcher/src/messenger/dialog.dart'; +import 'package:reboot_launcher/src/util/translations.dart'; +import 'package:reboot_launcher/src/widget/file/file_selector.dart'; +import 'package:path/path.dart' as path; +import 'package:version/version.dart'; + +class ImportVersionDialog extends StatefulWidget { + final FortniteVersion? version; + final bool closable; + const ImportVersionDialog({Key? key, required this.version, required this.closable}) : super(key: key); + + @override + State createState() => _ImportVersionDialogState(); +} + +class _ImportVersionDialogState extends State { + final TextEditingController _nameController = TextEditingController(); + final GameController _gameController = Get.find(); + final TextEditingController _pathController = TextEditingController(); + final GlobalKey _formKey = GlobalKey(); + final Rx<_ImportState> _validator = Rx(_ImportState.inputData); + + @override + void initState() { + final version = widget.version; + if(version != null) { + _nameController.text = version.name; + _nameController.selection = TextSelection.collapsed(offset: version.name.length); + _pathController.text = version.location.path; + _pathController.selection = TextSelection.collapsed(offset: version.location.path.length); + } + + super.initState(); + } + @override + void dispose() { + _nameController.dispose(); + _pathController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) => Form( + key: _formKey, + child: Obx(() { + switch(_validator.value) { + case _ImportState.inputData: + return FormDialog( + content: _importBody, + buttons: _importButtons + ); + case _ImportState.validating: + return ProgressDialog( + text: translations.importingVersion + ); + case _ImportState.success: + return InfoDialog( + text: translations.importedVersion + ); + case _ImportState.missingShippingExeError: + return InfoDialog( + text: translations.importVersionMissingShippingExeError(kShippingExe) + ); + case _ImportState.multipleShippingExesError: + return InfoDialog( + text: translations.importVersionMultipleShippingExesError(kShippingExe) + ); + case _ImportState.unsupportedVersionError: + return InfoDialog( + text: translations.importVersionUnsupportedVersionError + ); + } + }) + ); + + Widget get _importBody => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InfoLabel( + label: translations.versionName, + child: TextFormBox( + controller: _nameController, + validator: _checkVersionName, + placeholder: translations.versionNameLabel, + autovalidateMode: AutovalidateMode.onUserInteraction + ), + ), + + const SizedBox( + height: 16.0 + ), + + FileSelector( + label: translations.gameFolderTitle, + placeholder: translations.gameFolderPlaceholder, + windowTitle: translations.gameFolderPlaceWindowTitle, + controller: _pathController, + validator: _checkGamePath, + validatorMode: AutovalidateMode.onUserInteraction, + folder: true, + allowNavigator: true, + onSelected: (selected) { + var name = path.basename(selected); + if(_gameController.getVersionByName(name) != null) { + var counter = 1; + while(_gameController.getVersionByName("$name-$counter") != null) { + counter++; + } + name = "$name-$counter"; + } + _nameController.text = name; + _nameController.selection = TextSelection.collapsed(offset: name.length); + }, + ), + + const SizedBox( + height: 16.0 + ) + ], + ); + + List get _importButtons => [ + if(widget.closable) + DialogButton(type: ButtonType.secondary), + DialogButton( + text: translations.saveLocalVersion, + type: widget.closable ? ButtonType.primary : ButtonType.only, + color: FluentTheme.of(context).accentColor, + onTap: _importVersion, + ) + ]; + + void _importVersion() async { + final topResult = _formKey.currentState?.validate(); + if(topResult != true) { + return; + } + + _validator.value = _ImportState.validating; + final name = _nameController.text.trim(); + final directory = Directory(_pathController.text.trim()); + + final files = await Future.wait([ + Future.delayed(const Duration(seconds: 1)).then((_) => []), + findFiles(directory, kShippingExe).then((files) async { + if(files.length == 1) { + await patchHeadless(files.first); + } + return files; + }) + ]).then((values) => values.expand((entry) => entry).toList()); + + if (files.isEmpty) { + _validator.value = _ImportState.missingShippingExeError; + return; + } + + if(files.length != 1) { + _validator.value = _ImportState.multipleShippingExesError; + return; + } + + final gameVersion = await extractGameVersion(files.first.path, path.basename(directory.path)); + try { + if(Version.parse(gameVersion) >= kMaxAllowedVersion) { + _validator.value = _ImportState.unsupportedVersionError; + return; + } + }catch(_) { + + } + + if(widget.version == null) { + final version = FortniteVersion( + name: name, + gameVersion: gameVersion, + location: files.first.parent + ); + _gameController.addVersion(version); + }else { + widget.version?.name = name; + widget.version?.gameVersion = gameVersion; + widget.version?.location = files.first.parent; + } + _validator.value = _ImportState.success; + } + + String? _checkVersionName(String? text) { + final version = widget.version; + if(version != null && version.name == text) { + return null; + } + + if (text == null || text.isEmpty) { + return translations.emptyVersionName; + } + + if(_gameController.getVersionByName(text) != null) { + return translations.versionAlreadyExists; + } + + return null; + } + + String? _checkGamePath(String? input) { + if(input == null || input.isEmpty) { + return translations.emptyGamePath; + } + + final directory = Directory(input); + if(!directory.existsSync()) { + return translations.directoryDoesNotExist; + } + + return null; + } +} + +enum _ImportState { + inputData, + validating, + success, + missingShippingExeError, + multipleShippingExesError, + unsupportedVersionError +} + diff --git a/gui/lib/src/widget/version/version_selector.dart b/gui/lib/src/widget/version/version_selector.dart index 90aec27..dc63cb7 100644 --- a/gui/lib/src/widget/version/version_selector.dart +++ b/gui/lib/src/widget/version/version_selector.dart @@ -8,15 +8,46 @@ import 'package:reboot_common/common.dart'; import 'package:reboot_launcher/src/controller/game_controller.dart'; import 'package:reboot_launcher/src/messenger/dialog.dart'; import 'package:reboot_launcher/src/messenger/info_bar.dart'; -import 'package:reboot_launcher/src/widget/message/version.dart'; +import 'package:reboot_launcher/src/messenger/overlay.dart'; +import 'package:reboot_launcher/src/widget/fluent/setting_tile.dart'; +import 'package:reboot_launcher/src/widget/version/download_version.dart'; import 'package:reboot_launcher/src/util/translations.dart'; +import 'package:reboot_launcher/src/widget/version/import_version.dart'; import 'package:url_launcher/url_launcher.dart'; class VersionSelector extends StatefulWidget { const VersionSelector({Key? key}) : super(key: key); + static SettingTile buildTile({ + required GlobalKey key + }) => SettingTile( + icon: Icon( + FluentIcons.play_24_regular + ), + title: Text(translations.selectFortniteName), + subtitle: Text(translations.selectFortniteDescription), + contentWidth: null, + content: ConstrainedBox( + constraints: BoxConstraints( + minWidth: SettingTile.kDefaultContentWidth, + ), + child: OverlayTarget( + key: key, + child: const VersionSelector(), + ) + ) + ); + + static Future openImportDialog(FortniteVersion? version) => showRebootDialog( + builder: (context) => ImportVersionDialog( + version: version, + closable: true, + ), + dismissWithEsc: true + ); + static Future openDownloadDialog() => showRebootDialog( - builder: (context) => AddVersionDialog( + builder: (context) => DownloadVersionDialog( closable: true, ), dismissWithEsc: true @@ -34,7 +65,7 @@ class _VersionSelectorState extends State { @override Widget build(BuildContext context) => Obx(() { return _createOptionsMenu( - version: _gameController.selectedVersion, + version: _gameController.selectedVersion.value, close: false, child: FlyoutTarget( controller: _flyoutController, @@ -42,7 +73,7 @@ class _VersionSelectorState extends State { onOpen: () => inDialog = true, onClose: () => inDialog = false, leading: Text( - _gameController.selectedVersion?.content.toString() ?? translations.selectVersion, + _gameController.selectedVersion.value?.name ?? translations.selectVersion, maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -65,7 +96,7 @@ class _VersionSelectorState extends State { var result = await _flyoutController.showFlyout<_ContextualOption?>( builder: (context) => MenuFlyout( items: _ContextualOption.values - .map((entry) => _createOption(context, entry)) + .map((entry) => _createOption(entry)) .toList() ) ); @@ -76,7 +107,7 @@ class _VersionSelectorState extends State { List _createSelectorItems(BuildContext context) { final items = _gameController.versions.value - .map((version) => _createVersionItem(context, version)) + .map((version) => _createVersionItem(version)) .toList(); items.add(MenuFlyoutItem( trailing: Padding( @@ -87,12 +118,23 @@ class _VersionSelectorState extends State { ), ), text: Text(translations.addVersion), + onPressed: () => VersionSelector.openImportDialog(null) + )); + items.add(MenuFlyoutItem( + trailing: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + FluentIcons.arrow_download_24_regular, + size: 14 + ), + ), + text: Text(translations.downloadVersion), onPressed: VersionSelector.openDownloadDialog )); return items; } - MenuFlyoutItem _createVersionItem(BuildContext context, FortniteVersion version) => MenuFlyoutItem( + MenuFlyoutItem _createVersionItem(FortniteVersion version) => MenuFlyoutItem( text: Listener( onPointerDown: (event) async { if (event.kind != PointerDeviceKind.mouse || event.buttons != kSecondaryMouseButton) { @@ -101,7 +143,7 @@ class _VersionSelectorState extends State { await _openVersionOptions(version); }, - child: Text(version.content.toString()) + child: Text(version.name) ), trailing: IconButton( onPressed: () => _openVersionOptions(version), @@ -109,14 +151,14 @@ class _VersionSelectorState extends State { FluentIcons.more_vertical_24_regular ) ), - onPressed: () => _gameController.selectedVersion = version + onPressed: () => _gameController.selectedVersion.value = version ); Future _openVersionOptions(FortniteVersion version) async { final result = await _flyoutController.showFlyout<_ContextualOption?>( builder: (context) => MenuFlyout( items: _ContextualOption.values - .map((entry) => _createOption(context, entry)) + .map((entry) => _createOption(entry)) .toList() ), barrierDismissible: true, @@ -139,8 +181,19 @@ class _VersionSelectorState extends State { launchUrl(version.location.uri) .onError((error, stackTrace) => _onExplorerError()); break; + case _ContextualOption.modify: + if(!mounted){ + return; + } + + if(close) { + Navigator.of(context).pop(); + } + + await VersionSelector.openImportDialog(version); + break; case _ContextualOption.delete: - final result = await _openDeleteDialog(context, version) ?? false; + final result = await _openDeleteDialog(version) ?? false; if(!mounted || !result){ return; } @@ -160,7 +213,7 @@ class _VersionSelectorState extends State { } } - MenuFlyoutItem _createOption(BuildContext context, _ContextualOption entry) { + MenuFlyoutItem _createOption(_ContextualOption entry) { return MenuFlyoutItem( text: Text(entry.translatedName), onPressed: () => Navigator.of(context).pop(entry) @@ -168,11 +221,15 @@ class _VersionSelectorState extends State { } bool _onExplorerError() { - showRebootInfoBar(translations.missingVersion); + showRebootInfoBar( + translations.missingVersionError, + severity: InfoBarSeverity.error, + duration: infoBarLongDuration, + ); return false; } - Future _openDeleteDialog(BuildContext context, FortniteVersion version) { + Future _openDeleteDialog(FortniteVersion version) { return showRebootDialog( builder: (context) => ContentDialog( content: Column( @@ -209,18 +266,21 @@ class _VersionSelectorState extends State { ) ); } + + @override + GameController get gameController => _gameController; } enum _ContextualOption { openExplorer, - delete; + modify, + delete +} +extension _ContextualOptionExtension on _ContextualOption { String get translatedName { - switch(this) { - case _ContextualOption.openExplorer: - return translations.openInExplorer; - case _ContextualOption.delete: - return translations.delete; - } + return this == _ContextualOption.openExplorer ? translations.openInExplorer + : this == _ContextualOption.modify ? translations.modify + : translations.delete; } -} \ No newline at end of file +} diff --git a/gui/lib/src/widget/version/version_selector_tile.dart b/gui/lib/src/widget/version/version_selector_tile.dart deleted file mode 100644 index 895789e..0000000 --- a/gui/lib/src/widget/version/version_selector_tile.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:fluent_ui/fluent_ui.dart' hide FluentIcons; -import 'package:fluentui_system_icons/fluentui_system_icons.dart'; -import 'package:reboot_launcher/src/messenger/overlay.dart'; -import 'package:reboot_launcher/src/util/translations.dart'; -import 'package:reboot_launcher/src/widget/fluent/setting_tile.dart'; -import 'package:reboot_launcher/src/widget/version/version_selector.dart'; - -SettingTile buildVersionSelector({ - required GlobalKey key -}) => SettingTile( - icon: Icon( - FluentIcons.play_24_regular - ), - title: Text(translations.selectFortniteName), - subtitle: Text(translations.selectFortniteDescription), - contentWidth: null, - content: ConstrainedBox( - constraints: BoxConstraints( - minWidth: SettingTile.kDefaultContentWidth, - ), - child: OverlayTarget( - key: key, - child: const VersionSelector(), - ) - ) -); \ No newline at end of file diff --git a/gui/pubspec.yaml b/gui/pubspec.yaml index efeb2d4..88ae1c6 100644 --- a/gui/pubspec.yaml +++ b/gui/pubspec.yaml @@ -1,6 +1,6 @@ name: reboot_launcher description: Graphical User Interface for Project Reboot -version: "10.0.7" +version: "10.0.8" publish_to: 'none' @@ -33,9 +33,6 @@ dependencies: # Window management window_manager: ^0.4.2 - # Extract zip archives (for example the reboot.zip) - archive: ^3.6.1 - # Cryptographic functions bcrypt: ^1.1.3 pointycastle: ^3.9.1 @@ -49,6 +46,8 @@ dependencies: get: ^4.6.6 # Native utilities + archive: ^3.6.1 + watcher: ^1.1.1 clipboard: ^0.1.3 app_links: ^6.3.2 windows_taskbar: ^1.1.2 diff --git a/gui/windows/packaging/exe/custom-inno-setup-script.iss b/gui/windows/packaging/exe/custom-inno-setup-script.iss index 6b9eb20..04ae56b 100644 --- a/gui/windows/packaging/exe/custom-inno-setup-script.iss +++ b/gui/windows/packaging/exe/custom-inno-setup-script.iss @@ -55,6 +55,7 @@ begin ' Allow DLL injection', ' The Reboot Launcher needs to inject DLLs into Fortnite to create the game server', 'Selecting the option below will add the Reboot Launcher to the Windows Exclusions list. ' + + 'If you are using another AntiVirus, it might be necessary to add an exclusion manually. ' + 'This is necessary because DLL injection is often detected as a virus, but is necessary to modify Fortnite. ' + 'This option was designed for advanced users who want to manually manage the exclusions list on their machine. ' + 'If you do not trust the Reboot Launcher, you can audit the source code at https://github.com/Auties00/reboot_launcher and build it from source.',