All Rust commits from Facepunch
merge from main
Fix entity item ownership not preserved through reskin
When opening the spraycan reskin menu, the currently applied skin object you are looking at is now greyed out, instead of always being accessible and confusing - works with wallpaper too https://files.facepunch.com/cipeaX/2026/June/17_19-28-ScratchyBass.mp4
Typo fix
Phrases
Further spraycan refactor progress Entities restrict whether they are in a valid state for reskinning by overriding CanBeReskinned / CanBeRedirectSwapped Unified the way the reskin error toasts are sent, added 2 more - getting toasts when a reskin failed is now more consistent vs just not being able to open the menu Fixed not seeing the amount of seconds you need to wait when trying to reskin a recently damaged entity Some cleanup, moved BaseEntity.Reskinning to its own file
merge from main
Fix an edge case of errors when reskinning snowmobiles after they were saveloaded Child entity (fuel tank, storage) spawn order can vary after a server restart, causing a mismatch when trying to restore inventories using the child indices - add fallback to match by just prefab id For extra safety add more logging, and a fallback for the fallback - should anything go wrong with restoring containers, drop any leftover items instead of leaking them
merge from main
Fixed not being able to reskin large furnace while there's storage adaptors attached Fixed reskinning regular furnace <-> legacy furnace not preserving attached storage adaptor
merge from main
Fix electric furnace reskin not preserving attached storage adaptors Re-enable PreserveChildrenWhenReskinning but manually kill the child io entity so it gets recreated
Fix a IOEntity.Reskin_Restore NRE when reskinning to paintable window
merge from main
Minor cleanup Move CanBuild check further down Fix spray fail response logging to console of the whole net group Remove rundant codelock parent field Disallow reskinning turrets if not authed Disallow reskinning Busy doors Prevent potential error when reskinning io with mismatched slot counts
merge from main
Improved way to reposition socketed child entities when reskinning - look for the matching female socket on the new entity with the same name, fall back to the closest if needed Fixes door controller attached to an high external gate swapping sides when reskinned Add StringEx.EqualsAfterLastSeparator
merge from main 152363
Refactored the entire method / file now that reskinning is feature complete and all on the new system Clear steps, organized validation logic, comments, ripped out redundant stuff, etc. Allow reskinning while noclip flying
Add computer station reskinning Now preserves all the saved cctv codes and wire stays connected to the sub io entity, snapping to the new handle position Fix an NRE when trying to control drones on playground
merge from mfm (merge from main)
Add autoturret reskinning Preserves loaded ammo, authlist, rc identifier and peacekeeper setting
Implement IO entity reskinning with the new system, will now always nicely adjust any connected wires / pipes to the new positions: https://files.facepunch.com/cipeaX/2026/May/21_01-08-RightBighorn.mp4
Fix a bug causing io lines to not update correctly when multiple storage adaptors on the same barrel have connections between themselves
Integrate item container and child item container preserving into the new system Re-implement entity children preserving, with attachments repositioning if their sockets shifted, child io entity also have their connected lines update correctly Fixes various current bugs with storage adaptors / door controllers when their parent is reskinned Make ceilinglight reskinnable again, will fix reskinning io entities themselves next Fix not being able to skin snowmobile back to default
Some renaming
Improve the building of the PreserveInfo
Initial wip on an attempt to refactor the beast that is SprayCan.ChangeItemSkin The idea is that entities handle things they need to persist through reskinning themselves via Preserve and Restore methods