mirror of
https://git.sanhost.net/sanasol/hytale-f2p.git
synced 2026-02-25 22:31:46 -03:00
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:
732
docs/CLIENT_BINARY_ANALYSIS.md
Normal file
732
docs/CLIENT_BINARY_ANALYSIS.md
Normal 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
|
||||
113
docs/FASTUTIL_CLASSLOADER_ISSUE.md
Normal file
113
docs/FASTUTIL_CLASSLOADER_ISSUE.md
Normal 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`
|
||||
48
docs/KULVIN_RAM_PRESSURE_CRASH.md
Normal file
48
docs/KULVIN_RAM_PRESSURE_CRASH.md
Normal 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
138
docs/UPDATE_SYSTEM_FIXES.md
Normal 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
|
||||
Reference in New Issue
Block a user