Commit Graph

34 Commits

Author SHA1 Message Date
foxtacles
647bd28a07
Claude/npc animations local playback (#20)
* WIP: NPC animation local playback

Add NpcAnimCatalog and NpcAnimPlayer for playing NPC interaction
animations directly on player ROIs in multiplayer, bypassing the
singleplayer streaming pipeline.

- NpcAnimCatalog: reads animation entries from LegoAnimationManager
  with eligibility filtering per actor
- NpcAnimPlayer: minimal SI file reader (header + offset table only,
  then single MxSt read per object), extracts animation/audio/phoneme
  data from ISLE.SI composite objects
- Skeletal animation with position rebasing (absolute world coords
  converted to player-relative deltas)
- Audio via LegoCacheSound with proper WaveFormat parsing from SI
  chunks, wall-clock sync via SDL_GetTicks
- Phoneme lip sync with FLC decode, palette update, and proper
  texture restore on cleanup
- Movement lock via Controller::m_npcAnimPlaying flag
- Test trigger: emote 0 plays first eligible NPC animation

Still WIP: debug logging present, network sync not implemented,
needs testing with more animations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Fix NPC animation playback, props, crash safety, and movement lock

- Fix SI file reading: use declared offset count, handle RIFF word-alignment
  for odd-sized MxCh chunks, parse WaveFormat struct directly (not RIFF WAV)
- Fix animation type matching: use presenter name instead of MxOb::Type enum
  (skeletal anim is type Object=0x0B, phoneme is type Video=0x03)
- Fix animation positioning: compute full rigid-body rebase transform
  (savedTransform * inverse(animPose0)) so all motion, rotation, and extra
  actor positions are preserved relative to the player's current pose
- Add extra character support: use CharacterCloner::Clone for root-level
  characters (RHODA, RD, BD, PG), extend AssignROIIndices to match
  non-*-prefixed root-level nodes against extra ROIs
- Fix phoneme: update palette via SetEntries after FLC decode, restore
  original texture by passing saved pointer (not NULL), initialize
  filetype_/volume_ to avoid UBSan errors
- Fix sync: use SDL_GetTicks (wall-clock) instead of Timer()->GetTime()
  (game timer stalls during freezes), defer clock start to first Tick
- Fix crash on camera transition: add NPC anim stop callback in
  Controller::Deactivate and OnWorldDisabled (fires before ROI destruction)
- Block camera toggle and scroll/zoom disable during NPC animation
- Block player movement and camera-relative input during NPC animation
- Add StopNpcAnimation() public API on NetworkManager
- Add EnsureROIMapVisibility in Tick for prop visibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Fix rebase for nested camera nodes, revert test to eligible[0]

Accumulate parent transforms when computing the player's animation-
space world pose at time 0. Fixes position offset for animations with
nested '-' nodes (e.g. -SBA001BU -> -TILT -> BU) where the local
transform alone didn't account for parent TILT offset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Catalog filtering, prop LOD trimming, click anim blocking

- Split NpcAnimCatalog into NPC (location==-1) and cam (location>=0) buckets
- Filter by display actor's character index (not actorId)
- Eligibility: require all 5 main actor bits set (no counterpart for now)
- DisplayActorToCharacterIndex maps display actor -> g_characters index
- Trim trailing digits/underscores from prop LOD names matching original
  game's e_managedInvisibleRoiTrimmed logic (LETR12 -> letr)
- Handle *-prefixed non-actor root siblings as props via CreateAutoROI
- Block click animations during NPC animation playback (both local and
  remote player paths)
- Remove verbose per-entry catalog logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Actor metadata ROI creation, vehicle reuse, AssignROIIndices fix

- Replace scanForCharacters heuristic with LegoAnimActorEntry metadata
  loop (GetNumActors/GetActorType/GetActorName) matching original game
- Player identified by animation name suffix, not tree position
- Handle all actor types: managed actors (2), trimmed props (3),
  exact props (4), scene ROIs (5/6), and scene actors (0/1)
- Vehicle ROI reuse: borrow existing ride vehicle ROI for type 0/1
  actors when CreateAutoROI fails, restore name on Stop
- Fix AssignROIIndices: check extras before claiming root to handle
  tree ordering (BIKESY before SY)
- Use GetRefCount(ROI*) for cleanup instead of name-based Exists()
- Block click animations during NPC anim playback
- Vehicle animation not yet fully working (known issue)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Fix vehicle animation, skip Controller tick during NPC anim

The ride animation and SyncTransformFromNative in Controller::Tick
were overwriting ROI transforms set by NpcAnimPlayer every frame.
Skip the entire ride animation path and non-vehicle character
animation path when m_npcAnimPlaying is true, so only NpcAnimPlayer
controls ROI positioning during NPC animations.

Also add comprehensive ROI map and tree assignment debug logging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Move SI parsing from NpcAnimPlayer into libweaver

Replace ~300 lines of custom RIFF/MxOb/MxCh parsing in NpcAnimPlayer
with libweaver's new HeaderOnly read mode and slot-based ReadObject API.
This reuses ReadChunk's existing logic for the full MxSt->MxOb->MxCh
chain, eliminating code duplication.

Extract HD/CD path resolution into a shared ResolveGamePath utility
(extensions/common/pathutils), replacing the duplicated pattern in
NpcAnimPlayer, SiLoader, and TextureLoader.

Update libweaver to 17c7736 (HeaderOnly + ReadObject support).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Refactor animation playback into Multiplayer::Animation namespace

Split the monolithic NpcAnimPlayer and NpcAnimCatalog into five focused
components under extensions/multiplayer/animation/:

- Catalog: AnimInfo index with category enum, stores all animations
- Loader: SI file I/O, parsing, AnimData cache
- Controller: Play/Tick/Stop orchestrator, ROI creation, rebase matrix
- AudioPlayer: LegoCacheSound timed playback
- PhonemePlayer: FLC decoding, texture swap, lip sync

Also removes ~50 SDL_Log debug calls, renames all NpcAnim* references
to match the new structure, simplifies the camera animation callback
API, and documents AnimUtils divergences from the original game.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* DRY: Extract TrimLODSuffix helper and AnimData::ReleaseTracks

- controller.cpp: Extract repeated digit/underscore trimming loop into
  static TrimLODSuffix() (was duplicated 3 times in CreateExtraROIs)
- loader.cpp: Extract duplicated track cleanup loops into
  AnimData::ReleaseTracks() (was in both destructor and move-assignment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Updates

* Clarify animation system separation with renames and DRY extractions

Rename Controller → ScenePlayer to distinguish multi-actor scene
animations from simple character poses. Rename AnimData → SceneAnimData
to avoid confusion with the character lookup tables. Rename
animdata.h/cpp → charactertables.h/cpp to reflect their actual content
(walk/idle/emote/vehicle tables).

Extract ApplyTree, TrimLODSuffix, and ResolvePropLODName into AnimUtils
to reduce duplication across CharacterAnimator and ScenePlayer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove dta.py accidentally committed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix CleanupProps corrupting global NPC actor state

ReleaseActor looks up g_actorInfo[] by ROI name, which for renamed
clones (e.g. "ma") matches the real global NPC and deletes its actor
entity. Since all props are independent clones (not obtained via
GetActorROI), use ReleaseAutoROI unconditionally — it performs
identical map/ROI cleanup without touching g_actorInfo[].

Also removes the redundant explicit Remove() call since ReleaseAutoROI
already calls RemoveROI() internally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Add animation catalog rework, location proximity, and coordinator

Prerequisite systems for cooperative animation reenactment feature:

- Catalog: expanded CatalogEntry with performerMask, spectatorMask,
  location index. Exact character matching (replaces engine's lossy
  2-char prefix). New CanTrigger() checks collective player eligibility
  (spectator + all performers, mutually exclusive roles).

- LocationProximity: 2D XZ distance to nearest g_locations entry,
  integrated into Tickle with OnNearestLocationChanged callback.
  Remote player locations derived from ROI positions.

- Coordinator: state machine (idle/interested/countdown/playing/completed),
  ComputeEligibility for frontend consumption (pre-filtered to local
  player's participable animations). Networking hooks are stubs.

- NetworkManager: location proximity + coordinator integration, atomic
  request pattern for anim interest/cancel, state resets on all
  transition paths (world disable, disconnect, reconnect, stop).

- Bridge: OnNearestLocationChanged callback (Emscripten + Native),
  mp_set_anim_interest / mp_cancel_anim_interest WASM exports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Add push-based animation state bridge and slot fill computation

Add OnAnimationsAvailable callback that pushes full animation eligibility
state (location, coordinator state, per-animation slot fill status) to
the frontend whenever relevant state changes. Uses a dirty flag system
with 250ms cooldown (bypassed for interest changes) to batch updates.

- Add CanTriggerDetailed to Catalog (refactor CanTrigger as wrapper)
- Enrich EligibilityInfo with SlotInfo vector and CatalogEntry pointer
- Add Coordinator::OnLocationChanged for auto-clearing stale interest
- Add dirty flag triggers at all 7 state change points in NetworkManager
- Build JSON payload with unified slots (performers + spectator)
- Remove OnNearestLocationChanged (superseded by push-based approach)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Ghastly

* WIP

* Fix animation session sync, camera-cancel, and state management bugs

- Add m_cancelPending to coordinator to prevent stale session re-enrollment
- Allow ClearInterest during countdown/playing for camera-cancel support
- Camera toggle now cancels animation in any active state instead of blocking
- Safety net: cancel animation when camera is disabled by any source
- Push idle JSON when camera unavailable so frontend clears countdown UI
- HandleCancel includes playing sessions and erases them (explicit cancel stops all)
- HandleAnimCancel/HandleAnimUpdate detect playing→idle to stop local scenes
- SendAnimUpdateToPlayer for targeted session sync to newly joined players
- HandleHostAssign: skip ResetAnimationState on initial assignment to avoid race
- IsPeerNearby helper for shared proximity checks
- HandleAnimInterest: evict far-away participants when session is full
- PushAnimationState: suppress session display when no participant is nearby
- World filter in UpdateRemotePlayers and PushAnimationState
- Set m_animStateDirty on camera change and remote player world change
- Use anyInIsle instead of anyNearby for continuous proximity-based push

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Clean up animation code: extract DRY helpers, remove debug logging

- Extract BuildAnimUpdateMsg() and ExtractSlotPeerIds() to deduplicate
  message-building logic in BroadcastAnimUpdate/SendAnimUpdateToPlayer
- Replace manual tree iteration in controller.cpp with AnimUtils::ApplyTree
- Remove all [Anim]/[SessionHost] SDL_Log debug calls and unused includes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: ScenePlayer multi-participant support and cam_anim playback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* WIP: Vehicle ROI support, alias-based ROI mapping, audio fix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Refactor animation infrastructure: remove dead code, DRY, tighten data

Remove all debug logging (~20 SDL_Log calls), dead fields (m_savedVehicleName,
m_debugFirstTickLogged, boundingRadius, centerPoint), dead methods
(RestoreVehicleROI, HasActiveSounds), and unused parameters (Tick's deltaTime).

Tighten data structures: replace raw m_propROIs array with vector, derive
isSpectator from charIndex via IsSpectator() method (SessionSlot,
ParticipantROI), group action transform fields into sub-struct, replace
vehicle category magic numbers with VehicleCategory enum.

Extract DRY helpers: addAlias/createProp lambdas in SetupROIs,
StopScenePlayback() in NetworkManager (5 call sites), combine dual slot
iteration into single loop in HandleAnimStartLocally. Simplify Play()
signature by removing redundant p_localROI/p_vehicleROI params.

Fix bug: HandleAnimCancel now unlocks remote player ROIs when stopping
during playback (was skipping unlock, leaving remotes permanently locked).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Async SI asset preloading during animation countdown

Preload animation data from isle.si on a background thread when the
countdown starts (4s window), so ScenePlayer::Play() finds the data
already cached and avoids a 500ms-1s main-thread stall.

Adds Loader::PreloadAsync() with a one-shot MxThread subclass that
opens its own si::File/Interleaf, parses the object, and inserts into
the cache under MxCriticalSection. EnsureCached() joins any in-progress
preload before falling back to synchronous load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Refactor animation system: fix dangling pointer, DRY extractions, correctness

- Fix dangling .c_str() in ScenePlayer::SetupROIs by using std::deque
  for aliasNames (vector reallocation invalidated stored pointers)
- Push idle JSON fallback when userActor is null in PushAnimationState
  instead of silently returning with stale frontend state
- Extract GetPerformerIndices() to eliminate 3 duplicate bit-iteration
  loops across coordinator.cpp and sessionhost.cpp
- Promote CheckSpectatorMask to public Catalog method, replacing
  inlined duplicate in sessionhost.cpp
- Extract Loader::OpenSIHeaderOnly() to consolidate duplicated SI file
  open/parse between OpenSI() and PreloadThread::Run()
- Extract IDLE_ANIM_STATE_JSON constant to avoid string duplication
- Clarify proximity radius distinction with comment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Observer mode: uninvolved players see animations play out locally

Non-participant players in the same world now see scene animations
(cam_anim, npc_anim) play out on the performing players' ROIs as an
ambient background scene. The observer's camera, movement, and vehicle
are completely unaffected.

Key changes:
- HandleAnimStartLocally always runs (not just for session participants)
- ScenePlayer gains observer mode: skips camera control, spectator
  hiding, and vehicle hiding
- Preload during countdown for all clients, not just participants
- Fix 1st person camera: skip display ROI check for observers (the
  display clone is destroyed in 1st person mode)
- Track m_playingAnimIndex for observer early-stop detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:40:15 +01:00
foxtacles
13f6239808
Claude/fix platform compilation errors hol yw (#19)
* Add native platform multiplayer support via libwebsockets

Add a general-purpose WebSocket transport using libwebsockets (v4.5-stable)
for all non-Emscripten platforms, enabling multiplayer on desktop, mobile,
and any other platform that libwebsockets supports.

New files:
- LwsTransport: implements NetworkTransport using lws client API with
  non-blocking event loop integration via lws_service(ctx, 0) in Receive()
- NativeCallbacks: implements PlatformCallbacks with SDL_Log output

Build integration:
- libwebsockets fetched conditionally only when ISLE_EXTENSIONS=ON and
  not building for Emscripten, with SSL disabled (ws:// only)
- Follows existing 3rdparty dependency patterns (FetchContent/find_package)

https://claude.ai/code/session_01BojPvEEhREJ4xdihJfin3m

* Fix Connect() reconnection guard to check context instead of connected flag

The previous check (m_connected) would fail to clean up a stale lws context
when reconnecting after a connection error, since the error handler already
sets m_connected=false. Check m_context instead, matching the emscripten
version's behavior of cleaning up any existing connection state.

https://claude.ai/code/session_01BojPvEEhREJ4xdihJfin3m

* Fix cross-platform compilation errors for libwebsockets multiplayer

- Add ISLE_USE_WEBSOCKETS cmake option to conditionally build lws transport
  (disabled on Switch, 3DS, Vita, Emscripten which lack standard networking)
- Disable lws internal -Werror (DISABLE_WERROR) to fix GCC/Clang builds
- Override MSVC /WX with /WX- on the websockets target to fix MSVC builds
- Skip precompiled headers for native transport files to avoid miniwin/windows.h
  type conflicts on MinGW
- Guard native transport includes/instantiation with ISLE_USE_WEBSOCKETS define
  so platforms without lws gracefully skip multiplayer networking

https://claude.ai/code/session_01UdLx6KWCXocF6guCQDq8C8

* Fix native WebSocket transport compilation errors and disconnect detection

- Fix undefined variable: relayUrl → s_relayUrl in multiplayer.cpp
- Fix interface mismatch: LwsTransport now implements WasDisconnected()
  matching the base class pure virtual
- Add WasRejected() to NetworkTransport interface for parity between
  emscripten and native backends (rejected = closed before ever connected)
- Fix post-connection disconnect detection: m_disconnected is now set
  unconditionally on any close/error, not only for pre-connection failures
- Guard shared init code with #if defined(__EMSCRIPTEN__) || defined(ISLE_USE_WEBSOCKETS)
  to avoid creating a NetworkManager on platforms without a transport
- Collapse identical CONNECTION_ERROR/CLOSED handlers into fallthrough

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Move exit code constants to networktransport.h and eliminate magic numbers

Move EXIT_ROOM_FULL/EXIT_CONNECTION_LOST from NetworkManager (where they
were unused) to the Multiplayer namespace in networktransport.h so both
backends can reference them. Pass them into the emscripten inline JS as
parameters instead of hardcoding 10/11.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Implement missing PlatformCallbacks pure virtuals in NativeCallbacks

NativeCallbacks only overrode OnPlayerCountChanged, leaving three pure
virtuals unimplemented (OnThirdPersonChanged, OnNameBubblesChanged,
OnAllowCustomizeChanged), making it abstract and un-instantiable on MSVC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove WebSocket subprotocol request to match browser behavior

The relay server doesn't negotiate subprotocols, so lws requesting
Sec-WebSocket-Protocol: lws-multiplayer caused the handshake to stall
and freeze the game. The browser WebSocket API doesn't send this header.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add debug logging to native WebSocket transport

Temporary diagnostic logs to find where the game freezes on Windows:
- Before/after lws_create_context, lws_client_connect_via_info, lws_service
- In all lws callback events including unhandled reason codes
- Suppress verbose lws internal logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Move lws_service to background thread to prevent game loop blocking

lws_service(ctx, 0) blocks the main thread on Windows despite the 0ms
timeout, freezing the game on a black screen. Move all libwebsockets
event processing to a dedicated LwsServiceThread using MxThread, with
MxCriticalSection-protected queues for thread-safe send/receive and
std::atomic flags for connection state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix service thread lifecycle for reconnect support

MxThread is single-use: m_running is set TRUE in the constructor and
never reset after Terminate(). Allocate LwsServiceThread on the heap
so each connection gets a fresh instance. Also handle Start() failure
to avoid deadlock in Terminate() if SDL thread creation fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix right-click camera turning on Desktop by tracking button state internally

On Windows, SDL3 uses different mouse device IDs for button events (normal
input) vs motion events (raw input during relative mouse mode). This causes
motion.state to not reflect the right button being held, since the button
state was recorded under a different device ID. Track right button state
internally via SDL_EVENT_MOUSE_BUTTON_DOWN/UP instead of relying on
motion.state, which works reliably across all platforms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Restore cursor position after right-click camera drag on Desktop

On Desktop, SDL_SetWindowRelativeMouseMode accumulates absolute position
internally, so the cursor appears at a different location when released.
Save the cursor position before entering relative mode and warp it back
on release, matching the Emscripten pointer lock behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix default

* Add debug logging for peer ID assignment

Logs the assigned peer ID when MSG_ASSIGN_ID is received to help
diagnose whether ws:// connections are reaching the Durable Object.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add missing SDL_log.h include for SDL_Log

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add TLS/WSS support to native WebSocket transport via mbedTLS

Cloudflare custom domains require wss:// for proper Worker routing.
Fetch mbedTLS v3.6.3 via FetchContent and enable LWS_WITH_MBEDTLS so
the Desktop client can connect over TLS. The transport now detects
wss:// URLs and sets the appropriate SSL context and connection flags.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Disable iniparser test suite during FetchContent build

iniparser's main branch added tests that require Ruby. Set
BUILD_TESTING OFF in the block to skip test configuration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Revert "Disable iniparser test suite during FetchContent build"

This reverts commit abdd9b37bced18dd54486c1cfb23a53a2d1b3142.

* Fix mbedTLS tarball MD5 hash

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Bump mbedTLS from 3.6.3 to 3.6.5

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Use official mbedTLS release archive instead of GitHub auto-generated tarball

The auto-generated tarball from /archive/refs/tags/ doesn't include the
mbedtls_framework submodule, causing a build failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix mbedTLS download URL to use correct release tag format

Release tags use 'mbedtls-3.6.5' not 'v3.6.5'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix mbedTLS include dirs by setting cache vars inside block() scope

mbedtls_SOURCE_DIR and mbedtls_BINARY_DIR are only available inside
the block() where FetchContent_MakeAvailable runs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Disable lws export targets to fix mbedTLS export set conflict

lws install(EXPORT) fails because FetchContent'd mbedTLS targets
aren't in an export set. LWS_WITH_EXPORT_LWSTARGETS OFF disables
this since we don't need install rules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove EXCLUDE_FROM_ALL from mbedTLS FetchContent

mbedcrypto depends on internal sub-libraries (everest, p256m) that
don't get built when EXCLUDE_FROM_ALL is set, causing link failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add explicit build dependencies from websockets to mbedTLS internals

The Visual Studio generator doesn't infer the build order for
mbedTLS's internal sub-libraries (everest, p256m) when they are
transitive dependencies through mbedcrypto.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Force mbedTLS to build as static libraries

Without explicit BUILD_SHARED_LIBS OFF, mbedTLS (and its internal
sub-libraries like everest) build as DLLs instead of static libs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove unnecessary add_dependencies for mbedTLS internals

The real issue was BUILD_SHARED_LIBS, not build ordering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Scope BUILD_SHARED_LIBS to mbedTLS block instead of global cache

CACHE BOOL FORCE writes to the global cache, leaking beyond the
block() and preventing lego1.dll from being built as a shared lib.
A regular variable is properly scoped by block().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Pre-set mbedTLS 3.x API check results for lws configure

lws uses check_function_exists for mbedtls_md_setup but the check
fails since mbedTLS targets aren't built at configure time. Without
the result, lws falls back to the removed 2.x mbedtls_md_init_ctx.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add debug logging to multiplayer initialization

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Enable verbose lws logging to diagnose TLS handshake failure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix TLS: use ALLOW_INSECURE instead of SKIP_SERVER_CERT_HOSTNAME_CHECK

SKIP_SERVER_CERT_HOSTNAME_CHECK also skips setting SNI (Server Name
Indication) via mbedtls_ssl_set_hostname. Without SNI, Cloudflare
can't route the connection to the Worker. ALLOW_INSECURE disables
cert verification while still setting the SNI hostname.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Suppress CMake deprecation error for mbedTLS cmake_minimum_required

Newer CMake versions (3.27+) error on old cmake_minimum_required
values. Setting CMAKE_POLICY_VERSION_MINIMUM to 3.10 suppresses
this for the mbedTLS subdirectory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix left-click and cursor warp regression from right-click camera fix

The mouse button handler ran relative-mouse-mode and cursor-warp logic
for ALL button events, not just right-button events. Left clicks would
enter the else branch, disabling relative mode and warping the cursor
to a stale/zero position. Scope the entire block to right-button events
only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Move CMAKE_POLICY_VERSION_MINIMUM outside block() scope

The variable may not propagate from block() scope into
FetchContent's add_subdirectory call on some CMake versions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix mbedTLS cmake_minimum_required deprecation error in CI

CI uses -Werror=dev which makes the CMake deprecation warning for
cmake_minimum_required(VERSION < 3.10) a fatal error. Patch mbedTLS's
CMakeLists.txt via PATCH_COMMAND to use VERSION 3.10 instead.

CMAKE_POLICY_VERSION_MINIMUM only works on CMake 4.x, not 3.28.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Rename ISLE_USE_WEBSOCKETS to ISLE_HAS_LWS and clean up multiplayer code

Rename the CMake option and compile definition to better reflect the
presence of the libwebsockets library. Remove debug SDL_Log calls and
unused includes, extract magic numbers into named constants, add null
guard for lws_cancel_service, and use inline constexpr for namespace
constants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Rename ISLE_HAS_LWS to ISLE_USE_LWS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix uninitialized variable UB in WorldStateSync::HandleEntityMutation

Split GetInfoArray() output parameter from FindEntityIndex() call to
avoid undefined behavior from unspecified function argument evaluation
order. MSVC evaluates right-to-left, reading `count` before
GetInfoArray() initializes it, triggering _RTC_UninitUse and preventing
entity mutation sync in multiplayer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-14 23:38:24 +01:00
Christian Semmler
33223d1169
miniaudio: fix submodule commit 2026-01-30 20:01:21 -08:00
Christian Semmler
bae8c292f5
Update miniaudio to 0.11.24 (#774) 2026-01-30 19:42:06 -08:00
Anonymous Maarten
4a1fd5d2f2
Remove libweaver git submodule (#737)
The CMake build system is in charge of downloading libweaver
2025-11-24 20:50:16 +00:00
Anonymous Maarten
a90c7cb985
libweaver: support system library and use latest wip read flags (#735)
* Use system libweaver when DOWNLOAD_DEPENDENCIES is disabled

* Update to latest libweaver master
2025-11-23 00:26:54 +00:00
Anonymous Maarten
85ff14e997
Remove debug window (#736)
* Remove debug window

* LEGO1: remove a few exports

* LEGO1: Remove a few `friend class DebugViewer` declarations
2025-11-21 14:20:37 +00:00
Anonymous Maarten
3f974f7317
Fix build with disabled precompiled headers (#724) 2025-10-24 20:56:11 +00:00
Christian Semmler
d10ac7e77c
Add hdmusic.si asset pack, extend SiLoader with Replace directive (#671)
* Replace SI objects

* Changes

* Fix

* Remove obsolete file

* Add delete handler

* Updates

* Update assets

* Configure git LFS

* Add HD music

* Move files to LFS

* chmod files

* fix gitattributes

* Fixes

* Fixes

* Add other HD music

* Fix file perms

* Add comment

* Minor update

* Refactor

* Fix

* Add LFS flag

* Add check for file replace

* Exclude assets from CPack

* Attempt fix

* Update libweaver

* Fix MxDSBuffer leak

* Add .lfsconfig

* Set LFS URL

* Fix LFS CI

* Fix

* Space
2025-08-16 21:21:39 +02:00
Christian Semmler
841db2a577
Add SI Loader extension (#664)
* SiLoader draft

* Fixes

* Fixes

* Fix asset build on Windows

* Remove whitespace

* Package assets in CI

* Disable clang-tidy

* Fix NCC

* Try this

* Disable extensions on Xbox for now

* Update bitmap

* Update 3rdparty/CMakeLists.txt

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* Add DEPFILE for asset command

* Use assets.d instead of .d

---------

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>
2025-08-11 00:59:55 +00:00
Christian Semmler
54b56c6b13
Add MA_NO_RUNTIME_LINKING (#354) 2025-06-20 23:54:49 +00:00
Anonymous Maarten
9d06cd9e53
Show imgui window when starting app with --debug (#138)
* Show imgui window when starting app with --debug

* g_closed test in SDL_AppIterate is still needed

* Allow disabling isleapp debugging by configuring with -DISLE_DEBUG=OFF

* clang-format
2025-05-20 23:36:51 +02:00
Anonymous Maarten
537cde485a
Remove d3drm-wine (#75)
* remove d3drm-wine

* Update miniwin/miniwin/src/miniwin_ddraw.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

* Run clang-format

* Update miniwin/miniwin/src/miniwin.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

* Update miniwin/miniwin/src/miniwin_ddraw.cpp

Co-authored-by: Anders Jenbo <anders@jenbo.dk>

---------

Co-authored-by: Anders Jenbo <anders@jenbo.dk>
2025-05-13 19:18:20 +00:00
Anders Jenbo
e92805e863
Let CMake handle fetching of libsmacker and miniaudio when DOWNLOAD_DEPENDENCIES is enabled (#67) 2025-05-09 23:34:52 +02:00
Anonymous Maarten
196259c6c9
Parse cli arguments + log with SDL_Log (#30)
* cmake: copy DLL dependencies to output path

This also copies SDL3.dll from an external path when using system
dependencies.

* Only include <SDL3/SDL.h>

* isle: parse cli argument (--ini for custom ini path)

* Use SDL_CreateWIndowWithProperties to create SDL window

Less branching => Clearer code

* Log mxdirectx failure using SDL_Log + E_NOINTERFACE

* Fix d3drm32.def for msvc

* Define D3DRM_WINE when using d3drm from wine

* Ignore failed assertions from d3drm unimplemented functions

* inparser will/should create libiniparser.lib for static libraries and iniparser.lib for a shared library
2024-06-26 11:24:40 -07:00
Anonymous Maarten
659a54b221
Add support for building x64 executables (#29)
* d3drm: store LPVOID data instead of DWORD

* m_extraCharacterId is an integer, not a pointer

* cmake: look for iniparser using config file first, then try our custom module file

Our custom module file is still useful.
My linux distro does not package the cmake files.

* x86's stdcall becomes MS's x64 calling canvention

* Fix 64-bit mxdsbuffer pointer arithmetic

* Casting from void* to a smaller-sized integer needs an intermediate equally-sized integer

* Don't cast address to scalar (this is fishy)

* Add mingw64 build to the ci matrix

* Ignore -Wdiscarded-qualifiers warning with const vtables

* Ignore different 'const' qualifiers with MSVC

* Create d3dxof import library for MSVC

* DESCRIPTION in .def file(s) is deprecated

* Assume mmx is supported on x64, require a test for x86 and disabled on other archs

* 32- and 64-bit LEGO1.dll export different symbol names

* Introduce d3drm_guid containing the guids of d3drm

* Disable __wine_dbg_cdecl

* Include d3drm directory with EXCLUDE_FROM_ALL

* lego1 leaks d3drm headers

* Add dxfile.h

* Add 64-bit MSVC to the build matrix

* cmake: using ISLE_USE_DX5 means going all-in

* Load d3dxof.dll dynamically

* cmake: don't emit a warning about bitness anymore
2024-06-25 18:47:43 -07:00
Anonymous Maarten
ec19d5edb0 Fix mingw build + copy d3drm from wine (#25)
* Fix engineConfig declaration crossing jump

This fixes the following error:
```
/src/isle-portable/LEGO1/omni/src/audio/mxsoundmanager.cpp: In member function 'virtual MxResult MxSoundManager::Create(MxU32, MxBool)':
/src/isle-portable/LEGO1/omni/src/audio/mxsoundmanager.cpp:119:1: error: jump to label 'done'
  119 | done:
      | ^~~~
/src/isle-portable/LEGO1/omni/src/audio/mxsoundmanager.cpp:78:22: note:   from here
   78 |                 goto done;
      |                      ^~~~
/src/isle-portable/LEGO1/omni/src/audio/mxsoundmanager.cpp:84:26: note:   crosses initialization of 'ma_engine_config engineConfig'
   84 |         ma_engine_config engineConfig = ma_engine_config_init();
      |                          ^~~~~~~~~~~~
```

* Fix 'invalid conversion from 'SDL_FunctionPointer' {aka 'void (*)()'} to 'void*'

* /SAFESEH:NO is a VC thing

* SDL3 is still instable

* Cannot forward declare and use enum

* Remove MusicManager from public LEGO1.DLL interface

* Copy d3d from wine git 6c5d17af07a318d754c0c21023b2d162a0d3725d

* Build d3drm-wine with 32-bit mingw

* cmake: move 3rd party targets to cmake script in 3rdparty directory

* cmake: bump minimum required CMake version to 3.25 to allow adding a subproject with SYSTEM automatically applied

An alternative would be to use SYSTEM in target_include_directories in the 3rd party cmake script.

* Add a minimal Findiniparser.cmake (not all distributions carry the upstream iniparser-config.cmake files)

* Add wine's d3drm headers

* cmake: merge ISLE_USE_DX5_LIBS into ISLE_USE_DX5

* cmake: Build all shared libraries in the binary output directory (to avoid PATH issues)

* ci: enable msys2 mingw32 build

* Disable clang-tidy on d3drm wine

* Thread functions must have SDLCALL call convention

* cmake: disable clang-tidy for miniaudio and libsmacker as well

* Hopefully fix c++ format and skip ncc naming violation

* clang-format violations keep up popping out of nowhere

* No need for lego/legoomni/include

* ncc: define SDLCALL as empty instead
2024-06-25 20:02:58 +02:00
Christian Semmler
806afaa210 Replace DirectSound with miniaudio (#21)
* Add miniaudio

* WIP

* static const

* Fix missing looping

* Fix volume

* Implement 3D sound, WIP

* Remove unused WinMM code

* Update README.md

* Fixes

* Fix naming

* Fix naming

* disable ma threading

* Invert Z axis for OpenGL system

* Update comment

* Set rolloff

* Fix minimize/maximize suspension

* Rename function

* SDL3: changed macro name
2024-06-25 20:02:58 +02:00
Christian Semmler
dc61d91e99 Remove SmartHeap 2024-06-25 19:48:57 +02:00
Christian Semmler
a548770f7e Add libsmacker to replace smack.lib 2024-06-25 19:48:56 +02:00
Nathan M Gilbert
ff04b0ba5a
Implement FLIC (#481)
* Implement FLIC

* Refactor/style

* Remove library_flic.h

* Exclude flic.cpp from naming

* Temporary workaround

* Fix type

* Fix bugs in FLC decoding, and cleanup

* Fix braces

* Match ClampLine

* Fix struct type

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
2024-02-29 18:00:57 +01:00
Christian Semmler
b4bc0e51c9
Make all functions public symbols in FLIC library (#472) 2024-01-20 20:23:23 -05:00
Christian Semmler
701c700d69
Add library symbols for flic and smack (#461) 2024-01-19 23:11:51 +01:00
Christian Semmler
cecaced797
Implement MxFlcPresenter::LoadFrame, add flic library (#455)
* WIP

* Match

* Fix flic.lib

* Add source assembly

* Rename variable
2024-01-19 15:01:57 +01:00
Christian Semmler
c47206617d
Reorganize sources and files (#414)
* Reorganize sources

* Refactor

* Remove relative paths

* Renames

* Fix gitignore

* Remove stuff

* Try fixing format script

* Fix format

* Fix format

* Fix naming script

* Test format

* Fix format
2024-01-08 10:58:49 +01:00
Anonymous Maarten
fbe7f8bbb0
Fix all mingw errors & warnings (#411)
* Use COMPAT_MODE macro to fix errors with mingw gcc 12.2

* MxOmni::m_timerRunning is a MxBool

* MxDirect3D::m_unk0x88c is a MxBool

* MxBackgroundAudioManager::m_unk0x13c is a MxS32

* Fix warning: deleting 'void*' is undefined [-Wdelete-incomplete]

* Fix inline function 'void TglImpl::RendererImpl::Destroy()' used but never defined

* Fix warning: inline function 'MxStreamerSubClass1::MxStreamerSubClass1(undefined4)' used but never defined

* Use `FALSE` for m_timerRunning

* Format

* Format

* Remove comment

* Limit scope for variables in compat mode

* clang-format

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
2024-01-07 18:30:45 +01:00
Anonymous Maarten
dc3500f631
Fixes for building isle with mingw on Linux (#410)
* Add LEGO1.DLL resources

* Rename smack files to lowercase

This fixes casing issues with mingw on Linux
Also use double quotes for #error

* cmake: dxguid must come after dinput

* cmake: create LEGO1.DLL instead of libLEGO1.DLL, when using mingw

* act3actor.h  was not including mxcore.h, and using incorrect override

* g_mcoreCount seem to be signed integers

* LegoCameraController: return references to static data in stub functions

* Include string.h, stdlib.h and stdio.h for use of libc functions

* Override MxAtomId::operator!=

* Fix use of STL's std::map + std::vector

* Fix template functions for mingw

* iterator object is used after the for loop

* IDirectDrawSurface::BltFast's first 2 arguments are x/y coordinates, not pointers

* Add stub ViewLODListManager::Lookup

* Fixes

* Format

* Remove unnecessary COMPAT_CONST use

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
2024-01-06 18:56:15 +01:00
Christian Semmler
db60467ba3
Bootstrap MxSmack (#343)
* Bootstrap MxSmack

* Add comment about incorrect structure

* Fix naming

* Fix name

* Add a comment about SDK

* Add names from Smacker SDK

* Use SMACK.LIB and interface

* Use RAD.H defined types

* Use different commets

* Fix member offset

* Update mxsmack.cpp
2023-12-21 02:07:48 +01:00
Joshua Peisach
f7dcdf9894
MxFlcPresenter vtable70, m_unk64 (#304)
* MxFlcPresenter: vtable70

* begin work on MxFlcPresenter's m_unk64

* Add another function that makes use of the FLIC header

* Remove space

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
2023-11-29 13:35:32 +01:00
Ramen2X
153f4a872e
implement/match several mxsmkpresenter functions (#251)
* implement/match several mxsmkpresenter functions

* formatting

* formatting (sequel)

* Match remaining functions

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
2023-10-27 19:00:20 +02:00
Ramen2X
74329d681b
implement/match CalcLocalTransform (#241)
* implement/match CalcLocalTransform

* fix odd build error

* address feedback

move vec.h to thirdparty folder
update vec.h
move all realtime code to realtime folder
move calclocaltransform out of legoutil and into realtime
cast shift to MxS32
add additional unroll hack to CalcLocalTransform to prevent msvc entropy
2023-10-24 14:27:24 +02:00
itsmattkc
b59d8ef5cf include directx 5 sdk
This is almost certainly abandonware, fairly small (<1MB), and is going to save us a lot of dev environment headaches
2023-08-06 12:47:16 -07:00
Mark Langen
19dcfe1164
Fix SmartHeap files (#90) 2023-07-16 09:27:30 -07:00
MattKC
2ffe227d82
Add SmartHeap (#83)
* add smartheap

* cmake: bump even further

* this seemed to be necessary but now it isn't? ok

* cmake: force include smrtheap.hpp

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* cmake: force include smrtheap.hpp 2

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* remove compiler defs - unnecessary if force-including anyway

* cmake: use interface for cleaner code

---------

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>
2023-07-15 23:18:21 -07:00