
CartPort
Teleport any cart or sled (including bugged/floating ones) to a spot in front of your camera. Works in single-player, co-op, and dedicated servers.CartPort
BepInEx 6 IL2CPP plugin for ASKA that lists all loaded carts and sleds and teleports the selected one to a spot in front of your camera — including carts that have bugged out (e.g. floating in the sky over the ocean) where normal Fusion state authority won't let you move them.
Works in single-player, player-hosted co-op, and dedicated-server co-op (Fusion Shared mode).
Install
- Install BepInEx 6 IL2CPP into your ASKA install, launch the game once so
BepInEx\interop\contains a populatedAssembly-CSharp.dll(tens of MB, not 0 bytes). - Drop
CartPort.dllintoASKA\BepInEx\plugins\. - For dedicated-server co-op, drop the same DLL into
ASKA Dedicated Server\BepInEx\plugins\. - Launch the game once to generate the config at
BepInEx\config\com.cartport.aska.cfg.
Usage
- F9 — toggle cart/sled list (rebindable in config).
- Summon here — teleport the selected cart/sled to ~4m in front of the camera.
- Force Mode (toolbar toggle) — persistently re-applies the teleport every frame for ~10s. Use for orphaned carts where Fusion sync keeps snapping the cart back.
- Esc — close menu.
The list shows [Auth] / [No Auth] per cart based on local Fusion state authority, and [Forcing...] while Force Mode is active on that cart.
How it works
The interesting problem is Fusion networking in Shared mode: each NetworkObject (cart) has its own state-authority holder, and that holder is not necessarily the dedicated server process — in Shared mode a peer (often the Shared Master Client) holds authority. A naïve SendReliableDataToServer call routes to the Shared Master Client, which may not be the peer Fusion elected for this specific cart.
Summon path (in order)
- Local-authority shortcut — if
netObj.HasStateAuthorityis already true on this peer, apply the teleport directly (no relay). - Local peer is server/Shared-master relay — apply via
ApplySummonOnAuthorityimmediately. - Targeted authority relay — query
netObj.StateAuthorityfor the actualPlayerRefholding authority, andSendReliableDataToPlayer(stateAuthorityPlayer, payload)directly to that peer. This is the fix that retrieves "orphaned" carts. - Server/host relay fallback — if targeted send fails, fall back to
SendReliableDataToServer+ local prediction.
The receiving peer parses the CPRT payload (4-byte magic + NetworkId + pos + rot = 37 bytes), looks up the NetworkObject, and calls CartSummon.ApplySummonOnAuthorityImmediate. A dedup set prevents double-apply when multiple reliable hooks fire for the same frame.
Inbound reception (multiple hooks, best-effort)
Different game builds deliver Fusion ReliableData through different paths, so CartPort hooks several:
NetworkRunner.Fusion_Simulation_ICallbacks_OnReliableData(Harmony postfix — OFF by default, IL2CPP+Harmony+Fusion can hard-crash on some builds).Simulation.Fusion_Sockets_INetPeerGroupCallbacks_OnReliableData(Harmony postfix on dedicated).- Assembly-CSharp game
OnReliableDataReceivedoverloads (Harmony postfix — only whenPatchAssemblyCSharpReliableCallbacks=true). INetworkRunnerCallbacksregistered viaNetworkRunner.AddCallbacks(injected or subclass path, works even when Harmony hooks don't).
Bugged-cart recovery (CartPortServerSummonQueue + CartPortPersistentSummonOverride)
When running on a host that doesn't currently hold state authority for a cart:
RequestStateAuthority()(+AllowStateAuthorityOverride = true) is called and retried every N frames.- If authority arrives before
ServerSummonAuthorityWaitFrames(~10s), the summon applies through the normal path. - Otherwise, a Unity-physics fallback (
BruteForceApplyTransform) writes both the Fusion pose and raw Transform + wakes rigidbodies. - Because Fusion sync from the real authority holder keeps overwriting the position,
CartPortPersistentSummonOverridere-applies the transform every frame forForceSummonPersistDurationFrames(600 ≈ 10s @ 60fps) until the cart is within ~3m of the target (arrival), then auto-cancels.
Other components
CartRegistry— findsCartStructure+ anyStructurewhose IL2CPP type name containsSled.CartSummon— raycast-to-ground placement, authority-aware move application.CartPortGameplayInputSuspend— disables Unity Input SystemPlayer/Look/Movemaps while the menu is open so the mouse doesn't rotate the camera.CartPortInboundFusionCallbacks(Injected|Subclass)— IL2CPP-registeredINetworkRunnerCallbackswrapper. Inject path is tried first; subclass path used when ClassInjector reports the interface is exposed as an IL2CPP class.
Build
dotnet restore
dotnet build -c Release
The post-build step auto-copies CartPort.dll to ASKA\BepInEx\plugins\ and ASKA Dedicated Server\BepInEx\plugins\ if the paths resolve. Close the game and server process first to avoid file locks.
The project finds game assemblies in this order:
CartPort\GamePaths.propsnext toCartPort.csproj(copy fromGamePaths.props.examplefor manual override).- Environment variable
ASKA_BEPINEXpointing to theBepInExfolder containinginteropandunity-libs:setx ASKA_BEPINEX "D:\SteamLibrary\steamapps\common\ASKA\BepInEx" - Relative paths when the repo sits under
ASKA\BepInEx\CartPort\. - Steam auto-discovery via
tools\Discover-AskaBepInEx.ps1(readslibraryfolders.vdf+appmanifest_1898300.acf). Disable with MSBuild propertyCartPortSkipSteamDiscovery=true.
After major ASKA updates, delete BepInEx\interop and launch the game once so interop regenerates before rebuilding.
Config reference (com.cartport.aska.cfg)
Key settings (most defaults are fine):
General.ToggleMenuKey— menu toggle key (default F9).General.SuspendGameplayInputWhileMenuOpen— disable Player/Look/Move while menu open.Summon.ForwardDistance— horizontal offset in front of camera (default 4m).Summon.GroundRaycastStartHeight— raycast start height (default 120m).Summon.SummonVerticalOffset— extra lift off ground hit (default 0.35m).Summon.DeferSummonApply— defer one frame to dodge villager-equipment cleanup races.Network.ServerAuthoritativeSummon— relay summons to the authority holder (recommended for multiplayer).Network.RequestFusionStateAuthority/SummonWithoutAuthorityFallback— authority request + fallback behavior.Network.ForceSummonPersistDurationFrames— Force Mode / server-queue fallback persistence (default 600).Network.ForceSummonServerQueueFallbackPersist— keep re-applying after server queue authority-wait timeout.Network.EnableHarmonyFusionReliablePatches— NetworkRunner reliable-data postfix. OFF by default (can hard-crash IL2CPP on some builds — enable only after verifying the game starts cleanly).Network.EnableHarmonySimulationSocketPatch— Simulation socket postfix for dedicated. OFF by default; enable NetworkRunner hook first.Network.PatchAssemblyCSharpReliableCallbacks— Harmony-patch game-side Fusion callbacks. Sometimes required on dedicated; set false if startup crashes.Network.RegisterFusionInboundRunnerCallbacks— registerINetworkRunnerCallbacksviaAddCallbacks.Debug.VerboseLogging— extra BepInEx log lines. Default false.
License / credits
Plugin for the game ASKA by Sand Sailor Studio. Not affiliated with the developer. Uses BepInEx, HarmonyX, Il2CppInterop, and Fusion (Photon).