* WIP
* WIP
* Make camera the single source of truth for broadcast state
Remove redundant local copies of walkAnimId, idleAnimId, and
displayActorIndex from NetworkManager. BroadcastLocalState now reads
these from the camera's Controller, eliminating dual-copy sync issues.
Additional cleanup:
- Early-return on null cam in SendEmote/HandleCustomize for clarity
- Only consume camera-dependent pending requests when cam is available
- Move local name bubble creation from BroadcastLocalState to Tickle
- Remove dead NetworkManager::SetDisplayActorIndex method
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix clang format
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add optional sound effects to emotes
Replace the raw 2D string emote table with a struct-based EmoteEntry/EmotePhase
table so each emote phase can declare an optional 3D spatialized sound effect.
The sound plays via LegoCacheSoundManager when the emote phase starts, positioned
at the character's ROI. No extra network sync needed since sounds trigger locally
when TriggerEmote is called on each client.
Adds "crash5" sound to the BNsDis01 (disassemble) emote phase.
https://claude.ai/code/session_013XkwJJZ4RbNcBMFESuPTfJ
* Extract animation/asset tables from protocol.h into animdata.h
Move EmotePhase, EmoteEntry structs, animation table externs
(walk/idle/emote/vehicle), and helpers (IsMultiPartEmote,
IsLargeVehicle, DetectVehicleType) into a dedicated animdata.h/cpp
pair. This keeps protocol.h focused on wire-format concerns (message
structs, serialization, enums) while animdata.h owns game asset data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Extract ~420 lines of duplicated character animation logic from RemotePlayer
and ThirdPersonCamera into a shared CharacterAnimator component. Both classes
now compose a CharacterAnimator member that handles walk/idle/emote animation
playback, vehicle ride animations, click animation tracking, name bubbles,
and animation cache management.
Behavioral differences between consumers (emote transform save/restore) are
handled via CharacterAnimatorConfig.
Also extract duplicated username encoding (letter indices to ASCII) from
NetworkManager::BroadcastLocalState and ThirdPersonCamera::CreateNameBubble
into EncodeUsername() in protocol.cpp.
Replace C standard library usage across the multiplayer extension with SDL
equivalents: sprintf->SDL_snprintf, sscanf->SDL_sscanf, atoi->SDL_atoi,
strcmp->SDL_strcmp, fabsf->SDL_fabsf, floorf->SDL_floorf, and remove
unnecessary <cmath>, <cstdio>, <cstdlib> headers.
* WIP: Add character customization to multiplayer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Refine character customization: fix message buffering, DRY up code, request-based model
- Register NetworkManager with TickleManager via HandleCreate hook in
LegoOmni::Create(), so packets are processed continuously instead of
buffering between Connect() and OnWorldEnabled()
- Spawn unspawned remote players in OnWorldEnabled() (created before
world was ready)
- Switch to request-based customization: HandleROIClick sends
MSG_CUSTOMIZE to server, server echoes to all peers, HandleCustomize
applies state and plays effects
- DRY up SwitchVariant to delegate LOD cloning to ApplyHatVariant
- Add ApplyChange helper consolidating the switch-on-changeType pattern
- Fix InitFromActorInfo to derive dependent color parts from independent
parts (matching Unpack rules)
- Remove dead code: m_hasBeenTicked, ApplyCustomizeChange on
RemotePlayer, m_localCustomizeState on NetworkManager
- Add null ROI checks in HandleCustomize for unspawned players
- Move MSG_CUSTOMIZE constant to shared protocol.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix
* Fix character customization bugs from code review
- BUG-1: Add bounds check in SwitchColor to prevent OOB access from
unvalidated network input (p_partIndex could exceed array bounds)
- BUG-2: Enforce allowRemoteCustomize on receiver side in HandleCustomize
(was only checked on sender side, byppassable by malicious client)
- BUG-3: Document stale-state sound asymmetry for remote targets
- OBS-1: Remove unused bodyVariantIndex from CustomizeState (never
modified, wasted 3 bits per state message)
- NAME-1: Fix p_ prefix convention on ApplyCustomizeChange parameters
Renders a billboard text bubble showing each remote player's display
name. Includes a WASM export to toggle visibility from the frontend.
- Bitmap font renderer generates paletted textures for name labels
- Billboard quad faces the camera each frame via orientation matrix
- Bubble visibility managed globally by NetworkManager toggle
- Fix miniwin D3DRMIMAGE constructor code style (static_cast, const)
* Add feasibility plan for reusing multiplayer animation system for third-person camera
Evaluates reusing the multiplayer extension's RemotePlayer animation system
(BuildROIMap, AssignROIIndices, ApplyAnimationTransformation) for the local
player to enable a third-person camera mode. Conclusion: feasible with only
3 single-line extension hooks added to core game code.
https://claude.ai/code/session_01NC3zdQZ4nqEcYjyvStqcdD
* WIP: Third-person camera with animation reuse and movement fix
* Fix third-person camera bugs: vehicles, remote facing, emote distortion (#2)
- Fix spawn pose and building re-entry by applying idle frame 0 and
reinitializing on world enable
- Handle vehicle transitions: ride animations for small vehicles,
first-person fallback for large vehicles and helicopter
- Keep vehicle dashboards visible for exit controls
- Disable third-person camera for large vehicles, fix ROI cleanup
- Move HandleActorExit hook to end of Exit() for immediate reinit
- Fix remote player facing 180 degrees wrong by negating direction
in BroadcastLocalState when third-person camera is active
- Fix Hat Tip emote distortion from compounding transform scale by
saving clean parent transform at emote start and restoring after
each frame's animation application
* DRY cleanup for third-person camera branch
- Extract shared DetectVehicleType() to protocol.h/cpp (was duplicated
in ThirdPersonCamera and NetworkManager)
- Remove no-op HandlePostApplyTransform hook chain (called every frame
for every LegoPathActor but did nothing)
- Add ThirdPersonCamera::ClearAnimCaches() helper (pattern repeated 5x)
- Add AnimUtils::EnsureROIMapVisibility() inline helper (loop repeated
5x across ThirdPersonCamera and RemotePlayer)
- Remove redundant static_cast in multiplayer.cpp (UserActor() already
returns LegoPathActor*)
- Delete THIRD_PERSON_CAMERA_ANIMATION_REUSE_PLAN.md development artifact
Move all Emscripten-specific multiplayer code under platforms/emscripten/
and introduce an abstract PlatformCallbacks interface for outbound
notifications, mirroring the existing NetworkTransport pattern. This
removes all #ifdef __EMSCRIPTEN__ blocks from networkmanager.cpp.
Move WASM exports (mp_set_walk_animation, mp_set_idle_animation,
mp_trigger_emote) from multiplayer.cpp into a dedicated
wasm_exports.cpp, added to the isle target (guarded by both
EMSCRIPTEN and ISLE_EXTENSIONS) so the linker keeps the symbols.
Replace the polling mp_get_player_count export with push-based
playerCountChanged CustomEvents dispatched from NetworkManager.
The count only reflects players visible in the Isle world: null
when the local player is outside Isle, filtered by remote player
worldId when inside. Remove the now-unused GetPlayerCount() method.
Implement the animation system from the Phase 1 plan:
Protocol: Add walkAnimId/idleAnimId fields to PlayerStateMsg (2 extra bytes
per 15Hz tick), add MSG_EMOTE (type 9) with EmoteMsg struct, and define
shared animation lookup tables (walk: 6 anims, idle: 3, emote: 2).
NetworkManager: Store local walk/idle animation indices, include them in
every state broadcast, handle incoming MSG_EMOTE by dispatching to the
target remote player's TriggerEmote(). Add SetWalkAnimation(),
SetIdleAnimation(), SendEmote(), GetPlayerCount() public API.
RemotePlayer: Replace per-animation raw pointers with AnimCache struct
and lazy m_animCacheMap (name -> ROI map, built on first use, cleared on
Despawn). UpdateFromNetwork() detects walk/idle ID changes and swaps the
active animation cache. UpdateAnimation() now has three states: moving
(configurable walk anim), emote (one-shot with duration tracking,
interrupted by movement), and idle (configurable idle anim after 2.5s
timeout). Add TriggerEmote() for one-shot emote playback.
WASM exports: mp_set_walk_animation(), mp_set_idle_animation(),
mp_trigger_emote(), mp_get_player_count() with EMSCRIPTEN_KEEPALIVE.
CMakeLists.txt adds EXPORTED_FUNCTIONS and EXPORTED_RUNTIME_METHODS
for Svelte ccall/cwrap access.
https://claude.ai/code/session_01BEYdu8gXr1QmYwzRRgaEA6
Move world state synchronization logic (snapshots, events, entity
mutation routing) into a dedicated WorldStateSync class, reducing
NetworkManager from ~790 to ~420 lines.
Revert plant/building manager globals back to private class statics
(matching master) and use friend declarations for extension access.
Move CreateCharacterClone out of LegoCharacterManager into a new
CharacterCloner class in the multiplayer extension.
- WebSocket relay server (Cloudflare Worker + Durable Object)
- Remote player character cloning with walk/idle/ride animations
- Vehicle support for remote players
- INI config for relay URL
- Extension hook for world transition ROI management
CI / ${{ matrix.name }} (false, -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0, false, false, Visual Studio 17 2022, true, Xbox One, windows-latest, amd64, false, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake, false, devkitpro/devkitarm:latest, false, Ninja, true, Nintendo 3DS, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake, false, devkitpro/devkita64:latest, false, Ninja, Nintendo Switch, true, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0, false, false, Visual Studio 17 2022, true, Xbox One, windows-latest, amd64, false, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake, false, devkitpro/devkitarm:latest, false, Ninja, true, Nintendo 3DS, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake, false, devkitpro/devkita64:latest, false, Ninja, Nintendo Switch, true, ubuntu-latest, true) (push) Waiting to run
CI / ${{ matrix.name }} (false, -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0, false, false, Visual Studio 17 2022, true, Xbox One, windows-latest, amd64, false, true) (push) Has been cancelled
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake, false, devkitpro/devkitarm:latest, false, Ninja, true, Nintendo 3DS, ubuntu-latest, true) (push) Has been cancelled
CI / ${{ matrix.name }} (false, -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake, false, devkitpro/devkita64:latest, false, Ninja, Nintendo Switch, true, ubuntu-latest, true) (push) Has been cancelled
* - Set defaults if ini exists, but empty.
- Create a new dictionary object, not use null object.
* Switch Port
Todo: Fix: Misc crashes when interacting on island.
Todo: Fix: Joystick pointer is slow to move.
Todo: Fix: Touch doesn't behave.
* Fix: base GetPathInfo fixup in the SDL implementation, with check for null SDL_PathInfo.
Fix: Disable imgui shell functions.
Todo: Display imgui debug if enabled.
* Fix: Correction to suite style guidelines
* - Switch build homebrew NRO
- CI/CD to build Switch
* Fix typo in CI
* clang-format fix
* Clang-format against isleapp.cpp
* Use correct docker container for CI/CD
* Remove SDL fixups and use an SDL3 port with fixes.
Fixes crash bug and world issues!
* Fix: use Clang-Format 17 instead of 21
---------
Co-authored-by: SnepOMatic (Rhew) <github@rhew.co.uk>
* add psvita to cmake
* no PIE for vita
* add modules to vpk
* use custom pvr apphint
* select correct renderer for sdl renderer
* patch sdl3 shaders, got something on screen!
* use proper cmake patch for sdl
* add missing module
* remove test window which causes a bug in the vita sdl port to show up
* add gxm renderer (not working with display yet)
* avoid sdl renderer for vita, seems broken
* make gxm renderer work with new d3drm
* fix rendering somewhat, some geometry shows up
* support paletted textures directly to avoid copying the texture twice
* fix Draw2DImage
* make 3d work, broken lights
* clean up a bit
* fix normals matrix
* remove some unneeded changes
* forgot env var
* wrong env dest
* run clang format
* correct texture address mode, use tlsf instead of sceClibMspace
* double buffered uniforms seem to work now
* missed a line
* update GXMRenderer_EnumDevice
* hopefully actually fix uniform buffers
* run clang-format
* remove a change thats not needed
* improve fragment shader performance
* add vita to dist folder
* add base for vita config app
* add config self to vpk
* transform touch events to virtual size
* add livearea graphics
* Update cmake file to include livearea assets
* put manual in the right place
* add sample rco
* add messagebox on vita
* triple buffer textures because fences arent a thing on vita and making draw&cpu sync would be too slow
* make config app not crash on launch
* change defaults
* update gxm renderer with interface changes
* split 2d and 3d shaders completely
* update gxm renderer
* fix transition on gxm
* clang format
* move config cmake
* move CONFIG_vita
* always clear before drawing 2d image
* hopefully fix windows build
* clang-format fix broken includes
* order again
* undo moving qt cmake to its own list
* move uic search path
* use ifdefs for all d3drm backends, cpack to generate vpk
* cmake wrong escape
* small cleanups in gxm renderer
* defer texture delete to avoid overwriting the texture during a frame
* clang-format
* more of the layout for config
* remove top buttons
* use SceAppSettings instead of custom ui
* use select for back to info center on vita, to make screenshots possible again
* remove accidentally left in add_subdirectory
* adjust diskpath to be like other ports
* use vita_create_vpk and not cpack
* gxm: msaa support, fix wrong file path
* gxm: add mipmaps (disabled)
* clang-format
* fix open isle.ini with fopen
* add missing strings
* use iniparser_set not dictionary_set
* add default save path to config
* load config app after initializing ini on vita
* fix config build
* change the default disk & cd path, update the paf library
* update paf library headers
* include orders for clang-format
* clean up
* make shader compiler not required
* move asm language
* warn instead of error when shader source is changed when no compiler is found
---------
Co-authored-by: Li <li@silica.codes>
Co-authored-by: Christian Semmler <mail@csemmler.com>
* initial files
* get building
* proper paths & default to virtual mouse
* Wrap gradle under cmake & build SDL3.aar
run cmake with -DANDROID_NDK_PATH=/path/to/ndk to generate the .aar & run the gradle build
if using Android Studio you will have to run the aar script manually(or do the cmake cmd) then put the normal cmake args inside '-PcmakeArgs="-DCMAKE_BUILD_TYPE=Release ...."' at `Settings > Build, Execution, Deployment > Gradle-Android Compiler > Command-line Options`
Check CMakeLists.txt Android build block for more info
* workflow and format
* dont cmake -> gradle -> cmake
* icons
* prevent first start crash due to missing isle.ini
dont force require gles3 (vulkan & software are options)
* cleanup
* cmake script & ci cleanup
use a cmake script to downoad SDL3 sources for aar building
* script cleanups & gradle stub for android studio
handle the env var setting for the sdl3 aar build script
* signing
needed repository secrets:
- keystore : key.jks in base64
- keystorePassword : Key store password
- keyAlias : Key alias, ex key0
- keyPassword : Key Password
* conditionally run action without keys
* compile SDL once & cross-platformize gradle tasks
* suggestions
* use find_package over manual configuration
* use MxString
---------
Co-authored-by: Anders Jenbo <anders@jenbo.dk>
Co-authored-by: Christian Semmler <mail@csemmler.com>
* ✨ feat: add ios support
* ⚗️ chore: trying some experiments to make ci working
* ⚗️ chore: is it really ci version problem?
* 💚 fix: it really is just a ci version issue
* 🩹 fix: go as low as possible
* 🩹 fix: support ipad
* chore: update README.md
* ✨ feat: got the audio working
* 🔧 feat: add appxmanifest
* 🩹 fix: remove opengl stuff
* ⚗️ feat: add button support
* ⚗️ chore: try to make less modification from upstream
* 🩹 fix: doesnt compile
* ✨ feat: forcibly draw cursor and map right joystick to cursor
* 🩹 fix: remap joystick
* 🎨 fix: formatting
* 🎨 fix: cmakelists formatting
* 🩹 fix: 3ds build
* 👷 feat: add xbox one ci build
* 💚 fix: github hates xbox series naming
* 💚 fix: dont run cpack for xbox one, vs does that for you
* 💚 fix: xbox one need to use vs as generator
* 💚 fix: please
* 💚 fix: it could be msix not bundle
* 💚 fix: try recursive directory search when upload release
* 🔨 feat: support cpack
* 👷 feat: better packaging
* 💚 fix: ignore if mv fails
* 🔧 feat: add mouse sensitivity config
* 🔥 chore: dont need you
* ⚗️ chore: use d3d11
* ✨ feat: hardware acceleration!!
* 🚸 chore: change default cd path so user can easily copy the assets to xbox
* 🧑💻 chore: improve reusability
* 🚨 fix: formatting error
* 🚸 chore: draw cursor by default
* 🎨 chore: cmakelists formatting
* chore: match with upstream
* chore: more matching with upstream
* chore: don't need you
* 🩹 fix: apply changes
* 🔥 fix: we don't need controller map anymore
* 🩹 fix: use isle style include guard
* 🩹 fix: last newline fix
* 👷 chore: use cpack
* 💚 fix: try to fix ci
* 💚 fix: i tried my best...