Spent the better part of a day trying to ship a custom weapon as an addon to the sandbox gamemode. Hit a wall, then found the wall is documented. Want to share what I tried in case anyone has a workaround, and figure out when this is actually getting fixed.
The thing I'm building is a vape pen. Hold attack1 to inhale, release after about a second to puff out a smoke cloud and get a short speed boost. Few hundred lines of C# in another project of mine, works fine in multiplayer with
[Sync] and [Rpc]. I wanted to peel that out into its own addon so anyone running sandbox could mount it.So: Type "addon", ParentPackage "facepunch.sandbox",
Vape : BaseWeapon, the same [Sync]/[Rpc] attributes I already had. Editor swallows it for half a second, then:SB2000 A method __sync_SetValue( WrappedPropertySet ) is required on Vape. SB2000 A method __sync_GetValue( WrappedPropertyGet ) is required on Vape. SB2000 A method __rpc_Wrapper( WrappedMethod ) is required on Vape.
Six of those. The source generator that emits the
__sync_*/__rpc_* partials fails when it walks Vape → BaseWeapon → BaseCarryable → Component across the addon-to-parent-package compilation boundary. Same code in a Type "game" project, where everything compiles in one Roslyn invocation, works first try.Tried a bunch of things:
- Adding
"facepunch.sandbox"toPackageReferencesin the .sbproj. No change. As far as I can tell that field is for editor-runtime mounting, not compile-time references. - Cloning the github sandbox repo as a sibling project and writing a stub csproj for it. MSBuild builds vape.dll cleanly against that reference. The editor's own
Sandbox.Compilingpipeline ignores my csproj entirely, reads the asset.party-cached .cll instead, and keeps SB2000-ing. - Moved the clone into
addons/sandbox/to get the editor to pick it up as a local addon. Editor still mountsfacepunch.sandbox#228160from the cloud cache, never touches my local copy, the addons folder only auto-mountslocal.*idents. Vape : Componentas a sibling toBaseWeaponon the prefab. Compiles fine (single same-assembly hop), but I lose the inheritance I actually want.- Looked at hand-writing the partial methods the generator emits. They're emitted partials wrapping property accessors, you can't really write them by hand without re-implementing the generator, and they touch engine types that aren't meant to be poked from user code.
Then I find this in
getting-started/project-types/addon-project.md:
You can't make addon projects that contain code yet - but you can use actiongraph
So it's expected, the project type is content-only by design. ActionGraph technically lets you do behavior inside an addon, but RPC and Sync aren't graph-exposed and re-doing a multiplayer-correct SWEP visually feels like a step backwards.
Questions:
- Is code-in-addon support on the roadmap? Anything public about timing : this year, next year, "we'll see"?
- Is the SB2000 cross-assembly walk something that'll be fixed when code addons get unblocked, or are addons going to need a fundamentally different code workflow than game projects?
- For everyone who's shipped a community weapon or item that runs in vanilla sandbox: what did you actually do?