mirror of
https://git.sanhost.net/sanasol/hytale-f2p.git
synced 2026-02-26 06:41:47 -03:00
Add electron-updater auto-update support
- Install electron-updater package - Configure GitHub releases publish settings - Create AppUpdater class with full update lifecycle - Integrate auto-update into main.js - Add comprehensive documentation (AUTO-UPDATES.md, TESTING-UPDATES.md) - Set up dev-app-update.yml for testing
This commit is contained in:
284
AUTO-UPDATES.md
Normal file
284
AUTO-UPDATES.md
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
# Auto-Updates System
|
||||||
|
|
||||||
|
This document explains how the automatic update system works in the Hytale F2P Launcher.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The launcher uses [electron-updater](https://www.electron.build/auto-update) to automatically check for, download, and install updates. When a new version is available, users are notified and the update is downloaded in the background.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
### 1. Update Checking
|
||||||
|
|
||||||
|
- **Automatic Check**: The app automatically checks for updates 3 seconds after startup
|
||||||
|
- **Manual Check**: Users can manually check for updates through the UI
|
||||||
|
- **Update Source**: Updates are fetched from GitHub Releases
|
||||||
|
|
||||||
|
### 2. Update Process
|
||||||
|
|
||||||
|
1. **Check for Updates**: The app queries GitHub Releases for a newer version
|
||||||
|
2. **Notify User**: If an update is available, the user is notified via the UI
|
||||||
|
3. **Download**: The update is automatically downloaded in the background
|
||||||
|
4. **Progress Tracking**: Download progress is shown to the user
|
||||||
|
5. **Install**: When the download completes, the user can choose to install immediately or wait until the app restarts
|
||||||
|
|
||||||
|
### 3. Installation
|
||||||
|
|
||||||
|
- Updates are installed when the app quits (if `autoInstallOnAppQuit` is enabled)
|
||||||
|
- Users can also manually trigger installation through the UI
|
||||||
|
- The app will restart automatically after installation
|
||||||
|
|
||||||
|
## Version Detection & Comparison
|
||||||
|
|
||||||
|
### Current Version Source
|
||||||
|
|
||||||
|
The app's current version is read from `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "2.0.2b"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This version is embedded into the built application and is accessible via `app.getVersion()` in Electron. When the app is built, electron-builder also creates an internal `app-update.yml` file in the app's resources that contains this version information.
|
||||||
|
|
||||||
|
### How Version Detection Works
|
||||||
|
|
||||||
|
1. **Current Version**: The app knows its own version from `package.json`, which is:
|
||||||
|
- Read at build time
|
||||||
|
- Embedded in the application binary
|
||||||
|
- Stored in the app's metadata
|
||||||
|
|
||||||
|
2. **Fetching Latest Version**: When checking for updates, electron-updater:
|
||||||
|
- Queries the GitHub Releases API: `https://api.github.com/repos/amiayweb/Hytale-F2P/releases/latest`
|
||||||
|
- Or reads the update metadata file: `https://github.com/amiayweb/Hytale-F2P/releases/download/latest/latest.yml` (or `latest-mac.yml` for macOS)
|
||||||
|
- The metadata file contains:
|
||||||
|
```yaml
|
||||||
|
version: 2.0.3
|
||||||
|
releaseDate: '2024-01-15T10:30:00.000Z'
|
||||||
|
path: Hytale-F2P-Launcher-2.0.3-x64.exe
|
||||||
|
sha512: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Version Comparison**: electron-updater uses semantic versioning comparison:
|
||||||
|
- Compares the **current version** (from `package.json`) with the **latest version** (from GitHub Releases)
|
||||||
|
- Uses semantic versioning rules: `major.minor.patch` (e.g., `2.0.2` vs `2.0.3`)
|
||||||
|
- An update is available if the remote version is **greater than** the current version
|
||||||
|
- Examples:
|
||||||
|
- Current: `2.0.2` → Remote: `2.0.3` ✅ Update available
|
||||||
|
- Current: `2.0.2` → Remote: `2.0.2` ❌ No update (same version)
|
||||||
|
- Current: `2.0.3` → Remote: `2.0.2` ❌ No update (current is newer)
|
||||||
|
- Current: `2.0.2b` → Remote: `2.0.3` ✅ Update available (prerelease tags are handled)
|
||||||
|
|
||||||
|
4. **Version Format Handling**:
|
||||||
|
- **Semantic versions** (e.g., `1.0.0`, `2.1.3`) are compared numerically
|
||||||
|
- **Prerelease versions** (e.g., `2.0.2b`, `2.0.2-beta`) are compared with special handling
|
||||||
|
- **Non-semantic versions** may cause issues - it's recommended to use semantic versioning
|
||||||
|
|
||||||
|
### Update Metadata Files
|
||||||
|
|
||||||
|
When you build and publish a release, electron-builder generates platform-specific metadata files:
|
||||||
|
|
||||||
|
**Windows/Linux** (`latest.yml`):
|
||||||
|
```yaml
|
||||||
|
version: 2.0.3
|
||||||
|
files:
|
||||||
|
- url: Hytale-F2P-Launcher-2.0.3-x64.exe
|
||||||
|
sha512: abc123...
|
||||||
|
size: 12345678
|
||||||
|
path: Hytale-F2P-Launcher-2.0.3-x64.exe
|
||||||
|
sha512: abc123...
|
||||||
|
releaseDate: '2024-01-15T10:30:00.000Z'
|
||||||
|
```
|
||||||
|
|
||||||
|
**macOS** (`latest-mac.yml`):
|
||||||
|
```yaml
|
||||||
|
version: 2.0.3
|
||||||
|
files:
|
||||||
|
- url: Hytale-F2P-Launcher-2.0.3-arm64-mac.zip
|
||||||
|
sha512: def456...
|
||||||
|
size: 23456789
|
||||||
|
path: Hytale-F2P-Launcher-2.0.3-arm64-mac.zip
|
||||||
|
sha512: def456...
|
||||||
|
releaseDate: '2024-01-15T10:30:00.000Z'
|
||||||
|
```
|
||||||
|
|
||||||
|
These files are:
|
||||||
|
- Automatically generated during build
|
||||||
|
- Uploaded to GitHub Releases
|
||||||
|
- Fetched by electron-updater to check for updates
|
||||||
|
- Used to determine if an update is available and what to download
|
||||||
|
|
||||||
|
### The Check Process in Detail
|
||||||
|
|
||||||
|
When `appUpdater.checkForUpdatesAndNotify()` is called:
|
||||||
|
|
||||||
|
1. **Read Current Version**: Gets version from `app.getVersion()` (which reads from `package.json`)
|
||||||
|
2. **Fetch Update Info**:
|
||||||
|
- Makes HTTP request to GitHub Releases API or reads `latest.yml`
|
||||||
|
- Gets the version number from the metadata
|
||||||
|
3. **Compare Versions**:
|
||||||
|
- Uses semantic versioning comparison (e.g., `semver.gt(remoteVersion, currentVersion)`)
|
||||||
|
- If remote > current: update available
|
||||||
|
- If remote <= current: no update
|
||||||
|
4. **Emit Events**:
|
||||||
|
- `update-available` if newer version found
|
||||||
|
- `update-not-available` if already up to date
|
||||||
|
5. **Download if Available**: If `autoDownload` is enabled, starts downloading automatically
|
||||||
|
|
||||||
|
### Example Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
App Version: 2.0.2 (from package.json)
|
||||||
|
↓
|
||||||
|
Check GitHub Releases API
|
||||||
|
↓
|
||||||
|
Latest Release: 2.0.3
|
||||||
|
↓
|
||||||
|
Compare: 2.0.3 > 2.0.2? YES
|
||||||
|
↓
|
||||||
|
Emit: 'update-available' event
|
||||||
|
↓
|
||||||
|
Download update automatically
|
||||||
|
↓
|
||||||
|
Emit: 'update-downloaded' event
|
||||||
|
↓
|
||||||
|
User can install on next restart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
### AppUpdater Class (`backend/appUpdater.js`)
|
||||||
|
|
||||||
|
The main class that handles all update operations:
|
||||||
|
|
||||||
|
- **`checkForUpdatesAndNotify()`**: Checks for updates and shows a system notification if available
|
||||||
|
- **`checkForUpdates()`**: Manually checks for updates (returns a promise)
|
||||||
|
- **`quitAndInstall()`**: Quits the app and installs the downloaded update
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
The AppUpdater emits the following events that the UI can listen to:
|
||||||
|
|
||||||
|
- `update-checking`: Update check has started
|
||||||
|
- `update-available`: A new update is available
|
||||||
|
- `update-not-available`: App is up to date
|
||||||
|
- `update-download-progress`: Download progress updates
|
||||||
|
- `update-downloaded`: Update has finished downloading
|
||||||
|
- `update-error`: An error occurred during the update process
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Package.json
|
||||||
|
|
||||||
|
The publish configuration in `package.json` tells electron-builder where to publish updates:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"publish": {
|
||||||
|
"provider": "github",
|
||||||
|
"owner": "amiayweb",
|
||||||
|
"repo": "Hytale-F2P"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This means updates will be fetched from GitHub Releases for the `amiayweb/Hytale-F2P` repository.
|
||||||
|
|
||||||
|
## Publishing Updates
|
||||||
|
|
||||||
|
### For Developers
|
||||||
|
|
||||||
|
1. **Update Version**: Bump the version in `package.json` (e.g., `2.0.2b` → `2.0.3`)
|
||||||
|
|
||||||
|
2. **Build the App**: Run the build command for your platform:
|
||||||
|
```bash
|
||||||
|
npm run build:win # Windows
|
||||||
|
npm run build:mac # macOS
|
||||||
|
npm run build:linux # Linux
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Publish to GitHub**: When building with electron-builder, it will:
|
||||||
|
- Generate update metadata files (`latest.yml`, `latest-mac.yml`, etc.)
|
||||||
|
- Upload the built files to GitHub Releases (if configured with `GH_TOKEN`)
|
||||||
|
- Make them available for auto-update
|
||||||
|
|
||||||
|
4. **Release on GitHub**: Create a GitHub Release with the new version tag
|
||||||
|
|
||||||
|
### Important Notes
|
||||||
|
|
||||||
|
- **macOS Code Signing**: macOS apps **must** be code-signed for auto-updates to work
|
||||||
|
- **Version Format**: Use semantic versioning (e.g., `1.0.0`, `2.0.1`) for best compatibility
|
||||||
|
- **Update Files**: electron-builder automatically generates the required metadata files (`latest.yml`, etc.)
|
||||||
|
|
||||||
|
## Testing Updates
|
||||||
|
|
||||||
|
### Development Mode
|
||||||
|
|
||||||
|
To test updates during development, create a `dev-app-update.yml` file in the project root:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
owner: amiayweb
|
||||||
|
repo: Hytale-F2P
|
||||||
|
provider: github
|
||||||
|
```
|
||||||
|
|
||||||
|
Then enable dev mode in the code:
|
||||||
|
```javascript
|
||||||
|
autoUpdater.forceDevUpdateConfig = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Testing
|
||||||
|
|
||||||
|
For local testing, you can use a local server (like Minio) or a generic HTTP server to host update files.
|
||||||
|
|
||||||
|
## User Experience
|
||||||
|
|
||||||
|
### What Users See
|
||||||
|
|
||||||
|
1. **On Startup**: The app silently checks for updates in the background
|
||||||
|
2. **Update Available**: A notification appears if an update is found
|
||||||
|
3. **Downloading**: Progress bar shows download status
|
||||||
|
4. **Ready to Install**: User is notified when the update is ready
|
||||||
|
5. **Installation**: Update installs on app restart or when user clicks "Install Now"
|
||||||
|
|
||||||
|
### User Actions
|
||||||
|
|
||||||
|
- Users can manually check for updates through the settings/update menu
|
||||||
|
- Users can choose to install immediately or wait until next app launch
|
||||||
|
- Users can continue using the app while updates download in the background
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Updates Not Working
|
||||||
|
|
||||||
|
1. **Check GitHub Releases**: Ensure releases are published on GitHub
|
||||||
|
2. **Check Version**: Make sure the version in `package.json` is higher than the current release
|
||||||
|
3. **Check Logs**: Check the app logs for update-related errors
|
||||||
|
4. **Code Signing (macOS)**: Verify the app is properly code-signed
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
- **"Update not available"**: Version in `package.json` may not be higher than the current release
|
||||||
|
- **"Download failed"**: Network issues or GitHub API rate limits
|
||||||
|
- **"Installation failed"**: Permissions issue or app is running from an unsupported location
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
### Supported Platforms
|
||||||
|
|
||||||
|
- **Windows**: NSIS installer (auto-update supported)
|
||||||
|
- **macOS**: DMG + ZIP (auto-update supported, requires code signing)
|
||||||
|
- **Linux**: AppImage, DEB, RPM, Pacman (auto-update supported)
|
||||||
|
|
||||||
|
### Update Files Generated
|
||||||
|
|
||||||
|
When building, electron-builder generates:
|
||||||
|
- `latest.yml` (Windows/Linux)
|
||||||
|
- `latest-mac.yml` (macOS)
|
||||||
|
- `latest-linux.yml` (Linux)
|
||||||
|
|
||||||
|
These files contain metadata about the latest release and are automatically uploaded to GitHub Releases.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [electron-updater Documentation](https://www.electron.build/auto-update)
|
||||||
|
- [electron-builder Auto Update Guide](https://www.electron.build/auto-update)
|
||||||
196
TESTING-UPDATES.md
Normal file
196
TESTING-UPDATES.md
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
# Testing Auto-Updates
|
||||||
|
|
||||||
|
This guide explains how to test the auto-update system during development.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Option 1: Test with GitHub Releases (Easiest)
|
||||||
|
|
||||||
|
1. **Set up dev-app-update.yml** (already done):
|
||||||
|
```yaml
|
||||||
|
provider: github
|
||||||
|
owner: amiayweb
|
||||||
|
repo: Hytale-F2P
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Lower your current version** in `package.json`:
|
||||||
|
- Change version to something lower than what's on GitHub (e.g., `2.0.1` if GitHub has `2.0.3`)
|
||||||
|
|
||||||
|
3. **Run the app in dev mode**:
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **The app will check for updates** 3 seconds after startup
|
||||||
|
- If a newer version exists on GitHub, it will detect it
|
||||||
|
- Check the console logs for update messages
|
||||||
|
|
||||||
|
### Option 2: Test with Local HTTP Server
|
||||||
|
|
||||||
|
For more control, you can set up a local server:
|
||||||
|
|
||||||
|
1. **Create a test update server**:
|
||||||
|
```bash
|
||||||
|
# Create a test directory
|
||||||
|
mkdir -p test-updates
|
||||||
|
cd test-updates
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Build a test version** with a higher version number:
|
||||||
|
```bash
|
||||||
|
# In package.json, set version to 2.0.4
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Copy the generated files** to your test server:
|
||||||
|
- Copy `dist/latest.yml` (or `latest-mac.yml` for macOS)
|
||||||
|
- Copy the built installer/package
|
||||||
|
|
||||||
|
4. **Start a simple HTTP server**:
|
||||||
|
```bash
|
||||||
|
# Using Python
|
||||||
|
python3 -m http.server 8080
|
||||||
|
|
||||||
|
# Or using Node.js http-server
|
||||||
|
npx http-server -p 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Update dev-app-update.yml** to point to local server:
|
||||||
|
```yaml
|
||||||
|
provider: generic
|
||||||
|
url: http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Run the app** and it will check your local server
|
||||||
|
|
||||||
|
## Testing Steps
|
||||||
|
|
||||||
|
### 1. Prepare Test Environment
|
||||||
|
|
||||||
|
**Current version**: `2.0.3` (in package.json)
|
||||||
|
**Test version**: `2.0.4` (on GitHub or local server)
|
||||||
|
|
||||||
|
### 2. Run the App
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Watch for Update Events
|
||||||
|
|
||||||
|
The app will automatically check for updates 3 seconds after startup. Watch the console for:
|
||||||
|
|
||||||
|
```
|
||||||
|
Checking for updates...
|
||||||
|
Update available: 2.0.4
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Check Console Logs
|
||||||
|
|
||||||
|
Look for these messages:
|
||||||
|
- `Checking for updates...` - Update check started
|
||||||
|
- `Update available: 2.0.4` - New version found
|
||||||
|
- `Download speed: ...` - Download progress
|
||||||
|
- `Update downloaded: 2.0.4` - Download complete
|
||||||
|
|
||||||
|
### 5. Test UI Integration
|
||||||
|
|
||||||
|
The app sends these events to the renderer:
|
||||||
|
- `update-checking`
|
||||||
|
- `update-available` (with version info)
|
||||||
|
- `update-download-progress` (with progress data)
|
||||||
|
- `update-downloaded` (ready to install)
|
||||||
|
|
||||||
|
You can listen to these in your frontend code to show update notifications.
|
||||||
|
|
||||||
|
## Manual Testing
|
||||||
|
|
||||||
|
### Trigger Manual Update Check
|
||||||
|
|
||||||
|
You can also trigger a manual check via IPC:
|
||||||
|
```javascript
|
||||||
|
// In renderer process
|
||||||
|
const result = await window.electronAPI.invoke('check-for-updates');
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install Update
|
||||||
|
|
||||||
|
After an update is downloaded:
|
||||||
|
```javascript
|
||||||
|
// In renderer process
|
||||||
|
await window.electronAPI.invoke('quit-and-install-update');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Scenarios
|
||||||
|
|
||||||
|
### Scenario 1: Update Available
|
||||||
|
1. Set `package.json` version to `2.0.1`
|
||||||
|
2. Ensure GitHub has version `2.0.3` or higher
|
||||||
|
3. Run app → Should detect update
|
||||||
|
|
||||||
|
### Scenario 2: Already Up to Date
|
||||||
|
1. Set `package.json` version to `2.0.3`
|
||||||
|
2. Ensure GitHub has version `2.0.3` or lower
|
||||||
|
3. Run app → Should show "no update available"
|
||||||
|
|
||||||
|
### Scenario 3: Prerelease Version
|
||||||
|
1. Set `package.json` version to `2.0.2b`
|
||||||
|
2. Ensure GitHub has version `2.0.3`
|
||||||
|
3. Run app → Should detect update (prerelease < release)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Update Not Detected
|
||||||
|
|
||||||
|
1. **Check dev-app-update.yml exists** in project root
|
||||||
|
2. **Verify dev mode is enabled** - Check console for "Dev update mode enabled"
|
||||||
|
3. **Check version numbers** - Remote version must be higher than current
|
||||||
|
4. **Check network** - App needs internet to reach GitHub/local server
|
||||||
|
5. **Check logs** - Look for error messages in console
|
||||||
|
|
||||||
|
### Common Errors
|
||||||
|
|
||||||
|
- **"Cannot find module 'electron-updater'"**: Run `npm install`
|
||||||
|
- **"Update check failed"**: Check network connection or GitHub API access
|
||||||
|
- **"No update available"**: Version comparison issue - check versions
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
Enable more verbose logging by checking the console output. The logger will show:
|
||||||
|
- Update check requests
|
||||||
|
- Version comparisons
|
||||||
|
- Download progress
|
||||||
|
- Any errors
|
||||||
|
|
||||||
|
## Testing with Real GitHub Releases
|
||||||
|
|
||||||
|
For the most realistic test:
|
||||||
|
|
||||||
|
1. **Create a test release on GitHub**:
|
||||||
|
- Build the app with version `2.0.4`
|
||||||
|
- Create a GitHub release with tag `v2.0.4`
|
||||||
|
- Upload the built files
|
||||||
|
|
||||||
|
2. **Lower your local version**:
|
||||||
|
- Set `package.json` to `2.0.3`
|
||||||
|
|
||||||
|
3. **Run the app**:
|
||||||
|
- It will check GitHub and find `2.0.4`
|
||||||
|
- Download and install the update
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- **Dev mode only works when app is NOT packaged** (`!app.isPackaged`)
|
||||||
|
- **Production builds** ignore `dev-app-update.yml` and use the built-in `app-update.yml`
|
||||||
|
- **macOS**: Code signing is required for updates to work in production
|
||||||
|
- **Windows**: NSIS installer is required for auto-updates
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
Once testing is complete:
|
||||||
|
1. Remove or comment out `forceDevUpdateConfig` for production
|
||||||
|
2. Ensure proper code signing for macOS
|
||||||
|
3. Set up CI/CD to automatically publish releases
|
||||||
120
backend/appUpdater.js
Normal file
120
backend/appUpdater.js
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
const { autoUpdater } = require('electron-updater');
|
||||||
|
const { app } = require('electron');
|
||||||
|
const logger = require('./logger');
|
||||||
|
|
||||||
|
class AppUpdater {
|
||||||
|
constructor(mainWindow) {
|
||||||
|
this.mainWindow = mainWindow;
|
||||||
|
this.setupAutoUpdater();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupAutoUpdater() {
|
||||||
|
// Enable dev mode for testing (reads dev-app-update.yml)
|
||||||
|
// Only enable in development, not in production builds
|
||||||
|
if (process.env.NODE_ENV === 'development' || !app.isPackaged) {
|
||||||
|
autoUpdater.forceDevUpdateConfig = true;
|
||||||
|
console.log('Dev update mode enabled - using dev-app-update.yml');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure logger for electron-updater
|
||||||
|
// Create a compatible logger interface
|
||||||
|
autoUpdater.logger = {
|
||||||
|
info: (...args) => logger.info(...args),
|
||||||
|
warn: (...args) => logger.warn(...args),
|
||||||
|
error: (...args) => logger.error(...args),
|
||||||
|
debug: (...args) => logger.log(...args)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Auto download updates
|
||||||
|
autoUpdater.autoDownload = true;
|
||||||
|
// Auto install on quit (after download)
|
||||||
|
autoUpdater.autoInstallOnAppQuit = true;
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
autoUpdater.on('checking-for-update', () => {
|
||||||
|
console.log('Checking for updates...');
|
||||||
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
|
this.mainWindow.webContents.send('update-checking');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-available', (info) => {
|
||||||
|
console.log('Update available:', info.version);
|
||||||
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
|
this.mainWindow.webContents.send('update-available', {
|
||||||
|
version: info.version,
|
||||||
|
releaseName: info.releaseName,
|
||||||
|
releaseNotes: info.releaseNotes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-not-available', (info) => {
|
||||||
|
console.log('Update not available. Current version is latest.');
|
||||||
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
|
this.mainWindow.webContents.send('update-not-available', {
|
||||||
|
version: info.version
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('error', (err) => {
|
||||||
|
console.error('Error in auto-updater:', err);
|
||||||
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
|
this.mainWindow.webContents.send('update-error', {
|
||||||
|
message: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('download-progress', (progressObj) => {
|
||||||
|
const message = `Download speed: ${progressObj.bytesPerSecond} - Downloaded ${progressObj.percent}% (${progressObj.transferred}/${progressObj.total})`;
|
||||||
|
console.log(message);
|
||||||
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
|
this.mainWindow.webContents.send('update-download-progress', {
|
||||||
|
percent: progressObj.percent,
|
||||||
|
bytesPerSecond: progressObj.bytesPerSecond,
|
||||||
|
transferred: progressObj.transferred,
|
||||||
|
total: progressObj.total
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-downloaded', (info) => {
|
||||||
|
console.log('Update downloaded:', info.version);
|
||||||
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
|
this.mainWindow.webContents.send('update-downloaded', {
|
||||||
|
version: info.version,
|
||||||
|
releaseName: info.releaseName,
|
||||||
|
releaseNotes: info.releaseNotes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForUpdatesAndNotify() {
|
||||||
|
// Check for updates and notify if available
|
||||||
|
autoUpdater.checkForUpdatesAndNotify().catch(err => {
|
||||||
|
console.error('Failed to check for updates:', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForUpdates() {
|
||||||
|
// Manual check for updates (returns promise)
|
||||||
|
return autoUpdater.checkForUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
quitAndInstall() {
|
||||||
|
// Quit and install the update
|
||||||
|
autoUpdater.quitAndInstall(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUpdateInfo() {
|
||||||
|
return {
|
||||||
|
currentVersion: app.getVersion(),
|
||||||
|
updateAvailable: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AppUpdater;
|
||||||
3
dev-app-update.yml
Normal file
3
dev-app-update.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
provider: github
|
||||||
|
owner: amiayweb
|
||||||
|
repo: Hytale-F2P
|
||||||
47
main.js
47
main.js
@@ -2,14 +2,14 @@ const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { launchGame, launchGameWithVersionCheck, installGame, saveUsername, loadUsername, saveChatUsername, loadChatUsername, saveChatColor, loadChatColor, saveJavaPath, loadJavaPath, saveInstallPath, loadInstallPath, saveDiscordRPC, loadDiscordRPC, saveLanguage, loadLanguage, isGameInstalled, uninstallGame, repairGame, getHytaleNews, handleFirstLaunchCheck, proposeGameUpdate, markAsLaunched } = require('./backend/launcher');
|
const { launchGame, launchGameWithVersionCheck, installGame, saveUsername, loadUsername, saveChatUsername, loadChatUsername, saveChatColor, loadChatColor, saveJavaPath, loadJavaPath, saveInstallPath, loadInstallPath, saveDiscordRPC, loadDiscordRPC, saveLanguage, loadLanguage, isGameInstalled, uninstallGame, repairGame, getHytaleNews, handleFirstLaunchCheck, proposeGameUpdate, markAsLaunched } = require('./backend/launcher');
|
||||||
const UpdateManager = require('./backend/updateManager');
|
const AppUpdater = require('./backend/appUpdater');
|
||||||
const logger = require('./backend/logger');
|
const logger = require('./backend/logger');
|
||||||
const profileManager = require('./backend/managers/profileManager');
|
const profileManager = require('./backend/managers/profileManager');
|
||||||
|
|
||||||
logger.interceptConsole();
|
logger.interceptConsole();
|
||||||
|
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
let updateManager;
|
let appUpdater;
|
||||||
let discordRPC = null;
|
let discordRPC = null;
|
||||||
|
|
||||||
// Discord Rich Presence setup
|
// Discord Rich Presence setup
|
||||||
@@ -113,11 +113,13 @@ function createWindow() {
|
|||||||
// Initialize Discord Rich Presence
|
// Initialize Discord Rich Presence
|
||||||
initDiscordRPC();
|
initDiscordRPC();
|
||||||
|
|
||||||
updateManager = new UpdateManager();
|
// Initialize App Updater
|
||||||
setTimeout(async () => {
|
appUpdater = new AppUpdater(mainWindow);
|
||||||
const updateInfo = await updateManager.checkForUpdates();
|
|
||||||
if (updateInfo.updateAvailable) {
|
// Check for updates after a short delay (3 seconds)
|
||||||
mainWindow.webContents.send('show-update-popup', updateInfo);
|
setTimeout(() => {
|
||||||
|
if (appUpdater) {
|
||||||
|
appUpdater.checkForUpdatesAndNotify();
|
||||||
}
|
}
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
@@ -724,7 +726,15 @@ ipcMain.handle('copy-mod-file', async (event, sourcePath, modsPath) => {
|
|||||||
|
|
||||||
ipcMain.handle('check-for-updates', async () => {
|
ipcMain.handle('check-for-updates', async () => {
|
||||||
try {
|
try {
|
||||||
return await updateManager.checkForUpdates();
|
if (appUpdater) {
|
||||||
|
const result = await appUpdater.checkForUpdates();
|
||||||
|
return {
|
||||||
|
updateAvailable: result?.updateInfo ? true : false,
|
||||||
|
version: result?.updateInfo?.version,
|
||||||
|
currentVersion: app.getVersion()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { updateAvailable: false, error: 'AppUpdater not initialized' };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error checking for updates:', error);
|
console.error('Error checking for updates:', error);
|
||||||
return { updateAvailable: false, error: error.message };
|
return { updateAvailable: false, error: error.message };
|
||||||
@@ -733,7 +743,8 @@ ipcMain.handle('check-for-updates', async () => {
|
|||||||
|
|
||||||
ipcMain.handle('open-download-page', async () => {
|
ipcMain.handle('open-download-page', async () => {
|
||||||
try {
|
try {
|
||||||
await shell.openExternal(updateManager.getDownloadUrl());
|
// Open GitHub releases page
|
||||||
|
await shell.openExternal('https://github.com/amiayweb/Hytale-F2P/releases');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
@@ -748,8 +759,24 @@ ipcMain.handle('open-download-page', async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('quit-and-install-update', async () => {
|
||||||
|
try {
|
||||||
|
if (appUpdater) {
|
||||||
|
appUpdater.quitAndInstall();
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
return { success: false, error: 'AppUpdater not initialized' };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error installing update:', error);
|
||||||
|
return { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.handle('get-update-info', async () => {
|
ipcMain.handle('get-update-info', async () => {
|
||||||
return updateManager.getUpdateInfo();
|
if (appUpdater) {
|
||||||
|
return appUpdater.getUpdateInfo();
|
||||||
|
}
|
||||||
|
return { currentVersion: app.getVersion(), updateAvailable: false };
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('get-gpu-info', () => {
|
ipcMain.handle('get-gpu-info', () => {
|
||||||
|
|||||||
95
package-lock.json
generated
95
package-lock.json
generated
@@ -1,17 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "hytale-f2p-launcherv2",
|
"name": "hytale-f2p-launcher",
|
||||||
"version": "2.0.2b",
|
"version": "2.0.2b",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "hytale-f2p-launcherv2",
|
"name": "hytale-f2p-launcher",
|
||||||
"version": "2.0.2b",
|
"version": "2.0.2b",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"adm-zip": "^0.5.10",
|
"adm-zip": "^0.5.10",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
"discord-rpc": "^4.0.1",
|
"discord-rpc": "^4.0.1",
|
||||||
|
"electron-updater": "^6.7.3",
|
||||||
"tar": "^6.2.1",
|
"tar": "^6.2.1",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
@@ -1073,7 +1074,6 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
"dev": true,
|
|
||||||
"license": "Python-2.0"
|
"license": "Python-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/assert-plus": {
|
"node_modules/assert-plus": {
|
||||||
@@ -1283,7 +1283,6 @@
|
|||||||
"version": "9.5.1",
|
"version": "9.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz",
|
||||||
"integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==",
|
"integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
@@ -1711,7 +1710,6 @@
|
|||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "^2.1.3"
|
"ms": "^2.1.3"
|
||||||
@@ -2178,6 +2176,69 @@
|
|||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/electron-updater": {
|
||||||
|
"version": "6.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.7.3.tgz",
|
||||||
|
"integrity": "sha512-EgkT8Z9noqXKbwc3u5FkJA+r48jwZ5DTUiOkJMOTEEH//n5Am6wfQGz7nvSFEA2oIAMv9jRzn5JKTyWeSKOPgg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"builder-util-runtime": "9.5.1",
|
||||||
|
"fs-extra": "^10.1.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"lazy-val": "^1.0.5",
|
||||||
|
"lodash.escaperegexp": "^4.1.2",
|
||||||
|
"lodash.isequal": "^4.5.0",
|
||||||
|
"semver": "~7.7.3",
|
||||||
|
"tiny-typed-emitter": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/electron-updater/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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.2.0",
|
||||||
|
"jsonfile": "^6.0.1",
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/electron-updater/node_modules/jsonfile": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"graceful-fs": "^4.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/electron-updater/node_modules/semver": {
|
||||||
|
"version": "7.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||||
|
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/electron-updater/node_modules/universalify": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/electron-winstaller": {
|
"node_modules/electron-winstaller": {
|
||||||
"version": "5.4.0",
|
"version": "5.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
|
||||||
@@ -2759,7 +2820,6 @@
|
|||||||
"version": "4.2.11",
|
"version": "4.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/has-flag": {
|
"node_modules/has-flag": {
|
||||||
@@ -3082,7 +3142,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
@@ -3150,7 +3209,6 @@
|
|||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
|
||||||
"integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
|
"integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
@@ -3160,6 +3218,19 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.escaperegexp": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isequal": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||||
|
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/log-symbols": {
|
"node_modules/log-symbols": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||||
@@ -3476,7 +3547,6 @@
|
|||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/negotiator": {
|
"node_modules/negotiator": {
|
||||||
@@ -4131,7 +4201,6 @@
|
|||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz",
|
||||||
"integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==",
|
"integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==",
|
||||||
"dev": true,
|
|
||||||
"license": "BlueOak-1.0.0",
|
"license": "BlueOak-1.0.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=11.0.0"
|
"node": ">=11.0.0"
|
||||||
@@ -4602,6 +4671,12 @@
|
|||||||
"semver": "bin/semver"
|
"semver": "bin/semver"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-typed-emitter": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.15",
|
"version": "0.2.15",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
|
|||||||
69
package.json
69
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hytale-f2p-launcher",
|
"name": "hytale-f2p-launcher",
|
||||||
"version": "2.0.2b",
|
"version": "2.0.3",
|
||||||
"description": "A modern, cross-platform launcher for Hytale with automatic updates and multi-client support",
|
"description": "A modern, cross-platform launcher for Hytale with automatic updates and multi-client support",
|
||||||
"homepage": "https://github.com/amiayweb/Hytale-F2P",
|
"homepage": "https://github.com/amiayweb/Hytale-F2P",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
@@ -48,6 +48,7 @@
|
|||||||
"adm-zip": "^0.5.10",
|
"adm-zip": "^0.5.10",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
"discord-rpc": "^4.0.1",
|
"discord-rpc": "^4.0.1",
|
||||||
|
"electron-updater": "^6.7.3",
|
||||||
"tar": "^6.2.1",
|
"tar": "^6.2.1",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
@@ -70,25 +71,70 @@
|
|||||||
],
|
],
|
||||||
"win": {
|
"win": {
|
||||||
"target": [
|
"target": [
|
||||||
{ "target": "nsis", "arch": ["x64", "arm64"] },
|
{
|
||||||
{ "target": "portable", "arch": ["x64"] }
|
"target": "nsis",
|
||||||
|
"arch": [
|
||||||
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "portable",
|
||||||
|
"arch": [
|
||||||
|
"x64"
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon.ico"
|
"icon": "icon.ico"
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": [
|
"target": [
|
||||||
{ "target": "AppImage", "arch": ["x64", "arm64"] },
|
{
|
||||||
{ "target": "deb", "arch": ["x64", "arm64"] },
|
"target": "AppImage",
|
||||||
{ "target": "rpm", "arch": ["x64", "arm64"] },
|
"arch": [
|
||||||
{ "target": "pacman", "arch": ["x64", "arm64"] }
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "deb",
|
||||||
|
"arch": [
|
||||||
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "rpm",
|
||||||
|
"arch": [
|
||||||
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "pacman",
|
||||||
|
"arch": [
|
||||||
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"icon": "build/icon.png",
|
"icon": "build/icon.png",
|
||||||
"category": "Game"
|
"category": "Game"
|
||||||
},
|
},
|
||||||
"mac": {
|
"mac": {
|
||||||
"target": [
|
"target": [
|
||||||
{ "target": "dmg", "arch": ["universal"] },
|
{
|
||||||
{ "target": "zip", "arch": ["universal"] }
|
"target": "dmg",
|
||||||
|
"arch": [
|
||||||
|
"universal"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "zip",
|
||||||
|
"arch": [
|
||||||
|
"universal"
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"icon": "build/icon.icns",
|
"icon": "build/icon.icns",
|
||||||
"category": "public.app-category.games"
|
"category": "public.app-category.games"
|
||||||
@@ -98,6 +144,11 @@
|
|||||||
"allowToChangeInstallationDirectory": true,
|
"allowToChangeInstallationDirectory": true,
|
||||||
"createDesktopShortcut": true,
|
"createDesktopShortcut": true,
|
||||||
"createStartMenuShortcut": true
|
"createStartMenuShortcut": true
|
||||||
|
},
|
||||||
|
"publish": {
|
||||||
|
"provider": "github",
|
||||||
|
"owner": "amiayweb",
|
||||||
|
"repo": "Hytale-F2P"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user