Upload files to "/"
This commit is contained in:
7
._analysis.json
Normal file
7
._analysis.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"file_path": ".",
|
||||
"analysis": {},
|
||||
"errors": [
|
||||
"File read failed: [Errno 13] Permission denied: '.'"
|
||||
]
|
||||
}
|
||||
BIN
Fallout Shelter.log
Normal file
BIN
Fallout Shelter.log
Normal file
Binary file not shown.
181
README.md
Normal file
181
README.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Fallout Shelter Save Editor
|
||||
|
||||
A modern, cross-platform save editor for Fallout Shelter built with Electron.js. Features AES decryption support and a beautiful, intuitive interface.
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
✨ **Modern Interface** - Beautiful, dark-themed UI with smooth animations
|
||||
🔐 **AES Decryption** - Properly decrypt and encrypt Fallout Shelter save files
|
||||
💰 **Resource Editing** - Edit caps, food, water, power, stimpaks, and more
|
||||
🏠 **Vault Management** - Modify vault name, mode, and theme
|
||||
👥 **Dweller Overview** - View dweller information and stats
|
||||
📝 **Raw Data Access** - Direct JSON editing for advanced users
|
||||
💾 **Safe Backups** - Automatic backup creation before modifications
|
||||
⚡ **Cross-Platform** - Works on Windows, macOS, and Linux
|
||||
|
||||
## Installation
|
||||
|
||||
### Option 1: Download Pre-built Binary
|
||||
1. Go to the [Releases](https://github.com/your-repo/releases) page
|
||||
2. Download the appropriate version for your operating system
|
||||
3. Install and run the application
|
||||
|
||||
### Option 2: Build from Source
|
||||
|
||||
#### Prerequisites
|
||||
- Node.js 16 or higher
|
||||
- npm or yarn
|
||||
|
||||
#### Steps
|
||||
1. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/your-repo/fallout-shelter-save-editor.git
|
||||
cd fallout-shelter-save-editor
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Run in development mode:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
4. Build for production:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Loading a Save File
|
||||
1. Launch the application
|
||||
2. Click "Get Started - Open Save File" or use File → Open Save File
|
||||
3. Navigate to your Fallout Shelter save directory:
|
||||
- **Windows**: `%LOCALAPPDATA%/FalloutShelter/`
|
||||
- **macOS**: `~/Library/Application Support/FalloutShelter/`
|
||||
- **Android** (with file access): `/Android/data/com.bethsoft.falloutshelter/files/`
|
||||
|
||||
### Editing Resources
|
||||
1. Switch to the "Resources" tab
|
||||
2. Modify the values for caps, food, water, power, etc.
|
||||
3. Click "Apply Changes" to save modifications
|
||||
4. Use "Max All" for maximum resource values
|
||||
|
||||
### Vault Information
|
||||
1. Go to the "Vault Info" tab
|
||||
2. Edit vault name, mode (Normal/Survival), and theme
|
||||
3. Apply changes when ready
|
||||
|
||||
### Advanced Editing
|
||||
1. Use the "Raw Data" tab for direct JSON editing
|
||||
2. Format JSON for better readability
|
||||
3. Copy data to clipboard for external editing
|
||||
|
||||
### Saving Changes
|
||||
1. Use Ctrl+S (Cmd+S on Mac) or File → Save
|
||||
2. Create backups with File → Create Backup
|
||||
3. Use File → Save As to save to a different location
|
||||
|
||||
## Save File Locations
|
||||
|
||||
### Windows
|
||||
```
|
||||
%LOCALAPPDATA%/FalloutShelter/
|
||||
```
|
||||
|
||||
### macOS
|
||||
```
|
||||
~/Library/Application Support/FalloutShelter/
|
||||
```
|
||||
|
||||
### Android (Rooted/File Access)
|
||||
```
|
||||
/Android/data/com.bethsoft.falloutshelter/files/
|
||||
```
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Encryption
|
||||
Fallout Shelter save files use AES-CBC encryption with:
|
||||
- **Key**: `a7c2f3f367a2e2e2f0f2b6b1b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7` (hex)
|
||||
- **IV**: `7475383967656A693334307438397532` (hex)
|
||||
- **Mode**: CBC with PKCS7 padding
|
||||
- **Encoding**: Base64
|
||||
|
||||
### Save Structure
|
||||
The decrypted save file is a JSON object containing:
|
||||
- `vault.storage.resources` - Resource amounts (caps, food, water, etc.)
|
||||
- `vault.VaultName` - Vault name
|
||||
- `vault.VaultMode` - Game mode (Normal/Survival)
|
||||
- `dwellers.dwellers` - Array of dweller data
|
||||
- And much more...
|
||||
|
||||
## Development
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
├── main.js # Electron main process
|
||||
├── renderer.js # Renderer process (UI logic)
|
||||
├── index.html # Main UI
|
||||
├── styles.css # Styling
|
||||
├── package.json # Dependencies and scripts
|
||||
└── assets/ # Icons and images
|
||||
```
|
||||
|
||||
### Building
|
||||
```bash
|
||||
# Development
|
||||
npm run dev
|
||||
|
||||
# Build for current platform
|
||||
npm run build
|
||||
|
||||
# Build for specific platforms
|
||||
npm run build-win # Windows
|
||||
npm run build-mac # macOS
|
||||
npm run build-linux # Linux
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch: `git checkout -b feature-name`
|
||||
3. Make your changes and test thoroughly
|
||||
4. Commit your changes: `git commit -am 'Add feature'`
|
||||
5. Push to the branch: `git push origin feature-name`
|
||||
6. Submit a pull request
|
||||
|
||||
## Safety & Disclaimers
|
||||
|
||||
⚠️ **Important Notes:**
|
||||
- Always backup your save files before editing
|
||||
- Use at your own risk - save corruption is possible
|
||||
- This tool is for educational and personal use only
|
||||
- Not affiliated with Bethesda Game Studios
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- Bethesda Game Studios for Fallout Shelter
|
||||
- The modding community for reverse engineering the save format
|
||||
- Electron.js team for the framework
|
||||
- Font Awesome for icons
|
||||
|
||||
## Support
|
||||
|
||||
If you encounter issues:
|
||||
1. Check the [Issues](https://github.com/your-repo/issues) page
|
||||
2. Create a new issue with detailed information
|
||||
3. Include your operating system and save file details (without personal data)
|
||||
|
||||
---
|
||||
|
||||
**Enjoy modifying your vault! 🏠⚡**
|
||||
1
Vault1.sav
Normal file
1
Vault1.sav
Normal file
File diff suppressed because one or more lines are too long
1
Vault1.sav.backup_2025-07-31T08-31-37-852Z
Normal file
1
Vault1.sav.backup_2025-07-31T08-31-37-852Z
Normal file
File diff suppressed because one or more lines are too long
1
Vault1.sav.bkp
Normal file
1
Vault1.sav.bkp
Normal file
File diff suppressed because one or more lines are too long
19
Vault1.sav_analysis.json
Normal file
19
Vault1.sav_analysis.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"file_path": "Vault1.sav",
|
||||
"analysis": {
|
||||
"raw_size": 95532,
|
||||
"raw_preview": "7a434c314678456877355343656e6f776c487276705a48453338676d614d6e5a6c496c6d4d43347a5930504c2f4a505342666443625279533039335073614d5631674377734236624c562b586455792b57517241713759534e4f4b447961477730647467",
|
||||
"base64_decoded": true,
|
||||
"decoded_size": 71648,
|
||||
"decoded_preview": "cc22f5171121c394827a7a30947aefa591c4dfc82668c9d9948966302e336343cbfc93d205f7426d1c92d3ddcfb1a315d600",
|
||||
"zlib_error": "Error -3 while decompressing data: incorrect header check",
|
||||
"gzip_error": "Not a gzipped file (b'\\xcc\"')",
|
||||
"zlib_raw_error": "Error -3 while decompressing data: invalid code lengths set",
|
||||
"first_4_bytes_le": 401941196,
|
||||
"first_4_bytes_be": 3424843031,
|
||||
"possible_json_content": "\"\u0017\u0011!\u00d4zz0z\uf951&h\u0654f0.3cC\u0005Bm\u001c\u03f1\u0015\u0000\u001e-_uLY\n\u00124\u0261`\u001ae\u0007\u001f\u0013j\u000fk\u000b:\u001bT_m;3e\u071e\u0011\u001fNCt\u001cI\u0492&`OD<M\"v\rw\u0148\u0001\u0018g<\u0013pg\u0279 .9\u0017/V`<\u0011&fCQ7\n4ZshwStn?\u0019\u007fXr1U\u001b\r^+B:\u0010+}e|bZ\u007f\u07e2VZ\b\u001d\u0015]\u0440J9\u0016?\u0089\u0004\u007fq0(B\u0016v-\u01a1^)TLk\u001d\u0004H-\u0017;\u001ec*C\u001f\u0748}U\u000e\u0005r\rA[{xzr\nZ\u0015\n-<\u01c1\u0015QD)\u0010a,)Xk$\rpNK\u001d\u001c\u0005s\u0011Y\u0011\u0010r.\u0011#1&\u0015f\"y\u0007Z\u01b03.V\u0016PTYk\u0015$\u05cd>6:k\u01b33&'6\u000e\u033cV{\u001e\\d\u000f->\u007f\u001bG<O>Q=Y\u00b9pQ<<|x'2\u001dL6\u00139\u06e8\\im_\rr *}\u000fW\t[~\u0016$\u001aTo/~;S~&[)\ud1e5;\u0016N074lqk)B&\u000fBQBcZ;[\u0016R>\u0007gly\u0014\u001a\u0001\u007f*\u001f\u033c@F\u025a}:[pt:\u0006\u0701W:w]*\u0010Xa4{5` k\u001c.\u02a2\u0521(D\u001c$<\u0017\u04a8gj\u0017i-||\u0015\u001a-\u0527\u03577@~I\u0003l\u0007)\u0006n{=\t}\u03c8\u007f\u0017(\n>\u0006,2.\u001e)K\u0269\u00af\u0006~\u0007\u0018y\u0014l\u02ae.G+[T<\u001e\u007fYP;!\u0015\u04a9\u0004{B\u02be*U\u0487`\u05ab\"}wy6~\"z.\n1QRXex9}NWv,\"KON\u000e*tbk+jY'\u007f\u0018Q\u0004ko5\u0006\u0001V\u001cXFg0\u036aJA\u0011\u1cef",
|
||||
"entropy": 7.997523790919208,
|
||||
"likely_encrypted": true
|
||||
},
|
||||
"errors": []
|
||||
}
|
||||
BIN
advanced_save_editor.py
Normal file
BIN
advanced_save_editor.py
Normal file
Binary file not shown.
250
analyze_save.py
Normal file
250
analyze_save.py
Normal file
@@ -0,0 +1,250 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Fallout Shelter Save File Analyzer
|
||||
Analyzes the structure and format of Fallout Shelter save files.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import json
|
||||
import zlib
|
||||
import gzip
|
||||
import struct
|
||||
import binascii
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
|
||||
def analyze_save_file(filepath: str) -> Dict[str, Any]:
|
||||
"""Comprehensive analysis of a Fallout Shelter save file."""
|
||||
|
||||
results = {
|
||||
"file_path": filepath,
|
||||
"analysis": {},
|
||||
"errors": []
|
||||
}
|
||||
|
||||
try:
|
||||
# Read raw file
|
||||
with open(filepath, 'rb') as f:
|
||||
raw_data = f.read()
|
||||
|
||||
results["analysis"]["raw_size"] = len(raw_data)
|
||||
results["analysis"]["raw_preview"] = raw_data[:100].hex()
|
||||
|
||||
# Check if it's base64
|
||||
try:
|
||||
decoded_data = base64.b64decode(raw_data)
|
||||
results["analysis"]["base64_decoded"] = True
|
||||
results["analysis"]["decoded_size"] = len(decoded_data)
|
||||
results["analysis"]["decoded_preview"] = decoded_data[:50].hex()
|
||||
|
||||
# Analyze decoded data
|
||||
analyze_decoded_data(decoded_data, results)
|
||||
|
||||
except Exception as e:
|
||||
results["errors"].append(f"Base64 decode failed: {e}")
|
||||
results["analysis"]["base64_decoded"] = False
|
||||
|
||||
except Exception as e:
|
||||
results["errors"].append(f"File read failed: {e}")
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def analyze_decoded_data(data: bytes, results: Dict[str, Any]) -> None:
|
||||
"""Analyze the decoded binary data."""
|
||||
|
||||
# Check for common compression signatures
|
||||
compression_tests = [
|
||||
("zlib", lambda d: zlib.decompress(d)),
|
||||
("gzip", lambda d: gzip.decompress(d)),
|
||||
("zlib_raw", lambda d: zlib.decompress(d, -15)), # Raw deflate
|
||||
]
|
||||
|
||||
for name, decompress_func in compression_tests:
|
||||
try:
|
||||
decompressed = decompress_func(data)
|
||||
results["analysis"][f"{name}_success"] = True
|
||||
results["analysis"][f"{name}_size"] = len(decompressed)
|
||||
|
||||
# Try to parse as JSON
|
||||
try:
|
||||
text = decompressed.decode('utf-8')
|
||||
json_data = json.loads(text)
|
||||
results["analysis"][f"{name}_json_success"] = True
|
||||
results["analysis"][f"{name}_json_keys"] = list(json_data.keys()) if isinstance(json_data, dict) else "not_dict"
|
||||
results["analysis"]["parsed_data"] = json_data
|
||||
return # Success! Stop here
|
||||
except Exception as json_e:
|
||||
results["analysis"][f"{name}_json_error"] = str(json_e)
|
||||
|
||||
except Exception as e:
|
||||
results["analysis"][f"{name}_error"] = str(e)
|
||||
|
||||
# If no standard compression worked, try custom analysis
|
||||
analyze_custom_format(data, results)
|
||||
|
||||
|
||||
def analyze_custom_format(data: bytes, results: Dict[str, Any]) -> None:
|
||||
"""Analyze for custom Fallout Shelter format."""
|
||||
|
||||
# Check for common patterns
|
||||
if len(data) >= 4:
|
||||
# Try reading first 4 bytes as various integer formats
|
||||
results["analysis"]["first_4_bytes_le"] = struct.unpack('<I', data[:4])[0]
|
||||
results["analysis"]["first_4_bytes_be"] = struct.unpack('>I', data[:4])[0]
|
||||
|
||||
# Check if first 4 bytes could be a length field
|
||||
length_le = struct.unpack('<I', data[:4])[0]
|
||||
length_be = struct.unpack('>I', data[:4])[0]
|
||||
|
||||
if 4 < length_le < len(data):
|
||||
results["analysis"]["possible_length_field_le"] = length_le
|
||||
try_decompress_with_header(data[4:], results, "le_header")
|
||||
|
||||
if 4 < length_be < len(data):
|
||||
results["analysis"]["possible_length_field_be"] = length_be
|
||||
try_decompress_with_header(data[4:], results, "be_header")
|
||||
|
||||
# Look for JSON-like patterns in raw data
|
||||
text_preview = data.decode('utf-8', errors='ignore')[:500]
|
||||
if '{' in text_preview or '"' in text_preview:
|
||||
results["analysis"]["possible_json_content"] = text_preview
|
||||
|
||||
# Check for encryption patterns (high entropy)
|
||||
entropy = calculate_entropy(data)
|
||||
results["analysis"]["entropy"] = entropy
|
||||
|
||||
if entropy > 7.5:
|
||||
results["analysis"]["likely_encrypted"] = True
|
||||
else:
|
||||
results["analysis"]["likely_encrypted"] = False
|
||||
|
||||
|
||||
def try_decompress_with_header(data: bytes, results: Dict[str, Any], prefix: str) -> None:
|
||||
"""Try decompressing data after removing header."""
|
||||
|
||||
compression_methods = [
|
||||
("zlib", lambda d: zlib.decompress(d)),
|
||||
("gzip", lambda d: gzip.decompress(d)),
|
||||
("zlib_raw", lambda d: zlib.decompress(d, -15)),
|
||||
]
|
||||
|
||||
for name, decompress_func in compression_methods:
|
||||
try:
|
||||
decompressed = decompress_func(data)
|
||||
results["analysis"][f"{prefix}_{name}_success"] = True
|
||||
results["analysis"][f"{prefix}_{name}_size"] = len(decompressed)
|
||||
|
||||
# Try JSON parse
|
||||
try:
|
||||
text = decompressed.decode('utf-8')
|
||||
json_data = json.loads(text)
|
||||
results["analysis"][f"{prefix}_{name}_json_success"] = True
|
||||
results["analysis"]["parsed_data"] = json_data
|
||||
return
|
||||
except:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
results["analysis"][f"{prefix}_{name}_error"] = str(e)
|
||||
|
||||
|
||||
def calculate_entropy(data: bytes) -> float:
|
||||
"""Calculate Shannon entropy of data."""
|
||||
if not data:
|
||||
return 0
|
||||
|
||||
import math
|
||||
|
||||
# Count byte frequencies
|
||||
frequencies = [0] * 256
|
||||
for byte in data:
|
||||
frequencies[byte] += 1
|
||||
|
||||
# Calculate entropy
|
||||
entropy = 0
|
||||
data_len = len(data)
|
||||
for freq in frequencies:
|
||||
if freq > 0:
|
||||
p = freq / data_len
|
||||
entropy -= p * math.log2(p)
|
||||
|
||||
return entropy
|
||||
|
||||
|
||||
def print_analysis_results(results: Dict[str, Any]) -> None:
|
||||
"""Print analysis results in a readable format."""
|
||||
|
||||
print(f"Analysis Results for: {results['file_path']}")
|
||||
print("=" * 50)
|
||||
|
||||
if results["errors"]:
|
||||
print("ERRORS:")
|
||||
for error in results["errors"]:
|
||||
print(f" - {error}")
|
||||
print()
|
||||
|
||||
analysis = results["analysis"]
|
||||
|
||||
print("FILE INFO:")
|
||||
print(f" Raw size: {analysis.get('raw_size', 'unknown')} bytes")
|
||||
print(f" Base64 decoded: {analysis.get('base64_decoded', False)}")
|
||||
if analysis.get('decoded_size'):
|
||||
print(f" Decoded size: {analysis['decoded_size']} bytes")
|
||||
print()
|
||||
|
||||
print("COMPRESSION ANALYSIS:")
|
||||
compression_methods = ['zlib', 'gzip', 'zlib_raw']
|
||||
for method in compression_methods:
|
||||
if f"{method}_success" in analysis:
|
||||
print(f" {method}: SUCCESS (size: {analysis[f'{method}_size']})")
|
||||
if f"{method}_json_success" in analysis:
|
||||
print(f" JSON parse: SUCCESS")
|
||||
if "parsed_data" in analysis:
|
||||
data = analysis["parsed_data"]
|
||||
if isinstance(data, dict):
|
||||
print(f" Keys: {list(data.keys())[:10]}") # First 10 keys
|
||||
else:
|
||||
print(f" JSON parse: FAILED")
|
||||
elif f"{method}_error" in analysis:
|
||||
print(f" {method}: FAILED ({analysis[f'{method}_error']})")
|
||||
print()
|
||||
|
||||
if "entropy" in analysis:
|
||||
print(f"DATA CHARACTERISTICS:")
|
||||
print(f" Entropy: {analysis['entropy']:.2f}")
|
||||
print(f" Likely encrypted: {analysis.get('likely_encrypted', 'unknown')}")
|
||||
print()
|
||||
|
||||
if "parsed_data" in analysis:
|
||||
print("PARSED DATA PREVIEW:")
|
||||
data = analysis["parsed_data"]
|
||||
if isinstance(data, dict):
|
||||
for key, value in list(data.items())[:5]: # First 5 items
|
||||
print(f" {key}: {str(value)[:100]}")
|
||||
else:
|
||||
print(f" {str(data)[:200]}")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
import sys
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python analyze_save.py <save_file_path>")
|
||||
print("Example: python analyze_save.py Vault1.sav")
|
||||
return
|
||||
|
||||
filepath = sys.argv[1]
|
||||
results = analyze_save_file(filepath)
|
||||
print_analysis_results(results)
|
||||
|
||||
# Save detailed results to JSON
|
||||
output_file = f"{filepath}_analysis.json"
|
||||
with open(output_file, 'w') as f:
|
||||
json.dump(results, f, indent=2, default=str)
|
||||
print(f"\nDetailed analysis saved to: {output_file}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
5001
decrypted_save.json
Normal file
5001
decrypted_save.json
Normal file
@@ -0,0 +1,5001 @@
|
||||
{
|
||||
"timeMgr": {
|
||||
"gameTime": 5081.7,
|
||||
"questTime": 0.0,
|
||||
"time": 5260.19,
|
||||
"timeSaveDate": 638895299353878112,
|
||||
"timeGameBegin": 638895246749920421
|
||||
},
|
||||
"localNotificationMgr": {
|
||||
"UniqueIDS": []
|
||||
},
|
||||
"taskMgr": {
|
||||
"id": 1007,
|
||||
"time": 5260.19,
|
||||
"tasks": [
|
||||
{
|
||||
"startTime": 1788.73,
|
||||
"endTime": 88188.73,
|
||||
"id": 391,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 0.0,
|
||||
"endTime": 86400.0,
|
||||
"id": 7,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 0.0,
|
||||
"endTime": 86400.0,
|
||||
"id": 8,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4459.49,
|
||||
"endTime": 15259.49,
|
||||
"id": 843,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4309.49,
|
||||
"endTime": 15109.49,
|
||||
"id": 828,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4115.39,
|
||||
"endTime": 14915.39,
|
||||
"id": 800,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4054.49,
|
||||
"endTime": 14854.49,
|
||||
"id": 791,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 3563.79,
|
||||
"endTime": 14363.79,
|
||||
"id": 658,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 3503.79,
|
||||
"endTime": 14303.79,
|
||||
"id": 652,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 992.8,
|
||||
"endTime": 9770.85,
|
||||
"id": 219,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 4365.14,
|
||||
"endTime": 7965.14,
|
||||
"id": 835,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4235.23,
|
||||
"endTime": 7624.43,
|
||||
"id": 217,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 3600.0,
|
||||
"endTime": 7200.0,
|
||||
"id": 6,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 3033.77,
|
||||
"endTime": 6669.49,
|
||||
"id": 585,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4592.8,
|
||||
"endTime": 6392.8,
|
||||
"id": 213,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 4870.0,
|
||||
"endTime": 6162.4,
|
||||
"id": 221,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 4870.0,
|
||||
"endTime": 6162.4,
|
||||
"id": 220,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 3566.7,
|
||||
"endTime": 5966.7,
|
||||
"id": 659,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4592.8,
|
||||
"endTime": 5492.8,
|
||||
"id": 215,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 5252.8,
|
||||
"endTime": 5312.8,
|
||||
"id": 214,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 5252.8,
|
||||
"endTime": 5312.8,
|
||||
"id": 216,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 5250.62,
|
||||
"endTime": 5304.27,
|
||||
"id": 1,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5258.43,
|
||||
"endTime": 5273.43,
|
||||
"id": 1006,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5258.43,
|
||||
"endTime": 5273.43,
|
||||
"id": 1005,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5258.43,
|
||||
"endTime": 5273.43,
|
||||
"id": 1004,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5260.0,
|
||||
"endTime": 5270.0,
|
||||
"id": 3,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5260.0,
|
||||
"endTime": 5270.0,
|
||||
"id": 4,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5260.0,
|
||||
"endTime": 5270.0,
|
||||
"id": 5,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 4365.14,
|
||||
"endTime": 5265.14,
|
||||
"id": 834,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5252.8,
|
||||
"endTime": 5264.8,
|
||||
"id": 218,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": false
|
||||
},
|
||||
{
|
||||
"startTime": 5256.0,
|
||||
"endTime": 5264.0,
|
||||
"id": 2,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5256.0,
|
||||
"endTime": 5261.0,
|
||||
"id": 1007,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
},
|
||||
{
|
||||
"startTime": 5259.99,
|
||||
"endTime": 5260.24,
|
||||
"id": 1002,
|
||||
"paused": false,
|
||||
"rescheduleToOldest": true
|
||||
}
|
||||
],
|
||||
"pausedTasks": []
|
||||
},
|
||||
"ratingMgr": {
|
||||
"sampleId": 6,
|
||||
"dayRatingId": 7,
|
||||
"currentSamples": [
|
||||
100
|
||||
],
|
||||
"ratings": [],
|
||||
"ratingsLast": [],
|
||||
"hasWeekRating": false,
|
||||
"hasLastWeekRating": false,
|
||||
"weekRating": 0,
|
||||
"lastWeekRating": 0
|
||||
},
|
||||
"specialTheme": {
|
||||
"themeByRoomType": {},
|
||||
"eventsThemes": {
|
||||
"Cafeteria_Xmas": {
|
||||
"id": "Cafeteria_Xmas",
|
||||
"type": "Theme",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false,
|
||||
"extraData": {
|
||||
"partsCollectedCount": 10,
|
||||
"IsCraftingInProgress": false,
|
||||
"IsCrafted": true,
|
||||
"IsClaimed": true,
|
||||
"IsClaimedInCraftingRoom": true,
|
||||
"IsNew": true
|
||||
}
|
||||
},
|
||||
"Cafeteria_Halloween": {
|
||||
"id": "Cafeteria_Halloween",
|
||||
"type": "Theme",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false,
|
||||
"extraData": {
|
||||
"partsCollectedCount": 10,
|
||||
"IsCraftingInProgress": false,
|
||||
"IsCrafted": true,
|
||||
"IsClaimed": true,
|
||||
"IsClaimedInCraftingRoom": true,
|
||||
"IsNew": true
|
||||
}
|
||||
},
|
||||
"Cafeteria_ThanksGiving": {
|
||||
"id": "Cafeteria_ThanksGiving",
|
||||
"type": "Theme",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false,
|
||||
"extraData": {
|
||||
"partsCollectedCount": 10,
|
||||
"IsCraftingInProgress": false,
|
||||
"IsCrafted": true,
|
||||
"IsClaimed": true,
|
||||
"IsClaimedInCraftingRoom": true,
|
||||
"IsNew": true
|
||||
}
|
||||
},
|
||||
"LivingQuarters_Xmas": {
|
||||
"id": "LivingQuarters_Xmas",
|
||||
"type": "Theme",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false,
|
||||
"extraData": {
|
||||
"partsCollectedCount": 10,
|
||||
"IsCraftingInProgress": false,
|
||||
"IsCrafted": true,
|
||||
"IsClaimed": true,
|
||||
"IsClaimedInCraftingRoom": true,
|
||||
"IsNew": true
|
||||
}
|
||||
},
|
||||
"LivingQuarters_Halloween": {
|
||||
"id": "LivingQuarters_Halloween",
|
||||
"type": "Theme",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false,
|
||||
"extraData": {
|
||||
"partsCollectedCount": 10,
|
||||
"IsCraftingInProgress": false,
|
||||
"IsCrafted": true,
|
||||
"IsClaimed": true,
|
||||
"IsClaimedInCraftingRoom": true,
|
||||
"IsNew": true
|
||||
}
|
||||
},
|
||||
"LivingQuarters_ThanksGiving": {
|
||||
"id": "LivingQuarters_ThanksGiving",
|
||||
"type": "Theme",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false,
|
||||
"extraData": {
|
||||
"partsCollectedCount": 10,
|
||||
"IsCraftingInProgress": false,
|
||||
"IsCrafted": true,
|
||||
"IsClaimed": true,
|
||||
"IsClaimedInCraftingRoom": true,
|
||||
"IsNew": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"lastOverallTheme": "None"
|
||||
},
|
||||
"dwellers": {
|
||||
"dwellers": [
|
||||
{
|
||||
"serializeId": 3,
|
||||
"name": "Veronique",
|
||||
"lastName": "Perry",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 2916000.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 2,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 3,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": true,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4285552709,
|
||||
"hairColor": 4292039478,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "06",
|
||||
"equipedOutfit": {
|
||||
"id": "RadiationSuit_Advanced",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "PlasmaPistol",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 76,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Normal",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 10,
|
||||
"name": "Theresa",
|
||||
"lastName": "Boyd",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 2916000.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": true,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4294963174,
|
||||
"hairColor": 4294967122,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "22",
|
||||
"equipedOutfit": {
|
||||
"id": "jumpsuit",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "HuntingRifle_Enhanced",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 76,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Normal",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 2,
|
||||
"name": "Nancy",
|
||||
"lastName": "Young",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 2916000.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": true,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4287918423,
|
||||
"hairColor": 4293054406,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "14",
|
||||
"equipedOutfit": {
|
||||
"id": "jumpsuit",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "Fist",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 64,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Normal",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 8,
|
||||
"name": "Ashley",
|
||||
"lastName": "Brooks",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 1.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 2,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 1,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": false,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4294965454,
|
||||
"hairColor": 4291535471,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "22",
|
||||
"equipedOutfit": {
|
||||
"id": "BattleArmor",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "Fist",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": -1,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Normal",
|
||||
"deathTime": -1,
|
||||
"daysOnWasteland": 0,
|
||||
"hoursOnWasteland": 0
|
||||
},
|
||||
{
|
||||
"serializeId": 4,
|
||||
"name": "Nicole",
|
||||
"lastName": "Robinson",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 1.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": false,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4285552709,
|
||||
"hairColor": 4289023019,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "12",
|
||||
"equipedOutfit": {
|
||||
"id": "jumpsuit",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "Fist",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 20,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Normal",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 1,
|
||||
"name": "Ethan",
|
||||
"lastName": "Snow",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 1.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 2,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 72000.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 2,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 1,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": false,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4294896868,
|
||||
"hairColor": 4293440262,
|
||||
"outfitColor": 4294197569,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "14",
|
||||
"equipedOutfit": {
|
||||
"id": "ScribeRobe_Initiate",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "AlienBlaster_Amplified",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 14,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Common",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 9,
|
||||
"name": "Dennis",
|
||||
"lastName": "Johnson",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 2916000.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": -2147483438
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 2,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": false,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4285421123,
|
||||
"hairColor": 4285028691,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "02",
|
||||
"faceMask": "f_hair_08",
|
||||
"equipedOutfit": {
|
||||
"id": "jumpsuit",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "Fist",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 64,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Normal",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 6,
|
||||
"name": "Brenda",
|
||||
"lastName": "Mitchell",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 1.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 72000.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": true,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4285552709,
|
||||
"hairColor": 4294945618,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "02",
|
||||
"equipedOutfit": {
|
||||
"id": "jumpsuit",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "Fist",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 64,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Common",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 11,
|
||||
"name": "Grace",
|
||||
"lastName": "Davidson",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 2916000.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 3600.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": true,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4294963174,
|
||||
"hairColor": 4292039478,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "07",
|
||||
"equipedOutfit": {
|
||||
"id": "jumpsuit",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "Fist",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 76,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Normal",
|
||||
"deathTime": -1
|
||||
},
|
||||
{
|
||||
"serializeId": 7,
|
||||
"name": "Brittany",
|
||||
"lastName": "Miller",
|
||||
"happiness": {
|
||||
"happinessValue": 100.0
|
||||
},
|
||||
"health": {
|
||||
"healthValue": 644.0,
|
||||
"radiationValue": 0.0,
|
||||
"permaDeath": false,
|
||||
"lastLevelUpdated": 50,
|
||||
"maxHealth": 644.0
|
||||
},
|
||||
"experience": {
|
||||
"experienceValue": 2916000.0,
|
||||
"currentLevel": 50,
|
||||
"storage": 0,
|
||||
"accum": 0,
|
||||
"needLvUp": false,
|
||||
"wastelandExperience": 0
|
||||
},
|
||||
"relations": {
|
||||
"relations": [],
|
||||
"partner": -1,
|
||||
"lastPartner": -1,
|
||||
"ascendants": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"gender": 1,
|
||||
"stats": {
|
||||
"stats": [
|
||||
{
|
||||
"value": 1,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 72000.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 0.0
|
||||
},
|
||||
{
|
||||
"value": 99,
|
||||
"mod": 0,
|
||||
"exp": 14400.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"pregnant": true,
|
||||
"babyReady": false,
|
||||
"assigned": false,
|
||||
"sawIncident": false,
|
||||
"WillGoToWasteland": false,
|
||||
"WillBeEvicted": false,
|
||||
"IsEvictedWaitingForFollowers": false,
|
||||
"skinColor": 4294965454,
|
||||
"hairColor": 4283848802,
|
||||
"outfitColor": 4294967295,
|
||||
"pendingExperienceReward": 0,
|
||||
"hair": "07",
|
||||
"equipedOutfit": {
|
||||
"id": "jumpsuit",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"equipedWeapon": {
|
||||
"id": "Fist",
|
||||
"type": "Weapon",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
"savedRoom": 64,
|
||||
"lastChildBorn": -1,
|
||||
"rarity": "Common",
|
||||
"deathTime": -1
|
||||
}
|
||||
],
|
||||
"actors": [],
|
||||
"id": 0,
|
||||
"mrhId": 1,
|
||||
"min_happiness": 0.0
|
||||
},
|
||||
"constructMgr": {
|
||||
"roomDeserializeID": 108
|
||||
},
|
||||
"vault": {
|
||||
"rocks": [
|
||||
{
|
||||
"r": 7,
|
||||
"c": 21
|
||||
},
|
||||
{
|
||||
"r": 7,
|
||||
"c": 4
|
||||
},
|
||||
{
|
||||
"r": 7,
|
||||
"c": 9
|
||||
},
|
||||
{
|
||||
"r": 8,
|
||||
"c": 20
|
||||
},
|
||||
{
|
||||
"r": 8,
|
||||
"c": 8
|
||||
},
|
||||
{
|
||||
"r": 8,
|
||||
"c": 17
|
||||
},
|
||||
{
|
||||
"r": 9,
|
||||
"c": 0
|
||||
},
|
||||
{
|
||||
"r": 9,
|
||||
"c": 19
|
||||
},
|
||||
{
|
||||
"r": 9,
|
||||
"c": 4
|
||||
},
|
||||
{
|
||||
"r": 10,
|
||||
"c": 16
|
||||
},
|
||||
{
|
||||
"r": 10,
|
||||
"c": 19
|
||||
},
|
||||
{
|
||||
"r": 10,
|
||||
"c": 3
|
||||
},
|
||||
{
|
||||
"r": 11,
|
||||
"c": 24
|
||||
},
|
||||
{
|
||||
"r": 11,
|
||||
"c": 17
|
||||
},
|
||||
{
|
||||
"r": 11,
|
||||
"c": 5
|
||||
},
|
||||
{
|
||||
"r": 11,
|
||||
"c": 2
|
||||
},
|
||||
{
|
||||
"r": 12,
|
||||
"c": 1
|
||||
},
|
||||
{
|
||||
"r": 12,
|
||||
"c": 11
|
||||
},
|
||||
{
|
||||
"r": 12,
|
||||
"c": 9
|
||||
},
|
||||
{
|
||||
"r": 12,
|
||||
"c": 16
|
||||
},
|
||||
{
|
||||
"r": 13,
|
||||
"c": 8
|
||||
},
|
||||
{
|
||||
"r": 13,
|
||||
"c": 11
|
||||
},
|
||||
{
|
||||
"r": 13,
|
||||
"c": 2
|
||||
},
|
||||
{
|
||||
"r": 14,
|
||||
"c": 22
|
||||
},
|
||||
{
|
||||
"r": 14,
|
||||
"c": 12
|
||||
},
|
||||
{
|
||||
"r": 14,
|
||||
"c": 20
|
||||
},
|
||||
{
|
||||
"r": 15,
|
||||
"c": 23
|
||||
},
|
||||
{
|
||||
"r": 15,
|
||||
"c": 13
|
||||
},
|
||||
{
|
||||
"r": 15,
|
||||
"c": 9
|
||||
},
|
||||
{
|
||||
"r": 15,
|
||||
"c": 15
|
||||
},
|
||||
{
|
||||
"r": 16,
|
||||
"c": 21
|
||||
},
|
||||
{
|
||||
"r": 16,
|
||||
"c": 9
|
||||
},
|
||||
{
|
||||
"r": 16,
|
||||
"c": 14
|
||||
},
|
||||
{
|
||||
"r": 16,
|
||||
"c": 12
|
||||
},
|
||||
{
|
||||
"r": 16,
|
||||
"c": 24
|
||||
},
|
||||
{
|
||||
"r": 17,
|
||||
"c": 9
|
||||
},
|
||||
{
|
||||
"r": 17,
|
||||
"c": 12
|
||||
},
|
||||
{
|
||||
"r": 18,
|
||||
"c": 12
|
||||
},
|
||||
{
|
||||
"r": 18,
|
||||
"c": 14
|
||||
},
|
||||
{
|
||||
"r": 18,
|
||||
"c": 23
|
||||
},
|
||||
{
|
||||
"r": 18,
|
||||
"c": 2
|
||||
},
|
||||
{
|
||||
"r": 18,
|
||||
"c": 5
|
||||
},
|
||||
{
|
||||
"r": 19,
|
||||
"c": 4
|
||||
},
|
||||
{
|
||||
"r": 19,
|
||||
"c": 0
|
||||
},
|
||||
{
|
||||
"r": 19,
|
||||
"c": 10
|
||||
},
|
||||
{
|
||||
"r": 19,
|
||||
"c": 16
|
||||
},
|
||||
{
|
||||
"r": 19,
|
||||
"c": 23
|
||||
},
|
||||
{
|
||||
"r": 20,
|
||||
"c": 13
|
||||
},
|
||||
{
|
||||
"r": 20,
|
||||
"c": 8
|
||||
},
|
||||
{
|
||||
"r": 20,
|
||||
"c": 17
|
||||
},
|
||||
{
|
||||
"r": 20,
|
||||
"c": 4
|
||||
},
|
||||
{
|
||||
"r": 20,
|
||||
"c": 15
|
||||
},
|
||||
{
|
||||
"r": 21,
|
||||
"c": 9
|
||||
},
|
||||
{
|
||||
"r": 21,
|
||||
"c": 16
|
||||
},
|
||||
{
|
||||
"r": 21,
|
||||
"c": 7
|
||||
},
|
||||
{
|
||||
"r": 21,
|
||||
"c": 19
|
||||
},
|
||||
{
|
||||
"r": 22,
|
||||
"c": 12
|
||||
},
|
||||
{
|
||||
"r": 22,
|
||||
"c": 17
|
||||
},
|
||||
{
|
||||
"r": 22,
|
||||
"c": 10
|
||||
},
|
||||
{
|
||||
"r": 22,
|
||||
"c": 2
|
||||
},
|
||||
{
|
||||
"r": 22,
|
||||
"c": 14
|
||||
},
|
||||
{
|
||||
"r": 23,
|
||||
"c": 7
|
||||
},
|
||||
{
|
||||
"r": 23,
|
||||
"c": 22
|
||||
},
|
||||
{
|
||||
"r": 23,
|
||||
"c": 2
|
||||
},
|
||||
{
|
||||
"r": 23,
|
||||
"c": 13
|
||||
},
|
||||
{
|
||||
"r": 23,
|
||||
"c": 11
|
||||
},
|
||||
{
|
||||
"r": 23,
|
||||
"c": 9
|
||||
},
|
||||
{
|
||||
"r": 24,
|
||||
"c": 20
|
||||
},
|
||||
{
|
||||
"r": 24,
|
||||
"c": 3
|
||||
},
|
||||
{
|
||||
"r": 24,
|
||||
"c": 8
|
||||
},
|
||||
{
|
||||
"r": 24,
|
||||
"c": 16
|
||||
}
|
||||
],
|
||||
"rooms": [
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Entrance",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 2,
|
||||
"row": 0,
|
||||
"col": 3,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 1,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"broken": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "FakeWasteland",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 0,
|
||||
"col": 0,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 2,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Elevator",
|
||||
"class": "Utility",
|
||||
"mergeLevel": 1,
|
||||
"row": 0,
|
||||
"col": 9,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 3,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"withHole": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Elevator",
|
||||
"class": "Utility",
|
||||
"mergeLevel": 1,
|
||||
"row": 1,
|
||||
"col": 9,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 4,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"withHole": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Elevator",
|
||||
"class": "Utility",
|
||||
"mergeLevel": 1,
|
||||
"row": 2,
|
||||
"col": 9,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 5,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"withHole": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "LivingQuarters",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 0,
|
||||
"col": 10,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 226.89
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 6,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"children": [],
|
||||
"partners": []
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Geothermal",
|
||||
"class": "Production",
|
||||
"mergeLevel": 1,
|
||||
"row": 1,
|
||||
"col": 6,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 289.56
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 7,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 100.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Cafeteria",
|
||||
"class": "Production",
|
||||
"mergeLevel": 1,
|
||||
"row": 1,
|
||||
"col": 3,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 186.69
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": 659,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 8,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 64.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "WaterPlant",
|
||||
"class": "Production",
|
||||
"mergeLevel": 1,
|
||||
"row": 1,
|
||||
"col": 0,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 288.2
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": 585,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 9,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 77.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "WaterPlant",
|
||||
"class": "Production",
|
||||
"mergeLevel": 1,
|
||||
"row": 1,
|
||||
"col": 10,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 100.0,
|
||||
"initialValue": 57.71
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 10,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 68.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Storage",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 2,
|
||||
"col": 0,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 247.95
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 13,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "WaterPlant",
|
||||
"class": "Production",
|
||||
"mergeLevel": 2,
|
||||
"row": 2,
|
||||
"col": 3,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 1000.0,
|
||||
"initialValue": 494.38
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [
|
||||
1
|
||||
],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 14,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 7.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 26.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 14.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Cafeteria",
|
||||
"class": "Production",
|
||||
"mergeLevel": 1,
|
||||
"row": 2,
|
||||
"col": 10,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 250.79
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 15,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 70.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Storage",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 2,
|
||||
"col": 13,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 228.82
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 16,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Storage",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 0,
|
||||
"col": 13,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 209.81
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 17,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "LivingQuarters",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 1,
|
||||
"col": 13,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 153.33
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 18,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"children": [],
|
||||
"partners": []
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Geothermal",
|
||||
"class": "Production",
|
||||
"mergeLevel": 1,
|
||||
"row": 0,
|
||||
"col": 16,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 9.82,
|
||||
"initialValue": 191.82
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [
|
||||
4
|
||||
],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "RoomEmergency",
|
||||
"currentState": {
|
||||
"mode": 1,
|
||||
"controllerAdditionnalData": {}
|
||||
},
|
||||
"deserializeID": 20,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 5.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 15.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 51.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "LivingQuarters",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 2,
|
||||
"row": 2,
|
||||
"col": 16,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 1000.0,
|
||||
"initialValue": 420.93
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [
|
||||
6,
|
||||
7,
|
||||
2,
|
||||
9
|
||||
],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Working",
|
||||
"currentState": {
|
||||
"breedingTaskId": 1004
|
||||
},
|
||||
"deserializeID": 64,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"children": [],
|
||||
"partners": [
|
||||
{
|
||||
"m": 1,
|
||||
"f": 10,
|
||||
"s": "RaisingBaby",
|
||||
"ascendants": [
|
||||
1,
|
||||
10,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"maleName": "Ethan",
|
||||
"maleLast": "Snow",
|
||||
"femaleName": "Theresa",
|
||||
"femaleLast": "Boyd",
|
||||
"childColor": 4294963174,
|
||||
"childHairColor": 4294170924,
|
||||
"childRarity": 1,
|
||||
"childStat": [
|
||||
5
|
||||
],
|
||||
"notificationID": -1,
|
||||
"fatherId": 1,
|
||||
"pendingChildren": 0,
|
||||
"templateID": -1,
|
||||
"t": 791
|
||||
},
|
||||
{
|
||||
"m": 1,
|
||||
"f": 3,
|
||||
"s": "RaisingBaby",
|
||||
"ascendants": [
|
||||
1,
|
||||
3,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"maleName": "Ethan",
|
||||
"maleLast": "Snow",
|
||||
"femaleName": "Veronique",
|
||||
"femaleLast": "Perry",
|
||||
"childColor": 4294896868,
|
||||
"childHairColor": 4292707102,
|
||||
"childRarity": 2,
|
||||
"childStat": [
|
||||
5
|
||||
],
|
||||
"notificationID": -1,
|
||||
"fatherId": 1,
|
||||
"pendingChildren": 0,
|
||||
"templateID": -1,
|
||||
"t": 800
|
||||
},
|
||||
{
|
||||
"m": 1,
|
||||
"f": 2,
|
||||
"s": "RaisingBaby",
|
||||
"ascendants": [
|
||||
1,
|
||||
2,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"maleName": "Ethan",
|
||||
"maleLast": "Snow",
|
||||
"femaleName": "Nancy",
|
||||
"femaleLast": "Young",
|
||||
"childColor": 4287918423,
|
||||
"childHairColor": 4293247334,
|
||||
"childRarity": 1,
|
||||
"childStat": [
|
||||
5
|
||||
],
|
||||
"notificationID": -1,
|
||||
"fatherId": 1,
|
||||
"pendingChildren": 0,
|
||||
"templateID": -1,
|
||||
"t": 828
|
||||
},
|
||||
{
|
||||
"m": 1,
|
||||
"f": 11,
|
||||
"s": "RaisingBaby",
|
||||
"ascendants": [
|
||||
1,
|
||||
11,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"maleName": "Ethan",
|
||||
"maleLast": "Snow",
|
||||
"femaleName": "Grace",
|
||||
"femaleLast": "Davidson",
|
||||
"childColor": 4294897125,
|
||||
"childHairColor": 4293440262,
|
||||
"childRarity": 2,
|
||||
"childStat": [
|
||||
5
|
||||
],
|
||||
"notificationID": -1,
|
||||
"fatherId": 1,
|
||||
"pendingChildren": 0,
|
||||
"templateID": -1,
|
||||
"t": 843
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Elevator",
|
||||
"class": "Utility",
|
||||
"mergeLevel": 1,
|
||||
"row": 2,
|
||||
"col": 22,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 66,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"withHole": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Elevator",
|
||||
"class": "Utility",
|
||||
"mergeLevel": 1,
|
||||
"row": 3,
|
||||
"col": 22,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 67,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"withHole": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Elevator",
|
||||
"class": "Utility",
|
||||
"mergeLevel": 1,
|
||||
"row": 3,
|
||||
"col": 9,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 68,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"withHole": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Elevator",
|
||||
"class": "Utility",
|
||||
"mergeLevel": 1,
|
||||
"row": 4,
|
||||
"col": 9,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 69,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"withHole": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "LivingQuarters",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 2,
|
||||
"col": 23,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 500.0,
|
||||
"initialValue": 212.86
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 70,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"children": [],
|
||||
"partners": []
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "LivingQuarters",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 2,
|
||||
"row": 0,
|
||||
"col": 19,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Working",
|
||||
"currentState": {
|
||||
"breedingTaskId": 1005
|
||||
},
|
||||
"deserializeID": 72,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"children": [],
|
||||
"partners": [
|
||||
{
|
||||
"m": 1,
|
||||
"f": 6,
|
||||
"s": "RaisingBaby",
|
||||
"ascendants": [
|
||||
1,
|
||||
6,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"maleName": "Ethan",
|
||||
"maleLast": "Snow",
|
||||
"femaleName": "Brenda",
|
||||
"femaleLast": "Mitchell",
|
||||
"childColor": 4285552709,
|
||||
"childHairColor": 4293440262,
|
||||
"childRarity": 3,
|
||||
"childStat": [
|
||||
5
|
||||
],
|
||||
"notificationID": -1,
|
||||
"fatherId": 1,
|
||||
"pendingChildren": 0,
|
||||
"templateID": -1,
|
||||
"t": 652
|
||||
},
|
||||
{
|
||||
"m": 1,
|
||||
"f": 7,
|
||||
"s": "RaisingBaby",
|
||||
"ascendants": [
|
||||
1,
|
||||
7,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"maleName": "Ethan",
|
||||
"maleLast": "Snow",
|
||||
"femaleName": "Brittany",
|
||||
"femaleLast": "Miller",
|
||||
"childColor": 4294898393,
|
||||
"childHairColor": 4283848802,
|
||||
"childRarity": 1,
|
||||
"childStat": [
|
||||
5
|
||||
],
|
||||
"notificationID": -1,
|
||||
"fatherId": 1,
|
||||
"pendingChildren": 0,
|
||||
"templateID": -1,
|
||||
"t": 658
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Geothermal",
|
||||
"class": "Production",
|
||||
"mergeLevel": 2,
|
||||
"row": 3,
|
||||
"col": 10,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 1000.0,
|
||||
"initialValue": 338.75
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 75,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 7.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 23.92,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 18.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "LivingQuarters",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 3,
|
||||
"row": 1,
|
||||
"col": 16,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 1000.0,
|
||||
"initialValue": 505.76
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 2,
|
||||
"dwellers": [
|
||||
11,
|
||||
3,
|
||||
10
|
||||
],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Working",
|
||||
"currentState": {
|
||||
"breedingTaskId": 1006
|
||||
},
|
||||
"deserializeID": 76,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"children": [],
|
||||
"partners": []
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "Cafeteria",
|
||||
"class": "Production",
|
||||
"mergeLevel": 2,
|
||||
"row": 3,
|
||||
"col": 16,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 0.0
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 3,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 79,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"numberOfProductionCycle": 0.0,
|
||||
"ExperienceRewardIsDirty": false
|
||||
},
|
||||
{
|
||||
"emergencyDone": false,
|
||||
"type": "LivingQuarters",
|
||||
"class": "Facility",
|
||||
"mergeLevel": 1,
|
||||
"row": 4,
|
||||
"col": 10,
|
||||
"power": true,
|
||||
"roomHealth": {
|
||||
"damageValue": 0.0,
|
||||
"initialValue": 97.14
|
||||
},
|
||||
"mrHandyList": [],
|
||||
"rushTask": -1,
|
||||
"level": 1,
|
||||
"dwellers": [],
|
||||
"deadDwellers": [],
|
||||
"currentStateName": "Idle",
|
||||
"currentState": {},
|
||||
"deserializeID": 80,
|
||||
"assignedDecoration": "",
|
||||
"roomVisibility": false,
|
||||
"roomOutline": false,
|
||||
"children": [],
|
||||
"partners": []
|
||||
}
|
||||
],
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 1388.0,
|
||||
"Food": 9999.0,
|
||||
"Energy": 9999.0,
|
||||
"Water": 9999.0,
|
||||
"StimPack": 9999999.0,
|
||||
"RadAway": 9999999.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"inventory": {
|
||||
"items": [
|
||||
{
|
||||
"id": "PrinceSpecial",
|
||||
"type": "Outfit",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
{
|
||||
"id": "ChemistrySet",
|
||||
"type": "Junk",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
},
|
||||
{
|
||||
"id": "TeddyBear",
|
||||
"type": "Junk",
|
||||
"hasBeenAssigned": false,
|
||||
"hasRandonWeaponBeenAssigned": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"emergencyData": {
|
||||
"active": true,
|
||||
"cicleTaskId": 1002,
|
||||
"mode": 1,
|
||||
"consumedFood": 0.0,
|
||||
"consumedEnergy": 0.0,
|
||||
"consumedWater": 0.0,
|
||||
"emergencyConsumption": "VaultEmergencyConsumption",
|
||||
"randomEventTaskId": 1
|
||||
},
|
||||
"roomConsumption": {
|
||||
"taskIdOnline": 2,
|
||||
"taskIDShutDown": 3
|
||||
},
|
||||
"dwellerWaterConsumption": {
|
||||
"taskIdOnline": 4
|
||||
},
|
||||
"dwellerFoodConsumption": {
|
||||
"taskIdOnline": 5
|
||||
},
|
||||
"lunchboxRandomGenerator": "0001000000FFFFFFFF010000000000000004010000000D53797374656D2E52616E646F6D0300000005696E65787406696E65787470095365656441727261790000070808081D0000000500000009020000000F02000000380000000800000000A86D7720564E67678775DE4BC9BF60332CE773262BACCA3AD512971CDDBEC668EC8AAE737EDDF634C20480758D7BB625CC8B7548F4EB9D2602AA5766D9670E18F7DE7A013C12C1268ECEB11A8F170F0F8760AF0CB85A3E4886546A15C2484029418F1936FEBB737290E6125214A6EF5FDD89B24FDC0C3E7686EED13D80C2623592D8422C986AFE5498D7D316D3F17A3E0DD98A17F809386912D1A01431856542303FC14D7368BB41CA7CD666DB85560C5E42F53D76058768011B86758457F138AADCB767F821A45DA050206FA80C671EB2481C63692F5E5265401B160B",
|
||||
"LunchBoxesByType": [],
|
||||
"LunchBoxesCount": 0,
|
||||
"VaultName": "652",
|
||||
"VaultMode": "Normal",
|
||||
"VaultTheme": 0,
|
||||
"Achievements": {
|
||||
"objectivesInProgress": [
|
||||
{
|
||||
"objectiveID": "rush_success_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "rush_success_01",
|
||||
"satisfied": false,
|
||||
"rushCount": 29
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "merge_power_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "merge_power_01",
|
||||
"satisfied": false,
|
||||
"higherMergeLevelFound": 2
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "wasteland_kill_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "wasteland_kill_01",
|
||||
"satisfied": false,
|
||||
"currentCreatures": 37
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "merge_food_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "merge_food_01",
|
||||
"satisfied": false,
|
||||
"higherMergeLevelFound": 2
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "merge_water_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "merge_water_01",
|
||||
"satisfied": false,
|
||||
"higherMergeLevelFound": 2
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "make_baby_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "make_baby_01",
|
||||
"satisfied": false,
|
||||
"currentBabies": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "upgrade_room_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "upgrade_room_01",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 19
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "build_nukacola_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "build_nukacola_01",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "build_rooms_02",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "build_rooms_02",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 26
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "stop_raider_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "stop_raider_01",
|
||||
"satisfied": false,
|
||||
"currentInvasions": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "build_each_rooms_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_casino",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_storage",
|
||||
"satisfied": true,
|
||||
"acceptedRoom": 3
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_nukeCola",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_superRoom2",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_hydroponic",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_scienceLab",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_medBay",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_classroom",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_armory",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_radio",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_water2",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_energy2",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_gym",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_bar",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_dojo",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_livingquarters",
|
||||
"satisfied": true,
|
||||
"acceptedRoom": 11
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_geothermal",
|
||||
"satisfied": true,
|
||||
"acceptedRoom": 4
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_cafeteria",
|
||||
"satisfied": true,
|
||||
"acceptedRoom": 4
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_waterplant",
|
||||
"satisfied": true,
|
||||
"acceptedRoom": 4
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_overseer",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_weaponfactory",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_outfitfactory",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_designfactory",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "build_each_rooms_01_barbershop",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "completed_objectives_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "completed_objectives_01",
|
||||
"satisfied": false,
|
||||
"numberOfObjectivesCompleted": 17
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "collect_legendary_dwellers_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "collect_legendary_dwellers_01",
|
||||
"satisfied": false,
|
||||
"currentLegendaryDwellers": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "collect_legendary_outfits_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "collect_legendary_outfits_01",
|
||||
"satisfied": false,
|
||||
"currentLegendaryOutfits": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "collect_legendary_weapons_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "collect_legendary_weapons_01",
|
||||
"satisfied": false,
|
||||
"currentLegendaryWeapons": 1
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "complete_quests_10",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "complete_quests_10",
|
||||
"satisfied": false,
|
||||
"currentNumberQuestsCompleted": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "complete_quests_30",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "complete_quests_30",
|
||||
"satisfied": false,
|
||||
"currentNumberQuestsCompleted": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "complete_quests_60",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "complete_quests_60",
|
||||
"satisfied": false,
|
||||
"currentNumberQuestsCompleted": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "complete_quests_100",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "complete_quests_100",
|
||||
"satisfied": false,
|
||||
"currentNumberQuestsCompleted": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "barbershop_10",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "barbershop_10",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "craft_10_weapons",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "craft_10_weapons",
|
||||
"satisfied": false,
|
||||
"currentNumberItems": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "craft_10_outfits",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "craft_10_outfits",
|
||||
"satisfied": false,
|
||||
"currentNumberItems": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "craft_outfit_weapon_theme",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "craft_outfit",
|
||||
"satisfied": false,
|
||||
"currentNumberItems": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "craft_weapon",
|
||||
"satisfied": false,
|
||||
"currentNumberItems": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "craft_theme",
|
||||
"satisfied": false,
|
||||
"currentNumberItems": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "scrap_items_500",
|
||||
"satisfied": false,
|
||||
"currentNumberItems": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "collect_theme_all_parts_1",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "collect_theme_all_parts_1",
|
||||
"satisfied": false,
|
||||
"currentAllThemeParts": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "collect_theme_all_parts_4",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "collect_theme_all_parts_4",
|
||||
"satisfied": false,
|
||||
"currentAllThemeParts": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "quest_dialog_choices_01",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "quest_dialog_choices_01",
|
||||
"satisfied": false,
|
||||
"currentNumberQuestDialogChoicesMade": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "craft_themes_8",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "craft_themes_8",
|
||||
"satisfied": false,
|
||||
"currentNumberItems": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "kill_on_quests_500",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "kill_on_quests_500",
|
||||
"satisfied": false,
|
||||
"currentNumberQuestEnemiesToKill": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "stimpacks_100_radaway_100",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "stimpack_100",
|
||||
"satisfied": false,
|
||||
"currentNumberLoot": 0
|
||||
},
|
||||
{
|
||||
"requirementID": "radaway_100",
|
||||
"satisfied": false,
|
||||
"currentNumberLoot": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "boss_kill_10",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "boss_kill_10",
|
||||
"satisfied": false,
|
||||
"currentNumberQuestEnemiesToKill": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "build_rooms_stat",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "build_rooms_stat",
|
||||
"satisfied": false,
|
||||
"acceptedRoom": 26
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "collect_caps_stat",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "collect_caps_stat",
|
||||
"satisfied": false,
|
||||
"nukaCount": 41323.0,
|
||||
"isAchievement": true
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
}
|
||||
],
|
||||
"completed": [
|
||||
"levelup_dweller_01",
|
||||
"collect_caps_01",
|
||||
"levelup_dweller_02",
|
||||
"levelup_dweller_03",
|
||||
"collect_caps_02",
|
||||
"build_rooms_01"
|
||||
]
|
||||
},
|
||||
"wasteland": {
|
||||
"state": {
|
||||
"name": "Running"
|
||||
},
|
||||
"teams": [
|
||||
{
|
||||
"dwellers": [
|
||||
8
|
||||
],
|
||||
"returnTripDuration": 593.5,
|
||||
"elapsedTimeAliveExploring": 1187,
|
||||
"elapsedReturningTime": 527,
|
||||
"teamIndex": 0,
|
||||
"teamType": "Explore",
|
||||
"status": "ReturningToVault",
|
||||
"logs": [
|
||||
"0000@l2W",
|
||||
"0000@l44",
|
||||
"0001@l5#l8",
|
||||
"0001@l9",
|
||||
"0001@lA",
|
||||
"0001@l2a#s10@l2f#r025",
|
||||
"0002@l2c#r0297",
|
||||
"0002@l1b#l1u",
|
||||
"0002@l2D",
|
||||
"0002@l1w",
|
||||
"0002@l2e#s1@l2a#s915",
|
||||
"0003@l1Z#l1m",
|
||||
"0003@l1v",
|
||||
"0003@l1o",
|
||||
"0003@l2a#s255",
|
||||
"0005@l1a#l1q",
|
||||
"0005@l25",
|
||||
"0005@l1s",
|
||||
"0005@l2a#s285",
|
||||
"0006@l1Y#l1i",
|
||||
"0006@l1n",
|
||||
"0006@l1k",
|
||||
"0006@l2a#s225",
|
||||
"0008@ll#ls",
|
||||
"0008@lt",
|
||||
"0008@lu",
|
||||
"0008@l2a#s35",
|
||||
"0009@l1Z#l1q",
|
||||
"0009@l29",
|
||||
"0009@l1s",
|
||||
"0009@l2a#s285",
|
||||
"0010@l1X#l1i",
|
||||
"0010@l1n",
|
||||
"0010@l1k",
|
||||
"0010@l2a#s225",
|
||||
"0011@l1b#l1q",
|
||||
"0011@l29",
|
||||
"0011@l1s",
|
||||
"0011@l2a#s285",
|
||||
"0011@l2k#io6",
|
||||
"0012@l1c#l1e",
|
||||
"0012@l1f",
|
||||
"0012@l1g",
|
||||
"0012@l2a#s200",
|
||||
"0013@lh#lo",
|
||||
"0013@lp",
|
||||
"0013@lq",
|
||||
"0013@l2a#s25",
|
||||
"0014@l1Y#l1q",
|
||||
"0014@l29",
|
||||
"0014@l1s",
|
||||
"0014@l2a#s285",
|
||||
"0017@l0#s0",
|
||||
"0017@l2c#r0792",
|
||||
"0017@l1a#l1e",
|
||||
"0017@l1j",
|
||||
"0017@l1g",
|
||||
"0017@l2a#s200",
|
||||
"0019@l1Z#l1q",
|
||||
"0019@l25",
|
||||
"0019@l1s",
|
||||
"0019@l2a#s285"
|
||||
],
|
||||
"missedEncounters": 0,
|
||||
"introMessages": 1,
|
||||
"notificationID": -1,
|
||||
"notificationQuestArrivalID": -1,
|
||||
"isForceReturningToVault": false,
|
||||
"isSkippingTime": false,
|
||||
"isDoingQuest": false,
|
||||
"questSucceeded": false,
|
||||
"questDone": false,
|
||||
"teamEquipment": {
|
||||
"storage": {
|
||||
"resources": {
|
||||
"Nuka": 1114.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 25.0,
|
||||
"RadAway": 25.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"bonus": {
|
||||
"Nuka": 0.0,
|
||||
"Food": 0.0,
|
||||
"Energy": 0.0,
|
||||
"Water": 0.0,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
}
|
||||
},
|
||||
"inventory": {
|
||||
"items": []
|
||||
},
|
||||
"dwellers": [],
|
||||
"questClues": [],
|
||||
"collectedThemes": {
|
||||
"themeList": []
|
||||
}
|
||||
},
|
||||
"questteamQuestSeed": -1,
|
||||
"retryCount": 0,
|
||||
"questOverallPerformance": {
|
||||
"numberCombatsWon": 0,
|
||||
"numberCriticalHitsPerformed": 0,
|
||||
"numberPerfectCriticalHitsPerformed": 0,
|
||||
"numberContainersCollected": 0,
|
||||
"numberCapsCollected": 0,
|
||||
"numberLevelsGained": 0,
|
||||
"numberLevelsGainedWithBonus": 0
|
||||
},
|
||||
"actors": [],
|
||||
"initialItems": [
|
||||
{
|
||||
"initWeapon": "Fist",
|
||||
"initOutfit": "jumpsuit",
|
||||
"initPet": ""
|
||||
}
|
||||
],
|
||||
"postQuestStimpakDifference": 0,
|
||||
"postQuestRadawayDifference": 0,
|
||||
"initialRadDamage": [
|
||||
0.0
|
||||
]
|
||||
}
|
||||
],
|
||||
"cycles": [
|
||||
{
|
||||
"cycleType": "Radiation",
|
||||
"taskId": 213
|
||||
},
|
||||
{
|
||||
"cycleType": "Experience",
|
||||
"taskId": 214
|
||||
},
|
||||
{
|
||||
"cycleType": "NukaCaps",
|
||||
"taskId": 215
|
||||
},
|
||||
{
|
||||
"cycleType": "Encounters",
|
||||
"taskId": 216,
|
||||
"pendingCycles": [],
|
||||
"teamEncounters": [
|
||||
{
|
||||
"teamEncounters": [
|
||||
{
|
||||
"nonRepeatable": [],
|
||||
"poolType": "Creatures"
|
||||
},
|
||||
{
|
||||
"nonRepeatable": [
|
||||
"Location2",
|
||||
"Location1"
|
||||
],
|
||||
"poolType": "Location"
|
||||
},
|
||||
{
|
||||
"nonRepeatable": [
|
||||
"NPC1"
|
||||
],
|
||||
"poolType": "NPC"
|
||||
}
|
||||
],
|
||||
"teamID": 8
|
||||
}
|
||||
],
|
||||
"inProgress": []
|
||||
},
|
||||
{
|
||||
"cycleType": "Item",
|
||||
"taskId": 217,
|
||||
"pendingCycles": []
|
||||
},
|
||||
{
|
||||
"cycleType": "Speech",
|
||||
"taskId": 218
|
||||
},
|
||||
{
|
||||
"cycleType": "Junk",
|
||||
"taskId": 219,
|
||||
"pendingCycles": [],
|
||||
"teamEncounters": [
|
||||
{
|
||||
"teamEncounters": [
|
||||
{
|
||||
"nonRepeatable": [],
|
||||
"poolType": "JunkCycle_Location"
|
||||
}
|
||||
],
|
||||
"teamID": 8
|
||||
}
|
||||
],
|
||||
"inProgress": []
|
||||
}
|
||||
],
|
||||
"mrHandyCycles": [
|
||||
{
|
||||
"cycleType": "Speech",
|
||||
"taskId": 220
|
||||
},
|
||||
{
|
||||
"cycleType": "NukaCaps",
|
||||
"taskId": 221
|
||||
}
|
||||
],
|
||||
"questCycles": [],
|
||||
"allTimeTeamsCounter": 9,
|
||||
"lastSurpriseQuest": "",
|
||||
"lastSurprisePopupTime": -1.0
|
||||
}
|
||||
},
|
||||
"dwellerSpawner": {
|
||||
"dwellersWaiting": []
|
||||
},
|
||||
"deviceName": "DESKTOP-08TF5K6",
|
||||
"tutorialManager": {
|
||||
"phase": "Phase5",
|
||||
"taskNumber": 0,
|
||||
"objectivesTutorialMessage": true,
|
||||
"lunchboxTutorialMessage": true,
|
||||
"showingObjectiveTutorialMessage": false,
|
||||
"showingLunchboxTutorialMessage": false,
|
||||
"showWastelandMessageTime": 300.0,
|
||||
"showExploreWastelandMessageTime": 10.0,
|
||||
"exploreWastelandMessageShown": true,
|
||||
"skippedTutorial": 0,
|
||||
"questTutorialCompleted": 0,
|
||||
"intialTimerTasks": [],
|
||||
"ContextualVaultTecObjectives": false,
|
||||
"ContextualAddFriends": false,
|
||||
"ContextualWasteland": true,
|
||||
"ContextualRadioRoom": false,
|
||||
"ContextualWeaponsAndOutfits": true,
|
||||
"ContextualTrainDweller": false,
|
||||
"ContextualBabies": true,
|
||||
"ContextualDestroyRocks": true,
|
||||
"ContextualStorage": true,
|
||||
"ContextualNoRoomForDwellers": true,
|
||||
"ContextualUnequipedDweller": true,
|
||||
"ContextualBuildAnElevator": false,
|
||||
"ContextualDestroyRockToBuild": false,
|
||||
"ContextualNoBuildZonesAvailableByRock": false,
|
||||
"ContextualDestroyRockToAccessNextFloor": false,
|
||||
"ContextualResourcesAlert": false,
|
||||
"ContextualIncidentOcurs": true,
|
||||
"ContextualLowPowerAlert": false,
|
||||
"ContextualStorageFull": false,
|
||||
"ContextualMergeOrUpgradeRoom": true,
|
||||
"ContextualWastelandMessage": true,
|
||||
"ContextualObjectivesCompleted": true,
|
||||
"ContextualBabiesTutorial": true,
|
||||
"ContextualStimpackMessage": false,
|
||||
"ContextualLunchboxTutorial": true,
|
||||
"ContextualRadwayMessage": false,
|
||||
"ContextualRoomMerge2": true,
|
||||
"ContextualRoomMerge3": true,
|
||||
"ContextualStorage2": false,
|
||||
"ContextualEquippingItemsWeapon": false,
|
||||
"ContextualLuck": true,
|
||||
"ContextualEquppingItemsPet": false,
|
||||
"ContextualCrafting": false,
|
||||
"ContextualDecorations": false,
|
||||
"ContextualRequestJunk": false,
|
||||
"ContextualJunk": true,
|
||||
"ContextualTriggeredBirth": false,
|
||||
"ContextualInventoryFull": false,
|
||||
"ContextualInventoryFullWindow": false,
|
||||
"ContextualJunkGiveAway": false,
|
||||
"ContextualScrapping": false,
|
||||
"ContextualAssignWith3DTouch": false,
|
||||
"ContextualNukaQuantum": true,
|
||||
"ContextualSurpriseQuests": false,
|
||||
"ContextualReturningFromQuests": false,
|
||||
"ContextualRadioRoomToggle": false,
|
||||
"ContextualCraftTheme": false,
|
||||
"ContextualJoystickNavigationInVault": false,
|
||||
"MaleTasksQuant": 0,
|
||||
"FemaleTasksQuant": 0
|
||||
},
|
||||
"objectiveMgr": {
|
||||
"taskID": 8,
|
||||
"canDiscard": true,
|
||||
"nukaQuantumIncrement": 0,
|
||||
"shuffleBags": [
|
||||
[
|
||||
"QuestPerformPerfectCriticalHit1",
|
||||
"CollectRareWeapons1",
|
||||
"QuestPerformCriticalHit1_Survival",
|
||||
"KillRandomEnemyUnarmedHardcore1",
|
||||
"StopMoleratWithoutPropagate1",
|
||||
"EquipRandomWeapon",
|
||||
"RushRoom1",
|
||||
"RaiseSpecificSpecialLevel1",
|
||||
"Radaway1",
|
||||
"ExtinguishFireHardcore1",
|
||||
"CraftRareOutfits1",
|
||||
"UpgradeRoom1",
|
||||
"QuestWinBattles1",
|
||||
"CollectWeapons1",
|
||||
"SurviveMoleratNoCasualtiesHardcore1",
|
||||
"KillDeathclawAtVaultDoor1",
|
||||
"RushRoomHardcore1",
|
||||
"SellJunk1",
|
||||
"Outfits1",
|
||||
"Food1",
|
||||
"Water1_Survival",
|
||||
"QuestWinBattles1_Survival",
|
||||
"BaldDwellersInVault",
|
||||
"StopIncidentsHardcore1",
|
||||
"SurviveMoleratNoCasualties1",
|
||||
"CollectFoodWithinOneMin1",
|
||||
"KillCreatureHardcore1",
|
||||
"RightRoom1",
|
||||
"ExploreWastelandHours1_Survival",
|
||||
"CollectPowerWithinOneMin1",
|
||||
"Stimpack1",
|
||||
"KillCreature1",
|
||||
"CraftWeapons1",
|
||||
"SurviveRadscorpionNoCasualties1_Survival",
|
||||
"RaiseSpecialLevel1",
|
||||
"CraftOutfits1",
|
||||
"Power1",
|
||||
"MysteriousStranger1",
|
||||
"SurviveDeathclawNoCasualties1_Survival",
|
||||
"Water1",
|
||||
"Babies1",
|
||||
"SurviveGhoulNoCasualties1_Survival",
|
||||
"KillCreature1_Survival",
|
||||
"CraftRareWeapons1",
|
||||
"SurviveDeathclawNoCasualtiesHardcore1",
|
||||
"ScrapItems1",
|
||||
"StopRadroachWithoutPropagate1",
|
||||
"WastelandLevelUp1",
|
||||
"CollectOutfitsHardcore1",
|
||||
"CollectRareOutfits1",
|
||||
"Wasteland1",
|
||||
"CollectOutfits1",
|
||||
"Food1_Survival",
|
||||
"CollectWeaponsHardcore1",
|
||||
"QuestPerformPerfectCriticalHit1_Survival",
|
||||
"DwellerHappy1",
|
||||
"ExploreWastelandHoursWithoutRadaway1",
|
||||
"MakeFriend1",
|
||||
"RushRoom1_Survival",
|
||||
"BarberShopUse1",
|
||||
"WastelandCollectCaps1",
|
||||
"CollectCaps1",
|
||||
"Weapons1",
|
||||
"SurviveGhoulNoCasualties1",
|
||||
"SurviveRadscorpionNoCasualties1",
|
||||
"QuestCollectCaps1",
|
||||
"SurviveMoleratNoCasualties1_Survival",
|
||||
"RandomEnemyKilledUnarmed1_Survival",
|
||||
"StimpackHardcore1",
|
||||
"CompleteQuestInWasteland1",
|
||||
"CollectJunk1",
|
||||
"QuestCollectContainers1_Survival",
|
||||
"SurviveHoursNoCasualties1",
|
||||
"WastelandWithPet1",
|
||||
"LevelUp1",
|
||||
"StopIncidents1_Survival",
|
||||
"CollectPets1",
|
||||
"QuestCollectContainers1",
|
||||
"Couple1",
|
||||
"QuestCollectCaps1_Survival",
|
||||
"DwellerHappy1_Survival",
|
||||
"CollectWaterWithinOneMin1",
|
||||
"KillRaiderAtVaultDoor1",
|
||||
"ExploreLocation1",
|
||||
"ExtinguishFire1",
|
||||
"OutfitsHardcore1",
|
||||
"QuestPerformCriticalHit1",
|
||||
"RandomEnemyKilledUnarmed",
|
||||
"CompleteQuestInOverseer1",
|
||||
"CompleteQuestInWasteland1_Survival",
|
||||
"WeaponsHardcore1",
|
||||
"CompleteQuestInOverseer1_Survival",
|
||||
"MergeTwoRooms1",
|
||||
"SellItemHarcore1",
|
||||
"StopIncidents1",
|
||||
"SurviveDeathclawNoCasualties1"
|
||||
],
|
||||
[
|
||||
"WeaponsHardcore2",
|
||||
"StopMoleratWithoutPropagate2",
|
||||
"Power2_Survival",
|
||||
"EquipRandomWeapon2",
|
||||
"QuestCollectContainers2_Survival",
|
||||
"SurviveRadscorpionNoCasualties2",
|
||||
"QuestPerformCriticalHit2_Survival",
|
||||
"KillRaiderAtVaultDoor2",
|
||||
"CollectFoodWithinOneMin2",
|
||||
"ExploreWastelandHoursWithoutRadaway2",
|
||||
"RandomEnemyKilledUnarmed2_Survival",
|
||||
"LevelUp2",
|
||||
"ExtinguishFireHardcore2",
|
||||
"Outfits2",
|
||||
"StopRadroachWithoutPropagate2",
|
||||
"ExploreLocation2",
|
||||
"WastelandWithPet2",
|
||||
"QuestWinBattles2",
|
||||
"QuestPerformPerfectCriticalHit2_Survival",
|
||||
"SurviveMoleratNoCasualties2",
|
||||
"Weapons2",
|
||||
"StopIncidents2_Survival",
|
||||
"QuestPerformCriticalHit2",
|
||||
"StopIncidents2",
|
||||
"CollectWeapons2",
|
||||
"WastelandCollectCaps2",
|
||||
"CollectPets2",
|
||||
"Couple2",
|
||||
"SurviveMoleratNoCasualties2_Survival",
|
||||
"CompleteQuestInWasteland2_Survival",
|
||||
"KillDeathclawAtVaultDoor2",
|
||||
"DwellerHappy2",
|
||||
"SurviveHoursNoCasualties2",
|
||||
"CollectCaps2",
|
||||
"RightRoom2",
|
||||
"CollectOutfits2",
|
||||
"KillCreature2",
|
||||
"Pregnant2",
|
||||
"RaiseSpecificSpecialLevel2",
|
||||
"BaldDwellersInVault2",
|
||||
"SurviveGhoulNoCasualties2",
|
||||
"Water2_Survival",
|
||||
"ExploreWastelandHours2",
|
||||
"SellJunk2",
|
||||
"WastelandLevelUp2",
|
||||
"CollectWaterWithinOneMin2",
|
||||
"CraftRareWeapons2",
|
||||
"QuestWinBattles2_Survival",
|
||||
"Water2",
|
||||
"OutfitsHardcore2",
|
||||
"MergeTwoRooms2",
|
||||
"Food2_Survival",
|
||||
"CollectOutfitsHardcore2",
|
||||
"SurviveGhoulNoCasualties2_Survival",
|
||||
"SellItemHarcore2",
|
||||
"SurviveDeathclawNoCasualties2",
|
||||
"RushRoomHardcore2",
|
||||
"CollectPowerWithinOneMin2",
|
||||
"CompleteQuestInOverseer2",
|
||||
"CraftRareOutfits2",
|
||||
"RushRoom2",
|
||||
"CollectRareOutfits2",
|
||||
"QuestCollectCaps2_Survival",
|
||||
"QuestCollectContainers2",
|
||||
"MysteriousStranger2",
|
||||
"BarberShopUse2",
|
||||
"UpgradeRoom2",
|
||||
"SurviveMoleratNoCasualtiesHardcore2",
|
||||
"Babies2",
|
||||
"SurviveDeathclawNoCasualtiesHardcore2",
|
||||
"CollectWeaponsHardcore2",
|
||||
"CollectRareWeapons2",
|
||||
"SurviveDeathclawNoCasualties2_Survival",
|
||||
"CraftWeapons2",
|
||||
"SurviveRadscorpionNoCasualties2_Survival",
|
||||
"MakeFriend2",
|
||||
"RushRoom2_Survival",
|
||||
"StopIncidentsHardcore2",
|
||||
"KillCreatureHardcore2",
|
||||
"CollectJunk2",
|
||||
"QuestCollectCaps2",
|
||||
"ExploreWastelandHours2_Survival",
|
||||
"CompleteQuestInOverseer2_Survival",
|
||||
"Power2",
|
||||
"ExtinguishFire2",
|
||||
"KillRandomEnemyUnarmedHardcore2",
|
||||
"Radaway2",
|
||||
"RaiseSpecialLevel2",
|
||||
"ScrapItems2",
|
||||
"Stimpack2",
|
||||
"QuestPerformPerfectCriticalHit2",
|
||||
"StimpackHardcore2",
|
||||
"Wasteland2",
|
||||
"RandomEnemyKilledUnarmed2",
|
||||
"CompleteQuestInWasteland2",
|
||||
"CraftOutfits2"
|
||||
],
|
||||
[
|
||||
"QuestPerformCriticalHit3_Survival",
|
||||
"KillCreatureHardcore3",
|
||||
"CompleteQuestInOverseer3",
|
||||
"WastelandWithPet3",
|
||||
"QuestCollectCaps3_Survival",
|
||||
"BaldDwellersInVault3",
|
||||
"KillRaiderAtVaultDoor3",
|
||||
"CompleteQuestInWasteland3",
|
||||
"EquipRandomWeapon3",
|
||||
"Radaway3",
|
||||
"CollectOutfits3",
|
||||
"DwellerHappy3_Survival",
|
||||
"Wasteland3",
|
||||
"QuestPerformPerfectCriticalHit3",
|
||||
"SurviveMoleratNoCasualtiesHardcore3",
|
||||
"RightRoom3",
|
||||
"UpgradeRoom3",
|
||||
"DwellerHappy3",
|
||||
"CraftRareWeapons3",
|
||||
"CollectWaterWithinOneMin3",
|
||||
"OutfitsHardcore3",
|
||||
"SurviveRadscorpionNoCasualties3_Survival",
|
||||
"ExploreLocation3",
|
||||
"RaiseSpecialLevel3",
|
||||
"QuestPerformPerfectCriticalHit3_Survival",
|
||||
"Food3_Survival",
|
||||
"StopRadroachWithoutPropagate3",
|
||||
"RushRoom3_Survival",
|
||||
"CollectPowerWithinOneMin3",
|
||||
"CollectJunk3",
|
||||
"StopIncidents3_Survival",
|
||||
"StopMoleratWithoutPropagate3",
|
||||
"OutfitsT1",
|
||||
"KillRandomEnemyUnarmedHardcore3",
|
||||
"MakeFriend3",
|
||||
"Outfits3",
|
||||
"QuestCollectContainers3_Survival",
|
||||
"Stimpack3",
|
||||
"RaiseSpecificSpecialLevel3",
|
||||
"ExtinguishFire3",
|
||||
"CollectPets3",
|
||||
"Water3_Survival",
|
||||
"LevelUp3",
|
||||
"CraftWeapons3",
|
||||
"SellJunk3",
|
||||
"SurviveDeathclawNoCasualties3_Survival",
|
||||
"WastelandLevelUp3",
|
||||
"ExtinguishFireHardcore3",
|
||||
"CollectCaps3",
|
||||
"KillCreature3_Survival",
|
||||
"RushRoomHardcore3",
|
||||
"QuestCollectContainers3",
|
||||
"SurviveMoleratNoCasualties3",
|
||||
"QuestWinBattles3",
|
||||
"KillDeathclawAtVaultDoor3",
|
||||
"StimpackHardcore3",
|
||||
"CollectFoodWithinOneMin3",
|
||||
"SurviveDeathclawNoCasualtiesHardcore3",
|
||||
"StopIncidents3",
|
||||
"Pregnant3",
|
||||
"Power3_Survival",
|
||||
"SurviveGhoulNoCasualties3",
|
||||
"CollectWeaponsHardcore3",
|
||||
"SurviveHoursNoCasualties3",
|
||||
"ExploreWastelandHoursWithoutRadaway3",
|
||||
"ExploreWastelandHours3",
|
||||
"ExploreWastelandHours3_Survival",
|
||||
"SellItemHarcore3",
|
||||
"SurviveDeathclawNoCasualties3",
|
||||
"CompleteQuestInOverseer3_Survival",
|
||||
"Couple3",
|
||||
"StopIncidentsHardcore3",
|
||||
"RandomEnemyKilledUnarmed3_Survival",
|
||||
"WastelandCollectCaps3",
|
||||
"Babies3",
|
||||
"BarberShopUse3",
|
||||
"Weapons3",
|
||||
"QuestWinBattles3_Survival",
|
||||
"SurviveMoleratNoCasualties3_Survival",
|
||||
"CompleteQuestInWasteland3_Survival",
|
||||
"WeaponsHardcore3",
|
||||
"Food3",
|
||||
"QuestCollectCaps3",
|
||||
"WeaponsT1",
|
||||
"RushRoom3",
|
||||
"RandomEnemyKilledUnarmed3",
|
||||
"RadawayT1",
|
||||
"CollectOutfitsHardcore3",
|
||||
"CollectRareWeapons3",
|
||||
"MysteriousStranger3",
|
||||
"QuestPerformCriticalHit3",
|
||||
"SurviveGhoulNoCasualties3_Survival",
|
||||
"CraftRareOutfits3",
|
||||
"Water3",
|
||||
"CraftOutfits3",
|
||||
"MergeTwoRooms3",
|
||||
"SurviveRadscorpionNoCasualties3",
|
||||
"KillCreature3",
|
||||
"CollectWeapons3",
|
||||
"ScrapItems3",
|
||||
"CollectRareOutfits3"
|
||||
],
|
||||
[
|
||||
"SurviveGhoulNoCasualties4_Survival",
|
||||
"DwellerHappy4_Survival",
|
||||
"BaldDwellersInVault4",
|
||||
"SellItemHarcore4",
|
||||
"MergeTwoRooms4",
|
||||
"Weapons4",
|
||||
"RandomEnemyKilledUnarmed4",
|
||||
"SellJunk4",
|
||||
"QuestCollectContainers4_Survival",
|
||||
"WastelandLevelUp4",
|
||||
"CollectJunk4",
|
||||
"QuestPerformPerfectCriticalHit4",
|
||||
"QuestPerformCriticalHit4_Survival",
|
||||
"StimpackHardcore4",
|
||||
"Water4_Survival",
|
||||
"RushRoomHardcore4",
|
||||
"SurviveDeathclawNoCasualtiesHardcore4",
|
||||
"QuestPerformCriticalHit4",
|
||||
"SurviveRadscorpionNoCasualties4",
|
||||
"WeaponsHardcore4",
|
||||
"UpgradeRoom4",
|
||||
"CollectWeapons4",
|
||||
"CollectWaterWithinOneMin4",
|
||||
"SurviveDeathclawNoCasualties4",
|
||||
"SurviveGhoulNoCasualties4",
|
||||
"Stimpack4",
|
||||
"Pregnant4",
|
||||
"KillCreature4_Survival",
|
||||
"QuestWinBattles4",
|
||||
"ExploreWastelandHours4_Survival",
|
||||
"CompleteQuestInWasteland4",
|
||||
"KillCreature4",
|
||||
"EquipRandomWeapon4",
|
||||
"Food4_Survival",
|
||||
"ExtinguishFireHardcore4",
|
||||
"SurviveMoleratNoCasualtiesHardcore4",
|
||||
"DwellerHappy4",
|
||||
"RushRoom4",
|
||||
"Wasteland4",
|
||||
"ExploreWastelandHoursWithoutRadaway4",
|
||||
"QuestPerformPerfectCriticalHit4_Survival",
|
||||
"StopMoleratWithoutPropagate4",
|
||||
"CompleteQuestInOverseer4",
|
||||
"RandomEnemyKilledUnarmed4_Survival",
|
||||
"CraftWeapons4",
|
||||
"Radaway4",
|
||||
"CraftRareOutfits4",
|
||||
"StopIncidents4",
|
||||
"ScrapItems4",
|
||||
"SurviveMoleratNoCasualties4",
|
||||
"Power4",
|
||||
"CollectOutfits4",
|
||||
"SurviveDeathclawNoCasualties4_Survival",
|
||||
"StopIncidentsHardcore4",
|
||||
"StopIncidents4_Survival",
|
||||
"StopRadroachWithoutPropagate4",
|
||||
"ExtinguishFire4",
|
||||
"RaiseSpecialLevel4",
|
||||
"QuestWinBattles4_Survival",
|
||||
"QuestCollectContainers4",
|
||||
"CraftOutfits4",
|
||||
"BarberShopUse4",
|
||||
"MysteriousStranger4",
|
||||
"SurviveMoleratNoCasualties4_Survival",
|
||||
"Food4",
|
||||
"RaiseSpecificSpecialLevel4",
|
||||
"Babies4",
|
||||
"RushRoom4_Survival",
|
||||
"SurviveRadscorpionNoCasualties4_Survival",
|
||||
"CompleteQuestInWasteland4_Survival",
|
||||
"Outfits4",
|
||||
"CraftRareWeapons4",
|
||||
"WastelandWithPet4",
|
||||
"KillRandomEnemyUnarmedHardcore4",
|
||||
"ExploreWastelandHours4",
|
||||
"CollectPowerWithinOneMin4",
|
||||
"QuestCollectCaps4_Survival",
|
||||
"CollectRareOutfits4",
|
||||
"ExploreLocation4",
|
||||
"RightRoom4",
|
||||
"CollectCaps4",
|
||||
"QuestCollectCaps4",
|
||||
"MakeFriend4",
|
||||
"WastelandCollectCaps4",
|
||||
"Power4_Survival",
|
||||
"KillDeathclawAtVaultDoor4",
|
||||
"CollectRareWeapons4",
|
||||
"Water4",
|
||||
"CollectOutfitsHardcore4",
|
||||
"SurviveHoursNoCasualties4",
|
||||
"CompleteQuestInOverseer4_Survival",
|
||||
"CollectFoodWithinOneMin4",
|
||||
"CollectPets4",
|
||||
"KillCreatureHardcore4",
|
||||
"OutfitsHardcore4",
|
||||
"CollectWeaponsHardcore4",
|
||||
"KillRaiderAtVaultDoor4",
|
||||
"Couple4"
|
||||
],
|
||||
[
|
||||
"CollectRareOutfits5",
|
||||
"CollectWaterWithinOneMin5",
|
||||
"ExploreWastelandHoursWithoutRadaway5",
|
||||
"SurviveMoleratNoCasualties5_Survival",
|
||||
"ExploreLocation5",
|
||||
"Food5_Survival",
|
||||
"RushRoom5_Survival",
|
||||
"BarberShopUse5",
|
||||
"CollectFoodWithinOneMin5",
|
||||
"RandomEnemyKilledUnarmed5_Survival",
|
||||
"QuestWinBattles5",
|
||||
"SurviveRadscorpionNoCasualties5",
|
||||
"RushRoom5",
|
||||
"RaiseSpecificSpecialLevel5",
|
||||
"StopIncidents5",
|
||||
"Food5",
|
||||
"StopIncidentsHardcore5",
|
||||
"LevelUp5",
|
||||
"ExtinguishFire5",
|
||||
"CompleteQuestInWasteland5",
|
||||
"QuestPerformPerfectCriticalHit5",
|
||||
"WastelandLevelUp5",
|
||||
"DwellerHappy5_Survival",
|
||||
"SurviveGhoulNoCasualties5",
|
||||
"CompleteQuestInOverseer5_Survival",
|
||||
"EquipRandomWeapon5",
|
||||
"SurviveDeathclawNoCasualties5",
|
||||
"Water5",
|
||||
"QuestPerformCriticalHit5_Survival",
|
||||
"CollectWeapons5",
|
||||
"ScrapItems5",
|
||||
"Outfits5",
|
||||
"UpgradeRoom5",
|
||||
"StopRadroachWithoutPropagate5",
|
||||
"ExtinguishFireHardcore5",
|
||||
"CraftRareOutfits5",
|
||||
"CollectPets5",
|
||||
"CraftRareWeapons5",
|
||||
"QuestCollectCaps5_Survival",
|
||||
"MakeFriend5",
|
||||
"CollectJunk5",
|
||||
"DwellerHappy5",
|
||||
"Radaway5",
|
||||
"OutfitsHardcore5",
|
||||
"Pregnant5",
|
||||
"StopMoleratWithoutPropagate5",
|
||||
"BaldDwellersInVault5",
|
||||
"SellJunk5",
|
||||
"WeaponsHardcore5",
|
||||
"StimpackHardcore5",
|
||||
"CollectWeaponsHardcore5",
|
||||
"CraftWeapons5",
|
||||
"RushRoomHardcore5",
|
||||
"SurviveGhoulNoCasualties5_Survival",
|
||||
"QuestCollectContainers5",
|
||||
"CollectRareWeapons5",
|
||||
"CollectPowerWithinOneMin5",
|
||||
"QuestCollectCaps5",
|
||||
"SellItemHarcore5",
|
||||
"CompleteQuestInWasteland5_Survival",
|
||||
"WastelandWithPet5",
|
||||
"ExploreWastelandHours5",
|
||||
"SurviveHoursNoCasualties5",
|
||||
"Power5",
|
||||
"RightRoom5",
|
||||
"QuestPerformCriticalHit5",
|
||||
"KillCreature5",
|
||||
"CompleteQuestInOverseer5",
|
||||
"KillDeathclawAtVaultDoor5",
|
||||
"Wasteland5",
|
||||
"SurviveMoleratNoCasualtiesHardcore5",
|
||||
"KillRandomEnemyUnarmedHardcore5",
|
||||
"Water5_Survival",
|
||||
"KillCreatureHardcore5",
|
||||
"RandomEnemyKilledUnarmed5",
|
||||
"SurviveMoleratNoCasualties5",
|
||||
"Stimpack5",
|
||||
"QuestCollectContainers5_Survival",
|
||||
"QuestWinBattles5_Survival",
|
||||
"MysteriousStranger5",
|
||||
"Power5_Survival",
|
||||
"KillCreature5_Survival",
|
||||
"MergeTwoRooms5",
|
||||
"QuestPerformPerfectCriticalHit5_Survival",
|
||||
"CraftOutfits5",
|
||||
"Weapons5",
|
||||
"ExploreWastelandHours5_Survival",
|
||||
"KillRaiderAtVaultDoor5",
|
||||
"RaiseSpecialLevel5",
|
||||
"CollectOutfits5",
|
||||
"Couple5",
|
||||
"SurviveDeathclawNoCasualties5_Survival",
|
||||
"CollectOutfitsHardcore5",
|
||||
"SurviveRadscorpionNoCasualties5_Survival",
|
||||
"StopIncidents5_Survival",
|
||||
"SurviveDeathclawNoCasualtiesHardcore5",
|
||||
"CollectCaps5",
|
||||
"Babies5"
|
||||
]
|
||||
],
|
||||
"slotArray": [
|
||||
{
|
||||
"objective": {
|
||||
"objectiveID": "WastelandCollectCaps5",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "r1",
|
||||
"satisfied": false,
|
||||
"nukaCount": 0.0,
|
||||
"isAchievement": false
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
"incLevel": 0,
|
||||
"lottery": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
{
|
||||
"objective": {
|
||||
"objectiveID": "ExploreWastelandHours1",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "r1",
|
||||
"satisfied": false,
|
||||
"dwellers": [
|
||||
8
|
||||
]
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
"incLevel": 0,
|
||||
"lottery": [
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"objective": {
|
||||
"objectiveID": "BabiesT1",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "r1",
|
||||
"satisfied": false,
|
||||
"currentBabies": 0
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
"incLevel": 0,
|
||||
"lottery": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"unlockableMgr": {
|
||||
"objectivesInProgress": [
|
||||
{
|
||||
"objectiveID": "MedbayUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock1",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "RadioStationUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock3",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "NukacolaUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock15",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "SciencelabUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock2",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "GymUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock4",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "ArmoryUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock6",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "PowerPlantUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock12",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "CardioUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock8",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "WaterroomUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock13",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "HydroponicUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock14",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "BarUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock9",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "ClassUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock7",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "DojoUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock5",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "GameRoomUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock10",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "WeaponFactoryUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock16",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "OutfitFactoryUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock17",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "BarberShopUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock18",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "OverseerUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock20",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
},
|
||||
{
|
||||
"objectiveID": "DesignFactoryUnlock",
|
||||
"requirements": [
|
||||
{
|
||||
"requirementID": "unlock21",
|
||||
"satisfied": false,
|
||||
"currentCount": 12
|
||||
}
|
||||
],
|
||||
"completed": false,
|
||||
"incrementLevel": 0
|
||||
}
|
||||
],
|
||||
"completed": [],
|
||||
"claimed": [
|
||||
"StorageUnlock"
|
||||
]
|
||||
},
|
||||
"survivalW": {
|
||||
"weapons": [
|
||||
"N119",
|
||||
"N59",
|
||||
"N100",
|
||||
"N7"
|
||||
],
|
||||
"outfits": [
|
||||
"N95",
|
||||
"N79",
|
||||
"N76"
|
||||
],
|
||||
"dwellers": [],
|
||||
"pets": [],
|
||||
"breeds": [],
|
||||
"decorations": [],
|
||||
"junk": [
|
||||
"NAlarmClock",
|
||||
"NTeddyBear",
|
||||
"NChemistrySet"
|
||||
],
|
||||
"recipes": [
|
||||
"BOSUniform_Advanced",
|
||||
"RadiationSuit_Advanced",
|
||||
"UtilityJumpsuit",
|
||||
"BattleArmor",
|
||||
"CombatArmor",
|
||||
"ScribeRobe_Elder",
|
||||
"InstituteJumper_Expert",
|
||||
"FormalWear_Fancy",
|
||||
"FlightSuit",
|
||||
"FormalWear",
|
||||
"HandymanJumpsuit",
|
||||
"BattleArmor_Heavy",
|
||||
"RiotGear_Heavy",
|
||||
"ScribeRobe_Initiate",
|
||||
"ScientistScrubs",
|
||||
"LabCoat",
|
||||
"WandererArmor",
|
||||
"MechanicJumpsuit",
|
||||
"RiotGear",
|
||||
"MilitaryJumpsuit",
|
||||
"MoviefanSpecial",
|
||||
"AllNightware",
|
||||
"NinjaSuit",
|
||||
"ScientistScrubs_Officer",
|
||||
"PolkaDotDress",
|
||||
"SweaterVest",
|
||||
"RadiationSuit",
|
||||
"RaiderArmor",
|
||||
"WorkDress",
|
||||
"CheckeredShirt",
|
||||
"CombatArmor_Sturdy",
|
||||
"PowerArmor",
|
||||
"HunterGear_Treasure",
|
||||
"SequinDress",
|
||||
"HazmatSuit",
|
||||
"WastelandSurgeon_Settler",
|
||||
"WastelandSurgeon",
|
||||
"PowerArmor_MkI",
|
||||
"032Pistol",
|
||||
"032Pistol_Enhanced",
|
||||
"032Pistol_Rusty",
|
||||
"AlienBlaster_Tuned",
|
||||
"BBGun",
|
||||
"BBGun_Enhanced",
|
||||
"BBGun_Hardened",
|
||||
"BBGun_Rusty",
|
||||
"CombatShotgun_DoubleBarrelled",
|
||||
"CombatShotgun_Enhanced",
|
||||
"Flamer",
|
||||
"GaussRifle_Enhanced",
|
||||
"HuntingRifle",
|
||||
"HuntingRifle_Enhanced",
|
||||
"HuntingRifle_Hardened",
|
||||
"HuntingRifle_Rusty",
|
||||
"LaserPistol_Rusty",
|
||||
"LaserPistol_Tuned",
|
||||
"LaserRifle",
|
||||
"LaserRifle_Amplified",
|
||||
"Magnum",
|
||||
"Magnum_ArmorPiercing",
|
||||
"Magnum_Enhanced",
|
||||
"Magnum_Rusty",
|
||||
"Minigun_ArmorPiercing",
|
||||
"MissilLauncher_Guided",
|
||||
"MissilLauncher_Rusty",
|
||||
"PipePistol",
|
||||
"PipePistol_HairTrigger",
|
||||
"PipePistol_Heavy",
|
||||
"Pistol",
|
||||
"Pistol_Enhanced",
|
||||
"Pistol_Hardened",
|
||||
"Pistol_Rusty",
|
||||
"PlasmaPistol_Amplified",
|
||||
"PlasmaPistol_Rusty",
|
||||
"PlasmaRifle_Rusty",
|
||||
"PlasmaRifle_Tuned",
|
||||
"Railgun_Accelerated",
|
||||
"Rifle",
|
||||
"Rifle_Enhanced",
|
||||
"Rifle_Rusty",
|
||||
"SawedOffShotgun",
|
||||
"SawedOffShotgun_DoubleBarrelled",
|
||||
"SawedOffShotgun_Enhanced",
|
||||
"SawedOffShotgun_Rusty",
|
||||
"Shotgun"
|
||||
],
|
||||
"claimedRecipes": [],
|
||||
"collectedThemes": {
|
||||
"themeList": []
|
||||
}
|
||||
},
|
||||
"ShopWindow": {
|
||||
"isStarterPackPurchased": false,
|
||||
"hasStarterPackPopupShown": true
|
||||
},
|
||||
"happinessManager": {
|
||||
"dweller10": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dweller11": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dweller2": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dweller3": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dweller7": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dweller4": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dweller9": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dweller6": [
|
||||
{
|
||||
"type": 2,
|
||||
"rh": 0.0,
|
||||
"in": true
|
||||
}
|
||||
],
|
||||
"dwellers": [
|
||||
10,
|
||||
11,
|
||||
2,
|
||||
3,
|
||||
7,
|
||||
4,
|
||||
9,
|
||||
6
|
||||
]
|
||||
},
|
||||
"refugeeSpawner": {
|
||||
"newGameTask": -1,
|
||||
"succeed": 834,
|
||||
"currentPool": "Pool2",
|
||||
"currentPoolData": {
|
||||
"retrievedDwellers": 0,
|
||||
"failedChances": 1
|
||||
},
|
||||
"globalTimerTask": 835,
|
||||
"collectedAllRefugees": false
|
||||
},
|
||||
"LunchBoxCollectWindow": null,
|
||||
"DeathclawManager": {
|
||||
"deathclawTotalExtraChance": 0.0,
|
||||
"canDeathclawEmergencyOccurs": true,
|
||||
"deathclawCooldownID": -1
|
||||
},
|
||||
"PromoCodesWindow": null,
|
||||
"JunkGiveAwayWindow": null,
|
||||
"MysteriousStranger": {
|
||||
"currentState": "Hiding",
|
||||
"canAppear": true,
|
||||
"timeToAppear": 308.89,
|
||||
"remainingTimeToAppear": 250.0
|
||||
},
|
||||
"StatsWindow": {
|
||||
"vaultData": {
|
||||
"collectedRes": {
|
||||
"Nuka": 42093.0,
|
||||
"Food": 10291.23,
|
||||
"Energy": 11060.09,
|
||||
"Water": 10441.77,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"collectedOutfits": 3,
|
||||
"collectedWeapons": 4,
|
||||
"collectedDecorations": 0,
|
||||
"collectedPets": 0,
|
||||
"raidersKilled": 0,
|
||||
"elevatorRides": 339,
|
||||
"lunchBoxesOpened": 3,
|
||||
"petCarriersOpened": 0,
|
||||
"totalLifetimeDwellers": 12,
|
||||
"babiesBorn": 0,
|
||||
"dwellersRevived": 1,
|
||||
"levelsGained": 538,
|
||||
"specialStatTrained": 0,
|
||||
"takenStimpack": 0,
|
||||
"takenRadaway": 0,
|
||||
"deadDwellers": 0,
|
||||
"evictedDwellers": 2,
|
||||
"soldWeapons": 1,
|
||||
"soldOutfits": 0,
|
||||
"soldDecorations": 0,
|
||||
"soldPets": 0,
|
||||
"scrappedOutfits": 0,
|
||||
"scrappedWeapons": 0,
|
||||
"craftedWeapons": 0,
|
||||
"craftedOutfits": 0,
|
||||
"craftedDecorations": 0,
|
||||
"craftedThemes": 0,
|
||||
"collectedJunk": 3,
|
||||
"soldJunk": 1,
|
||||
"successfulRushes": 29,
|
||||
"failRushes": 0,
|
||||
"firesExtinguised": 3,
|
||||
"emergencyStopRaider": 0,
|
||||
"emergencyStopDeathClaw": 0,
|
||||
"emergencyStopGhoul": 0,
|
||||
"emergencyStopRadroach": 1,
|
||||
"emergencyStopRadscorpion": 0,
|
||||
"emergencyStopMolerat": 0,
|
||||
"dwellersSentWasteland": 9,
|
||||
"wastelandTotalTime": 3154.0,
|
||||
"wastelandCreaturesKilled": 37.0,
|
||||
"vaultCreatedBeforeUpdate": false,
|
||||
"dwellersCustomized": 0,
|
||||
"measuringSince": 638895246710443020,
|
||||
"previousVResources": {
|
||||
"Nuka": 1388.0,
|
||||
"Food": 9998.46,
|
||||
"Energy": 9999.0,
|
||||
"Water": 9998.46,
|
||||
"StimPack": 0.0,
|
||||
"RadAway": 0.0,
|
||||
"Lunchbox": 0.0,
|
||||
"MrHandy": 0.0,
|
||||
"PetCarrier": 0.0,
|
||||
"CraftedOutfit": 0.0,
|
||||
"CraftedWeapon": 0.0,
|
||||
"NukaColaQuantum": 0.0,
|
||||
"CraftedTheme": 0.0
|
||||
},
|
||||
"weaponFactoryBuilt": false,
|
||||
"outfitFactoryBuilt": false
|
||||
}
|
||||
},
|
||||
"PromotionFlags": [],
|
||||
"appVersion": " 1.13.13",
|
||||
"BottleAndCappyMgrSerializeKey": {
|
||||
"SerializeAccumulatedTriggerChance": 0.0,
|
||||
"SerializeLocked": false
|
||||
},
|
||||
"completedQuestDataManager": {
|
||||
"taskID": 391,
|
||||
"completedQuests": [],
|
||||
"foundClues": [],
|
||||
"standaloneQuestPicker": {},
|
||||
"dailyQuestPicker": {
|
||||
"currentDailies": [],
|
||||
"historyDailies": []
|
||||
},
|
||||
"weeklyQuestPicker": {
|
||||
"currentWeeklies": [],
|
||||
"historyWeeklies": []
|
||||
},
|
||||
"nukaQuantumIncrement": 0,
|
||||
"standaloneQuestSkipper": {
|
||||
"skippedQuests": []
|
||||
},
|
||||
"dailyQuestSkipper": {
|
||||
"skippedQuests": []
|
||||
},
|
||||
"weeklyQuestSkipper": {
|
||||
"skippedQuests": []
|
||||
}
|
||||
},
|
||||
"versionCount": 154
|
||||
}
|
||||
BIN
enhanced_save_decoder.py
Normal file
BIN
enhanced_save_decoder.py
Normal file
Binary file not shown.
605
fallout_shelter_editor.py
Normal file
605
fallout_shelter_editor.py
Normal file
@@ -0,0 +1,605 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Fallout Shelter Save Editor
|
||||
A comprehensive tool for editing Fallout Shelter save files.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import json
|
||||
import zlib
|
||||
import gzip
|
||||
import struct
|
||||
import os
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, Optional, List
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, filedialog, messagebox, scrolledtext
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
|
||||
|
||||
class FalloutShelterSave:
|
||||
"""Handles Fallout Shelter save file operations."""
|
||||
|
||||
# Fallout Shelter encryption constants (from JavaScript code)
|
||||
AES_KEY = bytes([
|
||||
(2815074099 >> 24) & 0xFF, (2815074099 >> 16) & 0xFF, (2815074099 >> 8) & 0xFF, 2815074099 & 0xFF,
|
||||
(1725469378 >> 24) & 0xFF, (1725469378 >> 16) & 0xFF, (1725469378 >> 8) & 0xFF, 1725469378 & 0xFF,
|
||||
(4039046167 >> 24) & 0xFF, (4039046167 >> 16) & 0xFF, (4039046167 >> 8) & 0xFF, 4039046167 & 0xFF,
|
||||
(874293617 >> 24) & 0xFF, (874293617 >> 16) & 0xFF, (874293617 >> 8) & 0xFF, 874293617 & 0xFF,
|
||||
(3063605751 >> 24) & 0xFF, (3063605751 >> 16) & 0xFF, (3063605751 >> 8) & 0xFF, 3063605751 & 0xFF,
|
||||
(3133984764 >> 24) & 0xFF, (3133984764 >> 16) & 0xFF, (3133984764 >> 8) & 0xFF, 3133984764 & 0xFF,
|
||||
(4097598161 >> 24) & 0xFF, (4097598161 >> 16) & 0xFF, (4097598161 >> 8) & 0xFF, 4097598161 & 0xFF,
|
||||
(3620741625 >> 24) & 0xFF, (3620741625 >> 16) & 0xFF, (3620741625 >> 8) & 0xFF, 3620741625 & 0xFF
|
||||
])
|
||||
AES_IV = bytes.fromhex("7475383967656A693334307438397532")
|
||||
|
||||
def __init__(self, filepath: str = None):
|
||||
self.filepath = filepath
|
||||
self.raw_data = None
|
||||
self.decoded_data = None
|
||||
self.save_data = None
|
||||
self.is_loaded = False
|
||||
|
||||
def load_save(self, filepath: str = None) -> bool:
|
||||
"""Load and decode a Fallout Shelter save file."""
|
||||
if filepath:
|
||||
self.filepath = filepath
|
||||
|
||||
if not self.filepath or not os.path.exists(self.filepath):
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(self.filepath, 'rb') as f:
|
||||
self.raw_data = f.read()
|
||||
|
||||
# Decode base64
|
||||
self.decoded_data = base64.b64decode(self.raw_data)
|
||||
|
||||
# Try to decompress and parse
|
||||
self.save_data = self._parse_save_data()
|
||||
self.is_loaded = True
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error loading save: {e}")
|
||||
return False
|
||||
|
||||
def _parse_save_data(self) -> Dict[str, Any]:
|
||||
"""Parse the decoded save data using AES-CBC decryption."""
|
||||
try:
|
||||
# Decrypt using AES-CBC
|
||||
cipher = AES.new(self.AES_KEY, AES.MODE_CBC, self.AES_IV)
|
||||
decrypted_data = cipher.decrypt(self.decoded_data)
|
||||
|
||||
# Remove PKCS7 padding
|
||||
try:
|
||||
unpadded_data = unpad(decrypted_data, AES.block_size)
|
||||
except ValueError:
|
||||
# If unpadding fails, try without unpadding (some implementations don't pad)
|
||||
unpadded_data = decrypted_data.rstrip(b'\x00')
|
||||
|
||||
# Convert to string and parse JSON
|
||||
json_str = unpadded_data.decode('utf-8')
|
||||
return json.loads(json_str)
|
||||
|
||||
except Exception as e:
|
||||
print(f"AES decryption failed: {e}")
|
||||
# Fallback to old methods if AES fails
|
||||
return self._try_fallback_methods()
|
||||
|
||||
def _try_fallback_methods(self) -> Dict[str, Any]:
|
||||
"""Fallback methods if AES decryption fails."""
|
||||
decompression_methods = [
|
||||
self._try_raw_json,
|
||||
self._try_zlib_decompress,
|
||||
self._try_gzip_decompress,
|
||||
self._try_custom_decompress,
|
||||
]
|
||||
|
||||
for method in decompression_methods:
|
||||
try:
|
||||
result = method(self.decoded_data)
|
||||
if result:
|
||||
return result
|
||||
except Exception as e:
|
||||
continue
|
||||
|
||||
# If all methods fail, return raw data info
|
||||
return {
|
||||
"error": "Could not parse save data",
|
||||
"raw_size": len(self.decoded_data),
|
||||
"raw_preview": self.decoded_data[:100].hex()
|
||||
}
|
||||
|
||||
def _try_raw_json(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try to parse as raw JSON."""
|
||||
try:
|
||||
text = data.decode('utf-8')
|
||||
return json.loads(text)
|
||||
except:
|
||||
return None
|
||||
|
||||
def _try_zlib_decompress(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try zlib decompression then JSON parse."""
|
||||
try:
|
||||
decompressed = zlib.decompress(data)
|
||||
text = decompressed.decode('utf-8')
|
||||
return json.loads(text)
|
||||
except:
|
||||
return None
|
||||
|
||||
def _try_gzip_decompress(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try gzip decompression then JSON parse."""
|
||||
try:
|
||||
decompressed = gzip.decompress(data)
|
||||
text = decompressed.decode('utf-8')
|
||||
return json.loads(text)
|
||||
except:
|
||||
return None
|
||||
|
||||
def _try_custom_decompress(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try custom Fallout Shelter decompression."""
|
||||
# Some Fallout Shelter saves use a custom format
|
||||
# This is a placeholder for reverse-engineered decompression
|
||||
try:
|
||||
# Check for common patterns in Fallout Shelter saves
|
||||
if len(data) > 4:
|
||||
# Try reading as little-endian uint32 header
|
||||
header = struct.unpack('<I', data[:4])[0]
|
||||
if header < len(data): # Reasonable size check
|
||||
# Try decompressing the rest
|
||||
compressed_data = data[4:]
|
||||
decompressed = zlib.decompress(compressed_data)
|
||||
text = decompressed.decode('utf-8')
|
||||
return json.loads(text)
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
def backup_save(self) -> str:
|
||||
"""Create a backup of the current save file."""
|
||||
if not self.filepath:
|
||||
return ""
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
backup_path = f"{self.filepath}.backup_{timestamp}"
|
||||
shutil.copy2(self.filepath, backup_path)
|
||||
return backup_path
|
||||
|
||||
def save_file(self, filepath: str = None) -> bool:
|
||||
"""Save the modified data back to file."""
|
||||
if not self.save_data or not self.is_loaded:
|
||||
return False
|
||||
|
||||
save_path = filepath or self.filepath
|
||||
if not save_path:
|
||||
return False
|
||||
|
||||
try:
|
||||
# Convert back to JSON (compact format)
|
||||
json_data = json.dumps(self.save_data, separators=(',', ':'))
|
||||
json_bytes = json_data.encode('utf-8')
|
||||
|
||||
# Pad data for AES encryption
|
||||
padded_data = pad(json_bytes, AES.block_size)
|
||||
|
||||
# Encrypt using AES-CBC
|
||||
cipher = AES.new(self.AES_KEY, AES.MODE_CBC, self.AES_IV)
|
||||
encrypted_data = cipher.encrypt(padded_data)
|
||||
|
||||
# Encode to base64
|
||||
encoded = base64.b64encode(encrypted_data)
|
||||
|
||||
# Write to file
|
||||
with open(save_path, 'wb') as f:
|
||||
f.write(encoded)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error saving file: {e}")
|
||||
return False
|
||||
|
||||
|
||||
class SaveEditorGUI:
|
||||
"""GUI for the Fallout Shelter Save Editor."""
|
||||
|
||||
def __init__(self):
|
||||
self.root = tk.Tk()
|
||||
self.root.title("Fallout Shelter Save Editor")
|
||||
self.root.geometry("800x600")
|
||||
|
||||
self.save_handler = FalloutShelterSave()
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self):
|
||||
"""Set up the user interface."""
|
||||
# Menu bar
|
||||
menubar = tk.Menu(self.root)
|
||||
self.root.config(menu=menubar)
|
||||
|
||||
file_menu = tk.Menu(menubar, tearoff=0)
|
||||
menubar.add_cascade(label="File", menu=file_menu)
|
||||
file_menu.add_command(label="Open Save", command=self.open_save)
|
||||
file_menu.add_command(label="Save", command=self.save_file)
|
||||
file_menu.add_command(label="Save As", command=self.save_as)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(label="Create Backup", command=self.create_backup)
|
||||
file_menu.add_separator()
|
||||
file_menu.add_command(label="Exit", command=self.root.quit)
|
||||
|
||||
# Main frame
|
||||
main_frame = ttk.Frame(self.root, padding="10")
|
||||
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# File info frame
|
||||
info_frame = ttk.LabelFrame(main_frame, text="Save File Info", padding="5")
|
||||
info_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
|
||||
|
||||
self.file_label = ttk.Label(info_frame, text="No file loaded")
|
||||
self.file_label.grid(row=0, column=0, sticky=tk.W)
|
||||
|
||||
# Notebook for different edit categories
|
||||
self.notebook = ttk.Notebook(main_frame)
|
||||
self.notebook.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# Raw data tab
|
||||
self.setup_raw_tab()
|
||||
|
||||
# Vault stats tab (placeholder for when we can parse the data)
|
||||
self.setup_vault_tab()
|
||||
|
||||
# Resources tab
|
||||
self.setup_resources_tab()
|
||||
|
||||
# Dwellers tab
|
||||
self.setup_dwellers_tab()
|
||||
|
||||
# Configure grid weights
|
||||
self.root.columnconfigure(0, weight=1)
|
||||
self.root.rowconfigure(0, weight=1)
|
||||
main_frame.columnconfigure(0, weight=1)
|
||||
main_frame.rowconfigure(1, weight=1)
|
||||
|
||||
def setup_raw_tab(self):
|
||||
"""Set up the raw data viewing tab."""
|
||||
raw_frame = ttk.Frame(self.notebook)
|
||||
self.notebook.add(raw_frame, text="Raw Data")
|
||||
|
||||
# Text area for raw data
|
||||
self.raw_text = scrolledtext.ScrolledText(raw_frame, wrap=tk.WORD, height=20)
|
||||
self.raw_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
|
||||
|
||||
def setup_vault_tab(self):
|
||||
"""Set up the vault statistics tab."""
|
||||
vault_frame = ttk.Frame(self.notebook)
|
||||
self.notebook.add(vault_frame, text="Vault Stats")
|
||||
|
||||
# Vault info
|
||||
ttk.Label(vault_frame, text="Vault Name:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=2)
|
||||
self.vault_name = ttk.Entry(vault_frame, width=30)
|
||||
self.vault_name.grid(row=0, column=1, sticky=tk.W, padx=5, pady=2)
|
||||
|
||||
ttk.Label(vault_frame, text="Vault Mode:").grid(row=1, column=0, sticky=tk.W, padx=5, pady=2)
|
||||
self.vault_number = ttk.Entry(vault_frame, width=30)
|
||||
self.vault_number.grid(row=1, column=1, sticky=tk.W, padx=5, pady=2)
|
||||
|
||||
def setup_resources_tab(self):
|
||||
"""Set up the resources editing tab."""
|
||||
resources_frame = ttk.Frame(self.notebook)
|
||||
self.notebook.add(resources_frame, text="Resources")
|
||||
|
||||
# Common resources
|
||||
resources = ["Caps", "Food", "Water", "Power", "Stimpaks", "RadAway", "Nuka Cola Quantum"]
|
||||
self.resource_entries = {}
|
||||
|
||||
for i, resource in enumerate(resources):
|
||||
ttk.Label(resources_frame, text=f"{resource}:").grid(row=i, column=0, sticky=tk.W, padx=5, pady=2)
|
||||
entry = ttk.Entry(resources_frame, width=20)
|
||||
entry.grid(row=i, column=1, sticky=tk.W, padx=5, pady=2)
|
||||
self.resource_entries[resource.lower().replace(" ", "_")] = entry
|
||||
|
||||
# Add buttons for resource modification
|
||||
button_frame = ttk.Frame(resources_frame)
|
||||
button_frame.grid(row=len(resources), column=0, columnspan=2, pady=10)
|
||||
|
||||
ttk.Button(button_frame, text="Apply Changes", command=self.apply_resource_changes).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Button(button_frame, text="Max All Resources", command=self.max_all_resources).pack(side=tk.LEFT, padx=5)
|
||||
|
||||
def setup_dwellers_tab(self):
|
||||
"""Set up the dwellers editing tab."""
|
||||
dwellers_frame = ttk.Frame(self.notebook)
|
||||
self.notebook.add(dwellers_frame, text="Dwellers")
|
||||
|
||||
# Dwellers list (placeholder)
|
||||
ttk.Label(dwellers_frame, text="Dwellers management will be available when save format is decoded").pack(pady=20)
|
||||
|
||||
def open_save(self):
|
||||
"""Open a save file."""
|
||||
filepath = filedialog.askopenfilename(
|
||||
title="Select Fallout Shelter Save File",
|
||||
filetypes=[("Save files", "*.sav"), ("All files", "*.*")]
|
||||
)
|
||||
|
||||
if filepath:
|
||||
if self.save_handler.load_save(filepath):
|
||||
self.file_label.config(text=f"Loaded: {os.path.basename(filepath)}")
|
||||
self.update_display()
|
||||
messagebox.showinfo("Success", "Save file loaded successfully!")
|
||||
else:
|
||||
messagebox.showerror("Error", "Failed to load save file")
|
||||
|
||||
def update_display(self):
|
||||
"""Update the display with loaded save data."""
|
||||
if not self.save_handler.is_loaded:
|
||||
return
|
||||
|
||||
# Update raw data tab
|
||||
if self.save_handler.save_data:
|
||||
raw_text = json.dumps(self.save_handler.save_data, indent=2)
|
||||
self.raw_text.delete(1.0, tk.END)
|
||||
self.raw_text.insert(1.0, raw_text)
|
||||
|
||||
# Try to populate other tabs if data structure is known
|
||||
self.populate_vault_info()
|
||||
self.populate_resources()
|
||||
|
||||
def populate_vault_info(self):
|
||||
"""Populate vault information if available."""
|
||||
if not self.save_handler.save_data:
|
||||
return
|
||||
|
||||
data = self.save_handler.save_data
|
||||
|
||||
# Get vault information from the correct location
|
||||
if "vault" in data and isinstance(data["vault"], dict):
|
||||
vault = data["vault"]
|
||||
|
||||
# Vault name
|
||||
if "VaultName" in vault:
|
||||
self.vault_name.delete(0, tk.END)
|
||||
self.vault_name.insert(0, str(vault["VaultName"]))
|
||||
|
||||
# Vault mode (instead of number, Fallout Shelter has mode)
|
||||
if "VaultMode" in vault:
|
||||
self.vault_number.delete(0, tk.END)
|
||||
self.vault_number.insert(0, str(vault["VaultMode"]))
|
||||
|
||||
def populate_resources(self):
|
||||
"""Populate resource information if available."""
|
||||
if not self.save_handler.save_data:
|
||||
return
|
||||
|
||||
data = self.save_handler.save_data
|
||||
|
||||
# Fallout Shelter resource field mappings (based on actual save structure)
|
||||
resource_mappings = {
|
||||
"caps": ["Nuka"], # Caps are stored as "Nuka" in the save
|
||||
"food": ["Food"],
|
||||
"water": ["Water"],
|
||||
"power": ["Energy"], # Power is stored as "Energy"
|
||||
"stimpaks": ["StimPack"],
|
||||
"radaway": ["RadAway"],
|
||||
"nuka_cola_quantum": ["NukaColaQuantum"]
|
||||
}
|
||||
|
||||
# Try to find and populate resource values
|
||||
# Look specifically in vault.storage.resources
|
||||
vault_storage = self._get_vault_storage(data)
|
||||
if vault_storage and "resources" in vault_storage:
|
||||
resources = vault_storage["resources"]
|
||||
|
||||
for resource_key, entry in self.resource_entries.items():
|
||||
possible_fields = resource_mappings.get(resource_key, [resource_key])
|
||||
|
||||
for field in possible_fields:
|
||||
if field in resources:
|
||||
entry.delete(0, tk.END)
|
||||
entry.insert(0, str(int(resources[field])))
|
||||
break
|
||||
|
||||
def _find_nested_value(self, data, key):
|
||||
"""Recursively search for a key in nested dictionaries."""
|
||||
if isinstance(data, dict):
|
||||
if key in data:
|
||||
return data[key]
|
||||
for value in data.values():
|
||||
result = self._find_nested_value(value, key)
|
||||
if result is not None:
|
||||
return result
|
||||
elif isinstance(data, list):
|
||||
for item in data:
|
||||
result = self._find_nested_value(item, key)
|
||||
if result is not None:
|
||||
return result
|
||||
return None
|
||||
|
||||
def save_file(self):
|
||||
"""Save the current file."""
|
||||
if self.save_handler.save_file():
|
||||
messagebox.showinfo("Success", "Save file updated successfully!")
|
||||
else:
|
||||
messagebox.showerror("Error", "Failed to save file")
|
||||
|
||||
def save_as(self):
|
||||
"""Save as a new file."""
|
||||
filepath = filedialog.asksaveasfilename(
|
||||
title="Save As",
|
||||
defaultextension=".sav",
|
||||
filetypes=[("Save files", "*.sav"), ("All files", "*.*")]
|
||||
)
|
||||
|
||||
if filepath:
|
||||
if self.save_handler.save_file(filepath):
|
||||
messagebox.showinfo("Success", f"Save file created: {os.path.basename(filepath)}")
|
||||
else:
|
||||
messagebox.showerror("Error", "Failed to create save file")
|
||||
|
||||
def create_backup(self):
|
||||
"""Create a backup of the current save."""
|
||||
if not self.save_handler.filepath:
|
||||
messagebox.showwarning("Warning", "No save file loaded")
|
||||
return
|
||||
|
||||
backup_path = self.save_handler.backup_save()
|
||||
if backup_path:
|
||||
messagebox.showinfo("Success", f"Backup created: {os.path.basename(backup_path)}")
|
||||
else:
|
||||
messagebox.showerror("Error", "Failed to create backup")
|
||||
|
||||
def apply_resource_changes(self):
|
||||
"""Apply resource changes to the save data."""
|
||||
if not self.save_handler.save_data:
|
||||
messagebox.showwarning("Warning", "No save data loaded")
|
||||
return
|
||||
|
||||
try:
|
||||
# Fallout Shelter resource field mappings
|
||||
resource_mappings = {
|
||||
"caps": ["Nuka"],
|
||||
"food": ["Food"],
|
||||
"water": ["Water"],
|
||||
"power": ["Energy"],
|
||||
"stimpaks": ["StimPack"],
|
||||
"radaway": ["RadAway"],
|
||||
"nuka_cola_quantum": ["NukaColaQuantum"]
|
||||
}
|
||||
|
||||
# Get vault storage
|
||||
vault_storage = self._get_vault_storage(self.save_handler.save_data)
|
||||
if not vault_storage or "resources" not in vault_storage:
|
||||
messagebox.showerror("Error", "Could not find vault storage in save data")
|
||||
return
|
||||
|
||||
resources = vault_storage["resources"]
|
||||
changes_made = 0
|
||||
|
||||
for resource_key, entry in self.resource_entries.items():
|
||||
value_str = entry.get().strip()
|
||||
if value_str:
|
||||
try:
|
||||
value = float(value_str) # Fallout Shelter uses floats for resources
|
||||
possible_fields = resource_mappings.get(resource_key, [resource_key])
|
||||
|
||||
for field in possible_fields:
|
||||
if field in resources:
|
||||
resources[field] = value
|
||||
changes_made += 1
|
||||
break
|
||||
except ValueError:
|
||||
messagebox.showerror("Error", f"Invalid value for {resource_key}: {value_str}")
|
||||
return
|
||||
|
||||
if changes_made > 0:
|
||||
messagebox.showinfo("Success", f"Applied {changes_made} resource changes")
|
||||
else:
|
||||
messagebox.showinfo("Info", "No changes were applied")
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("Error", f"Failed to apply changes: {e}")
|
||||
|
||||
def max_all_resources(self):
|
||||
"""Set all resources to maximum values."""
|
||||
max_values = {
|
||||
"caps": 999999,
|
||||
"food": 999999,
|
||||
"water": 999999,
|
||||
"power": 999999,
|
||||
"stimpaks": 999,
|
||||
"radaway": 999,
|
||||
"nuka_cola_quantum": 999
|
||||
}
|
||||
|
||||
for resource_key, entry in self.resource_entries.items():
|
||||
if resource_key in max_values:
|
||||
entry.delete(0, tk.END)
|
||||
entry.insert(0, str(max_values[resource_key]))
|
||||
|
||||
self.apply_resource_changes()
|
||||
|
||||
def _get_vault_storage(self, data):
|
||||
"""Get the vault storage section from save data."""
|
||||
if isinstance(data, dict) and "vault" in data:
|
||||
vault = data["vault"]
|
||||
if isinstance(vault, dict) and "storage" in vault:
|
||||
return vault["storage"]
|
||||
return None
|
||||
|
||||
def _set_nested_value(self, data, key, value):
|
||||
"""Recursively search for a key and set its value."""
|
||||
if isinstance(data, dict):
|
||||
if key in data:
|
||||
data[key] = value
|
||||
return True
|
||||
for nested_data in data.values():
|
||||
if self._set_nested_value(nested_data, key, value):
|
||||
return True
|
||||
elif isinstance(data, list):
|
||||
for item in data:
|
||||
if self._set_nested_value(item, key, value):
|
||||
return True
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
"""Start the GUI."""
|
||||
self.root.mainloop()
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
print("Fallout Shelter Save Editor")
|
||||
print("=" * 30)
|
||||
|
||||
# Check if GUI is available
|
||||
try:
|
||||
app = SaveEditorGUI()
|
||||
app.run()
|
||||
except ImportError:
|
||||
print("GUI not available, running in console mode")
|
||||
console_mode()
|
||||
|
||||
|
||||
def console_mode():
|
||||
"""Console-based interface."""
|
||||
print("\nConsole Mode")
|
||||
print("1. Analyze save file")
|
||||
print("2. Create backup")
|
||||
print("3. Exit")
|
||||
|
||||
while True:
|
||||
choice = input("\nEnter choice (1-3): ").strip()
|
||||
|
||||
if choice == "1":
|
||||
filepath = input("Enter save file path: ").strip()
|
||||
if os.path.exists(filepath):
|
||||
save = FalloutShelterSave(filepath)
|
||||
if save.load_save():
|
||||
print(f"Save loaded successfully!")
|
||||
print(f"Data preview: {str(save.save_data)[:200]}...")
|
||||
else:
|
||||
print("Failed to load save file")
|
||||
else:
|
||||
print("File not found")
|
||||
|
||||
elif choice == "2":
|
||||
filepath = input("Enter save file path: ").strip()
|
||||
if os.path.exists(filepath):
|
||||
save = FalloutShelterSave(filepath)
|
||||
backup_path = save.backup_save()
|
||||
if backup_path:
|
||||
print(f"Backup created: {backup_path}")
|
||||
else:
|
||||
print("Failed to create backup")
|
||||
else:
|
||||
print("File not found")
|
||||
|
||||
elif choice == "3":
|
||||
break
|
||||
else:
|
||||
print("Invalid choice")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
823
fallout_shelter_qt_editor.py
Normal file
823
fallout_shelter_qt_editor.py
Normal file
@@ -0,0 +1,823 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Fallout Shelter Save Editor - PyQt GUI
|
||||
A comprehensive PyQt-based tool for editing Fallout Shelter save files.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import base64
|
||||
import zlib
|
||||
import gzip
|
||||
import struct
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
import traceback
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QTabWidget, QTextEdit, QLabel, QLineEdit, QPushButton, QFileDialog,
|
||||
QMessageBox, QGroupBox, QGridLayout, QSpinBox, QDoubleSpinBox,
|
||||
QScrollArea, QFrame, QSplitter, QTreeWidget, QTreeWidgetItem,
|
||||
QHeaderView, QComboBox, QCheckBox, QProgressBar, QStatusBar,
|
||||
QMenuBar, QAction, QToolBar, QTableWidget, QTableWidgetItem
|
||||
)
|
||||
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
|
||||
from PyQt5.QtGui import QFont, QIcon, QPixmap
|
||||
|
||||
|
||||
class SaveDecryptionWorker(QThread):
|
||||
"""Worker thread for save file decryption/analysis."""
|
||||
|
||||
progress_updated = pyqtSignal(int)
|
||||
status_updated = pyqtSignal(str)
|
||||
finished_signal = pyqtSignal(dict)
|
||||
error_signal = pyqtSignal(str)
|
||||
|
||||
def __init__(self, filepath: str):
|
||||
super().__init__()
|
||||
self.filepath = filepath
|
||||
|
||||
def run(self):
|
||||
"""Run the decryption process."""
|
||||
try:
|
||||
self.status_updated.emit("Loading save file...")
|
||||
self.progress_updated.emit(10)
|
||||
|
||||
with open(self.filepath, 'rb') as f:
|
||||
raw_data = f.read()
|
||||
|
||||
self.status_updated.emit("Decoding base64...")
|
||||
self.progress_updated.emit(20)
|
||||
|
||||
decoded_data = base64.b64decode(raw_data)
|
||||
|
||||
self.status_updated.emit("Attempting decompression...")
|
||||
self.progress_updated.emit(40)
|
||||
|
||||
# Try various decompression methods
|
||||
result = self.try_decompress(decoded_data)
|
||||
|
||||
if result:
|
||||
self.status_updated.emit("Save file loaded successfully!")
|
||||
self.progress_updated.emit(100)
|
||||
self.finished_signal.emit(result)
|
||||
else:
|
||||
self.status_updated.emit("Could not decrypt save file")
|
||||
self.error_signal.emit("Unable to decrypt or decompress save file")
|
||||
|
||||
except Exception as e:
|
||||
self.error_signal.emit(f"Error loading save: {str(e)}")
|
||||
|
||||
def try_decompress(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try various decompression methods."""
|
||||
methods = [
|
||||
("Raw JSON", self.try_raw_json),
|
||||
("Zlib", self.try_zlib),
|
||||
("Gzip", self.try_gzip),
|
||||
("Custom Format", self.try_custom_format),
|
||||
]
|
||||
|
||||
for i, (name, method) in enumerate(methods):
|
||||
self.status_updated.emit(f"Trying {name}...")
|
||||
self.progress_updated.emit(40 + (i * 15))
|
||||
|
||||
try:
|
||||
result = method(data)
|
||||
if result:
|
||||
return {
|
||||
"method": name,
|
||||
"data": result,
|
||||
"raw_size": len(data)
|
||||
}
|
||||
except Exception as e:
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
def try_raw_json(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try parsing as raw JSON."""
|
||||
text = data.decode('utf-8')
|
||||
return json.loads(text)
|
||||
|
||||
def try_zlib(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try zlib decompression."""
|
||||
decompressed = zlib.decompress(data)
|
||||
text = decompressed.decode('utf-8')
|
||||
return json.loads(text)
|
||||
|
||||
def try_gzip(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try gzip decompression."""
|
||||
decompressed = gzip.decompress(data)
|
||||
text = decompressed.decode('utf-8')
|
||||
return json.loads(text)
|
||||
|
||||
def try_custom_format(self, data: bytes) -> Optional[Dict]:
|
||||
"""Try custom Fallout Shelter format."""
|
||||
# Try with header
|
||||
if len(data) > 4:
|
||||
header = struct.unpack('<I', data[:4])[0]
|
||||
if 4 < header < len(data):
|
||||
compressed_data = data[4:]
|
||||
decompressed = zlib.decompress(compressed_data)
|
||||
text = decompressed.decode('utf-8')
|
||||
return json.loads(text)
|
||||
return None
|
||||
|
||||
|
||||
class FalloutShelterSaveEditor(QMainWindow):
|
||||
"""Main application window."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.save_data = None
|
||||
self.save_filepath = None
|
||||
self.save_method = None
|
||||
self.is_modified = False
|
||||
|
||||
self.init_ui()
|
||||
self.setup_connections()
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialize the user interface."""
|
||||
self.setWindowTitle("Fallout Shelter Save Editor")
|
||||
self.setGeometry(100, 100, 1200, 800)
|
||||
|
||||
# Create menu bar
|
||||
self.create_menu_bar()
|
||||
|
||||
# Create toolbar
|
||||
self.create_toolbar()
|
||||
|
||||
# Create status bar
|
||||
self.status_bar = QStatusBar()
|
||||
self.setStatusBar(self.status_bar)
|
||||
|
||||
# Progress bar for status bar
|
||||
self.progress_bar = QProgressBar()
|
||||
self.progress_bar.setVisible(False)
|
||||
self.status_bar.addPermanentWidget(self.progress_bar)
|
||||
|
||||
# Central widget
|
||||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
# Main layout
|
||||
main_layout = QVBoxLayout(central_widget)
|
||||
|
||||
# File info section
|
||||
self.create_file_info_section(main_layout)
|
||||
|
||||
# Main content area with tabs
|
||||
self.create_main_content(main_layout)
|
||||
|
||||
# Update UI state
|
||||
self.update_ui_state()
|
||||
|
||||
def create_menu_bar(self):
|
||||
"""Create the menu bar."""
|
||||
menubar = self.menuBar()
|
||||
|
||||
# File menu
|
||||
file_menu = menubar.addMenu('File')
|
||||
|
||||
open_action = QAction('Open Save File', self)
|
||||
open_action.setShortcut('Ctrl+O')
|
||||
open_action.triggered.connect(self.open_save_file)
|
||||
file_menu.addAction(open_action)
|
||||
|
||||
save_action = QAction('Save', self)
|
||||
save_action.setShortcut('Ctrl+S')
|
||||
save_action.triggered.connect(self.save_file)
|
||||
file_menu.addAction(save_action)
|
||||
|
||||
save_as_action = QAction('Save As...', self)
|
||||
save_as_action.setShortcut('Ctrl+Shift+S')
|
||||
save_as_action.triggered.connect(self.save_file_as)
|
||||
file_menu.addAction(save_as_action)
|
||||
|
||||
file_menu.addSeparator()
|
||||
|
||||
backup_action = QAction('Create Backup', self)
|
||||
backup_action.triggered.connect(self.create_backup)
|
||||
file_menu.addAction(backup_action)
|
||||
|
||||
file_menu.addSeparator()
|
||||
|
||||
exit_action = QAction('Exit', self)
|
||||
exit_action.setShortcut('Ctrl+Q')
|
||||
exit_action.triggered.connect(self.close)
|
||||
file_menu.addAction(exit_action)
|
||||
|
||||
# Edit menu
|
||||
edit_menu = menubar.addMenu('Edit')
|
||||
|
||||
refresh_action = QAction('Refresh Data', self)
|
||||
refresh_action.setShortcut('F5')
|
||||
refresh_action.triggered.connect(self.refresh_data)
|
||||
edit_menu.addAction(refresh_action)
|
||||
|
||||
# Help menu
|
||||
help_menu = menubar.addMenu('Help')
|
||||
|
||||
about_action = QAction('About', self)
|
||||
about_action.triggered.connect(self.show_about)
|
||||
help_menu.addAction(about_action)
|
||||
|
||||
def create_toolbar(self):
|
||||
"""Create the toolbar."""
|
||||
toolbar = QToolBar()
|
||||
self.addToolBar(toolbar)
|
||||
|
||||
# Open button
|
||||
open_btn = QPushButton("Open Save")
|
||||
open_btn.clicked.connect(self.open_save_file)
|
||||
toolbar.addWidget(open_btn)
|
||||
|
||||
# Save button
|
||||
self.save_btn = QPushButton("Save")
|
||||
self.save_btn.clicked.connect(self.save_file)
|
||||
self.save_btn.setEnabled(False)
|
||||
toolbar.addWidget(self.save_btn)
|
||||
|
||||
# Backup button
|
||||
self.backup_btn = QPushButton("Backup")
|
||||
self.backup_btn.clicked.connect(self.create_backup)
|
||||
self.backup_btn.setEnabled(False)
|
||||
toolbar.addWidget(self.backup_btn)
|
||||
|
||||
def create_file_info_section(self, parent_layout):
|
||||
"""Create the file information section."""
|
||||
info_group = QGroupBox("Save File Information")
|
||||
info_layout = QGridLayout(info_group)
|
||||
|
||||
# File path
|
||||
info_layout.addWidget(QLabel("File:"), 0, 0)
|
||||
self.file_path_label = QLabel("No file loaded")
|
||||
self.file_path_label.setStyleSheet("font-weight: bold;")
|
||||
info_layout.addWidget(self.file_path_label, 0, 1)
|
||||
|
||||
# File size
|
||||
info_layout.addWidget(QLabel("Size:"), 1, 0)
|
||||
self.file_size_label = QLabel("-")
|
||||
info_layout.addWidget(self.file_size_label, 1, 1)
|
||||
|
||||
# Decryption method
|
||||
info_layout.addWidget(QLabel("Method:"), 2, 0)
|
||||
self.method_label = QLabel("-")
|
||||
info_layout.addWidget(self.method_label, 2, 1)
|
||||
|
||||
# Modified status
|
||||
info_layout.addWidget(QLabel("Status:"), 3, 0)
|
||||
self.status_label = QLabel("Not modified")
|
||||
info_layout.addWidget(self.status_label, 3, 1)
|
||||
|
||||
parent_layout.addWidget(info_group)
|
||||
|
||||
def create_main_content(self, parent_layout):
|
||||
"""Create the main content area with tabs."""
|
||||
self.tab_widget = QTabWidget()
|
||||
|
||||
# Raw Data tab
|
||||
self.create_raw_data_tab()
|
||||
|
||||
# Vault Info tab
|
||||
self.create_vault_info_tab()
|
||||
|
||||
# Resources tab
|
||||
self.create_resources_tab()
|
||||
|
||||
# Dwellers tab
|
||||
self.create_dwellers_tab()
|
||||
|
||||
# Rooms tab
|
||||
self.create_rooms_tab()
|
||||
|
||||
parent_layout.addWidget(self.tab_widget)
|
||||
|
||||
def create_raw_data_tab(self):
|
||||
"""Create the raw data viewing/editing tab."""
|
||||
raw_widget = QWidget()
|
||||
layout = QVBoxLayout(raw_widget)
|
||||
|
||||
# JSON editor
|
||||
self.json_editor = QTextEdit()
|
||||
self.json_editor.setFont(QFont("Consolas", 10))
|
||||
self.json_editor.textChanged.connect(self.on_data_modified)
|
||||
layout.addWidget(self.json_editor)
|
||||
|
||||
# Format button
|
||||
format_btn = QPushButton("Format JSON")
|
||||
format_btn.clicked.connect(self.format_json)
|
||||
layout.addWidget(format_btn)
|
||||
|
||||
self.tab_widget.addTab(raw_widget, "Raw Data")
|
||||
|
||||
def create_vault_info_tab(self):
|
||||
"""Create the vault information tab."""
|
||||
vault_widget = QWidget()
|
||||
layout = QVBoxLayout(vault_widget)
|
||||
|
||||
# Scroll area for vault info
|
||||
scroll = QScrollArea()
|
||||
scroll_widget = QWidget()
|
||||
scroll_layout = QGridLayout(scroll_widget)
|
||||
|
||||
# Vault basic info
|
||||
basic_group = QGroupBox("Basic Information")
|
||||
basic_layout = QGridLayout(basic_group)
|
||||
|
||||
# Vault name
|
||||
basic_layout.addWidget(QLabel("Vault Name:"), 0, 0)
|
||||
self.vault_name_edit = QLineEdit()
|
||||
self.vault_name_edit.textChanged.connect(self.on_data_modified)
|
||||
basic_layout.addWidget(self.vault_name_edit, 0, 1)
|
||||
|
||||
# Vault number
|
||||
basic_layout.addWidget(QLabel("Vault Number:"), 1, 0)
|
||||
self.vault_number_spin = QSpinBox()
|
||||
self.vault_number_spin.setRange(1, 999)
|
||||
self.vault_number_spin.valueChanged.connect(self.on_data_modified)
|
||||
basic_layout.addWidget(self.vault_number_spin, 1, 1)
|
||||
|
||||
# Experience
|
||||
basic_layout.addWidget(QLabel("Experience:"), 2, 0)
|
||||
self.experience_spin = QSpinBox()
|
||||
self.experience_spin.setRange(0, 999999999)
|
||||
self.experience_spin.valueChanged.connect(self.on_data_modified)
|
||||
basic_layout.addWidget(self.experience_spin, 2, 1)
|
||||
|
||||
scroll_layout.addWidget(basic_group, 0, 0)
|
||||
|
||||
scroll.setWidget(scroll_widget)
|
||||
layout.addWidget(scroll)
|
||||
|
||||
self.tab_widget.addTab(vault_widget, "Vault Info")
|
||||
|
||||
def create_resources_tab(self):
|
||||
"""Create the resources editing tab."""
|
||||
resources_widget = QWidget()
|
||||
layout = QVBoxLayout(resources_widget)
|
||||
|
||||
# Resources group
|
||||
resources_group = QGroupBox("Vault Resources")
|
||||
resources_layout = QGridLayout(resources_group)
|
||||
|
||||
# Common resources
|
||||
self.resource_spins = {}
|
||||
resources = [
|
||||
("Caps", "caps", 0, 999999999),
|
||||
("Food", "food", 0, 999999),
|
||||
("Water", "water", 0, 999999),
|
||||
("Power", "power", 0, 999999),
|
||||
("Stimpaks", "stimpaks", 0, 999999),
|
||||
("RadAway", "radaway", 0, 999999),
|
||||
("Nuka Cola Quantum", "nuka_quantum", 0, 999999),
|
||||
]
|
||||
|
||||
for i, (display_name, key, min_val, max_val) in enumerate(resources):
|
||||
resources_layout.addWidget(QLabel(f"{display_name}:"), i, 0)
|
||||
|
||||
spin = QSpinBox()
|
||||
spin.setRange(min_val, max_val)
|
||||
spin.valueChanged.connect(self.on_data_modified)
|
||||
self.resource_spins[key] = spin
|
||||
resources_layout.addWidget(spin, i, 1)
|
||||
|
||||
layout.addWidget(resources_group)
|
||||
layout.addStretch()
|
||||
|
||||
self.tab_widget.addTab(resources_widget, "Resources")
|
||||
|
||||
def create_dwellers_tab(self):
|
||||
"""Create the dwellers management tab."""
|
||||
dwellers_widget = QWidget()
|
||||
layout = QVBoxLayout(dwellers_widget)
|
||||
|
||||
# Dwellers table
|
||||
self.dwellers_table = QTableWidget()
|
||||
self.dwellers_table.setColumnCount(8)
|
||||
self.dwellers_table.setHorizontalHeaderLabels([
|
||||
"Name", "Level", "Health", "Happiness", "Strength", "Perception", "Endurance", "Charisma"
|
||||
])
|
||||
|
||||
# Make table stretch
|
||||
header = self.dwellers_table.horizontalHeader()
|
||||
header.setSectionResizeMode(QHeaderView.Stretch)
|
||||
|
||||
layout.addWidget(self.dwellers_table)
|
||||
|
||||
# Dwellers controls
|
||||
controls_layout = QHBoxLayout()
|
||||
|
||||
refresh_dwellers_btn = QPushButton("Refresh Dwellers")
|
||||
refresh_dwellers_btn.clicked.connect(self.refresh_dwellers)
|
||||
controls_layout.addWidget(refresh_dwellers_btn)
|
||||
|
||||
controls_layout.addStretch()
|
||||
layout.addLayout(controls_layout)
|
||||
|
||||
self.tab_widget.addTab(dwellers_widget, "Dwellers")
|
||||
|
||||
def create_rooms_tab(self):
|
||||
"""Create the rooms management tab."""
|
||||
rooms_widget = QWidget()
|
||||
layout = QVBoxLayout(rooms_widget)
|
||||
|
||||
# Rooms tree
|
||||
self.rooms_tree = QTreeWidget()
|
||||
self.rooms_tree.setHeaderLabels(["Room Type", "Level", "Position", "Status"])
|
||||
layout.addWidget(self.rooms_tree)
|
||||
|
||||
# Rooms controls
|
||||
controls_layout = QHBoxLayout()
|
||||
|
||||
refresh_rooms_btn = QPushButton("Refresh Rooms")
|
||||
refresh_rooms_btn.clicked.connect(self.refresh_rooms)
|
||||
controls_layout.addWidget(refresh_rooms_btn)
|
||||
|
||||
controls_layout.addStretch()
|
||||
layout.addLayout(controls_layout)
|
||||
|
||||
self.tab_widget.addTab(rooms_widget, "Rooms")
|
||||
|
||||
def setup_connections(self):
|
||||
"""Set up signal connections."""
|
||||
pass
|
||||
|
||||
def open_save_file(self):
|
||||
"""Open a save file."""
|
||||
filepath, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"Open Fallout Shelter Save File",
|
||||
"",
|
||||
"Save Files (*.sav);;All Files (*)"
|
||||
)
|
||||
|
||||
if filepath:
|
||||
self.load_save_file(filepath)
|
||||
|
||||
def load_save_file(self, filepath: str):
|
||||
"""Load a save file using worker thread."""
|
||||
self.progress_bar.setVisible(True)
|
||||
self.progress_bar.setValue(0)
|
||||
|
||||
# Create and start worker thread
|
||||
self.worker = SaveDecryptionWorker(filepath)
|
||||
self.worker.progress_updated.connect(self.progress_bar.setValue)
|
||||
self.worker.status_updated.connect(self.status_bar.showMessage)
|
||||
self.worker.finished_signal.connect(self.on_save_loaded)
|
||||
self.worker.error_signal.connect(self.on_load_error)
|
||||
self.worker.start()
|
||||
|
||||
def on_save_loaded(self, result: Dict):
|
||||
"""Handle successful save file loading."""
|
||||
self.save_data = result["data"]
|
||||
self.save_filepath = self.worker.filepath
|
||||
self.save_method = result["method"]
|
||||
self.is_modified = False
|
||||
|
||||
# Update UI
|
||||
self.update_file_info()
|
||||
self.populate_data()
|
||||
self.update_ui_state()
|
||||
|
||||
self.progress_bar.setVisible(False)
|
||||
self.status_bar.showMessage("Save file loaded successfully", 3000)
|
||||
|
||||
def on_load_error(self, error_msg: str):
|
||||
"""Handle save file loading error."""
|
||||
self.progress_bar.setVisible(False)
|
||||
self.status_bar.showMessage("Failed to load save file", 3000)
|
||||
|
||||
QMessageBox.critical(self, "Error", f"Failed to load save file:\n{error_msg}")
|
||||
|
||||
def update_file_info(self):
|
||||
"""Update the file information display."""
|
||||
if self.save_filepath:
|
||||
filename = os.path.basename(self.save_filepath)
|
||||
self.file_path_label.setText(filename)
|
||||
|
||||
file_size = os.path.getsize(self.save_filepath)
|
||||
self.file_size_label.setText(f"{file_size:,} bytes")
|
||||
|
||||
self.method_label.setText(self.save_method or "Unknown")
|
||||
|
||||
self.update_status_label()
|
||||
|
||||
def update_status_label(self):
|
||||
"""Update the modification status label."""
|
||||
if self.is_modified:
|
||||
self.status_label.setText("Modified")
|
||||
self.status_label.setStyleSheet("color: orange; font-weight: bold;")
|
||||
else:
|
||||
self.status_label.setText("Not modified")
|
||||
self.status_label.setStyleSheet("color: green;")
|
||||
|
||||
def populate_data(self):
|
||||
"""Populate all tabs with save data."""
|
||||
if not self.save_data:
|
||||
return
|
||||
|
||||
# Raw data tab
|
||||
json_text = json.dumps(self.save_data, indent=2)
|
||||
self.json_editor.setPlainText(json_text)
|
||||
|
||||
# Vault info tab
|
||||
self.populate_vault_info()
|
||||
|
||||
# Resources tab
|
||||
self.populate_resources()
|
||||
|
||||
# Dwellers tab
|
||||
self.refresh_dwellers()
|
||||
|
||||
# Rooms tab
|
||||
self.refresh_rooms()
|
||||
|
||||
def populate_vault_info(self):
|
||||
"""Populate vault information."""
|
||||
if not self.save_data:
|
||||
return
|
||||
|
||||
# Try to find vault info in common locations
|
||||
vault_info = self.save_data
|
||||
|
||||
# Vault name
|
||||
name_fields = ["vaultName", "name", "VaultName"]
|
||||
for field in name_fields:
|
||||
if field in vault_info:
|
||||
self.vault_name_edit.setText(str(vault_info[field]))
|
||||
break
|
||||
|
||||
# Vault number
|
||||
number_fields = ["vaultNumber", "number", "VaultNumber"]
|
||||
for field in number_fields:
|
||||
if field in vault_info:
|
||||
self.vault_number_spin.setValue(int(vault_info[field]))
|
||||
break
|
||||
|
||||
# Experience
|
||||
exp_fields = ["experience", "exp", "Experience"]
|
||||
for field in exp_fields:
|
||||
if field in vault_info:
|
||||
self.experience_spin.setValue(int(vault_info[field]))
|
||||
break
|
||||
|
||||
def populate_resources(self):
|
||||
"""Populate resource information."""
|
||||
if not self.save_data:
|
||||
return
|
||||
|
||||
# Try to find resources in common locations
|
||||
resources_data = self.save_data.get("resources", self.save_data)
|
||||
|
||||
# Map of UI keys to possible data keys
|
||||
resource_mappings = {
|
||||
"caps": ["caps", "money", "Caps"],
|
||||
"food": ["food", "Food"],
|
||||
"water": ["water", "Water"],
|
||||
"power": ["power", "electricity", "Power"],
|
||||
"stimpaks": ["stimpaks", "stimpak", "Stimpaks"],
|
||||
"radaway": ["radaway", "RadAway", "radAway"],
|
||||
"nuka_quantum": ["nuka_quantum", "quantum", "NukaQuantum"],
|
||||
}
|
||||
|
||||
for ui_key, data_keys in resource_mappings.items():
|
||||
if ui_key in self.resource_spins:
|
||||
for data_key in data_keys:
|
||||
if data_key in resources_data:
|
||||
self.resource_spins[ui_key].setValue(int(resources_data[data_key]))
|
||||
break
|
||||
|
||||
def refresh_dwellers(self):
|
||||
"""Refresh the dwellers table."""
|
||||
if not self.save_data:
|
||||
return
|
||||
|
||||
# Try to find dwellers data
|
||||
dwellers_data = self.save_data.get("dwellers", [])
|
||||
if not isinstance(dwellers_data, list):
|
||||
dwellers_data = []
|
||||
|
||||
self.dwellers_table.setRowCount(len(dwellers_data))
|
||||
|
||||
for i, dweller in enumerate(dwellers_data):
|
||||
if isinstance(dweller, dict):
|
||||
# Name
|
||||
name = dweller.get("name", f"Dweller {i+1}")
|
||||
self.dwellers_table.setItem(i, 0, QTableWidgetItem(str(name)))
|
||||
|
||||
# Level
|
||||
level = dweller.get("level", 1)
|
||||
self.dwellers_table.setItem(i, 1, QTableWidgetItem(str(level)))
|
||||
|
||||
# Health
|
||||
health = dweller.get("health", 100)
|
||||
self.dwellers_table.setItem(i, 2, QTableWidgetItem(str(health)))
|
||||
|
||||
# Happiness
|
||||
happiness = dweller.get("happiness", 100)
|
||||
self.dwellers_table.setItem(i, 3, QTableWidgetItem(str(happiness)))
|
||||
|
||||
# SPECIAL stats
|
||||
special = dweller.get("special", {})
|
||||
stats = ["strength", "perception", "endurance", "charisma"]
|
||||
for j, stat in enumerate(stats):
|
||||
value = special.get(stat, 1)
|
||||
self.dwellers_table.setItem(i, 4+j, QTableWidgetItem(str(value)))
|
||||
|
||||
def refresh_rooms(self):
|
||||
"""Refresh the rooms tree."""
|
||||
self.rooms_tree.clear()
|
||||
|
||||
if not self.save_data:
|
||||
return
|
||||
|
||||
# Try to find rooms data
|
||||
rooms_data = self.save_data.get("rooms", [])
|
||||
if not isinstance(rooms_data, list):
|
||||
rooms_data = []
|
||||
|
||||
for i, room in enumerate(rooms_data):
|
||||
if isinstance(room, dict):
|
||||
room_type = room.get("type", "Unknown")
|
||||
level = room.get("level", 1)
|
||||
position = f"({room.get('x', 0)}, {room.get('y', 0)})"
|
||||
status = room.get("status", "Active")
|
||||
|
||||
item = QTreeWidgetItem([room_type, str(level), position, status])
|
||||
self.rooms_tree.addTopLevelItem(item)
|
||||
|
||||
def on_data_modified(self):
|
||||
"""Handle data modification."""
|
||||
if not self.is_modified:
|
||||
self.is_modified = True
|
||||
self.update_status_label()
|
||||
self.update_ui_state()
|
||||
|
||||
def format_json(self):
|
||||
"""Format the JSON in the raw data tab."""
|
||||
try:
|
||||
text = self.json_editor.toPlainText()
|
||||
data = json.loads(text)
|
||||
formatted = json.dumps(data, indent=2)
|
||||
self.json_editor.setPlainText(formatted)
|
||||
except json.JSONDecodeError as e:
|
||||
QMessageBox.warning(self, "JSON Error", f"Invalid JSON: {e}")
|
||||
|
||||
def save_file(self):
|
||||
"""Save the current file."""
|
||||
if not self.save_filepath:
|
||||
self.save_file_as()
|
||||
return
|
||||
|
||||
if self.write_save_file(self.save_filepath):
|
||||
self.is_modified = False
|
||||
self.update_status_label()
|
||||
self.update_ui_state()
|
||||
self.status_bar.showMessage("File saved successfully", 3000)
|
||||
else:
|
||||
QMessageBox.critical(self, "Error", "Failed to save file")
|
||||
|
||||
def save_file_as(self):
|
||||
"""Save as a new file."""
|
||||
filepath, _ = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"Save Fallout Shelter Save File",
|
||||
"",
|
||||
"Save Files (*.sav);;All Files (*)"
|
||||
)
|
||||
|
||||
if filepath:
|
||||
if self.write_save_file(filepath):
|
||||
self.save_filepath = filepath
|
||||
self.is_modified = False
|
||||
self.update_file_info()
|
||||
self.update_ui_state()
|
||||
self.status_bar.showMessage("File saved successfully", 3000)
|
||||
else:
|
||||
QMessageBox.critical(self, "Error", "Failed to save file")
|
||||
|
||||
def write_save_file(self, filepath: str) -> bool:
|
||||
"""Write the save data to file."""
|
||||
try:
|
||||
# Get current data from JSON editor
|
||||
json_text = self.json_editor.toPlainText()
|
||||
data = json.loads(json_text)
|
||||
|
||||
# Convert to JSON string
|
||||
json_string = json.dumps(data, separators=(',', ':'))
|
||||
|
||||
# Compress (try to match original method)
|
||||
if self.save_method == "Zlib":
|
||||
compressed = zlib.compress(json_string.encode('utf-8'))
|
||||
else:
|
||||
# Default to zlib
|
||||
compressed = zlib.compress(json_string.encode('utf-8'))
|
||||
|
||||
# Encode to base64
|
||||
encoded = base64.b64encode(compressed)
|
||||
|
||||
# Write to file
|
||||
with open(filepath, 'wb') as f:
|
||||
f.write(encoded)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error writing save file: {e}")
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def create_backup(self):
|
||||
"""Create a backup of the current save file."""
|
||||
if not self.save_filepath:
|
||||
QMessageBox.warning(self, "Warning", "No save file loaded")
|
||||
return
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
backup_path = f"{self.save_filepath}.backup_{timestamp}"
|
||||
|
||||
try:
|
||||
shutil.copy2(self.save_filepath, backup_path)
|
||||
QMessageBox.information(self, "Success", f"Backup created:\n{os.path.basename(backup_path)}")
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Error", f"Failed to create backup:\n{e}")
|
||||
|
||||
def refresh_data(self):
|
||||
"""Refresh all data displays."""
|
||||
self.populate_data()
|
||||
|
||||
def update_ui_state(self):
|
||||
"""Update UI element states based on current state."""
|
||||
has_save = self.save_data is not None
|
||||
|
||||
self.save_btn.setEnabled(has_save and self.is_modified)
|
||||
self.backup_btn.setEnabled(has_save)
|
||||
|
||||
# Update window title
|
||||
title = "Fallout Shelter Save Editor"
|
||||
if self.save_filepath:
|
||||
filename = os.path.basename(self.save_filepath)
|
||||
title += f" - {filename}"
|
||||
if self.is_modified:
|
||||
title += " *"
|
||||
self.setWindowTitle(title)
|
||||
|
||||
def show_about(self):
|
||||
"""Show about dialog."""
|
||||
QMessageBox.about(
|
||||
self,
|
||||
"About Fallout Shelter Save Editor",
|
||||
"Fallout Shelter Save Editor v1.0\n\n"
|
||||
"A PyQt-based tool for editing Fallout Shelter save files.\n\n"
|
||||
"Features:\n"
|
||||
"• Load and save encrypted save files\n"
|
||||
"• Edit vault information and resources\n"
|
||||
"• View and manage dwellers\n"
|
||||
"• Raw JSON editing\n"
|
||||
"• Automatic backups"
|
||||
)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Handle window close event."""
|
||||
if self.is_modified:
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Unsaved Changes",
|
||||
"You have unsaved changes. Do you want to save before closing?",
|
||||
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Save:
|
||||
self.save_file()
|
||||
event.accept()
|
||||
elif reply == QMessageBox.Discard:
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
event.accept()
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
app = QApplication(sys.argv)
|
||||
app.setApplicationName("Fallout Shelter Save Editor")
|
||||
app.setApplicationVersion("1.0")
|
||||
|
||||
# Set application style
|
||||
app.setStyle('Fusion')
|
||||
|
||||
# Create and show main window
|
||||
window = FalloutShelterSaveEditor()
|
||||
window.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
434
index.html
Normal file
434
index.html
Normal file
@@ -0,0 +1,434 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Fallout Shelter Save Editor</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-container">
|
||||
<!-- Header -->
|
||||
<header class="app-header">
|
||||
<div class="header-content">
|
||||
<div class="logo">
|
||||
<i class="fas fa-radiation"></i>
|
||||
<h1>Fallout Shelter Save Editor</h1>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<span id="current-file">No file loaded</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<!-- Sidebar -->
|
||||
<aside class="sidebar">
|
||||
<nav class="nav-tabs">
|
||||
<button class="nav-tab active" data-tab="overview">
|
||||
<i class="fas fa-home"></i>
|
||||
Overview
|
||||
</button>
|
||||
<button class="nav-tab" data-tab="resources">
|
||||
<i class="fas fa-coins"></i>
|
||||
Resources
|
||||
</button>
|
||||
<button class="nav-tab" data-tab="vault">
|
||||
<i class="fas fa-building"></i>
|
||||
Vault Info
|
||||
</button>
|
||||
<button class="nav-tab" data-tab="dwellers">
|
||||
<i class="fas fa-users"></i>
|
||||
Dwellers
|
||||
</button>
|
||||
<button class="nav-tab" data-tab="raw">
|
||||
<i class="fas fa-code"></i>
|
||||
Raw Data
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="quick-actions">
|
||||
<h3>Quick Actions</h3>
|
||||
<button class="action-btn" id="open-file-btn">
|
||||
<i class="fas fa-folder-open"></i>
|
||||
Open Save
|
||||
</button>
|
||||
<button class="action-btn" id="save-btn" disabled>
|
||||
<i class="fas fa-save"></i>
|
||||
Save
|
||||
</button>
|
||||
<button class="action-btn" id="backup-btn" disabled>
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
Backup
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Content Area -->
|
||||
<section class="content-area">
|
||||
<!-- Overview Tab -->
|
||||
<div class="tab-content active" id="overview-tab">
|
||||
<div class="welcome-screen">
|
||||
<div class="welcome-icon">
|
||||
<i class="fas fa-radiation"></i>
|
||||
</div>
|
||||
<h2>Welcome to Fallout Shelter Save Editor</h2>
|
||||
<p>Load a save file to begin editing your vault's resources, dwellers, and more.</p>
|
||||
|
||||
<div class="feature-grid">
|
||||
<div class="feature-card">
|
||||
<i class="fas fa-coins"></i>
|
||||
<h3>Resource Management</h3>
|
||||
<p>Edit caps, food, water, power, and consumables</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<i class="fas fa-users"></i>
|
||||
<h3>Dweller Editor</h3>
|
||||
<p>Modify dweller stats and equipment</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<i class="fas fa-building"></i>
|
||||
<h3>Vault Information</h3>
|
||||
<p>View and edit vault details</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<i class="fas fa-shield-alt"></i>
|
||||
<h3>Safe Editing</h3>
|
||||
<p>Automatic backups and validation</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="primary-btn" id="get-started-btn">
|
||||
<i class="fas fa-folder-open"></i>
|
||||
Get Started - Open Save File
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Resources Tab -->
|
||||
<div class="tab-content" id="resources-tab">
|
||||
<div class="tab-header">
|
||||
<h2><i class="fas fa-coins"></i> Resource Management</h2>
|
||||
<div class="tab-actions">
|
||||
<button class="secondary-btn" id="max-resources-btn">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
Max All
|
||||
</button>
|
||||
<button class="secondary-btn" id="reset-resources-btn">
|
||||
<i class="fas fa-undo"></i>
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-grid">
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon caps">
|
||||
<i class="fas fa-coins"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="caps-input">Caps</label>
|
||||
<input type="number" id="caps-input" class="resource-input" min="0" max="999999999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon food">
|
||||
<i class="fas fa-apple-alt"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="food-input">Food</label>
|
||||
<input type="number" id="food-input" class="resource-input" min="0" max="999999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon water">
|
||||
<i class="fas fa-tint"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="water-input">Water</label>
|
||||
<input type="number" id="water-input" class="resource-input" min="0" max="999999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon power">
|
||||
<i class="fas fa-bolt"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="power-input">Power</label>
|
||||
<input type="number" id="power-input" class="resource-input" min="0" max="999999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon stimpaks">
|
||||
<i class="fas fa-syringe"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="stimpaks-input">Stimpaks</label>
|
||||
<input type="number" id="stimpaks-input" class="resource-input" min="0" max="999999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon radaway">
|
||||
<i class="fas fa-radiation-alt"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="radaway-input">RadAway</label>
|
||||
<input type="number" id="radaway-input" class="resource-input" min="0" max="999999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon quantum">
|
||||
<i class="fas fa-atom"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="quantum-input">Nuka Cola Quantum</label>
|
||||
<input type="number" id="quantum-input" class="resource-input" min="0" max="999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon lunchbox">
|
||||
<i class="fas fa-gift"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="lunchbox-input">Lunchboxes</label>
|
||||
<input type="number" id="lunchbox-input" class="resource-input" min="0" max="999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon mrhandy">
|
||||
<i class="fas fa-robot"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="mrhandy-input">Mr. Handy</label>
|
||||
<input type="number" id="mrhandy-input" class="resource-input" min="0" max="99">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon petcarrier">
|
||||
<i class="fas fa-paw"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="petcarrier-input">Pet Carriers</label>
|
||||
<input type="number" id="petcarrier-input" class="resource-input" min="0" max="999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon lunchbox">
|
||||
<i class="fas fa-gift"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="lunchbox-input">Lunchboxes</label>
|
||||
<input type="number" id="lunchbox-input" class="resource-input" min="0" max="999">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon mrhandy">
|
||||
<i class="fas fa-robot"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="mrhandy-input">Mr. Handy</label>
|
||||
<input type="number" id="mrhandy-input" class="resource-input" min="0" max="99">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-card">
|
||||
<div class="resource-icon petcarrier">
|
||||
<i class="fas fa-paw"></i>
|
||||
</div>
|
||||
<div class="resource-info">
|
||||
<label for="petcarrier-input">Pet Carriers</label>
|
||||
<input type="number" id="petcarrier-input" class="resource-input" min="0" max="999">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-bar">
|
||||
<button class="primary-btn" id="apply-resources-btn">
|
||||
<i class="fas fa-check"></i>
|
||||
Apply Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Vault Info Tab -->
|
||||
<div class="tab-content" id="vault-tab">
|
||||
<div class="tab-header">
|
||||
<h2><i class="fas fa-building"></i> Vault Information</h2>
|
||||
</div>
|
||||
|
||||
<div class="vault-info-grid">
|
||||
<div class="info-card">
|
||||
<label for="vault-name-input">Vault Name</label>
|
||||
<input type="text" id="vault-name-input" class="text-input">
|
||||
</div>
|
||||
|
||||
<div class="info-card">
|
||||
<label for="vault-mode-input">Vault Mode</label>
|
||||
<select id="vault-mode-input" class="select-input">
|
||||
<option value="Normal">Normal</option>
|
||||
<option value="Survival">Survival</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="info-card">
|
||||
<label for="vault-theme-input">Vault Theme</label>
|
||||
<input type="number" id="vault-theme-input" class="number-input" min="0" max="10">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-bar">
|
||||
<button class="primary-btn" id="apply-vault-btn">
|
||||
<i class="fas fa-check"></i>
|
||||
Apply Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dwellers Tab -->
|
||||
<div class="tab-content" id="dwellers-tab">
|
||||
<div class="tab-header">
|
||||
<h2><i class="fas fa-users"></i> Dwellers</h2>
|
||||
<div class="tab-actions">
|
||||
<button class="secondary-btn" id="max-all-dwellers-btn">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
Max All Dwellers
|
||||
</button>
|
||||
<button class="secondary-btn" id="refresh-dwellers-btn">
|
||||
<i class="fas fa-sync"></i>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dwellers-container">
|
||||
<div class="dwellers-list" id="dwellers-list">
|
||||
<div class="placeholder">
|
||||
<i class="fas fa-users"></i>
|
||||
<p>Load a save file to view dwellers</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Raw Data Tab -->
|
||||
<div class="tab-content" id="raw-tab">
|
||||
<div class="tab-header">
|
||||
<h2><i class="fas fa-code"></i> Raw Data</h2>
|
||||
<div class="tab-actions">
|
||||
<button class="secondary-btn" id="format-json-btn">
|
||||
<i class="fas fa-indent"></i>
|
||||
Format
|
||||
</button>
|
||||
<button class="secondary-btn" id="copy-json-btn">
|
||||
<i class="fas fa-copy"></i>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="raw-data-container">
|
||||
<textarea id="raw-data-textarea" class="raw-data-textarea" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- Status Bar -->
|
||||
<footer class="status-bar">
|
||||
<div class="status-left">
|
||||
<span id="status-text">Ready</span>
|
||||
</div>
|
||||
<div class="status-right">
|
||||
<span id="file-size">-</span>
|
||||
<span class="separator">|</span>
|
||||
<span id="last-modified">-</span>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Loading Overlay -->
|
||||
<div class="loading-overlay" id="loading-overlay">
|
||||
<div class="loading-spinner">
|
||||
<i class="fas fa-radiation fa-spin"></i>
|
||||
<p>Processing save file...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toast Notifications -->
|
||||
<div class="toast-container" id="toast-container"></div>
|
||||
|
||||
<!-- Startup Animation -->
|
||||
<div class="startup-overlay" id="startup-overlay">
|
||||
<div class="startup-content">
|
||||
<div class="vault-door">
|
||||
<div class="vault-door-outer">
|
||||
<div class="vault-door-inner">
|
||||
<div class="vault-number">111</div>
|
||||
<div class="vault-spokes">
|
||||
<div class="spoke"></div>
|
||||
<div class="spoke"></div>
|
||||
<div class="spoke"></div>
|
||||
<div class="spoke"></div>
|
||||
<div class="spoke"></div>
|
||||
<div class="spoke"></div>
|
||||
<div class="spoke"></div>
|
||||
<div class="spoke"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="startup-text">
|
||||
<h1 class="startup-title">FALLOUT SHELTER</h1>
|
||||
<h2 class="startup-subtitle">SAVE EDITOR</h2>
|
||||
<div class="version-info">
|
||||
<span class="version-badge">v1.0.0</span>
|
||||
<span class="vault-tec-badge">VAULT-TEC APPROVED</span>
|
||||
</div>
|
||||
<div class="loading-dots">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
<p class="startup-status" id="startup-status">Initializing Vault-Tec Systems...</p>
|
||||
</div>
|
||||
|
||||
<div class="startup-progress">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" id="startup-progress"></div>
|
||||
</div>
|
||||
<div class="progress-text">
|
||||
<span>VAULT-TEC APPROVED</span>
|
||||
<span id="progress-percent">0%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="radiation-particles">
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
139
main.js
Normal file
139
main.js
Normal file
@@ -0,0 +1,139 @@
|
||||
const { app, BrowserWindow, Menu, dialog, ipcMain } = require('electron');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
let mainWindow;
|
||||
|
||||
// Disable GPU acceleration to prevent crashes
|
||||
app.disableHardwareAcceleration();
|
||||
|
||||
function createWindow() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
},
|
||||
show: false,
|
||||
backgroundColor: '#1a1a2e'
|
||||
});
|
||||
|
||||
mainWindow.loadFile('index.html');
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.show();
|
||||
});
|
||||
|
||||
if (process.argv.includes('--dev')) {
|
||||
mainWindow.webContents.openDevTools();
|
||||
}
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null;
|
||||
});
|
||||
|
||||
createMenu();
|
||||
}
|
||||
|
||||
function createMenu() {
|
||||
const template = [
|
||||
{
|
||||
label: 'File',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Open Save File',
|
||||
accelerator: 'CmdOrCtrl+O',
|
||||
click: () => openSaveFile()
|
||||
},
|
||||
{
|
||||
label: 'Save',
|
||||
accelerator: 'CmdOrCtrl+S',
|
||||
click: () => mainWindow.webContents.send('menu-save')
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Exit',
|
||||
click: () => app.quit()
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
}
|
||||
|
||||
async function openSaveFile() {
|
||||
try {
|
||||
const result = await dialog.showOpenDialog(mainWindow, {
|
||||
title: 'Open Fallout Shelter Save File',
|
||||
filters: [
|
||||
{ name: 'Save Files', extensions: ['sav'] },
|
||||
{ name: 'All Files', extensions: ['*'] }
|
||||
],
|
||||
properties: ['openFile']
|
||||
});
|
||||
|
||||
if (!result.canceled && result.filePaths.length > 0) {
|
||||
const filePath = result.filePaths[0];
|
||||
const fileData = fs.readFileSync(filePath, 'utf8');
|
||||
mainWindow.webContents.send('file-opened', {
|
||||
path: filePath,
|
||||
data: fileData,
|
||||
name: path.basename(filePath)
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// IPC handlers
|
||||
ipcMain.on('open-file-dialog', () => {
|
||||
openSaveFile();
|
||||
});
|
||||
|
||||
ipcMain.handle('save-file', async (event, filePath, data) => {
|
||||
try {
|
||||
console.log('Main process: Saving file to:', filePath);
|
||||
console.log('Main process: Data length:', data.length);
|
||||
|
||||
fs.writeFileSync(filePath, data, 'utf8');
|
||||
console.log('Main process: File saved successfully');
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Main process: Save error:', error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('create-backup', async (event, originalPath) => {
|
||||
try {
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
const backupPath = `${originalPath}.backup_${timestamp}`;
|
||||
fs.copyFileSync(originalPath, backupPath);
|
||||
return { success: true, backupPath };
|
||||
} catch (error) {
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
4125
package-lock.json
generated
Normal file
4125
package-lock.json
generated
Normal file
@@ -0,0 +1,4125 @@
|
||||
{
|
||||
"name": "fallout-shelter-save-editor",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "fallout-shelter-save-editor",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^27.0.0",
|
||||
"electron-builder": "^24.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@develar/schema-utils": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
|
||||
"integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.0",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/asar": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz",
|
||||
"integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^5.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"minimatch": "^3.0.4"
|
||||
},
|
||||
"bin": {
|
||||
"asar": "bin/asar.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/asar/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/asar/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/get": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz",
|
||||
"integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
"env-paths": "^2.2.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"got": "^11.8.5",
|
||||
"progress": "^2.0.3",
|
||||
"semver": "^6.2.0",
|
||||
"sumchecker": "^3.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"global-agent": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/notarize": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz",
|
||||
"integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"promise-retry": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/notarize/node_modules/fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/notarize/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/notarize/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/osx-sign": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz",
|
||||
"integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"compare-version": "^0.1.2",
|
||||
"debug": "^4.3.4",
|
||||
"fs-extra": "^10.0.0",
|
||||
"isbinaryfile": "^4.0.8",
|
||||
"minimist": "^1.2.6",
|
||||
"plist": "^3.0.5"
|
||||
},
|
||||
"bin": {
|
||||
"electron-osx-flat": "bin/electron-osx-flat.js",
|
||||
"electron-osx-sign": "bin/electron-osx-sign.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/osx-sign/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/osx-sign/node_modules/isbinaryfile": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz",
|
||||
"integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/gjtorikian/"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/osx-sign/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/osx-sign/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz",
|
||||
"integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@electron/asar": "^3.2.1",
|
||||
"@malept/cross-spawn-promise": "^1.1.0",
|
||||
"debug": "^4.3.1",
|
||||
"dir-compare": "^3.0.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"plist": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal/node_modules/fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^5.1.2",
|
||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||
"strip-ansi": "^7.0.1",
|
||||
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
|
||||
"wrap-ansi": "^8.1.0",
|
||||
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eastasianwidth": "^0.2.0",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.1.0",
|
||||
"string-width": "^5.0.1",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@malept/cross-spawn-promise": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz",
|
||||
"integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/malept"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund"
|
||||
}
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@malept/flatpak-bundler": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz",
|
||||
"integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^9.0.0",
|
||||
"lodash": "^4.17.15",
|
||||
"tmp-promise": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@malept/flatpak-bundler/node_modules/fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@malept/flatpak-bundler/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@malept/flatpak-bundler/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"defer-to-connect": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||
"integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cacheable-request": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
|
||||
"integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/http-cache-semantics": "*",
|
||||
"@types/keyv": "^3.1.4",
|
||||
"@types/node": "*",
|
||||
"@types/responselike": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/debug": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||
"integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/ms": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/fs-extra": {
|
||||
"version": "9.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
|
||||
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/http-cache-semantics": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
|
||||
"integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/keyv": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
|
||||
"integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ms": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
|
||||
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/plist": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz",
|
||||
"integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"xmlbuilder": ">=11.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/responselike": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
|
||||
"integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/verror": {
|
||||
"version": "1.10.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz",
|
||||
"integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@types/yauzl": {
|
||||
"version": "2.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
|
||||
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.8.10",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
|
||||
"integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/7zip-bin": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz",
|
||||
"integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"ajv": "^6.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-bin": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz",
|
||||
"integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/app-builder-lib": {
|
||||
"version": "24.13.3",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz",
|
||||
"integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@develar/schema-utils": "~2.6.5",
|
||||
"@electron/notarize": "2.2.1",
|
||||
"@electron/osx-sign": "1.0.5",
|
||||
"@electron/universal": "1.5.1",
|
||||
"@malept/flatpak-bundler": "^0.4.0",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"chromium-pickle-js": "^0.2.0",
|
||||
"debug": "^4.3.4",
|
||||
"ejs": "^3.1.8",
|
||||
"electron-publish": "24.13.1",
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"hosted-git-info": "^4.1.0",
|
||||
"is-ci": "^3.0.0",
|
||||
"isbinaryfile": "^5.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lazy-val": "^1.0.5",
|
||||
"minimatch": "^5.1.1",
|
||||
"read-config-file": "6.3.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"semver": "^7.3.8",
|
||||
"tar": "^6.1.12",
|
||||
"temp-file": "^3.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"dmg-builder": "24.13.3",
|
||||
"electron-builder-squirrel-windows": "24.13.3"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/app-builder-lib/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/archiver": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz",
|
||||
"integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"archiver-utils": "^2.1.0",
|
||||
"async": "^3.2.4",
|
||||
"buffer-crc32": "^0.2.1",
|
||||
"readable-stream": "^3.6.0",
|
||||
"readdir-glob": "^1.1.2",
|
||||
"tar-stream": "^2.2.0",
|
||||
"zip-stream": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/archiver-utils": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
|
||||
"integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"lazystream": "^1.0.0",
|
||||
"lodash.defaults": "^4.2.0",
|
||||
"lodash.difference": "^4.5.0",
|
||||
"lodash.flatten": "^4.4.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.union": "^4.6.0",
|
||||
"normalize-path": "^3.0.0",
|
||||
"readable-stream": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/archiver-utils/node_modules/readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/archiver-utils/node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/archiver-utils/node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/astral-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
|
||||
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
|
||||
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/async-exit-hook": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
|
||||
"integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bluebird-lst": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz",
|
||||
"integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bluebird": "^3.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/boolean": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
|
||||
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
|
||||
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-equal": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz",
|
||||
"integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/builder-util": {
|
||||
"version": "24.13.1",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz",
|
||||
"integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/debug": "^4.1.6",
|
||||
"7zip-bin": "~5.2.0",
|
||||
"app-builder-bin": "4.0.0",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"chalk": "^4.1.2",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"debug": "^4.3.4",
|
||||
"fs-extra": "^10.1.0",
|
||||
"http-proxy-agent": "^5.0.0",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"is-ci": "^3.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"source-map-support": "^0.5.19",
|
||||
"stat-mode": "^1.0.0",
|
||||
"temp-file": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/builder-util-runtime": {
|
||||
"version": "9.2.4",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz",
|
||||
"integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/builder-util/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/builder-util/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/builder-util/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-lookup": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-request": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
|
||||
"integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"clone-response": "^1.0.2",
|
||||
"get-stream": "^5.1.0",
|
||||
"http-cache-semantics": "^4.0.0",
|
||||
"keyv": "^4.0.0",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"normalize-url": "^6.0.1",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/chromium-pickle-js": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz",
|
||||
"integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ci-info": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
|
||||
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/sibiraj-s"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-truncate": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
|
||||
"integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"slice-ansi": "^3.0.0",
|
||||
"string-width": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/clone-response": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
|
||||
"integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-response": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
|
||||
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/compare-version": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz",
|
||||
"integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/compress-commons": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz",
|
||||
"integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"buffer-crc32": "^0.2.13",
|
||||
"crc32-stream": "^4.0.2",
|
||||
"normalize-path": "^3.0.0",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/config-file-ts": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz",
|
||||
"integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"glob": "^10.3.10",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/config-file-ts/node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.4",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^1.11.1"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/config-file-ts/node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/config-file-ts/node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/crc": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
|
||||
"integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/crc-32": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"crc32": "bin/crc32.njs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/crc32-stream": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz",
|
||||
"integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"crc-32": "^1.2.0",
|
||||
"readable-stream": "^3.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/crypto-js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response/node_modules/mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/defer-to-connect": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
||||
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/define-properties": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
||||
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0",
|
||||
"object-keys": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-node": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
|
||||
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/dir-compare": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz",
|
||||
"integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-equal": "^1.0.0",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/dir-compare/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dir-compare/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/dmg-builder": {
|
||||
"version": "24.13.3",
|
||||
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz",
|
||||
"integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"app-builder-lib": "24.13.3",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"fs-extra": "^10.1.0",
|
||||
"iconv-lite": "^0.6.2",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"dmg-license": "^1.0.11"
|
||||
}
|
||||
},
|
||||
"node_modules/dmg-builder/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/dmg-builder/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/dmg-builder/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dmg-license": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz",
|
||||
"integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/plist": "^3.0.1",
|
||||
"@types/verror": "^1.10.3",
|
||||
"ajv": "^6.10.0",
|
||||
"crc": "^3.8.0",
|
||||
"iconv-corefoundation": "^1.1.7",
|
||||
"plist": "^3.0.4",
|
||||
"smart-buffer": "^4.0.2",
|
||||
"verror": "^1.10.0"
|
||||
},
|
||||
"bin": {
|
||||
"dmg-license": "bin/dmg-license.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz",
|
||||
"integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-expand": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
|
||||
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"jake": "^10.8.5"
|
||||
},
|
||||
"bin": {
|
||||
"ejs": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "27.3.11",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-27.3.11.tgz",
|
||||
"integrity": "sha512-E1SiyEoI8iW5LW/MigCr7tJuQe7+0105UjqY7FkmCD12e2O6vtUbQ0j05HaBh2YgvkcEVgvQ2A8suIq5b5m6Gw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@electron/get": "^2.0.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"extract-zip": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"electron": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.20.55"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder": {
|
||||
"version": "24.13.3",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz",
|
||||
"integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"app-builder-lib": "24.13.3",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"chalk": "^4.1.2",
|
||||
"dmg-builder": "24.13.3",
|
||||
"fs-extra": "^10.1.0",
|
||||
"is-ci": "^3.0.0",
|
||||
"lazy-val": "^1.0.5",
|
||||
"read-config-file": "6.3.2",
|
||||
"simple-update-notifier": "2.0.0",
|
||||
"yargs": "^17.6.2"
|
||||
},
|
||||
"bin": {
|
||||
"electron-builder": "cli.js",
|
||||
"install-app-deps": "install-app-deps.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder-squirrel-windows": {
|
||||
"version": "24.13.3",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz",
|
||||
"integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"app-builder-lib": "24.13.3",
|
||||
"archiver": "^5.3.1",
|
||||
"builder-util": "24.13.1",
|
||||
"fs-extra": "^10.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder-squirrel-windows/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-builder/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-publish": {
|
||||
"version": "24.13.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz",
|
||||
"integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/fs-extra": "^9.0.11",
|
||||
"builder-util": "24.13.1",
|
||||
"builder-util-runtime": "9.2.4",
|
||||
"chalk": "^4.1.2",
|
||||
"fs-extra": "^10.1.0",
|
||||
"lazy-val": "^1.0.5",
|
||||
"mime": "^2.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-publish/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-publish/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-publish/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/err-code": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
|
||||
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-error": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
|
||||
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/extract-zip": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
|
||||
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
"get-stream": "^5.1.0",
|
||||
"yauzl": "^2.10.0"
|
||||
},
|
||||
"bin": {
|
||||
"extract-zip": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.17.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@types/yauzl": "^2.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/extsprintf": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz",
|
||||
"integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==",
|
||||
"dev": true,
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fd-slicer": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/filelist": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
|
||||
"integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"minimatch": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
||||
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.6",
|
||||
"signal-exit": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6 <7 || >=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/global-agent": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
|
||||
"integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"boolean": "^3.0.1",
|
||||
"es6-error": "^4.1.1",
|
||||
"matcher": "^3.0.0",
|
||||
"roarr": "^2.15.3",
|
||||
"semver": "^7.3.2",
|
||||
"serialize-error": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/global-agent/node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/globalthis": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
|
||||
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"define-properties": "^1.2.1",
|
||||
"gopd": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/got": {
|
||||
"version": "11.8.6",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
|
||||
"integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.0.0",
|
||||
"@szmarczak/http-timer": "^4.0.5",
|
||||
"@types/cacheable-request": "^6.0.1",
|
||||
"@types/responselike": "^1.0.0",
|
||||
"cacheable-lookup": "^5.0.3",
|
||||
"cacheable-request": "^7.0.2",
|
||||
"decompress-response": "^6.0.0",
|
||||
"http2-wrapper": "^1.0.0-beta.5.2",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"p-cancelable": "^2.0.0",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/got?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"es-define-property": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
|
||||
"integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
|
||||
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tootallnate/once": "2",
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/http2-wrapper": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
|
||||
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"quick-lru": "^5.1.1",
|
||||
"resolve-alpn": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-corefoundation": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz",
|
||||
"integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"dependencies": {
|
||||
"cli-truncate": "^2.1.0",
|
||||
"node-addon-api": "^1.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.11.2 || >=10"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/is-ci": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
|
||||
"integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ci-info": "^3.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"is-ci": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/isbinaryfile": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.4.tgz",
|
||||
"integrity": "sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/gjtorikian/"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
||||
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@pkgjs/parseargs": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jake": {
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
|
||||
"integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"async": "^3.2.3",
|
||||
"chalk": "^4.0.2",
|
||||
"filelist": "^1.0.4",
|
||||
"minimatch": "^3.1.2"
|
||||
},
|
||||
"bin": {
|
||||
"jake": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/json-buffer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lazy-val": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
|
||||
"integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lazystream": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
|
||||
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"readable-stream": "^2.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6.3"
|
||||
}
|
||||
},
|
||||
"node_modules/lazystream/node_modules/readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/lazystream/node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lazystream/node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.defaults": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.difference": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
|
||||
"integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.flatten": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
||||
"integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lodash.union": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
|
||||
"integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/matcher": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
|
||||
"integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-response": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz",
|
||||
"integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-url": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
|
||||
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/p-cancelable": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
|
||||
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.2.0",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/plist": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
|
||||
"integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.8.8",
|
||||
"base64-js": "^1.5.1",
|
||||
"xmlbuilder": "^15.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/promise-retry": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
|
||||
"integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"err-code": "^2.0.2",
|
||||
"retry": "^0.12.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
||||
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/quick-lru": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
|
||||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/read-config-file": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz",
|
||||
"integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"config-file-ts": "^0.2.4",
|
||||
"dotenv": "^9.0.2",
|
||||
"dotenv-expand": "^5.1.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"json5": "^2.2.0",
|
||||
"lazy-val": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/readdir-glob": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz",
|
||||
"integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minimatch": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-alpn": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
|
||||
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/responselike": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
|
||||
"integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lowercase-keys": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/roarr": {
|
||||
"version": "2.15.4",
|
||||
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
|
||||
"integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"boolean": "^3.0.1",
|
||||
"detect-node": "^2.0.4",
|
||||
"globalthis": "^1.0.1",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"semver-compare": "^1.0.0",
|
||||
"sprintf-js": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sanitize-filename": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
|
||||
"integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
|
||||
"dev": true,
|
||||
"license": "WTFPL OR ISC",
|
||||
"dependencies": {
|
||||
"truncate-utf8-bytes": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/semver-compare": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
||||
"integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/serialize-error": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
|
||||
"integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"type-fest": "^0.13.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-update-notifier": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
|
||||
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^7.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-update-notifier/node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/slice-ansi": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
|
||||
"integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"astral-regex": "^2.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/smart-buffer": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sprintf-js": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
||||
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/stat-mode": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz",
|
||||
"integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width-cjs": {
|
||||
"name": "string-width",
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi-cjs": {
|
||||
"name": "strip-ansi",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/sumchecker": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
|
||||
"integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
"fs-constants": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/temp-file": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz",
|
||||
"integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"fs-extra": "^10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/temp-file/node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/temp-file/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/temp-file/node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
||||
"integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp-promise": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz",
|
||||
"integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tmp": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/truncate-utf8-bytes": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
|
||||
"integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==",
|
||||
"dev": true,
|
||||
"license": "WTFPL",
|
||||
"dependencies": {
|
||||
"utf8-byte-length": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
|
||||
"integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
|
||||
"dev": true,
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf8-byte-length": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz",
|
||||
"integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==",
|
||||
"dev": true,
|
||||
"license": "(WTFPL OR MIT)"
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/verror": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
|
||||
"integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs": {
|
||||
"name": "wrap-ansi",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "15.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
||||
"integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yauzl": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-crc32": "~0.2.3",
|
||||
"fd-slicer": "~1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/zip-stream": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz",
|
||||
"integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"archiver-utils": "^3.0.4",
|
||||
"compress-commons": "^4.1.2",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/zip-stream/node_modules/archiver-utils": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz",
|
||||
"integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.2.3",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"lazystream": "^1.0.0",
|
||||
"lodash.defaults": "^4.2.0",
|
||||
"lodash.difference": "^4.5.0",
|
||||
"lodash.flatten": "^4.4.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.union": "^4.6.0",
|
||||
"normalize-path": "^3.0.0",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
package.json
Normal file
57
package.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "fallout-shelter-save-editor",
|
||||
"version": "1.0.0",
|
||||
"description": "A modern save editor for Fallout Shelter with AES decryption support",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "electron .",
|
||||
"dev": "electron . --dev",
|
||||
"build": "electron-builder",
|
||||
"build-win": "electron-builder --win",
|
||||
"build-mac": "electron-builder --mac",
|
||||
"build-linux": "electron-builder --linux",
|
||||
"pack": "electron-builder --dir",
|
||||
"dist": "electron-builder --publish=never"
|
||||
},
|
||||
"keywords": [
|
||||
"fallout-shelter",
|
||||
"save-editor",
|
||||
"game-modding",
|
||||
"electron"
|
||||
],
|
||||
"author": "Kiro AI Assistant",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"electron": "^27.0.0",
|
||||
"electron-builder": "^24.6.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.2.0"
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.kiro.fallout-shelter-editor",
|
||||
"productName": "Fallout Shelter Save Editor",
|
||||
"directories": {
|
||||
"output": "dist"
|
||||
},
|
||||
"files": [
|
||||
"main.js",
|
||||
"renderer.js",
|
||||
"index.html",
|
||||
"styles.css",
|
||||
"assets/**/*"
|
||||
],
|
||||
"win": {
|
||||
"target": "nsis",
|
||||
"icon": "assets/icon.ico"
|
||||
},
|
||||
"mac": {
|
||||
"target": "dmg",
|
||||
"icon": "assets/icon.icns"
|
||||
},
|
||||
"linux": {
|
||||
"target": "AppImage",
|
||||
"icon": "assets/icon.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
824
renderer.js
Normal file
824
renderer.js
Normal file
@@ -0,0 +1,824 @@
|
||||
const { ipcRenderer } = require('electron');
|
||||
const CryptoJS = require('crypto-js');
|
||||
|
||||
// Application state
|
||||
let currentSaveData = null;
|
||||
let currentFilePath = null;
|
||||
let isModified = false;
|
||||
|
||||
// AES encryption constants
|
||||
const AES_KEY_WORDS = [2815074099, 1725469378, 4039046167, 874293617, 3063605751, 3133984764, 4097598161, 3620741625];
|
||||
const AES_KEY = CryptoJS.lib.WordArray.create(AES_KEY_WORDS);
|
||||
const AES_IV = CryptoJS.enc.Hex.parse('7475383967656A693334307438397532');
|
||||
|
||||
// Initialize the application
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setTimeout(() => {
|
||||
startupAnimation();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
function startupAnimation() {
|
||||
const overlay = document.getElementById('startup-overlay');
|
||||
const progressFill = document.getElementById('startup-progress');
|
||||
const progressPercent = document.getElementById('progress-percent');
|
||||
const statusText = document.getElementById('startup-status');
|
||||
|
||||
if (!overlay || !progressFill || !progressPercent || !statusText) {
|
||||
initializeApp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize
|
||||
progressFill.style.width = '0%';
|
||||
progressPercent.textContent = '0%';
|
||||
|
||||
const steps = [
|
||||
{ progress: 25, status: 'Loading Vault-Tec Database...', delay: 300 },
|
||||
{ progress: 50, status: 'Initializing Encryption...', delay: 300 },
|
||||
{ progress: 75, status: 'Connecting Systems...', delay: 300 },
|
||||
{ progress: 100, status: 'Welcome to Vault-Tec!', delay: 400 }
|
||||
];
|
||||
|
||||
let currentStep = 0;
|
||||
|
||||
function updateProgress() {
|
||||
if (currentStep < steps.length) {
|
||||
const step = steps[currentStep];
|
||||
|
||||
statusText.textContent = step.status;
|
||||
progressFill.style.width = step.progress + '%';
|
||||
progressPercent.textContent = step.progress + '%';
|
||||
|
||||
currentStep++;
|
||||
setTimeout(updateProgress, step.delay);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
overlay.classList.add('fade-out');
|
||||
setTimeout(() => {
|
||||
overlay.style.display = 'none';
|
||||
initializeApp();
|
||||
}, 800);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(updateProgress, 500);
|
||||
}
|
||||
|
||||
function initializeApp() {
|
||||
initializeEventListeners();
|
||||
initializeTabSystem();
|
||||
updateUI();
|
||||
setStatus('Ready');
|
||||
|
||||
setTimeout(() => {
|
||||
showToast('Vault-Tec Save Editor ready!', 'success');
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function initializeEventListeners() {
|
||||
// Navigation tabs
|
||||
document.querySelectorAll('.nav-tab').forEach(tab => {
|
||||
tab.addEventListener('click', () => switchTab(tab.dataset.tab));
|
||||
});
|
||||
|
||||
// File operations
|
||||
const openFileBtn = document.getElementById('open-file-btn');
|
||||
const getStartedBtn = document.getElementById('get-started-btn');
|
||||
const saveBtn = document.getElementById('save-btn');
|
||||
const backupBtn = document.getElementById('backup-btn');
|
||||
|
||||
if (openFileBtn) openFileBtn.addEventListener('click', openFile);
|
||||
if (getStartedBtn) getStartedBtn.addEventListener('click', openFile);
|
||||
if (saveBtn) saveBtn.addEventListener('click', saveFile);
|
||||
if (backupBtn) backupBtn.addEventListener('click', createBackup);
|
||||
|
||||
// Resource operations
|
||||
const maxResourcesBtn = document.getElementById('max-resources-btn');
|
||||
const resetResourcesBtn = document.getElementById('reset-resources-btn');
|
||||
const applyResourcesBtn = document.getElementById('apply-resources-btn');
|
||||
|
||||
if (maxResourcesBtn) maxResourcesBtn.addEventListener('click', maxAllResources);
|
||||
if (resetResourcesBtn) resetResourcesBtn.addEventListener('click', resetResources);
|
||||
if (applyResourcesBtn) applyResourcesBtn.addEventListener('click', applyResourceChanges);
|
||||
|
||||
// Vault operations
|
||||
const applyVaultBtn = document.getElementById('apply-vault-btn');
|
||||
if (applyVaultBtn) applyVaultBtn.addEventListener('click', applyVaultChanges);
|
||||
|
||||
// Raw data operations
|
||||
const formatJsonBtn = document.getElementById('format-json-btn');
|
||||
const copyJsonBtn = document.getElementById('copy-json-btn');
|
||||
|
||||
if (formatJsonBtn) formatJsonBtn.addEventListener('click', formatJSON);
|
||||
if (copyJsonBtn) copyJsonBtn.addEventListener('click', copyJSON);
|
||||
|
||||
// Dweller operations
|
||||
const maxAllDwellersBtn = document.getElementById('max-all-dwellers-btn');
|
||||
const refreshDwellersBtn = document.getElementById('refresh-dwellers-btn');
|
||||
|
||||
if (maxAllDwellersBtn) maxAllDwellersBtn.addEventListener('click', maxAllDwellers);
|
||||
if (refreshDwellersBtn) refreshDwellersBtn.addEventListener('click', populateDwellers);
|
||||
|
||||
// IPC listeners
|
||||
ipcRenderer.on('file-opened', handleFileOpened);
|
||||
ipcRenderer.on('menu-save', saveFile);
|
||||
}
|
||||
|
||||
function initializeTabSystem() {
|
||||
switchTab('overview');
|
||||
}
|
||||
|
||||
function switchTab(tabName) {
|
||||
document.querySelectorAll('.nav-tab').forEach(tab => {
|
||||
tab.classList.toggle('active', tab.dataset.tab === tabName);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.tab-content').forEach(content => {
|
||||
content.classList.toggle('active', content.id === `${tabName}-tab`);
|
||||
});
|
||||
}
|
||||
|
||||
function openFile() {
|
||||
ipcRenderer.send('open-file-dialog');
|
||||
}
|
||||
|
||||
async function handleFileOpened(event, fileData) {
|
||||
showLoading(true);
|
||||
setStatus('Loading save file...');
|
||||
|
||||
try {
|
||||
currentFilePath = fileData.path;
|
||||
document.getElementById('current-file').textContent = fileData.name;
|
||||
|
||||
const decryptedData = decryptSaveData(fileData.data.trim());
|
||||
currentSaveData = JSON.parse(decryptedData);
|
||||
|
||||
populateResourceInputs();
|
||||
populateVaultInfo();
|
||||
populateDwellers();
|
||||
updateRawData();
|
||||
|
||||
document.getElementById('save-btn').disabled = false;
|
||||
document.getElementById('backup-btn').disabled = false;
|
||||
|
||||
switchTab('resources');
|
||||
|
||||
setStatus('Save file loaded successfully');
|
||||
showToast('Save file loaded successfully', 'success');
|
||||
setModified(false);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading save file:', error);
|
||||
showToast(`Error loading save file: ${error.message}`, 'error');
|
||||
setStatus('Error loading save file');
|
||||
} finally {
|
||||
showLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
function decryptSaveData(base64Data) {
|
||||
try {
|
||||
const ciphertext = CryptoJS.enc.Base64.parse(base64Data);
|
||||
const cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext: ciphertext
|
||||
});
|
||||
|
||||
const decrypted = CryptoJS.AES.decrypt(cipherParams, AES_KEY, {
|
||||
iv: AES_IV,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
const decryptedString = decrypted.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
if (!decryptedString) {
|
||||
throw new Error('Decryption failed - invalid key or corrupted data');
|
||||
}
|
||||
|
||||
return decryptedString;
|
||||
} catch (error) {
|
||||
throw new Error(`Decryption failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function encryptSaveData(jsonString) {
|
||||
try {
|
||||
const encrypted = CryptoJS.AES.encrypt(jsonString, AES_KEY, {
|
||||
iv: AES_IV,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
return encrypted.toString();
|
||||
} catch (error) {
|
||||
throw new Error(`Encryption failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function populateResourceInputs() {
|
||||
if (!currentSaveData || !currentSaveData.vault || !currentSaveData.vault.storage) {
|
||||
console.log('No vault storage data found');
|
||||
return;
|
||||
}
|
||||
|
||||
const resources = currentSaveData.vault.storage.resources;
|
||||
console.log('Available resources:', Object.keys(resources));
|
||||
|
||||
const resourceMap = {
|
||||
'caps-input': 'Nuka',
|
||||
'food-input': 'Food',
|
||||
'water-input': 'Water',
|
||||
'power-input': 'Energy',
|
||||
'stimpaks-input': 'StimPack',
|
||||
'radaway-input': 'RadAway',
|
||||
'quantum-input': 'NukaColaQuantum',
|
||||
'lunchbox-input': 'Lunchbox',
|
||||
'mrhandy-input': 'MrHandy',
|
||||
'petcarrier-input': 'PetCarrier'
|
||||
};
|
||||
|
||||
Object.entries(resourceMap).forEach(([inputId, resourceKey]) => {
|
||||
const input = document.getElementById(inputId);
|
||||
if (input && resources[resourceKey] !== undefined) {
|
||||
input.value = Math.floor(resources[resourceKey]);
|
||||
console.log(`Set ${inputId} to ${resources[resourceKey]}`);
|
||||
} else {
|
||||
console.log(`Could not find ${inputId} or ${resourceKey}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function populateVaultInfo() {
|
||||
if (!currentSaveData || !currentSaveData.vault) {
|
||||
return;
|
||||
}
|
||||
|
||||
const vault = currentSaveData.vault;
|
||||
|
||||
const vaultNameInput = document.getElementById('vault-name-input');
|
||||
if (vaultNameInput && vault.VaultName !== undefined) {
|
||||
vaultNameInput.value = vault.VaultName;
|
||||
}
|
||||
|
||||
const vaultModeInput = document.getElementById('vault-mode-input');
|
||||
if (vaultModeInput && vault.VaultMode !== undefined) {
|
||||
vaultModeInput.value = vault.VaultMode;
|
||||
}
|
||||
|
||||
const vaultThemeInput = document.getElementById('vault-theme-input');
|
||||
if (vaultThemeInput && vault.VaultTheme !== undefined) {
|
||||
vaultThemeInput.value = vault.VaultTheme;
|
||||
}
|
||||
}
|
||||
|
||||
function applyResourceChanges() {
|
||||
if (!currentSaveData || !currentSaveData.vault || !currentSaveData.vault.storage) {
|
||||
showToast('No save data loaded', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Applying resource changes...');
|
||||
const resources = currentSaveData.vault.storage.resources;
|
||||
console.log('Current resources before changes:', resources);
|
||||
|
||||
const resourceMap = {
|
||||
'caps-input': 'Nuka',
|
||||
'food-input': 'Food',
|
||||
'water-input': 'Water',
|
||||
'power-input': 'Energy',
|
||||
'stimpaks-input': 'StimPack',
|
||||
'radaway-input': 'RadAway',
|
||||
'quantum-input': 'NukaColaQuantum',
|
||||
'lunchbox-input': 'Lunchbox',
|
||||
'mrhandy-input': 'MrHandy',
|
||||
'petcarrier-input': 'PetCarrier'
|
||||
};
|
||||
|
||||
let changesApplied = 0;
|
||||
|
||||
Object.entries(resourceMap).forEach(([inputId, resourceKey]) => {
|
||||
const input = document.getElementById(inputId);
|
||||
if (input && input.value.trim()) {
|
||||
const value = parseFloat(input.value);
|
||||
if (!isNaN(value) && value >= 0) {
|
||||
console.log(`Changing ${resourceKey} from ${resources[resourceKey]} to ${value}`);
|
||||
resources[resourceKey] = value;
|
||||
changesApplied++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Resources after changes:', resources);
|
||||
console.log(`Applied ${changesApplied} changes`);
|
||||
|
||||
if (changesApplied > 0) {
|
||||
setModified(true);
|
||||
updateRawData();
|
||||
showToast(`Applied ${changesApplied} resource changes`, 'success');
|
||||
} else {
|
||||
showToast('No valid changes to apply', 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
function maxAllResources() {
|
||||
const maxValues = {
|
||||
'caps-input': 999999,
|
||||
'food-input': 999999,
|
||||
'water-input': 999999,
|
||||
'power-input': 999999,
|
||||
'stimpaks-input': 999999,
|
||||
'radaway-input': 999999,
|
||||
'quantum-input': 999,
|
||||
'lunchbox-input': 999,
|
||||
'mrhandy-input': 99,
|
||||
'petcarrier-input': 999
|
||||
};
|
||||
|
||||
Object.entries(maxValues).forEach(([inputId, value]) => {
|
||||
const input = document.getElementById(inputId);
|
||||
if (input) {
|
||||
input.value = value;
|
||||
}
|
||||
});
|
||||
|
||||
applyResourceChanges();
|
||||
}
|
||||
|
||||
function resetResources() {
|
||||
populateResourceInputs();
|
||||
showToast('Resources reset to saved values', 'info');
|
||||
}
|
||||
|
||||
function applyVaultChanges() {
|
||||
if (!currentSaveData || !currentSaveData.vault) {
|
||||
showToast('No save data loaded', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const vault = currentSaveData.vault;
|
||||
let changesApplied = 0;
|
||||
|
||||
const vaultNameInput = document.getElementById('vault-name-input');
|
||||
if (vaultNameInput && vaultNameInput.value.trim()) {
|
||||
vault.VaultName = vaultNameInput.value.trim();
|
||||
changesApplied++;
|
||||
}
|
||||
|
||||
const vaultModeInput = document.getElementById('vault-mode-input');
|
||||
if (vaultModeInput && vaultModeInput.value) {
|
||||
vault.VaultMode = vaultModeInput.value;
|
||||
changesApplied++;
|
||||
}
|
||||
|
||||
const vaultThemeInput = document.getElementById('vault-theme-input');
|
||||
if (vaultThemeInput && vaultThemeInput.value.trim()) {
|
||||
const theme = parseInt(vaultThemeInput.value);
|
||||
if (!isNaN(theme) && theme >= 0) {
|
||||
vault.VaultTheme = theme;
|
||||
changesApplied++;
|
||||
}
|
||||
}
|
||||
|
||||
if (changesApplied > 0) {
|
||||
setModified(true);
|
||||
updateRawData();
|
||||
showToast(`Applied ${changesApplied} vault changes`, 'success');
|
||||
} else {
|
||||
showToast('No valid changes to apply', 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
function updateRawData() {
|
||||
const textarea = document.getElementById('raw-data-textarea');
|
||||
if (currentSaveData && textarea) {
|
||||
textarea.value = JSON.stringify(currentSaveData, null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
function formatJSON() {
|
||||
const textarea = document.getElementById('raw-data-textarea');
|
||||
if (!textarea) return;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(textarea.value);
|
||||
textarea.value = JSON.stringify(parsed, null, 2);
|
||||
showToast('JSON formatted successfully', 'success');
|
||||
} catch (error) {
|
||||
showToast('Invalid JSON format', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function copyJSON() {
|
||||
const textarea = document.getElementById('raw-data-textarea');
|
||||
if (!textarea) return;
|
||||
|
||||
textarea.select();
|
||||
document.execCommand('copy');
|
||||
showToast('JSON copied to clipboard', 'success');
|
||||
}
|
||||
|
||||
async function saveFile() {
|
||||
if (!currentSaveData || !currentFilePath) {
|
||||
showToast('No file loaded to save', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Starting save process...');
|
||||
console.log('Current file path:', currentFilePath);
|
||||
console.log('Save data exists:', !!currentSaveData);
|
||||
|
||||
showLoading(true);
|
||||
setStatus('Saving file...');
|
||||
|
||||
try {
|
||||
console.log('Converting to JSON...');
|
||||
const jsonString = JSON.stringify(currentSaveData);
|
||||
console.log('JSON string length:', jsonString.length);
|
||||
|
||||
console.log('Encrypting data...');
|
||||
const encryptedData = encryptSaveData(jsonString);
|
||||
console.log('Encrypted data length:', encryptedData.length);
|
||||
|
||||
console.log('Sending to main process...');
|
||||
const result = await ipcRenderer.invoke('save-file', currentFilePath, encryptedData);
|
||||
console.log('Save result:', result);
|
||||
|
||||
if (result.success) {
|
||||
setModified(false);
|
||||
setStatus('File saved successfully');
|
||||
showToast('File saved successfully', 'success');
|
||||
console.log('Save completed successfully');
|
||||
} else {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error saving file:', error);
|
||||
showToast(`Error saving file: ${error.message}`, 'error');
|
||||
setStatus('Error saving file');
|
||||
} finally {
|
||||
showLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function createBackup() {
|
||||
if (!currentFilePath) {
|
||||
showToast('No file loaded to backup', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await ipcRenderer.invoke('create-backup', currentFilePath);
|
||||
|
||||
if (result.success) {
|
||||
showToast(`Backup created: ${require('path').basename(result.backupPath)}`, 'success');
|
||||
} else {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error creating backup:', error);
|
||||
showToast(`Error creating backup: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function setStatus(message) {
|
||||
const statusText = document.getElementById('status-text');
|
||||
if (statusText) {
|
||||
statusText.textContent = message;
|
||||
}
|
||||
}
|
||||
|
||||
function setModified(modified) {
|
||||
isModified = modified;
|
||||
updateUI();
|
||||
}
|
||||
|
||||
function updateUI() {
|
||||
if (isModified) {
|
||||
document.title = 'Fallout Shelter Save Editor - Modified';
|
||||
} else {
|
||||
document.title = 'Fallout Shelter Save Editor';
|
||||
}
|
||||
}
|
||||
|
||||
function showLoading(show) {
|
||||
const overlay = document.getElementById('loading-overlay');
|
||||
if (overlay) {
|
||||
overlay.classList.toggle('show', show);
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(message, type = 'info') {
|
||||
const container = document.getElementById('toast-container');
|
||||
if (!container) return;
|
||||
|
||||
const toast = document.createElement('div');
|
||||
toast.className = `toast ${type}`;
|
||||
toast.textContent = message;
|
||||
|
||||
container.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.remove();
|
||||
}, 4000);
|
||||
}
|
||||
|
||||
// Dwellers Management
|
||||
function populateDwellers() {
|
||||
const dwellersList = document.getElementById('dwellers-list');
|
||||
|
||||
if (!currentSaveData || !currentSaveData.dwellers || !currentSaveData.dwellers.dwellers) {
|
||||
if (dwellersList) {
|
||||
dwellersList.innerHTML = `
|
||||
<div class="placeholder">
|
||||
<i class="fas fa-users"></i>
|
||||
<p>No dwellers found in save file</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const dwellers = currentSaveData.dwellers.dwellers;
|
||||
|
||||
if (dwellers.length === 0) {
|
||||
dwellersList.innerHTML = `
|
||||
<div class="placeholder">
|
||||
<i class="fas fa-users"></i>
|
||||
<p>No dwellers in vault</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Found ${dwellers.length} dwellers`);
|
||||
|
||||
dwellersList.innerHTML = dwellers.map((dweller, index) => {
|
||||
const name = dweller.name || `Dweller ${index + 1}`;
|
||||
const level = dweller.experience?.currentLevel || 1;
|
||||
const happiness = Math.round(dweller.happiness?.happinessValue || 0);
|
||||
const health = Math.round(dweller.health?.healthValue || 100);
|
||||
const gender = dweller.gender === 2 ? 'Female' : 'Male';
|
||||
const pregnant = dweller.relations?.pregnant || false;
|
||||
|
||||
// SPECIAL stats
|
||||
const special = dweller.serializeableSpecialStats || {};
|
||||
const strength = special.stats?.[1] || 1;
|
||||
const perception = special.stats?.[2] || 1;
|
||||
const endurance = special.stats?.[3] || 1;
|
||||
const charisma = special.stats?.[4] || 1;
|
||||
const intelligence = special.stats?.[5] || 1;
|
||||
const agility = special.stats?.[6] || 1;
|
||||
const luck = special.stats?.[7] || 1;
|
||||
|
||||
return `
|
||||
<div class="dweller-card" data-index="${index}">
|
||||
<div class="dweller-header">
|
||||
<h3 class="dweller-name">${name}</h3>
|
||||
<span class="dweller-gender ${gender.toLowerCase()}">${gender}</span>
|
||||
${pregnant ? '<span class="pregnant-badge">Pregnant</span>' : ''}
|
||||
</div>
|
||||
|
||||
<div class="dweller-stats">
|
||||
<div class="stat-row">
|
||||
<span>Level:</span>
|
||||
<input type="number" class="dweller-input" data-field="experience.currentLevel" value="${level}" min="1" max="50">
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Happiness:</span>
|
||||
<input type="number" class="dweller-input" data-field="happiness.happinessValue" value="${happiness}" min="0" max="100">%
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Health:</span>
|
||||
<input type="number" class="dweller-input" data-field="health.healthValue" value="${health}" min="0" max="100">%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="special-stats">
|
||||
<h4>SPECIAL</h4>
|
||||
<div class="special-grid">
|
||||
<div class="special-stat">
|
||||
<label>S</label>
|
||||
<input type="number" class="special-input" data-stat="1" value="${strength}" min="1" max="10">
|
||||
</div>
|
||||
<div class="special-stat">
|
||||
<label>P</label>
|
||||
<input type="number" class="special-input" data-stat="2" value="${perception}" min="1" max="10">
|
||||
</div>
|
||||
<div class="special-stat">
|
||||
<label>E</label>
|
||||
<input type="number" class="special-input" data-stat="3" value="${endurance}" min="1" max="10">
|
||||
</div>
|
||||
<div class="special-stat">
|
||||
<label>C</label>
|
||||
<input type="number" class="special-input" data-stat="4" value="${charisma}" min="1" max="10">
|
||||
</div>
|
||||
<div class="special-stat">
|
||||
<label>I</label>
|
||||
<input type="number" class="special-input" data-stat="5" value="${intelligence}" min="1" max="10">
|
||||
</div>
|
||||
<div class="special-stat">
|
||||
<label>A</label>
|
||||
<input type="number" class="special-input" data-stat="6" value="${agility}" min="1" max="10">
|
||||
</div>
|
||||
<div class="special-stat">
|
||||
<label>L</label>
|
||||
<input type="number" class="special-input" data-stat="7" value="${luck}" min="1" max="10">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dweller-actions">
|
||||
<button class="secondary-btn apply-dweller-btn" data-index="${index}">
|
||||
<i class="fas fa-check"></i>
|
||||
Apply Changes
|
||||
</button>
|
||||
<button class="secondary-btn max-special-btn" data-index="${index}">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
Max SPECIAL
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
// Add event listeners for dweller editing
|
||||
addDwellerEventListeners();
|
||||
}
|
||||
|
||||
function addDwellerEventListeners() {
|
||||
// Apply changes buttons
|
||||
document.querySelectorAll('.apply-dweller-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const index = parseInt(e.target.closest('.apply-dweller-btn').dataset.index);
|
||||
applyDwellerChanges(index);
|
||||
});
|
||||
});
|
||||
|
||||
// Max SPECIAL buttons
|
||||
document.querySelectorAll('.max-special-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
const index = parseInt(e.target.closest('.max-special-btn').dataset.index);
|
||||
maxDwellerSpecial(index);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function applyDwellerChanges(dwellerIndex) {
|
||||
if (!currentSaveData || !currentSaveData.dwellers || !currentSaveData.dwellers.dwellers[dwellerIndex]) {
|
||||
showToast('Dweller not found', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const dweller = currentSaveData.dwellers.dwellers[dwellerIndex];
|
||||
const card = document.querySelector(`.dweller-card[data-index="${dwellerIndex}"]`);
|
||||
|
||||
if (!card) return;
|
||||
|
||||
let changesApplied = 0;
|
||||
|
||||
// Apply basic stats
|
||||
card.querySelectorAll('.dweller-input').forEach(input => {
|
||||
const field = input.dataset.field;
|
||||
const value = parseFloat(input.value);
|
||||
|
||||
if (!isNaN(value)) {
|
||||
setNestedValue(dweller, field, value);
|
||||
changesApplied++;
|
||||
}
|
||||
});
|
||||
|
||||
// Apply SPECIAL stats
|
||||
card.querySelectorAll('.special-input').forEach(input => {
|
||||
const statIndex = parseInt(input.dataset.stat);
|
||||
const value = parseInt(input.value);
|
||||
|
||||
if (!isNaN(value) && value >= 1 && value <= 10) {
|
||||
if (!dweller.serializeableSpecialStats) {
|
||||
dweller.serializeableSpecialStats = { stats: {} };
|
||||
}
|
||||
if (!dweller.serializeableSpecialStats.stats) {
|
||||
dweller.serializeableSpecialStats.stats = {};
|
||||
}
|
||||
|
||||
dweller.serializeableSpecialStats.stats[statIndex] = value;
|
||||
changesApplied++;
|
||||
}
|
||||
});
|
||||
|
||||
if (changesApplied > 0) {
|
||||
setModified(true);
|
||||
updateRawData();
|
||||
showToast(`Applied ${changesApplied} changes to dweller`, 'success');
|
||||
} else {
|
||||
showToast('No valid changes to apply', 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
function maxDwellerSpecial(dwellerIndex) {
|
||||
const card = document.querySelector(`.dweller-card[data-index="${dwellerIndex}"]`);
|
||||
if (!card) return;
|
||||
|
||||
// Set all SPECIAL stats to 10
|
||||
card.querySelectorAll('.special-input').forEach(input => {
|
||||
input.value = 10;
|
||||
});
|
||||
|
||||
applyDwellerChanges(dwellerIndex);
|
||||
}
|
||||
|
||||
function setNestedValue(obj, path, value) {
|
||||
const keys = path.split('.');
|
||||
let current = obj;
|
||||
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
if (!current[keys[i]]) {
|
||||
current[keys[i]] = {};
|
||||
}
|
||||
current = current[keys[i]];
|
||||
}
|
||||
|
||||
current[keys[keys.length - 1]] = value;
|
||||
}
|
||||
|
||||
// Advanced Editing Functions
|
||||
function addAdvancedResourceOptions() {
|
||||
// Add lunchbox and other premium resources
|
||||
const advancedResources = {
|
||||
'lunchbox-input': 'Lunchbox',
|
||||
'mrhandy-input': 'MrHandy',
|
||||
'petcarrier-input': 'PetCarrier',
|
||||
'craftedoutfit-input': 'CraftedOutfit',
|
||||
'craftedweapon-input': 'CraftedWeapon',
|
||||
'craftedtheme-input': 'CraftedTheme'
|
||||
};
|
||||
|
||||
if (currentSaveData && currentSaveData.vault && currentSaveData.vault.storage) {
|
||||
const resources = currentSaveData.vault.storage.resources;
|
||||
|
||||
Object.entries(advancedResources).forEach(([inputId, resourceKey]) => {
|
||||
const input = document.getElementById(inputId);
|
||||
if (input && resources[resourceKey] !== undefined) {
|
||||
input.value = Math.floor(resources[resourceKey]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function maxAllDwellers() {
|
||||
if (!currentSaveData || !currentSaveData.dwellers || !currentSaveData.dwellers.dwellers) {
|
||||
showToast('No dwellers found', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const dwellers = currentSaveData.dwellers.dwellers;
|
||||
let modifiedCount = 0;
|
||||
|
||||
dwellers.forEach((dweller, index) => {
|
||||
// Max level
|
||||
if (dweller.experience) {
|
||||
dweller.experience.currentLevel = 50;
|
||||
dweller.experience.experienceValue = 2916000; // Max XP for level 50
|
||||
}
|
||||
|
||||
// Max happiness and health
|
||||
if (dweller.happiness) {
|
||||
dweller.happiness.happinessValue = 100;
|
||||
}
|
||||
if (dweller.health) {
|
||||
dweller.health.healthValue = 100;
|
||||
}
|
||||
|
||||
// Max SPECIAL
|
||||
if (!dweller.serializeableSpecialStats) {
|
||||
dweller.serializeableSpecialStats = { stats: {} };
|
||||
}
|
||||
if (!dweller.serializeableSpecialStats.stats) {
|
||||
dweller.serializeableSpecialStats.stats = {};
|
||||
}
|
||||
|
||||
for (let i = 1; i <= 7; i++) {
|
||||
dweller.serializeableSpecialStats.stats[i] = 10;
|
||||
}
|
||||
|
||||
modifiedCount++;
|
||||
});
|
||||
|
||||
if (modifiedCount > 0) {
|
||||
setModified(true);
|
||||
updateRawData();
|
||||
populateDwellers(); // Refresh the display
|
||||
showToast(`Maxed out ${modifiedCount} dwellers`, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
PyQt5>=5.15.0
|
||||
cryptography>=3.4.0
|
||||
pycryptodome>=3.15.0
|
||||
73
run_editor.py
Normal file
73
run_editor.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple launcher for the Fallout Shelter Save Editor
|
||||
"""
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def check_requirements():
|
||||
"""Check if required packages are installed."""
|
||||
required_packages = ['PyQt5', 'cryptography', 'pycryptodome']
|
||||
missing_packages = []
|
||||
|
||||
for package in required_packages:
|
||||
try:
|
||||
__import__(package)
|
||||
except ImportError:
|
||||
missing_packages.append(package)
|
||||
|
||||
return missing_packages
|
||||
|
||||
def install_requirements():
|
||||
"""Install missing requirements."""
|
||||
print("Installing required packages...")
|
||||
try:
|
||||
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-r', 'requirements.txt'])
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Main launcher function."""
|
||||
print("Fallout Shelter Save Editor Launcher")
|
||||
print("=" * 40)
|
||||
|
||||
# Check for missing packages
|
||||
missing = check_requirements()
|
||||
|
||||
if missing:
|
||||
print(f"Missing required packages: {', '.join(missing)}")
|
||||
|
||||
if os.path.exists('requirements.txt'):
|
||||
response = input("Would you like to install them now? (y/n): ").lower().strip()
|
||||
if response == 'y':
|
||||
if install_requirements():
|
||||
print("Packages installed successfully!")
|
||||
else:
|
||||
print("Failed to install packages. Please install manually:")
|
||||
print("pip install -r requirements.txt")
|
||||
return
|
||||
else:
|
||||
print("Please install the required packages manually:")
|
||||
print("pip install -r requirements.txt")
|
||||
return
|
||||
else:
|
||||
print("requirements.txt not found. Please install manually:")
|
||||
print("pip install PyQt5 cryptography pycryptodome")
|
||||
return
|
||||
|
||||
# Launch the editor
|
||||
print("Starting Fallout Shelter Save Editor...")
|
||||
try:
|
||||
from fallout_shelter_qt_editor import main as editor_main
|
||||
editor_main()
|
||||
except ImportError as e:
|
||||
print(f"Error importing editor: {e}")
|
||||
print("Make sure fallout_shelter_qt_editor.py is in the same directory.")
|
||||
except Exception as e:
|
||||
print(f"Error starting editor: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
4
start-dev.bat
Normal file
4
start-dev.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
echo Starting Fallout Shelter Save Editor in Development Mode...
|
||||
npm run dev
|
||||
pause
|
||||
4
start.bat
Normal file
4
start.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
echo Starting Fallout Shelter Save Editor...
|
||||
npm run start
|
||||
pause
|
||||
4
steam_autocloud.vdf
Normal file
4
steam_autocloud.vdf
Normal file
@@ -0,0 +1,4 @@
|
||||
"steam_autocloud.vdf"
|
||||
{
|
||||
"accountid" "1046964385"
|
||||
}
|
||||
1167
styles.css
Normal file
1167
styles.css
Normal file
@@ -0,0 +1,1167 @@
|
||||
/* Reset and Base Styles */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
|
||||
color: #e0e0e0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* App Container */
|
||||
.app-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.app-header {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding: 12px 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.logo i {
|
||||
font-size: 24px;
|
||||
color: #ffd700;
|
||||
animation: glow 2s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes glow {
|
||||
from { text-shadow: 0 0 5px #ffd700, 0 0 10px #ffd700; }
|
||||
to { text-shadow: 0 0 10px #ffd700, 0 0 20px #ffd700, 0 0 30px #ffd700; }
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
font-size: 14px;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
.main-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.nav-tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #b0b0b0;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
.nav-tab:hover {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.nav-tab.active {
|
||||
background: rgba(255, 215, 0, 0.1);
|
||||
color: #ffd700;
|
||||
border-left-color: #ffd700;
|
||||
}
|
||||
|
||||
.nav-tab i {
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quick-actions {
|
||||
margin-top: auto;
|
||||
padding: 20px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.quick-actions h3 {
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
margin-bottom: 8px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 6px;
|
||||
color: #e0e0e0;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.action-btn:hover:not(:disabled) {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.action-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Content Area */
|
||||
.content-area {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.tab-header h2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-size: 24px;
|
||||
color: #ffffff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tab-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* Welcome Screen */
|
||||
.welcome-screen {
|
||||
text-align: center;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.welcome-icon {
|
||||
font-size: 64px;
|
||||
color: #ffd700;
|
||||
margin-bottom: 20px;
|
||||
animation: glow 2s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
.welcome-screen h2 {
|
||||
font-size: 32px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 15px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.welcome-screen p {
|
||||
font-size: 16px;
|
||||
color: #b0b0b0;
|
||||
margin-bottom: 40px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 12px;
|
||||
padding: 25px 20px;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-color: rgba(255, 215, 0, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.feature-card i {
|
||||
font-size: 32px;
|
||||
color: #ffd700;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.feature-card p {
|
||||
font-size: 14px;
|
||||
color: #b0b0b0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Resource Grid */
|
||||
.resource-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.resource-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.resource-card:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.resource-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.resource-icon.caps { background: linear-gradient(135deg, #ffd700, #ffed4e); }
|
||||
.resource-icon.food { background: linear-gradient(135deg, #ff6b6b, #ff8e8e); }
|
||||
.resource-icon.water { background: linear-gradient(135deg, #4ecdc4, #44a08d); }
|
||||
.resource-icon.power { background: linear-gradient(135deg, #45b7d1, #96c93d); }
|
||||
.resource-icon.stimpaks { background: linear-gradient(135deg, #f093fb, #f5576c); }
|
||||
.resource-icon.radaway { background: linear-gradient(135deg, #4facfe, #00f2fe); }
|
||||
.resource-icon.quantum { background: linear-gradient(135deg, #a8edea, #fed6e3); }
|
||||
.resource-icon.lunchbox { background: linear-gradient(135deg, #ff9a9e, #fecfef); }
|
||||
.resource-icon.mrhandy { background: linear-gradient(135deg, #667eea, #764ba2); }
|
||||
.resource-icon.petcarrier { background: linear-gradient(135deg, #f093fb, #f5576c); }
|
||||
.resource-icon.lunchbox { background: linear-gradient(135deg, #ff9a9e, #fecfef); }
|
||||
.resource-icon.mrhandy { background: linear-gradient(135deg, #667eea, #764ba2); }
|
||||
.resource-icon.petcarrier { background: linear-gradient(135deg, #f093fb, #f5576c); }
|
||||
|
||||
.resource-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.resource-info label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.resource-input {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.resource-input:focus {
|
||||
outline: none;
|
||||
border-color: #ffd700;
|
||||
box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Vault Info Grid */
|
||||
.vault-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.info-card label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.text-input, .number-input, .select-input {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.text-input:focus, .number-input:focus, .select-input:focus {
|
||||
outline: none;
|
||||
border-color: #ffd700;
|
||||
box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Dwellers */
|
||||
.dwellers-container {
|
||||
height: calc(100vh - 200px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.dwellers-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.dweller-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.dweller-card:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.dweller-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.dweller-name {
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.dweller-gender {
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dweller-gender.male {
|
||||
background: rgba(0, 150, 255, 0.2);
|
||||
color: #0096ff;
|
||||
border: 1px solid #0096ff;
|
||||
}
|
||||
|
||||
.dweller-gender.female {
|
||||
background: rgba(255, 100, 150, 0.2);
|
||||
color: #ff6496;
|
||||
border: 1px solid #ff6496;
|
||||
}
|
||||
|
||||
.pregnant-badge {
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
background: rgba(255, 215, 0, 0.2);
|
||||
color: #ffd700;
|
||||
border: 1px solid #ffd700;
|
||||
}
|
||||
|
||||
.dweller-stats {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.stat-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.stat-row span {
|
||||
font-size: 14px;
|
||||
color: #b0b0b0;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.dweller-input {
|
||||
width: 80px;
|
||||
padding: 4px 8px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 4px;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dweller-input:focus {
|
||||
outline: none;
|
||||
border-color: #ffd700;
|
||||
}
|
||||
|
||||
.special-stats {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.special-stats h4 {
|
||||
font-size: 14px;
|
||||
color: #ffd700;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.special-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.special-stat {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.special-stat label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: #ffd700;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.special-input {
|
||||
width: 100%;
|
||||
padding: 4px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 215, 0, 0.3);
|
||||
border-radius: 4px;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.special-input:focus {
|
||||
outline: none;
|
||||
border-color: #ffd700;
|
||||
}
|
||||
|
||||
.dweller-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.dweller-actions .secondary-btn {
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
grid-column: 1 / -1;
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.placeholder i {
|
||||
font-size: 48px;
|
||||
margin-bottom: 20px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Raw Data */
|
||||
.raw-data-container {
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
.raw-data-textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 8px;
|
||||
color: #e0e0e0;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
padding: 15px;
|
||||
resize: none;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.raw-data-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #ffd700;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.primary-btn, .secondary-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
background: linear-gradient(135deg, #ffd700, #ffed4e);
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.primary-btn:hover {
|
||||
background: linear-gradient(135deg, #ffed4e, #ffd700);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(255, 215, 0, 0.3);
|
||||
}
|
||||
|
||||
.secondary-btn {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #ffffff;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.secondary-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
/* Status Bar */
|
||||
.status-bar {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding: 8px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
.status-right {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.separator {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Loading Overlay */
|
||||
.loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.loading-overlay.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.loading-spinner i {
|
||||
font-size: 48px;
|
||||
color: #ffd700;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.loading-spinner p {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Toast Notifications */
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.toast {
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
color: #ffffff;
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
border-left: 4px solid #ffd700;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||
animation: slideIn 0.3s ease;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.toast.error {
|
||||
border-left-color: #ff4757;
|
||||
}
|
||||
|
||||
.toast.success {
|
||||
border-left-color: #2ed573;
|
||||
}
|
||||
|
||||
.toast.warning {
|
||||
border-left-color: #ffa502;
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scrollbar Styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
/* Startup Animation */
|
||||
.startup-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
opacity: 1;
|
||||
transition: opacity 0.8s ease-out;
|
||||
}
|
||||
|
||||
.startup-overlay.fade-out {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.startup-content {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Vault Door Animation */
|
||||
.vault-door {
|
||||
margin-bottom: 40px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vault-door-outer {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 8px solid #ffd700;
|
||||
border-radius: 50%;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
animation: vaultGlow 2s ease-in-out infinite alternate;
|
||||
box-shadow:
|
||||
0 0 20px rgba(255, 215, 0, 0.5),
|
||||
inset 0 0 20px rgba(255, 215, 0, 0.2);
|
||||
}
|
||||
|
||||
.vault-door-inner {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
background: radial-gradient(circle, #2a2a2a 0%, #1a1a1a 100%);
|
||||
border: 4px solid #666;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: vaultRotate 3s linear infinite;
|
||||
}
|
||||
|
||||
.vault-number {
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
color: #ffd700;
|
||||
text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.vault-spokes {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.spoke {
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 60px;
|
||||
background: linear-gradient(to bottom, #ffd700, #ffed4e);
|
||||
left: 50%;
|
||||
top: 10px;
|
||||
transform-origin: 2px 70px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 5px rgba(255, 215, 0, 0.5);
|
||||
}
|
||||
|
||||
.spoke:nth-child(1) { transform: translateX(-50%) rotate(0deg); }
|
||||
.spoke:nth-child(2) { transform: translateX(-50%) rotate(45deg); }
|
||||
.spoke:nth-child(3) { transform: translateX(-50%) rotate(90deg); }
|
||||
.spoke:nth-child(4) { transform: translateX(-50%) rotate(135deg); }
|
||||
.spoke:nth-child(5) { transform: translateX(-50%) rotate(180deg); }
|
||||
.spoke:nth-child(6) { transform: translateX(-50%) rotate(225deg); }
|
||||
.spoke:nth-child(7) { transform: translateX(-50%) rotate(270deg); }
|
||||
.spoke:nth-child(8) { transform: translateX(-50%) rotate(315deg); }
|
||||
|
||||
@keyframes vaultGlow {
|
||||
0% {
|
||||
box-shadow:
|
||||
0 0 20px rgba(255, 215, 0, 0.5),
|
||||
inset 0 0 20px rgba(255, 215, 0, 0.2);
|
||||
}
|
||||
100% {
|
||||
box-shadow:
|
||||
0 0 40px rgba(255, 215, 0, 0.8),
|
||||
inset 0 0 30px rgba(255, 215, 0, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes vaultRotate {
|
||||
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
||||
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Startup Text */
|
||||
.startup-text {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.startup-title {
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
color: #ffd700;
|
||||
margin-bottom: 10px;
|
||||
text-shadow:
|
||||
0 0 10px rgba(255, 215, 0, 0.8),
|
||||
0 0 20px rgba(255, 215, 0, 0.6),
|
||||
0 0 30px rgba(255, 215, 0, 0.4);
|
||||
animation: titlePulse 1.5s ease-in-out infinite alternate;
|
||||
font-family: 'Courier New', monospace;
|
||||
letter-spacing: 4px;
|
||||
}
|
||||
|
||||
.startup-subtitle {
|
||||
font-size: 24px;
|
||||
color: #ffffff;
|
||||
margin-bottom: 30px;
|
||||
font-weight: 300;
|
||||
letter-spacing: 2px;
|
||||
opacity: 0;
|
||||
animation: fadeInUp 1s ease-out 0.5s forwards;
|
||||
}
|
||||
|
||||
@keyframes titlePulse {
|
||||
0% {
|
||||
text-shadow:
|
||||
0 0 10px rgba(255, 215, 0, 0.8),
|
||||
0 0 20px rgba(255, 215, 0, 0.6),
|
||||
0 0 30px rgba(255, 215, 0, 0.4);
|
||||
}
|
||||
100% {
|
||||
text-shadow:
|
||||
0 0 20px rgba(255, 215, 0, 1),
|
||||
0 0 30px rgba(255, 215, 0, 0.8),
|
||||
0 0 40px rgba(255, 215, 0, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loading Dots */
|
||||
.loading-dots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.loading-dots span {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #ffd700;
|
||||
border-radius: 50%;
|
||||
animation: dotPulse 1.5s ease-in-out infinite;
|
||||
box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
|
||||
}
|
||||
|
||||
.loading-dots span:nth-child(1) { animation-delay: 0s; }
|
||||
.loading-dots span:nth-child(2) { animation-delay: 0.2s; }
|
||||
.loading-dots span:nth-child(3) { animation-delay: 0.4s; }
|
||||
|
||||
@keyframes dotPulse {
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0.5;
|
||||
}
|
||||
40% {
|
||||
transform: scale(1.2);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.version-info {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
opacity: 0;
|
||||
animation: fadeInUp 1s ease-out 0.8s forwards;
|
||||
}
|
||||
|
||||
.version-badge, .vault-tec-badge {
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.version-badge {
|
||||
background: rgba(255, 215, 0, 0.2);
|
||||
border: 1px solid #ffd700;
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
.vault-tec-badge {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
border: 1px solid #00ff00;
|
||||
color: #00ff00;
|
||||
animation: badgePulse 2s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes badgePulse {
|
||||
0% {
|
||||
box-shadow: 0 0 5px rgba(0, 255, 0, 0.3);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 15px rgba(0, 255, 0, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
.startup-status {
|
||||
font-size: 16px;
|
||||
color: #b0b0b0;
|
||||
font-family: 'Courier New', monospace;
|
||||
opacity: 0;
|
||||
animation: fadeInUp 1s ease-out 1s forwards;
|
||||
min-height: 20px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* Progress Bar */
|
||||
.startup-progress {
|
||||
width: 400px;
|
||||
margin: 0 auto;
|
||||
opacity: 0;
|
||||
animation: fadeInUp 1s ease-out 1.5s forwards;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid rgba(255, 215, 0, 0.3);
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #ffd700, #ffed4e, #ffd700);
|
||||
background-size: 200% 100%;
|
||||
border-radius: 4px;
|
||||
width: 0%;
|
||||
transition: width 0.3s ease;
|
||||
animation: progressShimmer 1.5s linear infinite;
|
||||
box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
|
||||
}
|
||||
|
||||
@keyframes progressShimmer {
|
||||
0% { background-position: -200% 0; }
|
||||
100% { background-position: 200% 0; }
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
font-family: 'Courier New', monospace;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
/* Radiation Particles */
|
||||
.radiation-particles {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.particle {
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: #ffd700;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
animation: particleFloat 8s linear infinite;
|
||||
box-shadow: 0 0 6px rgba(255, 215, 0, 0.8);
|
||||
}
|
||||
|
||||
.particle:nth-child(1) {
|
||||
left: 10%;
|
||||
animation-delay: 0s;
|
||||
animation-duration: 6s;
|
||||
}
|
||||
|
||||
.particle:nth-child(2) {
|
||||
left: 20%;
|
||||
animation-delay: 1s;
|
||||
animation-duration: 8s;
|
||||
}
|
||||
|
||||
.particle:nth-child(3) {
|
||||
left: 30%;
|
||||
animation-delay: 2s;
|
||||
animation-duration: 7s;
|
||||
}
|
||||
|
||||
.particle:nth-child(4) {
|
||||
left: 40%;
|
||||
animation-delay: 0.5s;
|
||||
animation-duration: 9s;
|
||||
}
|
||||
|
||||
.particle:nth-child(5) {
|
||||
left: 60%;
|
||||
animation-delay: 1.5s;
|
||||
animation-duration: 6.5s;
|
||||
}
|
||||
|
||||
.particle:nth-child(6) {
|
||||
left: 70%;
|
||||
animation-delay: 2.5s;
|
||||
animation-duration: 8.5s;
|
||||
}
|
||||
|
||||
.particle:nth-child(7) {
|
||||
left: 80%;
|
||||
animation-delay: 3s;
|
||||
animation-duration: 7.5s;
|
||||
}
|
||||
|
||||
.particle:nth-child(8) {
|
||||
left: 90%;
|
||||
animation-delay: 3.5s;
|
||||
animation-duration: 9.5s;
|
||||
}
|
||||
|
||||
@keyframes particleFloat {
|
||||
0% {
|
||||
transform: translateY(100vh) translateX(0px);
|
||||
opacity: 0;
|
||||
}
|
||||
10% {
|
||||
opacity: 1;
|
||||
}
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-100px) translateX(50px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.resource-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.startup-title {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.startup-subtitle {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.vault-door-outer {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.vault-door-inner {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.vault-number {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.startup-progress {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
65
test-electron.js
Normal file
65
test-electron.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// Simple test to verify the Electron app functionality
|
||||
const fs = require('fs');
|
||||
const CryptoJS = require('crypto-js');
|
||||
|
||||
// Test the decryption with the actual save file
|
||||
function testDecryption() {
|
||||
try {
|
||||
console.log('Testing Fallout Shelter save decryption...');
|
||||
|
||||
// Read the save file
|
||||
const saveData = fs.readFileSync('Vault1.sav', 'utf8');
|
||||
console.log('Save file loaded, length:', saveData.length);
|
||||
|
||||
// AES constants (same as in renderer.js)
|
||||
const AES_KEY_WORDS = [2815074099, 1725469378, 4039046167, 874293617, 3063605751, 3133984764, 4097598161, 3620741625];
|
||||
const AES_KEY = CryptoJS.lib.WordArray.create(AES_KEY_WORDS);
|
||||
const AES_IV = CryptoJS.enc.Hex.parse('7475383967656A693334307438397532');
|
||||
|
||||
console.log('Key:', AES_KEY.toString());
|
||||
console.log('IV:', AES_IV.toString());
|
||||
|
||||
// Create cipher text object from base64 string (same as renderer.js)
|
||||
const ciphertext = CryptoJS.enc.Base64.parse(saveData);
|
||||
const cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext: ciphertext
|
||||
});
|
||||
|
||||
// Decrypt
|
||||
const decrypted = CryptoJS.AES.decrypt(cipherParams, AES_KEY, {
|
||||
iv: AES_IV,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
const decryptedString = decrypted.toString(CryptoJS.enc.Utf8);
|
||||
console.log('Decryption successful!');
|
||||
console.log('Decrypted length:', decryptedString.length);
|
||||
console.log('First 200 chars:', decryptedString.substring(0, 200));
|
||||
|
||||
// Try to parse JSON
|
||||
const jsonData = JSON.parse(decryptedString);
|
||||
console.log('JSON parsing successful!');
|
||||
console.log('Top-level keys:', Object.keys(jsonData));
|
||||
|
||||
// Test encryption back
|
||||
const encrypted = CryptoJS.AES.encrypt(decryptedString, AES_KEY, {
|
||||
iv: AES_IV,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
|
||||
console.log('Re-encryption successful!');
|
||||
console.log('Original length:', saveData.length);
|
||||
console.log('Re-encrypted length:', encrypted.toString().length);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
testDecryption();
|
||||
}
|
||||
98
test_decryption.py
Normal file
98
test_decryption.py
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to verify Fallout Shelter save decryption
|
||||
"""
|
||||
|
||||
import base64
|
||||
import json
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
|
||||
def test_decryption():
|
||||
"""Test the decryption with the Vault1.sav file."""
|
||||
|
||||
# Fallout Shelter encryption constants
|
||||
AES_KEY = bytes([
|
||||
(2815074099 >> 24) & 0xFF, (2815074099 >> 16) & 0xFF, (2815074099 >> 8) & 0xFF, 2815074099 & 0xFF,
|
||||
(1725469378 >> 24) & 0xFF, (1725469378 >> 16) & 0xFF, (1725469378 >> 8) & 0xFF, 1725469378 & 0xFF,
|
||||
(4039046167 >> 24) & 0xFF, (4039046167 >> 16) & 0xFF, (4039046167 >> 8) & 0xFF, 4039046167 & 0xFF,
|
||||
(874293617 >> 24) & 0xFF, (874293617 >> 16) & 0xFF, (874293617 >> 8) & 0xFF, 874293617 & 0xFF,
|
||||
(3063605751 >> 24) & 0xFF, (3063605751 >> 16) & 0xFF, (3063605751 >> 8) & 0xFF, 3063605751 & 0xFF,
|
||||
(3133984764 >> 24) & 0xFF, (3133984764 >> 16) & 0xFF, (3133984764 >> 8) & 0xFF, 3133984764 & 0xFF,
|
||||
(4097598161 >> 24) & 0xFF, (4097598161 >> 16) & 0xFF, (4097598161 >> 8) & 0xFF, 4097598161 & 0xFF,
|
||||
(3620741625 >> 24) & 0xFF, (3620741625 >> 16) & 0xFF, (3620741625 >> 8) & 0xFF, 3620741625 & 0xFF
|
||||
])
|
||||
AES_IV = bytes.fromhex("7475383967656A693334307438397532")
|
||||
|
||||
try:
|
||||
# Read the save file
|
||||
with open("Vault1.sav", "rb") as f:
|
||||
raw_data = f.read()
|
||||
|
||||
print(f"Raw file size: {len(raw_data)} bytes")
|
||||
print(f"First 50 bytes (hex): {raw_data[:50].hex()}")
|
||||
|
||||
# Decode base64
|
||||
try:
|
||||
decoded_data = base64.b64decode(raw_data)
|
||||
print(f"Decoded size: {len(decoded_data)} bytes")
|
||||
print(f"First 50 bytes of decoded (hex): {decoded_data[:50].hex()}")
|
||||
except Exception as e:
|
||||
print(f"Base64 decode failed: {e}")
|
||||
return
|
||||
|
||||
# Decrypt using AES-CBC
|
||||
try:
|
||||
cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
|
||||
decrypted_data = cipher.decrypt(decoded_data)
|
||||
print(f"Decrypted size: {len(decrypted_data)} bytes")
|
||||
|
||||
# Try to remove padding
|
||||
try:
|
||||
unpadded_data = unpad(decrypted_data, AES.block_size)
|
||||
print(f"Unpadded size: {len(unpadded_data)} bytes")
|
||||
except ValueError as e:
|
||||
print(f"Unpadding failed: {e}")
|
||||
# Try without unpadding
|
||||
unpadded_data = decrypted_data.rstrip(b'\x00')
|
||||
print(f"Manual padding removal size: {len(unpadded_data)} bytes")
|
||||
|
||||
# Try to decode as UTF-8
|
||||
try:
|
||||
json_str = unpadded_data.decode('utf-8')
|
||||
print(f"UTF-8 decode successful, length: {len(json_str)}")
|
||||
print(f"First 200 characters: {json_str[:200]}")
|
||||
|
||||
# Try to parse as JSON
|
||||
try:
|
||||
save_data = json.loads(json_str)
|
||||
print("JSON parsing successful!")
|
||||
print(f"Top-level keys: {list(save_data.keys()) if isinstance(save_data, dict) else 'Not a dict'}")
|
||||
|
||||
# Save pretty-printed JSON for inspection
|
||||
with open("decrypted_save.json", "w") as f:
|
||||
json.dump(save_data, f, indent=2)
|
||||
print("Decrypted save written to decrypted_save.json")
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"JSON parsing failed: {e}")
|
||||
print("Saving raw decrypted text for inspection...")
|
||||
with open("decrypted_raw.txt", "w", encoding='utf-8', errors='ignore') as f:
|
||||
f.write(json_str)
|
||||
|
||||
except UnicodeDecodeError as e:
|
||||
print(f"UTF-8 decode failed: {e}")
|
||||
print("Saving raw decrypted bytes for inspection...")
|
||||
with open("decrypted_raw.bin", "wb") as f:
|
||||
f.write(unpadded_data)
|
||||
|
||||
except Exception as e:
|
||||
print(f"AES decryption failed: {e}")
|
||||
|
||||
except FileNotFoundError:
|
||||
print("Vault1.sav not found in current directory")
|
||||
except Exception as e:
|
||||
print(f"Unexpected error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_decryption()
|
||||
91
test_save_loading.py
Normal file
91
test_save_loading.py
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to verify save file loading functionality
|
||||
"""
|
||||
|
||||
import base64
|
||||
import json
|
||||
import zlib
|
||||
import os
|
||||
|
||||
def test_save_loading(filepath="Vault1.sav"):
|
||||
"""Test loading the save file with different methods."""
|
||||
|
||||
print(f"Testing save file: {filepath}")
|
||||
print("=" * 50)
|
||||
|
||||
if not os.path.exists(filepath):
|
||||
print(f"Error: File {filepath} not found")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Read raw file
|
||||
with open(filepath, 'rb') as f:
|
||||
raw_data = f.read()
|
||||
|
||||
print(f"Raw file size: {len(raw_data)} bytes")
|
||||
|
||||
# Decode base64
|
||||
try:
|
||||
decoded_data = base64.b64decode(raw_data)
|
||||
print(f"Base64 decoded size: {len(decoded_data)} bytes")
|
||||
print(f"First 20 bytes: {decoded_data[:20].hex()}")
|
||||
except Exception as e:
|
||||
print(f"Base64 decode failed: {e}")
|
||||
return False
|
||||
|
||||
# Try decompression methods
|
||||
methods = [
|
||||
("Raw JSON", lambda d: json.loads(d.decode('utf-8'))),
|
||||
("Zlib", lambda d: json.loads(zlib.decompress(d).decode('utf-8'))),
|
||||
("Zlib with header", lambda d: json.loads(zlib.decompress(d[4:]).decode('utf-8'))),
|
||||
]
|
||||
|
||||
for name, method in methods:
|
||||
try:
|
||||
result = method(decoded_data)
|
||||
print(f"\n✓ SUCCESS with {name}")
|
||||
print(f"Data type: {type(result)}")
|
||||
if isinstance(result, dict):
|
||||
print(f"Keys: {list(result.keys())[:10]}") # First 10 keys
|
||||
|
||||
# Look for common Fallout Shelter fields
|
||||
common_fields = ['vault', 'dwellers', 'resources', 'rooms', 'gameStats']
|
||||
found_fields = [field for field in common_fields if field in result]
|
||||
if found_fields:
|
||||
print(f"Found common fields: {found_fields}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Failed with {name}: {str(e)[:100]}")
|
||||
|
||||
print("\nAll decompression methods failed")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error reading file: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Main test function."""
|
||||
print("Fallout Shelter Save File Test")
|
||||
print("=" * 40)
|
||||
|
||||
# Test with default save file
|
||||
success = test_save_loading("Vault1.sav")
|
||||
|
||||
if success:
|
||||
print("\n🎉 Save file can be loaded successfully!")
|
||||
print("The PyQt editor should be able to handle this file.")
|
||||
else:
|
||||
print("\n❌ Could not load save file with current methods.")
|
||||
print("The save file might use a different encryption/compression method.")
|
||||
|
||||
# Test if backup exists
|
||||
if os.path.exists("Vault1.sav.bkp"):
|
||||
print("\nTesting backup file...")
|
||||
test_save_loading("Vault1.sav.bkp")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user