Fix community link order: TG Group > TG Channel > Chat

Consistent order across all files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
sanasol
2026-02-25 01:11:17 +01:00
parent 89b9135523
commit 66493d35ca
47 changed files with 18884 additions and 0 deletions

View File

@@ -0,0 +1,732 @@
# Hytale Client Binary Analysis
CSC_LINK="/Users/sanasol/Downloads/Certificates-hytale.p12" CSC_KEY_PASSWORD="YieocpBVP68Rih*" APPLE_ID="sanasol2008rs@gmail.com" APPLE_APP_SPECIFIC_PASSWORD="ihah-lbta-movj-iqni" APPLE_TEAM_ID="9WVL8YG95H" npm run build:mac
CSC_LINK="/Users/sanasol/Downloads/Certificates-hytale.p12" CSC_KEY_PASSWORD="YieocpBVP68Rih*" APPLE_ID="sanasol2008rs@gmail.com" APPLE_APP_SPECIFIC_PASSWORD="ihah-lbta-movj-iqni" APPLE_TEAM_ID="9WVL8YG95H" npx electron-builder --mac --arm64
password ihah-lbta-movj-iqni
team id 9WVL8YG95H
cert pass YieocpBVP68Rih*
## Overview
This document contains a comprehensive analysis of the HytaleClient binary, documenting all discovered URLs, API endpoints, service domains, patchable strings, and internal functionality.
**Binary Analyzed:** `HytaleClient` (macOS .NET AOT compiled)
**Analysis Date:** 2026-01-27
**String Encoding:** UTF-16LE (Windows .NET string format)
---
## Table of Contents
1. [Service URLs](#1-service-urls)
2. [API Endpoints](#2-api-endpoints)
3. [World Tools & Builder Tools](#3-world-tools--builder-tools)
4. [External Service URLs](#4-external-service-urls)
5. [Patchable Strings](#5-patchable-strings)
6. [Sentry Error Tracking](#6-sentry-error-tracking)
7. [Internal Class References](#7-internal-class-references)
8. [Binary Offsets Reference](#8-binary-offsets-reference)
9. [Implementation Notes](#9-implementation-notes)
---
## 1. Service URLs
### 1.1 Primary Hytale Services
The client connects to four main service subdomains:
| Service | URL Pattern | Purpose | Status |
|---------|-------------|---------|--------|
| **Sessions** | `https://sessions.{domain}` | Authentication, JWT tokens, session management | Implemented in auth-server |
| **Account Data** | `https://account-data.{domain}` | Player profiles, skins, account information | Implemented in auth-server |
| **Telemetry** | `https://telemetry.{domain}` | Analytics, error reporting, usage statistics | Implemented (accepts/discards) |
| **Tools** | `https://tools.{domain}` | Asset editor, prefab management, world tools | **Not implemented** |
### 1.2 URL Construction
The client constructs URLs by combining:
1. Protocol: `https://`
2. Subdomain: `sessions.`, `account-data.`, `telemetry.`, `tools.`
3. Base domain: `hytale.com`
**Example:** `https://` + `sessions.` + `hytale.com` = `https://sessions.hytale.com`
The client patcher replaces these components to redirect traffic to the F2P auth server.
### 1.3 F2P Domain Routing
For F2P mode, all subdomains route to a single endpoint:
- `sessions.{f2p_domain}``https://{f2p_domain}`
- `account-data.{f2p_domain}``https://{f2p_domain}`
- `telemetry.{f2p_domain}``https://{f2p_domain}`
- `tools.{f2p_domain}``https://{f2p_domain}`
---
## 2. API Endpoints
### 2.1 Session Management Endpoints
#### POST /game-session/new
Create a new game session.
**Request:**
```json
{
"clientVersion": "string",
"platform": "string"
}
```
**Response:**
```json
{
"token": "JWT token",
"refreshToken": "refresh token",
"expiresIn": 36000
}
```
#### POST /game-session/refresh
Refresh an existing session token.
**Request:**
```json
{
"refreshToken": "string"
}
```
**Response:**
```json
{
"token": "new JWT token",
"refreshToken": "new refresh token",
"expiresIn": 36000
}
```
#### POST /game-session/child
Create a child session (for server connections).
**Request:**
```json
{
"parentToken": "string",
"audience": "server identifier"
}
```
#### DELETE /game-session
Notify server of session end (player disconnect).
### 2.2 Server Join Endpoints
#### POST /server-join/auth-grant
Request authorization grant for connecting to a game server.
**Request:**
```json
{
"serverAddress": "string",
"serverPort": number
}
```
**Response:**
```json
{
"grant": "authorization grant string"
}
```
#### POST /server-join/auth-token
Exchange authorization grant for server-specific token with certificate binding.
**Request:**
```json
{
"grant": "authorization grant",
"clientCertHash": "SHA256 hash of client certificate"
}
```
**Response:**
```json
{
"token": "server-specific JWT with cnf claim"
}
```
### 2.3 Account Endpoints
#### GET /my-account/game-profile
Get the player's game profile.
**Response:**
```json
{
"uuid": "player UUID",
"username": "display name",
"createdAt": "timestamp"
}
```
#### POST /my-account/game-profile
Update the player's game profile.
**Request:**
```json
{
"username": "new display name"
}
```
#### GET /my-account/cosmetics
Get list of unlocked cosmetics for the player.
**Response:**
```json
{
"cosmetics": [
{
"id": "cosmetic_id",
"category": "category_name",
"unlockedAt": "timestamp"
}
]
}
```
#### POST /my-account/skin
Save player's skin/character customization preferences.
**Request:**
```json
{
"skinTone": "SkinTone_01",
"bodyType": "Default",
"parts": {
"haircut": "Haircut_ShortMessy.Blue",
"eyes": "Eyes_Default.Green",
"eyebrows": "Eyebrows_Default",
"face": "Face_Default"
}
}
```
### 2.4 JWKS Endpoint
#### GET /.well-known/jwks.json
Get JSON Web Key Set for JWT verification.
**Response:**
```json
{
"keys": [
{
"kty": "OKP",
"crv": "Ed25519",
"x": "base64url-encoded-public-key",
"kid": "key-id",
"use": "sig",
"alg": "EdDSA"
}
]
}
```
### 2.5 Profile Lookup Endpoints
#### GET /profile/uuid/{uuid}
Lookup player profile by UUID.
#### GET /profile/username/{username}
Lookup player profile by username (server-scoped).
---
## 3. World Tools & Builder Tools
### 3.1 World Tools (worldtools.*)
These are in-game tools for world creation and editing in builder/creative mode.
| Tool | Command | Description |
|------|---------|-------------|
| **Change Model** | `worldtools.changeModel` | Change the model of an entity in the world |
| **Import Image** | `worldtools.importImage` | Import image files into the world as textures |
| **Import OBJ** | `worldtools.importObj` | Import 3D OBJ model files into the world |
| **Instance** | `worldtools.instance` | Manage world instances and copies |
| **Play Sound** | `worldtools.playSound` | Play sound effects in the world |
| **Prefab Editor** | `worldtools.prefabEditor` | Open the prefab editor interface |
| **Prefab List** | `worldtools.prefabList` | List and manage saved prefabs |
| **Spawn Entity** | `worldtools.spawnEntity` | Spawn entities at specified locations |
| **Spawn Particle** | `worldtools.spawnParticle` | Spawn particle effects |
| **Tint Chunk** | `worldtools.tintChunk` | Apply color tinting to world chunks |
### 3.2 Builder Tools (buildertools.*)
Additional tools for the asset editor and builder mode.
| Tool | Class | Description |
|------|-------|-------------|
| **Image Import** | `buildertools.imageimport.ImageImportPage` | UI page for importing images |
| **OBJ Import** | `buildertools.objimport.ObjImportPage` | UI page for importing OBJ models |
| **Prefab Editor** | `buildertools.prefabeditor.ui.PrefabEditorLoadSettings` | Prefab editor with load/save |
| **Prefab List** | `buildertools.prefablist.PrefabPage` | Prefab listing and management |
### 3.3 Machinima Tool
- **Purpose:** In-game cinematic/video recording tool
- **Access:** Available via hotbar slot
- **Message:** "Hotbar is full. Clear a slot to receive the Machinima tool."
### 3.4 Asset Editor
The client includes an asset editor with these features:
- `AssetEditorDownload` - Download assets from tools service
- `assetEditor.exportModal` - Export modal for assets
- `assetEditor.fileSaveState` - File save state management
- `assetEditor.property.tooltip` - Property tooltips
### 3.5 tools.hytale.com API Requirements
To fully support builder mode, the tools service would need:
```
POST /assets/upload
- Upload asset files (images, models, sounds)
- Returns asset ID/URL
GET /assets/{assetId}
- Download asset by ID
- Returns asset binary data
POST /prefabs/save
- Save prefab definition
- Returns prefab ID
GET /prefabs/{prefabId}
- Load prefab by ID
- Returns prefab JSON
GET /prefabs/list
- List user's saved prefabs
- Returns array of prefab metadata
DELETE /prefabs/{prefabId}
- Delete a prefab
```
**Note:** The game functions without tools.hytale.com - it's only needed for cloud-based asset sharing in builder mode.
---
## 4. External Service URLs
### 4.1 Hytale Official URLs
| URL | Purpose | Patchable |
|-----|---------|-----------|
| `https://store.hytale.com/?upgrade=` | In-game store for purchases | Yes |
| `https://hytale.com/help/joining-friends` | Help documentation | Yes |
| `https://discord.gg/hytale` | Official Discord invite | Yes |
### 4.2 Third-Party Service URLs
| URL | Purpose | Notes |
|-----|---------|-------|
| `https://blockbench.net/downloads` | Blockbench download page | 3D model editor |
| `https://blockbench.net/plugins/hytale_plugin` | Hytale Blockbench plugin | For asset creation |
| `https://docs.sentry.io/platforms/dotnet/*` | Sentry documentation | Error tracking docs |
| `https://aka.ms/*` | Microsoft .NET documentation | Runtime docs |
| `https://learn.microsoft.com/*` | Microsoft Learn | .NET API docs |
| `https://go.microsoft.com/*` | Microsoft redirects | Various docs |
### 4.3 Graphics/Rendering References
| URL | Purpose |
|-----|---------|
| `https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)` | GLSL interface blocks |
| `https://www.khronos.org/opengl/wiki/Sampler_(GLSL)` | GLSL texture samplers |
| `https://www.shadertoy.com/view/Xd23Dh` | Shader reference |
| `https://www.shadertoy.com/view/ltlSRj` | Shader reference |
| `https://aras-p.info/texts/CompactNormalStorage.html` | Normal map compression |
| `https://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/` | Depth reconstruction |
| `https://briansharpe.files.wordpress.com/2018/07/moment-transparency-supp-av.pdf` | Transparency rendering |
| `https://www.pmavridis.com/research/fbcompression/` | Frame buffer compression |
| `https://jcgt.org/published/0002/02/09/` | Graphics technique |
| `https://jcgt.org/published/0006/01/03/` | Graphics technique |
| `https://graphics.cs.williams.edu/papers/CSSM/` | Graphics paper |
| `http://www.humus.name/Articles/Persson_LowLevelThinking.pdf` | Low-level graphics |
### 4.4 GitHub References
| URL | Purpose |
|-----|---------|
| `https://github.com/NLog/NLog.git` | Logging framework |
| `https://github.com/Noesis/Managed/tree/master/Src/Noesis/Core` | NoesisGUI core |
| `https://github.com/Noesis/Managed/tree/master/Src/NoesisApp/Core` | NoesisGUI app |
| `https://github.com/dotnet/dotnet` | .NET runtime |
| `https://github.com/ektrah/nsec.git` | NSec cryptography |
| `https://github.com/getsentry/sentry-dotnet` | Sentry .NET SDK |
---
## 5. Patchable Strings
### 5.1 Domain Strings
| Original | Replacement | Purpose |
|----------|-------------|---------|
| `hytale.com` | `{f2p_domain}` | Base domain (4-16 chars) |
| `sessions.` | Stripped or replaced | Session service subdomain |
| `account-data.` | Stripped or replaced | Account service subdomain |
| `telemetry.` | Stripped or replaced | Telemetry subdomain |
| `tools.` | Stripped or replaced | Tools service subdomain |
### 5.2 URL Strings
| Original | Can Replace With | Notes |
|----------|------------------|-------|
| `https://store.hytale.com/?upgrade=` | Custom store URL | In-game purchases |
| `https://discord.gg/hytale` | Custom Discord | Community link |
| `https://hytale.com/help/joining-friends` | Custom help docs | Help system |
| `sentry.hytale.com` | Own Sentry or disable | Error tracking |
### 5.3 String Encoding Details
**.NET UTF-16LE Format:**
- Each character is 2 bytes (little-endian)
- Example: "hytale" = `68 00 79 00 74 00 61 00 6c 00 65 00`
- Strings are length-prefixed in the binary
**Length Prefix Format:**
- 1 byte for strings < 128 chars
- 2 bytes (varint) for longer strings
- Followed by UTF-16LE character data
### 5.4 Current Patcher Behavior
The `clientPatcher.js` patches:
1. `sessions.hytale.com``{f2p_domain}` (single endpoint)
2. `account-data.hytale.com``{f2p_domain}`
3. `telemetry.hytale.com``{f2p_domain}`
**Not currently patched:**
- `tools.hytale.com` (builder mode assets)
- `store.hytale.com` (in-game store)
- `sentry.hytale.com` (error tracking)
---
## 6. Sentry Error Tracking
### 6.1 Sentry Configuration
**DSN Found in Binary:**
```
https://ca900df42fcf57d4dd8401a86ddd7da2@sentry.hytale.com/
```
**DSN Components:**
- Protocol: `https`
- Public Key: `ca900df42fcf57d4dd8401a86ddd7da2`
- Host: `sentry.hytale.com`
- Project ID: (after trailing slash)
### 6.2 Sentry Integration
The client uses the official Sentry .NET SDK:
- Package: `sentry-dotnet`
- Documentation refs found in binary
### 6.3 Patching Options
**Option 1: Disable Sentry**
- Replace DSN with invalid string
- Errors won't be reported
**Option 2: Redirect to Own Sentry**
- Replace `sentry.hytale.com` with own Sentry host
- Requires same-length domain or binary patching
**Option 3: Leave As-Is**
- Errors still report to Hypixel
- May expose F2P server information
### 6.4 Sentry Environment Variables
Found configuration references:
- `SENTRY_DSN` - DSN override
- `SENTRY_ENVIRONMENT` - Environment name
- Docs: `https://docs.sentry.io/platforms/dotnet/configuration/environments`
---
## 7. Internal Class References
### 7.1 Package Structure
```
com.hypixel.hytale/
├── builtin/
│ ├── buildertools/
│ │ ├── imageimport/
│ │ │ └── ImageImportPage
│ │ ├── objimport/
│ │ │ └── ObjImportPage
│ │ ├── prefabeditor/
│ │ │ └── ui/PrefabEditorLoadSettings
│ │ └── prefablist/
│ │ └── PrefabPage
│ ├── instances/
│ │ └── page/InstanceListPage
│ └── model/
│ └── pages/ChangeModelPage
├── server/
│ └── core/
│ └── asset/
│ └── type/
│ └── particle/
│ └── pages/ParticleSpawn*
└── Creation/
└── navigation/
├── buildertools/
└── worldtools/
├── changeModel
├── importImage
├── importObj
├── instance
├── playSound
├── prefabEditor
├── prefabList
├── spawnEntity
├── spawnParticle
└── tintChunk
```
### 7.2 UI Components
| Component | Path | Purpose |
|-----------|------|---------|
| GameLoading | `/GameLoading.u` | Loading screen |
| GamePageNavigation | `/GamePageNavigation.u` | Main navigation |
| ServerButton | `/ServerButton.u` | Server list button |
| ServerModal | `/ServerModal.u` | Server details modal |
| ServersPage | `/Servers/ServersPage.u` | Server browser |
| DirectConnectPopup | `/Servers/DirectConnectPopup.u` | Direct connect dialog |
| EditServerPopup | `/Servers/EditServerPopup.u` | Edit server dialog |
| JoinViaCodePopup | `/Servers/JoinViaCodePopup.u` | Join via code dialog |
| MinigamesPage | `/Minigames/MinigamesPage.u` | Minigames browser |
### 7.3 Configuration Files
| File | Purpose |
|------|---------|
| `/GameplayConfigs/Default.json` | Default gameplay settings |
| `hytale_plugin.js` | Blockbench plugin script |
| `hytale_assets` | Asset reference |
---
## 8. Binary Offsets Reference
### 8.1 URL String Offsets (macOS binary)
| Offset | Content | Length |
|--------|---------|--------|
| `0x1bf0098` | `https://account-data` | ~21 chars |
| `0x1bf00c9` | `https://aka.ms/dotnet-warnings/{0}` | ~35 chars |
| `0x1bf0114` | `https://blockbench.net/downloads` | ~33 chars |
| `0x1bf015d` | `https://blockbench.net/plugins/hytale_plugin` | ~45 chars |
| `0x1bf01bc` | `https://...@sentry.hytale.com/` | ~60 chars |
| `0x1bf023b` | `https://discord.gg/hytale` | ~26 chars |
| `0x1bf0274` | `https://hytale.com/help/joining-friends` | ~40 chars |
| `0x1bf02c9` | `https://sessions` | ~17 chars |
| `0x1bf02f2` | `https://store.hytale.com/?upgrade=` | ~35 chars |
| `0x1bf033d` | `https://telemetry` | ~18 chars |
| `0x1bf0368` | `https://tools` | ~14 chars |
### 8.2 API Endpoint Offsets
| Offset | Endpoint |
|--------|----------|
| `0x1b115d2` | `/game-session/child` |
| `0x1b115ff` | `/game-session/refresh` |
| `0x1b117c2` | `/server-join/auth-grant` |
| `0x1b117f7` | `/server-join/auth-token` |
| `0x1b11689` | `/my-account/cosmetics` |
| `0x1b116ba` | `/my-account/game-profile` |
| `0x1b116f1` | `/my-account/skin` |
| `0x1b10d8c` | `/.well-known/jwks.json` |
### 8.3 Notes on Offsets
- Offsets are for the macOS binary
- Windows/Linux binaries will have different offsets
- Offsets may change between game versions
- Always verify offsets before patching
---
## 9. Implementation Notes
### 9.1 Current Auth Server Implementation
The auth server (`hytale-auth-server`) currently implements:
**Fully Implemented:**
- [x] `/game-session/new` - Session creation
- [x] `/game-session/refresh` - Token refresh
- [x] `/server-join/auth-grant` - Auth grants
- [x] `/server-join/auth-token` - Token exchange with cert binding
- [x] `/my-account/cosmetics` - Cosmetic list
- [x] `/my-account/game-profile` - Profile get/update
- [x] `/my-account/skin` - Skin save
- [x] `/.well-known/jwks.json` - JWKS endpoint
- [x] `/profile/uuid/{uuid}` - UUID lookup
- [x] `/profile/username/{username}` - Username lookup
- [x] Telemetry endpoints (accept and discard)
**Not Implemented:**
- [ ] `tools.hytale.com` API (asset upload/download)
- [ ] Prefab cloud storage
- [ ] Asset sharing between players
### 9.2 Tools Service Implementation (Future)
If implementing tools.hytale.com functionality:
```javascript
// Suggested endpoints for auth-server
// Asset upload
app.post('/tools/assets/upload', async (req, res) => {
// Handle multipart file upload
// Store in local filesystem or S3
// Return asset ID
});
// Asset download
app.get('/tools/assets/:assetId', async (req, res) => {
// Retrieve asset by ID
// Stream file to client
});
// Prefab operations
app.post('/tools/prefabs', async (req, res) => {
// Save prefab JSON
// Associate with user
});
app.get('/tools/prefabs/:prefabId', async (req, res) => {
// Get prefab by ID
});
app.get('/tools/prefabs', async (req, res) => {
// List user's prefabs
});
app.delete('/tools/prefabs/:prefabId', async (req, res) => {
// Delete prefab
});
```
### 9.3 Patching Recommendations
**Essential (Already Done):**
1. Patch `sessions.hytale.com` → F2P domain
2. Patch `account-data.hytale.com` → F2P domain
3. Patch `telemetry.hytale.com` → F2P domain (or disable)
**Optional Enhancements:**
1. Patch `tools.hytale.com` → F2P domain (if implementing tools API)
2. Patch `sentry.hytale.com` → Own Sentry or disable
3. Patch `discord.gg/hytale` → Community Discord
4. Patch `store.hytale.com` → Custom store (if applicable)
**Not Recommended to Patch:**
- Blockbench URLs (useful for modding)
- Microsoft documentation URLs
- Graphics reference URLs
### 9.4 Security Considerations
1. **Sentry DSN Exposure**
- Current: Errors report to Hypixel's Sentry
- Risk: May expose F2P server details
- Recommendation: Disable or redirect
2. **Telemetry Data**
- Current: Accepted but discarded
- Alternative: Log for analytics
- Risk: Privacy concerns
3. **Asset Upload (if implemented)**
- Validate file types
- Limit file sizes
- Scan for malicious content
- Rate limit uploads
---
## Appendix A: String Extraction Commands
### Extract UTF-16LE Strings
```bash
python3 << 'EOF'
with open("HytaleClient", "rb") as f:
data = f.read()
pattern = b'h\x00t\x00t\x00p\x00s\x00:\x00/\x00/\x00'
idx = 0
while True:
idx = data.find(pattern, idx)
if idx == -1:
break
end = idx
chars = []
while end < len(data) - 1:
char = data[end] | (data[end+1] << 8)
if 0x20 <= char <= 0x7e:
chars.append(chr(char))
end += 2
else:
break
print(f"{hex(idx)}: {''.join(chars)}")
idx += 2
EOF
```
### Search for Specific Pattern
```bash
xxd HytaleClient | grep "h.y.t.a.l.e"
```
### Extract Context Around Offset
```bash
dd if=HytaleClient bs=1 skip=$((0x1bf0000)) count=2048 | xxd
```
---
## Appendix B: Version History
| Date | Changes |
|------|---------|
| 2026-01-27 | Initial analysis of macOS client binary |
---
## Appendix C: Related Documentation
- `CLAUDE.md` - Project overview and architecture
- `DUAL_AUTH_FLOW.md` - Dual authentication flow diagrams
- `STEAMDECK_CRASH_INVESTIGATION.md` - libzstd crash fix
- `PLAYER_PASSWORD_FEATURE.md` - Planned password authentication
- `backend/utils/clientPatcher.js` - Client patcher implementation

View File

@@ -0,0 +1,113 @@
# Singleplayer Server Crash: fastutil ClassNotFoundException
## Status: Open (user-specific, Feb 24 2026)
## Symptom
Singleplayer server crashes immediately after DualAuth Agent installs successfully:
```
Exception in thread "main" java.lang.NoClassDefFoundError: it/unimi/dsi/fastutil/objects/ObjectArrayList
at com.hypixel.hytale.plugin.early.EarlyPluginLoader.<clinit>(EarlyPluginLoader.java:34)
at com.hypixel.hytale.Main.main(Main.java:36)
Caused by: java.lang.ClassNotFoundException: it.unimi.dsi.fastutil.objects.ObjectArrayList
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
```
Server exits with code 1. Multiplayer works fine for the same user.
## Affected User
- Discord: ヅ𝚃 JAYED !
- Platform: Windows (standard x86_64, NOT ARM)
- Reproduces 100% on singleplayer, every attempt
- Other users (including macOS/Linux) are NOT affected
## What Works
- Java wrapper correctly strips `-XX:+UseCompactObjectHeaders`
- Java wrapper correctly injects `--disable-sentry`
- DualAuth Agent v1.1.12 installs successfully (STATIC mode)
- Multiplayer connections work fine
- Repair and reinstall did NOT fix the issue
## Root Cause Analysis
`fastutil` (`it.unimi.dsi.fastutil`) should be bundled inside `HytaleServer.jar` (fat JAR). The `ClassNotFoundException` means the JVM's app classloader cannot find it despite it being in the JAR.
### Ruled Out
- **Wrapper issue**: Wrapper is working correctly (confirmed in logs)
- **UseCompactObjectHeaders**: Server also has `-XX:+IgnoreUnrecognizedVMOptions`, so unrecognized flags don't crash it
- **DualAuth Agent**: Works for all other users; agent installs successfully before the crash
- **Corrupted game files**: Repair/reinstall didn't help
- **ARM64/Parallels**: User is on standard Windows, not ARM
### Likely Causes (user-specific)
1. **Antivirus interference** — Windows Defender or third-party AV blocking Java from reading classes out of JAR files, especially with `-javaagent` active
2. **Corrupted/incompatible JRE** — bundled JRE might be broken on their system
3. **File locking** — another process holding HytaleServer.jar open
## Debugging Steps (ask user)
1. **Does official Hytale singleplayer work?** (without F2P launcher)
- Yes → something about our launch setup
- No → their system/JRE issue
2. **Check antivirus** — add game directory to Windows Defender exclusions:
- Settings → Windows Security → Virus & threat protection → Exclusions
- Add their HytaleF2P install folder
3. **Verify fastutil is in the JAR**:
```cmd
jar tf "D:\path\to\Server\HytaleServer.jar" | findstr fastutil
```
- If output shows fastutil classes → JAR is fine, classloader issue
- If no output → JAR is incomplete/corrupt (different from other users)
4. **Try without DualAuth agent** — rename `dualauth-agent.jar` in Server/ folder, retry singleplayer
- If works → agent's classloader manipulation breaks fastutil on their setup
- If still fails → unrelated to agent
5. **Check JRE version** — have them run:
```cmd
"D:\path\to\jre\latest\bin\java.exe" -version
```
## Update (Feb 24): `-XX:+UseCompactObjectHeaders` stripping removed from defaults
Stripping this flag did NOT fix the issue. The server already has `-XX:+IgnoreUnrecognizedVMOptions` so unrecognized flags are harmless. The flag was removed from default `stripFlags` in `backend/core/config.js`.
## Using the Java Wrapper to Strip JVM Flags
If a user needs to strip a specific JVM flag (e.g., for debugging or compatibility), they can do it via the launcher UI:
1. Open **Settings** → scroll to **Java Wrapper Configuration**
2. Under **JVM Flags to Remove**, type the flag (e.g. `-XX:+UseCompactObjectHeaders`) and click **Add**
3. The flag will be stripped from all JVM invocations at launch time
4. To inject custom arguments, use the **Arguments to Inject** section (with optional "Server Only" condition)
5. **Restore Defaults** resets to empty strip flags + `--disable-sentry` (server only)
The wrapper generates platform-specific scripts at launch time:
- **Windows**: `java-wrapper.bat` in `jre/latest/bin/`
- **macOS/Linux**: `java-wrapper` shell script in the same directory
Config is stored in `config.json` under `javaWrapperConfig`:
```json
{
"javaWrapperConfig": {
"stripFlags": ["-XX:+SomeFlag"],
"injectArgs": [
{ "arg": "--some-arg", "condition": "server" },
{ "arg": "--other-arg", "condition": "always" }
]
}
}
```
## Related
- Java wrapper config: `backend/core/config.js` (stripFlags / injectArgs)
- DualAuth Agent: v1.1.12, package `ws.sanasol.dualauth`
- Game version at time of report: `2026.02.19-1a311a592`

View File

@@ -0,0 +1,48 @@
# Client Crash: RAM Pressure on Low-End Hardware
## Status: Resolved (Feb 24, 2026)
## Symptom
Game launches but crashes with exit code 1 after ~32 seconds. Launcher logs show stale `java.exe(HytaleServer)` killed on every relaunch. Earlier sessions showed game running for ~4 minutes before `System.OutOfMemoryException`.
## Affected User
- Discord: KULVIN
- Hardware: Intel UHD 620 + NVIDIA MX150 (2GB VRAM), low-end laptop
- 22 mods installed
- Platform: Windows x64
## Root Cause
RAM pressure from background apps + 22 mods. The game's .NET client ran out of memory, and the embedded singleplayer server JVM (no `-Xmx` cap) competed for the same limited RAM.
## Timeline
1. Morning session: Game ran ~4 minutes, then `System.OutOfMemoryException` crashed client, server JVM crashed with `EXCEPTION_ACCESS_VIOLATION`
2. Evening sessions: Game started crashing in ~32 seconds (system still degraded from earlier OOM)
3. Server JVM orphaned every time (cleaned up by `killGameProcesses()` on next launch)
## Resolution
User fixed by:
1. Closing background applications to free RAM
2. Reinstalling the game
## Additional Issues Found
- `WeaponStatsViewer` mod left a directory (not a .jar) in `HytaleSaves\Mods\`, causing EPERM on every mod sync
- Stale AOT cache (`HytaleServer.aot`) cleaned up automatically by launcher
## Debugging Steps (for similar cases)
1. Check RAM usage in Task Manager before launching
2. Windows Event Viewer (Win+R → `eventvwr.msc` → Application) for crash module details
3. Try with all mods disabled
4. Reboot to clear degraded memory state
5. Close background apps (browsers, Discord, etc.)
## Recommendations
- Low-end hardware: reduce mod count (10 or fewer)
- Consider adding `-Xmx` cap to singleplayer server JVM to prevent unbounded memory growth

138
docs/UPDATE_SYSTEM_FIXES.md Normal file
View File

@@ -0,0 +1,138 @@
# Update System Fixes Summary
## Overview
This document summarizes the fixes made to the launcher auto-update system to improve UX and fix macOS-specific issues.
## Issues Fixed
### 1. Duplicate Update Popups
**Problem:** Two different update UI files (`update.js` and `updater.js`) were both listening for update events, causing duplicate popups to appear.
**Solution:**
- Disabled `updater.js` in `index.html` (commented out the script tag)
- Now only `update.js` handles all update UI with improved features
### 2. Missing Skip Button
**Problem:** Users were soft-locked on the update screen with no way to dismiss it, especially problematic on macOS where auto-install often fails.
**Solution:**
- Added "Skip for now (not recommended)" button to update popup
- Skip button appears:
- After 30 seconds (timeout fallback)
- Immediately on any update error
- After install attempt fails (5 second timeout)
- Always visible once download completes
### 3. macOS Auto-Install Failure
**Problem:** `quitAndInstall()` silently fails on unsigned macOS apps, leaving users stuck.
**Solution:**
- Detect macOS in `main.js` and send `autoInstallSupported: false` flag
- On macOS, show "Download Manually (Recommended)" as primary action
- "Try Install & Restart" shown as secondary option
- Added force quit fallback in `install-update` handler for macOS
- Clear messaging: "Update downloaded but auto-install may not work on macOS"
### 4. Missing IPC Handlers
**Problem:** `open-download-page` IPC handler was not registered, causing errors when clicking manual download.
**Solution:**
- Added `open-download-page` handler in `main.js` that opens GitHub releases page
- Added `quitAndInstallUpdate` alias in `preload.js` for compatibility
### 5. Interface Blocking Not Removed
**Problem:** `unblockInterface()` method was called but never defined, leaving the UI blurred after closing popup.
**Solution:**
- Added complete `unblockInterface()` method that:
- Removes `interface-blocked` class from main content
- Removes `no-select` class from body
- Properly removes event listeners using stored bound function references
### 6. Breathing Animation on Downloaded State
**Problem:** The pulse/breathing animation continued after download completed, which felt inappropriate for a "ready to install" state.
**Solution:**
- Remove `update-popup-pulse` class in `showUpdateDownloaded()` method
### 7. Player Name Not Synced on First Install
**Problem:** Player name entered during installation wasn't synced to settings page input.
**Solution:**
- In `install.js`, sync player name to both `playerName` and `settingsPlayerName` inputs after installation completes
## Files Modified
### `GUI/index.html`
- Commented out `updater.js` script tag (duplicate update UI)
### `GUI/js/update.js`
- Removed legacy `onUpdatePopup` listener
- Added `closeUpdatePopup()` method
- Added `unblockInterface()` method
- Added skip button to popup HTML
- Added skip button visibility logic (30s timeout, on error, after download)
- Added macOS detection and alternative UI (manual download as primary)
- Removed pulse animation when download completes
- Added console logging for debugging
- Added extra DOM check to prevent duplicate popups
- Fixed manual download button to show "Opened in browser" and close popup
### `main.js`
- Changed `autoUpdater.autoDownload` from `false` to `true`
- Added macOS error handling with `requiresManualDownload` flag
- Added `autoInstallSupported` flag to `update-downloaded` event
- Added `open-download-page` IPC handler
- Enhanced `install-update` handler with macOS force quit fallback
### `preload.js`
- Added `quitAndInstallUpdate` alias for `install-update` IPC
### `GUI/js/install.js`
- Sync player name to `settingsPlayerName` input after installation
### `backend/utils/clientPatcher.js`
- Removed server patching code (server uses pre-patched JAR from CDN)
- Simplified to client-only patching
- Removed unused imports: `crypto`, `AdmZip`, `execSync`, `spawn`, `getJavaExec`, `getBundledJavaPath`, `JRE_DIR`
- Removed unused methods: `stringToUtf8()`, `findAndReplaceDomainUtf8()`
- Cleaned up comments and documentation
- Localhost/local dev code moved to `clientPatcher.localhost.js.bak` for reference
## Testing
To test the update popup manually, you can temporarily add this debug code to `update.js` init():
```javascript
// DEBUG: Simulate update available popup after 2 seconds
setTimeout(() => {
this.showUpdatePopup({
currentVersion: '2.0.0',
newVersion: '2.1.0',
releaseNotes: 'Debug test update'
});
// Simulate download complete after 3 more seconds
setTimeout(() => {
this.showUpdateDownloaded({
version: '2.1.0',
platform: 'darwin',
autoInstallSupported: false // Simulate macOS
});
}, 3000);
}, 2000);
```
## Platform-Specific Behavior
### Windows/Linux
- Auto-download enabled
- "Install & Restart" as primary action
- Skip button available as fallback
### macOS
- Auto-download enabled (download works, install doesn't)
- "Download Manually (Recommended)" as primary action
- "Try Install & Restart" as secondary option
- Skip button always visible after download
- Force quit fallback if quitAndInstall fails