Files
gitea-docker/desktop/UPDATE.md
2026-03-30 21:51:50 -07:00

700 lines
21 KiB
Markdown

# LibGDX 1.9.6 → 1.14.1 Upgrade Plan
## Overview
This plan upgrades Tick's Tales from libGDX 1.9.6 to 1.14.1, along with updating Clojure, core.async, and Java target version.
**Risk Level:** Medium - Breaking changes are well-defined and limited to specific methods.
**Estimated Effort:** 2-4 hours including testing
---
## Background & Research Sources
Before executing this plan, the implementor should understand the scope of changes between libGDX 1.9.6 and 1.14.1.
### Primary Research Sources
| Source | URL | Purpose |
|--------|-----|---------|
| libGDX CHANGES file | https://github.com/libgdx/libgdx/raw/master/CHANGES | Official changelog - read versions 1.9.7 through 1.14.1 |
| libGDX Releases | https://github.com/libgdx/libgdx/releases | Release notes with upgrade guidance |
| libGDX Wiki | https://libgdx.com/wiki/ | General documentation |
| LWJGL 3 Changelog | https://www.lwjgl.org/changelog | LWJGL changes bundled with libGDX |
| Clojure Changelog | https://github.com/clojure/clojure/blob/master/Changes.md | Clojure version changes |
| core.async Changelog | https://github.com/clojure/core.async/blob/master/CHANGES.md | core.async version changes |
### How to Research Issues
If you encounter unexpected errors during this upgrade:
1. **Check the libGDX CHANGES file** for your specific error message or class name
```bash
# Search for a specific class or method
curl -s https://raw.githubusercontent.com/libgdx/libgdx/master/CHANGES | grep -i "YourClassName"
```
2. **Search libGDX issues**: https://github.com/libgdx/libgdx/issues
- Search for error messages
- Search for class names that fail
3. **Check LWJGL issues**: https://github.com/LWJGL/lwjgl3/issues
- LWJGL3 is bundled with libGDX; native library issues may originate here
4. **Check play-clj keyword translation**:
- The macro `key->method` in `play-clj/src/play_clj/utils.clj:80-83` converts keywords to Java method calls
- `:set-fullscreen-mode` becomes `.setFullscreenMode()`
- If a method was renamed, search for the new name using the keyword pattern
---
## Why This Upgrade?
### 1. Bug Fixes
LibGDX 1.9.6 was released in 2017. The 1.14.1 release includes fixes for:
- Audio device switching issues (automatic in 1.12.1+)
- Borderless fullscreen bugs
- Various native crashes on LWJGL 3
- Memory leaks in frame buffer handling
### 2. LWJGL 3 Updates
The bundled LWJGL version updates from 3.1.0 to 3.3.3:
- Better hardware compatibility
- Fixed various native crashes
- Improved Wayland support (Linux)
### 3. Java Compatibility
LibGDX 1.13.0+ is built with Java 17:
- Targeting Java 11 ensures compatibility with modern JVMs
- Your current JDK 25 will work without issues
### 4. Clojure Updates
Clojure 1.8.0 → 1.11.3 brings:
- Better error messages
- Performance improvements
- `parse-double`, `parse-long`, `parse-boolean` utilities
- `update-keys`, `update-vals` functions
---
## Prerequisites
- [ ] **Create a branch for this upgrade work**
```bash
cd /home/noti/dev/tickstales/desktop
git checkout -b upgrade/libgdx-1.14.1
```
- [ ] **Verify current build works**
```bash
lein check
```
Note any warnings or errors for comparison later.
---
## Part 1: Update play-clj Library
The play-clj library (symlinked at `/home/noti/dev/tickstales/play-clj` → `/home/noti/dev/play-clj`) requires modifications before the game can be updated.
### 1.1 Create Branch in play-clj
- [ ] Navigate to play-clj and create a branch
```bash
cd /home/noti/dev/play-clj
git checkout -b upgrade/libgdx-1.14.1
```
### 1.2 Update play-clj Dependencies
**File:** `/home/noti/dev/play-clj/project.clj`
**Why this change:**
- LibGDX must be updated to match the game's version
- Clojure 1.6.0 is ancient (2014); 1.11.3 is the current stable release
- Java 11 target is required for libGDX 1.13.0+ which is built with Java 17
**Research if blocked:**
- Check Maven Central for available versions: https://central.sonatype.com/search?q=g:com.badlogicgames.gdx
- Clojure versions: https://clojure.org/releases/downloads
- [ ] Update libGDX dependencies (approximately lines 6-8):
```clojure
;; BEFORE
[com.badlogicgames.gdx/gdx "1.9.5"]
[com.badlogicgames.gdx/gdx-box2d "1.9.5"]
[com.badlogicgames.gdx/gdx-bullet "1.9.5"]
;; AFTER
[com.badlogicgames.gdx/gdx "1.14.1"]
[com.badlogicgames.gdx/gdx-box2d "1.14.1"]
[com.badlogicgames.gdx/gdx-bullet "1.14.1"]
```
- [ ] Update Clojure version (approximately line 9):
```clojure
;; BEFORE
[org.clojure/clojure "1.6.0"]
;; AFTER
[org.clojure/clojure "1.11.3"]
```
- [ ] Update Java target version in `:javac-options`:
```clojure
;; BEFORE
:javac-options ["-target" "1.8" "-source" "1.8" "-Xlint:-options"]
;; AFTER
:javac-options ["-target" "11" "-source" "11" "-Xlint:-options"]
```
- [ ] **Commit this change:**
```bash
git add project.clj
git commit -m "Update libGDX to 1.14.1 and Clojure to 1.11.3"
```
### 1.3 Fix InputProcessor.scrolled() Signature Change
**File:** `/home/noti/dev/play-clj/src/play_clj/core_listeners.clj`
**Why this change:**
In libGDX 1.9.12, the `InputProcessor.scrolled()` method signature changed to support:
1. **Horizontal scrolling** (trackpads, some mice)
2. **Fractional scroll amounts** (high-precision devices)
**Before (1.9.6 - 1.9.11):**
```java
// InputProcessor interface
boolean scrolled(int amount);
```
**After (1.9.12+):**
```java
// InputProcessor interface
boolean scrolled(float amountX, float amountY);
```
**What happens if you don't fix this:**
- `AbstractMethodError` at runtime when any scroll event occurs
- The game will crash when the mouse wheel is used
**Research if blocked:**
- libGDX CHANGES: Search for "scrolled" or "InputProcessor"
- libGDX PR #6154: https://github.com/libgdx/libgdx/pull/6154
- InputProcessor javadoc: https://libgdx.com/wiki/input/input-handling
**Location in code:**
The `input-processor` function creates a `reify` of the `InputProcessor` interface. Line 22-23 defines the `scrolled` method.
- [ ] Update the `scrolled` method in the `input-processor` function (lines 22-23):
```clojure
;; BEFORE
(scrolled [this a]
(execute-fn! on-scrolled {:amount a})
;; AFTER
(scrolled [this amountX amountY]
(execute-fn! on-scrolled {:amount-x amountX :amount-y amountY})
```
**Impact on game code:**
- Your game's `:on-scrolled` handler in `scene.clj:1445` is commented out, so this won't immediately affect gameplay
- If you use scrolling in the future, access scroll amounts via `:amount-x` and `:amount-y` instead of `:amount`
- [ ] **Commit this change:**
```bash
git add src/play_clj/core_listeners.clj
git commit -m "Fix scrolled() signature for libGDX 1.9.12+ compatibility"
```
### 1.4 Add InputProcessor.touchCancelled() Method
**File:** `/home/noti/dev/play-clj/src/play_clj/core_listeners.clj`
**Why this change:**
In libGDX 1.12.0, a new method was added to the `InputProcessor` interface:
```java
// Added in libGDX 1.12.0
boolean touchCancelled(int screenX, int screenY, int pointer, int button);
```
**Purpose:** This method is called when a touch event is cancelled by the system (e.g., when a dialog appears during a touch, or on mobile when a call comes in). Previously, these situations could leave the game in an inconsistent state.
**What happens if you don't fix this:**
- `AbstractMethodError` at runtime when the game first processes any input
- The reify will not implement all interface methods, causing immediate crash on startup
**Research if blocked:**
- libGDX CHANGES: Search for "touchCancelled"
- libGDX issue #6871: https://github.com/libgdx/libgdx/issues/6871
- libGDX 1.12.0 release notes: https://github.com/libgdx/libgdx/releases/tag/1.12.0
**Location in code:**
Add this method inside the `reify InputProcessor` block, after the `touchUp` method.
- [ ] Add the `touchCancelled` method to the `input-processor` function (after the `touchUp` method, around line 33):
```clojure
(touchUp [this sx sy p b]
(execute-fn! on-touch-up {:input-x sx :input-y sy :pointer p :button b})
false)
;; ADD THIS METHOD:
(touchCancelled [this sx sy p b]
false)
```
**Optional enhancement:** If you want to handle touch cancellation events:
```clojure
;; You could add an :on-touch-cancelled handler similar to other input handlers:
(touchCancelled [this sx sy p b]
(execute-fn! on-touch-cancelled {:input-x sx :input-y sy :pointer p :button b})
false)
```
- [ ] **Commit this change:**
```bash
git add src/play_clj/core_listeners.clj
git commit -m "Add touchCancelled() method for libGDX 1.12.0+ compatibility"
```
### 1.5 Update Documentation (Optional)
**File:** `/home/noti/dev/play-clj/src/play_clj/core.clj`
**Why this change:**
The docstring example for `:on-scrolled` shows the old `:amount` key. Updating it prevents confusion for future developers.
- [ ] Update the `:on-scrolled` docstring (lines 206-210) to reflect new keys:
```clojure
;; BEFORE
; the mouse wheel was scrolled
:on-scrolled
(fn [screen entities]
(println (:amount screen)) ; the amount scrolled
entities)
;; AFTER
; the mouse wheel was scrolled
:on-scrolled
(fn [screen entities]
(println (:amount-x screen)) ; the horizontal scroll amount
(println (:amount-y screen)) ; the vertical scroll amount
entities)
```
- [ ] **Commit this change (if made):**
```bash
git add src/play_clj/core.clj
git commit -m "Update :on-scrolled documentation for new scroll API"
```
### 1.6 Install Updated play-clj
- [ ] Install the updated play-clj library:
```bash
cd /home/noti/dev/play-clj
lein install
```
- [ ] Verify installation succeeded (should see "Created jar" message)
**If installation fails:**
- Check that all dependencies resolve: `lein deps`
- Check for Clojure syntax errors: `lein check`
- Verify Maven local repository: `ls ~/.m2/repository/play-clj/play-clj/`
- [ ] **Commit any generated files:**
```bash
git status
# If pom.xml or other files were modified:
git add -A
git commit -m "Update generated files after lein install"
```
---
## Part 2: Update Game Project
### 2.1 Return to Game Directory
- [ ] Navigate back to the game:
```bash
cd /home/noti/dev/tickstales/desktop
```
### 2.2 Update Game Dependencies
**File:** `/home/noti/dev/tickstales/desktop/project.clj`
**Why this change:**
- libGDX must match the version installed in play-clj
- Clojure 1.11.3 is compatible with 1.8.0 code; no source changes required
- core.async 1.6.681 includes bug fixes and performance improvements
- Java 11 target is required for libGDX 1.13.0+
**Research if blocked:**
- Clojure compatibility: https://clojure.org/reference/compatibility
- core.async releases: https://github.com/clojure/core.async/releases
- [ ] Update libGDX dependencies (approximately lines 19-21):
```clojure
;; BEFORE
[com.badlogicgames.gdx/gdx "1.9.6"]
[com.badlogicgames.gdx/gdx-backend-lwjgl3 "1.9.6"]
[com.badlogicgames.gdx/gdx-platform "1.9.6" :classifier "natives-desktop"]
;; AFTER
[com.badlogicgames.gdx/gdx "1.14.1"]
[com.badlogicgames.gdx/gdx-backend-lwjgl3 "1.14.1"]
[com.badlogicgames.gdx/gdx-platform "1.14.1" :classifier "natives-desktop"]
```
- [ ] Update Clojure version (approximately line 22):
```clojure
;; BEFORE
[org.clojure/clojure "1.8.0"]
;; AFTER
[org.clojure/clojure "1.11.3"]
```
- [ ] Update core.async version (approximately line 27):
```clojure
;; BEFORE
[org.clojure/core.async "0.2.385"]
;; AFTER
[org.clojure/core.async "1.6.681"]
```
- [ ] Update Java target version in `:javac-options` (approximately line 30):
```clojure
;; BEFORE
:javac-options ["-target" "1.7" "-source" "1.7" "-Xlint:-options"]
;; AFTER
:javac-options ["-target" "11" "-source" "11" "-Xlint:-options"]
```
- [ ] **Commit this change:**
```bash
git add project.clj
git commit -m "Update libGDX to 1.14.1, Clojure to 1.11.3, core.async to 1.6.681"
```
### 2.3 Fix ScreenUtils.getFrameBufferPixmap() Deprecation
**File:** `/home/noti/dev/tickstales/desktop/src-common/advent/utils.clj`
**Why this change:**
In libGDX 1.9.14, `ScreenUtils.getFrameBufferPixmap()` was deprecated and replaced with `Pixmap.createFromFrameBuffer()`.
**Old API (deprecated):**
```java
Pixmap pm = ScreenUtils.getFrameBufferPixmap(x, y, width, height);
```
**New API:**
```java
Pixmap pm = Pixmap.createFromFrameBuffer(x, y, width, height);
```
**What happens if you don't fix this:**
- The code will still compile (deprecation warning, not error)
- May fail at runtime in future versions when the method is removed
- The new method is more efficient
**Research if blocked:**
- libGDX CHANGES: Search for "ScreenUtils" or "getFrameBufferPixmap"
- Pixmap javadoc: https://libgdx.com/wiki/graphics/2d/pixmaps
**Location in code:**
Line 258 in `src-common/advent/utils.clj`, inside the function that captures screenshots for save files.
- [ ] Find line 258 and update the deprecated call:
```clojure
;; BEFORE
pm (ScreenUtils/getFrameBufferPixmap x y w h)
;; AFTER
pm (Pixmap/createFromFrameBuffer x y w h)
```
- [ ] **Commit this change:**
```bash
git add src-common/advent/utils.clj
git commit -m "Replace deprecated ScreenUtils/getFrameBufferPixmap with Pixmap/createFromFrameBuffer"
```
---
## Part 3: Build and Test
### 3.1 Clean and Compile
- [ ] Clean previous build artifacts:
```bash
lein clean
```
- [ ] Compile and check for errors:
```bash
lein check
```
Expected: Compilation should succeed. Some reflection warnings are acceptable.
**If compilation fails:**
1. **"Could not locate play_clj__init.class"** - play-clj wasn't installed
```bash
cd /home/noti/dev/play-clj && lein install && cd /home/noti/dev/tickstales/desktop
```
2. **"AbstractMethodError"** - Interface method not implemented
- Check that `touchCancelled` was added to `core_listeners.clj`
- Check that `scrolled` has the correct signature
3. **"ClassNotFoundException"** for libGDX classes
- Run `lein deps` to download dependencies
- Check Maven Central for correct artifact names
4. **Java version errors**
- Verify you're running JDK 11+: `java -version`
- Update `:javac-options` if needed
- [ ] If compilation fails, fix errors and commit fixes before proceeding.
### 3.2 Run Development Build
- [ ] Start the game:
```bash
lein run
```
- [ ] **Test Checklist:**
- [ ] Game launches without errors
- [ ] Main menu displays correctly
- [ ] Mouse cursor changes work
- [ ] Click interactions work (left-click on objects)
- [ ] Dialogue system works
- [ ] Inventory system works
- [ ] Save/Load works
- [ ] Music plays
- [ ] Sound effects play
- [ ] Fullscreen/windowed toggle works
- [ ] Game exits cleanly
**If runtime errors occur:**
1. **"UnsatisfiedLinkError"** - Native library issue
- Check that `gdx-platform` with `:classifier "natives-desktop"` is in dependencies
- LWJGL natives should auto-extract
2. **"NoClassDefFoundError"** - Missing class at runtime
- Check for deprecated/removed classes in libGDX CHANGES
- Ensure all dependencies have matching versions
3. **Audio issues**
- LWJGL 3.3.x has improved audio device handling
- Check system audio configuration
- [ ] If any tests fail, fix issues and commit fixes before proceeding.
### 3.3 Build Release Uberjar
- [ ] Build the standalone jar:
```bash
LEIN_SNAPSHOTS_IN_RELEASE=true lein with-profile steam do clean, compile, uberjar
```
- [ ] Verify jar was created:
```bash
ls -la target/advent-standalone.jar
```
- [ ] Test the uberjar:
```bash
java -jar target/advent-standalone.jar
```
- [ ] **Test Checklist (uberjar):**
- [ ] Game launches from uberjar
- [ ] Basic gameplay works
- [ ] Steam integration works (if applicable)
---
## Part 4: Packaging (Optional)
If you need to create distributable packages:
### 4.1 Update packr Configuration (If Needed)
The packr configuration files reference JDK 8 JREs in the `jvms/` directory. These should continue to work since the bytecode targets Java 11.
**Why Java 8 JREs still work:**
- We compile with `-target 11 -source 11`
- Java bytecode is backwards compatible within major versions
- No Java 11+ specific APIs are used
**Research if updating JREs:**
- Azul Zulu JREs: https://azul.com/downloads/?package=jre
- packr documentation: https://github.com/libgdx/packr
- [ ] If updating to Java 17+ runtime for distribution:
- Download Azul Zulu JDK 17+ JREs
- Place in `jvms/` directory
- Update `build-*.json` files to reference new JRE paths
### 4.2 Test packr Build
- [ ] Build Linux package:
```bash
java -jar packr.jar build-linux-64.json
```
- [ ] Test the built executable:
```bash
./target/linux/amd64/"Tick's Tales"
```
---
## Summary of Changes
### play-clj Changes (3 files)
| File | Change | Reason |
|------|--------|--------|
| `project.clj` | libGDX 1.9.5 → 1.14.1 | Match game version, get bug fixes |
| `project.clj` | Clojure 1.6.0 → 1.11.3 | Modern version, better error messages |
| `project.clj` | Java target 1.8 → 11 | Required for libGDX 1.13.0+ |
| `src/play_clj/core_listeners.clj` | Fix `scrolled` signature | API changed in 1.9.12 |
| `src/play_clj/core_listeners.clj` | Add `touchCancelled` method | New method in 1.12.0 |
| `src/play_clj/core.clj` | Update `:on-scrolled` docstring | Reflect new API |
### Game Changes (2 files)
| File | Change | Reason |
|------|--------|--------|
| `project.clj` | libGDX 1.9.6 → 1.14.1 | Match play-clj version |
| `project.clj` | Clojure 1.8.0 → 1.11.3 | Match play-clj version |
| `project.clj` | core.async 0.2.385 → 1.6.681 | Bug fixes, performance |
| `project.clj` | Java target 1.7 → 11 | Required for libGDX 1.13.0+ |
| `src-common/advent/utils.clj` | `ScreenUtils/getFrameBufferPixmap` → `Pixmap/createFromFrameBuffer` | Deprecated in 1.9.14 |
---
## What Does NOT Need Changes
Based on analysis, the following do NOT require modifications:
### Keyword-Based Method Calls (All Compatible)
All keyword-based method calls in both play-clj and the game remain compatible. The play-clj macro system translates keywords to Java method calls at compile time:
```
:set-fullscreen-mode → .setFullscreenMode()
:get-key-frame-index → .getKeyFrameIndex()
```
None of the methods used by your game were renamed between 1.9.6 and 1.14.1.
**Verified compatible keywords:**
- `(graphics! :set-cursor ...)` ✓
- `(music! ... :set-volume ...)` ✓
- `(sound! ... :set-volume ...)` ✓
- `(slider! ... :get-value)` ✓
- `(label! ... :set-text ...)` ✓
- `(texture! ... :get-region-width)` ✓
- `(animation! ... :get-key-frame-index ...)` ✓
- `(pixmap! ... :set-filter ...)` ✓
- `(particle-effect! ... :reset/:start)` ✓
### Features Not Used by Game
These libGDX features changed but your game doesn't use them:
- Box2D physics (API changes)
- Bullet 3D physics (API changes)
- TiledMap loading (new loaders)
- Pools/ReflectionPool (deprecated)
- 3D rendering (ModelBatch changes)
- JsonValue parsing (case sensitivity)
- `Scaling` enum (became object)
---
## Rollback Plan
If issues arise that cannot be resolved:
```bash
# Rollback play-clj
cd /home/noti/dev/play-clj
git checkout .
lein install
# Rollback game
cd /home/noti/dev/tickstales/desktop
git checkout .
lein clean
```
---
## Completion
- [ ] **Final commit with all changes:**
```bash
git add -A
git commit -m "Complete libGDX 1.14.1 upgrade"
```
- [ ] **Push branches (when ready):**
```bash
# play-clj
cd /home/noti/dev/play-clj
git push origin upgrade/libgdx-1.14.1
# game
cd /home/noti/dev/tickstales/desktop
git push origin upgrade/libgdx-1.14.1
```
---
## References
### Official Documentation
- [libGDX CHANGES](https://github.com/libgdx/libgdx/blob/master/CHANGES) - Complete changelog
- [libGDX Wiki](https://libgdx.com/wiki/) - General documentation
- [LWJGL 3 Documentation](https://www.lwjgl.org/guide) - LWJGL3 guide
### Release Notes
- [libGDX 1.14.1 Release](https://github.com/libgdx/libgdx/releases/tag/1.14.1)
- [libGDX 1.14.0 Release](https://github.com/libgdx/libgdx/releases/tag/1.14.0) - Major changes
- [libGDX 1.13.0 Release](https://github.com/libgdx/libgdx/releases/tag/1.13.0) - Java 17 build
- [libGDX 1.12.0 Release](https://github.com/libgdx/libgdx/releases/tag/1.12.0) - `touchCancelled` added
- [libGDX 1.9.12 Release](https://github.com/libgdx/libgdx/releases/tag/1.9.12) - `scrolled` signature changed
- [libGDX 1.9.14 Release](https://github.com/libgdx/libgdx/releases/tag/1.9.14) - `ScreenUtils.getFrameBufferPixmap` deprecated
### Related Projects
- [Clojure Changelog](https://github.com/clojure/clojure/blob/master/Changes.md)
- [core.async Changelog](https://github.com/clojure/core.async/blob/master/CHANGES.md)
- [packr](https://github.com/libgdx/packr) - JRE bundling tool
### Issue Trackers
- [libGDX Issues](https://github.com/libgdx/libgdx/issues)
- [LWJGL Issues](https://github.com/LWJGL/lwjgl3/issues)