diff --git a/MSBuild/Robust.Engine.Version.props b/MSBuild/Robust.Engine.Version.props
index 8893015f20a..bb21edd8f8d 100644
--- a/MSBuild/Robust.Engine.Version.props
+++ b/MSBuild/Robust.Engine.Version.props
@@ -1,4 +1,4 @@
- 175.0.0
+ 180.1.0
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 48c725c110f..5b168756a6c 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -54,6 +54,123 @@ END TEMPLATE-->
*None yet*
+## 180.1.0
+
+### New features
+
+* Add the map name to lsmap.
+* Add net.pool_size to CVars to control the message data pool size in Lidgren and to also toggle pooling.
+
+### Bugfixes
+
+* Fix physics contraints causing enormous heap allocations.
+* Fix potential error when writing a runtime log.
+* Fix shape lookups for non-hard fixtures in EntityLookupSystem from 180.0.0
+
+
+## 180.0.0
+
+### Breaking changes
+
+* Removed some obsolete methods from EntityLookupSystem.
+
+### New features
+
+* PhysicsSystem.TryGetNearest now supports chain shapes.
+* Add IPhysShape methods to EntityLookupSystem rather than relying on AABB checks.
+* Add some more helper methods to SharedTransformSystem.
+* Add GetOrNew dictionary extension that also returns a bool on whether the key existed.
+* Add a GetAnchoredEntities overload that takes in a list.
+
+### Other
+
+* Use NetEntities for the F3 debug panel to align with command usage.
+
+
+## 179.0.0
+
+### Breaking changes
+
+* EyeComponent.Eye is no longer nullable
+
+### New features
+
+* Light rendering can now be enabled or disable per eye.
+
+### Bugfixes
+
+* Deserializing old maps with empty grid chunks should now just ignore those chunks.
+
+### Other
+
+* UnknownPrototypeException now also tells you the prototype kind instead of just the unkown ID.
+* Adding or removing networked components while resetting predicted entities now results in a more informative exception.
+
+
+## 178.0.0
+
+### Breaking changes
+
+* Most methods in ActorSystem have been moved to ISharedPlayerManager.
+* Several actor/player related components and events have been moved to shared.
+
+### New features
+
+* Added `NetListAsArray.Value` to the sandbox whitelist
+
+
+## 177.0.0
+
+### Breaking changes
+
+* Removed toInsertXform and added containerXform in SharedContainerSystem.CanInsert.
+* Removed EntityQuery parameters from SharedContainerSystem.IsEntityOrParentInContainer.
+* Changed the signature of ContainsEntity in SharedTransformSystem to use Entity.
+* Removed one obsoleted SharedTransformSystem.AnchorEntity method.
+* Changed signature of SharedTransformSystem.SetCoordinates to use Entity.
+
+### New features
+
+* Added more Entity query methods.
+* Added BeforeApplyState event to replay playback.
+
+### Bugfixes
+
+* Fixed inverted GetAllMapGrids map id check.
+* Fixed transform test warnings.
+* Fixed PlacementManager warnings.
+* Fixed reparenting bug for entities that are being deleted.
+
+### Other
+
+* Changed VerticalAlignment of RichTextLabel to Center to be consistent with Label.
+* Changed PVS error log to be a warning instead.
+* Marked insert and remove container methods as obsolete, added container system methods to replace them.
+* Marked TransformComponent.MapPosition as obsolete, added GetMapCoordinates system method to replace it.
+
+### Internal
+
+* Moved TryGetUi/TryToggleUi/ToggleUi/TryOpen/OpenUi/TryClose/CloseUi methods from UserInterfaceSystem to SharedUserInterfaceSystem.
+
+
+## 176.0.0
+
+### Breaking changes
+
+* Reverted audio rework temporarily until packaging is fixed.
+* Changes to Robust.Packaging to facilitate Content.Packaging ports from the python packaging scripts.
+
+### New features
+
+* Add a cvar for max game state buffer size.
+* Add an overload for GetEntitiesInRange that takes in a set.
+
+### Bugfixes
+
+* Fix PVS initial list capacity always being 0.
+* Fix replay lerp error spam.
+
+
## 175.0.0
### Breaking changes
diff --git a/Resources/EnginePrototypes/audio_presets.yml b/Resources/EnginePrototypes/audio_presets.yml
deleted file mode 100644
index d13767f021c..00000000000
--- a/Resources/EnginePrototypes/audio_presets.yml
+++ /dev/null
@@ -1,3076 +0,0 @@
-- type: audioPreset
- id: Generic
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.8913
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.8300
- decayLfRatio: 1.0000
- reflectionsGain: 0.0500
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: PaddedCell
- density: 0.1715
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0010
- gainLf: 1.0000
- decayTime: 0.1700
- decayHfRatio: 0.1000
- decayLfRatio: 1.0000
- reflectionsGain: 0.2500
- reflectionsDelay: 0.0010
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2691
- lateReverbDelay: 0.0020
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Room
- density: 0.4287
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.5929
- gainLf: 1.0000
- decayTime: 0.4000
- decayHfRatio: 0.8300
- decayLfRatio: 1.0000
- reflectionsGain: 0.1503
- reflectionsDelay: 0.0020
- reflectionsPan: 0,0,0
- lateReverbGain: 1.0629
- lateReverbDelay: 0.0030
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Bathroom
- density: 0.1715
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.2512
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.5400
- decayLfRatio: 1.0000
- reflectionsGain: 0.6531
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 3.2734
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: LivingRoom
- density: 0.9766
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0010
- gainLf: 1.0000
- decayTime: 0.5000
- decayHfRatio: 0.1000
- decayLfRatio: 1.0000
- reflectionsGain: 0.2051
- reflectionsDelay: 0.0030
- reflectionsPan: 0,0,0
- lateReverbGain: 0.2805
- lateReverbDelay: 0.0040
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: StoneRoom
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 1.0000
- decayTime: 2.3100
- decayHfRatio: 0.6400
- decayLfRatio: 1.0000
- reflectionsGain: 0.4411
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1003
- lateReverbDelay: 0.0170
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Auditorium
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.5781
- gainLf: 1.0000
- decayTime: 4.3200
- decayHfRatio: 0.5900
- decayLfRatio: 1.0000
- reflectionsGain: 0.4032
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7170
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: ConcertHall
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 1.0000
- decayTime: 3.9200
- decayHfRatio: 0.7000
- decayLfRatio: 1.0000
- reflectionsGain: 0.2427
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 0.9977
- lateReverbDelay: 0.0290
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Cave
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 1.0000
- gainLf: 1.0000
- decayTime: 2.9100
- decayHfRatio: 1.3000
- decayLfRatio: 1.0000
- reflectionsGain: 0.5000
- reflectionsDelay: 0.0150
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7063
- lateReverbDelay: 0.0220
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: Arena
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.4477
- gainLf: 1.0000
- decayTime: 7.2400
- decayHfRatio: 0.3300
- decayLfRatio: 1.0000
- reflectionsGain: 0.2612
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 1.0186
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Hangar
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.3162
- gainLf: 1.0000
- decayTime: 10.0500
- decayHfRatio: 0.2300
- decayLfRatio: 1.0000
- reflectionsGain: 0.5000
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2560
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CarpetedHallway
- density: 0.4287
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0100
- gainLf: 1.0000
- decayTime: 0.3000
- decayHfRatio: 0.1000
- decayLfRatio: 1.0000
- reflectionsGain: 0.1215
- reflectionsDelay: 0.0020
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1531
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Hallway
- density: 0.3645
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.5900
- decayLfRatio: 1.0000
- reflectionsGain: 0.2458
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.6615
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: StoneCorridor
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.7612
- gainLf: 1.0000
- decayTime: 2.7000
- decayHfRatio: 0.7900
- decayLfRatio: 1.0000
- reflectionsGain: 0.2472
- reflectionsDelay: 0.0130
- reflectionsPan: 0,0,0
- lateReverbGain: 1.5758
- lateReverbDelay: 0.0200
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Alley
- density: 1.0000
- diffusion: 0.3000
- gain: 0.3162
- gainHf: 0.7328
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.8600
- decayLfRatio: 1.0000
- reflectionsGain: 0.2500
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 0.9954
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.1250
- echoDepth: 0.9500
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Forest
- density: 1.0000
- diffusion: 0.3000
- gain: 0.3162
- gainHf: 0.0224
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.5400
- decayLfRatio: 1.0000
- reflectionsGain: 0.0525
- reflectionsDelay: 0.1620
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7682
- lateReverbDelay: 0.0880
- lateReverbPan: 0,0,0
- echoTime: 0.1250
- echoDepth: 1.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: City
- density: 1.0000
- diffusion: 0.5000
- gain: 0.3162
- gainHf: 0.3981
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.6700
- decayLfRatio: 1.0000
- reflectionsGain: 0.0730
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1427
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Mountains
- density: 1.0000
- diffusion: 0.2700
- gain: 0.3162
- gainHf: 0.0562
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.2100
- decayLfRatio: 1.0000
- reflectionsGain: 0.0407
- reflectionsDelay: 0.3000
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1919
- lateReverbDelay: 0.1000
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 1.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: Quarry
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.3162
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.8300
- decayLfRatio: 1.0000
- reflectionsGain: 0.0000
- reflectionsDelay: 0.0610
- reflectionsPan: 0,0,0
- lateReverbGain: 1.7783
- lateReverbDelay: 0.0250
- lateReverbPan: 0,0,0
- echoTime: 0.1250
- echoDepth: 0.7000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Plain
- density: 1.0000
- diffusion: 0.2100
- gain: 0.3162
- gainHf: 0.1000
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.5000
- decayLfRatio: 1.0000
- reflectionsGain: 0.0585
- reflectionsDelay: 0.1790
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1089
- lateReverbDelay: 0.1000
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 1.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: ParkingLot
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 1.0000
- gainLf: 1.0000
- decayTime: 1.6500
- decayHfRatio: 1.5000
- decayLfRatio: 1.0000
- reflectionsGain: 0.2082
- reflectionsDelay: 0.0080
- reflectionsPan: 0,0,0
- lateReverbGain: 0.2652
- lateReverbDelay: 0.0120
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: SewerPipe
- density: 0.3071
- diffusion: 0.8000
- gain: 0.3162
- gainHf: 0.3162
- gainLf: 1.0000
- decayTime: 2.8100
- decayHfRatio: 0.1400
- decayLfRatio: 1.0000
- reflectionsGain: 1.6387
- reflectionsDelay: 0.0140
- reflectionsPan: 0,0,0
- lateReverbGain: 3.2471
- lateReverbDelay: 0.0210
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Underwater
- density: 0.3645
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0100
- gainLf: 1.0000
- decayTime: 1.4900
- decayHfRatio: 0.1000
- decayLfRatio: 1.0000
- reflectionsGain: 0.5963
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 7.0795
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 1.1800
- modulationDepth: 0.3480
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Drugged
- density: 0.4287
- diffusion: 0.5000
- gain: 0.3162
- gainHf: 1.0000
- gainLf: 1.0000
- decayTime: 8.3900
- decayHfRatio: 1.3900
- decayLfRatio: 1.0000
- reflectionsGain: 0.8760
- reflectionsDelay: 0.0020
- reflectionsPan: 0,0,0
- lateReverbGain: 3.1081
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 1.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: Dizzy
- density: 0.3645
- diffusion: 0.6000
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 1.0000
- decayTime: 17.2300
- decayHfRatio: 0.5600
- decayLfRatio: 1.0000
- reflectionsGain: 0.1392
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 0.4937
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 1.0000
- modulationTime: 0.8100
- modulationDepth: 0.3100
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: Psychotic
- density: 0.0625
- diffusion: 0.5000
- gain: 0.3162
- gainHf: 0.8404
- gainLf: 1.0000
- decayTime: 7.5600
- decayHfRatio: 0.9100
- decayLfRatio: 1.0000
- reflectionsGain: 0.4864
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 2.4378
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 4.0000
- modulationDepth: 1.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-# Castle Presets
-
-- type: audioPreset
- id: CastleSmallRoom
- density: 1.0000
- diffusion: 0.8900
- gain: 0.3162
- gainHf: 0.3981
- gainLf: 0.1000
- decayTime: 1.2200
- decayHfRatio: 0.8300
- decayLfRatio: 0.3100
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0220
- reflectionsPan: 0,0,0
- lateReverbGain: 1.9953
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.1380
- echoDepth: 0.0800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CastleShortPassage
- density: 1.0000
- diffusion: 0.8900
- gain: 0.3162
- gainHf: 0.3162
- gainLf: 0.1000
- decayTime: 2.3200
- decayHfRatio: 0.8300
- decayLfRatio: 0.3100
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0230
- lateReverbPan: 0,0,0
- echoTime: 0.1380
- echoDepth: 0.0800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CastleMediumRoom
- density: 1.0000
- diffusion: 0.9300
- gain: 0.3162
- gainHf: 0.2818
- gainLf: 0.1000
- decayTime: 2.0400
- decayHfRatio: 0.8300
- decayLfRatio: 0.4600
- reflectionsGain: 0.6310
- reflectionsDelay: 0.0220
- reflectionsPan: 0,0,0
- lateReverbGain: 1.5849
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.1550
- echoDepth: 0.0300
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CastleLargeRoom
- density: 1.0000
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.2818
- gainLf: 0.1259
- decayTime: 2.5300
- decayHfRatio: 0.8300
- decayLfRatio: 0.5000
- reflectionsGain: 0.4467
- reflectionsDelay: 0.0340
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0160
- lateReverbPan: 0,0,0
- echoTime: 0.1850
- echoDepth: 0.0700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CastleLongPassage
- density: 1.0000
- diffusion: 0.8900
- gain: 0.3162
- gainHf: 0.3981
- gainLf: 0.1000
- decayTime: 3.4200
- decayHfRatio: 0.8300
- decayLfRatio: 0.3100
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0230
- lateReverbPan: 0,0,0
- echoTime: 0.1380
- echoDepth: 0.0800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CastleHall
- density: 1.0000
- diffusion: 0.8100
- gain: 0.3162
- gainHf: 0.2818
- gainLf: 0.1778
- decayTime: 3.1400
- decayHfRatio: 0.7900
- decayLfRatio: 0.6200
- reflectionsGain: 0.1778
- reflectionsDelay: 0.0560
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0240
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CastleCupboard
- density: 1.0000
- diffusion: 0.8900
- gain: 0.3162
- gainHf: 0.2818
- gainLf: 0.1000
- decayTime: 0.6700
- decayHfRatio: 0.8700
- decayLfRatio: 0.3100
- reflectionsGain: 1.4125
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 3.5481
- lateReverbDelay: 0.0070
- lateReverbPan: 0,0,0
- echoTime: 0.1380
- echoDepth: 0.0800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CastleCourtyard
- density: 1.0000
- diffusion: 0.4200
- gain: 0.3162
- gainHf: 0.4467
- gainLf: 0.1995
- decayTime: 2.1300
- decayHfRatio: 0.6100
- decayLfRatio: 0.2300
- reflectionsGain: 0.2239
- reflectionsDelay: 0.1600
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7079
- lateReverbDelay: 0.0360
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.3700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: CastleAlcove
- density: 1.0000
- diffusion: 0.8900
- gain: 0.3162
- gainHf: 0.5012
- gainLf: 0.1000
- decayTime: 1.6400
- decayHfRatio: 0.8700
- decayLfRatio: 0.3100
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0340
- lateReverbPan: 0,0,0
- echoTime: 0.1380
- echoDepth: 0.0800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5168.6001
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# Factory Presets
-
-- type: audioPreset
- id: FactorySmallRoom
- density: 0.3645
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.7943
- gainLf: 0.5012
- decayTime: 1.7200
- decayHfRatio: 0.6500
- decayLfRatio: 1.3100
- reflectionsGain: 0.7079
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.7783
- lateReverbDelay: 0.0240
- lateReverbPan: 0,0,0
- echoTime: 0.1190
- echoDepth: 0.0700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryShortPassage
- density: 0.3645
- diffusion: 0.6400
- gain: 0.2512
- gainHf: 0.7943
- gainLf: 0.5012
- decayTime: 2.5300
- decayHfRatio: 0.6500
- decayLfRatio: 1.3100
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0380
- lateReverbPan: 0,0,0
- echoTime: 0.1350
- echoDepth: 0.2300
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryMediumRoom
- density: 0.4287
- diffusion: 0.8200
- gain: 0.2512
- gainHf: 0.7943
- gainLf: 0.5012
- decayTime: 2.7600
- decayHfRatio: 0.6500
- decayLfRatio: 1.3100
- reflectionsGain: 0.2818
- reflectionsDelay: 0.0220
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0230
- lateReverbPan: 0,0,0
- echoTime: 0.1740
- echoDepth: 0.0700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryLargeRoom
- density: 0.4287
- diffusion: 0.7500
- gain: 0.2512
- gainHf: 0.7079
- gainLf: 0.6310
- decayTime: 4.2400
- decayHfRatio: 0.5100
- decayLfRatio: 1.3100
- reflectionsGain: 0.1778
- reflectionsDelay: 0.0390
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0230
- lateReverbPan: 0,0,0
- echoTime: 0.2310
- echoDepth: 0.0700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryLongPassage
- density: 0.3645
- diffusion: 0.6400
- gain: 0.2512
- gainHf: 0.7943
- gainLf: 0.5012
- decayTime: 4.0600
- decayHfRatio: 0.6500
- decayLfRatio: 1.3100
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0370
- lateReverbPan: 0,0,0
- echoTime: 0.1350
- echoDepth: 0.2300
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryHall
- density: 0.4287
- diffusion: 0.7500
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 0.6310
- decayTime: 7.4300
- decayHfRatio: 0.5100
- decayLfRatio: 1.3100
- reflectionsGain: 0.0631
- reflectionsDelay: 0.0730
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0270
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryCupboard
- density: 0.3071
- diffusion: 0.6300
- gain: 0.2512
- gainHf: 0.7943
- gainLf: 0.5012
- decayTime: 0.4900
- decayHfRatio: 0.6500
- decayLfRatio: 1.3100
- reflectionsGain: 1.2589
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.9953
- lateReverbDelay: 0.0320
- lateReverbPan: 0,0,0
- echoTime: 0.1070
- echoDepth: 0.0700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryCourtyard
- density: 0.3071
- diffusion: 0.5700
- gain: 0.3162
- gainHf: 0.3162
- gainLf: 0.6310
- decayTime: 2.3200
- decayHfRatio: 0.2900
- decayLfRatio: 0.5600
- reflectionsGain: 0.2239
- reflectionsDelay: 0.1400
- reflectionsPan: 0,0,0
- lateReverbGain: 0.3981
- lateReverbDelay: 0.0390
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.2900
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: FactoryAlcove
- density: 0.3645
- diffusion: 0.5900
- gain: 0.2512
- gainHf: 0.7943
- gainLf: 0.5012
- decayTime: 3.1400
- decayHfRatio: 0.6500
- decayLfRatio: 1.3100
- reflectionsGain: 1.4125
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.0000
- lateReverbDelay: 0.0380
- lateReverbPan: 0,0,0
- echoTime: 0.1140
- echoDepth: 0.1000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3762.6001
- lfReference: 362.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# Ice Palace Presets
-
-- type: audioPreset
- id: IcePalaceSmallRoom
- density: 1.0000
- diffusion: 0.8400
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.2818
- decayTime: 1.5100
- decayHfRatio: 1.5300
- decayLfRatio: 0.2700
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.1640
- echoDepth: 0.1400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceShortPassage
- density: 1.0000
- diffusion: 0.7500
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.2818
- decayTime: 1.7900
- decayHfRatio: 1.4600
- decayLfRatio: 0.2800
- reflectionsGain: 0.5012
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0190
- lateReverbPan: 0,0,0
- echoTime: 0.1770
- echoDepth: 0.0900
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceMediumRoom
- density: 1.0000
- diffusion: 0.8700
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.4467
- decayTime: 2.2200
- decayHfRatio: 1.5300
- decayLfRatio: 0.3200
- reflectionsGain: 0.3981
- reflectionsDelay: 0.0390
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0270
- lateReverbPan: 0,0,0
- echoTime: 0.1860
- echoDepth: 0.1200
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceLargeRoom
- density: 1.0000
- diffusion: 0.8100
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.4467
- decayTime: 3.1400
- decayHfRatio: 1.5300
- decayLfRatio: 0.3200
- reflectionsGain: 0.2512
- reflectionsDelay: 0.0390
- reflectionsPan: 0,0,0
- lateReverbGain: 1.0000
- lateReverbDelay: 0.0270
- lateReverbPan: 0,0,0
- echoTime: 0.2140
- echoDepth: 0.1100
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceLongPassage
- density: 1.0000
- diffusion: 0.7700
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.3981
- decayTime: 3.0100
- decayHfRatio: 1.4600
- decayLfRatio: 0.2800
- reflectionsGain: 0.7943
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0250
- lateReverbPan: 0,0,0
- echoTime: 0.1860
- echoDepth: 0.0400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceHall
- density: 1.0000
- diffusion: 0.7600
- gain: 0.3162
- gainHf: 0.4467
- gainLf: 0.5623
- decayTime: 5.4900
- decayHfRatio: 1.5300
- decayLfRatio: 0.3800
- reflectionsGain: 0.1122
- reflectionsDelay: 0.0540
- reflectionsPan: 0,0,0
- lateReverbGain: 0.6310
- lateReverbDelay: 0.0520
- lateReverbPan: 0,0,0
- echoTime: 0.2260
- echoDepth: 0.1100
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceCupboard
- density: 1.0000
- diffusion: 0.8300
- gain: 0.3162
- gainHf: 0.5012
- gainLf: 0.2239
- decayTime: 0.7600
- decayHfRatio: 1.5300
- decayLfRatio: 0.2600
- reflectionsGain: 1.1220
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.9953
- lateReverbDelay: 0.0160
- lateReverbPan: 0,0,0
- echoTime: 0.1430
- echoDepth: 0.0800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceCourtyard
- density: 1.0000
- diffusion: 0.5900
- gain: 0.3162
- gainHf: 0.2818
- gainLf: 0.3162
- decayTime: 2.0400
- decayHfRatio: 1.2000
- decayLfRatio: 0.3800
- reflectionsGain: 0.3162
- reflectionsDelay: 0.1730
- reflectionsPan: 0,0,0
- lateReverbGain: 0.3162
- lateReverbDelay: 0.0430
- lateReverbPan: 0,0,0
- echoTime: 0.2350
- echoDepth: 0.4800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: IcePalaceAlcove
- density: 1.0000
- diffusion: 0.8400
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.2818
- decayTime: 2.7600
- decayHfRatio: 1.4600
- decayLfRatio: 0.2800
- reflectionsGain: 1.1220
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.1610
- echoDepth: 0.0900
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 12428.5000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# Space Station Presets
-
-- type: audioPreset
- id: SpaceStationSmallRoom
- density: 0.2109
- diffusion: 0.7000
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 0.8913
- decayTime: 1.7200
- decayHfRatio: 0.8200
- decayLfRatio: 0.5500
- reflectionsGain: 0.7943
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0130
- lateReverbPan: 0,0,0
- echoTime: 0.1880
- echoDepth: 0.2600
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SpaceStationShortPassage
- density: 0.2109
- diffusion: 0.8700
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 0.8913
- decayTime: 3.5700
- decayHfRatio: 0.5000
- decayLfRatio: 0.5500
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0160
- lateReverbPan: 0,0,0
- echoTime: 0.1720
- echoDepth: 0.2000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SpaceStationMediumRoom
- density: 0.2109
- diffusion: 0.7500
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 0.8913
- decayTime: 3.0100
- decayHfRatio: 0.5000
- decayLfRatio: 0.5500
- reflectionsGain: 0.3981
- reflectionsDelay: 0.0340
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0350
- lateReverbPan: 0,0,0
- echoTime: 0.2090
- echoDepth: 0.3100
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SpaceStationLargeRoom
- density: 0.3645
- diffusion: 0.8100
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 0.8913
- decayTime: 3.8900
- decayHfRatio: 0.3800
- decayLfRatio: 0.6100
- reflectionsGain: 0.3162
- reflectionsDelay: 0.0560
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0350
- lateReverbPan: 0,0,0
- echoTime: 0.2330
- echoDepth: 0.2800
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SpaceStationLongPassage
- density: 0.4287
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 0.8913
- decayTime: 4.6200
- decayHfRatio: 0.6200
- decayLfRatio: 0.5500
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0310
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.2300
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SpaceStationHall
- density: 0.4287
- diffusion: 0.8700
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 0.8913
- decayTime: 7.1100
- decayHfRatio: 0.3800
- decayLfRatio: 0.6100
- reflectionsGain: 0.1778
- reflectionsDelay: 0.1000
- reflectionsPan: 0,0,0
- lateReverbGain: 0.6310
- lateReverbDelay: 0.0470
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.2500
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SpaceStationCupboard
- density: 0.1715
- diffusion: 0.5600
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 0.8913
- decayTime: 0.7900
- decayHfRatio: 0.8100
- decayLfRatio: 0.5500
- reflectionsGain: 1.4125
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.7783
- lateReverbDelay: 0.0180
- lateReverbPan: 0,0,0
- echoTime: 0.1810
- echoDepth: 0.3100
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SpaceStationAlcove
- density: 0.2109
- diffusion: 0.7800
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 0.8913
- decayTime: 1.1600
- decayHfRatio: 0.8100
- decayLfRatio: 0.5500
- reflectionsGain: 1.4125
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 1.0000
- lateReverbDelay: 0.0180
- lateReverbPan: 0,0,0
- echoTime: 0.1920
- echoDepth: 0.2100
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 3316.1001
- lfReference: 458.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# Wooden Galleon Presets
-
-- type: audioPreset
- id: WoodenSmallRoom
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1122
- gainLf: 0.3162
- decayTime: 0.7900
- decayHfRatio: 0.3200
- decayLfRatio: 0.8700
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0320
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0290
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenShortPassage
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1259
- gainLf: 0.3162
- decayTime: 1.7500
- decayHfRatio: 0.5000
- decayLfRatio: 0.8700
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 0.6310
- lateReverbDelay: 0.0240
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenMediumRoom
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1000
- gainLf: 0.2818
- decayTime: 1.4700
- decayHfRatio: 0.4200
- decayLfRatio: 0.8200
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0490
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0290
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenLargeRoom
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0891
- gainLf: 0.2818
- decayTime: 2.6500
- decayHfRatio: 0.3300
- decayLfRatio: 0.8200
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0660
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7943
- lateReverbDelay: 0.0490
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenLongPassage
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1000
- gainLf: 0.3162
- decayTime: 1.9900
- decayHfRatio: 0.4000
- decayLfRatio: 0.7900
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 0.4467
- lateReverbDelay: 0.0360
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenHall
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0794
- gainLf: 0.2818
- decayTime: 3.4500
- decayHfRatio: 0.3000
- decayLfRatio: 0.8200
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0880
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7943
- lateReverbDelay: 0.0630
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenCupboard
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1413
- gainLf: 0.3162
- decayTime: 0.5600
- decayHfRatio: 0.4600
- decayLfRatio: 0.9100
- reflectionsGain: 1.1220
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0280
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenCourtyard
- density: 1.0000
- diffusion: 0.6500
- gain: 0.3162
- gainHf: 0.0794
- gainLf: 0.3162
- decayTime: 1.7900
- decayHfRatio: 0.3500
- decayLfRatio: 0.7900
- reflectionsGain: 0.5623
- reflectionsDelay: 0.1230
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1000
- lateReverbDelay: 0.0320
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: WoodenAlcove
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1259
- gainLf: 0.3162
- decayTime: 1.2200
- decayHfRatio: 0.6200
- decayLfRatio: 0.9100
- reflectionsGain: 1.1220
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7079
- lateReverbDelay: 0.0240
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4705.0000
- lfReference: 99.6000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# Sports Presets
-
-- type: audioPreset
- id: SportEmptyStadium
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.4467
- gainLf: 0.7943
- decayTime: 6.2600
- decayHfRatio: 0.5100
- decayLfRatio: 1.1000
- reflectionsGain: 0.0631
- reflectionsDelay: 0.1830
- reflectionsPan: 0,0,0
- lateReverbGain: 0.3981
- lateReverbDelay: 0.0380
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SportSquashCourt
- density: 1.0000
- diffusion: 0.7500
- gain: 0.3162
- gainHf: 0.3162
- gainLf: 0.7943
- decayTime: 2.2200
- decayHfRatio: 0.9100
- decayLfRatio: 1.1600
- reflectionsGain: 0.4467
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7943
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.1260
- echoDepth: 0.1900
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 7176.8999
- lfReference: 211.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SportSmallSwimmingPool
- density: 1.0000
- diffusion: 0.7000
- gain: 0.3162
- gainHf: 0.7943
- gainLf: 0.8913
- decayTime: 2.7600
- decayHfRatio: 1.2500
- decayLfRatio: 1.1400
- reflectionsGain: 0.6310
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7943
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.1790
- echoDepth: 0.1500
- modulationTime: 0.8950
- modulationDepth: 0.1900
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: SportLargeSwimmingPool
- density: 1.0000
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.7943
- gainLf: 1.0000
- decayTime: 5.4900
- decayHfRatio: 1.3100
- decayLfRatio: 1.1400
- reflectionsGain: 0.4467
- reflectionsDelay: 0.0390
- reflectionsPan: 0,0,0
- lateReverbGain: 0.5012
- lateReverbDelay: 0.0490
- lateReverbPan: 0,0,0
- echoTime: 0.2220
- echoDepth: 0.5500
- modulationTime: 1.1590
- modulationDepth: 0.2100
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: SportGymnasium
- density: 1.0000
- diffusion: 0.8100
- gain: 0.3162
- gainHf: 0.4467
- gainLf: 0.8913
- decayTime: 3.1400
- decayHfRatio: 1.0600
- decayLfRatio: 1.3500
- reflectionsGain: 0.3981
- reflectionsDelay: 0.0290
- reflectionsPan: 0,0,0
- lateReverbGain: 0.5623
- lateReverbDelay: 0.0450
- lateReverbPan: 0,0,0
- echoTime: 0.1460
- echoDepth: 0.1400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 7176.8999
- lfReference: 211.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SportFullStadium
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0708
- gainLf: 0.7943
- decayTime: 5.2500
- decayHfRatio: 0.1700
- decayLfRatio: 0.8000
- reflectionsGain: 0.1000
- reflectionsDelay: 0.1880
- reflectionsPan: 0,0,0
- lateReverbGain: 0.2818
- lateReverbDelay: 0.0380
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SportStadiumTannoy
- density: 1.0000
- diffusion: 0.7800
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.5012
- decayTime: 2.5300
- decayHfRatio: 0.8800
- decayLfRatio: 0.6800
- reflectionsGain: 0.2818
- reflectionsDelay: 0.2300
- reflectionsPan: 0,0,0
- lateReverbGain: 0.5012
- lateReverbDelay: 0.0630
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.2000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# Prefab Presets
-
-- type: audioPreset
- id: PrefabWorkshop
- density: 0.4287
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1413
- gainLf: 0.3981
- decayTime: 0.7600
- decayHfRatio: 1.0000
- decayLfRatio: 1.0000
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0120
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: PrefabSchoolroom
- density: 0.4022
- diffusion: 0.6900
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 0.5012
- decayTime: 0.9800
- decayHfRatio: 0.4500
- decayLfRatio: 0.1800
- reflectionsGain: 1.4125
- reflectionsDelay: 0.0170
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0150
- lateReverbPan: 0,0,0
- echoTime: 0.0950
- echoDepth: 0.1400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 7176.8999
- lfReference: 211.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: PrefabPractiseRoom
- density: 0.4022
- diffusion: 0.8700
- gain: 0.3162
- gainHf: 0.3981
- gainLf: 0.5012
- decayTime: 1.1200
- decayHfRatio: 0.5600
- decayLfRatio: 0.1800
- reflectionsGain: 1.2589
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0110
- lateReverbPan: 0,0,0
- echoTime: 0.0950
- echoDepth: 0.1400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 7176.8999
- lfReference: 211.2000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: PrefabOuthouse
- density: 1.0000
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.1122
- gainLf: 0.1585
- decayTime: 1.3800
- decayHfRatio: 0.3800
- decayLfRatio: 0.3500
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0240
- reflectionsPan: 0, 0, 0
- lateReverbGain: 0.6310
- lateReverbDelay: 0.0440
- lateReverbPan: 0,0,0
- echoTime: 0.1210
- echoDepth: 0.1700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 107.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: PrefabCaravan
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.0891
- gainLf: 0.1259
- decayTime: 0.4300
- decayHfRatio: 1.5000
- decayLfRatio: 1.0000
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0120
- reflectionsPan: 0,0,0
- lateReverbGain: 1.9953
- lateReverbDelay: 0.0120
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-# Dome and Pipe Presets
-
-- type: audioPreset
- id: DomeTomb
- density: 1.0000
- diffusion: 0.7900
- gain: 0.3162
- gainHf: 0.3548
- gainLf: 0.2239
- decayTime: 4.1800
- decayHfRatio: 0.2100
- decayLfRatio: 0.1000
- reflectionsGain: 0.3868
- reflectionsDelay: 0.0300
- reflectionsPan: 0,0,0
- lateReverbGain: 1.6788
- lateReverbDelay: 0.0220
- lateReverbPan: 0,0,0
- echoTime: 0.1770
- echoDepth: 0.1900
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 20.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: PipeSmall
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.3548
- gainLf: 0.2239
- decayTime: 5.0400
- decayHfRatio: 0.1000
- decayLfRatio: 0.1000
- reflectionsGain: 0.5012
- reflectionsDelay: 0.0320
- reflectionsPan: 0,0,0
- lateReverbGain: 2.5119
- lateReverbDelay: 0.0150
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 20.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: DomeSaintPauls
- density: 1.0000
- diffusion: 0.8700
- gain: 0.3162
- gainHf: 0.3548
- gainLf: 0.2239
- decayTime: 10.4800
- decayHfRatio: 0.1900
- decayLfRatio: 0.1000
- reflectionsGain: 0.1778
- reflectionsDelay: 0.0900
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0420
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.1200
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 20.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: PipeLongThin
- density: 0.2560
- diffusion: 0.9100
- gain: 0.3162
- gainHf: 0.4467
- gainLf: 0.2818
- decayTime: 9.2100
- decayHfRatio: 0.1800
- decayLfRatio: 0.1000
- reflectionsGain: 0.7079
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7079
- lateReverbDelay: 0.0220
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 20.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: PipeLarge
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.3548
- gainLf: 0.2239
- decayTime: 8.4500
- decayHfRatio: 0.1000
- decayLfRatio: 0.1000
- reflectionsGain: 0.3981
- reflectionsDelay: 0.0460
- reflectionsPan: 0,0,0
- lateReverbGain: 1.5849
- lateReverbDelay: 0.0320
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 20.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: PipeResonant
- density: 0.1373
- diffusion: 0.9100
- gain: 0.3162
- gainHf: 0.4467
- gainLf: 0.2818
- decayTime: 6.8100
- decayHfRatio: 0.1800
- decayLfRatio: 0.1000
- reflectionsGain: 0.7079
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.0000
- lateReverbDelay: 0.0220
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 20.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-# Outdoors Presets
-
-- type: audioPreset
- id: OutdoorsBackyard
- density: 1.0000
- diffusion: 0.4500
- gain: 0.3162
- gainHf: 0.2512
- gainLf: 0.5012
- decayTime: 1.1200
- decayHfRatio: 0.3400
- decayLfRatio: 0.4600
- reflectionsGain: 0.4467
- reflectionsDelay: 0.0690
- reflectionsPan: 0, 0, 0
- lateReverbGain: 0.7079
- lateReverbDelay: 0.0230
- lateReverbPan: 0,0,0
- echoTime: 0.2180
- echoDepth: 0.3400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4399.1001
- lfReference: 242.9000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: OutdoorsRollingPlains
- density: 1.0000
- diffusion: 0.0000
- gain: 0.3162
- gainHf: 0.0112
- gainLf: 0.6310
- decayTime: 2.1300
- decayHfRatio: 0.2100
- decayLfRatio: 0.4600
- reflectionsGain: 0.1778
- reflectionsDelay: 0.3000
- reflectionsPan: 0,0,0
- lateReverbGain: 0.4467
- lateReverbDelay: 0.0190
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 1.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4399.1001
- lfReference: 242.9000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: OutdoorsDeepCanyon
- density: 1.0000
- diffusion: 0.7400
- gain: 0.3162
- gainHf: 0.1778
- gainLf: 0.6310
- decayTime: 3.8900
- decayHfRatio: 0.2100
- decayLfRatio: 0.4600
- reflectionsGain: 0.3162
- reflectionsDelay: 0.2230
- reflectionsPan: 0,0,0
- lateReverbGain: 0.3548
- lateReverbDelay: 0.0190
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 1.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4399.1001
- lfReference: 242.9000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: OutdoorsCreek
- density: 1.0000
- diffusion: 0.3500
- gain: 0.3162
- gainHf: 0.1778
- gainLf: 0.5012
- decayTime: 2.1300
- decayHfRatio: 0.2100
- decayLfRatio: 0.4600
- reflectionsGain: 0.3981
- reflectionsDelay: 0.1150
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1995
- lateReverbDelay: 0.0310
- lateReverbPan: 0,0,0
- echoTime: 0.2180
- echoDepth: 0.3400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 4399.1001
- lfReference: 242.9000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: OutdoorsValley
- density: 1.0000
- diffusion: 0.2800
- gain: 0.3162
- gainHf: 0.0282
- gainLf: 0.1585
- decayTime: 2.8800
- decayHfRatio: 0.2600
- decayLfRatio: 0.3500
- reflectionsGain: 0.1413
- reflectionsDelay: 0.2630
- reflectionsPan: 0,0,0
- lateReverbGain: 0.3981
- lateReverbDelay: 0.1000
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.3400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 107.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-# Mood Presets
-
-- type: audioPreset
- id: MoodHeaven
- density: 1.0000
- diffusion: 0.9400
- gain: 0.3162
- gainHf: 0.7943
- gainLf: 0.4467
- decayTime: 5.0400
- decayHfRatio: 1.1200
- decayLfRatio: 0.5600
- reflectionsGain: 0.2427
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0290
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0800
- modulationTime: 2.7420
- modulationDepth: 0.0500
- airAbsorptionGainHf: 0.9977
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: MoodHell
- density: 1.0000
- diffusion: 0.5700
- gain: 0.3162
- gainHf: 0.3548
- gainLf: 0.4467
- decayTime: 3.5700
- decayHfRatio: 0.4900
- decayLfRatio: 2.0000
- reflectionsGain: 0.0000
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.1100
- echoDepth: 0.0400
- modulationTime: 2.1090
- modulationDepth: 0.5200
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 139.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: MoodMemory
- density: 1.0000
- diffusion: 0.8500
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 0.3548
- decayTime: 4.0600
- decayHfRatio: 0.8200
- decayLfRatio: 0.5600
- reflectionsGain: 0.0398
- reflectionsDelay: 0.0000
- reflectionsPan: 0,0,0
- lateReverbGain: 1.1220
- lateReverbDelay: 0.0000
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.4740
- modulationDepth: 0.4500
- airAbsorptionGainHf: 0.9886
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-# Driving Presets
-
-- type: audioPreset
- id: DrivingCommentator
- density: 1.0000
- diffusion: 0.0000
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 0.5012
- decayTime: 2.4200
- decayHfRatio: 0.8800
- decayLfRatio: 0.6800
- reflectionsGain: 0.1995
- reflectionsDelay: 0.0930
- reflectionsPan: 0,0,0
- lateReverbGain: 0.2512
- lateReverbDelay: 0.0170
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 1.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9886
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: DrivingPitGarage
- density: 0.4287
- diffusion: 0.5900
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 0.5623
- decayTime: 1.7200
- decayHfRatio: 0.9300
- decayLfRatio: 0.8700
- reflectionsGain: 0.5623
- reflectionsDelay: 0.0000
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0160
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.1100
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: DrivingInCarRacer
- density: 0.0832
- diffusion: 0.8000
- gain: 0.3162
- gainHf: 1.0000
- gainLf: 0.7943
- decayTime: 0.1700
- decayHfRatio: 2.0000
- decayLfRatio: 0.4100
- reflectionsGain: 1.7783
- reflectionsDelay: 0.0070
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7079
- lateReverbDelay: 0.0150
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 10268.2002
- lfReference: 251.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: DrivingInCarSports
- density: 0.0832
- diffusion: 0.8000
- gain: 0.3162
- gainHf: 0.6310
- gainLf: 1.0000
- decayTime: 0.1700
- decayHfRatio: 0.7500
- decayLfRatio: 0.4100
- reflectionsGain: 1.0000
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 0.5623
- lateReverbDelay: 0.0000
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 10268.2002
- lfReference: 251.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: DrivingInCarLuxury
- density: 0.2560
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.1000
- gainLf: 0.5012
- decayTime: 0.1300
- decayHfRatio: 0.4100
- decayLfRatio: 0.4600
- reflectionsGain: 0.7943
- reflectionsDelay: 0.0100
- reflectionsPan: 0,0,0
- lateReverbGain: 1.5849
- lateReverbDelay: 0.0100
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 10268.2002
- lfReference: 251.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: DrivingFullGrandstand
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 0.2818
- gainLf: 0.6310
- decayTime: 3.0100
- decayHfRatio: 1.3700
- decayLfRatio: 1.2800
- reflectionsGain: 0.3548
- reflectionsDelay: 0.0900
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1778
- lateReverbDelay: 0.0490
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 10420.2002
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: DrivingEmptyGrandstand
- density: 1.0000
- diffusion: 1.0000
- gain: 0.3162
- gainHf: 1.0000
- gainLf: 0.7943
- decayTime: 4.6200
- decayHfRatio: 1.7500
- decayLfRatio: 1.4000
- reflectionsGain: 0.2082
- reflectionsDelay: 0.0900
- reflectionsPan: 0,0,0
- lateReverbGain: 0.2512
- lateReverbDelay: 0.0490
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 10420.2002
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: DrivingTunnel
- density: 1.0000
- diffusion: 0.8100
- gain: 0.3162
- gainHf: 0.3981
- gainLf: 0.8913
- decayTime: 3.4200
- decayHfRatio: 0.9400
- decayLfRatio: 1.3100
- reflectionsGain: 0.7079
- reflectionsDelay: 0.0510
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7079
- lateReverbDelay: 0.0470
- lateReverbPan: 0,0,0
- echoTime: 0.2140
- echoDepth: 0.0500
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 155.3000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# City Presets
-
-- type: audioPreset
- id: CityStreets
- density: 1.0000
- diffusion: 0.7800
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 0.8913
- decayTime: 1.7900
- decayHfRatio: 1.1200
- decayLfRatio: 0.9100
- reflectionsGain: 0.2818
- reflectionsDelay: 0.0460
- reflectionsPan: 0,0,0
- lateReverbGain: 0.1995
- lateReverbDelay: 0.0280
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.2000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CitySubway
- density: 1.0000
- diffusion: 0.7400
- gain: 0.3162
- gainHf: 0.7079
- gainLf: 0.8913
- decayTime: 3.0100
- decayHfRatio: 1.2300
- decayLfRatio: 0.9100
- reflectionsGain: 0.7079
- reflectionsDelay: 0.0460
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0280
- lateReverbPan: 0,0,0
- echoTime: 0.1250
- echoDepth: 0.2100
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CityMuseum
- density: 1.0000
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.1778
- gainLf: 0.1778
- decayTime: 3.2800
- decayHfRatio: 1.4000
- decayLfRatio: 0.5700
- reflectionsGain: 0.2512
- reflectionsDelay: 0.0390
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0340
- lateReverbPan: 0,0,0
- echoTime: 0.1300
- echoDepth: 0.1700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 107.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: CityLibrary
- density: 1.0000
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.2818
- gainLf: 0.0891
- decayTime: 2.7600
- decayHfRatio: 0.8900
- decayLfRatio: 0.4100
- reflectionsGain: 0.3548
- reflectionsDelay: 0.0290
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0200
- lateReverbPan: 0,0,0
- echoTime: 0.1300
- echoDepth: 0.1700
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9943
- hfReference: 2854.3999
- lfReference: 107.5000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
-
-- type: audioPreset
- id: CityUnderpass
- density: 1.0000
- diffusion: 0.8200
- gain: 0.3162
- gainHf: 0.4467
- gainLf: 0.8913
- decayTime: 3.5700
- decayHfRatio: 1.1200
- decayLfRatio: 0.9100
- reflectionsGain: 0.3981
- reflectionsDelay: 0.0590
- reflectionsPan: 0,0,0
- lateReverbGain: 0.8913
- lateReverbDelay: 0.0370
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.1400
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9920
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: CityAbandoned
- density: 1.0000
- diffusion: 0.6900
- gain: 0.3162
- gainHf: 0.7943
- gainLf: 0.8913
- decayTime: 3.2800
- decayHfRatio: 1.1700
- decayLfRatio: 0.9100
- reflectionsGain: 0.4467
- reflectionsDelay: 0.0440
- reflectionsPan: 0,0,0
- lateReverbGain: 0.2818
- lateReverbDelay: 0.0240
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.2000
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9966
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-# Misc. Presets
-
-- type: audioPreset
- id: DustyRoom
- density: 0.3645
- diffusion: 0.5600
- gain: 0.3162
- gainHf: 0.7943
- gainLf: 0.7079
- decayTime: 1.7900
- decayHfRatio: 0.3800
- decayLfRatio: 0.2100
- reflectionsGain: 0.5012
- reflectionsDelay: 0.0020
- reflectionsPan: 0,0,0
- lateReverbGain: 1.2589
- lateReverbDelay: 0.0060
- lateReverbPan: 0,0,0
- echoTime: 0.2020
- echoDepth: 0.0500
- modulationTime: 0.2500
- modulationDepth: 0.0000
- airAbsorptionGainHf: 0.9886
- hfReference: 13046.0000
- lfReference: 163.3000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: Chapel
- density: 1.0000
- diffusion: 0.8400
- gain: 0.3162
- gainHf: 0.5623
- gainLf: 1.0000
- decayTime: 4.6200
- decayHfRatio: 0.6400
- decayLfRatio: 1.2300
- reflectionsGain: 0.4467
- reflectionsDelay: 0.0320
- reflectionsPan: 0,0,0
- lateReverbGain: 0.7943
- lateReverbDelay: 0.0490
- lateReverbPan: 0,0,0
- echoTime: 0.2500
- echoDepth: 0.0000
- modulationTime: 0.2500
- modulationDepth: 0.1100
- airAbsorptionGainHf: 0.9943
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 1
-
-
-- type: audioPreset
- id: SmallWaterRoom
- density: 1.0000
- diffusion: 0.7000
- gain: 0.3162
- gainHf: 0.4477
- gainLf: 1.0000
- decayTime: 1.5100
- decayHfRatio: 1.2500
- decayLfRatio: 1.1400
- reflectionsGain: 0.8913
- reflectionsDelay: 0.0200
- reflectionsPan: 0,0,0
- lateReverbGain: 1.4125
- lateReverbDelay: 0.0300
- lateReverbPan: 0,0,0
- echoTime: 0.1790
- echoDepth: 0.1500
- modulationTime: 0.8950
- modulationDepth: 0.1900
- airAbsorptionGainHf: 0.9920
- hfReference: 5000.0000
- lfReference: 250.0000
- roomRolloffFactor: 0.0000
- decayHfLimit: 0
-
diff --git a/Resources/EnginePrototypes/entity.yml b/Resources/EnginePrototypes/entity.yml
deleted file mode 100644
index 0013afe62f4..00000000000
--- a/Resources/EnginePrototypes/entity.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-- type: entity
- id: Audio
- name: Audio
- description: Audio entity used by engine
- save: false
\ No newline at end of file
diff --git a/Robust.Client/Animations/AnimationTrackPlaySound.cs b/Robust.Client/Animations/AnimationTrackPlaySound.cs
index be5051a4d8f..1ffd5f20779 100644
--- a/Robust.Client/Animations/AnimationTrackPlaySound.cs
+++ b/Robust.Client/Animations/AnimationTrackPlaySound.cs
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
-using Robust.Client.Audio;
using Robust.Client.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
using Robust.Shared.Player;
namespace Robust.Client.Animations
@@ -39,12 +37,7 @@ public override (int KeyFrameIndex, float FramePlayingTime)
var keyFrame = KeyFrames[keyFrameIndex];
- var audioParams = keyFrame.AudioParamsFunc.Invoke();
- var audio = new SoundPathSpecifier(keyFrame.Resource)
- {
- Params = audioParams
- };
- IoCManager.Resolve().GetEntitySystem().PlayEntity(audio, Filter.Local(), entity, true);
+ SoundSystem.Play(keyFrame.Resource, Filter.Local(), entity, keyFrame.AudioParamsFunc.Invoke());
}
return (keyFrameIndex, playingTime);
diff --git a/Robust.Client/Audio/AudioManager.ALDisposeQueues.cs b/Robust.Client/Audio/AudioManager.ALDisposeQueues.cs
deleted file mode 100644
index c60448f07bf..00000000000
--- a/Robust.Client/Audio/AudioManager.ALDisposeQueues.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using System.Collections.Concurrent;
-using OpenTK.Audio.OpenAL;
-
-namespace Robust.Client.Audio;
-
-internal partial class AudioManager
-{
- // Used to track audio sources that were disposed in the finalizer thread,
- // so we need to properly send them off in the main thread.
- private readonly ConcurrentQueue<(int sourceHandle, int filterHandle)> _sourceDisposeQueue = new();
- private readonly ConcurrentQueue<(int sourceHandle, int filterHandle)> _bufferedSourceDisposeQueue = new();
- private readonly ConcurrentQueue _bufferDisposeQueue = new();
-
- public void FlushALDisposeQueues()
- {
- // Clear out finalized audio sources.
- while (_sourceDisposeQueue.TryDequeue(out var handles))
- {
- OpenALSawmill.Debug("Cleaning out source {0} which finalized in another thread.", handles.sourceHandle);
- if (IsEfxSupported) RemoveEfx(handles);
- AL.DeleteSource(handles.sourceHandle);
- _checkAlError();
- _audioSources.Remove(handles.sourceHandle);
- }
-
- // Clear out finalized buffered audio sources.
- while (_bufferedSourceDisposeQueue.TryDequeue(out var handles))
- {
- OpenALSawmill.Debug("Cleaning out buffered source {0} which finalized in another thread.", handles.sourceHandle);
- if (IsEfxSupported) RemoveEfx(handles);
- AL.DeleteSource(handles.sourceHandle);
- _checkAlError();
- _bufferedAudioSources.Remove(handles.sourceHandle);
- }
-
- // Clear out finalized audio buffers.
- while (_bufferDisposeQueue.TryDequeue(out var handle))
- {
- AL.DeleteBuffer(handle);
- _checkAlError();
- }
- }
-
- internal void DeleteSourceOnMainThread(int sourceHandle, int filterHandle)
- {
- _sourceDisposeQueue.Enqueue((sourceHandle, filterHandle));
- }
-
- internal void DeleteBufferedSourceOnMainThread(int bufferedSourceHandle, int filterHandle)
- {
- _bufferedSourceDisposeQueue.Enqueue((bufferedSourceHandle, filterHandle));
- }
-
- internal void DeleteAudioBufferOnMainThread(int bufferHandle)
- {
- _bufferDisposeQueue.Enqueue(bufferHandle);
- }
-}
diff --git a/Robust.Client/Audio/AudioManager.Public.cs b/Robust.Client/Audio/AudioManager.Public.cs
deleted file mode 100644
index 23a715d2fe6..00000000000
--- a/Robust.Client/Audio/AudioManager.Public.cs
+++ /dev/null
@@ -1,338 +0,0 @@
-using System;
-using System.IO;
-using System.Numerics;
-using System.Threading;
-using OpenTK.Audio.OpenAL;
-using Robust.Client.Audio.Sources;
-using Robust.Client.Graphics;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Maths;
-
-namespace Robust.Client.Audio;
-
-internal partial class AudioManager
-{
- private float _zOffset;
-
- public void SetZOffset(float offset)
- {
- _zOffset = offset;
- }
-
- ///
- public float GetAttenuationGain(float distance, float rolloffFactor, float referenceDistance, float maxDistance)
- {
- switch (_attenuation)
- {
- case Attenuation.LinearDistance:
- return 1 - rolloffFactor * (distance - referenceDistance) / (maxDistance - referenceDistance);
- case Attenuation.LinearDistanceClamped:
- distance = MathF.Max(referenceDistance, MathF.Min(distance, maxDistance));
- return 1 - rolloffFactor * (distance - referenceDistance) / (maxDistance - referenceDistance);
- default:
- // TODO: If you see this you can implement
- throw new NotImplementedException();
- }
- }
-
- public void InitializePostWindowing()
- {
- _gameThread = Thread.CurrentThread;
- InitializeAudio();
- }
-
- public void Shutdown()
- {
- DisposeAllAudio();
-
- if (_openALContext != ALContext.Null)
- {
- ALC.MakeContextCurrent(ALContext.Null);
-
- ALC.DestroyContext(_openALContext);
- }
-
- if (_openALDevice != IntPtr.Zero)
- {
- ALC.CloseDevice(_openALDevice);
- }
- }
-
- ///
- public void SetPosition(Vector2 position)
- {
- AL.Listener(ALListener3f.Position, position.X, position.Y, _zOffset);
- }
-
- ///
- public void SetRotation(Angle angle)
- {
- var vec = angle.ToVec();
-
- // Default orientation: at: (0, 0, -1) up: (0, 1, 0)
- var at = new OpenTK.Mathematics.Vector3(0f, 0f, -1f);
- var up = new OpenTK.Mathematics.Vector3(vec.Y, vec.X, 0f);
- AL.Listener(ALListenerfv.Orientation, new []{0, 0, -1, vec.X, vec.Y, 0});
- AL.Listener(ALListenerfv.Orientation, ref at, ref up);
- }
-
- ///
- public override AudioStream LoadAudioOggVorbis(Stream stream, string? name = null)
- {
- var vorbis = _readOggVorbis(stream);
-
- var buffer = AL.GenBuffer();
-
- ALFormat format;
- // NVorbis only supports loading into floats.
- // If this becomes a problem due to missing extension support (doubt it but ok),
- // check the git history, I originally used libvorbisfile which worked and loaded 16 bit LPCM.
- if (vorbis.Channels == 1)
- {
- format = ALFormat.MonoFloat32Ext;
- }
- else if (vorbis.Channels == 2)
- {
- format = ALFormat.StereoFloat32Ext;
- }
- else
- {
- throw new InvalidOperationException("Unable to load audio with more than 2 channels.");
- }
-
- unsafe
- {
- fixed (float* ptr = vorbis.Data.Span)
- {
- AL.BufferData(buffer, format, (IntPtr) ptr, vorbis.Data.Length * sizeof(float),
- (int) vorbis.SampleRate);
- }
- }
-
- _checkAlError();
-
- var handle = new ClydeHandle(_audioSampleBuffers.Count);
- _audioSampleBuffers.Add(new LoadedAudioSample(buffer));
- var length = TimeSpan.FromSeconds(vorbis.TotalSamples / (double) vorbis.SampleRate);
- return new AudioStream(handle, length, (int) vorbis.Channels, name, vorbis.Title, vorbis.Artist);
- }
-
- ///
- public override AudioStream LoadAudioWav(Stream stream, string? name = null)
- {
- var wav = _readWav(stream);
-
- var buffer = AL.GenBuffer();
-
- ALFormat format;
- if (wav.BitsPerSample == 16)
- {
- if (wav.NumChannels == 1)
- {
- format = ALFormat.Mono16;
- }
- else if (wav.NumChannels == 2)
- {
- format = ALFormat.Stereo16;
- }
- else
- {
- throw new InvalidOperationException("Unable to load audio with more than 2 channels.");
- }
- }
- else if (wav.BitsPerSample == 8)
- {
- if (wav.NumChannels == 1)
- {
- format = ALFormat.Mono8;
- }
- else if (wav.NumChannels == 2)
- {
- format = ALFormat.Stereo8;
- }
- else
- {
- throw new InvalidOperationException("Unable to load audio with more than 2 channels.");
- }
- }
- else
- {
- throw new InvalidOperationException("Unable to load wav with bits per sample different from 8 or 16");
- }
-
- unsafe
- {
- fixed (byte* ptr = wav.Data.Span)
- {
- AL.BufferData(buffer, format, (IntPtr) ptr, wav.Data.Length, wav.SampleRate);
- }
- }
-
- _checkAlError();
-
- var handle = new ClydeHandle(_audioSampleBuffers.Count);
- _audioSampleBuffers.Add(new LoadedAudioSample(buffer));
- var length = TimeSpan.FromSeconds(wav.Data.Length / (double) wav.BlockAlign / wav.SampleRate);
- return new AudioStream(handle, length, wav.NumChannels, name);
- }
-
- ///
- public override AudioStream LoadAudioRaw(ReadOnlySpan samples, int channels, int sampleRate, string? name = null)
- {
- var fmt = channels switch
- {
- 1 => ALFormat.Mono16,
- 2 => ALFormat.Stereo16,
- _ => throw new ArgumentOutOfRangeException(
- nameof(channels), "Only stereo and mono is currently supported")
- };
-
- var buffer = AL.GenBuffer();
- _checkAlError();
-
- unsafe
- {
- fixed (short* ptr = samples)
- {
- AL.BufferData(buffer, fmt, (IntPtr) ptr, samples.Length * sizeof(short), sampleRate);
- }
- }
-
- _checkAlError();
-
- var handle = new ClydeHandle(_audioSampleBuffers.Count);
- var length = TimeSpan.FromSeconds((double) samples.Length / channels / sampleRate);
- _audioSampleBuffers.Add(new LoadedAudioSample(buffer));
- return new AudioStream(handle, length, channels, name);
- }
-
- public void SetMasterVolume(float newVolume)
- {
- AL.Listener(ALListenerf.Gain, newVolume);
- }
-
- public void SetAttenuation(Attenuation attenuation)
- {
- switch (attenuation)
- {
- case Attenuation.NoAttenuation:
- AL.DistanceModel(ALDistanceModel.None);
- break;
- case Attenuation.InverseDistance:
- AL.DistanceModel(ALDistanceModel.InverseDistance);
- break;
- case Attenuation.InverseDistanceClamped:
- AL.DistanceModel(ALDistanceModel.InverseDistanceClamped);
- break;
- case Attenuation.LinearDistance:
- AL.DistanceModel(ALDistanceModel.LinearDistance);
- break;
- case Attenuation.LinearDistanceClamped:
- AL.DistanceModel(ALDistanceModel.LinearDistanceClamped);
- break;
- case Attenuation.ExponentDistance:
- AL.DistanceModel(ALDistanceModel.ExponentDistance);
- break;
- case Attenuation.ExponentDistanceClamped:
- AL.DistanceModel(ALDistanceModel.ExponentDistanceClamped);
- break;
- default:
- throw new ArgumentOutOfRangeException($"No implementation to set {attenuation.ToString()} for DistanceModel!");
- }
-
- _attenuation = attenuation;
- OpenALSawmill.Info($"Set audio attenuation to {attenuation.ToString()}");
- }
-
- internal void RemoveAudioSource(int handle)
- {
- _audioSources.Remove(handle);
- }
-
- internal void RemoveBufferedAudioSource(int handle)
- {
- _bufferedAudioSources.Remove(handle);
- }
-
- public IAudioSource? CreateAudioSource(AudioStream stream)
- {
- var source = AL.GenSource();
-
- if (!AL.IsSource(source))
- {
- OpenALSawmill.Error("Failed to generate source. Too many simultaneous audio streams? {0}", Environment.StackTrace);
- return null;
- }
-
- // ReSharper disable once PossibleInvalidOperationException
- // TODO: This really shouldn't be indexing based on the ClydeHandle...
- AL.Source(source, ALSourcei.Buffer, _audioSampleBuffers[(int) stream.ClydeHandle!.Value].BufferHandle);
-
- var audioSource = new AudioSource(this, source, stream);
- _audioSources.Add(source, new WeakReference(audioSource));
- return audioSource;
- }
-
- public IBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio=false)
- {
- var source = AL.GenSource();
-
- if (!AL.IsSource(source))
- {
- OpenALSawmill.Error("Failed to generate source. Too many simultaneous audio streams? {0}", Environment.StackTrace);
- }
-
- // ReSharper disable once PossibleInvalidOperationException
-
- var audioSource = new BufferedAudioSource(this, source, AL.GenBuffers(buffers), floatAudio);
- _bufferedAudioSources.Add(source, new WeakReference(audioSource));
- return audioSource;
- }
-
- ///
- public void StopAllAudio()
- {
- foreach (var source in _audioSources.Values)
- {
- if (source.TryGetTarget(out var target))
- {
- target.Playing = false;
- }
- }
-
- foreach (var source in _bufferedAudioSources.Values)
- {
- if (source.TryGetTarget(out var target))
- {
- target.Playing = false;
- }
- }
- }
-
- public void DisposeAllAudio()
- {
- // TODO: Do we even need to stop?
- foreach (var source in _audioSources.Values)
- {
- if (source.TryGetTarget(out var target))
- {
- target.Playing = false;
- target.Dispose();
- }
- }
-
- _audioSources.Clear();
-
- foreach (var source in _bufferedAudioSources.Values)
- {
- if (source.TryGetTarget(out var target))
- {
- target.Playing = false;
- target.Dispose();
- }
- }
-
- _bufferedAudioSources.Clear();
- }
-}
diff --git a/Robust.Client/Audio/AudioManager.cs b/Robust.Client/Audio/AudioManager.cs
deleted file mode 100644
index 3c89564733b..00000000000
--- a/Robust.Client/Audio/AudioManager.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using OpenTK.Audio.OpenAL;
-using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
-using Robust.Client.Audio.Sources;
-using Robust.Shared;
-using Robust.Shared.Audio;
-using Robust.Shared.Configuration;
-using Robust.Shared.Log;
-using Robust.Shared.Utility;
-
-namespace Robust.Client.Audio;
-
-internal sealed partial class AudioManager : SharedAudioManager, IAudioInternal
-{
- [Shared.IoC.Dependency] private readonly IConfigurationManager _cfg = default!;
- [Shared.IoC.Dependency] private readonly ILogManager _logMan = default!;
-
- private Thread? _gameThread;
-
- private ALDevice _openALDevice;
- private ALContext _openALContext;
-
- private readonly List _audioSampleBuffers = new();
-
- private readonly Dictionary> _audioSources =
- new();
-
- private readonly Dictionary> _bufferedAudioSources =
- new();
-
- private readonly HashSet _alcDeviceExtensions = new();
- private readonly HashSet _alContextExtensions = new();
- private Attenuation _attenuation;
-
- public bool HasAlDeviceExtension(string extension) => _alcDeviceExtensions.Contains(extension);
- public bool HasAlContextExtension(string extension) => _alContextExtensions.Contains(extension);
-
- internal bool IsEfxSupported;
-
- internal ISawmill OpenALSawmill = default!;
-
- private void _audioCreateContext()
- {
- unsafe
- {
- _openALContext = ALC.CreateContext(_openALDevice, (int*) 0);
- }
-
- ALC.MakeContextCurrent(_openALContext);
- _checkAlcError(_openALDevice);
- _checkAlError();
-
- // Load up AL context extensions.
- var s = ALC.GetString(ALDevice.Null, AlcGetString.Extensions) ?? "";
- foreach (var extension in s.Split(' '))
- {
- _alContextExtensions.Add(extension);
- }
-
- OpenALSawmill.Debug("OpenAL Vendor: {0}", AL.Get(ALGetString.Vendor));
- OpenALSawmill.Debug("OpenAL Renderer: {0}", AL.Get(ALGetString.Renderer));
- OpenALSawmill.Debug("OpenAL Version: {0}", AL.Get(ALGetString.Version));
- }
-
- private bool _audioOpenDevice()
- {
- var preferredDevice = _cfg.GetCVar(CVars.AudioDevice);
-
- // Open device.
- if (!string.IsNullOrEmpty(preferredDevice))
- {
- _openALDevice = ALC.OpenDevice(preferredDevice);
- if (_openALDevice == IntPtr.Zero)
- {
- OpenALSawmill.Warning("Unable to open preferred audio device '{0}': {1}. Falling back default.",
- preferredDevice, ALC.GetError(ALDevice.Null));
-
- _openALDevice = ALC.OpenDevice(null);
- }
- }
- else
- {
- _openALDevice = ALC.OpenDevice(null);
- }
-
- _checkAlcError(_openALDevice);
-
- if (_openALDevice == IntPtr.Zero)
- {
- OpenALSawmill.Error("Unable to open OpenAL device! {1}", ALC.GetError(ALDevice.Null));
- return false;
- }
-
- // Load up ALC extensions.
- var s = ALC.GetString(_openALDevice, AlcGetString.Extensions) ?? "";
- foreach (var extension in s.Split(' '))
- {
- _alcDeviceExtensions.Add(extension);
- }
- return true;
- }
-
- private void InitializeAudio()
- {
- OpenALSawmill = _logMan.GetSawmill("clyde.oal");
-
- if (!_audioOpenDevice())
- return;
-
- // Create OpenAL context.
- _audioCreateContext();
-
- IsEfxSupported = HasAlDeviceExtension("ALC_EXT_EFX");
-
- _cfg.OnValueChanged(CVars.AudioMasterVolume, SetMasterVolume, true);
- }
-
- internal bool IsMainThread()
- {
- return Thread.CurrentThread == _gameThread;
- }
-
- private static void RemoveEfx((int sourceHandle, int filterHandle) handles)
- {
- if (handles.filterHandle != 0)
- EFX.DeleteFilter(handles.filterHandle);
- }
-
- private void _checkAlcError(ALDevice device,
- [CallerMemberName] string callerMember = "",
- [CallerLineNumber] int callerLineNumber = -1)
- {
- var error = ALC.GetError(device);
- if (error != AlcError.NoError)
- {
- OpenALSawmill.Error("[{0}:{1}] ALC error: {2}", callerMember, callerLineNumber, error);
- }
- }
-
- public void _checkAlError([CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLineNumber = -1)
- {
- var error = AL.GetError();
- if (error != ALError.NoError)
- {
- OpenALSawmill.Error("[{0}:{1}] AL error: {2}", callerMember, callerLineNumber, error);
- }
- }
-
- private sealed class LoadedAudioSample
- {
- public readonly int BufferHandle;
-
- public LoadedAudioSample(int bufferHandle)
- {
- BufferHandle = bufferHandle;
- }
- }
-}
diff --git a/Robust.Client/Audio/AudioOverlay.cs b/Robust.Client/Audio/AudioOverlay.cs
deleted file mode 100644
index c6bb24e75ca..00000000000
--- a/Robust.Client/Audio/AudioOverlay.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-using System.Numerics;
-using System.Text;
-using Robust.Client.GameObjects;
-using Robust.Client.Graphics;
-using Robust.Client.Player;
-using Robust.Client.ResourceManagement;
-using Robust.Shared.Audio;
-using Robust.Shared.Enums;
-using Robust.Shared.GameObjects;
-using Robust.Shared.Map;
-using Robust.Shared.Maths;
-using AudioComponent = Robust.Shared.Audio.Components.AudioComponent;
-
-namespace Robust.Client.Audio;
-
-///
-/// Debug overlay for audio.
-///
-public sealed class AudioOverlay : Overlay
-{
- public override OverlaySpace Space => OverlaySpace.ScreenSpace;
-
- private IEntityManager _entManager;
- private IPlayerManager _playerManager;
- private AudioSystem _audio;
- private SharedTransformSystem _transform;
-
- private Font _font;
-
- public AudioOverlay(IEntityManager entManager, IPlayerManager playerManager, IClientResourceCache cache, AudioSystem audio, SharedTransformSystem transform)
- {
- _entManager = entManager;
- _playerManager = playerManager;
- _audio = audio;
- _transform = transform;
-
- _font = new VectorFont(cache.GetResource("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
- }
-
- protected internal override void Draw(in OverlayDrawArgs args)
- {
- var localPlayer = _playerManager.LocalPlayer?.ControlledEntity;
-
- if (args.ViewportControl == null || localPlayer == null)
- return;
-
- var screenHandle = args.ScreenHandle;
- var output = new StringBuilder();
- var listenerPos = _entManager.GetComponent(localPlayer.Value).MapPosition;
-
- if (listenerPos.MapId != args.MapId)
- return;
-
- var query = _entManager.AllEntityQueryEnumerator();
-
- while (query.MoveNext(out var uid, out var comp))
- {
- var mapId = MapId.Nullspace;
- var audioPos = Vector2.Zero;
-
- if (_entManager.TryGetComponent(uid, out var xform))
- {
- mapId = xform.MapID;
- audioPos = _transform.GetWorldPosition(uid);
- }
-
- if (mapId != args.MapId)
- continue;
-
- var screenPos = args.ViewportControl.WorldToScreen(audioPos);
- var distance = audioPos - listenerPos.Position;
- var posOcclusion = _audio.GetOcclusion(uid, listenerPos, distance, distance.Length());
-
- output.Clear();
- output.AppendLine("Audio Source");
- output.AppendLine("Runtime:");
- output.AppendLine($"- Occlusion: {posOcclusion:0.0000}");
- output.AppendLine("Params:");
- output.AppendLine($"- Volume: {comp.Volume:0.0000}");
- output.AppendLine($"- Reference distance: {comp.ReferenceDistance}");
- output.AppendLine($"- Max distance: {comp.MaxDistance}");
- var outputText = output.ToString().Trim();
- var dimensions = screenHandle.GetDimensions(_font, outputText, 1f);
- var buffer = new Vector2(3f, 3f);
- screenHandle.DrawRect(new UIBox2(screenPos - buffer, screenPos + dimensions + buffer), new Color(39, 39, 48));
- screenHandle.DrawString(_font, screenPos, outputText);
- }
- }
-}
diff --git a/Robust.Shared/Audio/AudioStream.cs b/Robust.Client/Audio/AudioStream.cs
similarity index 51%
rename from Robust.Shared/Audio/AudioStream.cs
rename to Robust.Client/Audio/AudioStream.cs
index a5ff7399347..605e5f76056 100644
--- a/Robust.Shared/Audio/AudioStream.cs
+++ b/Robust.Client/Audio/AudioStream.cs
@@ -1,21 +1,18 @@
using System;
-using Robust.Shared.Graphics;
+using Robust.Client.Graphics;
-namespace Robust.Shared.Audio;
+namespace Robust.Client.Audio;
-///
-/// Has the metadata for a particular audio stream as well as the relevant internal handle to it.
-///
public sealed class AudioStream
{
public TimeSpan Length { get; }
- internal IClydeHandle? ClydeHandle { get; }
+ internal ClydeHandle? ClydeHandle { get; }
public string? Name { get; }
public string? Title { get; }
public string? Artist { get; }
public int ChannelCount { get; }
- internal AudioStream(IClydeHandle? handle, TimeSpan length, int channelCount, string? name = null, string? title = null, string? artist = null)
+ internal AudioStream(ClydeHandle handle, TimeSpan length, int channelCount, string? name = null, string? title = null, string? artist = null)
{
ClydeHandle = handle;
Length = length;
diff --git a/Robust.Client/Audio/AudioSystem.Effects.cs b/Robust.Client/Audio/AudioSystem.Effects.cs
deleted file mode 100644
index 35706e4d768..00000000000
--- a/Robust.Client/Audio/AudioSystem.Effects.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
-using Robust.Client.Audio.Effects;
-using Robust.Shared.Audio.Components;
-using Robust.Shared.GameObjects;
-
-namespace Robust.Client.Audio;
-
-public sealed partial class AudioSystem
-{
- protected override void InitializeEffect()
- {
- base.InitializeEffect();
- SubscribeLocalEvent(OnEffectAdd);
- SubscribeLocalEvent(OnEffectShutdown);
-
- SubscribeLocalEvent(OnAuxiliaryAdd);
- SubscribeLocalEvent(OnAuxiliaryAuto);
- }
-
- private void OnEffectAdd(EntityUid uid, AudioEffectComponent component, ComponentAdd args)
- {
- var effect = new AudioEffect(_audio);
- component.Effect = effect;
- }
-
- private void OnEffectShutdown(EntityUid uid, AudioEffectComponent component, ComponentShutdown args)
- {
- if (component.Effect is AudioEffect effect)
- {
- effect.Dispose();
- }
- }
-
- private void OnAuxiliaryAdd(EntityUid uid, AudioAuxiliaryComponent component, ComponentAdd args)
- {
- component.Auxiliary = new AuxiliaryAudio();
- }
-
- private void OnAuxiliaryAuto(EntityUid uid, AudioAuxiliaryComponent component, ref AfterAutoHandleStateEvent args)
- {
- if (TryComp(component.Effect, out var effectComp))
- {
- component.Auxiliary.SetEffect(effectComp.Effect);
- }
- else
- {
- component.Auxiliary.SetEffect(null);
- }
- }
-
- public override void SetAuxiliary(EntityUid uid, AudioComponent audio, EntityUid? auxUid)
- {
- base.SetAuxiliary(uid, audio, auxUid);
- if (TryComp(audio.Auxiliary, out var auxComp))
- {
- audio.Source.SetAuxiliary(auxComp.Auxiliary);
- }
- else
- {
- audio.Source.SetAuxiliary(null);
- }
- }
-
- public override void SetEffect(EntityUid auxUid, AudioAuxiliaryComponent aux, EntityUid? effectUid)
- {
- base.SetEffect(auxUid, aux, effectUid);
- if (TryComp(aux.Effect, out var effectComp))
- {
- aux.Auxiliary.SetEffect(effectComp.Effect);
- }
- else
- {
- aux.Auxiliary.SetEffect(null);
- }
- }
-}
diff --git a/Robust.Client/Audio/AudioSystem.cs b/Robust.Client/Audio/AudioSystem.cs
deleted file mode 100644
index b0fabaf9e1c..00000000000
--- a/Robust.Client/Audio/AudioSystem.cs
+++ /dev/null
@@ -1,596 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Numerics;
-using System.Threading.Tasks;
-using Robust.Client.GameObjects;
-using Robust.Client.Graphics;
-using Robust.Client.ResourceManagement;
-using Robust.Shared;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Components;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Exceptions;
-using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-using Robust.Shared.Map;
-using Robust.Shared.Map.Components;
-using Robust.Shared.Physics;
-using Robust.Shared.Physics.Components;
-using Robust.Shared.Physics.Systems;
-using Robust.Shared.Player;
-using Robust.Shared.Replays;
-using Robust.Shared.ResourceManagement.ResourceTypes;
-using Robust.Shared.Threading;
-using Robust.Shared.Utility;
-using AudioComponent = Robust.Shared.Audio.Components.AudioComponent;
-
-namespace Robust.Client.Audio;
-
-public sealed partial class AudioSystem : SharedAudioSystem
-{
- /*
- * There's still a lot more OpenAL can do in terms of filters, auxiliary slots, etc.
- * but exposing the whole thing in an easy way is a lot of effort.
- */
-
- [Dependency] private readonly IReplayRecordingManager _replayRecording = default!;
- [Dependency] private readonly IEyeManager _eyeManager = default!;
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
- [Dependency] private readonly IMapManager _mapManager = default!;
- [Dependency] private readonly IParallelManager _parMan = default!;
- [Dependency] private readonly IRuntimeLog _runtimeLog = default!;
- [Dependency] private readonly IAudioInternal _audio = default!;
- [Dependency] private readonly SharedTransformSystem _xformSys = default!;
- [Dependency] private readonly SharedPhysicsSystem _physics = default!;
-
- ///
- /// Per-tick cache of relevant streams.
- ///
- private readonly List<(EntityUid Entity, AudioComponent Component, TransformComponent Xform)> _streams = new();
- private EntityUid? _listenerGrid;
-
- private EntityQuery _gridQuery;
- private EntityQuery _physicsQuery;
- private EntityQuery _xformQuery;
-
- private float _maxRayLength;
-
- ///
- public override void Initialize()
- {
- base.Initialize();
-
- UpdatesOutsidePrediction = true;
- // Need to run after Eye updates so we have an accurate listener position.
- UpdatesAfter.Add(typeof(EyeSystem));
-
- _gridQuery = GetEntityQuery();
- _physicsQuery = GetEntityQuery();
- _xformQuery = GetEntityQuery();
-
- SubscribeLocalEvent(OnAudioStartup);
- SubscribeLocalEvent(OnAudioShutdown);
- SubscribeLocalEvent(OnAudioPaused);
- SubscribeLocalEvent(OnAudioState);
-
- // Replay stuff
- SubscribeNetworkEvent(OnGlobalAudio);
- SubscribeNetworkEvent(OnEntityAudio);
- SubscribeNetworkEvent(OnEntityCoordinates);
-
- CfgManager.OnValueChanged(CVars.AudioAttenuation, OnAudioAttenuation, true);
- CfgManager.OnValueChanged(CVars.AudioRaycastLength, OnRaycastLengthChanged, true);
- }
-
- private void OnAudioState(EntityUid uid, AudioComponent component, ref AfterAutoHandleStateEvent args)
- {
- ApplyAudioParams(component.Params, component);
- component.Source.Global = component.Global;
-
- if (TryComp(component.Auxiliary, out var auxComp))
- {
- component.Source.SetAuxiliary(auxComp.Auxiliary);
- }
- else
- {
- component.Source.SetAuxiliary(null);
- }
- }
-
- ///
- /// Sets the volume for the entire game.
- ///
- public void SetMasterVolume(float value)
- {
- _audio.SetMasterVolume(value);
- }
-
- protected override void SetZOffset(float value)
- {
- base.SetZOffset(value);
- _audio.SetZOffset(value);
- }
-
- public override void Shutdown()
- {
- CfgManager.UnsubValueChanged(CVars.AudioAttenuation, OnAudioAttenuation);
- CfgManager.UnsubValueChanged(CVars.AudioRaycastLength, OnRaycastLengthChanged);
- base.Shutdown();
- }
-
- private void OnAudioPaused(EntityUid uid, AudioComponent component, ref EntityPausedEvent args)
- {
- component.Pause();
- }
-
- protected override void OnAudioUnpaused(EntityUid uid, AudioComponent component, ref EntityUnpausedEvent args)
- {
- base.OnAudioUnpaused(uid, component, ref args);
- component.StartPlaying();
- }
-
- private void OnAudioStartup(EntityUid uid, AudioComponent component, ComponentStartup args)
- {
- if (!Timing.ApplyingState && !Timing.IsFirstTimePredicted)
- {
- return;
- }
-
- if (!TryGetAudio(component.FileName, out var audioResource))
- {
- Log.Error($"Error creating audio source for {audioResource}, can't find file {component.FileName}");
- component.Source = new DummyAudioSource();
- return;
- }
-
- var source = _audio.CreateAudioSource(audioResource);
-
- if (source == null)
- {
- Log.Error($"Error creating audio source for {audioResource}");
- DebugTools.Assert(false);
- source = new DummyAudioSource();
- }
-
- // Need to set all initial data for first frame.
- component.Source = source;
- ApplyAudioParams(component.Params, component);
- component.Global = component.Global;
- // Don't play until first frame so occlusion etc. are correct.
- component.Gain = 0f;
-
- // If audio came into range then start playback at the correct position.
- var offset = (Timing.CurTime - component.AudioStart).TotalSeconds % GetAudioLength(component.FileName).TotalSeconds;
-
- if (offset != 0)
- {
- component.PlaybackPosition = (float) offset;
- }
- }
-
- private void OnAudioShutdown(EntityUid uid, AudioComponent component, ComponentShutdown args)
- {
- // Breaks with prediction?
- component.Source.Dispose();
- }
-
- private void OnAudioAttenuation(int obj)
- {
- _audio.SetAttenuation((Attenuation) obj);
- }
-
- private void OnRaycastLengthChanged(float value)
- {
- _maxRayLength = value;
- }
-
- public override void FrameUpdate(float frameTime)
- {
- var eye = _eyeManager.CurrentEye;
- _audio.SetRotation(eye.Rotation);
- _audio.SetPosition(eye.Position.Position);
-
- var ourPos = eye.Position;
- var opts = new ParallelOptions { MaxDegreeOfParallelism = _parMan.ParallelProcessCount };
-
- var query = AllEntityQuery();
- _streams.Clear();
-
- while (query.MoveNext(out var uid, out var comp, out var xform))
- {
- _streams.Add((uid, comp, xform));
- }
-
- _mapManager.TryFindGridAt(ourPos, out var gridUid, out _);
- _listenerGrid = gridUid == EntityUid.Invalid ? null : gridUid;
-
- try
- {
- Parallel.ForEach(_streams, opts, comp => ProcessStream(comp.Entity, comp.Component, comp.Xform, ourPos));
- }
- catch (Exception e)
- {
- Log.Error($"Caught exception while processing entity streams.");
- _runtimeLog.LogException(e, $"{nameof(AudioSystem)}.{nameof(FrameUpdate)}");
- }
- }
-
- private void ProcessStream(EntityUid entity, AudioComponent component, TransformComponent xform, MapCoordinates listener)
- {
- // TODO:
- // I Originally tried to be fancier here but it caused audio issues so just trying
- // to replicate the old behaviour for now.
- if (!component.Started)
- {
- component.Started = true;
- component.StartPlaying();
- }
-
- // If it's global but on another map (that isn't nullspace) then stop playing it.
- if (component.Global)
- {
- if (xform.MapID != MapId.Nullspace && listener.MapId != xform.MapID)
- {
- component.Gain = 0f;
- return;
- }
-
- // Resume playing.
- component.Volume = component.Params.Volume;
- return;
- }
-
- // Non-global sounds, stop playing if on another map.
- // Not relevant to us.
- if (listener.MapId != xform.MapID)
- {
- component.Gain = 0f;
- return;
- }
-
- Vector2 worldPos;
- var gridUid = xform.ParentUid;
-
- // Handle grid audio differently by using nearest-edge instead of entity centre.
- if (_gridQuery.HasComponent(gridUid))
- {
- // It's our grid so max volume.
- if (_listenerGrid == gridUid)
- {
- component.Volume = component.Params.Volume;
- component.Occlusion = 0f;
- component.Position = listener.Position;
- return;
- }
-
- // TODO: Need a grid-optimised version because this is gonna be expensive.
- // Just to avoid clipping on and off grid or nearestPoint changing we'll
- // always set the sound to listener's pos, we'll just manually do gain ourselves.
- if (_physics.TryGetNearest(gridUid, listener, out _, out var gridDistance))
- {
- // Out of range
- if (gridDistance > component.MaxDistance)
- {
- component.Gain = 0f;
- return;
- }
-
- var paramsGain = MathF.Pow(10, component.Params.Volume / 10);
-
- // Thought I'd never have to manually calculate gain again but this is the least
- // unpleasant audio I could get at the moment.
- component.Gain = paramsGain * _audio.GetAttenuationGain(
- gridDistance,
- component.Params.RolloffFactor,
- component.Params.ReferenceDistance,
- component.Params.MaxDistance);
- component.Position = listener.Position;
- return;
- }
-
- // Can't get nearest point so don't play anymore.
- component.Gain = 0f;
- return;
- }
-
- worldPos = _xformSys.GetWorldPosition(entity);
- component.Volume = component.Params.Volume;
-
- // Max distance check
- var delta = worldPos - listener.Position;
- var distance = delta.Length();
-
- // Out of range so just clip it for us.
- if (distance > component.MaxDistance)
- {
- // Still keeps the source playing, just with no volume.
- component.Gain = 0f;
- return;
- }
-
- // Update audio occlusion
- var occlusion = GetOcclusion(entity, listener, delta, distance);
- component.Occlusion = occlusion;
-
- // Update audio positions.
- component.Position = worldPos;
-
- // Make race cars go NYYEEOOOOOMMMMM
- if (_physicsQuery.TryGetComponent(entity, out var physicsComp))
- {
- // This actually gets the tracked entity's xform & iterates up though the parents for the second time. Bit
- // inefficient.
- var velocity = _physics.GetMapLinearVelocity(entity, physicsComp, xform, _xformQuery, _physicsQuery);
- component.Velocity = velocity;
- }
- }
-
- internal float GetOcclusion(EntityUid entity, MapCoordinates listener, Vector2 delta, float distance)
- {
- float occlusion = 0;
-
- if (distance > 0.1)
- {
- var rayLength = MathF.Min(distance, _maxRayLength);
- var ray = new CollisionRay(listener.Position, delta / distance, OcclusionCollisionMask);
- occlusion = _physics.IntersectRayPenetration(listener.MapId, ray, rayLength, entity);
- }
-
- return occlusion;
- }
-
- private bool TryGetAudio(string filename, [NotNullWhen(true)] out AudioResource? audio)
- {
- if (_resourceCache.TryGetResource(new ResPath(filename), out audio))
- return true;
-
- Log.Error($"Server tried to play audio file {filename} which does not exist.");
- return false;
- }
-
- private bool TryCreateAudioSource(AudioStream stream, [NotNullWhen(true)] out IAudioSource? source)
- {
- if (!Timing.IsFirstTimePredicted)
- {
- source = null;
- Log.Error($"Tried to create audio source outside of prediction!");
- DebugTools.Assert(false);
- return false;
- }
-
- source = _audio.CreateAudioSource(stream);
- return source != null;
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayPvs(string filename, EntityCoordinates coordinates,
- AudioParams? audioParams = null)
- {
- return PlayStatic(filename, Filter.Local(), coordinates, true, audioParams);
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayPvs(string filename, EntityUid uid, AudioParams? audioParams = null)
- {
- return PlayEntity(filename, Filter.Local(), uid, true, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(SoundSpecifier? sound, EntityUid source, EntityUid? user, AudioParams? audioParams = null)
- {
- if (Timing.IsFirstTimePredicted || sound == null)
- return PlayEntity(sound, Filter.Local(), source, false, audioParams);
-
- return null; // uhh Lets hope predicted audio never needs to somehow store the playing audio....
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(SoundSpecifier? sound, EntityCoordinates coordinates, EntityUid? user, AudioParams? audioParams = null)
- {
- if (Timing.IsFirstTimePredicted || sound == null)
- return PlayStatic(sound, Filter.Local(), coordinates, false, audioParams);
-
- return null;
- }
-
- ///
- /// Play an audio file globally, without position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- ///
- private (EntityUid Entity, AudioComponent Component)? PlayGlobal(string filename, AudioParams? audioParams = null, bool recordReplay = true)
- {
- if (recordReplay && _replayRecording.IsRecording)
- {
- _replayRecording.RecordReplayMessage(new PlayAudioGlobalMessage
- {
- FileName = filename,
- AudioParams = audioParams ?? AudioParams.Default
- });
- }
-
- return TryGetAudio(filename, out var audio) ? PlayGlobal(audio, audioParams) : default;
- }
-
- ///
- /// Play an audio stream globally, without position.
- ///
- /// The audio stream to play.
- ///
- private (EntityUid Entity, AudioComponent Component)? PlayGlobal(AudioStream stream, AudioParams? audioParams = null)
- {
- var (entity, component) = CreateAndStartPlayingStream(audioParams, stream);
- component.Global = true;
- component.Source.Global = true;
- Dirty(entity, component);
- return (entity, component);
- }
-
- ///
- /// Play an audio file following an entity.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The entity "emitting" the audio.
- private (EntityUid Entity, AudioComponent Component)? PlayEntity(string filename, EntityUid entity, AudioParams? audioParams = null, bool recordReplay = true)
- {
- if (recordReplay && _replayRecording.IsRecording)
- {
- _replayRecording.RecordReplayMessage(new PlayAudioEntityMessage
- {
- FileName = filename,
- NetEntity = GetNetEntity(entity),
- AudioParams = audioParams ?? AudioParams.Default
- });
- }
-
- return TryGetAudio(filename, out var audio) ? PlayEntity(audio, entity, audioParams) : default;
- }
-
- ///
- /// Play an audio stream following an entity.
- ///
- /// The audio stream to play.
- /// The entity "emitting" the audio.
- ///
- private (EntityUid Entity, AudioComponent Component)? PlayEntity(AudioStream stream, EntityUid entity, AudioParams? audioParams = null)
- {
- var playing = CreateAndStartPlayingStream(audioParams, stream);
- _xformSys.SetCoordinates(playing.Entity, new EntityCoordinates(entity, Vector2.Zero));
-
- return playing;
- }
-
- ///
- /// Play an audio file at a static position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The coordinates at which to play the audio.
- ///
- private (EntityUid Entity, AudioComponent Component)? PlayStatic(string filename, EntityCoordinates coordinates, AudioParams? audioParams = null, bool recordReplay = true)
- {
- if (recordReplay && _replayRecording.IsRecording)
- {
- _replayRecording.RecordReplayMessage(new PlayAudioPositionalMessage
- {
- FileName = filename,
- Coordinates = GetNetCoordinates(coordinates),
- AudioParams = audioParams ?? AudioParams.Default
- });
- }
-
- return TryGetAudio(filename, out var audio) ? PlayStatic(audio, coordinates, audioParams) : default;
- }
-
- ///
- /// Play an audio stream at a static position.
- ///
- /// The audio stream to play.
- /// The coordinates at which to play the audio.
- ///
- private (EntityUid Entity, AudioComponent Component)? PlayStatic(AudioStream stream, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- var playing = CreateAndStartPlayingStream(audioParams, stream);
- _xformSys.SetCoordinates(playing.Entity, coordinates);
- return playing;
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string filename, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null)
- {
- return PlayGlobal(filename, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string filename, Filter playerFilter, EntityUid entity, bool recordReplay, AudioParams? audioParams = null)
- {
- return PlayEntity(filename, entity, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string filename, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null)
- {
- return PlayStatic(filename, coordinates, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string filename, ICommonSession recipient, AudioParams? audioParams = null)
- {
- return PlayGlobal(filename, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string filename, EntityUid recipient, AudioParams? audioParams = null)
- {
- return PlayGlobal(filename, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string filename, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
- {
- return PlayEntity(filename, uid, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string filename, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
- {
- return PlayEntity(filename, uid, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string filename, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- return PlayStatic(filename, coordinates, audioParams);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string filename, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- return PlayStatic(filename, coordinates, audioParams);
- }
-
- private (EntityUid Entity, AudioComponent Component) CreateAndStartPlayingStream(AudioParams? audioParams, AudioStream stream)
- {
- var audioP = audioParams ?? AudioParams.Default;
- var entity = EntityManager.CreateEntityUninitialized("Audio", MapCoordinates.Nullspace);
- var comp = SetupAudio(entity, stream.Name!, audioP);
- EntityManager.InitializeAndStartEntity(entity);
- var source = comp.Source;
-
- // TODO clamp the offset inside of SetPlaybackPosition() itself.
- var offset = audioP.PlayOffsetSeconds;
- offset = Math.Clamp(offset, 0f, (float) stream.Length.TotalSeconds - 0.01f);
- source.PlaybackPosition = offset;
-
- ApplyAudioParams(audioP, comp);
- comp.Params = audioP;
- source.StartPlaying();
- return (entity, comp);
- }
-
- ///
- /// Applies the audioparams to the underlying audio source.
- ///
- private void ApplyAudioParams(AudioParams audioParams, IAudioSource source)
- {
- source.Pitch = audioParams.Pitch;
- source.Volume = audioParams.Volume;
- source.RolloffFactor = audioParams.RolloffFactor;
- source.MaxDistance = audioParams.MaxDistance;
- source.ReferenceDistance = audioParams.ReferenceDistance;
- source.Looping = audioParams.Loop;
- }
-
- private void OnEntityCoordinates(PlayAudioPositionalMessage ev)
- {
- PlayStatic(ev.FileName, GetCoordinates(ev.Coordinates), ev.AudioParams, false);
- }
-
- private void OnEntityAudio(PlayAudioEntityMessage ev)
- {
- PlayEntity(ev.FileName, GetEntity(ev.NetEntity), ev.AudioParams, false);
- }
-
- private void OnGlobalAudio(PlayAudioGlobalMessage ev)
- {
- PlayGlobal(ev.FileName, ev.AudioParams, false);
- }
-}
diff --git a/Robust.Client/Audio/Effects/AudioEffect.cs b/Robust.Client/Audio/Effects/AudioEffect.cs
deleted file mode 100644
index 8e563ddab43..00000000000
--- a/Robust.Client/Audio/Effects/AudioEffect.cs
+++ /dev/null
@@ -1,455 +0,0 @@
-using System;
-using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.Maths;
-
-namespace Robust.Client.Audio.Effects;
-
-///
-internal sealed class AudioEffect : IAudioEffect
-{
- internal int Handle;
-
- private readonly IAudioInternal _master;
-
- public AudioEffect(IAudioInternal manager)
- {
- Handle = EFX.GenEffect();
- _master = manager;
- EFX.Effect(Handle, EffectInteger.EffectType, (int) EffectType.EaxReverb);
- }
-
- public void Dispose()
- {
- if (Handle != 0)
- {
- EFX.DeleteEffect(Handle);
- Handle = 0;
- }
- }
-
- private void _checkDisposed()
- {
- if (Handle == -1)
- {
- throw new ObjectDisposedException(nameof(AudioEffect));
- }
- }
-
- ///
- public float Density
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbDensity, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbDensity, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float Diffusion
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbDiffusion, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbDiffusion, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float Gain
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbGain, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbGain, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float GainHF
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbGainHF, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbGainHF, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float GainLF
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbGainLF, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbGainLF, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float DecayTime
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbDecayTime, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbDecayTime, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float DecayHFRatio
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbDecayHFRatio, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbDecayHFRatio, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float DecayLFRatio
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbDecayLFRatio, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbDecayLFRatio, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float ReflectionsGain
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbReflectionsGain, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbReflectionsGain, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float ReflectionsDelay
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbReflectionsDelay, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbReflectionsDelay, value);
- _master._checkAlError();
- }
- }
-
- ///
- public Vector3 ReflectionsPan
- {
- get
- {
- _checkDisposed();
- var value = EFX.GetEffect(Handle, EffectVector3.EaxReverbReflectionsPan);
- _master._checkAlError();
- return new Vector3(value.X, value.Z, value.Y);
- }
- set
- {
- _checkDisposed();
- var openVec = new OpenTK.Mathematics.Vector3(value.X, value.Y, value.Z);
- EFX.Effect(Handle, EffectVector3.EaxReverbReflectionsPan, ref openVec);
- _master._checkAlError();
- }
- }
-
- ///
- public float LateReverbGain
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbLateReverbGain, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbLateReverbGain, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float LateReverbDelay
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbLateReverbDelay, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbLateReverbDelay, value);
- _master._checkAlError();
- }
- }
-
- ///
- public Vector3 LateReverbPan
- {
- get
- {
- _checkDisposed();
- var value = EFX.GetEffect(Handle, EffectVector3.EaxReverbLateReverbPan);
- _master._checkAlError();
- return new Vector3(value.X, value.Z, value.Y);
- }
- set
- {
- _checkDisposed();
- var openVec = new OpenTK.Mathematics.Vector3(value.X, value.Y, value.Z);
- EFX.Effect(Handle, EffectVector3.EaxReverbLateReverbPan, ref openVec);
- _master._checkAlError();
- }
- }
-
- ///
- public float EchoTime
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbEchoTime, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbEchoTime, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float EchoDepth
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbEchoDepth, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbEchoDepth, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float ModulationTime
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbModulationTime, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbModulationTime, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float ModulationDepth
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbModulationDepth, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbModulationDepth, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float AirAbsorptionGainHF
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbAirAbsorptionGainHF, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbAirAbsorptionGainHF, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float HFReference
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbHFReference, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbHFReference, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float LFReference
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbLFReference, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbLFReference, value);
- _master._checkAlError();
- }
- }
-
- ///
- public float RoomRolloffFactor
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectFloat.EaxReverbRoomRolloffFactor, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectFloat.EaxReverbRoomRolloffFactor, value);
- _master._checkAlError();
- }
- }
-
- ///
- public int DecayHFLimit
- {
- get
- {
- _checkDisposed();
- EFX.GetEffect(Handle, EffectInteger.EaxReverbDecayHFLimit, out var value);
- _master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- EFX.Effect(Handle, EffectInteger.EaxReverbDecayHFLimit, value);
- _master._checkAlError();
- }
- }
-}
diff --git a/Robust.Client/Audio/Effects/AuxiliaryAudio.cs b/Robust.Client/Audio/Effects/AuxiliaryAudio.cs
deleted file mode 100644
index a638a390bb4..00000000000
--- a/Robust.Client/Audio/Effects/AuxiliaryAudio.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
-using Robust.Shared.Audio.Effects;
-
-namespace Robust.Client.Audio.Effects;
-
-///
-internal sealed class AuxiliaryAudio : IAuxiliaryAudio
-{
- internal int Handle = EFX.GenAuxiliaryEffectSlot();
-
- public void Dispose()
- {
- if (Handle != -1)
- {
- EFX.DeleteAuxiliaryEffectSlot(Handle);
- Handle = -1;
- }
- }
-
- ///
- public void SetEffect(IAudioEffect? effect)
- {
- if (effect is AudioEffect audEffect)
- {
- EFX.AuxiliaryEffectSlot(Handle, EffectSlotInteger.Effect, audEffect.Handle);
- }
- else
- {
- EFX.AuxiliaryEffectSlot(Handle, EffectSlotInteger.Effect, 0);
- }
- }
-}
diff --git a/Robust.Client/Audio/Midi/IMidiRenderer.cs b/Robust.Client/Audio/Midi/IMidiRenderer.cs
index 216fe2c09d2..96cf7a2f4bb 100644
--- a/Robust.Client/Audio/Midi/IMidiRenderer.cs
+++ b/Robust.Client/Audio/Midi/IMidiRenderer.cs
@@ -3,7 +3,6 @@
using System.Collections.Generic;
using Robust.Client.Graphics;
using Robust.Shared.Audio.Midi;
-using Robust.Shared.Audio.Sources;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
@@ -21,7 +20,7 @@ public interface IMidiRenderer : IDisposable
///
/// The buffered audio source of this renderer.
///
- internal IBufferedAudioSource Source { get; }
+ internal IClydeBufferedAudioSource Source { get; }
///
/// Whether this renderer has been disposed or not.
diff --git a/Robust.Client/Audio/Midi/MidiManager.cs b/Robust.Client/Audio/Midi/MidiManager.cs
index a3b0363461e..19d827aed7d 100644
--- a/Robust.Client/Audio/Midi/MidiManager.cs
+++ b/Robust.Client/Audio/Midi/MidiManager.cs
@@ -10,7 +10,6 @@
using Robust.Client.ResourceManagement;
using Robust.Shared;
using Robust.Shared.Asynchronous;
-using Robust.Shared.Audio;
using Robust.Shared.Audio.Midi;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
@@ -42,10 +41,10 @@ internal sealed partial class MidiManager : IMidiManager
[ViewVariables] private TimeSpan _nextPositionUpdate = TimeSpan.Zero;
[Dependency] private readonly IEyeManager _eyeManager = default!;
- [Dependency] private readonly IResourceManager _resourceManager = default!;
+ [Dependency] private readonly IResourceCacheInternal _resourceManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IConfigurationManager _cfgMan = default!;
- [Dependency] private readonly IAudioInternal _audio = default!;
+ [Dependency] private readonly IClydeAudio _clydeAudio = default!;
[Dependency] private readonly ITaskManager _taskManager = default!;
[Dependency] private readonly ILogManager _logger = default!;
[Dependency] private readonly IParallelManager _parallel = default!;
@@ -274,7 +273,7 @@ private void LoggerDelegate(NFluidsynth.Logger.LogLevel level, string message, I
{
soundfontLoader.SetCallbacks(_soundfontLoaderCallbacks);
- var renderer = new MidiRenderer(_settings!, soundfontLoader, mono, this, _audio, _taskManager, _midiSawmill);
+ var renderer = new MidiRenderer(_settings!, soundfontLoader, mono, this, _clydeAudio, _taskManager, _midiSawmill);
_midiSawmill.Debug($"Loading fallback soundfont {FallbackSoundfont}");
// Since the last loaded soundfont takes priority, we load the fallback soundfont before the soundfont.
@@ -352,7 +351,7 @@ private void LoggerDelegate(NFluidsynth.Logger.LogLevel level, string message, I
renderer.LoadSoundfont(file.ToString());
}
- renderer.Source.Volume = _volume;
+ renderer.Source.SetVolume(Volume);
lock (_renderers)
{
@@ -375,7 +374,6 @@ public void FrameUpdate(float frameTime)
// Update positions of streams every frame.
// This has a lot of code duplication with AudioSystem.FrameUpdate(), and they should probably be combined somehow.
- // so TRUE
lock (_renderers)
{
@@ -417,13 +415,11 @@ private void UpdateRenderer(IMidiRenderer renderer, EntityQuery _rendererState;
- public IBufferedAudioSource Source { get; set; }
- IBufferedAudioSource IMidiRenderer.Source => Source;
+ public IClydeBufferedAudioSource Source { get; set; }
+ IClydeBufferedAudioSource IMidiRenderer.Source => Source;
[ViewVariables]
public bool Disposed { get; private set; } = false;
@@ -249,7 +247,7 @@ public IMidiRenderer? Master
public event Action? OnMidiPlayerFinished;
internal MidiRenderer(Settings settings, SoundFontLoader soundFontLoader, bool mono,
- IMidiManager midiManager, IAudioInternal clydeAudio, ITaskManager taskManager, ISawmill midiSawmill)
+ IMidiManager midiManager, IClydeAudio clydeAudio, ITaskManager taskManager, ISawmill midiSawmill)
{
_midiManager = midiManager;
_taskManager = taskManager;
@@ -490,7 +488,7 @@ private void Render(int length = SampleRate / 250)
}
}
- Source.StartPlaying();
+ if (!Source.IsPlaying) Source.StartPlaying();
}
public void ApplyState(MidiRendererState state, bool filterChannels = false)
diff --git a/Robust.Client/Audio/ShowAudioCommand.cs b/Robust.Client/Audio/ShowAudioCommand.cs
deleted file mode 100644
index 897db432a7a..00000000000
--- a/Robust.Client/Audio/ShowAudioCommand.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using Robust.Client.Audio;
-using Robust.Client.GameObjects;
-using Robust.Client.Graphics;
-using Robust.Client.Player;
-using Robust.Client.ResourceManagement;
-using Robust.Shared.Console;
-using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-
-namespace Robust.Client.Commands;
-
-///
-/// Shows a debug overlay for audio sources.
-///
-public sealed class ShowAudioCommand : LocalizedCommands
-{
- [Dependency] private readonly IClientResourceCache _client = default!;
- [Dependency] private readonly IEntityManager _entManager = default!;
- [Dependency] private readonly IOverlayManager _overlayManager = default!;
- [Dependency] private readonly IPlayerManager _playerMgr = default!;
- public override string Command => "showaudio";
- public override void Execute(IConsoleShell shell, string argStr, string[] args)
- {
- if (_overlayManager.HasOverlay())
- _overlayManager.RemoveOverlay();
- else
- _overlayManager.AddOverlay(new AudioOverlay(
- _entManager,
- _playerMgr,
- _client,
- _entManager.System(),
- _entManager.System()));
- }
-}
diff --git a/Robust.Client/Audio/Sources/AudioSource.cs b/Robust.Client/Audio/Sources/AudioSource.cs
deleted file mode 100644
index 0558f29f36e..00000000000
--- a/Robust.Client/Audio/Sources/AudioSource.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using System;
-using System.Numerics;
-using OpenTK.Audio.OpenAL;
-using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
-using Robust.Shared.Audio;
-using Robust.Shared.Maths;
-using Robust.Shared.Utility;
-
-namespace Robust.Client.Audio.Sources;
-
-internal sealed class AudioSource : BaseAudioSource
-{
- ///
- /// Underlying stream to the audio.
- ///
- private readonly AudioStream _sourceStream;
-
-#if DEBUG
- private bool _didPositionWarning;
-#endif
-
- public AudioSource(AudioManager master, int sourceHandle, AudioStream sourceStream) : base(master, sourceHandle)
- {
- _sourceStream = sourceStream;
- }
-
- ///
- public override Vector2 Position
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSource3f.Position, out var x, out var y, out _);
- Master._checkAlError();
- return new Vector2(x, y);
- }
- set
- {
- _checkDisposed();
-
- var (x, y) = value;
-
- if (!AreFinite(x, y))
- {
- return;
- }
-#if DEBUG
- // OpenAL doesn't seem to want to play stereo positionally.
- // Log a warning if people try to.
- if (_sourceStream.ChannelCount > 1 && !_didPositionWarning)
- {
- _didPositionWarning = true;
- Master.OpenALSawmill.Warning("Attempting to set position on audio source with multiple audio channels! Stream: '{0}'. Make sure the audio is MONO, not stereo.",
- _sourceStream.Name);
- // warning isn't enough, people just ignore it :(
- DebugTools.Assert(false, $"Attempting to set position on audio source with multiple audio channels! Stream: '{_sourceStream.Name}'. Make sure the audio is MONO, not stereo.");
- }
-#endif
-
- AL.Source(SourceHandle, ALSource3f.Position, x, y, 0);
- Master._checkAlError();
- }
- }
-
- ~AudioSource()
- {
- Dispose(false);
- }
-
- protected override void Dispose(bool disposing)
- {
- if (!disposing)
- {
- // We can't run this code inside the finalizer thread so tell Clyde to clear it up later.
- Master.DeleteSourceOnMainThread(SourceHandle, FilterHandle);
- }
- else
- {
- if (FilterHandle != 0)
- EFX.DeleteFilter(FilterHandle);
-
- AL.DeleteSource(SourceHandle);
- Master.RemoveAudioSource(SourceHandle);
- Master._checkAlError();
- }
-
- FilterHandle = 0;
- SourceHandle = -1;
- }
-}
diff --git a/Robust.Client/Audio/Sources/BaseAudioSource.cs b/Robust.Client/Audio/Sources/BaseAudioSource.cs
deleted file mode 100644
index 38c9fdb3ec3..00000000000
--- a/Robust.Client/Audio/Sources/BaseAudioSource.cs
+++ /dev/null
@@ -1,390 +0,0 @@
-using System;
-using System.Numerics;
-using OpenTK.Audio.OpenAL;
-using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
-using Robust.Client.Audio.Effects;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Maths;
-
-namespace Robust.Client.Audio.Sources;
-
-internal abstract class BaseAudioSource : IAudioSource
-{
- /*
- * This may look weird having all these methods here however
- * we need to handle disposing plus checking for errors hence we get this.
- */
-
- ///
- /// Handle to the AL source.
- ///
- protected int SourceHandle;
-
- ///
- /// Source to the EFX filter if applicable.
- ///
- protected int FilterHandle;
-
- protected readonly AudioManager Master;
-
- ///
- /// Prior gain that was set.
- ///
- private float _gain;
-
- private bool IsEfxSupported => Master.IsEfxSupported;
-
- protected BaseAudioSource(AudioManager master, int sourceHandle)
- {
- Master = master;
- SourceHandle = sourceHandle;
- AL.GetSource(SourceHandle, ALSourcef.Gain, out _gain);
- }
-
- public void Pause()
- {
- AL.SourcePause(SourceHandle);
- }
-
- ///
- public void StartPlaying()
- {
- if (Playing)
- return;
-
- Playing = true;
- }
-
- ///
- public void StopPlaying()
- {
- if (!Playing)
- return;
-
- Playing = false;
- }
-
- ///
- public virtual bool Playing
- {
- get
- {
- _checkDisposed();
- var state = AL.GetSourceState(SourceHandle);
- Master._checkAlError();
- return state == ALSourceState.Playing;
- }
- set
- {
- _checkDisposed();
-
- if (value)
- {
- AL.SourcePlay(SourceHandle);
- }
- else
- {
- AL.SourceStop(SourceHandle);
- }
-
-
- Master._checkAlError();
- }
- }
-
- ///
- public bool Looping
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourceb.Looping, out var ret);
- Master._checkAlError();
- return ret;
- }
- set
- {
- _checkDisposed();
- AL.Source(SourceHandle, ALSourceb.Looping, value);
- Master._checkAlError();
- }
- }
-
- ///
- public bool Global
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourceb.SourceRelative, out var value);
- Master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- AL.Source(SourceHandle, ALSourceb.SourceRelative, value);
- Master._checkAlError();
- }
- }
-
- ///
- public virtual Vector2 Position
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSource3f.Position, out var x, out var y, out _);
- Master._checkAlError();
- return new Vector2(x, y);
- }
- set
- {
- _checkDisposed();
-
- var (x, y) = value;
-
- if (!AreFinite(x, y))
- {
- return;
- }
-
- AL.Source(SourceHandle, ALSource3f.Position, x, y, 0);
- Master._checkAlError();
- }
- }
-
- ///
- public float Pitch { get; set; }
-
- ///
- public float Volume
- {
- get
- {
- var gain = Gain;
- var volume = 10f * MathF.Log10(gain);
- return volume;
- }
- set => Gain = MathF.Pow(10, value / 10);
- }
-
- ///
- public float Gain
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourcef.Gain, out var gain);
- Master._checkAlError();
- return gain;
- }
- set
- {
- _checkDisposed();
- var priorOcclusion = 1f;
- if (!IsEfxSupported)
- {
- AL.GetSource(SourceHandle, ALSourcef.Gain, out var priorGain);
- priorOcclusion = priorGain / _gain;
- }
-
- _gain = value;
- AL.Source(SourceHandle, ALSourcef.Gain, _gain * priorOcclusion);
- Master._checkAlError();
- }
- }
-
- ///
- public float MaxDistance
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourcef.MaxDistance, out var value);
- Master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- AL.Source(SourceHandle, ALSourcef.MaxDistance, value);
- Master._checkAlError();
- }
- }
-
- ///
- public float RolloffFactor
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourcef.RolloffFactor, out var value);
- Master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- AL.Source(SourceHandle, ALSourcef.RolloffFactor, value);
- Master._checkAlError();
- }
- }
-
- ///
- public float ReferenceDistance
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourcef.ReferenceDistance, out var value);
- Master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- AL.Source(SourceHandle, ALSourcef.ReferenceDistance, value);
- Master._checkAlError();
- }
- }
-
- ///
- public float Occlusion
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourcef.MaxDistance, out var value);
- Master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- var cutoff = MathF.Exp(-value * 1);
- var gain = MathF.Pow(cutoff, 0.1f);
- if (IsEfxSupported)
- {
- SetOcclusionEfx(gain, cutoff);
- }
- else
- {
- gain *= gain * gain;
- AL.Source(SourceHandle, ALSourcef.Gain, _gain * gain);
- }
- Master._checkAlError();
- }
- }
-
- ///
- public float PlaybackPosition
- {
- get
- {
- _checkDisposed();
- AL.GetSource(SourceHandle, ALSourcef.SecOffset, out var value);
- Master._checkAlError();
- return value;
- }
- set
- {
- _checkDisposed();
- AL.Source(SourceHandle, ALSourcef.SecOffset, value);
- Master._checkAlError();
- }
- }
-
- ///
- public Vector2 Velocity
- {
- get
- {
- _checkDisposed();
-
- AL.GetSource(SourceHandle, ALSource3f.Velocity, out var x, out var y, out _);
- Master._checkAlError();
- return new Vector2(x, y);
- }
- set
- {
- _checkDisposed();
-
- var (x, y) = value;
-
- if (!AreFinite(x, y))
- {
- return;
- }
-
- AL.Source(SourceHandle, ALSource3f.Velocity, x, y, 0);
- Master._checkAlError();
- }
- }
-
- public void SetAuxiliary(IAuxiliaryAudio? audio)
- {
- _checkDisposed();
-
- if (audio is AuxiliaryAudio impAudio)
- {
- EFX.Source(SourceHandle, EFXSourceInteger3.AuxiliarySendFilter, impAudio.Handle, 0, 0);
- }
- else
- {
- EFX.Source(SourceHandle, EFXSourceInteger3.AuxiliarySendFilter, 0, 0, 0);
- }
-
- Master._checkAlError();
- }
-
- private void SetOcclusionEfx(float gain, float cutoff)
- {
- if (FilterHandle == 0)
- {
- FilterHandle = EFX.GenFilter();
- EFX.Filter(FilterHandle, FilterInteger.FilterType, (int) FilterType.Lowpass);
- }
-
- EFX.Filter(FilterHandle, FilterFloat.LowpassGain, gain);
- EFX.Filter(FilterHandle, FilterFloat.LowpassGainHF, cutoff);
- AL.Source(SourceHandle, ALSourcei.EfxDirectFilter, FilterHandle);
- }
-
- protected static bool AreFinite(float x, float y)
- {
- if (float.IsFinite(x) && float.IsFinite(y))
- {
- return true;
- }
-
- return false;
- }
-
- ~BaseAudioSource()
- {
- Dispose(false);
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected abstract void Dispose(bool disposing);
-
- protected bool _isDisposed()
- {
- return SourceHandle == -1;
- }
-
- protected void _checkDisposed()
- {
- if (SourceHandle == -1)
- {
- throw new ObjectDisposedException(nameof(BaseAudioSource));
- }
- }
-}
diff --git a/Robust.Client/Audio/Sources/BufferedAudioSource.cs b/Robust.Client/Audio/Sources/BufferedAudioSource.cs
deleted file mode 100644
index 31ed004b883..00000000000
--- a/Robust.Client/Audio/Sources/BufferedAudioSource.cs
+++ /dev/null
@@ -1,224 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-using OpenTK.Audio.OpenAL;
-using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
-using Robust.Client.Graphics;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Maths;
-
-namespace Robust.Client.Audio.Sources;
-
-internal sealed class BufferedAudioSource : BaseAudioSource, IBufferedAudioSource
-{
- private int? SourceHandle = null;
- private int[] BufferHandles;
- private Dictionary BufferMap = new();
- private readonly AudioManager _master;
- private bool _mono = true;
- private bool _float = false;
- private int FilterHandle;
-
- private float _gain;
-
- public int SampleRate { get; set; } = 44100;
-
- private bool IsEfxSupported => _master.IsEfxSupported;
-
- public BufferedAudioSource(AudioManager master, int sourceHandle, int[] bufferHandles, bool floatAudio = false) : base(master, sourceHandle)
- {
- _master = master;
- SourceHandle = sourceHandle;
- BufferHandles = bufferHandles;
- for (int i = 0; i < BufferHandles.Length; i++)
- {
- var bufferHandle = BufferHandles[i];
- BufferMap[bufferHandle] = i;
- }
- _float = floatAudio;
- AL.GetSource(sourceHandle, ALSourcef.Gain, out _gain);
- }
-
- ///
- public override bool Playing
- {
- get
- {
- _checkDisposed();
- var state = AL.GetSourceState(SourceHandle!.Value);
- _master._checkAlError();
- return state == ALSourceState.Playing;
- }
- set
- {
- if (value)
- {
- _checkDisposed();
- // IDK why this stackallocs but gonna leave it for now.
- AL.SourcePlay(stackalloc int[] {SourceHandle!.Value});
- _master._checkAlError();
- }
- else
- {
- if (_isDisposed())
- return;
-
- AL.SourceStop(SourceHandle!.Value);
- _master._checkAlError();
- }
- }
- }
-
- ~BufferedAudioSource()
- {
- Dispose(false);
- }
-
- protected override void Dispose(bool disposing)
- {
- if (SourceHandle == null)
- return;
-
- if (!_master.IsMainThread())
- {
- // We can't run this code inside another thread so tell Clyde to clear it up later.
- _master.DeleteBufferedSourceOnMainThread(SourceHandle.Value, FilterHandle);
-
- foreach (var handle in BufferHandles)
- {
- _master.DeleteAudioBufferOnMainThread(handle);
- }
- }
- else
- {
- if (FilterHandle != 0)
- EFX.DeleteFilter(FilterHandle);
-
- AL.DeleteSource(SourceHandle.Value);
- AL.DeleteBuffers(BufferHandles);
- _master.RemoveBufferedAudioSource(SourceHandle.Value);
- _master._checkAlError();
- }
-
- FilterHandle = 0;
- SourceHandle = null;
- }
-
- public int GetNumberOfBuffersProcessed()
- {
- _checkDisposed();
- // ReSharper disable once PossibleInvalidOperationException
- AL.GetSource(SourceHandle!.Value, ALGetSourcei.BuffersProcessed, out var buffersProcessed);
- return buffersProcessed;
- }
-
- public unsafe void GetBuffersProcessed(Span handles)
- {
- _checkDisposed();
- var entries = Math.Min(Math.Min(handles.Length, BufferHandles.Length), GetNumberOfBuffersProcessed());
- fixed (int* ptr = handles)
- {
- AL.SourceUnqueueBuffers(SourceHandle!.Value, entries, ptr);
- }
-
- for (var i = 0; i < entries; i++)
- {
- handles[i] = BufferMap[handles[i]];
- }
- }
-
- public unsafe void WriteBuffer(int handle, ReadOnlySpan data)
- {
- _checkDisposed();
-
- if(_float)
- throw new InvalidOperationException("Can't write ushort numbers to buffers when buffer type is float!");
-
- if (handle >= BufferHandles.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(handle),
- $"Got {handle}. Expected less than {BufferHandles.Length}");
- }
-
- fixed (ushort* ptr = data)
- {
- AL.BufferData(BufferHandles[handle], _mono ? ALFormat.Mono16 : ALFormat.Stereo16, (IntPtr) ptr,
- _mono ? data.Length / 2 * sizeof(ushort) : data.Length * sizeof(ushort), SampleRate);
- }
- }
-
- public unsafe void WriteBuffer(int handle, ReadOnlySpan data)
- {
- _checkDisposed();
-
- if(!_float)
- throw new InvalidOperationException("Can't write float numbers to buffers when buffer type is ushort!");
-
- if (handle >= BufferHandles.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(handle),
- $"Got {handle}. Expected less than {BufferHandles.Length}");
- }
-
- fixed (float* ptr = data)
- {
- AL.BufferData(BufferHandles[handle], _mono ? ALFormat.MonoFloat32Ext : ALFormat.StereoFloat32Ext, (IntPtr) ptr,
- _mono ? data.Length / 2 * sizeof(float) : data.Length * sizeof(float), SampleRate);
- }
- }
-
- public unsafe void QueueBuffers(ReadOnlySpan handles)
- {
- _checkDisposed();
-
- Span realHandles = stackalloc int[handles.Length];
- handles.CopyTo(realHandles);
-
- for (var i = 0; i < realHandles.Length; i++)
- {
- var handle = realHandles[i];
- if (handle >= BufferHandles.Length)
- throw new ArgumentOutOfRangeException(nameof(handles), $"Invalid handle with index {i}!");
- realHandles[i] = BufferHandles[handle];
- }
-
- fixed (int* ptr = realHandles)
- // ReSharper disable once PossibleInvalidOperationException
- {
- AL.SourceQueueBuffers(SourceHandle!.Value, handles.Length, ptr);
- }
- }
-
- public unsafe void EmptyBuffers()
- {
- _checkDisposed();
- var length = SampleRate / BufferHandles.Length * (_mono ? 1 : 2);
-
- Span handles = stackalloc int[BufferHandles.Length];
-
- if (_float)
- {
- var empty = new float[length];
- var span = (Span) empty;
-
- for (var i = 0; i < BufferHandles.Length; i++)
- {
- WriteBuffer(BufferMap[BufferHandles[i]], span);
- handles[i] = BufferMap[BufferHandles[i]];
- }
- }
- else
- {
- var empty = new ushort[length];
- var span = (Span) empty;
-
- for (var i = 0; i < BufferHandles.Length; i++)
- {
- WriteBuffer(BufferMap[BufferHandles[i]], span);
- handles[i] = BufferMap[BufferHandles[i]];
- }
- }
-
- QueueBuffers(handles);
- }
-}
diff --git a/Robust.Client/ClientIoC.cs b/Robust.Client/ClientIoC.cs
index da5064ef0cf..4e6f377d19c 100644
--- a/Robust.Client/ClientIoC.cs
+++ b/Robust.Client/ClientIoC.cs
@@ -1,5 +1,4 @@
using System;
-using Robust.Client.Audio;
using Robust.Client.Audio.Midi;
using Robust.Client.Configuration;
using Robust.Client.Console;
@@ -7,6 +6,7 @@
using Robust.Client.GameObjects;
using Robust.Client.GameStates;
using Robust.Client.Graphics;
+using Robust.Client.Graphics.Audio;
using Robust.Client.Graphics.Clyde;
using Robust.Client.Input;
using Robust.Client.Map;
@@ -29,7 +29,6 @@
using Robust.Client.Utility;
using Robust.Client.ViewVariables;
using Robust.Shared;
-using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
@@ -73,11 +72,10 @@ public static void RegisterIoC(GameController.DisplayMode mode, IDependencyColle
deps.Register();
deps.Register();
deps.Register();
- deps.Register();
- deps.Register();
- deps.Register();
- deps.Register();
+ deps.Register();
+ deps.Register();
deps.Register();
+ deps.Register();
deps.Register();
deps.Register();
deps.Register();
@@ -109,8 +107,8 @@ public static void RegisterIoC(GameController.DisplayMode mode, IDependencyColle
deps.Register();
deps.Register();
deps.Register();
- deps.Register();
- deps.Register();
+ deps.Register();
+ deps.Register();
deps.Register();
deps.Register();
deps.Register();
@@ -119,8 +117,8 @@ public static void RegisterIoC(GameController.DisplayMode mode, IDependencyColle
deps.Register();
deps.Register();
deps.Register();
- deps.Register();
- deps.Register();
+ deps.Register();
+ deps.Register();
deps.Register();
deps.Register();
deps.Register();
diff --git a/Robust.Client/Console/Commands/Debug.cs b/Robust.Client/Console/Commands/Debug.cs
index ee19401ff12..3540aeeeae4 100644
--- a/Robust.Client/Console/Commands/Debug.cs
+++ b/Robust.Client/Console/Commands/Debug.cs
@@ -15,7 +15,6 @@
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.Asynchronous;
-using Robust.Shared.Audio;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
@@ -355,7 +354,7 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
internal sealed class LoadResource : LocalizedCommands
{
- [Dependency] private readonly IClientResourceCache _res = default!;
+ [Dependency] private readonly IResourceCache _res = default!;
[Dependency] private readonly IReflectionManager _reflection = default!;
public override string Command => "ldrsc";
@@ -392,7 +391,7 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
internal sealed class ReloadResource : LocalizedCommands
{
- [Dependency] private readonly IClientResourceCache _res = default!;
+ [Dependency] private readonly IResourceCache _res = default!;
[Dependency] private readonly IReflectionManager _reflection = default!;
public override string Command => "rldrsc";
@@ -459,13 +458,13 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
internal sealed class GuiDumpCommand : LocalizedCommands
{
[Dependency] private readonly IUserInterfaceManager _ui = default!;
- [Dependency] private readonly IResourceManager _resManager = default!;
+ [Dependency] private readonly IResourceCache _res = default!;
public override string Command => "guidump";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
- using var writer = _resManager.UserData.OpenWriteText(new ResPath("/guidump.txt"));
+ using var writer = _res.UserData.OpenWriteText(new ResPath("/guidump.txt"));
foreach (var root in _ui.AllRoots)
{
@@ -645,8 +644,7 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
internal sealed class ReloadShadersCommand : LocalizedCommands
{
- [Dependency] private readonly IResourceCache _cache = default!;
- [Dependency] private readonly IResourceManagerInternal _resManager = default!;
+ [Dependency] private readonly IResourceCacheInternal _res = default!;
[Dependency] private readonly ITaskManager _taskManager = default!;
public override string Command => "rldshader";
@@ -657,7 +655,7 @@ internal sealed class ReloadShadersCommand : LocalizedCommands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
- var resC = _resManager;
+ var resC = _res;
if (args.Length == 1)
{
if (args[0] == "+watch")
@@ -681,9 +679,9 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
var shaderCount = 0;
var created = 0;
var dirs = new ConcurrentDictionary>(stringComparer);
- foreach (var (path, src) in _cache.GetAllResources())
+ foreach (var (path, src) in resC.GetAllResources())
{
- if (!_resManager.TryGetDiskFilePath(path, out var fullPath))
+ if (!resC.TryGetDiskFilePath(path, out var fullPath))
{
throw new NotImplementedException();
}
@@ -732,7 +730,7 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
try
{
- _cache.ReloadResource(resPath);
+ resC.ReloadResource(resPath);
shell.WriteLine($"Reloaded shader: {resPath}");
}
catch (Exception)
@@ -793,11 +791,11 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
shell.WriteLine("Reloading content shader resources...");
- foreach (var (path, _) in _cache.GetAllResources())
+ foreach (var (path, _) in resC.GetAllResources())
{
try
{
- _cache.ReloadResource(path);
+ resC.ReloadResource(path);
}
catch (Exception)
{
diff --git a/Robust.Client/Debugging/DebugPhysicsSystem.cs b/Robust.Client/Debugging/DebugPhysicsSystem.cs
index 9e9ec237ad6..ec4bb760ac0 100644
--- a/Robust.Client/Debugging/DebugPhysicsSystem.cs
+++ b/Robust.Client/Debugging/DebugPhysicsSystem.cs
@@ -96,7 +96,7 @@ public PhysicsDebugFlags Flags
IoCManager.Resolve(),
IoCManager.Resolve(),
IoCManager.Resolve(),
- IoCManager.Resolve(),
+ IoCManager.Resolve(),
this,
Get(),
Get()));
@@ -208,7 +208,7 @@ internal sealed class PhysicsDebugOverlay : Overlay
private HashSet _drawnJoints = new();
private List> _grids = new();
- public PhysicsDebugOverlay(IEntityManager entityManager, IEyeManager eyeManager, IInputManager inputManager, IMapManager mapManager, IPlayerManager playerManager, IClientResourceCache cache, DebugPhysicsSystem system, EntityLookupSystem lookup, SharedPhysicsSystem physicsSystem)
+ public PhysicsDebugOverlay(IEntityManager entityManager, IEyeManager eyeManager, IInputManager inputManager, IMapManager mapManager, IPlayerManager playerManager, IResourceCache cache, DebugPhysicsSystem system, EntityLookupSystem lookup, SharedPhysicsSystem physicsSystem)
{
_entityManager = entityManager;
_eyeManager = eyeManager;
diff --git a/Robust.Client/GameController/GameController.cs b/Robust.Client/GameController/GameController.cs
index 308caaa39f1..6e5e2ad876a 100644
--- a/Robust.Client/GameController/GameController.cs
+++ b/Robust.Client/GameController/GameController.cs
@@ -4,7 +4,6 @@
using System.Net;
using System.Runtime;
using System.Threading.Tasks;
-using Robust.Client.Audio;
using Robust.Client.Audio.Midi;
using Robust.Client.Console;
using Robust.Client.GameObjects;
@@ -25,7 +24,6 @@
using Robust.LoaderApi;
using Robust.Shared;
using Robust.Shared.Asynchronous;
-using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Exceptions;
@@ -50,8 +48,7 @@ namespace Robust.Client
internal sealed partial class GameController : IGameControllerInternal
{
[Dependency] private readonly INetConfigurationManagerInternal _configurationManager = default!;
- [Dependency] private readonly IClientResourceCacheInternal _resourceCache = default!;
- [Dependency] private readonly IResourceManagerInternal _resManager = default!;
+ [Dependency] private readonly IResourceCacheInternal _resourceCache = default!;
[Dependency] private readonly IRobustSerializer _serializer = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IClientNetManager _networkManager = default!;
@@ -71,7 +68,7 @@ internal sealed partial class GameController : IGameControllerInternal
[Dependency] private readonly IClientViewVariablesManagerInternal _viewVariablesManager = default!;
[Dependency] private readonly IDiscordRichPresence _discord = default!;
[Dependency] private readonly IClydeInternal _clyde = default!;
- [Dependency] private readonly IAudioInternal _audio = default!;
+ [Dependency] private readonly IClydeAudioInternal _clydeAudio = default!;
[Dependency] private readonly IFontManagerInternal _fontManager = default!;
[Dependency] private readonly IModLoaderInternal _modLoader = default!;
[Dependency] private readonly IScriptClient _scriptClient = default!;
@@ -114,7 +111,7 @@ internal bool StartupContinue(DisplayMode displayMode)
DebugTools.AssertNotNull(_resourceManifest);
_clyde.InitializePostWindowing();
- _audio.InitializePostWindowing();
+ _clydeAudio.InitializePostWindowing();
_clyde.SetWindowTitle(
Options.DefaultWindowTitle ?? _resourceManifest!.DefaultWindowTitle ?? "RobustToolbox");
@@ -151,7 +148,7 @@ internal bool StartupContinue(DisplayMode displayMode)
// Start bad file extensions check after content init,
// in case content screws with the VFS.
var checkBadExtensions = ProgramShared.CheckBadFileExtensions(
- _resManager,
+ _resourceCache,
_configurationManager,
_logManager.GetSawmill("res"));
@@ -363,13 +360,13 @@ internal bool StartupSystemSplash(
_parallelMgr.Initialize();
_prof.Initialize();
- _resManager.Initialize(Options.LoadConfigAndUserData ? userDataDir : null);
+ _resourceCache.Initialize(Options.LoadConfigAndUserData ? userDataDir : null);
var mountOptions = _commandLineArgs != null
? MountOptions.Merge(_commandLineArgs.MountOptions, Options.MountOptions)
: Options.MountOptions;
- ProgramShared.DoMounts(_resManager, mountOptions, Options.ContentBuildDirectory,
+ ProgramShared.DoMounts(_resourceCache, mountOptions, Options.ContentBuildDirectory,
Options.AssemblyDirectory,
Options.LoadContentResources, _loaderArgs != null && !Options.ResourceMountDisabled, ContentStart);
@@ -379,16 +376,16 @@ internal bool StartupSystemSplash(
{
foreach (var (api, prefix) in mounts)
{
- _resourceCache.MountLoaderApi(_resManager, api, "", new(prefix));
+ _resourceCache.MountLoaderApi(api, "", new(prefix));
}
}
_stringSerializer.EnableCaching = false;
- _resourceCache.MountLoaderApi(_resManager, _loaderArgs.FileApi, "Resources/");
+ _resourceCache.MountLoaderApi(_loaderArgs.FileApi, "Resources/");
_modLoader.VerifierExtraLoadHandler = VerifierExtraLoadHandler;
}
- _resourceManifest = ResourceManifestData.LoadResourceManifest(_resManager);
+ _resourceManifest = ResourceManifestData.LoadResourceManifest(_resourceCache);
{
// Handle GameControllerOptions implicit CVar overrides.
@@ -570,6 +567,11 @@ private void Update(FrameEventArgs frameEventArgs)
}
}
+ using (_prof.Group("ClydeAudio"))
+ {
+ _clydeAudio.FrameProcess(frameEventArgs);
+ }
+
using (_prof.Group("Clyde"))
{
_clyde.FrameProcess(frameEventArgs);
@@ -708,7 +710,7 @@ internal void CleanupGameThread()
internal void CleanupWindowThread()
{
_clyde.Shutdown();
- _audio.Shutdown();
+ _clydeAudio.Shutdown();
}
public event Action? TickUpdateOverride;
diff --git a/Robust.Client/GameObjects/Components/Renderable/SpriteComponent.cs b/Robust.Client/GameObjects/Components/Renderable/SpriteComponent.cs
index 9499e8ca419..dcd434ed3dd 100644
--- a/Robust.Client/GameObjects/Components/Renderable/SpriteComponent.cs
+++ b/Robust.Client/GameObjects/Components/Renderable/SpriteComponent.cs
@@ -36,7 +36,7 @@ namespace Robust.Client.GameObjects
[RegisterComponent]
public sealed partial class SpriteComponent : Component, IComponentDebug, ISerializationHooks, IComponentTreeEntry, IAnimationProperties
{
- [Dependency] private readonly IClientResourceCache resourceCache = default!;
+ [Dependency] private readonly IResourceCache resourceCache = default!;
[Dependency] private readonly IPrototypeManager prototypes = default!;
[Dependency] private readonly IEntityManager entities = default!;
[Dependency] private readonly IReflectionManager reflection = default!;
@@ -1379,7 +1379,7 @@ private void QueueUpdateIsInert()
}
[Obsolete("Use SpriteSystem instead.")]
- internal static RSI.State GetFallbackState(IClientResourceCache cache)
+ internal static RSI.State GetFallbackState(IResourceCache cache)
{
var rsi = cache.GetResource("/Textures/error.rsi").RSI;
return rsi["error"];
@@ -2101,12 +2101,12 @@ public IRsiStateLike? Icon
}
}
- public static IEnumerable GetPrototypeTextures(EntityPrototype prototype, IClientResourceCache resourceCache)
+ public static IEnumerable GetPrototypeTextures(EntityPrototype prototype, IResourceCache resourceCache)
{
return GetPrototypeTextures(prototype, resourceCache, out var _);
}
- public static IEnumerable GetPrototypeTextures(EntityPrototype prototype, IClientResourceCache resourceCache, out bool noRot)
+ public static IEnumerable GetPrototypeTextures(EntityPrototype prototype, IResourceCache resourceCache, out bool noRot)
{
var results = new List();
noRot = false;
@@ -2161,7 +2161,7 @@ public static IEnumerable GetPrototypeTextures(Enti
}
[Obsolete("Use SpriteSystem")]
- public static IRsiStateLike GetPrototypeIcon(EntityPrototype prototype, IClientResourceCache resourceCache)
+ public static IRsiStateLike GetPrototypeIcon(EntityPrototype prototype, IResourceCache resourceCache)
{
// TODO when moving to a non-static method in a system, pass in IComponentFactory
if (prototype.TryGetComponent(out IconComponent? icon))
diff --git a/Robust.Client/GameObjects/EntitySystems/AudioSystem.cs b/Robust.Client/GameObjects/EntitySystems/AudioSystem.cs
new file mode 100644
index 00000000000..70ac0c61eb8
--- /dev/null
+++ b/Robust.Client/GameObjects/EntitySystems/AudioSystem.cs
@@ -0,0 +1,626 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Robust.Client.Audio;
+using Robust.Client.Graphics;
+using Robust.Client.ResourceManagement;
+using Robust.Shared;
+using Robust.Shared.Audio;
+using Robust.Shared.Exceptions;
+using Robust.Shared.GameObjects;
+using Robust.Shared.IoC;
+using Robust.Shared.Log;
+using Robust.Shared.Map;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Physics.Systems;
+using Robust.Shared.Player;
+using Robust.Shared.Random;
+using Robust.Shared.Replays;
+using Robust.Shared.Threading;
+using Robust.Shared.Timing;
+using Robust.Shared.Utility;
+
+namespace Robust.Client.GameObjects;
+
+[UsedImplicitly]
+public sealed class AudioSystem : SharedAudioSystem
+{
+ [Dependency] private readonly IReplayRecordingManager _replayRecording = default!;
+ [Dependency] private readonly SharedPhysicsSystem _broadPhaseSystem = default!;
+ [Dependency] private readonly IClydeAudio _clyde = default!;
+ [Dependency] private readonly IEyeManager _eyeManager = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly IParallelManager _parMan = default!;
+ [Dependency] private readonly SharedTransformSystem _xformSys = default!;
+ [Dependency] private readonly SharedPhysicsSystem _physics = default!;
+ [Dependency] private readonly IRuntimeLog _runtimeLog = default!;
+ [Dependency] private readonly ILogManager _logManager = default!;
+
+ private readonly List _playingClydeStreams = new();
+
+ private ISawmill _sawmill = default!;
+
+ private float _maxRayLength;
+
+ ///
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeNetworkEvent(PlayAudioEntityHandler);
+ SubscribeNetworkEvent(PlayAudioGlobalHandler);
+ SubscribeNetworkEvent(PlayAudioPositionalHandler);
+ SubscribeNetworkEvent(StopAudioMessageHandler);
+
+ _sawmill = _logManager.GetSawmill("audio");
+
+ CfgManager.OnValueChanged(CVars.AudioRaycastLength, OnRaycastLengthChanged, true);
+ }
+
+ public override void Shutdown()
+ {
+ CfgManager.UnsubValueChanged(CVars.AudioRaycastLength, OnRaycastLengthChanged);
+ foreach (var stream in _playingClydeStreams)
+ {
+ stream.Source.Dispose();
+ }
+ _playingClydeStreams.Clear();
+
+ base.Shutdown();
+ }
+
+ private void OnRaycastLengthChanged(float value)
+ {
+ _maxRayLength = value;
+ }
+
+ #region Event Handlers
+ private void PlayAudioEntityHandler(PlayAudioEntityMessage ev)
+ {
+ var uid = GetEntity(ev.NetEntity);
+ var coords = GetCoordinates(ev.Coordinates);
+ var fallback = GetCoordinates(ev.FallbackCoordinates);
+
+ var stream = EntityManager.EntityExists(uid)
+ ? (PlayingStream?) Play(ev.FileName, uid, fallback, ev.AudioParams, false)
+ : (PlayingStream?) Play(ev.FileName, coords, fallback, ev.AudioParams, false);
+
+ if (stream != null)
+ stream.NetIdentifier = ev.Identifier;
+ }
+
+ private void PlayAudioGlobalHandler(PlayAudioGlobalMessage ev)
+ {
+ var stream = (PlayingStream?) Play(ev.FileName, ev.AudioParams, false);
+ if (stream != null)
+ stream.NetIdentifier = ev.Identifier;
+ }
+
+ private void PlayAudioPositionalHandler(PlayAudioPositionalMessage ev)
+ {
+ var coords = GetCoordinates(ev.Coordinates);
+ var fallback = GetCoordinates(ev.FallbackCoordinates);
+
+ var stream = (PlayingStream?) Play(ev.FileName, coords, fallback, ev.AudioParams, false);
+ if (stream != null)
+ stream.NetIdentifier = ev.Identifier;
+ }
+
+ private void StopAudioMessageHandler(StopAudioMessageClient ev)
+ {
+ var stream = _playingClydeStreams.Find(p => p.NetIdentifier == ev.Identifier);
+ if (stream == null)
+ return;
+
+ stream.Done = true;
+ stream.Source.Dispose();
+ _playingClydeStreams.Remove(stream);
+ }
+ #endregion
+
+ public override void FrameUpdate(float frameTime)
+ {
+ var xforms = GetEntityQuery();
+ var physics = GetEntityQuery();
+ var ourPos = _eyeManager.CurrentEye.Position;
+ var opts = new ParallelOptions { MaxDegreeOfParallelism = _parMan.ParallelProcessCount };
+
+ try
+ {
+ Parallel.ForEach(_playingClydeStreams, opts, (stream) => ProcessStream(stream, ourPos, xforms, physics));
+ }
+ catch (Exception e)
+ {
+ _sawmill.Error($"Caught exception while processing entity streams.");
+ _runtimeLog.LogException(e, $"{nameof(AudioSystem)}.{nameof(FrameUpdate)}");
+ }
+ finally
+ {
+
+ for (var i = _playingClydeStreams.Count - 1; i >= 0; i--)
+ {
+ var stream = _playingClydeStreams[i];
+ if (stream.Done)
+ {
+ stream.Source.Dispose();
+ _playingClydeStreams.RemoveSwap(i);
+ }
+ }
+ }
+ }
+
+ private void ProcessStream(PlayingStream stream,
+ MapCoordinates listener,
+ EntityQuery xforms,
+ EntityQuery physics)
+ {
+ if (!stream.Source.IsPlaying)
+ {
+ stream.Done = true;
+ return;
+ }
+
+ if (stream.Source.IsGlobal)
+ {
+ DebugTools.Assert(stream.TrackingCoordinates == null
+ && stream.TrackingEntity == null
+ && stream.TrackingFallbackCoordinates == null);
+
+ return;
+ }
+
+ DebugTools.Assert(stream.TrackingCoordinates != null
+ || stream.TrackingEntity != null
+ || stream.TrackingFallbackCoordinates != null);
+
+ // Get audio Position
+ if (!TryGetStreamPosition(stream, xforms, out var mapPos)
+ || mapPos == MapCoordinates.Nullspace
+ || mapPos.Value.MapId != listener.MapId)
+ {
+ stream.Done = true;
+ return;
+ }
+
+ // Max distance check
+ var delta = mapPos.Value.Position - listener.Position;
+ var distance = delta.Length();
+ if (distance > stream.MaxDistance)
+ {
+ stream.Source.SetVolumeDirect(0);
+ return;
+ }
+
+ // Update audio occlusion
+ float occlusion = 0;
+ if (distance > 0.1)
+ {
+ var rayLength = MathF.Min(distance, _maxRayLength);
+ var ray = new CollisionRay(listener.Position, delta/distance, OcclusionCollisionMask);
+ occlusion = _broadPhaseSystem.IntersectRayPenetration(listener.MapId, ray, rayLength, stream.TrackingEntity);
+ }
+ stream.Source.SetOcclusion(occlusion);
+
+ // Update attenuation dependent volume.
+ UpdatePositionalVolume(stream, distance);
+
+ // Update audio positions.
+ var audioPos = stream.Attenuation != Attenuation.NoAttenuation ? mapPos.Value : listener;
+ if (!stream.Source.SetPosition(audioPos.Position))
+ {
+ _sawmill.Warning("Interrupting positional audio, can't set position.");
+ stream.Source.StopPlaying();
+ return;
+ }
+
+ // Make race cars go NYYEEOOOOOMMMMM
+ if (stream.TrackingEntity != null && physics.TryGetComponent(stream.TrackingEntity, out var physicsComp))
+ {
+ // This actually gets the tracked entity's xform & iterates up though the parents for the second time. Bit
+ // inefficient.
+ var velocity = _physics.GetMapLinearVelocity(stream.TrackingEntity.Value, physicsComp, null, xforms, physics);
+ stream.Source.SetVelocity(velocity);
+ }
+ }
+
+ private void UpdatePositionalVolume(PlayingStream stream, float distance)
+ {
+ // OpenAL also limits the distance to <= AL_MAX_DISTANCE, but since we cull
+ // sources that are further away than stream.MaxDistance, we don't do that.
+ distance = MathF.Max(stream.ReferenceDistance, distance);
+ float gain;
+
+ // Technically these are formulas for gain not decibels but EHHHHHHHH.
+ switch (stream.Attenuation)
+ {
+ case Attenuation.Default:
+ gain = 1f;
+ break;
+ // You thought I'd implement clamping per source? Hell no that's just for the overall OpenAL setting
+ // I didn't even wanna implement this much for linear but figured it'd be cleaner.
+ case Attenuation.InverseDistanceClamped:
+ case Attenuation.InverseDistance:
+ gain = stream.ReferenceDistance
+ / (stream.ReferenceDistance
+ + stream.RolloffFactor * (distance - stream.ReferenceDistance));
+
+ break;
+ case Attenuation.LinearDistanceClamped:
+ case Attenuation.LinearDistance:
+ gain = 1f
+ - stream.RolloffFactor
+ * (distance - stream.ReferenceDistance)
+ / (stream.MaxDistance - stream.ReferenceDistance);
+
+ break;
+ case Attenuation.ExponentDistanceClamped:
+ case Attenuation.ExponentDistance:
+ gain = MathF.Pow(distance / stream.ReferenceDistance, -stream.RolloffFactor);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(
+ $"No implemented attenuation for {stream.Attenuation}");
+ }
+
+ var volume = MathF.Pow(10, stream.Volume / 10);
+ var actualGain = MathF.Max(0f, volume * gain);
+ stream.Source.SetVolumeDirect(actualGain);
+ }
+
+ private bool TryGetStreamPosition(PlayingStream stream, EntityQuery xformQuery, [NotNullWhen(true)] out MapCoordinates? mapPos)
+ {
+ if (stream.TrackingCoordinates != null)
+ {
+ mapPos = stream.TrackingCoordinates.Value.ToMap(EntityManager);
+ if (mapPos != MapCoordinates.Nullspace)
+ return true;
+ }
+
+ if (xformQuery.TryGetComponent(stream.TrackingEntity, out var xform)
+ && xform.MapID != MapId.Nullspace)
+ {
+ mapPos = new MapCoordinates(_xformSys.GetWorldPosition(xform, xformQuery), xform.MapID);
+ return true;
+ }
+
+ if (stream.TrackingFallbackCoordinates != null)
+ {
+ mapPos = stream.TrackingFallbackCoordinates.Value.ToMap(EntityManager);
+ return mapPos != MapCoordinates.Nullspace;
+ }
+
+ mapPos = MapCoordinates.Nullspace;
+ return false;
+ }
+
+ #region Play AudioStream
+ private bool TryGetAudio(string filename, [NotNullWhen(true)] out AudioResource? audio)
+ {
+ if (_resourceCache.TryGetResource(new ResPath(filename), out audio))
+ return true;
+
+ _sawmill.Error($"Server tried to play audio file {filename} which does not exist.");
+ return false;
+ }
+
+ private bool TryCreateAudioSource(AudioStream stream, [NotNullWhen(true)] out IClydeAudioSource? source)
+ {
+ if (!_timing.IsFirstTimePredicted)
+ {
+ source = null;
+ _sawmill.Error($"Tried to create audio source outside of prediction!");
+ DebugTools.Assert(false);
+ return false;
+ }
+
+ source = _clyde.CreateAudioSource(stream);
+ return source != null;
+ }
+
+ private PlayingStream CreateAndStartPlayingStream(IClydeAudioSource source, AudioParams? audioParams, AudioStream stream)
+ {
+ ApplyAudioParams(audioParams, source, stream);
+ source.StartPlaying();
+ var playing = new PlayingStream
+ {
+ Source = source,
+ Attenuation = audioParams?.Attenuation ?? Attenuation.Default,
+ MaxDistance = audioParams?.MaxDistance ?? float.MaxValue,
+ ReferenceDistance = audioParams?.ReferenceDistance ?? 1f,
+ RolloffFactor = audioParams?.RolloffFactor ?? 1f,
+ Volume = audioParams?.Volume ?? 0
+ };
+ _playingClydeStreams.Add(playing);
+ return playing;
+ }
+
+ ///
+ /// Play an audio file globally, without position.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ ///
+ private IPlayingAudioStream? Play(string filename, AudioParams? audioParams = null, bool recordReplay = true)
+ {
+ if (recordReplay && _replayRecording.IsRecording)
+ {
+ _replayRecording.RecordReplayMessage(new PlayAudioGlobalMessage
+ {
+ FileName = filename,
+ AudioParams = audioParams ?? AudioParams.Default
+ });
+ }
+
+ return TryGetAudio(filename, out var audio) ? Play(audio, audioParams) : default;
+ }
+
+ ///
+ /// Play an audio stream globally, without position.
+ ///
+ /// The audio stream to play.
+ ///
+ private IPlayingAudioStream? Play(AudioStream stream, AudioParams? audioParams = null)
+ {
+ if (!TryCreateAudioSource(stream, out var source))
+ {
+ _sawmill.Error($"Error setting up global audio for {stream.Name}: {0}", Environment.StackTrace);
+ return null;
+ }
+
+ source.SetGlobal();
+
+ return CreateAndStartPlayingStream(source, audioParams, stream);
+ }
+
+ ///
+ /// Play an audio file following an entity.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ /// The entity "emitting" the audio.
+ /// The map or grid coordinates at which to play the audio when entity is invalid.
+ ///
+ private IPlayingAudioStream? Play(string filename, EntityUid entity, EntityCoordinates? fallbackCoordinates,
+ AudioParams? audioParams = null, bool recordReplay = true)
+ {
+ if (recordReplay && _replayRecording.IsRecording)
+ {
+ _replayRecording.RecordReplayMessage(new PlayAudioEntityMessage
+ {
+ FileName = filename,
+ NetEntity = GetNetEntity(entity),
+ FallbackCoordinates = GetNetCoordinates(fallbackCoordinates) ?? default,
+ AudioParams = audioParams ?? AudioParams.Default
+ });
+ }
+
+ return TryGetAudio(filename, out var audio) ? Play(audio, entity, fallbackCoordinates, audioParams) : default;
+ }
+
+ ///
+ /// Play an audio stream following an entity.
+ ///
+ /// The audio stream to play.
+ /// The entity "emitting" the audio.
+ /// The map or grid coordinates at which to play the audio when entity is invalid.
+ ///
+ private IPlayingAudioStream? Play(AudioStream stream, EntityUid entity, EntityCoordinates? fallbackCoordinates = null,
+ AudioParams? audioParams = null)
+ {
+ if (!TryCreateAudioSource(stream, out var source))
+ {
+ _sawmill.Error($"Error setting up entity audio for {stream.Name} / {ToPrettyString(entity)}: {0}", Environment.StackTrace);
+ return null;
+ }
+
+ var query = GetEntityQuery();
+ var xform = query.GetComponent(entity);
+ var worldPos = _xformSys.GetWorldPosition(xform, query);
+ fallbackCoordinates ??= GetFallbackCoordinates(new MapCoordinates(worldPos, xform.MapID));
+
+ if (!source.SetPosition(worldPos))
+ return Play(stream, fallbackCoordinates.Value, fallbackCoordinates.Value, audioParams);
+
+ var playing = CreateAndStartPlayingStream(source, audioParams, stream);
+ playing.TrackingEntity = entity;
+ playing.TrackingFallbackCoordinates = fallbackCoordinates != EntityCoordinates.Invalid ? fallbackCoordinates : null;
+ return playing;
+ }
+
+ ///
+ /// Play an audio file at a static position.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ /// The coordinates at which to play the audio.
+ /// The map or grid coordinates at which to play the audio when coordinates are invalid.
+ ///
+ private IPlayingAudioStream? Play(string filename, EntityCoordinates coordinates,
+ EntityCoordinates fallbackCoordinates, AudioParams? audioParams = null, bool recordReplay = true)
+ {
+ if (recordReplay && _replayRecording.IsRecording)
+ {
+ _replayRecording.RecordReplayMessage(new PlayAudioPositionalMessage
+ {
+ FileName = filename,
+ Coordinates = GetNetCoordinates(coordinates),
+ FallbackCoordinates = GetNetCoordinates(fallbackCoordinates),
+ AudioParams = audioParams ?? AudioParams.Default
+ });
+ }
+
+ return TryGetAudio(filename, out var audio) ? Play(audio, coordinates, fallbackCoordinates, audioParams) : default;
+ }
+
+ ///
+ /// Play an audio stream at a static position.
+ ///
+ /// The audio stream to play.
+ /// The coordinates at which to play the audio.
+ /// The map or grid coordinates at which to play the audio when coordinates are invalid.
+ ///
+ private IPlayingAudioStream? Play(AudioStream stream, EntityCoordinates coordinates,
+ EntityCoordinates fallbackCoordinates, AudioParams? audioParams = null)
+ {
+ if (!TryCreateAudioSource(stream, out var source))
+ {
+ _sawmill.Error($"Error setting up coordinates audio for {stream.Name} / {coordinates}: {0}", Environment.StackTrace);
+ return null;
+ }
+
+ if (!source.SetPosition(fallbackCoordinates.Position))
+ {
+ source.Dispose();
+ _sawmill.Warning($"Can't play positional audio \"{stream.Name}\", can't set position.");
+ return null;
+ }
+
+ var playing = CreateAndStartPlayingStream(source, audioParams, stream);
+ playing.TrackingCoordinates = coordinates;
+ playing.TrackingFallbackCoordinates = fallbackCoordinates != EntityCoordinates.Invalid ? fallbackCoordinates : null;
+ return playing;
+ }
+ #endregion
+
+ ///
+ public override IPlayingAudioStream? PlayPredicted(SoundSpecifier? sound, EntityUid source, EntityUid? user,
+ AudioParams? audioParams = null)
+ {
+ if (_timing.IsFirstTimePredicted || sound == null)
+ return Play(sound, Filter.Local(), source, false, audioParams);
+ return null; // uhh Lets hope predicted audio never needs to somehow store the playing audio....
+ }
+
+ public override IPlayingAudioStream? PlayPredicted(SoundSpecifier? sound, EntityCoordinates coordinates, EntityUid? user,
+ AudioParams? audioParams = null)
+ {
+ if (_timing.IsFirstTimePredicted || sound == null)
+ return Play(sound, Filter.Local(), coordinates, false, audioParams);
+ return null;
+ }
+
+ private void ApplyAudioParams(AudioParams? audioParams, IClydeAudioSource source, AudioStream audio)
+ {
+ if (!audioParams.HasValue)
+ return;
+
+ if (audioParams.Value.Variation.HasValue)
+ source.SetPitch(audioParams.Value.PitchScale
+ * (float) RandMan.NextGaussian(1, audioParams.Value.Variation.Value));
+ else
+ source.SetPitch(audioParams.Value.PitchScale);
+
+ source.SetVolume(audioParams.Value.Volume);
+ source.SetRolloffFactor(audioParams.Value.RolloffFactor);
+ source.SetMaxDistance(audioParams.Value.MaxDistance);
+ source.SetReferenceDistance(audioParams.Value.ReferenceDistance);
+ source.IsLooping = audioParams.Value.Loop;
+
+ // TODO clamp the offset inside of SetPlaybackPosition() itself.
+ var offset = audioParams.Value.PlayOffsetSeconds;
+ offset = Math.Clamp(offset, 0f, (float) audio.Length.TotalSeconds);
+ source.SetPlaybackPosition(offset);
+ }
+
+ public sealed class PlayingStream : IPlayingAudioStream
+ {
+ public uint? NetIdentifier;
+ public IClydeAudioSource Source = default!;
+ public EntityUid? TrackingEntity;
+ public EntityCoordinates? TrackingCoordinates;
+ public EntityCoordinates? TrackingFallbackCoordinates;
+ public bool Done;
+
+ public float Volume
+ {
+ get => _volume;
+ set
+ {
+ _volume = value;
+ Source.SetVolume(value);
+ }
+ }
+
+ private float _volume;
+
+ public float MaxDistance;
+ public float ReferenceDistance;
+ public float RolloffFactor;
+
+ public Attenuation Attenuation
+ {
+ get => _attenuation;
+ set
+ {
+ if (value == _attenuation) return;
+ _attenuation = value;
+ if (_attenuation != Attenuation.Default)
+ {
+ // Need to disable default attenuation when using a custom one
+ // Damn Sloth wanting linear ambience sounds so they smoothly cut-off and are short-range
+ Source.SetRolloffFactor(0f);
+ }
+ }
+ }
+ private Attenuation _attenuation = Attenuation.Default;
+
+ public void Stop()
+ {
+ Source.StopPlaying();
+ }
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayGlobal(string filename, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null)
+ {
+ return Play(filename, audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? Play(string filename, Filter playerFilter, EntityUid entity, bool recordReplay, AudioParams? audioParams = null)
+ {
+ return Play(filename, entity, null, audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? Play(string filename, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null)
+ {
+ return Play(filename, coordinates, GetFallbackCoordinates(coordinates.ToMap(EntityManager)), audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayGlobal(string filename, ICommonSession recipient, AudioParams? audioParams = null)
+ {
+ return Play(filename, audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayGlobal(string filename, EntityUid recipient, AudioParams? audioParams = null)
+ {
+ return Play(filename, audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayEntity(string filename, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
+ {
+ return Play(filename, uid, null, audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayEntity(string filename, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
+ {
+ return Play(filename, uid, null, audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayStatic(string filename, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
+ {
+ return Play(filename, coordinates, GetFallbackCoordinates(coordinates.ToMap(EntityManager)), audioParams);
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayStatic(string filename, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
+ {
+ return Play(filename, coordinates, GetFallbackCoordinates(coordinates.ToMap(EntityManager)), audioParams);
+ }
+}
diff --git a/Robust.Client/GameObjects/EntitySystems/EyeSystem.cs b/Robust.Client/GameObjects/EntitySystems/EyeSystem.cs
index a30b73aab44..f2a7bba70c6 100644
--- a/Robust.Client/GameObjects/EntitySystems/EyeSystem.cs
+++ b/Robust.Client/GameObjects/EntitySystems/EyeSystem.cs
@@ -1,9 +1,8 @@
using Robust.Client.Graphics;
using Robust.Client.Physics;
-using Robust.Client.Player;
using Robust.Shared.GameObjects;
-using Robust.Shared.Graphics;
using Robust.Shared.IoC;
+using Robust.Shared.Player;
namespace Robust.Client.GameObjects;
@@ -26,17 +25,13 @@ public override void Initialize()
private void OnEyeAutoState(EntityUid uid, EyeComponent component, ref AfterAutoHandleStateEvent args)
{
- UpdateEye(component);
+ UpdateEye((uid, component));
}
private void OnEyeAttached(EntityUid uid, EyeComponent component, LocalPlayerAttachedEvent args)
{
- // TODO: This probably shouldn't be nullable bruv.
- if (component._eye != null)
- {
- _eyeManager.CurrentEye = component._eye;
- }
-
+ UpdateEye((uid, component));
+ _eyeManager.CurrentEye = component.Eye;
var ev = new EyeAttachedEvent(uid, component);
RaiseLocalEvent(uid, ref ev, true);
}
@@ -48,13 +43,7 @@ private void OnEyeDetached(EntityUid uid, EyeComponent component, LocalPlayerDet
private void OnInit(EntityUid uid, EyeComponent component, ComponentInit args)
{
- component._eye = new Eye
- {
- Position = Transform(uid).MapPosition,
- Zoom = component.Zoom,
- DrawFov = component.DrawFov,
- Rotation = component.Rotation,
- };
+ UpdateEye((uid, component));
}
///
@@ -64,7 +53,7 @@ public override void FrameUpdate(float frameTime)
while (query.MoveNext(out var uid, out var eyeComponent))
{
- if (eyeComponent._eye == null)
+ if (eyeComponent.Eye == null)
continue;
if (!TryComp(eyeComponent.Target, out var xform))
@@ -73,7 +62,7 @@ public override void FrameUpdate(float frameTime)
eyeComponent.Target = null;
}
- eyeComponent._eye.Position = xform.MapPosition;
+ eyeComponent.Eye.Position = xform.MapPosition;
}
}
}
diff --git a/Robust.Client/GameObjects/EntitySystems/MapSystem.cs b/Robust.Client/GameObjects/EntitySystems/MapSystem.cs
index e57dbc7bb6b..b9ed64b92d9 100644
--- a/Robust.Client/GameObjects/EntitySystems/MapSystem.cs
+++ b/Robust.Client/GameObjects/EntitySystems/MapSystem.cs
@@ -11,7 +11,7 @@ public sealed class MapSystem : SharedMapSystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IOverlayManager _overlayManager = default!;
- [Dependency] private readonly IClientResourceCache _resource = default!;
+ [Dependency] private readonly IResourceCache _resource = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
public override void Initialize()
diff --git a/Robust.Client/GameObjects/EntitySystems/PointLightSystem.cs b/Robust.Client/GameObjects/EntitySystems/PointLightSystem.cs
index c70a21d1c84..a29a7d01537 100644
--- a/Robust.Client/GameObjects/EntitySystems/PointLightSystem.cs
+++ b/Robust.Client/GameObjects/EntitySystems/PointLightSystem.cs
@@ -10,7 +10,7 @@ namespace Robust.Client.GameObjects
{
public sealed class PointLightSystem : SharedPointLightSystem
{
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly LightTreeSystem _lightTree = default!;
public override void Initialize()
diff --git a/Robust.Client/GameObjects/EntitySystems/SpriteSystem.cs b/Robust.Client/GameObjects/EntitySystems/SpriteSystem.cs
index 4c1f541c100..0067b886387 100644
--- a/Robust.Client/GameObjects/EntitySystems/SpriteSystem.cs
+++ b/Robust.Client/GameObjects/EntitySystems/SpriteSystem.cs
@@ -32,7 +32,7 @@ public sealed partial class SpriteSystem : EntitySystem
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly ILogManager _logManager = default!;
private readonly Queue _inertUpdateQueue = new();
diff --git a/Robust.Client/GameObjects/EntitySystems/TransformSystem.cs b/Robust.Client/GameObjects/EntitySystems/TransformSystem.cs
index 91540803b05..9f997d74e49 100644
--- a/Robust.Client/GameObjects/EntitySystems/TransformSystem.cs
+++ b/Robust.Client/GameObjects/EntitySystems/TransformSystem.cs
@@ -54,9 +54,10 @@ public override void ActivateLerp(EntityUid uid, TransformComponent xform)
// should show the entity lerping.
// - If the client predicts an entity will move while already lerping due to a state-application, it should
// clear the state's lerp, under the assumption that the client predicted the state and already rendered
- // the entity in the final position.
+ // the entity in the state's final position.
// - If the client predicts that an entity moves, then we only lerp if this is the first time that the tick
- // was predicted. I.e., we assume the entity was already rendered in it's final of that lerp.
+ // was predicted. I.e., we assume the entity was already rendered in the final position that was
+ // previously predicted.
// - If the client predicts that an entity should lerp twice in the same tick, then we need to combine them.
// I.e. moving from a->b then b->c, the client should lerp from a->c.
diff --git a/Robust.Client/GameStates/ClientGameStateManager.cs b/Robust.Client/GameStates/ClientGameStateManager.cs
index ef84e427dd7..0756bf8ac53 100644
--- a/Robust.Client/GameStates/ClientGameStateManager.cs
+++ b/Robust.Client/GameStates/ClientGameStateManager.cs
@@ -129,6 +129,8 @@ public sealed class ClientGameStateManager : IClientGameStateManager
public bool DropStates;
#endif
+ private bool _resettingPredictedEntities;
+
///
public void Initialize()
{
@@ -151,6 +153,7 @@ public void Initialize()
_config.OnValueChanged(CVars.NetPredictLagBias, i => PredictLagBias = i, true);
_config.OnValueChanged(CVars.NetStateBufMergeThreshold, i => StateBufferMergeThreshold = i, true);
_config.OnValueChanged(CVars.NetPVSEntityExitBudget, i => _pvsDetachBudget = i, true);
+ _config.OnValueChanged(CVars.NetMaxBufferSize, i => _processor.MaxBufferSize = i, true);
_processor.Interpolation = _config.GetCVar(CVars.NetInterp);
_processor.BufferSize = _config.GetCVar(CVars.NetBufferSize);
@@ -165,6 +168,8 @@ public void Initialize()
_conHost.RegisterCommand("localdelete", Loc.GetString("cmd-local-delete-desc"), Loc.GetString("cmd-local-delete-help"), LocalDeleteEntCommand);
_conHost.RegisterCommand("fullstatereset", Loc.GetString("cmd-full-state-reset-desc"), Loc.GetString("cmd-full-state-reset-help"), (_,_,_) => RequestFullState());
+ _entities.ComponentAdded += OnComponentAdded;
+
var metaId = _compFactory.GetRegistration(typeof(MetaDataComponent)).NetID;
if (!metaId.HasValue)
throw new InvalidOperationException("MetaDataComponent does not have a NetId.");
@@ -172,6 +177,23 @@ public void Initialize()
_metaCompNetId = metaId.Value;
}
+ private void OnComponentAdded(AddedComponentEventArgs args)
+ {
+ if (_resettingPredictedEntities)
+ {
+ var comp = args.ComponentType;
+
+ if (comp.NetID == null)
+ return;
+
+ _sawmill.Error($"""
+ Added component {comp.Name} with net id {comp.NetID} while resetting predicted entities.
+ Stack trace:
+ {Environment.StackTrace}
+ """);
+ }
+ }
+
///
public void Reset()
{
@@ -543,40 +565,50 @@ public void ResetPredictedEntities()
countReset += 1;
- foreach (var (netId, comp) in meta.NetComponents)
+ try
{
- if (!comp.NetSyncEnabled)
- continue;
+ _resettingPredictedEntities = true;
- // Was this component added during prediction?
- if (comp.CreationTick > _timing.LastRealTick)
+ foreach (var (netId, comp) in meta.NetComponents)
{
- if (last.ContainsKey(netId))
+ if (!comp.NetSyncEnabled)
+ continue;
+
+ // Was this component added during prediction?
+ if (comp.CreationTick > _timing.LastRealTick)
{
- // Component was probably removed and then re-addedd during a single prediction run
- // Just reset state as normal.
- comp.ClearCreationTick();
+ if (last.ContainsKey(netId))
+ {
+ // Component was probably removed and then re-addedd during a single prediction run
+ // Just reset state as normal.
+ comp.ClearCreationTick();
+ }
+ else
+ {
+ toRemove.Add(comp);
+ if (_sawmill.Level <= LogLevel.Debug)
+ _sawmill.Debug($" A new component was added: {comp.GetType()}");
+ continue;
+ }
}
- else
+
+ if (comp.LastModifiedTick <= _timing.LastRealTick ||
+ !last.TryGetValue(netId, out var compState))
{
- toRemove.Add(comp);
- if (_sawmill.Level <= LogLevel.Debug)
- _sawmill.Debug($" A new component was added: {comp.GetType()}");
continue;
}
- }
- if (comp.LastModifiedTick <= _timing.LastRealTick || !last.TryGetValue(netId, out var compState))
- {
- continue;
- }
-
- if (_sawmill.Level <= LogLevel.Debug)
- _sawmill.Debug($" A component was dirtied: {comp.GetType()}");
+ if (_sawmill.Level <= LogLevel.Debug)
+ _sawmill.Debug($" A component was dirtied: {comp.GetType()}");
- var handleState = new ComponentHandleState(compState, null);
- _entities.EventBus.RaiseComponentEvent(comp, ref handleState);
- comp.LastModifiedTick = _timing.LastRealTick;
+ var handleState = new ComponentHandleState(compState, null);
+ _entities.EventBus.RaiseComponentEvent(comp, ref handleState);
+ comp.LastModifiedTick = _timing.LastRealTick;
+ }
+ }
+ finally
+ {
+ _resettingPredictedEntities = false;
}
if (toRemove.Count > 0)
diff --git a/Robust.Client/GameStates/GameStateProcessor.cs b/Robust.Client/GameStates/GameStateProcessor.cs
index cfe9b9210c0..e69e8b401b5 100644
--- a/Robust.Client/GameStates/GameStateProcessor.cs
+++ b/Robust.Client/GameStates/GameStateProcessor.cs
@@ -14,8 +14,6 @@ namespace Robust.Client.GameStates
///
internal sealed class GameStateProcessor : IGameStateProcessor
{
- public const int MaxBufferSize = 512;
-
private readonly IClientGameTiming _timing;
private readonly IClientGameStateManager _state;
private readonly ISawmill _logger;
@@ -28,6 +26,8 @@ internal sealed class GameStateProcessor : IGameStateProcessor
public (GameTick Tick, DateTime Time)? LastFullStateRequested { get; private set; } = (GameTick.Zero, DateTime.MaxValue);
private int _bufferSize;
+ private int _maxBufferSize = 512;
+ public const int MinimumMaxBufferSize = 256;
///
/// This dictionary stores the full most recently received server state of any entity. This is used whenever predicted entities get reset.
@@ -48,7 +48,14 @@ internal readonly Dictionary> _las
public int BufferSize
{
get => _bufferSize;
- set => _bufferSize = value < 0 ? 0 : value;
+ set => _bufferSize = Math.Max(value, 0);
+ }
+
+ public int MaxBufferSize
+ {
+ get => _maxBufferSize;
+ // We place a lower bound on the maximum size to avoid spamming servers with full game state requests.
+ set => _maxBufferSize = Math.Max(value, MinimumMaxBufferSize);
}
///
@@ -100,21 +107,21 @@ public bool AddNewState(GameState state)
return true;
}
- if (LastFullState == null && state.FromSequence == GameTick.Zero && state.ToSequence >= LastFullStateRequested!.Value.Tick)
+ if (LastFullState == null && state.FromSequence == GameTick.Zero)
{
- LastFullState = state;
-
- if (Logging)
+ if (state.ToSequence >= LastFullStateRequested!.Value.Tick)
+ {
+ LastFullState = state;
_logger.Info($"Received Full GameState: to={state.ToSequence}, sz={state.PayloadSize}");
+ return true;
+ }
- return true;
+ _logger.Info($"Received a late full game state. Received: {state.ToSequence}. Requested: {LastFullStateRequested.Value.Tick}");
}
if (LastFullState != null && state.ToSequence <= LastFullState.ToSequence)
{
- if (Logging)
- _logger.Info($"While waiting for full, received late GameState with lower to={state.ToSequence} than the last full state={LastFullState.ToSequence}");
-
+ _logger.Info($"While waiting for full, received late GameState with lower to={state.ToSequence} than the last full state={LastFullState.ToSequence}");
return false;
}
diff --git a/Robust.Client/GameStates/NetEntityOverlay.cs b/Robust.Client/GameStates/NetEntityOverlay.cs
index ff527e7ebaf..e63c3e33af4 100644
--- a/Robust.Client/GameStates/NetEntityOverlay.cs
+++ b/Robust.Client/GameStates/NetEntityOverlay.cs
@@ -40,7 +40,7 @@ sealed class NetEntityOverlay : Overlay
public NetEntityOverlay()
{
IoCManager.InjectDependencies(this);
- var cache = IoCManager.Resolve();
+ var cache = IoCManager.Resolve();
_font = new VectorFont(cache.GetResource("/EngineFonts/NotoSans/NotoSans-Regular.ttf"), 10);
_lineHeight = _font.GetLineHeight(1);
diff --git a/Robust.Client/GameStates/NetGraphOverlay.cs b/Robust.Client/GameStates/NetGraphOverlay.cs
index 38bbce15217..26c559b9097 100644
--- a/Robust.Client/GameStates/NetGraphOverlay.cs
+++ b/Robust.Client/GameStates/NetGraphOverlay.cs
@@ -53,7 +53,7 @@ internal sealed class NetGraphOverlay : Overlay
public NetGraphOverlay()
{
IoCManager.InjectDependencies(this);
- var cache = IoCManager.Resolve();
+ var cache = IoCManager.Resolve();
_font = new VectorFont(cache.GetResource("/EngineFonts/NotoSans/NotoSans-Regular.ttf"), 10);
_gameStateManager.GameStateApplied += HandleGameStateApplied;
diff --git a/Robust.Client/Graphics/Audio/ClydeAudio.ALDisposeQueues.cs b/Robust.Client/Graphics/Audio/ClydeAudio.ALDisposeQueues.cs
new file mode 100644
index 00000000000..10d0abc4f3b
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ClydeAudio.ALDisposeQueues.cs
@@ -0,0 +1,59 @@
+using System.Collections.Concurrent;
+using OpenTK.Audio.OpenAL;
+
+namespace Robust.Client.Graphics.Audio
+{
+ internal partial class ClydeAudio
+ {
+ // Used to track audio sources that were disposed in the finalizer thread,
+ // so we need to properly send them off in the main thread.
+ private readonly ConcurrentQueue<(int sourceHandle, int filterHandle)> _sourceDisposeQueue = new();
+ private readonly ConcurrentQueue<(int sourceHandle, int filterHandle)> _bufferedSourceDisposeQueue = new();
+ private readonly ConcurrentQueue _bufferDisposeQueue = new();
+
+ private void _flushALDisposeQueues()
+ {
+ // Clear out finalized audio sources.
+ while (_sourceDisposeQueue.TryDequeue(out var handles))
+ {
+ OpenALSawmill.Debug("Cleaning out source {0} which finalized in another thread.", handles.sourceHandle);
+ if (IsEfxSupported) RemoveEfx(handles);
+ AL.DeleteSource(handles.sourceHandle);
+ _checkAlError();
+ _audioSources.Remove(handles.sourceHandle);
+ }
+
+ // Clear out finalized buffered audio sources.
+ while (_bufferedSourceDisposeQueue.TryDequeue(out var handles))
+ {
+ OpenALSawmill.Debug("Cleaning out buffered source {0} which finalized in another thread.", handles.sourceHandle);
+ if (IsEfxSupported) RemoveEfx(handles);
+ AL.DeleteSource(handles.sourceHandle);
+ _checkAlError();
+ _bufferedAudioSources.Remove(handles.sourceHandle);
+ }
+
+ // Clear out finalized audio buffers.
+ while (_bufferDisposeQueue.TryDequeue(out var handle))
+ {
+ AL.DeleteBuffer(handle);
+ _checkAlError();
+ }
+ }
+
+ private void DeleteSourceOnMainThread(int sourceHandle, int filterHandle)
+ {
+ _sourceDisposeQueue.Enqueue((sourceHandle, filterHandle));
+ }
+
+ private void DeleteBufferedSourceOnMainThread(int bufferedSourceHandle, int filterHandle)
+ {
+ _bufferedSourceDisposeQueue.Enqueue((bufferedSourceHandle, filterHandle));
+ }
+
+ private void DeleteAudioBufferOnMainThread(int bufferHandle)
+ {
+ _bufferDisposeQueue.Enqueue(bufferHandle);
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/ClydeAudio.AudioSources.cs b/Robust.Client/Graphics/Audio/ClydeAudio.AudioSources.cs
new file mode 100644
index 00000000000..3ef560a82b2
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ClydeAudio.AudioSources.cs
@@ -0,0 +1,680 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using OpenTK.Audio.OpenAL;
+using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
+using OpenTK.Mathematics;
+using Robust.Client.Audio;
+using Robust.Shared;
+using Robust.Shared.Configuration;
+using Robust.Shared.IoC;
+using Robust.Shared.Audio;
+using Robust.Shared.Log;
+using Robust.Shared.Maths;
+using Vector2 = System.Numerics.Vector2;
+using Robust.Shared.Utility;
+
+namespace Robust.Client.Graphics.Audio
+{
+ internal partial class ClydeAudio
+ {
+ private sealed class AudioSource : IClydeAudioSource
+ {
+ private int SourceHandle;
+ private readonly ClydeAudio _master;
+ private readonly AudioStream _sourceStream;
+ private int FilterHandle;
+#if DEBUG
+ private bool _didPositionWarning;
+#endif
+
+ private float _gain;
+
+ private bool IsEfxSupported => _master.IsEfxSupported;
+
+ public AudioSource(ClydeAudio master, int sourceHandle, AudioStream sourceStream)
+ {
+ _master = master;
+ SourceHandle = sourceHandle;
+ _sourceStream = sourceStream;
+ AL.GetSource(SourceHandle, ALSourcef.Gain, out _gain);
+ }
+
+ public void StartPlaying()
+ {
+ _checkDisposed();
+ AL.SourcePlay(SourceHandle);
+ _master._checkAlError();
+ }
+
+ public void StopPlaying()
+ {
+ if (_isDisposed()) return;
+ AL.SourceStop(SourceHandle);
+ _master._checkAlError();
+ }
+
+ public bool IsPlaying
+ {
+ get
+ {
+ _checkDisposed();
+ var state = AL.GetSourceState(SourceHandle);
+ return state == ALSourceState.Playing;
+ }
+ }
+
+ public bool IsLooping
+ {
+ get
+ {
+ _checkDisposed();
+ AL.GetSource(SourceHandle, ALSourceb.Looping, out var ret);
+ _master._checkAlError();
+ return ret;
+ }
+ set
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle, ALSourceb.Looping, value);
+ _master._checkAlError();
+ }
+ }
+
+ public bool IsGlobal
+ {
+ get
+ {
+ _checkDisposed();
+ AL.GetSource(SourceHandle, ALSourceb.SourceRelative, out var value);
+ _master._checkAlError();
+ return value;
+ }
+ }
+
+ public void SetGlobal()
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle, ALSourceb.SourceRelative, true);
+ _master._checkAlError();
+ }
+
+ public void SetVolume(float decibels)
+ {
+ _checkDisposed();
+ var priorOcclusion = 1f;
+ if (!IsEfxSupported)
+ {
+ AL.GetSource(SourceHandle, ALSourcef.Gain, out var priorGain);
+ priorOcclusion = priorGain / _gain;
+ }
+ _gain = MathF.Pow(10, decibels / 10);
+ AL.Source(SourceHandle, ALSourcef.Gain, _gain * priorOcclusion);
+ _master._checkAlError();
+ }
+
+ public void SetVolumeDirect(float gain)
+ {
+ _checkDisposed();
+ var priorOcclusion = 1f;
+ if (!IsEfxSupported)
+ {
+ AL.GetSource(SourceHandle, ALSourcef.Gain, out var priorGain);
+ priorOcclusion = priorGain / _gain;
+ }
+ _gain = gain;
+ AL.Source(SourceHandle, ALSourcef.Gain, _gain * priorOcclusion);
+ _master._checkAlError();
+ }
+
+ public void SetMaxDistance(float distance)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle, ALSourcef.MaxDistance, distance);
+ _master._checkAlError();
+ }
+
+ public void SetRolloffFactor(float rolloffFactor)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle, ALSourcef.RolloffFactor, rolloffFactor);
+ _master._checkAlError();
+ }
+
+ public void SetReferenceDistance(float refDistance)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle, ALSourcef.ReferenceDistance, refDistance);
+ _master._checkAlError();
+ }
+
+ public void SetOcclusion(float blocks)
+ {
+ _checkDisposed();
+ var cutoff = MathF.Exp(-blocks * 1);
+ var gain = MathF.Pow(cutoff, 0.1f);
+ if (IsEfxSupported)
+ {
+ SetOcclusionEfx(gain, cutoff);
+ }
+ else
+ {
+ gain *= gain * gain;
+ AL.Source(SourceHandle, ALSourcef.Gain, _gain * gain);
+ }
+ _master._checkAlError();
+ }
+
+ private void SetOcclusionEfx(float gain, float cutoff)
+ {
+ if (FilterHandle == 0)
+ {
+ FilterHandle = EFX.GenFilter();
+ EFX.Filter(FilterHandle, FilterInteger.FilterType, (int) FilterType.Lowpass);
+ }
+
+ EFX.Filter(FilterHandle, FilterFloat.LowpassGain, gain);
+ EFX.Filter(FilterHandle, FilterFloat.LowpassGainHF, cutoff);
+ AL.Source(SourceHandle, ALSourcei.EfxDirectFilter, FilterHandle);
+ }
+
+ public void SetPlaybackPosition(float seconds)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle, ALSourcef.SecOffset, seconds);
+ _master._checkAlError();
+ }
+
+ public bool SetPosition(Vector2 position)
+ {
+ _checkDisposed();
+
+ var (x, y) = position;
+
+ if (!AreFinite(x, y))
+ {
+ return false;
+ }
+#if DEBUG
+ // OpenAL doesn't seem to want to play stereo positionally.
+ // Log a warning if people try to.
+ if (_sourceStream.ChannelCount > 1 && !_didPositionWarning)
+ {
+ _didPositionWarning = true;
+ _master.OpenALSawmill.Warning("Attempting to set position on audio source with multiple audio channels! Stream: '{0}'. Make sure the audio is MONO, not stereo.",
+ _sourceStream.Name);
+ // warning isn't enough, people just ignore it :(
+ DebugTools.Assert(false, $"Attempting to set position on audio source with multiple audio channels! Stream: '{_sourceStream.Name}'. Make sure the audio is MONO, not stereo.");
+ }
+#endif
+
+ AL.Source(SourceHandle, ALSource3f.Position, x, y, 0);
+ _master._checkAlError();
+ return true;
+ }
+
+ private static bool AreFinite(float x, float y)
+ {
+ if (float.IsFinite(x) && float.IsFinite(y))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void SetVelocity(Vector2 velocity)
+ {
+ _checkDisposed();
+
+ var (x, y) = velocity;
+
+ if (!AreFinite(x, y))
+ {
+ return;
+ }
+
+ AL.Source(SourceHandle, ALSource3f.Velocity, x, y, 0);
+
+ _master._checkAlError();
+ }
+
+ public void SetPitch(float pitch)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle, ALSourcef.Pitch, pitch);
+ _master._checkAlError();
+ }
+
+ ~AudioSource()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (!disposing)
+ {
+ // We can't run this code inside the finalizer thread so tell Clyde to clear it up later.
+ _master.DeleteSourceOnMainThread(SourceHandle, FilterHandle);
+ }
+ else
+ {
+ if (FilterHandle != 0) EFX.DeleteFilter(FilterHandle);
+ AL.DeleteSource(SourceHandle);
+ _master._audioSources.Remove(SourceHandle);
+ _master._checkAlError();
+ }
+
+ SourceHandle = -1;
+ }
+
+ private bool _isDisposed()
+ {
+ return SourceHandle == -1;
+ }
+
+ private void _checkDisposed()
+ {
+ if (SourceHandle == -1)
+ {
+ throw new ObjectDisposedException(nameof(AudioSource));
+ }
+ }
+ }
+
+ private sealed class BufferedAudioSource : IClydeBufferedAudioSource
+ {
+ private int? SourceHandle = null;
+ private int[] BufferHandles;
+ private Dictionary BufferMap = new();
+ private readonly ClydeAudio _master;
+ private bool _mono = true;
+ private bool _float = false;
+ private int FilterHandle;
+
+ private float _gain;
+
+ public int SampleRate { get; set; } = 44100;
+
+ private bool IsEfxSupported => _master.IsEfxSupported;
+
+ public BufferedAudioSource(ClydeAudio master, int sourceHandle, int[] bufferHandles, bool floatAudio = false)
+ {
+ _master = master;
+ SourceHandle = sourceHandle;
+ BufferHandles = bufferHandles;
+ for (int i = 0; i < BufferHandles.Length; i++)
+ {
+ var bufferHandle = BufferHandles[i];
+ BufferMap[bufferHandle] = i;
+ }
+ _float = floatAudio;
+ AL.GetSource(sourceHandle, ALSourcef.Gain, out _gain);
+ }
+
+ public void StartPlaying()
+ {
+ _checkDisposed();
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.SourcePlay(stackalloc int[] {SourceHandle!.Value});
+ _master._checkAlError();
+ }
+
+ public void StopPlaying()
+ {
+ if (_isDisposed()) return;
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.SourceStop(SourceHandle!.Value);
+ _master._checkAlError();
+ }
+
+ public bool IsPlaying
+ {
+ get
+ {
+ _checkDisposed();
+ // ReSharper disable once PossibleInvalidOperationException
+ var state = AL.GetSourceState(SourceHandle!.Value);
+ return state == ALSourceState.Playing;
+ }
+ }
+
+ public bool IsLooping
+ {
+ get => throw new NotImplementedException();
+ set => throw new NotImplementedException();
+ }
+
+ public void SetGlobal()
+ {
+ _checkDisposed();
+ _mono = false;
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.Source(SourceHandle!.Value, ALSourceb.SourceRelative, true);
+ _master._checkAlError();
+ }
+
+ public void SetLooping()
+ {
+ // TODO?waaaaddDDDDD
+ }
+
+ public void SetVolume(float decibels)
+ {
+ _checkDisposed();
+ var priorOcclusion = 1f;
+ if (!IsEfxSupported)
+ {
+ AL.GetSource(SourceHandle!.Value, ALSourcef.Gain, out var priorGain);
+ priorOcclusion = priorGain / _gain;
+ }
+ _gain = MathF.Pow(10, decibels / 10);
+ AL.Source(SourceHandle!.Value, ALSourcef.Gain, _gain * priorOcclusion);
+ _master._checkAlError();
+ }
+
+ public void SetVolumeDirect(float gain)
+ {
+ _checkDisposed();
+ var priorOcclusion = 1f;
+ if (!IsEfxSupported)
+ {
+ AL.GetSource(SourceHandle!.Value, ALSourcef.Gain, out var priorGain);
+ priorOcclusion = priorGain / _gain;
+ }
+ _gain = gain;
+ AL.Source(SourceHandle!.Value, ALSourcef.Gain, _gain * priorOcclusion);
+ _master._checkAlError();
+ }
+
+ public void SetMaxDistance(float distance)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle!.Value, ALSourcef.MaxDistance, distance);
+ _master._checkAlError();
+ }
+
+ public void SetRolloffFactor(float rolloffFactor)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle!.Value, ALSourcef.RolloffFactor, rolloffFactor);
+ _master._checkAlError();
+ }
+
+ public void SetReferenceDistance(float refDistance)
+ {
+ _checkDisposed();
+ AL.Source(SourceHandle!.Value, ALSourcef.ReferenceDistance, refDistance);
+ _master._checkAlError();
+ }
+
+ public void SetOcclusion(float blocks)
+ {
+ _checkDisposed();
+ var cutoff = MathF.Exp(-blocks * 1.5f);
+ var gain = MathF.Pow(cutoff, 0.1f);
+ if (IsEfxSupported)
+ {
+ SetOcclusionEfx(gain, cutoff);
+ }
+ else
+ {
+ gain *= gain * gain;
+ AL.Source(SourceHandle!.Value, ALSourcef.Gain, gain * _gain);
+ }
+
+ _master._checkAlError();
+ }
+
+ private void SetOcclusionEfx(float gain, float cutoff)
+ {
+ if (FilterHandle == 0)
+ {
+ FilterHandle = EFX.GenFilter();
+ EFX.Filter(FilterHandle, FilterInteger.FilterType, (int) FilterType.Lowpass);
+ }
+ EFX.Filter(FilterHandle, FilterFloat.LowpassGain, gain);
+ EFX.Filter(FilterHandle, FilterFloat.LowpassGainHF, cutoff);
+ AL.Source(SourceHandle!.Value, ALSourcei.EfxDirectFilter, FilterHandle);
+ }
+
+ public void SetPlaybackPosition(float seconds)
+ {
+ _checkDisposed();
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.Source(SourceHandle!.Value, ALSourcef.SecOffset, seconds);
+ _master._checkAlError();
+ }
+
+ public bool IsGlobal
+ {
+ get
+ {
+ _checkDisposed();
+ AL.GetSource(SourceHandle!.Value, ALSourceb.SourceRelative, out var value);
+ _master._checkAlError();
+ return value;
+ }
+ }
+
+ public bool SetPosition(Vector2 position)
+ {
+ _checkDisposed();
+
+ var (x, y) = position;
+
+ if (!AreFinite(x, y))
+ {
+ return false;
+ }
+
+ _mono = true;
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.Source(SourceHandle!.Value, ALSource3f.Position, x, y, 0);
+ _master._checkAlError();
+ return true;
+ }
+
+ private static bool AreFinite(float x, float y)
+ {
+ if (float.IsFinite(x) && float.IsFinite(y))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void SetVelocity(Vector2 velocity)
+ {
+ _checkDisposed();
+
+ var (x, y) = velocity;
+
+ if (!AreFinite(x, y))
+ {
+ return;
+ }
+
+ AL.Source(SourceHandle!.Value, ALSource3f.Velocity, x, y, 0);
+
+ _master._checkAlError();
+ }
+
+ public void SetPitch(float pitch)
+ {
+ _checkDisposed();
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.Source(SourceHandle!.Value, ALSourcef.Pitch, pitch);
+ _master._checkAlError();
+ }
+
+ ~BufferedAudioSource()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (SourceHandle == null) return;
+
+ if (!_master.IsMainThread())
+ {
+ // We can't run this code inside another thread so tell Clyde to clear it up later.
+ _master.DeleteBufferedSourceOnMainThread(SourceHandle.Value, FilterHandle);
+ for (var i = 0; i < BufferHandles.Length; i++)
+ _master.DeleteAudioBufferOnMainThread(BufferHandles[i]);
+ }
+ else
+ {
+ if (FilterHandle != 0) EFX.DeleteFilter(FilterHandle);
+ AL.DeleteSource(SourceHandle.Value);
+ AL.DeleteBuffers(BufferHandles);
+ _master._bufferedAudioSources.Remove(SourceHandle.Value);
+ _master._checkAlError();
+ }
+
+ SourceHandle = null;
+ }
+
+ private bool _isDisposed()
+ {
+ return SourceHandle == null;
+ }
+
+ private void _checkDisposed()
+ {
+ if (SourceHandle == null)
+ {
+ throw new ObjectDisposedException(nameof(AudioSource));
+ }
+ }
+
+ public int GetNumberOfBuffersProcessed()
+ {
+ _checkDisposed();
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.GetSource(SourceHandle!.Value, ALGetSourcei.BuffersProcessed, out var buffersProcessed);
+ return buffersProcessed;
+ }
+
+ public unsafe void GetBuffersProcessed(Span handles)
+ {
+ _checkDisposed();
+ var entries = Math.Min(Math.Min(handles.Length, BufferHandles.Length), GetNumberOfBuffersProcessed());
+ fixed (int* ptr = handles)
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.SourceUnqueueBuffers(SourceHandle!.Value, entries, ptr);
+
+ for (var i = 0; i < entries; i++)
+ handles[i] = BufferMap[handles[i]];
+ }
+
+ public unsafe void WriteBuffer(int handle, ReadOnlySpan data)
+ {
+ _checkDisposed();
+
+ if(_float)
+ throw new InvalidOperationException("Can't write ushort numbers to buffers when buffer type is float!");
+
+ if (handle >= BufferHandles.Length)
+ throw new ArgumentOutOfRangeException(nameof(handle),
+ $"Got {handle}. Expected less than {BufferHandles.Length}");
+
+ fixed (ushort* ptr = data)
+ {
+ AL.BufferData(BufferHandles[handle], _mono ? ALFormat.Mono16 : ALFormat.Stereo16, (IntPtr) ptr,
+ _mono ? data.Length / 2 * sizeof(ushort) : data.Length * sizeof(ushort), SampleRate);
+ }
+ }
+
+ public unsafe void WriteBuffer(int handle, ReadOnlySpan data)
+ {
+ _checkDisposed();
+
+ if(!_float)
+ throw new InvalidOperationException("Can't write float numbers to buffers when buffer type is ushort!");
+
+ if (handle >= BufferHandles.Length)
+ throw new ArgumentOutOfRangeException(nameof(handle),
+ $"Got {handle}. Expected less than {BufferHandles.Length}");
+
+ fixed (float* ptr = data)
+ {
+ AL.BufferData(BufferHandles[handle], _mono ? ALFormat.MonoFloat32Ext : ALFormat.StereoFloat32Ext, (IntPtr) ptr,
+ _mono ? data.Length / 2 * sizeof(float) : data.Length * sizeof(float), SampleRate);
+ }
+ }
+
+ public unsafe void QueueBuffers(ReadOnlySpan handles)
+ {
+ _checkDisposed();
+
+ Span realHandles = stackalloc int[handles.Length];
+ handles.CopyTo(realHandles);
+
+ for (var i = 0; i < realHandles.Length; i++)
+ {
+ var handle = realHandles[i];
+ if (handle >= BufferHandles.Length)
+ throw new ArgumentOutOfRangeException(nameof(handles), $"Invalid handle with index {i}!");
+ realHandles[i] = BufferHandles[handle];
+ }
+
+ fixed (int* ptr = realHandles)
+ // ReSharper disable once PossibleInvalidOperationException
+ AL.SourceQueueBuffers(SourceHandle!.Value, handles.Length, ptr);
+ }
+
+ public unsafe void EmptyBuffers()
+ {
+ _checkDisposed();
+ var length = (SampleRate / BufferHandles.Length) * (_mono ? 1 : 2);
+
+ Span handles = stackalloc int[BufferHandles.Length];
+
+ if (_float)
+ {
+ var empty = new float[length];
+ var span = (Span) empty;
+
+ for (var i = 0; i < BufferHandles.Length; i++)
+ {
+ WriteBuffer(BufferMap[BufferHandles[i]], span);
+ handles[i] = BufferMap[BufferHandles[i]];
+ }
+ }
+ else
+ {
+ var empty = new ushort[length];
+ var span = (Span) empty;
+
+ for (var i = 0; i < BufferHandles.Length; i++)
+ {
+ WriteBuffer(BufferMap[BufferHandles[i]], span);
+ handles[i] = BufferMap[BufferHandles[i]];
+ }
+ }
+
+ QueueBuffers(handles);
+ }
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/ClydeAudio.Formats.OggVorbis.cs b/Robust.Client/Graphics/Audio/ClydeAudio.Formats.OggVorbis.cs
new file mode 100644
index 00000000000..2a84f7da46c
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ClydeAudio.Formats.OggVorbis.cs
@@ -0,0 +1,54 @@
+using System;
+using System.IO;
+
+namespace Robust.Client.Graphics.Audio
+{
+ internal partial class ClydeAudio
+ {
+ private OggVorbisData _readOggVorbis(Stream stream)
+ {
+ using (var vorbis = new NVorbis.VorbisReader(stream, false))
+ {
+ var sampleRate = vorbis.SampleRate;
+ var channels = vorbis.Channels;
+ var totalSamples = vorbis.TotalSamples;
+
+ var readSamples = 0;
+ var buffer = new float[totalSamples * channels];
+
+ while (readSamples < totalSamples)
+ {
+ var read = vorbis.ReadSamples(buffer, readSamples * channels, buffer.Length - readSamples);
+ if (read == 0)
+ {
+ break;
+ }
+
+ readSamples += read;
+ }
+
+ return new OggVorbisData(totalSamples, sampleRate, channels, buffer, vorbis.Tags.Title, vorbis.Tags.Artist);
+ }
+ }
+
+ private readonly struct OggVorbisData
+ {
+ public readonly long TotalSamples;
+ public readonly long SampleRate;
+ public readonly long Channels;
+ public readonly ReadOnlyMemory Data;
+ public readonly string Title;
+ public readonly string Artist;
+
+ public OggVorbisData(long totalSamples, long sampleRate, long channels, ReadOnlyMemory data, string title, string artist)
+ {
+ TotalSamples = totalSamples;
+ SampleRate = sampleRate;
+ Channels = channels;
+ Data = data;
+ Title = title;
+ Artist = artist;
+ }
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/ClydeAudio.Formats.Wav.cs b/Robust.Client/Graphics/Audio/ClydeAudio.Formats.Wav.cs
new file mode 100644
index 00000000000..7394716534e
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ClydeAudio.Formats.Wav.cs
@@ -0,0 +1,144 @@
+using System;
+using System.IO;
+using JetBrains.Annotations;
+using Robust.Shared.Utility;
+
+namespace Robust.Client.Graphics.Audio
+{
+ internal partial class ClydeAudio
+ {
+ ///
+ /// Load up a WAVE file.
+ ///
+ private static WavData _readWav(Stream stream)
+ {
+ var reader = new BinaryReader(stream, EncodingHelpers.UTF8, true);
+
+ void SkipChunk()
+ {
+ var length = reader.ReadUInt32();
+ stream.Position += length;
+ }
+
+ // Read outer most chunks.
+ Span fourCc = stackalloc byte[4];
+ while (true)
+ {
+ _readFourCC(reader, fourCc);
+
+ if (!fourCc.SequenceEqual("RIFF"u8))
+ {
+ SkipChunk();
+ continue;
+ }
+
+ return _readRiffChunk(reader);
+ }
+ }
+
+ private static void _skipChunk(BinaryReader reader)
+ {
+ var length = reader.ReadUInt32();
+ reader.BaseStream.Position += length;
+ }
+
+ private static void _readFourCC(BinaryReader reader, Span fourCc)
+ {
+ fourCc[0] = reader.ReadByte();
+ fourCc[1] = reader.ReadByte();
+ fourCc[2] = reader.ReadByte();
+ fourCc[3] = reader.ReadByte();
+ }
+
+ private static WavData _readRiffChunk(BinaryReader reader)
+ {
+ Span format = stackalloc byte[4];
+ reader.ReadUInt32();
+ _readFourCC(reader, format);
+ if (!format.SequenceEqual("WAVE"u8))
+ {
+ throw new InvalidDataException("File is not a WAVE file.");
+ }
+
+ _readFourCC(reader, format);
+ if (!format.SequenceEqual("fmt "u8))
+ {
+ throw new InvalidDataException("Expected fmt chunk.");
+ }
+
+ // Read fmt chunk.
+
+ var size = reader.ReadInt32();
+ var afterFmtPos = reader.BaseStream.Position + size;
+
+ var audioType = (WavAudioFormatType) reader.ReadInt16();
+ var channels = reader.ReadInt16();
+ var sampleRate = reader.ReadInt32();
+ var byteRate = reader.ReadInt32();
+ var blockAlign = reader.ReadInt16();
+ var bitsPerSample = reader.ReadInt16();
+
+ if (audioType != WavAudioFormatType.PCM)
+ {
+ throw new NotImplementedException("Unable to support audio types other than PCM.");
+ }
+
+ DebugTools.Assert(byteRate == sampleRate * channels * bitsPerSample / 8);
+
+ // Fmt is not of guaranteed size, so use the size header to skip to the end.
+ reader.BaseStream.Position = afterFmtPos;
+
+ while (true)
+ {
+ _readFourCC(reader, format);
+ if (!format.SequenceEqual("data"u8))
+ {
+ _skipChunk(reader);
+ continue;
+ }
+
+ break;
+ }
+
+ // We are in the data chunk.
+ size = reader.ReadInt32();
+ var data = reader.ReadBytes(size);
+
+ return new WavData(audioType, channels, sampleRate, byteRate, blockAlign, bitsPerSample, data);
+ }
+
+ ///
+ /// See http://soundfile.sapp.org/doc/WaveFormat/ for reference.
+ ///
+ [PublicAPI]
+ private readonly struct WavData
+ {
+ public readonly WavAudioFormatType AudioType;
+ public readonly short NumChannels;
+ public readonly int SampleRate;
+ public readonly int ByteRate;
+ public readonly short BlockAlign;
+ public readonly short BitsPerSample;
+ public readonly ReadOnlyMemory Data;
+
+ public WavData(WavAudioFormatType audioType, short numChannels, int sampleRate, int byteRate,
+ short blockAlign, short bitsPerSample, ReadOnlyMemory data)
+ {
+ AudioType = audioType;
+ NumChannels = numChannels;
+ SampleRate = sampleRate;
+ ByteRate = byteRate;
+ BlockAlign = blockAlign;
+ BitsPerSample = bitsPerSample;
+ Data = data;
+ }
+ }
+
+ private enum WavAudioFormatType : short
+ {
+ Unknown = 0,
+ PCM = 1,
+ // There's a bunch of other types, those are all unsupported.
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/ClydeAudio.IoC.cs b/Robust.Client/Graphics/Audio/ClydeAudio.IoC.cs
new file mode 100644
index 00000000000..69fb7041afd
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ClydeAudio.IoC.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using OpenTK.Audio.OpenAL;
+using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
+using OpenTK.Mathematics;
+using Robust.Client.Audio;
+using Robust.Shared;
+using Robust.Shared.Configuration;
+using Robust.Shared.IoC;
+using Robust.Shared.Audio;
+using Robust.Shared.Log;
+using Robust.Shared.Timing;
+using Vector2 = System.Numerics.Vector2;
+
+namespace Robust.Client.Graphics.Audio
+{
+ internal partial class ClydeAudio
+ {
+ [Robust.Shared.IoC.Dependency] private readonly IConfigurationManager _cfg = default!;
+ [Robust.Shared.IoC.Dependency] private readonly IEyeManager _eyeManager = default!;
+ [Robust.Shared.IoC.Dependency] private readonly ILogManager _logMan = default!;
+
+ private Thread? _gameThread;
+
+ public bool InitializePostWindowing()
+ {
+ _gameThread = Thread.CurrentThread;
+ return _initializeAudio();
+ }
+
+ public void FrameProcess(FrameEventArgs eventArgs)
+ {
+ _updateAudio();
+ }
+
+ public void Shutdown()
+ {
+ _shutdownAudio();
+ }
+
+ private bool IsMainThread()
+ {
+ return Thread.CurrentThread == _gameThread;
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/ClydeAudio.cs b/Robust.Client/Graphics/Audio/ClydeAudio.cs
new file mode 100644
index 00000000000..cdbbca2d443
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ClydeAudio.cs
@@ -0,0 +1,432 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using OpenTK.Audio.OpenAL;
+using OpenTK.Audio.OpenAL.Extensions.Creative.EFX;
+using OpenTK.Mathematics;
+using Robust.Client.Audio;
+using Robust.Shared;
+using Robust.Shared.Audio;
+using Robust.Shared.Log;
+
+namespace Robust.Client.Graphics.Audio
+{
+ internal sealed partial class ClydeAudio : IClydeAudio, IClydeAudioInternal
+ {
+ private ALDevice _openALDevice;
+ private ALContext _openALContext;
+
+ private readonly List _audioSampleBuffers = new();
+
+ private readonly Dictionary> _audioSources =
+ new();
+
+ private readonly Dictionary> _bufferedAudioSources =
+ new();
+
+ private readonly HashSet _alcDeviceExtensions = new();
+ private readonly HashSet _alContextExtensions = new();
+
+ // The base gain value for a listener, used to boost the default volume.
+ private const float _baseGain = 2f;
+
+ public bool HasAlDeviceExtension(string extension) => _alcDeviceExtensions.Contains(extension);
+ public bool HasAlContextExtension(string extension) => _alContextExtensions.Contains(extension);
+
+ internal bool IsEfxSupported;
+
+ internal ISawmill OpenALSawmill = default!;
+
+ private bool _initializeAudio()
+ {
+ OpenALSawmill = _logMan.GetSawmill("clyde.oal");
+
+ if (!_audioOpenDevice())
+ return false;
+
+ // Create OpenAL context.
+ _audioCreateContext();
+
+ IsEfxSupported = HasAlDeviceExtension("ALC_EXT_EFX");
+
+ _cfg.OnValueChanged(CVars.AudioMasterVolume, SetMasterVolume, true);
+ _cfg.OnValueChanged(CVars.AudioAttenuation, SetAudioAttenuation, true);
+ return true;
+ }
+
+ private void _audioCreateContext()
+ {
+ unsafe
+ {
+ _openALContext = ALC.CreateContext(_openALDevice, (int*) 0);
+ }
+
+ ALC.MakeContextCurrent(_openALContext);
+ _checkAlcError(_openALDevice);
+ _checkAlError();
+
+ // Load up AL context extensions.
+ var s = ALC.GetString(ALDevice.Null, AlcGetString.Extensions) ?? "";
+ foreach (var extension in s.Split(' '))
+ {
+ _alContextExtensions.Add(extension);
+ }
+
+ OpenALSawmill.Debug("OpenAL Vendor: {0}", AL.Get(ALGetString.Vendor));
+ OpenALSawmill.Debug("OpenAL Renderer: {0}", AL.Get(ALGetString.Renderer));
+ OpenALSawmill.Debug("OpenAL Version: {0}", AL.Get(ALGetString.Version));
+ }
+
+ private bool _audioOpenDevice()
+ {
+ var preferredDevice = _cfg.GetCVar(CVars.AudioDevice);
+
+ // Open device.
+ if (!string.IsNullOrEmpty(preferredDevice))
+ {
+ _openALDevice = ALC.OpenDevice(preferredDevice);
+ if (_openALDevice == IntPtr.Zero)
+ {
+ OpenALSawmill.Warning("Unable to open preferred audio device '{0}': {1}. Falling back default.",
+ preferredDevice, ALC.GetError(ALDevice.Null));
+
+ _openALDevice = ALC.OpenDevice(null);
+ }
+ }
+ else
+ {
+ _openALDevice = ALC.OpenDevice(null);
+ }
+
+ _checkAlcError(_openALDevice);
+
+ if (_openALDevice == IntPtr.Zero)
+ {
+ OpenALSawmill.Error("Unable to open OpenAL device! {1}", ALC.GetError(ALDevice.Null));
+ return false;
+ }
+
+ // Load up ALC extensions.
+ var s = ALC.GetString(_openALDevice, AlcGetString.Extensions) ?? "";
+ foreach (var extension in s.Split(' '))
+ {
+ _alcDeviceExtensions.Add(extension);
+ }
+ return true;
+ }
+
+ public void StopAllAudio()
+ {
+ foreach (var (key, source) in _audioSources)
+ {
+ if (source.TryGetTarget(out var target))
+ {
+ target.StopPlaying();
+ }
+ }
+
+ foreach (var (key, source) in _bufferedAudioSources)
+ {
+ if (source.TryGetTarget(out var target))
+ {
+ target.StopPlaying();
+ }
+ }
+ }
+
+ public void DisposeAllAudio()
+ {
+ foreach (var (key, source) in _audioSources)
+ {
+ if (source.TryGetTarget(out var target))
+ {
+ target.Dispose();
+ }
+ }
+ _audioSources.Clear();
+
+ foreach (var (key, source) in _bufferedAudioSources)
+ {
+ if (source.TryGetTarget(out var target))
+ {
+ target.StopPlaying();
+ target.Dispose();
+ }
+ }
+ _bufferedAudioSources.Clear();
+ }
+
+ private void _shutdownAudio()
+ {
+ DisposeAllAudio();
+
+ if (_openALContext != ALContext.Null)
+ {
+ ALC.MakeContextCurrent(ALContext.Null);
+
+ ALC.DestroyContext(_openALContext);
+ }
+
+ if (_openALDevice != IntPtr.Zero)
+ {
+ ALC.CloseDevice(_openALDevice);
+ }
+ }
+
+ private void _updateAudio()
+ {
+ var eye = _eyeManager.CurrentEye;
+ var vec = eye.Position.Position;
+ AL.Listener(ALListener3f.Position, vec.X, vec.Y, -5);
+ var rot2d = eye.Rotation.ToVec();
+ AL.Listener(ALListenerfv.Orientation, new []{0, 0, -1, rot2d.X, rot2d.Y, 0});
+
+ // Default orientation: at: (0, 0, -1) up: (0, 1, 0)
+ var rot = eye.Rotation.ToVec();
+ var at = new Vector3(0f, 0f, -1f);
+ var up = new Vector3(rot.Y, rot.X, 0f);
+ AL.Listener(ALListenerfv.Orientation, ref at, ref up);
+
+ _flushALDisposeQueues();
+ }
+
+ private static void RemoveEfx((int sourceHandle, int filterHandle) handles)
+ {
+ if (handles.filterHandle != 0) EFX.DeleteFilter(handles.filterHandle);
+ }
+
+ public void SetMasterVolume(float newVolume)
+ {
+ AL.Listener(ALListenerf.Gain, _baseGain * newVolume);
+ }
+
+ public void SetAudioAttenuation(int value)
+ {
+ var attenuation = (Attenuation) value;
+
+ switch (attenuation)
+ {
+ case Attenuation.NoAttenuation:
+ AL.DistanceModel(ALDistanceModel.None);
+ break;
+ case Attenuation.InverseDistance:
+ AL.DistanceModel(ALDistanceModel.InverseDistance);
+ break;
+ case Attenuation.Default:
+ case Attenuation.InverseDistanceClamped:
+ AL.DistanceModel(ALDistanceModel.InverseDistanceClamped);
+ break;
+ case Attenuation.LinearDistance:
+ AL.DistanceModel(ALDistanceModel.LinearDistance);
+ break;
+ case Attenuation.LinearDistanceClamped:
+ AL.DistanceModel(ALDistanceModel.LinearDistanceClamped);
+ break;
+ case Attenuation.ExponentDistance:
+ AL.DistanceModel(ALDistanceModel.ExponentDistance);
+ break;
+ case Attenuation.ExponentDistanceClamped:
+ AL.DistanceModel(ALDistanceModel.ExponentDistanceClamped);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException($"No implementation to set {attenuation.ToString()} for DistanceModel!");
+ }
+
+ var attToString = attenuation == Attenuation.Default ? Attenuation.InverseDistanceClamped : attenuation;
+
+ OpenALSawmill.Info($"Set audio attenuation to {attToString.ToString()}");
+ }
+
+ public IClydeAudioSource? CreateAudioSource(AudioStream stream)
+ {
+ var source = AL.GenSource();
+
+ if (!AL.IsSource(source))
+ {
+ OpenALSawmill.Error("Failed to generate source. Too many simultaneous audio streams? {0}", Environment.StackTrace);
+ return null;
+ }
+
+ // ReSharper disable once PossibleInvalidOperationException
+ // TODO: This really shouldn't be indexing based on the ClydeHandle...
+ AL.Source(source, ALSourcei.Buffer, _audioSampleBuffers[(int) stream.ClydeHandle!.Value.Value].BufferHandle);
+
+ var audioSource = new AudioSource(this, source, stream);
+ _audioSources.Add(source, new WeakReference(audioSource));
+ return audioSource;
+ }
+
+ public IClydeBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio=false)
+ {
+ var source = AL.GenSource();
+
+ if (!AL.IsSource(source))
+ throw new Exception("Failed to generate source. Too many simultaneous audio streams?");
+
+ // ReSharper disable once PossibleInvalidOperationException
+
+ var audioSource = new BufferedAudioSource(this, source, AL.GenBuffers(buffers), floatAudio);
+ _bufferedAudioSources.Add(source, new WeakReference(audioSource));
+ return audioSource;
+ }
+
+ private void _checkAlcError(ALDevice device,
+ [CallerMemberName] string callerMember = "",
+ [CallerLineNumber] int callerLineNumber = -1)
+ {
+ var error = ALC.GetError(device);
+ if (error != AlcError.NoError)
+ {
+ OpenALSawmill.Error("[{0}:{1}] ALC error: {2}", callerMember, callerLineNumber, error);
+ }
+ }
+
+ private void _checkAlError([CallerMemberName] string callerMember = "",
+ [CallerLineNumber] int callerLineNumber = -1)
+ {
+ var error = AL.GetError();
+ if (error != ALError.NoError)
+ {
+ OpenALSawmill.Error("[{0}:{1}] AL error: {2}", callerMember, callerLineNumber, error);
+ }
+ }
+
+ public AudioStream LoadAudioOggVorbis(Stream stream, string? name = null)
+ {
+ var vorbis = _readOggVorbis(stream);
+
+ var buffer = AL.GenBuffer();
+
+ ALFormat format;
+ // NVorbis only supports loading into floats.
+ // If this becomes a problem due to missing extension support (doubt it but ok),
+ // check the git history, I originally used libvorbisfile which worked and loaded 16 bit LPCM.
+ if (vorbis.Channels == 1)
+ {
+ format = ALFormat.MonoFloat32Ext;
+ }
+ else if (vorbis.Channels == 2)
+ {
+ format = ALFormat.StereoFloat32Ext;
+ }
+ else
+ {
+ throw new InvalidOperationException("Unable to load audio with more than 2 channels.");
+ }
+
+ unsafe
+ {
+ fixed (float* ptr = vorbis.Data.Span)
+ {
+ AL.BufferData(buffer, format, (IntPtr) ptr, vorbis.Data.Length * sizeof(float),
+ (int) vorbis.SampleRate);
+ }
+ }
+
+ _checkAlError();
+
+ var handle = new ClydeHandle(_audioSampleBuffers.Count);
+ _audioSampleBuffers.Add(new LoadedAudioSample(buffer));
+ var length = TimeSpan.FromSeconds(vorbis.TotalSamples / (double) vorbis.SampleRate);
+ return new AudioStream(handle, length, (int) vorbis.Channels, name, vorbis.Title, vorbis.Artist);
+ }
+
+ public AudioStream LoadAudioWav(Stream stream, string? name = null)
+ {
+ var wav = _readWav(stream);
+
+ var buffer = AL.GenBuffer();
+
+ ALFormat format;
+ if (wav.BitsPerSample == 16)
+ {
+ if (wav.NumChannels == 1)
+ {
+ format = ALFormat.Mono16;
+ }
+ else if (wav.NumChannels == 2)
+ {
+ format = ALFormat.Stereo16;
+ }
+ else
+ {
+ throw new InvalidOperationException("Unable to load audio with more than 2 channels.");
+ }
+ }
+ else if (wav.BitsPerSample == 8)
+ {
+ if (wav.NumChannels == 1)
+ {
+ format = ALFormat.Mono8;
+ }
+ else if (wav.NumChannels == 2)
+ {
+ format = ALFormat.Stereo8;
+ }
+ else
+ {
+ throw new InvalidOperationException("Unable to load audio with more than 2 channels.");
+ }
+ }
+ else
+ {
+ throw new InvalidOperationException("Unable to load wav with bits per sample different from 8 or 16");
+ }
+
+ unsafe
+ {
+ fixed (byte* ptr = wav.Data.Span)
+ {
+ AL.BufferData(buffer, format, (IntPtr) ptr, wav.Data.Length, wav.SampleRate);
+ }
+ }
+
+ _checkAlError();
+
+ var handle = new ClydeHandle(_audioSampleBuffers.Count);
+ _audioSampleBuffers.Add(new LoadedAudioSample(buffer));
+ var length = TimeSpan.FromSeconds(wav.Data.Length / (double) wav.BlockAlign / wav.SampleRate);
+ return new AudioStream(handle, length, wav.NumChannels, name);
+ }
+
+ public AudioStream LoadAudioRaw(ReadOnlySpan samples, int channels, int sampleRate, string? name = null)
+ {
+ var fmt = channels switch
+ {
+ 1 => ALFormat.Mono16,
+ 2 => ALFormat.Stereo16,
+ _ => throw new ArgumentOutOfRangeException(
+ nameof(channels), "Only stereo and mono is currently supported")
+ };
+
+ var buffer = AL.GenBuffer();
+ _checkAlError();
+
+ unsafe
+ {
+ fixed (short* ptr = samples)
+ {
+ AL.BufferData(buffer, fmt, (IntPtr) ptr, samples.Length * sizeof(short), sampleRate);
+ }
+ }
+
+ _checkAlError();
+
+ var handle = new ClydeHandle(_audioSampleBuffers.Count);
+ var length = TimeSpan.FromSeconds((double) samples.Length / channels / sampleRate);
+ _audioSampleBuffers.Add(new LoadedAudioSample(buffer));
+ return new AudioStream(handle, length, channels, name);
+ }
+
+ private sealed class LoadedAudioSample
+ {
+ public readonly int BufferHandle;
+
+ public LoadedAudioSample(int bufferHandle)
+ {
+ BufferHandle = bufferHandle;
+ }
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/ClydeAudioHeadless.cs b/Robust.Client/Graphics/Audio/ClydeAudioHeadless.cs
new file mode 100644
index 00000000000..c1a2d29522c
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ClydeAudioHeadless.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Robust.Client.Audio;
+using Robust.Client.Input;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+using Robust.Shared.Timing;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.PixelFormats;
+using Color = Robust.Shared.Maths.Color;
+
+namespace Robust.Client.Graphics.Audio
+{
+ ///
+ /// Hey look, it's ClydeAudio's evil twin brother!
+ ///
+ [UsedImplicitly]
+ internal sealed class ClydeAudioHeadless : IClydeAudio, IClydeAudioInternal
+ {
+ public bool InitializePostWindowing()
+ {
+ return true;
+ }
+
+ public void FrameProcess(FrameEventArgs eventArgs)
+ {
+ }
+
+ public void Shutdown()
+ {
+ }
+
+ public AudioStream LoadAudioOggVorbis(Stream stream, string? name = null)
+ {
+ // TODO: Might wanna actually load this so the length gets reported correctly.
+ return new(default, default, 1, name);
+ }
+
+ public AudioStream LoadAudioWav(Stream stream, string? name = null)
+ {
+ // TODO: Might wanna actually load this so the length gets reported correctly.
+ return new(default, default, 1, name);
+ }
+
+ public AudioStream LoadAudioRaw(ReadOnlySpan samples, int channels, int sampleRate, string? name = null)
+ {
+ // TODO: Might wanna actually load this so the length gets reported correctly.
+ return new(default, default, channels, name);
+ }
+
+ public IClydeAudioSource CreateAudioSource(AudioStream stream)
+ {
+ return DummyAudioSource.Instance;
+ }
+
+ public IClydeBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio = false)
+ {
+ return DummyBufferedAudioSource.Instance;
+ }
+
+ public void SetMasterVolume(float newVolume)
+ {
+ // Nada.
+ }
+
+ public void DisposeAllAudio()
+ {
+ // Nada.
+ }
+
+ public void StopAllAudio()
+ {
+ // Nada.
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/DummyAudioSource.cs b/Robust.Client/Graphics/Audio/DummyAudioSource.cs
new file mode 100644
index 00000000000..aa706f21149
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/DummyAudioSource.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Numerics;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Robust.Client.Audio;
+using Robust.Client.Input;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+using Robust.Shared.Timing;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.PixelFormats;
+using Color = Robust.Shared.Maths.Color;
+
+namespace Robust.Client.Graphics.Audio
+{
+ ///
+ /// Hey look, it's ClydeAudio.AudioSource's evil twin brother!
+ ///
+ [Virtual]
+ internal class DummyAudioSource : IClydeAudioSource
+ {
+ public static DummyAudioSource Instance { get; } = new();
+
+ public bool IsPlaying => default;
+ public bool IsLooping { get; set; }
+
+ public void Dispose()
+ {
+ // Nada.
+ }
+
+ public void StartPlaying()
+ {
+ // Nada.
+ }
+
+ public void StopPlaying()
+ {
+ // Nada.
+ }
+
+ public bool IsGlobal { get; }
+
+ public bool SetPosition(Vector2 position)
+ {
+ return true;
+ }
+
+ public void SetPitch(float pitch)
+ {
+ // Nada.
+ }
+
+ public void SetGlobal()
+ {
+ // Nada.
+ }
+
+ public void SetVolume(float decibels)
+ {
+ // Nada.
+ }
+
+ public void SetVolumeDirect(float gain)
+ {
+ // Nada.
+ }
+
+ public void SetMaxDistance(float maxDistance)
+ {
+ // Nada.
+ }
+
+ public void SetRolloffFactor(float rolloffFactor)
+ {
+ // Nada.
+ }
+
+ public void SetReferenceDistance(float refDistance)
+ {
+ // Nada.
+ }
+
+ public void SetOcclusion(float blocks)
+ {
+ // Nada.
+ }
+
+ public void SetPlaybackPosition(float seconds)
+ {
+ // Nada.
+ }
+
+ public void SetVelocity(Vector2 velocity)
+ {
+ // Nada.
+ }
+ }
+}
diff --git a/Robust.Shared/Audio/Sources/DummyBufferedAudioSource.cs b/Robust.Client/Graphics/Audio/DummyBufferedAudioSource.cs
similarity index 60%
rename from Robust.Shared/Audio/Sources/DummyBufferedAudioSource.cs
rename to Robust.Client/Graphics/Audio/DummyBufferedAudioSource.cs
index 122a261a83f..640168b0ba5 100644
--- a/Robust.Shared/Audio/Sources/DummyBufferedAudioSource.cs
+++ b/Robust.Client/Graphics/Audio/DummyBufferedAudioSource.cs
@@ -1,11 +1,24 @@
using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Robust.Client.Audio;
+using Robust.Client.Input;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+using Robust.Shared.Timing;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.PixelFormats;
+using Color = Robust.Shared.Maths.Color;
-namespace Robust.Shared.Audio.Sources
+namespace Robust.Client.Graphics.Audio
{
///
- /// Hey look, it's Audio.BufferedAudioSource's evil twin brother!
+ /// Hey look, it's ClydeAudio.BufferedAudioSource's evil twin brother!
///
- internal sealed class DummyBufferedAudioSource : DummyAudioSource, IBufferedAudioSource
+ internal sealed class DummyBufferedAudioSource : DummyAudioSource, IClydeBufferedAudioSource
{
public new static DummyBufferedAudioSource Instance { get; } = new();
public int SampleRate { get; set; } = 0;
diff --git a/Robust.Client/Graphics/Audio/FallbackProxyClydeAudio.cs b/Robust.Client/Graphics/Audio/FallbackProxyClydeAudio.cs
new file mode 100644
index 00000000000..98673451b5d
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/FallbackProxyClydeAudio.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Robust.Client.Audio;
+using Robust.Client.Input;
+using Robust.Shared.Timing;
+using Robust.Shared.IoC;
+
+namespace Robust.Client.Graphics.Audio
+{
+ ///
+ /// For "start ss14 with no audio devices" Smugleaf
+ ///
+ [UsedImplicitly]
+ internal sealed class FallbackProxyClydeAudio : ProxyClydeAudio
+ {
+ [Dependency] private readonly IDependencyCollection _deps = default!;
+
+ public override bool InitializePostWindowing()
+ {
+ // Deliberate lack of base call here (see base implementation for comments as to why there even is a base)
+
+ ActualImplementation = new ClydeAudio();
+ _deps.InjectDependencies(ActualImplementation, true);
+ if (ActualImplementation.InitializePostWindowing())
+ return true;
+
+ // If we get here, that failed, so use the fallback
+ ActualImplementation = new ClydeAudioHeadless();
+ _deps.InjectDependencies(ActualImplementation, true);
+ return ActualImplementation.InitializePostWindowing();
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Audio/ProxyClydeAudio.cs b/Robust.Client/Graphics/Audio/ProxyClydeAudio.cs
new file mode 100644
index 00000000000..79b5eeaf7fc
--- /dev/null
+++ b/Robust.Client/Graphics/Audio/ProxyClydeAudio.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Robust.Client.Audio;
+using Robust.Client.Input;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+using Robust.Shared.Timing;
+using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.PixelFormats;
+using Color = Robust.Shared.Maths.Color;
+
+namespace Robust.Client.Graphics.Audio
+{
+ ///
+ /// For "start ss14 with no audio devices" Smugleaf
+ ///
+ [UsedImplicitly]
+ internal abstract class ProxyClydeAudio : IClydeAudio, IClydeAudioInternal
+ {
+ protected IClydeAudioInternal ActualImplementation = default!;
+
+ public virtual bool InitializePostWindowing()
+ {
+ // This particular implementation exists to be overridden because removing this method causes C# to complain
+ return ActualImplementation.InitializePostWindowing();
+ }
+
+ public void FrameProcess(FrameEventArgs eventArgs)
+ {
+ ActualImplementation.FrameProcess(eventArgs);
+ }
+
+ public void Shutdown()
+ {
+ ActualImplementation.Shutdown();
+ }
+
+ public AudioStream LoadAudioOggVorbis(Stream stream, string? name = null)
+ {
+ return ActualImplementation.LoadAudioOggVorbis(stream, name);
+ }
+
+ public AudioStream LoadAudioWav(Stream stream, string? name = null)
+ {
+ return ActualImplementation.LoadAudioWav(stream, name);
+ }
+
+ public AudioStream LoadAudioRaw(ReadOnlySpan samples, int channels, int sampleRate, string? name = null)
+ {
+ return ActualImplementation.LoadAudioRaw(samples, channels, sampleRate, name);
+ }
+
+ public IClydeAudioSource? CreateAudioSource(AudioStream stream)
+ {
+ return ActualImplementation.CreateAudioSource(stream);
+ }
+
+ public IClydeBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio = false)
+ {
+ return ActualImplementation.CreateBufferedAudioSource(buffers, floatAudio);
+ }
+
+ public void SetMasterVolume(float newVolume)
+ {
+ ActualImplementation.SetMasterVolume(newVolume);
+ }
+
+ public void DisposeAllAudio()
+ {
+ ActualImplementation.DisposeAllAudio();
+ }
+
+ public void StopAllAudio()
+ {
+ ActualImplementation.StopAllAudio();
+ }
+ }
+}
diff --git a/Robust.Client/Graphics/Clyde/Clyde.HLR.cs b/Robust.Client/Graphics/Clyde/Clyde.HLR.cs
index 36b7a015418..1da177f6af7 100644
--- a/Robust.Client/Graphics/Clyde/Clyde.HLR.cs
+++ b/Robust.Client/Graphics/Clyde/Clyde.HLR.cs
@@ -512,7 +512,7 @@ private void RenderViewport(Viewport viewport)
RenderOverlays(viewport, OverlaySpace.WorldSpaceBelowFOV, worldAABB, worldBounds);
}
- if (_lightManager.Enabled && _lightManager.DrawHardFov && eye.DrawFov)
+ if (_lightManager.Enabled && _lightManager.DrawHardFov && eye.DrawLight && eye.DrawFov)
{
ApplyFovToBuffer(viewport, eye);
}
diff --git a/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs b/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs
index f1cfdfdce19..1aeb2872b09 100644
--- a/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs
+++ b/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs
@@ -332,7 +332,7 @@ private void FinalizeDepthDraw()
private void DrawLightsAndFov(Viewport viewport, Box2Rotated worldBounds, Box2 worldAABB, IEye eye)
{
- if (!_lightManager.Enabled)
+ if (!_lightManager.Enabled || !eye.DrawLight)
{
return;
}
diff --git a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs
index ebda3975e1f..98ca8b9d946 100644
--- a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs
+++ b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs
@@ -260,14 +260,14 @@ private IEnumerable> LoadWindowIcons()
yield break;
}
- foreach (var file in _resManager.ContentFindFiles(_windowIconPath))
+ foreach (var file in _resourceCache.ContentFindFiles(_windowIconPath))
{
if (file.Extension != "png")
{
continue;
}
- using var stream = _resManager.ContentFileRead(file);
+ using var stream = _resourceCache.ContentFileRead(file);
yield return Image.Load(stream);
}
}
diff --git a/Robust.Client/Graphics/Clyde/Clyde.cs b/Robust.Client/Graphics/Clyde/Clyde.cs
index 088faaf05c0..b85f33b3c54 100644
--- a/Robust.Client/Graphics/Clyde/Clyde.cs
+++ b/Robust.Client/Graphics/Clyde/Clyde.cs
@@ -11,7 +11,6 @@
using Robust.Client.UserInterface;
using Robust.Shared;
using Robust.Shared.Configuration;
-using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Graphics;
using Robust.Shared.IoC;
@@ -36,8 +35,7 @@ internal sealed partial class Clyde : IClydeInternal, IPostInjectInit, IEntityEv
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IOverlayManager _overlayManager = default!;
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
- [Dependency] private readonly IResourceManager _resManager = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IUserInterfaceManagerInternal _userInterfaceManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
diff --git a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs
index 972d2c9d1a0..a75ff8de7a8 100644
--- a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs
+++ b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs
@@ -292,6 +292,123 @@ public void Dispose()
}
}
+ [Virtual]
+ private class DummyAudioSource : IClydeAudioSource
+ {
+ public static DummyAudioSource Instance { get; } = new();
+
+ public bool IsPlaying => default;
+ public bool IsLooping { get; set; }
+
+ public void Dispose()
+ {
+ // Nada.
+ }
+
+ public void StartPlaying()
+ {
+ // Nada.
+ }
+
+ public void StopPlaying()
+ {
+ // Nada.
+ }
+
+ public bool IsGlobal { get; }
+
+ public bool SetPosition(Vector2 position)
+ {
+ return true;
+ }
+
+ public void SetPitch(float pitch)
+ {
+ // Nada.
+ }
+
+ public void SetGlobal()
+ {
+ // Nada.
+ }
+
+ public void SetVolume(float decibels)
+ {
+ // Nada.
+ }
+
+ public void SetVolumeDirect(float gain)
+ {
+ // Nada.
+ }
+
+ public void SetMaxDistance(float maxDistance)
+ {
+ // Nada.
+ }
+
+ public void SetRolloffFactor(float rolloffFactor)
+ {
+ // Nada.
+ }
+
+ public void SetReferenceDistance(float refDistance)
+ {
+ // Nada.
+ }
+
+ public void SetOcclusion(float blocks)
+ {
+ // Nada.
+ }
+
+ public void SetPlaybackPosition(float seconds)
+ {
+ // Nada.
+ }
+
+ public void SetVelocity(Vector2 velocity)
+ {
+ // Nada.
+ }
+ }
+
+ private sealed class DummyBufferedAudioSource : DummyAudioSource, IClydeBufferedAudioSource
+ {
+ public new static DummyBufferedAudioSource Instance { get; } = new();
+ public int SampleRate { get; set; } = 0;
+
+ public void WriteBuffer(int handle, ReadOnlySpan data)
+ {
+ // Nada.
+ }
+
+ public void WriteBuffer(int handle, ReadOnlySpan data)
+ {
+ // Nada.
+ }
+
+ public void QueueBuffers(ReadOnlySpan handles)
+ {
+ // Nada.
+ }
+
+ public void EmptyBuffers()
+ {
+ // Nada.
+ }
+
+ public void GetBuffersProcessed(Span handles)
+ {
+ // Nada.
+ }
+
+ public int GetNumberOfBuffersProcessed()
+ {
+ return 0;
+ }
+ }
+
private sealed class DummyTexture : OwnedTexture
{
public DummyTexture(Vector2i size) : base(size)
diff --git a/Robust.Client/Graphics/ClydeHandle.cs b/Robust.Client/Graphics/ClydeHandle.cs
index 5dadc3f6247..3e7319e8220 100644
--- a/Robust.Client/Graphics/ClydeHandle.cs
+++ b/Robust.Client/Graphics/ClydeHandle.cs
@@ -1,54 +1,54 @@
using System;
-using Robust.Shared.Graphics;
-namespace Robust.Client.Graphics;
-
-internal readonly struct ClydeHandle : IEquatable, IClydeHandle
+namespace Robust.Client.Graphics
{
- public ClydeHandle(long value)
- {
- Value = value;
- }
-
- public long Value { get; }
-
- public static explicit operator ClydeHandle(long x)
- {
- return new(x);
- }
-
- public static explicit operator long(ClydeHandle h)
- {
- return h.Value;
- }
-
- public bool Equals(ClydeHandle other)
- {
- return Value == other.Value;
- }
-
- public override bool Equals(object? obj)
- {
- return obj is ClydeHandle other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return Value.GetHashCode();
- }
-
- public static bool operator ==(ClydeHandle left, ClydeHandle right)
- {
- return left.Value == right.Value;
- }
-
- public static bool operator !=(ClydeHandle left, ClydeHandle right)
- {
- return left.Value != right.Value;
- }
-
- public override string ToString()
- {
- return $"ClydeHandle {Value}";
+ internal struct ClydeHandle : IEquatable
+ {
+ public ClydeHandle(long value)
+ {
+ Value = value;
+ }
+
+ public readonly long Value;
+
+ public static explicit operator ClydeHandle(long x)
+ {
+ return new(x);
+ }
+
+ public static explicit operator long(ClydeHandle h)
+ {
+ return h.Value;
+ }
+
+ public bool Equals(ClydeHandle other)
+ {
+ return Value == other.Value;
+ }
+
+ public override bool Equals(object? obj)
+ {
+ return obj is ClydeHandle other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return Value.GetHashCode();
+ }
+
+ public static bool operator ==(ClydeHandle left, ClydeHandle right)
+ {
+ return left.Value == right.Value;
+ }
+
+ public static bool operator !=(ClydeHandle left, ClydeHandle right)
+ {
+ return left.Value != right.Value;
+ }
+
+ public override string ToString()
+ {
+ return $"ClydeHandle {Value}";
+ }
}
}
diff --git a/Robust.Client/Graphics/Drawing/DrawingHandleScreen.cs b/Robust.Client/Graphics/Drawing/DrawingHandleScreen.cs
index e6192d7af44..5decd158515 100644
--- a/Robust.Client/Graphics/Drawing/DrawingHandleScreen.cs
+++ b/Robust.Client/Graphics/Drawing/DrawingHandleScreen.cs
@@ -114,10 +114,9 @@ public Vector2 GetDimensions(Font font, ReadOnlySpan str, float scale)
{
if (rune == new Rune('\n'))
{
+ baseLine.X = 0f;
baseLine.Y += lineHeight;
advanceTotal.Y += lineHeight;
- advanceTotal.X = Math.Max(advanceTotal.X, baseLine.X);
- baseLine.X = 0f;
continue;
}
@@ -127,6 +126,7 @@ public Vector2 GetDimensions(Font font, ReadOnlySpan str, float scale)
continue;
var advance = metrics.Value.Advance;
+ advanceTotal.X += advance;
baseLine += new Vector2(advance, 0);
}
diff --git a/Robust.Client/Graphics/IClydeAudio.cs b/Robust.Client/Graphics/IClydeAudio.cs
new file mode 100644
index 00000000000..277c6ac182b
--- /dev/null
+++ b/Robust.Client/Graphics/IClydeAudio.cs
@@ -0,0 +1,23 @@
+using System;
+using System.IO;
+using Robust.Client.Audio;
+
+namespace Robust.Client.Graphics
+{
+ public interface IClydeAudio
+ {
+ // AUDIO SYSTEM DOWN BELOW.
+ AudioStream LoadAudioOggVorbis(Stream stream, string? name = null);
+ AudioStream LoadAudioWav(Stream stream, string? name = null);
+ AudioStream LoadAudioRaw(ReadOnlySpan samples, int channels, int sampleRate, string? name = null);
+
+ void SetMasterVolume(float newVolume);
+
+ void DisposeAllAudio();
+
+ void StopAllAudio();
+
+ IClydeAudioSource? CreateAudioSource(AudioStream stream);
+ IClydeBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio=false);
+ }
+}
diff --git a/Robust.Client/Graphics/IClydeAudioInternal.cs b/Robust.Client/Graphics/IClydeAudioInternal.cs
new file mode 100644
index 00000000000..df19590a8ac
--- /dev/null
+++ b/Robust.Client/Graphics/IClydeAudioInternal.cs
@@ -0,0 +1,16 @@
+using System;
+using Robust.Client.Input;
+using Robust.Client.UserInterface;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
+using Robust.Shared.Timing;
+
+namespace Robust.Client.Graphics
+{
+ internal interface IClydeAudioInternal : IClydeAudio
+ {
+ bool InitializePostWindowing();
+ void FrameProcess(FrameEventArgs eventArgs);
+ void Shutdown();
+ }
+}
diff --git a/Robust.Client/Graphics/IClydeAudioSource.cs b/Robust.Client/Graphics/IClydeAudioSource.cs
new file mode 100644
index 00000000000..c03b3dd33ca
--- /dev/null
+++ b/Robust.Client/Graphics/IClydeAudioSource.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Numerics;
+using JetBrains.Annotations;
+using Robust.Shared.Maths;
+
+namespace Robust.Client.Graphics
+{
+ public interface IClydeAudioSource : IDisposable
+ {
+ void StartPlaying();
+ void StopPlaying();
+
+ bool IsPlaying { get; }
+
+ bool IsLooping { get; set; }
+ bool IsGlobal { get; }
+
+ [MustUseReturnValue]
+ bool SetPosition(Vector2 position);
+ void SetPitch(float pitch);
+ void SetGlobal();
+ void SetVolume(float decibels);
+ void SetVolumeDirect(float gain);
+ void SetMaxDistance(float maxDistance);
+ void SetRolloffFactor(float rolloffFactor);
+ void SetReferenceDistance(float refDistance);
+ void SetOcclusion(float blocks);
+ void SetPlaybackPosition(float seconds);
+ void SetVelocity(Vector2 velocity);
+ }
+}
diff --git a/Robust.Client/Graphics/IClydeBufferedAudioSource.cs b/Robust.Client/Graphics/IClydeBufferedAudioSource.cs
new file mode 100644
index 00000000000..eccda3dc7c6
--- /dev/null
+++ b/Robust.Client/Graphics/IClydeBufferedAudioSource.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Robust.Client.Graphics
+{
+ public interface IClydeBufferedAudioSource : IClydeAudioSource
+ {
+ int SampleRate { get; set; }
+ int GetNumberOfBuffersProcessed();
+ void GetBuffersProcessed(Span handles);
+ void WriteBuffer(int handle, ReadOnlySpan data);
+ void WriteBuffer(int handle, ReadOnlySpan data);
+ void QueueBuffers(ReadOnlySpan handles);
+ void EmptyBuffers();
+ }
+}
diff --git a/Robust.Client/Graphics/Overlays/IOverlayManager.cs b/Robust.Client/Graphics/Overlays/IOverlayManager.cs
index 1c94894e004..611bae5e195 100644
--- a/Robust.Client/Graphics/Overlays/IOverlayManager.cs
+++ b/Robust.Client/Graphics/Overlays/IOverlayManager.cs
@@ -4,29 +4,32 @@
using JetBrains.Annotations;
using Robust.Shared.Timing;
-namespace Robust.Client.Graphics;
-
-[PublicAPI]
-public interface IOverlayManager
+namespace Robust.Client.Graphics
{
- bool AddOverlay(Overlay overlay);
- bool RemoveOverlay(Overlay overlay);
- bool RemoveOverlay(Type overlayClass);
- bool RemoveOverlay() where T : Overlay;
- bool TryGetOverlay(Type overlayClass, [NotNullWhen(true)] out Overlay? overlay);
- bool TryGetOverlay([NotNullWhen(true)] out T? overlay) where T : Overlay;
+ [PublicAPI]
+ public interface IOverlayManager
+ {
+ bool AddOverlay(Overlay overlay);
- Overlay GetOverlay(Type overlayClass);
- T GetOverlay() where T : Overlay;
+ bool RemoveOverlay(Overlay overlay);
+ bool RemoveOverlay(Type overlayClass);
+ bool RemoveOverlay() where T : Overlay;
- bool HasOverlay(Type overlayClass);
- bool HasOverlay() where T : Overlay;
+ bool TryGetOverlay(Type overlayClass, [NotNullWhen(true)] out Overlay? overlay);
+ bool TryGetOverlay([NotNullWhen(true)] out T? overlay) where T : Overlay;
- IEnumerable AllOverlays { get; }
-}
+ Overlay GetOverlay(Type overlayClass);
+ T GetOverlay() where T : Overlay;
-internal interface IOverlayManagerInternal : IOverlayManager
-{
- void FrameUpdate(FrameEventArgs args);
+ bool HasOverlay(Type overlayClass);
+ bool HasOverlay() where T : Overlay;
+
+ IEnumerable AllOverlays { get; }
+ }
+
+ internal interface IOverlayManagerInternal : IOverlayManager
+ {
+ void FrameUpdate(FrameEventArgs args);
+ }
}
diff --git a/Robust.Client/Graphics/Overlays/OverlayManager.cs b/Robust.Client/Graphics/Overlays/OverlayManager.cs
index e0022802bb7..5bb32c7109a 100644
--- a/Robust.Client/Graphics/Overlays/OverlayManager.cs
+++ b/Robust.Client/Graphics/Overlays/OverlayManager.cs
@@ -6,106 +6,107 @@
using Robust.Shared.Timing;
using Robust.Shared.ViewVariables;
-namespace Robust.Client.Graphics;
-
-internal sealed class OverlayManager : IOverlayManagerInternal, IPostInjectInit
+namespace Robust.Client.Graphics
{
- [Dependency] private readonly ILogManager _logMan = default!;
+ internal sealed class OverlayManager : IOverlayManagerInternal, IPostInjectInit
+ {
+ [Dependency] private readonly ILogManager _logMan = default!;
- [ViewVariables]
- private readonly Dictionary _overlays = new Dictionary();
- private ISawmill _logger = default!;
+ [ViewVariables]
+ private readonly Dictionary _overlays = new Dictionary();
+ private ISawmill _logger = default!;
- public IEnumerable AllOverlays => _overlays.Values;
+ public IEnumerable AllOverlays => _overlays.Values;
- public void FrameUpdate(FrameEventArgs args)
- {
- foreach (var overlay in _overlays.Values)
+ public void FrameUpdate(FrameEventArgs args)
{
- overlay.FrameUpdate(args);
+ foreach (var overlay in _overlays.Values)
+ {
+ overlay.FrameUpdate(args);
+ }
}
- }
-
- public bool AddOverlay(Overlay overlay)
- {
- if (_overlays.ContainsKey(overlay.GetType()))
- return false;
- _overlays.Add(overlay.GetType(), overlay);
- return true;
- }
- public bool RemoveOverlay(Type overlayClass)
- {
- if (!overlayClass.IsSubclassOf(typeof(Overlay)))
+ public bool AddOverlay(Overlay overlay)
{
- _logger.Error($"RemoveOverlay was called with arg: {overlayClass}, which is not a subclass of Overlay!");
- return false;
+ if (_overlays.ContainsKey(overlay.GetType()))
+ return false;
+ _overlays.Add(overlay.GetType(), overlay);
+ return true;
}
- return _overlays.Remove(overlayClass);
- }
-
- public bool RemoveOverlay() where T : Overlay
- {
- return RemoveOverlay(typeof(T));
- }
+ public bool RemoveOverlay(Type overlayClass)
+ {
+ if (!overlayClass.IsSubclassOf(typeof(Overlay)))
+ {
+ _logger.Error($"RemoveOverlay was called with arg: {overlayClass}, which is not a subclass of Overlay!");
+ return false;
+ }
- public bool RemoveOverlay(Overlay overlay)
- {
- return _overlays.Remove(overlay.GetType());
- }
+ return _overlays.Remove(overlayClass);
+ }
- public bool TryGetOverlay(Type overlayClass, [NotNullWhen(true)] out Overlay? overlay)
- {
- overlay = null;
- if (!overlayClass.IsSubclassOf(typeof(Overlay)))
+ public bool RemoveOverlay() where T : Overlay
{
- _logger.Error($"TryGetOverlay was called with arg: {overlayClass}, which is not a subclass of Overlay!");
- return false;
+ return RemoveOverlay(typeof(T));
}
- return _overlays.TryGetValue(overlayClass, out overlay);
- }
+ public bool RemoveOverlay(Overlay overlay)
+ {
+ return _overlays.Remove(overlay.GetType());
+ }
- public bool TryGetOverlay([NotNullWhen(true)] out T? overlay) where T : Overlay
- {
- overlay = null;
- if (_overlays.TryGetValue(typeof(T), out Overlay? toReturn))
+ public bool TryGetOverlay(Type overlayClass, [NotNullWhen(true)] out Overlay? overlay)
{
- overlay = (T)toReturn;
- return true;
+ overlay = null;
+ if (!overlayClass.IsSubclassOf(typeof(Overlay)))
+ {
+ _logger.Error($"TryGetOverlay was called with arg: {overlayClass}, which is not a subclass of Overlay!");
+ return false;
+ }
+
+ return _overlays.TryGetValue(overlayClass, out overlay);
}
- return false;
- }
+ public bool TryGetOverlay([NotNullWhen(true)] out T? overlay) where T : Overlay
+ {
+ overlay = null;
+ if (_overlays.TryGetValue(typeof(T), out Overlay? toReturn))
+ {
+ overlay = (T)toReturn;
+ return true;
+ }
- public Overlay GetOverlay(Type overlayClass)
- {
- return _overlays[overlayClass];
- }
+ return false;
+ }
- public T GetOverlay() where T : Overlay
- {
- return (T)_overlays[typeof(T)];
- }
+ public Overlay GetOverlay(Type overlayClass)
+ {
+ return _overlays[overlayClass];
+ }
- public bool HasOverlay(Type overlayClass)
- {
- if (!overlayClass.IsSubclassOf(typeof(Overlay)))
+ public T GetOverlay() where T : Overlay
{
- _logger.Error($"HasOverlay was called with arg: {overlayClass}, which is not a subclass of Overlay!");
+ return (T)_overlays[typeof(T)];
}
- return _overlays.ContainsKey(overlayClass);
- }
+ public bool HasOverlay(Type overlayClass)
+ {
+ if (!overlayClass.IsSubclassOf(typeof(Overlay)))
+ {
+ _logger.Error($"HasOverlay was called with arg: {overlayClass}, which is not a subclass of Overlay!");
+ }
- public bool HasOverlay() where T : Overlay
- {
- return _overlays.ContainsKey(typeof(T));
- }
+ return _overlays.ContainsKey(overlayClass);
+ }
- void IPostInjectInit.PostInject()
- {
- _logger = _logMan.GetSawmill("overlay");
+ public bool HasOverlay() where T : Overlay
+ {
+ return _overlays.ContainsKey(typeof(T));
+ }
+
+ void IPostInjectInit.PostInject()
+ {
+ _logger = _logMan.GetSawmill("overlay");
+ }
}
}
diff --git a/Robust.Client/Graphics/Shaders/ShaderPrototype.cs b/Robust.Client/Graphics/Shaders/ShaderPrototype.cs
index 144f745795d..2ab6b323e1c 100644
--- a/Robust.Client/Graphics/Shaders/ShaderPrototype.cs
+++ b/Robust.Client/Graphics/Shaders/ShaderPrototype.cs
@@ -120,7 +120,7 @@ void ISerializationHooks.AfterDeserialization()
if (_path == null)
throw new InvalidOperationException("Source shaders must specify a source file.");
- _source = IoCManager.Resolve().GetResource(_path.Value);
+ _source = IoCManager.Resolve().GetResource(_path.Value);
if (_paramMapping != null)
{
@@ -142,7 +142,7 @@ void ISerializationHooks.AfterDeserialization()
case "canvas":
Kind = ShaderKind.Canvas;
- _source = IoCManager.Resolve().GetResource("/Shaders/Internal/default-sprite.swsl");
+ _source = IoCManager.Resolve().GetResource("/Shaders/Internal/default-sprite.swsl");
break;
default:
diff --git a/Robust.Client/Map/ClydeTileDefinitionManager.cs b/Robust.Client/Map/ClydeTileDefinitionManager.cs
index d0dd55655aa..ce8081a88bd 100644
--- a/Robust.Client/Map/ClydeTileDefinitionManager.cs
+++ b/Robust.Client/Map/ClydeTileDefinitionManager.cs
@@ -7,7 +7,6 @@
using Robust.Client.ResourceManagement;
using Robust.Client.Utility;
using Robust.Shared.Console;
-using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Graphics;
using Robust.Shared.IoC;
@@ -23,7 +22,7 @@ namespace Robust.Client.Map
{
internal sealed class ClydeTileDefinitionManager : TileDefinitionManager, IClydeTileDefinitionManager
{
- [Dependency] private readonly IResourceManager _manager = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
private Texture? _tileTextureAtlas;
@@ -87,7 +86,7 @@ internal void _genTextureAtlas()
0, (h - EyeManager.PixelsPerMeter) / h,
tileSize / w, tileSize / h);
Image image;
- using (var stream = _manager.ContentFileRead("/Textures/noTile.png"))
+ using (var stream = _resourceCache.ContentFileRead("/Textures/noTile.png"))
{
image = Image.Load(stream);
}
@@ -111,7 +110,7 @@ internal void _genTextureAtlas()
// Already know it's not null above
var path = def.Sprite!.Value;
- using (var stream = _manager.ContentFileRead(path))
+ using (var stream = _resourceCache.ContentFileRead(path))
{
image = Image.Load(stream);
}
diff --git a/Robust.Client/Physics/PhysicsSystem.Predict.cs b/Robust.Client/Physics/PhysicsSystem.Predict.cs
index c47c15b4863..5a05bc3da97 100644
--- a/Robust.Client/Physics/PhysicsSystem.Predict.cs
+++ b/Robust.Client/Physics/PhysicsSystem.Predict.cs
@@ -1,6 +1,5 @@
using System.Buffers;
using System.Collections.Generic;
-using Robust.Client.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
@@ -8,6 +7,7 @@
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Physics.Dynamics.Contacts;
using Robust.Shared.Physics.Systems;
+using Robust.Shared.Player;
using Robust.Shared.Utility;
namespace Robust.Client.Physics;
diff --git a/Robust.Client/Placement/PlacementManager.cs b/Robust.Client/Placement/PlacementManager.cs
index f68adc236de..c83576138e1 100644
--- a/Robust.Client/Placement/PlacementManager.cs
+++ b/Robust.Client/Placement/PlacementManager.cs
@@ -28,7 +28,7 @@ public sealed partial class PlacementManager : IPlacementManager, IDisposable, I
{
[Dependency] private readonly IClientNetManager _networkManager = default!;
[Dependency] internal readonly IPlayerManager PlayerManager = default!;
- [Dependency] internal readonly IClientResourceCache ResourceCache = default!;
+ [Dependency] internal readonly IResourceCache ResourceCache = default!;
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
[Dependency] internal readonly IMapManager MapManager = default!;
[Dependency] private readonly IGameTiming _time = default!;
diff --git a/Robust.Client/Player/IPlayerManager.cs b/Robust.Client/Player/IPlayerManager.cs
index 20478543a74..cb3b2cc0052 100644
--- a/Robust.Client/Player/IPlayerManager.cs
+++ b/Robust.Client/Player/IPlayerManager.cs
@@ -15,15 +15,22 @@ public interface IPlayerManager : ISharedPlayerManager
event Action? PlayerListUpdated;
///
- /// Invoked when gets attached to a new entity. See also
+ /// Invoked when gets attached to a new entity, or when the local
+ /// session gets updated. See also
///
event Action? LocalPlayerAttached;
///
- /// Invoked when gets detached from new entity. See also
+ /// Invoked when gets detached from an entity, or when the local
+ /// session gets updated. See also
///
event Action? LocalPlayerDetached;
+ ///
+ /// Invoked whenever changes.
+ ///
+ event Action<(ICommonSession? Old, ICommonSession? New)>? LocalSessionChanged;
+
void ApplyPlayerStates(IReadOnlyCollection list);
///
@@ -38,34 +45,8 @@ public interface IPlayerManager : ISharedPlayerManager
///
void SetupMultiplayer(INetChannel channel);
+ void SetLocalSession(ICommonSession session);
+
[Obsolete("Use LocalSession instead")]
LocalPlayer? LocalPlayer { get;}
}
-
-///
-/// ECS event that gets raised when the local player gets attached to a new entity. The event is both broadcast and
-/// raised directed at the new entity.
-///
-public sealed class LocalPlayerAttachedEvent : EntityEventArgs
-{
- public LocalPlayerAttachedEvent(EntityUid entity)
- {
- Entity = entity;
- }
-
- public EntityUid Entity { get; }
-}
-
-///
-/// ECS event that gets raised when the local player gets detached from an entity. The event is both broadcast and
-/// raised directed at the new entity.
-///
-public sealed class LocalPlayerDetachedEvent : EntityEventArgs
-{
- public LocalPlayerDetachedEvent(EntityUid entity)
- {
- Entity = entity;
- }
-
- public EntityUid Entity { get; }
-}
\ No newline at end of file
diff --git a/Robust.Client/Player/PlayerManager.cs b/Robust.Client/Player/PlayerManager.cs
index 7c5557dcdd0..682b433ce06 100644
--- a/Robust.Client/Player/PlayerManager.cs
+++ b/Robust.Client/Player/PlayerManager.cs
@@ -42,12 +42,13 @@ public override ICommonSession[] NetworkedSessions
///
public override int MaxPlayers => _client.GameInfo?.ServerMaxPlayers ?? -1;
- public LocalPlayer? LocalPlayer { get; set; }
+ public LocalPlayer? LocalPlayer { get; private set; }
public event Action? LocalStatusChanged;
public event Action? PlayerListUpdated;
public event Action? LocalPlayerDetached;
public event Action? LocalPlayerAttached;
+ public event Action<(ICommonSession? Old, ICommonSession? New)>? LocalSessionChanged;
///
public override void Initialize(int maxPlayers)
@@ -64,22 +65,14 @@ private void StatusChanged(object? sender, SessionStatusEventArgs e)
LocalStatusChanged?.Invoke(e);
}
- ///
- public override void Startup()
- {
- if (LocalSession == null)
- throw new InvalidOperationException("LocalSession cannot be null");
-
- LocalPlayer = new LocalPlayer(LocalSession);
- base.Startup();
- }
-
public void SetupSinglePlayer(string name)
{
if (LocalSession != null)
throw new InvalidOperationException($"Player manager already running?");
- LocalSession = CreateAndAddSession(default, name);
+ var session = CreateAndAddSession(default, name);
+ session.ClientSide = true;
+ SetLocalSession(session);
Startup();
PlayerListUpdated?.Invoke();
}
@@ -89,18 +82,44 @@ public void SetupMultiplayer(INetChannel channel)
if (LocalSession != null)
throw new InvalidOperationException($"Player manager already running?");
- var session = CreateAndAddSession(channel.UserId, channel.UserName);
- session.Channel = channel;
- LocalSession = session;
+ SetLocalSession(CreateAndAddSession(channel));
Startup();
_network.ClientSendMessage(new MsgPlayerListReq());
}
+ public void SetLocalSession(ICommonSession? session)
+ {
+ if (session == LocalSession)
+ return;
+
+ var old = LocalSession;
+
+ if (old?.AttachedEntity is {} oldUid)
+ {
+ LocalSession = null;
+ LocalPlayer = null;
+ Sawmill.Info($"Detaching local player from {EntManager.ToPrettyString(oldUid)}.");
+ EntManager.EventBus.RaiseLocalEvent(oldUid, new LocalPlayerDetachedEvent(oldUid), true);
+ LocalPlayerDetached?.Invoke(oldUid);
+ }
+
+ LocalSession = session;
+ LocalPlayer = session == null ? null : new LocalPlayer(session);
+ Sawmill.Info($"Changing local session from {old?.ToString() ?? "null"} to {session?.ToString() ?? "null"}.");
+ LocalSessionChanged?.Invoke((old, LocalSession));
+
+ if (session?.AttachedEntity is {} newUid)
+ {
+ Sawmill.Info($"Attaching local player to {EntManager.ToPrettyString(newUid)}.");
+ EntManager.EventBus.RaiseLocalEvent(newUid, new LocalPlayerAttachedEvent(newUid), true);
+ LocalPlayerAttached?.Invoke(newUid);
+ }
+ }
+
///
public override void Shutdown()
{
- if (LocalSession != null)
- SetAttachedEntity(LocalSession, null);
+ SetAttachedEntity(LocalSession, null, out _);
LocalPlayer = null;
LocalSession = null;
_pendingStates.Clear();
@@ -108,16 +127,21 @@ public override void Shutdown()
PlayerListUpdated?.Invoke();
}
- public override void SetAttachedEntity(ICommonSession session, EntityUid? uid)
+ public override bool SetAttachedEntity(ICommonSession? session, EntityUid? uid, out ICommonSession? kicked, bool force = false)
{
+ kicked = null;
+ if (session == null)
+ return false;
+
if (session.AttachedEntity == uid)
- return;
+ return true;
var old = session.AttachedEntity;
- base.SetAttachedEntity(session, uid);
+ if (!base.SetAttachedEntity(session, uid, out kicked, force))
+ return false;
if (session != LocalSession)
- return;
+ return true;
if (old.HasValue)
{
@@ -129,13 +153,13 @@ public override void SetAttachedEntity(ICommonSession session, EntityUid? uid)
if (uid == null)
{
Sawmill.Info($"Local player is no longer attached to any entity.");
- return;
+ return true;
}
if (!EntManager.EntityExists(uid))
{
Sawmill.Error($"Attempted to attach player to non-existent entity {uid}!");
- return;
+ return true;
}
if (!EntManager.EnsureComponent(uid.Value, out EyeComponent eye))
@@ -148,6 +172,7 @@ public override void SetAttachedEntity(ICommonSession session, EntityUid? uid)
Sawmill.Info($"Attaching local player to {EntManager.ToPrettyString(uid)}.");
EntManager.EventBus.RaiseLocalEvent(uid.Value, new LocalPlayerAttachedEvent(uid.Value), true);
LocalPlayerAttached?.Invoke(uid.Value);
+ return true;
}
public void ApplyPlayerStates(IReadOnlyCollection list)
@@ -193,7 +218,7 @@ private bool ApplyStates(IReadOnlyCollection list, bool fullList)
_pendingStates.Remove(state.UserId);
}
- SetAttachedEntity(LocalSession, uid);
+ SetAttachedEntity(LocalSession, uid, out _, true);
SetStatus(LocalSession, state.Status);
}
@@ -233,11 +258,10 @@ private bool UpdatePlayerList(IEnumerable remotePlayers, bool full
{
// This is a new userid, so we create a new session.
DebugTools.Assert(state.UserId != LocalPlayer?.UserId);
- var newSession = CreateAndAddSession(state.UserId, state.Name);
+ var newSession = (CommonSession) CreateAndAddSession(state.UserId, state.Name);
newSession.Ping = state.Ping;
- newSession.Name = state.Name;
SetStatus(newSession, state.Status);
- SetAttachedEntity(newSession, controlled);
+ SetAttachedEntity(newSession, controlled, out _, true);
dirty = true;
continue;
}
@@ -256,7 +280,7 @@ private bool UpdatePlayerList(IEnumerable remotePlayers, bool full
local.Name = state.Name;
local.Ping = state.Ping;
SetStatus(local, state.Status);
- SetAttachedEntity(local, controlled);
+ SetAttachedEntity(local, controlled, out _, true);
}
// Remove old users. This only works if the provided state is a list of all players
@@ -264,10 +288,12 @@ private bool UpdatePlayerList(IEnumerable remotePlayers, bool full
{
foreach (var oldUser in InternalSessions.Keys.ToArray())
{
- // clear slot, player left
if (users.Contains(oldUser))
continue;
+ if (InternalSessions[oldUser].ClientSide)
+ continue;
+
DebugTools.Assert(oldUser != LocalUser
|| LocalUser == null
|| LocalUser == default(NetUserId),
diff --git a/Robust.Client/Profiling/LiveProfileViewControl.cs b/Robust.Client/Profiling/LiveProfileViewControl.cs
index 5154b543400..01e1a67d076 100644
--- a/Robust.Client/Profiling/LiveProfileViewControl.cs
+++ b/Robust.Client/Profiling/LiveProfileViewControl.cs
@@ -13,7 +13,7 @@ namespace Robust.Client.Profiling;
public sealed class LiveProfileViewControl : Control
{
[Dependency] private readonly ProfManager _profManager = default!;
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
public int MaxDepth { get; set; } = 2;
diff --git a/Robust.Client/Replays/Playback/IReplayPlaybackManager.cs b/Robust.Client/Replays/Playback/IReplayPlaybackManager.cs
index 3073bc754a7..3793f81403b 100644
--- a/Robust.Client/Replays/Playback/IReplayPlaybackManager.cs
+++ b/Robust.Client/Replays/Playback/IReplayPlaybackManager.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Robust.Shared.GameObjects;
+using Robust.Shared.GameStates;
using Robust.Shared.Network;
using Robust.Shared.Replays;
using Robust.Shared.Serialization.Markdown.Mapping;
@@ -128,6 +129,11 @@ public interface IReplayPlaybackManager
///
event Action? ReplayUnpaused;
+ ///
+ /// Invoked just before a replay applies a game state.
+ ///
+ event Action<(GameState Current, GameState? Next)>? BeforeApplyState;
+
///
/// If currently replaying a client-side recording, this is the user that recorded the replay.
/// Useful for setting default observer spawn positions.
@@ -137,5 +143,5 @@ public interface IReplayPlaybackManager
///
/// Fetches the entity that the is currently attached to.
///
- public bool TryGetRecorderEntity([NotNullWhen(true)] out EntityUid? uid);
+ bool TryGetRecorderEntity([NotNullWhen(true)] out EntityUid? uid);
}
diff --git a/Robust.Client/Replays/Playback/ReplayPlaybackManager.Checkpoint.cs b/Robust.Client/Replays/Playback/ReplayPlaybackManager.Checkpoint.cs
index cfd9f77e0a8..adc8ed1248f 100644
--- a/Robust.Client/Replays/Playback/ReplayPlaybackManager.Checkpoint.cs
+++ b/Robust.Client/Replays/Playback/ReplayPlaybackManager.Checkpoint.cs
@@ -66,6 +66,7 @@ private void ApplyCheckpointState(CheckpointState checkpoint, ReplayData replay)
_gameState.ClearDetachQueue();
EnsureDetachedExist(checkpoint);
_gameState.DetachImmediate(checkpoint.Detached);
+ BeforeApplyState?.Invoke((checkpoint.State, next));
_gameState.ApplyGameState(checkpoint.State, next);
}
diff --git a/Robust.Client/Replays/Playback/ReplayPlaybackManager.Time.cs b/Robust.Client/Replays/Playback/ReplayPlaybackManager.Time.cs
index f19d66a7328..9643ae1ac1a 100644
--- a/Robust.Client/Replays/Playback/ReplayPlaybackManager.Time.cs
+++ b/Robust.Client/Replays/Playback/ReplayPlaybackManager.Time.cs
@@ -1,4 +1,5 @@
using System;
+using Robust.Client.GameObjects;
using Robust.Client.GameStates;
using Robust.Shared.Utility;
@@ -58,7 +59,13 @@ public void SetIndex(int value, bool pausePlayback = true)
_timing.LastRealTick = _timing.LastProcessedTick = _timing.CurTick = Replay.CurTick;
_gameState.UpdateFullRep(state, cloneDelta: true);
- _gameState.ApplyGameState(state, Replay.NextState);
+
+ // Clear existing lerps
+ _entMan.EntitySysManager.GetEntitySystem().Reset();
+
+ var next = Replay.NextState;
+ BeforeApplyState?.Invoke((state, next));
+ _gameState.ApplyGameState(state, next);
ProcessMessages(Replay.CurMessages, skipEffectEvents);
// TODO REPLAYS block audio
diff --git a/Robust.Client/Replays/Playback/ReplayPlaybackManager.Update.cs b/Robust.Client/Replays/Playback/ReplayPlaybackManager.Update.cs
index b14a36b3669..6fb60f36e54 100644
--- a/Robust.Client/Replays/Playback/ReplayPlaybackManager.Update.cs
+++ b/Robust.Client/Replays/Playback/ReplayPlaybackManager.Update.cs
@@ -42,7 +42,9 @@ private void TickUpdateOverride(FrameEventArgs args)
{
var state = Replay.CurState;
_gameState.UpdateFullRep(state, cloneDelta: true);
- _gameState.ApplyGameState(state, Replay.NextState);
+ var next = Replay.NextState;
+ BeforeApplyState?.Invoke((state, next));
+ _gameState.ApplyGameState(state, next);
DebugTools.Assert(Replay.LastApplied >= state.FromSequence);
DebugTools.Assert(Replay.LastApplied + 1 <= state.ToSequence);
Replay.LastApplied = state.ToSequence;
diff --git a/Robust.Client/Replays/Playback/ReplayPlaybackManager.cs b/Robust.Client/Replays/Playback/ReplayPlaybackManager.cs
index 0b3c7d1d54e..a8df7fe91b9 100644
--- a/Robust.Client/Replays/Playback/ReplayPlaybackManager.cs
+++ b/Robust.Client/Replays/Playback/ReplayPlaybackManager.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using Robust.Client.Audio;
using Robust.Client.Audio.Midi;
using Robust.Client.Configuration;
using Robust.Client.GameObjects;
@@ -11,9 +10,9 @@
using Robust.Client.Timing;
using Robust.Client.Upload;
using Robust.Shared;
-using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
+using Robust.Shared.GameStates;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Network;
@@ -29,7 +28,7 @@ internal sealed partial class ReplayPlaybackManager : IReplayPlaybackManager
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly IMidiManager _midi = default!;
[Dependency] private readonly IPlayerManager _player = default!;
- [Dependency] private readonly IAudioInternal _clydeAudio = default!;
+ [Dependency] private readonly IClydeAudio _clydeAudio = default!;
[Dependency] private readonly IClientGameTiming _timing = default!;
[Dependency] private readonly IClientNetManager _netMan = default!;
[Dependency] private readonly IComponentFactory _factory = default!;
@@ -46,6 +45,7 @@ internal sealed partial class ReplayPlaybackManager : IReplayPlaybackManager
public event Action? ReplayPlaybackStopped;
public event Action? ReplayPaused;
public event Action? ReplayUnpaused;
+ public event Action<(GameState Current, GameState? Next)>? BeforeApplyState;
public ReplayData? Replay { get; private set; }
public NetUserId? Recorder => Replay?.Recorder;
diff --git a/Robust.Client/ResourceManagement/BaseResource.cs b/Robust.Client/ResourceManagement/BaseResource.cs
new file mode 100644
index 00000000000..0381c708a15
--- /dev/null
+++ b/Robust.Client/ResourceManagement/BaseResource.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Threading;
+using Robust.Shared.Utility;
+
+namespace Robust.Client.ResourceManagement
+{
+ ///
+ /// Base resource for the cache.
+ ///
+ public abstract class BaseResource : IDisposable
+ {
+ ///
+ /// Fallback resource path if this one does not exist.
+ ///
+ public virtual ResPath? Fallback => null;
+
+ ///
+ /// Disposes this resource.
+ ///
+ public virtual void Dispose()
+ {
+ }
+
+ ///
+ /// Deserializes the resource from the VFS.
+ ///
+ /// ResourceCache this resource is being loaded into.
+ /// Path of the resource requested on the VFS.
+ public abstract void Load(IResourceCache cache, ResPath path);
+
+ public virtual void Reload(IResourceCache cache, ResPath path, CancellationToken ct = default)
+ {
+
+ }
+ }
+}
diff --git a/Robust.Client/ResourceManagement/IClientResourceCache.cs b/Robust.Client/ResourceManagement/IClientResourceCache.cs
deleted file mode 100644
index ba14ee5806d..00000000000
--- a/Robust.Client/ResourceManagement/IClientResourceCache.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using Robust.Client.Graphics;
-using Robust.Shared.Audio;
-using Robust.Shared.GameObjects;
-
-namespace Robust.Client.ResourceManagement;
-
-///
-public interface IClientResourceCache : IResourceCache
-{
- // Resource load callbacks so content can hook stuff like click maps.
- event Action OnRawTextureLoaded;
- event Action OnRsiLoaded;
-
- IClyde Clyde { get; }
- IFontManager FontManager { get; }
-}
diff --git a/Robust.Client/ResourceManagement/IClientResourceCacheInternal.cs b/Robust.Client/ResourceManagement/IClientResourceCacheInternal.cs
deleted file mode 100644
index a9e5c8e0510..00000000000
--- a/Robust.Client/ResourceManagement/IClientResourceCacheInternal.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Robust.LoaderApi;
-using Robust.Shared.ContentPack;
-using Robust.Shared.Utility;
-
-namespace Robust.Client.ResourceManagement;
-
-///
-internal interface IClientResourceCacheInternal : IClientResourceCache
-{
- void TextureLoaded(TextureLoadedEventArgs eventArgs);
- void RsiLoaded(RsiLoadedEventArgs eventArgs);
- void PreloadTextures();
-
- void MountLoaderApi(IResourceManager manager, IFileApi api, string apiPrefix, ResPath? prefix = null);
-}
diff --git a/Robust.Client/ResourceManagement/IResourceCache.cs b/Robust.Client/ResourceManagement/IResourceCache.cs
new file mode 100644
index 00000000000..7b9b3a98a35
--- /dev/null
+++ b/Robust.Client/ResourceManagement/IResourceCache.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using Robust.Client.Graphics;
+using Robust.Shared.ContentPack;
+using Robust.Shared.Utility;
+
+namespace Robust.Client.ResourceManagement
+{
+ public interface IResourceCache : IResourceManager
+ {
+ T GetResource(string path, bool useFallback = true)
+ where T : BaseResource, new();
+
+ T GetResource(ResPath path, bool useFallback = true)
+ where T : BaseResource, new();
+
+ bool TryGetResource(string path, [NotNullWhen(true)] out T? resource)
+ where T : BaseResource, new();
+
+ bool TryGetResource(ResPath path, [NotNullWhen(true)] out T? resource)
+ where T : BaseResource, new();
+
+ void ReloadResource(string path)
+ where T : BaseResource, new();
+
+ void ReloadResource(ResPath path)
+ where T : BaseResource, new();
+
+ void CacheResource(string path, T resource)
+ where T : BaseResource, new();
+
+ void CacheResource(ResPath path, T resource)
+ where T : BaseResource, new();
+
+ T GetFallback()
+ where T : BaseResource, new();
+
+ IEnumerable> GetAllResources() where T : BaseResource, new();
+
+ // Resource load callbacks so content can hook stuff like click maps.
+ event Action OnRawTextureLoaded;
+ event Action OnRsiLoaded;
+
+ IClyde Clyde { get; }
+ IClydeAudio ClydeAudio { get; }
+ IFontManager FontManager { get; }
+ }
+}
diff --git a/Robust.Client/ResourceManagement/IResourceCacheInternal.cs b/Robust.Client/ResourceManagement/IResourceCacheInternal.cs
new file mode 100644
index 00000000000..ed78d53d4e6
--- /dev/null
+++ b/Robust.Client/ResourceManagement/IResourceCacheInternal.cs
@@ -0,0 +1,15 @@
+using Robust.LoaderApi;
+using Robust.Shared.ContentPack;
+using Robust.Shared.Utility;
+
+namespace Robust.Client.ResourceManagement
+{
+ internal interface IResourceCacheInternal : IResourceCache, IResourceManagerInternal
+ {
+ void TextureLoaded(TextureLoadedEventArgs eventArgs);
+ void RsiLoaded(RsiLoadedEventArgs eventArgs);
+
+ void MountLoaderApi(IFileApi api, string apiPrefix, ResPath? prefix=null);
+ void PreloadTextures();
+ }
+}
diff --git a/Robust.Client/ResourceManagement/ResourceCache.LoaderApi.cs b/Robust.Client/ResourceManagement/ResourceCache.LoaderApi.cs
index ca60ad6132d..6bfbf6af933 100644
--- a/Robust.Client/ResourceManagement/ResourceCache.LoaderApi.cs
+++ b/Robust.Client/ResourceManagement/ResourceCache.LoaderApi.cs
@@ -9,13 +9,6 @@ namespace Robust.Client.ResourceManagement
{
internal partial class ResourceCache
{
- public void MountLoaderApi(IResourceManager manager, IFileApi api, string apiPrefix, ResPath? prefix = null)
- {
- prefix ??= ResPath.Root;
- var root = new LoaderApiLoader(api, apiPrefix);
- manager.AddRoot(prefix.Value, root);
- }
-
private sealed class LoaderApiLoader : IContentRoot
{
private readonly IFileApi _api;
diff --git a/Robust.Client/ResourceManagement/ResourceCache.Preload.cs b/Robust.Client/ResourceManagement/ResourceCache.Preload.cs
index f698171adbf..90a526a1a57 100644
--- a/Robust.Client/ResourceManagement/ResourceCache.Preload.cs
+++ b/Robust.Client/ResourceManagement/ResourceCache.Preload.cs
@@ -3,13 +3,10 @@
using System.Linq;
using System.Threading.Tasks;
using OpenToolkit.Graphics.OpenGL4;
-using Robust.Client.Audio;
using Robust.Client.Graphics;
using Robust.Client.Utility;
using Robust.Shared;
-using Robust.Shared.Audio;
using Robust.Shared.Configuration;
-using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Maths;
@@ -22,8 +19,7 @@ namespace Robust.Client.ResourceManagement
internal partial class ResourceCache
{
[field: Dependency] public IClyde Clyde { get; } = default!;
- [field: Dependency] public IAudioInternal ClydeAudio { get; } = default!;
- [Dependency] private readonly IResourceManager _manager = default!;
+ [field: Dependency] public IClydeAudio ClydeAudio { get; } = default!;
[field: Dependency] public IFontManager FontManager { get; } = default!;
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
@@ -48,7 +44,7 @@ private void PreloadTextures(ISawmill sawmill)
var sw = Stopwatch.StartNew();
var resList = GetTypeDict();
- var texList = _manager.ContentFindFiles("/Textures/")
+ var texList = ContentFindFiles("/Textures/")
// Skip PNG files inside RSIs.
.Where(p => p.Extension == "png" && !p.ToString().Contains(".rsi/") && !resList.ContainsKey(p))
.Select(p => new TextureResource.LoadStepData {Path = p})
@@ -58,7 +54,7 @@ private void PreloadTextures(ISawmill sawmill)
{
try
{
- TextureResource.LoadPreTexture(_manager, data);
+ TextureResource.LoadPreTexture(this, data);
}
catch (Exception e)
{
@@ -120,7 +116,7 @@ private void PreloadRsis(ISawmill sawmill)
var sw = Stopwatch.StartNew();
var resList = GetTypeDict();
- var rsiList = _manager.ContentFindFiles("/Textures/")
+ var rsiList = ContentFindFiles("/Textures/")
.Where(p => p.ToString().EndsWith(".rsi/meta.json"))
.Select(c => c.Directory)
.Where(p => !resList.ContainsKey(p))
@@ -131,7 +127,7 @@ private void PreloadRsis(ISawmill sawmill)
{
try
{
- RSIResource.LoadPreTexture(_manager, data);
+ RSIResource.LoadPreTexture(this, data);
}
catch (Exception e)
{
diff --git a/Robust.Client/ResourceManagement/ResourceCache.cs b/Robust.Client/ResourceManagement/ResourceCache.cs
index 94f0fe9f482..8e3de707549 100644
--- a/Robust.Client/ResourceManagement/ResourceCache.cs
+++ b/Robust.Client/ResourceManagement/ResourceCache.cs
@@ -1,23 +1,221 @@
-using System;
-using Robust.Shared.ResourceManagement;
+using Robust.Shared.ContentPack;
+using Robust.Shared.Log;
+using Robust.Shared.Utility;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using Robust.LoaderApi;
-namespace Robust.Client.ResourceManagement;
-
-///
-/// Handles caching of
-///
-internal sealed partial class ResourceCache : SharedResourceCache, IClientResourceCacheInternal, IDisposable
+namespace Robust.Client.ResourceManagement
{
- public event Action? OnRawTextureLoaded;
- public event Action? OnRsiLoaded;
-
- public void TextureLoaded(TextureLoadedEventArgs eventArgs)
+ internal sealed partial class ResourceCache : ResourceManager, IResourceCacheInternal, IDisposable
{
- OnRawTextureLoaded?.Invoke(eventArgs);
- }
+ private readonly Dictionary> CachedResources =
+ new();
- public void RsiLoaded(RsiLoadedEventArgs eventArgs)
- {
- OnRsiLoaded?.Invoke(eventArgs);
+ private readonly Dictionary _fallbacks = new();
+
+ public T GetResource(string path, bool useFallback = true) where T : BaseResource, new()
+ {
+ return GetResource(new ResPath(path), useFallback);
+ }
+
+ public T GetResource(ResPath path, bool useFallback = true) where T : BaseResource, new()
+ {
+ var cache = GetTypeDict();
+ if (cache.TryGetValue(path, out var cached))
+ {
+ return (T) cached;
+ }
+
+ var _resource = new T();
+ try
+ {
+ _resource.Load(this, path);
+ cache[path] = _resource;
+ return _resource;
+ }
+ catch (Exception e)
+ {
+ if (useFallback && _resource.Fallback != null)
+ {
+ Logger.Error(
+ $"Exception while loading resource {typeof(T)} at '{path}', resorting to fallback.\n{Environment.StackTrace}\n{e}");
+ return GetResource(_resource.Fallback.Value, false);
+ }
+ else
+ {
+ Logger.Error(
+ $"Exception while loading resource {typeof(T)} at '{path}', no fallback available\n{Environment.StackTrace}\n{e}");
+ throw;
+ }
+ }
+ }
+
+ public bool TryGetResource(string path, [NotNullWhen(true)] out T? resource) where T : BaseResource, new()
+ {
+ return TryGetResource(new ResPath(path), out resource);
+ }
+
+ public bool TryGetResource(ResPath path, [NotNullWhen(true)] out T? resource) where T : BaseResource, new()
+ {
+ var cache = GetTypeDict();
+ if (cache.TryGetValue(path, out var cached))
+ {
+ resource = (T) cached;
+ return true;
+ }
+
+ var _resource = new T();
+ try
+ {
+ _resource.Load(this, path);
+ resource = _resource;
+ cache[path] = resource;
+ return true;
+ }
+ catch
+ {
+ resource = null;
+ return false;
+ }
+ }
+
+ public void ReloadResource(string path) where T : BaseResource, new()
+ {
+ ReloadResource(new ResPath(path));
+ }
+
+ public void ReloadResource(ResPath path) where T : BaseResource, new()
+ {
+ var cache = GetTypeDict();
+
+ if (!cache.TryGetValue(path, out var res))
+ {
+ return;
+ }
+
+ try
+ {
+ res.Reload(this, path);
+ }
+ catch (Exception e)
+ {
+ Logger.Error($"Exception while reloading resource {typeof(T)} at '{path}'\n{e}");
+ throw;
+ }
+ }
+
+ public bool HasResource(string path) where T : BaseResource, new()
+ {
+ return HasResource(new ResPath(path));
+ }
+
+ public bool HasResource(ResPath path) where T : BaseResource, new()
+ {
+ return TryGetResource(path, out var _);
+ }
+
+ public void CacheResource(string path, T resource) where T : BaseResource, new()
+ {
+ CacheResource(new ResPath(path), resource);
+ }
+
+ public void CacheResource(ResPath path, T resource) where T : BaseResource, new()
+ {
+ GetTypeDict()[path] = resource;
+ }
+
+ public T GetFallback() where T : BaseResource, new()
+ {
+ if (_fallbacks.TryGetValue(typeof(T), out var fallback))
+ {
+ return (T) fallback;
+ }
+
+ var res = new T();
+ if (res.Fallback == null)
+ {
+ throw new InvalidOperationException($"Resource of type '{typeof(T)}' has no fallback.");
+ }
+
+ fallback = GetResource(res.Fallback.Value, useFallback: false);
+ _fallbacks.Add(typeof(T), fallback);
+ return (T) fallback;
+ }
+
+ public IEnumerable> GetAllResources() where T : BaseResource, new()
+ {
+ return GetTypeDict().Select(p => new KeyValuePair(p.Key, (T) p.Value));
+ }
+
+ public event Action? OnRawTextureLoaded;
+ public event Action? OnRsiLoaded;
+
+ #region IDisposable Members
+
+ private bool disposed = false;
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ foreach (var res in CachedResources.Values.SelectMany(dict => dict.Values))
+ {
+ res.Dispose();
+ }
+ }
+
+ disposed = true;
+ }
+
+ ~ResourceCache()
+ {
+ Dispose(false);
+ }
+
+ #endregion IDisposable Members
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private Dictionary GetTypeDict()
+ {
+ if (!CachedResources.TryGetValue(typeof(T), out var ret))
+ {
+ ret = new Dictionary();
+ CachedResources.Add(typeof(T), ret);
+ }
+
+ return ret;
+ }
+
+ public void TextureLoaded(TextureLoadedEventArgs eventArgs)
+ {
+ OnRawTextureLoaded?.Invoke(eventArgs);
+ }
+
+ public void RsiLoaded(RsiLoadedEventArgs eventArgs)
+ {
+ OnRsiLoaded?.Invoke(eventArgs);
+ }
+
+ public void MountLoaderApi(IFileApi api, string apiPrefix, ResPath? prefix=null)
+ {
+ prefix ??= ResPath.Root;
+ var root = new LoaderApiLoader(api, apiPrefix);
+ AddRoot(prefix.Value, root);
+ }
}
}
diff --git a/Robust.Client/ResourceManagement/ResourceTypes/AudioResource.cs b/Robust.Client/ResourceManagement/ResourceTypes/AudioResource.cs
new file mode 100644
index 00000000000..110a7c5250e
--- /dev/null
+++ b/Robust.Client/ResourceManagement/ResourceTypes/AudioResource.cs
@@ -0,0 +1,43 @@
+using System;
+using Robust.Client.Audio;
+using Robust.Shared.Utility;
+using System.IO;
+using Robust.Client.Graphics;
+using Robust.Shared.IoC;
+
+namespace Robust.Client.ResourceManagement
+{
+ public sealed class AudioResource : BaseResource
+ {
+ public AudioStream AudioStream { get; private set; } = default!;
+
+ public override void Load(IResourceCache cache, ResPath path)
+ {
+ if (!cache.ContentFileExists(path))
+ {
+ throw new FileNotFoundException("Content file does not exist for audio sample.");
+ }
+
+ using (var fileStream = cache.ContentFileRead(path))
+ {
+ if (path.Extension == "ogg")
+ {
+ AudioStream = cache.ClydeAudio.LoadAudioOggVorbis(fileStream, path.ToString());
+ }
+ else if (path.Extension == "wav")
+ {
+ AudioStream = cache.ClydeAudio.LoadAudioWav(fileStream, path.ToString());
+ }
+ else
+ {
+ throw new NotSupportedException("Unable to load audio files outside of ogg Vorbis or PCM wav");
+ }
+ }
+ }
+
+ public static implicit operator AudioStream(AudioResource res)
+ {
+ return res.AudioStream;
+ }
+ }
+}
diff --git a/Robust.Client/ResourceManagement/ResourceTypes/FontResource.cs b/Robust.Client/ResourceManagement/ResourceTypes/FontResource.cs
index 8c7f3994948..8f570542151 100644
--- a/Robust.Client/ResourceManagement/ResourceTypes/FontResource.cs
+++ b/Robust.Client/ResourceManagement/ResourceTypes/FontResource.cs
@@ -1,8 +1,6 @@
using System.IO;
using Robust.Client.Graphics;
-using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
-using Robust.Shared.ResourceManagement;
using Robust.Shared.Utility;
namespace Robust.Client.ResourceManagement
@@ -11,17 +9,16 @@ public sealed class FontResource : BaseResource
{
internal IFontFaceHandle FontFaceHandle { get; private set; } = default!;
- public override void Load(IDependencyCollection dependencies, ResPath path)
+ public override void Load(IResourceCache cache, ResPath path)
{
-
- if (!dependencies.Resolve().TryContentFileRead(path, out var stream))
+ if (!cache.TryContentFileRead(path, out var stream))
{
throw new FileNotFoundException("Content file does not exist for font");
}
using (stream)
{
- FontFaceHandle = dependencies.Resolve().Load(stream);
+ FontFaceHandle = ((IFontManagerInternal)cache.FontManager).Load(stream);
}
}
diff --git a/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs b/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs
index 24e213dc527..c7cb919f115 100644
--- a/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs
+++ b/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs
@@ -3,12 +3,10 @@
using System.Linq;
using Robust.Client.Graphics;
using Robust.Client.Utility;
-using Robust.Shared.ContentPack;
using Robust.Shared.Graphics;
using Robust.Shared.Graphics.RSI;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
-using Robust.Shared.ResourceManagement;
using Robust.Shared.Resources;
using Robust.Shared.Utility;
using SixLabors.ImageSharp;
@@ -36,27 +34,26 @@ public sealed class RSIResource : BaseResource
///
public const uint MAXIMUM_RSI_VERSION = RsiLoading.MAXIMUM_RSI_VERSION;
- public override void Load(IDependencyCollection dependencies, ResPath path)
+ public override void Load(IResourceCache cache, ResPath path)
{
var loadStepData = new LoadStepData {Path = path};
- var manager = dependencies.Resolve();
- LoadPreTexture(manager, loadStepData);
+ LoadPreTexture(cache, loadStepData);
- loadStepData.AtlasTexture = dependencies.Resolve().LoadTextureFromImage(
+ loadStepData.AtlasTexture = cache.Clyde.LoadTextureFromImage(
loadStepData.AtlasSheet,
loadStepData.Path.ToString());
LoadPostTexture(loadStepData);
- LoadFinish(dependencies.Resolve(), loadStepData);
+ LoadFinish(cache, loadStepData);
loadStepData.AtlasSheet.Dispose();
}
- internal static void LoadPreTexture(IResourceManager manager, LoadStepData data)
+ internal static void LoadPreTexture(IResourceCache cache, LoadStepData data)
{
var manifestPath = data.Path / "meta.json";
RsiLoading.RsiMetadata metadata;
- using (var manifestFile = manager.ContentFileRead(manifestPath))
+ using (var manifestFile = cache.ContentFileRead(manifestPath))
{
metadata = RsiLoading.LoadRsiMetadata(manifestFile);
}
@@ -89,7 +86,7 @@ internal static void LoadPreTexture(IResourceManager manager, LoadStepData data)
var stateObject = metadata.States[index];
// Load image from disk.
var texPath = data.Path / (stateObject.StateId + ".png");
- using (var stream = manager.ContentFileRead(texPath))
+ using (var stream = cache.ContentFileRead(texPath))
{
reg.Src = Image.Load(stream);
}
@@ -215,10 +212,14 @@ internal static void LoadPostTexture(LoadStepData data)
}
}
- internal void LoadFinish(IClientResourceCacheInternal cache, LoadStepData data)
+ internal void LoadFinish(IResourceCache cache, LoadStepData data)
{
RSI = data.Rsi;
- cache.RsiLoaded(new RsiLoadedEventArgs(data.Path, this, data.AtlasSheet, data.CallbackOffsets));
+
+ if (cache is IResourceCacheInternal cacheInternal)
+ {
+ cacheInternal.RsiLoaded(new RsiLoadedEventArgs(data.Path, this, data.AtlasSheet, data.CallbackOffsets));
+ }
}
///
diff --git a/Robust.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs b/Robust.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs
index deae43661c6..5d5df20b111 100644
--- a/Robust.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs
+++ b/Robust.Client/ResourceManagement/ResourceTypes/ShaderSourceResource.cs
@@ -4,7 +4,6 @@
using Robust.Client.Graphics.Clyde;
using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
-using Robust.Shared.ResourceManagement;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
@@ -21,31 +20,28 @@ internal sealed class ShaderSourceResource : BaseResource
[ViewVariables]
internal ParsedShader ParsedShader { get; private set; } = default!;
- public override void Load(IDependencyCollection dependencies, ResPath path)
+ public override void Load(IResourceCache cache, ResPath path)
{
- var manager = dependencies.Resolve();
-
- using (var stream = manager.ContentFileRead(path))
+ using (var stream = cache.ContentFileRead(path))
using (var reader = new StreamReader(stream, EncodingHelpers.UTF8))
{
- ParsedShader = ShaderParser.Parse(reader, manager);
+ ParsedShader = ShaderParser.Parse(reader, cache);
}
- ClydeHandle = dependencies.Resolve().LoadShader(ParsedShader, path.ToString());
+ ClydeHandle = ((IClydeInternal)cache.Clyde).LoadShader(ParsedShader, path.ToString());
}
- public override void Reload(IDependencyCollection dependencies, ResPath path, CancellationToken ct = default)
+ public override void Reload(IResourceCache cache, ResPath path, CancellationToken ct = default)
{
- var manager = dependencies.Resolve();
ct = ct != default ? ct : new CancellationTokenSource(30000).Token;
for (;;)
{
try
{
- using var stream = manager.ContentFileRead(path);
+ using var stream = cache.ContentFileRead(path);
using var reader = new StreamReader(stream, EncodingHelpers.UTF8);
- ParsedShader = ShaderParser.Parse(reader, manager);
+ ParsedShader = ShaderParser.Parse(reader, cache);
break;
}
catch (IOException ioe)
@@ -61,7 +57,7 @@ public override void Reload(IDependencyCollection dependencies, ResPath path, Ca
}
}
- dependencies.Resolve().ReloadShader(ClydeHandle, ParsedShader);
+ ((IClydeInternal)cache.Clyde).ReloadShader(ClydeHandle, ParsedShader);
}
}
}
diff --git a/Robust.Client/ResourceManagement/ResourceTypes/TextureResource.cs b/Robust.Client/ResourceManagement/ResourceTypes/TextureResource.cs
index c375e2d5f08..24db71b9207 100644
--- a/Robust.Client/ResourceManagement/ResourceTypes/TextureResource.cs
+++ b/Robust.Client/ResourceManagement/ResourceTypes/TextureResource.cs
@@ -1,12 +1,10 @@
using System.IO;
using System.Threading;
using Robust.Client.Graphics;
-using Robust.Shared.ContentPack;
using Robust.Shared.Graphics;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Maths;
-using Robust.Shared.ResourceManagement;
using Robust.Shared.Utility;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
@@ -21,7 +19,7 @@ public sealed class TextureResource : BaseResource
public Texture Texture => _texture;
- public override void Load(IDependencyCollection dependencies, ResPath path)
+ public override void Load(IResourceCache cache, ResPath path)
{
if (path.Directory.Filename.EndsWith(".rsi"))
{
@@ -33,12 +31,12 @@ public override void Load(IDependencyCollection dependencies, ResPath path)
var data = new LoadStepData {Path = path};
- LoadPreTexture(dependencies.Resolve(), data);
- LoadTexture(dependencies.Resolve(), data);
- LoadFinish(dependencies.Resolve(), data);
+ LoadPreTexture(cache, data);
+ LoadTexture(cache.Clyde, data);
+ LoadFinish(cache, data);
}
- internal static void LoadPreTexture(IResourceManager cache, LoadStepData data)
+ internal static void LoadPreTexture(IResourceCache cache, LoadStepData data)
{
using (var stream = cache.ContentFileRead(data.Path))
{
@@ -53,11 +51,11 @@ internal static void LoadTexture(IClyde clyde, LoadStepData data)
data.Texture = clyde.LoadTextureFromImage(data.Image, data.Path.ToString(), data.LoadParameters);
}
- internal void LoadFinish(IClientResourceCache cache, LoadStepData data)
+ internal void LoadFinish(IResourceCache cache, LoadStepData data)
{
_texture = data.Texture;
- if (cache is IClientResourceCacheInternal cacheInternal)
+ if (cache is IResourceCacheInternal cacheInternal)
{
cacheInternal.TextureLoaded(new TextureLoadedEventArgs(data.Path, data.Image, this));
}
@@ -65,7 +63,7 @@ internal void LoadFinish(IClientResourceCache cache, LoadStepData data)
data.Image.Dispose();
}
- private static TextureLoadParameters? TryLoadTextureParameters(IResourceManager cache, ResPath path)
+ private static TextureLoadParameters? TryLoadTextureParameters(IResourceCache cache, ResPath path)
{
var metaPath = path.WithName(path.Filename + ".yml");
if (cache.TryContentFileRead(metaPath, out var stream))
@@ -92,11 +90,12 @@ internal void LoadFinish(IClientResourceCache cache, LoadStepData data)
return null;
}
- public override void Reload(IDependencyCollection dependencies, ResPath path, CancellationToken ct = default)
+ public override void Reload(IResourceCache cache, ResPath path, CancellationToken ct = default)
{
- var data = new LoadStepData {Path = path};
+ var clyde = IoCManager.Resolve();
- LoadPreTexture(dependencies.Resolve(), data);
+ var data = new LoadStepData {Path = path};
+ LoadPreTexture(cache, data);
if (data.Image.Width == Texture.Width && data.Image.Height == Texture.Height)
{
@@ -107,7 +106,7 @@ public override void Reload(IDependencyCollection dependencies, ResPath path, Ca
{
// Dimensions do not match, make new texture.
_texture.Dispose();
- LoadTexture(dependencies.Resolve(), data);
+ LoadTexture(clyde, data);
_texture = data.Texture;
}
diff --git a/Robust.Client/Robust.Client.csproj b/Robust.Client/Robust.Client.csproj
index 4654b0cc8a9..b1eb05fc071 100644
--- a/Robust.Client/Robust.Client.csproj
+++ b/Robust.Client/Robust.Client.csproj
@@ -16,12 +16,12 @@
+
-
diff --git a/Robust.Client/Serialization/ClientSpriteSpecifierSerializer.cs b/Robust.Client/Serialization/ClientSpriteSpecifierSerializer.cs
index 08ee5d3b882..aea3cc09bde 100644
--- a/Robust.Client/Serialization/ClientSpriteSpecifierSerializer.cs
+++ b/Robust.Client/Serialization/ClientSpriteSpecifierSerializer.cs
@@ -27,7 +27,7 @@ public override ValidationNode ValidateRsi(ISerializationManager serializationMa
return new ErrorNode(node, "Sprite specifier has missing/invalid state node");
}
- var res = dependencies.Resolve();
+ var res = dependencies.Resolve();
var rsiPath = TextureRoot / valuePathNode.Value;
if (!res.TryGetResource(rsiPath, out RSIResource? resource))
{
diff --git a/Robust.Client/UserInterface/Controllers/Implementations/EntitySpawningUIController.cs b/Robust.Client/UserInterface/Controllers/Implementations/EntitySpawningUIController.cs
index b687e94dc4b..dda465d5369 100644
--- a/Robust.Client/UserInterface/Controllers/Implementations/EntitySpawningUIController.cs
+++ b/Robust.Client/UserInterface/Controllers/Implementations/EntitySpawningUIController.cs
@@ -21,7 +21,7 @@ public sealed class EntitySpawningUIController : UIController
{
[Dependency] private readonly IPlacementManager _placement = default!;
[Dependency] private readonly IPrototypeManager _prototypes = default!;
- [Dependency] private readonly IClientResourceCache _resources = default!;
+ [Dependency] private readonly IResourceCache _resources = default!;
private EntitySpawnWindow? _window;
private readonly List _shownEntities = new();
diff --git a/Robust.Client/UserInterface/Controllers/Implementations/TileSpawningUIController.cs b/Robust.Client/UserInterface/Controllers/Implementations/TileSpawningUIController.cs
index 445344d6042..104f20df466 100644
--- a/Robust.Client/UserInterface/Controllers/Implementations/TileSpawningUIController.cs
+++ b/Robust.Client/UserInterface/Controllers/Implementations/TileSpawningUIController.cs
@@ -19,7 +19,7 @@ namespace Robust.Client.UserInterface.Controllers.Implementations;
public sealed class TileSpawningUIController : UIController
{
[Dependency] private readonly IPlacementManager _placement = default!;
- [Dependency] private readonly IClientResourceCache _resources = default!;
+ [Dependency] private readonly IResourceCache _resources = default!;
[Dependency] private readonly ITileDefinitionManager _tiles = default!;
private TileSpawnWindow? _window;
diff --git a/Robust.Client/UserInterface/Controls/RichTextLabel.cs b/Robust.Client/UserInterface/Controls/RichTextLabel.cs
index 8d406382272..8836b42e3c0 100644
--- a/Robust.Client/UserInterface/Controls/RichTextLabel.cs
+++ b/Robust.Client/UserInterface/Controls/RichTextLabel.cs
@@ -20,6 +20,7 @@ public class RichTextLabel : Control
public RichTextLabel()
{
IoCManager.InjectDependencies(this);
+ VerticalAlignment = VAlignment.Center;
}
public void SetMessage(FormattedMessage message, Type[]? tagsAllowed = null, Color? defaultColor = null)
diff --git a/Robust.Client/UserInterface/Controls/TextureRect.cs b/Robust.Client/UserInterface/Controls/TextureRect.cs
index f982a16b898..34e21137a3e 100644
--- a/Robust.Client/UserInterface/Controls/TextureRect.cs
+++ b/Robust.Client/UserInterface/Controls/TextureRect.cs
@@ -48,7 +48,7 @@ public string TexturePath
{
set
{
- Texture = IoCManager.Resolve().GetResource(value);
+ Texture = IoCManager.Resolve().GetResource(value);
_texturePath = value;
}
diff --git a/Robust.Client/UserInterface/CustomControls/DebugMonitorControls/DebugCoordsPanel.cs b/Robust.Client/UserInterface/CustomControls/DebugMonitorControls/DebugCoordsPanel.cs
index 5e1783ccc98..a8415381918 100644
--- a/Robust.Client/UserInterface/CustomControls/DebugMonitorControls/DebugCoordsPanel.cs
+++ b/Robust.Client/UserInterface/CustomControls/DebugMonitorControls/DebugCoordsPanel.cs
@@ -70,6 +70,7 @@ protected override void FrameUpdate(FrameEventArgs args)
return;
var mapSystem = _entityManager.System();
+ var xformSystem = _entityManager.System();
if (_mapManager.TryFindGridAt(mouseWorldMap, out var mouseGridUid, out var mouseGrid))
{
@@ -80,7 +81,7 @@ protected override void FrameUpdate(FrameEventArgs args)
{
mouseGridPos = new EntityCoordinates(_mapManager.GetMapEntityId(mouseWorldMap.MapId),
mouseWorldMap.Position);
- tile = new TileRef(EntityUid.Invalid, mouseGridPos.ToVector2i(_entityManager, _mapManager), Tile.Empty);
+ tile = new TileRef(EntityUid.Invalid, mouseGridPos.ToVector2i(_entityManager, _mapManager, xformSystem), Tile.Empty);
}
var controlHovered = UserInterfaceManager.CurrentlyHovered;
@@ -90,35 +91,35 @@ protected override void FrameUpdate(FrameEventArgs args)
Mouse Pos:
Screen: {mouseScreenPos}
{mouseWorldMap}
- {mouseGridPos}
+ {_entityManager.GetNetCoordinates(mouseGridPos)}
{tile}
GUI: {controlHovered}");
- _textBuilder.AppendLine("\nAttached Entity:");
- var controlledEntity = _playerManager?.LocalPlayer?.ControlledEntity ?? EntityUid.Invalid;
+ _textBuilder.AppendLine("\nAttached NetEntity:");
+ var controlledEntity = _playerManager.LocalSession?.AttachedEntity ?? EntityUid.Invalid;
+
if (controlledEntity == EntityUid.Invalid)
{
- _textBuilder.AppendLine("No attached entity.");
+ _textBuilder.AppendLine("No attached netentity.");
}
else
{
var entityTransform = _entityManager.GetComponent(controlledEntity);
- var playerWorldOffset = entityTransform.MapPosition;
+ var playerWorldOffset = xformSystem.GetMapCoordinates(entityTransform);
var playerScreen = _eyeManager.WorldToScreen(playerWorldOffset.Position);
var playerCoordinates = entityTransform.Coordinates;
- var playerRotation = entityTransform.WorldRotation;
+ var playerRotation = xformSystem.GetWorldRotation(entityTransform);
var gridRotation = entityTransform.GridUid != null
- ? _entityManager.GetComponent(entityTransform.GridUid.Value)
- .WorldRotation
+ ? xformSystem.GetWorldRotation(entityTransform.GridUid.Value)
: Angle.Zero;
_textBuilder.Append($@" Screen: {playerScreen}
{playerWorldOffset}
- {playerCoordinates}
+ {_entityManager.GetNetCoordinates(playerCoordinates)}
Rotation: {playerRotation.Degrees:F2}°
- EntId: {controlledEntity}
- GridUid: {entityTransform.GridUid}
+ NEntId: {_entityManager.GetNetEntity(controlledEntity)}
+ Grid NEntId: {_entityManager.GetNetEntity(entityTransform.GridUid)}
Grid Rotation: {gridRotation.Degrees:F2}°");
}
diff --git a/Robust.Client/UserInterface/DevWindow/DevWindow.xaml.cs b/Robust.Client/UserInterface/DevWindow/DevWindow.xaml.cs
index b641777f892..2502d3b0e65 100644
--- a/Robust.Client/UserInterface/DevWindow/DevWindow.xaml.cs
+++ b/Robust.Client/UserInterface/DevWindow/DevWindow.xaml.cs
@@ -28,7 +28,7 @@ private void InitializeComponent()
TabContainer.SetTabTitle(Perf, "Profiling");
Stylesheet =
- new DefaultStylesheet(IoCManager.Resolve(), IoCManager.Resolve()).Stylesheet;
+ new DefaultStylesheet(IoCManager.Resolve(), IoCManager.Resolve()).Stylesheet;
}
}
diff --git a/Robust.Client/UserInterface/RichText/BoldItalicTag.cs b/Robust.Client/UserInterface/RichText/BoldItalicTag.cs
index c1a0b00af2e..eda24e5c190 100644
--- a/Robust.Client/UserInterface/RichText/BoldItalicTag.cs
+++ b/Robust.Client/UserInterface/RichText/BoldItalicTag.cs
@@ -9,7 +9,7 @@ public sealed class BoldItalicTag : IMarkupTag
{
public const string BoldItalicFont = "DefaultBoldItalic";
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public string Name => "bolditalic";
diff --git a/Robust.Client/UserInterface/RichText/BoldTag.cs b/Robust.Client/UserInterface/RichText/BoldTag.cs
index 8fb2f39158a..c1e832e563c 100644
--- a/Robust.Client/UserInterface/RichText/BoldTag.cs
+++ b/Robust.Client/UserInterface/RichText/BoldTag.cs
@@ -10,7 +10,7 @@ public sealed class BoldTag : IMarkupTag
{
public const string BoldFont = "DefaultBold";
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public string Name => "bold";
diff --git a/Robust.Client/UserInterface/RichText/FontTag.cs b/Robust.Client/UserInterface/RichText/FontTag.cs
index 222b9691768..f9d88fb2f74 100644
--- a/Robust.Client/UserInterface/RichText/FontTag.cs
+++ b/Robust.Client/UserInterface/RichText/FontTag.cs
@@ -16,7 +16,7 @@ public sealed class FontTag : IMarkupTag
public const string DefaultFont = "Default";
public const int DefaultSize = 12;
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public string Name => "font";
@@ -43,7 +43,7 @@ public void PopDrawContext(MarkupNode node, MarkupDrawingContext context)
public static Font CreateFont(
Stack contextFontStack,
MarkupNode node,
- IClientResourceCache cache,
+ IResourceCache cache,
IPrototypeManager prototypeManager,
string fontId)
{
diff --git a/Robust.Client/UserInterface/RichText/HeadingTag.cs b/Robust.Client/UserInterface/RichText/HeadingTag.cs
index acd189783c2..4d8c4e784e6 100644
--- a/Robust.Client/UserInterface/RichText/HeadingTag.cs
+++ b/Robust.Client/UserInterface/RichText/HeadingTag.cs
@@ -8,7 +8,7 @@ namespace Robust.Client.UserInterface.RichText;
public sealed class HeadingTag : IMarkupTag
{
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public string Name => "head";
diff --git a/Robust.Client/UserInterface/RichText/ItalicTag.cs b/Robust.Client/UserInterface/RichText/ItalicTag.cs
index 37eedb6505d..b70cc11fb0f 100644
--- a/Robust.Client/UserInterface/RichText/ItalicTag.cs
+++ b/Robust.Client/UserInterface/RichText/ItalicTag.cs
@@ -10,7 +10,7 @@ public sealed class ItalicTag : IMarkupTag
{
public const string ItalicFont = "DefaultItalic";
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public string Name => "italic";
diff --git a/Robust.Client/UserInterface/Stylesheets/DefaultStylesheet.cs b/Robust.Client/UserInterface/Stylesheets/DefaultStylesheet.cs
index a1c39f08195..72575887cec 100644
--- a/Robust.Client/UserInterface/Stylesheets/DefaultStylesheet.cs
+++ b/Robust.Client/UserInterface/Stylesheets/DefaultStylesheet.cs
@@ -12,7 +12,7 @@ public sealed class DefaultStylesheet
{
public Stylesheet Stylesheet { get; private set; } = default!;
- public DefaultStylesheet(IClientResourceCache res, IUserInterfaceManager userInterfaceManager)
+ public DefaultStylesheet(IResourceCache res, IUserInterfaceManager userInterfaceManager)
{
var notoSansFont = res.GetResource("/EngineFonts/NotoSans/NotoSans-Regular.ttf");
var notoSansFont12 = new VectorFont(notoSansFont, 12);
diff --git a/Robust.Client/UserInterface/Themes/UiTheme.cs b/Robust.Client/UserInterface/Themes/UiTheme.cs
index ab97260db99..872f4309ef0 100644
--- a/Robust.Client/UserInterface/Themes/UiTheme.cs
+++ b/Robust.Client/UserInterface/Themes/UiTheme.cs
@@ -4,7 +4,6 @@
using System.Linq;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
-using Robust.Shared.ContentPack;
using Robust.Shared.Graphics;
using Robust.Shared.IoC;
using Robust.Shared.Log;
@@ -19,7 +18,7 @@ namespace Robust.Client.UserInterface.Themes;
[Prototype("uiTheme")]
public sealed class UITheme : IPrototype
{
- private IClientResourceCache? _cache;
+ private IResourceCache? _cache;
private IUserInterfaceManager? _uiMan;
//this is used for ease of access
@@ -38,11 +37,10 @@ public sealed class UITheme : IPrototype
public Dictionary? Colors { get; }
public ResPath Path => _path == default ? new ResPath(DefaultPath+"/"+ID) : _path;
- private void ValidateFilePath(IResourceManager manager)
+ private void ValidateFilePath(IResourceCache resourceCache)
{
- var foundFolders = manager.ContentFindFiles(Path.ToRootedPath());
- if (!foundFolders.Any())
- throw new Exception("UITheme: "+ID+" not found in resources!");
+ var foundFolders = resourceCache.ContentFindFiles(Path.ToRootedPath());
+ if (!foundFolders.Any()) throw new Exception("UITheme: "+ID+" not found in resources!");
}
public Texture ResolveTexture(string texturePath)
diff --git a/Robust.Client/UserInterface/UserInterfaceManager.cs b/Robust.Client/UserInterface/UserInterfaceManager.cs
index 28a3921c146..8c1be1b0612 100644
--- a/Robust.Client/UserInterface/UserInterfaceManager.cs
+++ b/Robust.Client/UserInterface/UserInterfaceManager.cs
@@ -38,7 +38,7 @@ internal sealed partial class UserInterfaceManager : IUserInterfaceManagerIntern
[Dependency] private readonly IFontManager _fontManager = default!;
[Dependency] private readonly IClydeInternal _clyde = default!;
[Dependency] private readonly IClientGameTiming _gameTiming = default!;
- [Dependency] private readonly IClientResourceCache _resourceCache = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!;
diff --git a/Robust.Client/Utility/SpriteSpecifierExt.cs b/Robust.Client/Utility/SpriteSpecifierExt.cs
index 178f426ca79..412857a41ef 100644
--- a/Robust.Client/Utility/SpriteSpecifierExt.cs
+++ b/Robust.Client/Utility/SpriteSpecifierExt.cs
@@ -17,7 +17,7 @@ namespace Robust.Client.Utility
///
public static class SpriteSpecifierExt
{
- public static Texture GetTexture(this SpriteSpecifier.Texture texSpecifier, IClientResourceCache cache)
+ public static Texture GetTexture(this SpriteSpecifier.Texture texSpecifier, IResourceCache cache)
{
return cache
.GetResource(SpriteSpecifierSerializer.TextureRoot / texSpecifier.TexturePath)
@@ -25,7 +25,7 @@ public static Texture GetTexture(this SpriteSpecifier.Texture texSpecifier, ICli
}
[Obsolete("Use SpriteSystem")]
- public static RSI.State GetState(this SpriteSpecifier.Rsi rsiSpecifier, IClientResourceCache cache)
+ public static RSI.State GetState(this SpriteSpecifier.Rsi rsiSpecifier, IResourceCache cache)
{
if (!cache.TryGetResource(SpriteSpecifierSerializer.TextureRoot / rsiSpecifier.RsiPath, out var theRsi))
{
@@ -56,7 +56,7 @@ public static IDirectionalTextureProvider DirFrame0(this SpriteSpecifier specifi
[Obsolete("Use SpriteSystem")]
public static IRsiStateLike RsiStateLike(this SpriteSpecifier specifier)
{
- var resC = IoCManager.Resolve();
+ var resC = IoCManager.Resolve();
switch (specifier)
{
case SpriteSpecifier.Texture tex:
diff --git a/Robust.Packaging/AssetProcessing/Passes/AssetPassPackRsis.cs b/Robust.Packaging/AssetProcessing/Passes/AssetPassPackRsis.cs
index ffc99c744ec..5b0f04e177c 100644
--- a/Robust.Packaging/AssetProcessing/Passes/AssetPassPackRsis.cs
+++ b/Robust.Packaging/AssetProcessing/Passes/AssetPassPackRsis.cs
@@ -61,7 +61,7 @@ protected override void AcceptFinished()
foreach (var (key, dat) in _foundRsis)
{
if (dat.MetaJson == null)
- return;
+ continue;
RunJob(() =>
{
diff --git a/Robust.Packaging/RobustClientAssetGraph.cs b/Robust.Packaging/RobustClientAssetGraph.cs
index 485111c4b64..85a2eca9030 100644
--- a/Robust.Packaging/RobustClientAssetGraph.cs
+++ b/Robust.Packaging/RobustClientAssetGraph.cs
@@ -21,11 +21,11 @@ public sealed class RobustClientAssetGraph
///
public IReadOnlyCollection AllPasses { get; }
- public RobustClientAssetGraph()
+ public RobustClientAssetGraph(bool parallel = true)
{
// The code injecting the list of source files is assumed to be pretty single-threaded.
// We use a parallelizing input to break out all the work on files coming in onto multiple threads.
- Input = new AssetPassPipe { Name = "RobustClientAssetGraphInput", Parallelize = true };
+ Input = new AssetPassPipe { Name = "RobustClientAssetGraphInput", Parallelize = parallel };
PresetPasses = new AssetPassPipe { Name = "RobustClientAssetGraphPresetPasses" };
Output = new AssetPassPipe { Name = "RobustClientAssetGraphOutput", CheckDuplicates = true };
NormalizeText = new AssetPassNormalizeText { Name = "RobustClientAssetGraphNormalizeText" };
diff --git a/Robust.Packaging/RobustClientPackaging.cs b/Robust.Packaging/RobustClientPackaging.cs
index 49a94534474..c23fe4479bb 100644
--- a/Robust.Packaging/RobustClientPackaging.cs
+++ b/Robust.Packaging/RobustClientPackaging.cs
@@ -4,9 +4,10 @@ namespace Robust.Packaging;
public sealed class RobustClientPackaging
{
- public static IReadOnlySet ClientIgnoresResources { get; } = new HashSet
+ public static IReadOnlySet ClientIgnoredResources { get; } = new HashSet
{
"Maps",
+ "ConfigPresets",
// Leaving this here for future archaeologists to ponder at.
"emotes.xml",
"Groups",
@@ -18,48 +19,8 @@ public static async Task WriteClientResources(
AssetPass pass,
CancellationToken cancel = default)
{
- var ignoreSet = ClientIgnoresResources.Union(RobustSharedPackaging.SharedIgnoredResources).ToHashSet();
+ var ignoreSet = ClientIgnoredResources.Union(RobustSharedPackaging.SharedIgnoredResources).ToHashSet();
- await RobustSharedPackaging.DoResourceCopy(Path.Combine(contentDir, "Resources"), pass, ignoreSet, cancel);
- }
-
- public static async Task WriteContentAssemblies(
- AssetPass pass,
- string contentDir,
- string binDir,
- IEnumerable contentAssemblies,
- CancellationToken cancel = default)
- {
- await WriteContentAssemblies("Assemblies", pass, contentDir, binDir, contentAssemblies, cancel);
- }
-
- public static Task WriteContentAssemblies(
- string target,
- AssetPass pass,
- string contentDir,
- string binDir,
- IEnumerable contentAssemblies,
- CancellationToken cancel = default)
- {
- var files = new List();
-
- var sourceDir = Path.Combine(contentDir, "bin", binDir);
-
- foreach (var asm in contentAssemblies)
- {
- files.Add($"{asm}.dll");
-
- var pdbPath = $"{asm}.pdb";
- if (File.Exists(Path.Combine(sourceDir, pdbPath)))
- files.Add(pdbPath);
- }
-
- foreach (var f in files)
- {
- cancel.ThrowIfCancellationRequested();
- pass.InjectFileFromDisk($"{target}/{f}", Path.Combine(sourceDir, f));
- }
-
- return Task.CompletedTask;
+ await RobustSharedPackaging.DoResourceCopy(Path.Combine(contentDir, "Resources"), pass, ignoreSet, cancel: cancel);
}
}
diff --git a/Robust.Packaging/RobustServerPackaging.cs b/Robust.Packaging/RobustServerPackaging.cs
new file mode 100644
index 00000000000..a53bad809b2
--- /dev/null
+++ b/Robust.Packaging/RobustServerPackaging.cs
@@ -0,0 +1,33 @@
+using Robust.Packaging.AssetProcessing;
+
+namespace Robust.Packaging;
+
+public sealed class RobustServerPackaging
+{
+ public static IReadOnlySet ServerIgnoresResources { get; } = new HashSet
+ {
+ "Audio",
+ "Textures",
+ "Fonts",
+ "Shaders",
+ };
+
+ public static async Task WriteServerResources(
+ string contentDir,
+ AssetPass pass,
+ CancellationToken cancel = default)
+ {
+ var ignoreSet = ServerIgnoresResources.Union(RobustSharedPackaging.SharedIgnoredResources).ToHashSet();
+
+ await RobustSharedPackaging.DoResourceCopy(Path.Combine(contentDir, "Resources"),
+ pass,
+ ignoreSet,
+ "Resources",
+ cancel);
+ await RobustSharedPackaging.DoResourceCopy(Path.Combine("RobustToolbox", "Resources"),
+ pass,
+ ignoreSet,
+ "Resources",
+ cancel);
+ }
+}
diff --git a/Robust.Packaging/RobustSharedPackaging.cs b/Robust.Packaging/RobustSharedPackaging.cs
index 6644ad5c7c1..a2a23bf7820 100644
--- a/Robust.Packaging/RobustSharedPackaging.cs
+++ b/Robust.Packaging/RobustSharedPackaging.cs
@@ -15,10 +15,53 @@ public sealed class RobustSharedPackaging
".DS_Store"
};
+ // IDK what these are supposed to correspond to but targetDir is the target directory.
+ public static async Task WriteContentAssemblies(
+ AssetPass pass,
+ string contentDir,
+ string binDir,
+ IEnumerable contentAssemblies,
+ string targetDir = "Assemblies",
+ CancellationToken cancel = default)
+ {
+ await WriteContentAssemblies(targetDir, pass, contentDir, binDir, contentAssemblies, cancel);
+ }
+
+ public static Task WriteContentAssemblies(
+ string target,
+ AssetPass pass,
+ string contentDir,
+ string binDir,
+ IEnumerable contentAssemblies,
+ CancellationToken cancel = default)
+ {
+ var files = new List();
+
+ var sourceDir = Path.Combine(contentDir, "bin", binDir);
+
+ foreach (var asm in contentAssemblies)
+ {
+ files.Add($"{asm}.dll");
+
+ var pdbPath = $"{asm}.pdb";
+ if (File.Exists(Path.Combine(sourceDir, pdbPath)))
+ files.Add(pdbPath);
+ }
+
+ foreach (var f in files)
+ {
+ cancel.ThrowIfCancellationRequested();
+ pass.InjectFileFromDisk($"{target}/{f}", Path.Combine(sourceDir, f));
+ }
+
+ return Task.CompletedTask;
+ }
+
public static Task DoResourceCopy(
string diskSource,
AssetPass pass,
IReadOnlySet ignoreSet,
+ string targetDir = "",
CancellationToken cancel = default)
{
foreach (var path in Directory.EnumerateFileSystemEntries(diskSource))
@@ -29,7 +72,7 @@ public static Task DoResourceCopy(
if (ignoreSet.Contains(filename))
continue;
- var targetPath = filename;
+ var targetPath = Path.Combine(targetDir, filename);
if (Directory.Exists(path))
CopyDirIntoZip(path, targetPath, pass);
else
@@ -44,11 +87,11 @@ private static void CopyDirIntoZip(string directory, string basePath, AssetPass
foreach (var file in Directory.EnumerateFiles(directory, "*.*", SearchOption.AllDirectories))
{
var relPath = Path.GetRelativePath(directory, file);
- if (Path.DirectorySeparatorChar != '/')
- relPath = relPath.Replace(Path.DirectorySeparatorChar, '/');
-
var zipPath = $"{basePath}/{relPath}";
+ if (Path.DirectorySeparatorChar != '/')
+ zipPath = zipPath.Replace(Path.DirectorySeparatorChar, '/');
+
// Console.WriteLine($"{directory}/{zipPath} -> /{zipPath}");
pass.InjectFileFromDisk(zipPath, file);
}
diff --git a/Robust.Server/Audio/AudioSystem.Effects.cs b/Robust.Server/Audio/AudioSystem.Effects.cs
deleted file mode 100644
index ea14d71164c..00000000000
--- a/Robust.Server/Audio/AudioSystem.Effects.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Components;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.Collections;
-using Robust.Shared.GameObjects;
-
-namespace Robust.Server.Audio;
-
-public sealed partial class AudioSystem
-{
- protected override void InitializeEffect()
- {
- base.InitializeEffect();
- SubscribeLocalEvent(OnEffectAdd);
- SubscribeLocalEvent(OnAuxiliaryAdd);
- }
-
- private void ShutdownEffect()
- {
- }
-
- ///
- /// Reloads all entities.
- ///
- public void ReloadPresets()
- {
- var query = AllEntityQuery();
- var toDelete = new ValueList();
-
- while (query.MoveNext(out var uid, out _))
- {
- toDelete.Add(uid);
- }
-
- foreach (var ent in toDelete)
- {
- Del(ent);
- }
-
- foreach (var proto in ProtoMan.EnumeratePrototypes())
- {
- if (!proto.CreateAuxiliary)
- continue;
-
- var effect = CreateEffect();
- var aux = CreateAuxiliary();
- SetEffectPreset(effect.Entity, effect.Component, proto);
- SetEffect(aux.Entity, aux.Component, effect.Entity);
- var preset = AddComp(aux.Entity);
- _auxiliaries.Remove(preset.Preset);
- preset.Preset = proto.ID;
- _auxiliaries[preset.Preset] = aux.Entity;
- }
- }
-
- private void OnEffectAdd(EntityUid uid, AudioEffectComponent component, ComponentAdd args)
- {
- component.Effect = new DummyAudioEffect();
- }
-
- private void OnAuxiliaryAdd(EntityUid uid, AudioAuxiliaryComponent component, ComponentAdd args)
- {
- component.Auxiliary = new DummyAuxiliaryAudio();
- }
-
- public override (EntityUid Entity, AudioAuxiliaryComponent Component) CreateAuxiliary()
- {
- var (ent, comp) = base.CreateAuxiliary();
- _pvs.AddGlobalOverride(GetNetEntity(ent));
- return (ent, comp);
- }
-
- public override (EntityUid Entity, AudioEffectComponent Component) CreateEffect()
- {
- var (ent, comp) = base.CreateEffect();
- _pvs.AddGlobalOverride(GetNetEntity(ent));
- return (ent, comp);
- }
-}
diff --git a/Robust.Server/Audio/AudioSystem.cs b/Robust.Server/Audio/AudioSystem.cs
deleted file mode 100644
index b7604667d89..00000000000
--- a/Robust.Server/Audio/AudioSystem.cs
+++ /dev/null
@@ -1,193 +0,0 @@
-using System.Collections.Generic;
-using System.Numerics;
-using Robust.Server.GameObjects;
-using Robust.Server.GameStates;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Components;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-using Robust.Shared.Map;
-using Robust.Shared.Player;
-using Robust.Shared.Utility;
-
-namespace Robust.Server.Audio;
-
-public sealed partial class AudioSystem : SharedAudioSystem
-{
- [Dependency] private readonly PvsOverrideSystem _pvs = default!;
-
- public override void Initialize()
- {
- base.Initialize();
- SubscribeLocalEvent(OnAudioStartup);
- }
-
- public override void Shutdown()
- {
- base.Shutdown();
- ShutdownEffect();
- }
-
- private void OnAudioStartup(EntityUid uid, AudioComponent component, ComponentStartup args)
- {
- component.Source = new DummyAudioSource();
- }
-
- private void AddAudioFilter(EntityUid uid, AudioComponent component, Filter filter)
- {
- var count = filter.Count;
-
- if (count == 0)
- return;
-
- var nent = GetNetEntity(uid);
- _pvs.AddSessionOverrides(nent, filter);
-
- var ents = new HashSet(count);
-
- foreach (var session in filter.Recipients)
- {
- var ent = session.AttachedEntity;
-
- if (ent == null)
- continue;
-
- ents.Add(ent.Value);
- }
-
- DebugTools.Assert(component.IncludedEntities == null);
- component.IncludedEntities = ents;
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string filename, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null)
- {
- var entity = Spawn("Audio", MapCoordinates.Nullspace);
- var audio = SetupAudio(entity, filename, audioParams);
- AddAudioFilter(entity, audio, playerFilter);
-
- return (entity, audio);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string filename, Filter playerFilter, EntityUid uid, bool recordReplay, AudioParams? audioParams = null)
- {
- if (!Exists(uid))
- return null;
-
- var entity = Spawn("Audio", new EntityCoordinates(uid, Vector2.Zero));
- var audio = SetupAudio(entity, filename, audioParams);
- AddAudioFilter(entity, audio, playerFilter);
-
- return (entity, audio);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayPvs(string filename, EntityUid uid, AudioParams? audioParams = null)
- {
- if (!Exists(uid))
- return null;
-
- var entity = Spawn("Audio", new EntityCoordinates(uid, Vector2.Zero));
- var audio = SetupAudio(entity, filename, audioParams);
-
- return (entity, audio);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string filename, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null)
- {
- if (!coordinates.IsValid(EntityManager))
- return null;
-
- var entity = Spawn("Audio", coordinates);
- var audio = SetupAudio(entity, filename, audioParams);
- AddAudioFilter(entity, audio, playerFilter);
-
- return (entity, audio);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayPvs(string filename, EntityCoordinates coordinates,
- AudioParams? audioParams = null)
- {
- if (!coordinates.IsValid(EntityManager))
- return null;
-
- var entity = Spawn("Audio", coordinates);
- var audio = SetupAudio(entity, filename, audioParams);
-
- return (entity, audio);
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(SoundSpecifier? sound, EntityUid source, EntityUid? user, AudioParams? audioParams = null)
- {
- if (sound == null)
- return null;
-
- var audio = PlayPvs(GetSound(sound), source, audioParams ?? sound.Params);
-
- if (audio == null)
- return null;
-
- audio.Value.Component.ExcludedEntity = user;
- return audio;
- }
-
- ///
- public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(SoundSpecifier? sound, EntityCoordinates coordinates, EntityUid? user, AudioParams? audioParams = null)
- {
- if (sound == null)
- return null;
-
- var audio = PlayPvs(GetSound(sound), coordinates, audioParams ?? sound.Params);
-
- if (audio == null)
- return null;
-
- audio.Value.Component.ExcludedEntity = user;
- return audio;
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string filename, ICommonSession recipient, AudioParams? audioParams = null)
- {
- return PlayGlobal(filename, Filter.SinglePlayer(recipient), false, audioParams);
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string filename, EntityUid recipient, AudioParams? audioParams = null)
- {
- if (TryComp(recipient, out ActorComponent? actor))
- return PlayGlobal(filename, actor.PlayerSession, audioParams);
-
- return null;
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string filename, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
- {
- return PlayEntity(filename, Filter.SinglePlayer(recipient), uid, false, audioParams);
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string filename, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
- {
- if (TryComp(recipient, out ActorComponent? actor))
- return PlayEntity(filename, actor.PlayerSession, uid, audioParams);
-
- return null;
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string filename, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- return PlayStatic(filename, Filter.SinglePlayer(recipient), coordinates, false, audioParams);
- }
-
- public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string filename, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- if (TryComp(recipient, out ActorComponent? actor))
- return PlayStatic(filename, actor.PlayerSession, coordinates, audioParams);
-
- return null;
- }
-}
diff --git a/Robust.Server/BaseServer.cs b/Robust.Server/BaseServer.cs
index aa2268f0389..e4d4a0f5462 100644
--- a/Robust.Server/BaseServer.cs
+++ b/Robust.Server/BaseServer.cs
@@ -660,10 +660,14 @@ public void Cleanup()
{
// Write down exception log
var logPath = _config.GetCVar(CVars.LogPath);
- var relPath = PathHelpers.ExecutableRelativeFile(logPath);
- Directory.CreateDirectory(relPath);
- var pathToWrite = Path.Combine(relPath,
+ if (!Path.IsPathRooted(logPath))
+ {
+ logPath = PathHelpers.ExecutableRelativeFile(logPath);
+ }
+
+ var pathToWrite = Path.Combine(logPath,
"Runtime-" + DateTime.Now.ToString("yyyy-MM-dd-THH-mm-ss") + ".txt");
+ Directory.CreateDirectory(logPath);
File.WriteAllText(pathToWrite, _runtimeLog.Display(), EncodingHelpers.UTF8);
}
diff --git a/Robust.Server/GameObjects/EntitySystems/ActorSystem.cs b/Robust.Server/GameObjects/EntitySystems/ActorSystem.cs
deleted file mode 100644
index 4b5584d8098..00000000000
--- a/Robust.Server/GameObjects/EntitySystems/ActorSystem.cs
+++ /dev/null
@@ -1,189 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using JetBrains.Annotations;
-using Robust.Server.Player;
-using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-using Robust.Shared.Network;
-using Robust.Shared.Player;
-using Robust.Shared.Utility;
-
-namespace Robust.Server.GameObjects
-{
- ///
- /// System that handles players being attached/detached from entities.
- ///
- [UsedImplicitly]
- public sealed class ActorSystem : EntitySystem
- {
- [Dependency] private readonly IPlayerManager _playerManager = default!;
-
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeLocalEvent(OnActorShutdown);
- }
-
- ///
- /// Attaches a player session to an entity, optionally kicking any sessions already attached to it.
- ///
- /// The entity to attach the player to
- /// The player to attach to the entity
- /// Whether to kick any existing players from the entity
- /// Whether the attach succeeded, or not.
- public bool Attach(EntityUid? uid, ICommonSession player, bool force = false)
- {
- return Attach(uid, player, false, out _);
- }
-
- ///
- /// Attaches a player session to an entity, optionally kicking any sessions already attached to it.
- ///
- /// The entity to attach the player to
- /// The player to attach to the entity
- /// Whether to kick any existing players from the entity
- /// The player that was forcefully kicked, or null.
- /// Whether the attach succeeded, or not.
- public bool Attach(EntityUid? entity, ICommonSession player, bool force, out ICommonSession? forceKicked)
- {
- // Null by default.
- forceKicked = null;
-
- if (player.AttachedEntity == entity)
- {
- DebugTools.Assert(entity == null || HasComp(entity));
- return true;
- }
-
- if (entity is not { } uid)
- return Detach(player);
-
- // Cannot attach to a deleted, nonexisting or terminating entity.
- if (TerminatingOrDeleted(uid))
- return false;
-
- // Check if there was a player attached to the entity already...
- if (TryComp(uid, out ActorComponent? actor))
- {
- // If we're not forcing the attach, this fails.
- if (!force)
- return false;
-
- // Set the event's force-kicked session before detaching it.
- forceKicked = actor.PlayerSession;
- RemComp(uid, actor);
- DebugTools.AssertNull(forceKicked.AttachedEntity);
- }
-
- // Detach from the currently attached entity.
- Detach(player);
-
- // We add the actor component.
- actor = EntityManager.AddComponent(uid);
- EntityManager.EnsureComponent(uid);
- actor.PlayerSession = player;
- _playerManager.SetAttachedEntity(player, uid);
- DebugTools.Assert(player.AttachedEntity == entity);
-
- // The player is fully attached now, raise an event!
- RaiseLocalEvent(uid, new PlayerAttachedEvent(uid, player, forceKicked), true);
- return true;
- }
-
- ///
- /// Detaches an attached session from the entity, if any.
- ///
- /// The entity player sessions will be detached from.
- /// Whether any player session was detached.
- public bool Detach(EntityUid uid, ActorComponent? actor = null)
- {
- if (!Resolve(uid, ref actor, false))
- return false;
-
- RemComp(uid, actor);
- return true;
- }
-
- ///
- /// Detaches this player from its attached entity, if any.
- ///
- /// The player session that will be detached from any attached entities.
- /// Whether the player is now detached from any entities.
- /// This returns true if the player wasn't attached to any entity.
- public bool Detach(ICommonSession player, ActorComponent? actor = null)
- {
- var uid = player.AttachedEntity;
- if (uid == null)
- return true;
-
- if (!Resolve(uid.Value, ref actor, false))
- {
- Log.Error($"Player {player} was attached to a deleted entity?");
- ((CommonSession) player).AttachedEntity = null;
- return true;
- }
-
- RemComp(uid.Value, actor);
- DebugTools.AssertNull(player.AttachedEntity);
- return false;
- }
-
- private void OnActorShutdown(EntityUid entity, ActorComponent component, ComponentShutdown args)
- {
- _playerManager.SetAttachedEntity(component.PlayerSession, null);
-
- // The player is fully detached now that the component has shut down.
- RaiseLocalEvent(entity, new PlayerDetachedEvent(entity, component.PlayerSession), true);
- }
-
- public bool TryGetActorFromUserId(NetUserId? userId, [NotNullWhen(true)] out ICommonSession? actor, out EntityUid? actorEntity)
- {
- actor = null;
- actorEntity = null;
- if (userId != null)
- {
- if (!_playerManager.TryGetSessionById(userId.Value, out actor))
- return false;
- actorEntity = actor.AttachedEntity;
- }
-
- return actor != null;
- }
- }
-
- ///
- /// Event for when a player has been attached to an entity.
- ///
- public sealed class PlayerAttachedEvent : EntityEventArgs
- {
- public EntityUid Entity { get; }
- public ICommonSession Player { get; }
-
- ///
- /// The player session that was forcefully kicked from the entity, if any.
- ///
- public ICommonSession? Kicked { get; }
-
- public PlayerAttachedEvent(EntityUid entity, ICommonSession player, ICommonSession? kicked = null)
- {
- Entity = entity;
- Player = player;
- Kicked = kicked;
- }
- }
-
- ///
- /// Event for when a player has been detached from an entity.
- ///
- public sealed class PlayerDetachedEvent : EntityEventArgs
- {
- public EntityUid Entity { get; }
- public ICommonSession Player { get; }
-
- public PlayerDetachedEvent(EntityUid entity, ICommonSession player)
- {
- Entity = entity;
- Player = player;
- }
- }
-}
diff --git a/Robust.Server/GameObjects/EntitySystems/AudioSystem.cs b/Robust.Server/GameObjects/EntitySystems/AudioSystem.cs
new file mode 100644
index 00000000000..c917fc1e569
--- /dev/null
+++ b/Robust.Server/GameObjects/EntitySystems/AudioSystem.cs
@@ -0,0 +1,176 @@
+using System.Collections.Generic;
+using System.Linq;
+using JetBrains.Annotations;
+using Robust.Shared.Audio;
+using Robust.Shared.GameObjects;
+using Robust.Shared.IoC;
+using Robust.Shared.Map;
+using Robust.Shared.Player;
+
+namespace Robust.Server.GameObjects;
+[UsedImplicitly]
+public sealed class AudioSystem : SharedAudioSystem
+{
+ [Dependency] private readonly TransformSystem _transform = default!;
+
+
+ private uint _streamIndex;
+
+ private sealed class AudioSourceServer : IPlayingAudioStream
+ {
+ private readonly uint _id;
+ private readonly AudioSystem _audioSystem;
+ private readonly IEnumerable? _sessions;
+
+ internal AudioSourceServer(AudioSystem parent, uint identifier, IEnumerable? sessions = null)
+ {
+ _audioSystem = parent;
+ _id = identifier;
+ _sessions = sessions;
+ }
+ public void Stop()
+ {
+ _audioSystem.InternalStop(_id, _sessions);
+ }
+ }
+
+ private void InternalStop(uint id, IEnumerable? sessions = null)
+ {
+ var msg = new StopAudioMessageClient
+ {
+ Identifier = id
+ };
+
+ if (sessions == null)
+ RaiseNetworkEvent(msg);
+ else
+ {
+ foreach (var session in sessions)
+ {
+ RaiseNetworkEvent(msg, session.ConnectedClient);
+ }
+ }
+ }
+
+ private uint CacheIdentifier()
+ {
+ return unchecked(_streamIndex++);
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayGlobal(string filename, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null)
+ {
+ var id = CacheIdentifier();
+ var msg = new PlayAudioGlobalMessage
+ {
+ FileName = filename,
+ AudioParams = audioParams ?? AudioParams.Default,
+ Identifier = id
+ };
+
+ RaiseNetworkEvent(msg, playerFilter, recordReplay);
+
+ return new AudioSourceServer(this, id, playerFilter.Recipients.ToArray());
+ }
+
+ public override IPlayingAudioStream? Play(string filename, Filter playerFilter, EntityUid uid, bool recordReplay, AudioParams? audioParams = null)
+ {
+ if(!EntityManager.TryGetComponent(uid, out var transform))
+ return null;
+
+ var id = CacheIdentifier();
+
+ var fallbackCoordinates = GetFallbackCoordinates(transform.MapPosition);
+
+ var msg = new PlayAudioEntityMessage
+ {
+ FileName = filename,
+ Coordinates = GetNetCoordinates(transform.Coordinates),
+ FallbackCoordinates = GetNetCoordinates(fallbackCoordinates),
+ NetEntity = GetNetEntity(uid),
+ AudioParams = audioParams ?? AudioParams.Default,
+ Identifier = id,
+ };
+
+ RaiseNetworkEvent(msg, playerFilter, recordReplay);
+
+ return new AudioSourceServer(this, id, playerFilter.Recipients.ToArray());
+ }
+
+ ///
+ public override IPlayingAudioStream? Play(string filename, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null)
+ {
+ var id = CacheIdentifier();
+
+ var fallbackCoordinates = GetFallbackCoordinates(coordinates.ToMap(EntityManager, _transform));
+
+ var msg = new PlayAudioPositionalMessage
+ {
+ FileName = filename,
+ Coordinates = GetNetCoordinates(coordinates),
+ FallbackCoordinates = GetNetCoordinates(fallbackCoordinates),
+ AudioParams = audioParams ?? AudioParams.Default,
+ Identifier = id
+ };
+
+ RaiseNetworkEvent(msg, playerFilter, recordReplay);
+
+ return new AudioSourceServer(this, id, playerFilter.Recipients.ToArray());
+ }
+
+ ///
+ public override IPlayingAudioStream? PlayPredicted(SoundSpecifier? sound, EntityUid source, EntityUid? user, AudioParams? audioParams = null)
+ {
+ if (sound == null)
+ return null;
+
+ var filter = Filter.Pvs(source, entityManager: EntityManager, playerManager: PlayerManager, cfgManager: CfgManager).RemoveWhereAttachedEntity(e => e == user);
+ return Play(sound, filter, source, true, audioParams);
+ }
+
+ public override IPlayingAudioStream? PlayPredicted(SoundSpecifier? sound, EntityCoordinates coordinates, EntityUid? user,
+ AudioParams? audioParams = null)
+ {
+ if (sound == null)
+ return null;
+
+ var filter = Filter.Pvs(coordinates, entityMan: EntityManager, playerMan: PlayerManager).RemoveWhereAttachedEntity(e => e == user);
+ return Play(sound, filter, coordinates, true, audioParams);
+ }
+
+ public override IPlayingAudioStream? PlayGlobal(string filename, ICommonSession recipient, AudioParams? audioParams = null)
+ {
+ return PlayGlobal(filename, Filter.SinglePlayer(recipient), false, audioParams);
+ }
+
+ public override IPlayingAudioStream? PlayGlobal(string filename, EntityUid recipient, AudioParams? audioParams = null)
+ {
+ if (TryComp(recipient, out ActorComponent? actor))
+ return PlayGlobal(filename, actor.PlayerSession, audioParams);
+ return null;
+ }
+
+ public override IPlayingAudioStream? PlayEntity(string filename, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
+ {
+ return Play(filename, Filter.SinglePlayer(recipient), uid, false, audioParams);
+ }
+
+ public override IPlayingAudioStream? PlayEntity(string filename, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
+ {
+ if (TryComp(recipient, out ActorComponent? actor))
+ return PlayEntity(filename, actor.PlayerSession, uid, audioParams);
+ return null;
+ }
+
+ public override IPlayingAudioStream? PlayStatic(string filename, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
+ {
+ return Play(filename, Filter.SinglePlayer(recipient), coordinates, false, audioParams);
+ }
+
+ public override IPlayingAudioStream? PlayStatic(string filename, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
+ {
+ if (TryComp(recipient, out ActorComponent? actor))
+ return PlayStatic(filename, actor.PlayerSession, coordinates, audioParams);
+ return null;
+ }
+}
diff --git a/Robust.Server/GameObjects/EntitySystems/EyeSystem.cs b/Robust.Server/GameObjects/EntitySystems/EyeSystem.cs
index f9d19c48910..4f9e01d659d 100644
--- a/Robust.Server/GameObjects/EntitySystems/EyeSystem.cs
+++ b/Robust.Server/GameObjects/EntitySystems/EyeSystem.cs
@@ -1,5 +1,4 @@
using Robust.Shared.GameObjects;
-using Robust.Shared.GameStates;
namespace Robust.Server.GameObjects;
diff --git a/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs b/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs
index a17af19a693..6c3f40dd694 100644
--- a/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs
+++ b/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs
@@ -296,6 +296,9 @@ private bool Deserialize(MapData data)
ReadGrids(data);
+ // grids prior to engine v175 might've been serialized with empty chunks which now throw debug asserts.
+ RemoveEmptyChunks(data);
+
// Then, go hierarchically in order and do the entity things.
StartupEntities(data);
@@ -311,6 +314,25 @@ private bool Deserialize(MapData data)
return true;
}
+ private void RemoveEmptyChunks(MapData data)
+ {
+ var gridQuery = _serverEntityManager.GetEntityQuery();
+ foreach (var uid in data.EntitiesToDeserialize.Keys)
+ {
+ if (!gridQuery.TryGetComponent(uid, out var gridComp))
+ continue;
+
+ foreach (var (index, chunk) in gridComp.Chunks)
+ {
+ if (chunk.FilledTiles > 0)
+ continue;
+
+ Log.Warning($"Encountered empty chunk while deserializing map. Grid: {ToPrettyString(uid)}. Chunk index: {index}");
+ gridComp.Chunks.Remove(index);
+ }
+ }
+ }
+
private bool VerifyEntitiesExist(MapData data, BeforeEntityReadEvent ev)
{
_stopwatch.Restart();
diff --git a/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs b/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs
index 9eea4f661ac..91b7eb995b0 100644
--- a/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs
+++ b/Robust.Server/GameObjects/EntitySystems/ServerMetaDataSystem.cs
@@ -1,6 +1,7 @@
using Robust.Server.GameStates;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
+using Robust.Shared.Player;
namespace Robust.Server.GameObjects;
diff --git a/Robust.Server/GameObjects/EntitySystems/UserInterfaceSystem.cs b/Robust.Server/GameObjects/EntitySystems/UserInterfaceSystem.cs
index 6d96e6df350..2861d7301ff 100644
--- a/Robust.Server/GameObjects/EntitySystems/UserInterfaceSystem.cs
+++ b/Robust.Server/GameObjects/EntitySystems/UserInterfaceSystem.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using JetBrains.Annotations;
using Robust.Server.Player;
@@ -21,8 +20,6 @@ public sealed class UserInterfaceSystem : SharedUserInterfaceSystem
private readonly List _sessionCache = new();
- private readonly Dictionary> _openInterfaces = new();
-
///
public override void Initialize()
{
@@ -46,7 +43,7 @@ private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs args)
if (args.NewStatus != SessionStatus.Disconnected)
return;
- if (!_openInterfaces.TryGetValue(args.Session, out var buis))
+ if (!OpenInterfaces.TryGetValue(args.Session, out var buis))
return;
foreach (var bui in buis.ToArray())
@@ -92,7 +89,7 @@ public override void Update(float frameTime)
///
/// Verify that the subscribed clients are still in range of the interface.
///
- private void CheckRange(EntityUid uid, Shared.GameObjects.ActiveUserInterfaceComponent activeUis, PlayerBoundUserInterface ui, TransformComponent transform, EntityQuery query)
+ private void CheckRange(EntityUid uid, ActiveUserInterfaceComponent activeUis, PlayerBoundUserInterface ui, TransformComponent transform, EntityQuery query)
{
if (ui.InteractionRange <= 0)
return;
@@ -139,11 +136,6 @@ private void CheckRange(EntityUid uid, Shared.GameObjects.ActiveUserInterfaceCom
}
}
- private void ActivateInterface(PlayerBoundUserInterface ui)
- {
- EnsureComp(ui.Owner).Interfaces.Add(ui);
- }
-
#region Get BUI
public bool HasUi(EntityUid uid, Enum uiKey, UserInterfaceComponent? ui = null)
@@ -168,20 +160,14 @@ public PlayerBoundUserInterface GetUi(EntityUid uid, Enum uiKey, UserInterfaceCo
? bui
: null;
}
- public bool TryGetUi(EntityUid uid, Enum uiKey, [NotNullWhen(true)] out PlayerBoundUserInterface? bui, UserInterfaceComponent? ui = null)
- {
- bui = null;
-
- return Resolve(uid, ref ui, false) && ui.Interfaces.TryGetValue(uiKey, out bui);
- }
///
/// Return UIs a session has open.
/// Null if empty.
- ///
+ ///
public List? GetAllUIsForSession(ICommonSession session)
{
- _openInterfaces.TryGetValue(session, out var value);
+ OpenInterfaces.TryGetValue(session, out var value);
return value;
}
#endregion
@@ -259,94 +245,14 @@ public void SetUiState(PlayerBoundUserInterface bui, BoundUserInterfaceState sta
bui.StateDirty = true;
}
- ///
- /// Switches between closed and open for a specific client.
- ///
- public bool TryToggleUi(EntityUid uid, Enum uiKey, ICommonSession session, UserInterfaceComponent? ui = null)
- {
- if (!TryGetUi(uid, uiKey, out var bui, ui))
- return false;
-
- ToggleUi(bui, session);
- return true;
- }
-
- ///
- /// Switches between closed and open for a specific client.
- ///
- public void ToggleUi(PlayerBoundUserInterface bui, ICommonSession session)
- {
- if (bui._subscribedSessions.Contains(session))
- CloseUi(bui, session);
- else
- OpenUi(bui, session);
- }
-
- #region Open
-
- public bool TryOpen(EntityUid uid, Enum uiKey, ICommonSession session, UserInterfaceComponent? ui = null)
- {
- if (!TryGetUi(uid, uiKey, out var bui, ui))
- return false;
-
- return OpenUi(bui, session);
- }
-
- ///
- /// Opens this interface for a specific client.
- ///
- public bool OpenUi(PlayerBoundUserInterface bui, ICommonSession session)
- {
- if (session.Status == SessionStatus.Connecting || session.Status == SessionStatus.Disconnected)
- return false;
-
- if (!bui._subscribedSessions.Add(session))
- return false;
-
- _openInterfaces.GetOrNew(session).Add(bui);
- RaiseLocalEvent(bui.Owner, new BoundUIOpenedEvent(bui.UiKey, bui.Owner, session));
-
- RaiseNetworkEvent(new BoundUIWrapMessage(GetNetEntity(bui.Owner), new OpenBoundInterfaceMessage(), bui.UiKey), session.ConnectedClient);
-
- // Fun fact, clients needs to have BUIs open before they can receive the state.....
- if (bui.LastStateMsg != null)
- RaiseNetworkEvent(bui.LastStateMsg, session.ConnectedClient);
-
- ActivateInterface(bui);
- return true;
- }
-
- #endregion
-
#region Close
- public bool TryClose(EntityUid uid, Enum uiKey, ICommonSession session, UserInterfaceComponent? ui = null)
- {
- if (!TryGetUi(uid, uiKey, out var bui, ui))
- return false;
-
- return CloseUi(bui, session);
- }
-
- ///
- /// Close this interface for a specific client.
- ///
- public bool CloseUi(PlayerBoundUserInterface bui, ICommonSession session, ActiveUserInterfaceComponent? activeUis = null)
- {
- if (!bui._subscribedSessions.Remove(session))
- return false;
-
- RaiseNetworkEvent(new BoundUIWrapMessage(GetNetEntity(bui.Owner), new CloseBoundInterfaceMessage(), bui.UiKey), session.ConnectedClient);
- CloseShared(bui, session, activeUis);
- return true;
- }
-
protected override void CloseShared(PlayerBoundUserInterface bui, ICommonSession session, ActiveUserInterfaceComponent? activeUis = null)
{
var owner = bui.Owner;
bui._subscribedSessions.Remove(session);
bui.PlayerStateOverrides.Remove(session);
- if (_openInterfaces.TryGetValue(session, out var buis))
+ if (OpenInterfaces.TryGetValue(session, out var buis))
buis.Remove(bui);
RaiseLocalEvent(owner, new BoundUIClosedEvent(bui.UiKey, owner, session));
diff --git a/Robust.Server/GameStates/PvsOverrideSystem.cs b/Robust.Server/GameStates/PvsOverrideSystem.cs
index ddef2110ce0..bd022a688a3 100644
--- a/Robust.Server/GameStates/PvsOverrideSystem.cs
+++ b/Robust.Server/GameStates/PvsOverrideSystem.cs
@@ -16,38 +16,30 @@ public sealed class PvsOverrideSystem : EntitySystem
///
/// Whether or not to supersede existing overrides.
/// If true, this will also recursively send any children of the given index.
- public void AddGlobalOverride(NetEntity entity, bool removeExistingOverride = true, bool recursive = false)
+ public void AddGlobalOverride(EntityUid uid, bool removeExistingOverride = true, bool recursive = false)
{
- _pvs.EntityPVSCollection.AddGlobalOverride(entity, removeExistingOverride, recursive);
+ _pvs.EntityPVSCollection.AddGlobalOverride(GetNetEntity(uid), removeExistingOverride, recursive);
}
///
- /// Used to ensure that an entity is always sent to a specific client. Overrides any global or pre-existing
- /// client-specific overrides.
+ /// Used to ensure that an entity is always sent to a specific client. By default this overrides any global or pre-existing
+ /// client-specific overrides. Unlike global overrides, this is always recursive.
///
/// Whether or not to supersede existing overrides.
- public void AddSessionOverride(NetEntity entity, ICommonSession session, bool removeExistingOverride = true)
- {
- _pvs.EntityPVSCollection.AddSessionOverride(entity, session, removeExistingOverride);
- }
-
- // 'placeholder'
- public void AddSessionOverrides(NetEntity entity, Filter filter, bool removeExistingOverride = true)
+ /// If true, this will also recursively send any children of the given index.
+ public void AddSessionOverride(EntityUid uid, ICommonSession session, bool removeExistingOverride = true)
{
- foreach (var player in filter.Recipients)
- {
- AddSessionOverride(entity, player, removeExistingOverride);
- }
+ _pvs.EntityPVSCollection.AddSessionOverride(GetNetEntity(uid), session, removeExistingOverride);
}
///
/// Removes any global or client-specific overrides.
///
- public void ClearOverride(NetEntity entity, TransformComponent? xform = null)
+ public void ClearOverride(EntityUid uid, TransformComponent? xform = null)
{
- if (!TryGetEntity(entity, out var uid) || !Resolve(uid.Value, ref xform))
+ if (!Resolve(uid, ref xform))
return;
- _pvs.EntityPVSCollection.UpdateIndex(entity, xform.Coordinates, true);
+ _pvs.EntityPVSCollection.UpdateIndex(GetNetEntity(uid), xform.Coordinates, true);
}
}
diff --git a/Robust.Server/GameStates/PvsSystem.cs b/Robust.Server/GameStates/PvsSystem.cs
index 186f792d73c..a70d164588f 100644
--- a/Robust.Server/GameStates/PvsSystem.cs
+++ b/Robust.Server/GameStates/PvsSystem.cs
@@ -888,7 +888,7 @@ private void AddToChunkSetRecursively(in EntityUid uid, in NetEntity netEntity,
return null;
var tick = _gameTiming.CurTick;
- var minSize = Math.Max(0, lastSent.Count - lastSent.Count);
+ var minSize = Math.Max(0, lastSent.Count - visibleEnts.Count);
var leftView = new List(minSize);
foreach (var netEntity in lastSent.Keys)
diff --git a/Robust.Server/GameStates/ServerGameStateManager.cs b/Robust.Server/GameStates/ServerGameStateManager.cs
index 2c67cb5dce3..1f1db6a3ce3 100644
--- a/Robust.Server/GameStates/ServerGameStateManager.cs
+++ b/Robust.Server/GameStates/ServerGameStateManager.cs
@@ -378,15 +378,10 @@ private void SendStateUpdate(int i,
if (_gameTiming.CurTick.Value > lastAck.Value + _pvs.ForceAckThreshold)
{
stateUpdateMessage.ForceSendReliably = true;
-
- // Aside from the time shortly after connecting, this shouldn't be common. If it is happening.
- // something is probably wrong (or we have a malicious client). Hence we log an error.
- // If it is more frequent than I think, this can be downgraded to a warning.
-
#if FULL_RELEASE
var connectedTime = (DateTime.UtcNow - session.ConnectedTime).TotalMinutes;
if (lastAck > GameTick.Zero && connectedTime > 1)
- _logger.Error($"Client {session} exceeded ack-tick threshold. Last ack: {lastAck}. Cur tick: {_gameTiming.CurTick}. Connect time: {connectedTime} minutes");
+ _logger.Warning($"Client {session} exceeded ack-tick threshold. Last ack: {lastAck}. Cur tick: {_gameTiming.CurTick}. Connect time: {connectedTime} minutes");
#endif
}
diff --git a/Robust.Server/Graphics/ClydeHandle.cs b/Robust.Server/Graphics/ClydeHandle.cs
deleted file mode 100644
index 313867fa34d..00000000000
--- a/Robust.Server/Graphics/ClydeHandle.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using Robust.Shared.Graphics;
-
-namespace Robust.Server.Graphics;
-
-public struct ClydeHandle : IClydeHandle
-{
- public long Value => -1;
-}
diff --git a/Robust.Server/Maps/MapChunkSerializer.cs b/Robust.Server/Maps/MapChunkSerializer.cs
index dff28e56130..d06e45679b5 100644
--- a/Robust.Server/Maps/MapChunkSerializer.cs
+++ b/Robust.Server/Maps/MapChunkSerializer.cs
@@ -12,6 +12,7 @@
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Serialization.Markdown.Value;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
+using Robust.Shared.Utility;
namespace Robust.Server.Maps;
@@ -93,6 +94,7 @@ public DataNode Write(ISerializationManager serializationManager, MapChunk value
IDependencyCollection dependencies, bool alwaysWrite = false,
ISerializationContext? context = null)
{
+ DebugTools.Assert(value.FilledTiles > 0, "Attempting to write an empty chunk");
var root = new MappingDataNode();
var ind = new ValueDataNode($"{value.X},{value.Y}");
root.Add("ind", ind);
diff --git a/Robust.Server/Placement/PlacementManager.cs b/Robust.Server/Placement/PlacementManager.cs
index b9a0fc4fb4e..ec68bc9dd99 100644
--- a/Robust.Server/Placement/PlacementManager.cs
+++ b/Robust.Server/Placement/PlacementManager.cs
@@ -31,6 +31,10 @@ public sealed class PlacementManager : IPlacementManager
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly ILogManager _logManager = default!;
+ private EntityLookupSystem _lookup => _entityManager.System();
+ private SharedMapSystem _maps => _entityManager.System();
+ private SharedTransformSystem _xformSystem => _entityManager.System();
+
//TO-DO: Expand for multiple permission per mob?
// Add support for multi-use placeables (tiles etc.).
public List BuildPermissions { get; set; } = new();
@@ -45,6 +49,7 @@ public sealed class PlacementManager : IPlacementManager
public void Initialize()
{
+ // Someday PlacementManagerSystem my beloved.
_sawmill = _logManager.GetSawmill("placement");
_networkManager.RegisterNetMessage(HandleNetMessage);
@@ -143,7 +148,7 @@ public void HandlePlacementRequest(MsgPlacement msg)
if (_entityManager.TryGetComponent(gridUid, out var grid))
{
var replacementQuery = _entityManager.GetEntityQuery();
- var anc = grid.GetAnchoredEntitiesEnumerator(grid.LocalToTile(coordinates));
+ var anc = _maps.GetAnchoredEntitiesEnumerator(gridUid.Value, grid, _maps.LocalToTile(gridUid.Value, grid, coordinates));
var toDelete = new ValueList();
while (anc.MoveNext(out var ent))
@@ -186,14 +191,11 @@ private void PlaceNewTile(int tileType, EntityCoordinates coordinates, NetUserId
MapGridComponent? grid;
- _mapManager.TryGetGrid(coordinates.EntityId, out grid);
-
- if (grid == null)
- _mapManager.TryFindGridAt(coordinates.ToMap(_entityManager), out _, out grid);
-
- if (grid != null) // stick to existing grid
+ EntityUid gridId = coordinates.EntityId;
+ if (_entityManager.TryGetComponent(coordinates.EntityId, out grid)
+ || _mapManager.TryFindGridAt(coordinates.ToMap(_entityManager, _xformSystem), out gridId, out grid))
{
- grid.SetTile(coordinates, new Tile(tileType));
+ _maps.SetTile(gridId, grid, coordinates, new Tile(tileType));
var placementEraseEvent = new PlacementTileEvent(tileType, coordinates, placingUserId);
_entityManager.EventBus.RaiseEvent(EventSource.Local, placementEraseEvent);
@@ -202,9 +204,9 @@ private void PlaceNewTile(int tileType, EntityCoordinates coordinates, NetUserId
{
var newGrid = _mapManager.CreateGridEntity(coordinates.GetMapId(_entityManager));
var newGridXform = _entityManager.GetComponent(newGrid);
- newGridXform.WorldPosition = coordinates.Position - newGrid.Comp.TileSizeHalfVector; // assume bottom left tile origin
+ _xformSystem.SetWorldPosition(newGridXform, coordinates.Position - newGrid.Comp.TileSizeHalfVector); // assume bottom left tile origin
var tilePos = newGrid.Comp.WorldToTile(coordinates.Position);
- newGrid.Comp.SetTile(tilePos, new Tile(tileType));
+ _maps.SetTile(newGrid.Owner, newGrid.Comp, tilePos, new Tile(tileType));
var placementEraseEvent = new PlacementTileEvent(tileType, coordinates, placingUserId);
_entityManager.EventBus.RaiseEvent(EventSource.Local, placementEraseEvent);
@@ -228,11 +230,16 @@ private void HandleRectRemoveReq(MsgPlacement msg)
{
EntityCoordinates start = _entityManager.GetCoordinates(msg.NetCoordinates);
Vector2 rectSize = msg.RectSize;
- foreach (EntityUid entity in EntitySystem.Get().GetEntitiesIntersecting(start.GetMapId(_entityManager),
+ foreach (var entity in _lookup.GetEntitiesIntersecting(start.GetMapId(_entityManager),
new Box2(start.Position, start.Position + rectSize)))
{
- if (_entityManager.Deleted(entity) || _entityManager.HasComponent(entity) || _entityManager.HasComponent(entity))
+ if (_entityManager.Deleted(entity) ||
+ _entityManager.HasComponent(entity) ||
+ _entityManager.HasComponent(entity))
+ {
continue;
+ }
+
var placementEraseEvent = new PlacementEntityEvent(entity, _entityManager.GetComponent(entity).Coordinates, PlacementEventAction.Erase, msg.MsgChannel.UserId);
_entityManager.EventBus.RaiseEvent(EventSource.Local, placementEraseEvent);
_entityManager.DeleteEntity(entity);
@@ -247,16 +254,16 @@ public void SendPlacementBegin(EntityUid mob, int range, string objectType, stri
if (!_entityManager.TryGetComponent(mob, out ActorComponent? actor))
return;
- var playerConnection = actor.PlayerSession.ConnectedClient;
- if (playerConnection == null)
- return;
+ var playerConnection = actor.PlayerSession.Channel;
- var message = new MsgPlacement();
- message.PlaceType = PlacementManagerMessage.StartPlacement;
- message.Range = range;
- message.IsTile = false;
- message.ObjType = objectType;
- message.AlignOption = alignOption;
+ var message = new MsgPlacement
+ {
+ PlaceType = PlacementManagerMessage.StartPlacement,
+ Range = range,
+ IsTile = false,
+ ObjType = objectType,
+ AlignOption = alignOption
+ };
_networkManager.ServerSendMessage(message, playerConnection);
}
@@ -268,16 +275,16 @@ public void SendPlacementBeginTile(EntityUid mob, int range, string tileType, st
if (!_entityManager.TryGetComponent(mob, out ActorComponent? actor))
return;
- var playerConnection = actor.PlayerSession.ConnectedClient;
- if (playerConnection == null)
- return;
+ var playerConnection = actor.PlayerSession.Channel;
- var message = new MsgPlacement();
- message.PlaceType = PlacementManagerMessage.StartPlacement;
- message.Range = range;
- message.IsTile = true;
- message.ObjType = tileType;
- message.AlignOption = alignOption;
+ var message = new MsgPlacement
+ {
+ PlaceType = PlacementManagerMessage.StartPlacement,
+ Range = range,
+ IsTile = true,
+ ObjType = tileType,
+ AlignOption = alignOption
+ };
_networkManager.ServerSendMessage(message, playerConnection);
}
@@ -289,12 +296,12 @@ public void SendPlacementCancel(EntityUid mob)
if (!_entityManager.TryGetComponent(mob, out ActorComponent? actor))
return;
- var playerConnection = actor.PlayerSession.ConnectedClient;
- if (playerConnection == null)
- return;
+ var playerConnection = actor.PlayerSession.Channel;
- var message = new MsgPlacement();
- message.PlaceType = PlacementManagerMessage.CancelPlacement;
+ var message = new MsgPlacement
+ {
+ PlaceType = PlacementManagerMessage.CancelPlacement
+ };
_networkManager.ServerSendMessage(message, playerConnection);
}
diff --git a/Robust.Server/Player/PlayerManager.cs b/Robust.Server/Player/PlayerManager.cs
index 4407d364285..61f562691e5 100644
--- a/Robust.Server/Player/PlayerManager.cs
+++ b/Robust.Server/Player/PlayerManager.cs
@@ -80,9 +80,7 @@ private Task OnConnecting(NetConnectingArgs args)
///
private void NewSession(object? sender, NetChannelArgs args)
{
- var session = CreateAndAddSession(args.Channel.UserId, args.Channel.UserName);
- session.Channel = args.Channel;
-
+ CreateAndAddSession(args.Channel);
PlayerCountMetric.Set(PlayerCount);
// Synchronize base time.
var msgTimeBase = new MsgSyncTimeBase();
@@ -106,8 +104,7 @@ private void EndSession(object? sender, NetChannelArgs args)
DebugTools.Assert(session.Channel == args.Channel);
SetStatus(session, SessionStatus.Disconnected);
- if (session.AttachedEntity != null)
- EntManager.System().Detach(session.AttachedEntity.Value);
+ SetAttachedEntity(session, null, out _, true);
var viewSys = EntManager.System();
foreach (var eye in session.ViewSubscriptions.ToArray())
diff --git a/Robust.Server/ServerIoC.cs b/Robust.Server/ServerIoC.cs
index feffc05b46c..8d9ca24fc86 100644
--- a/Robust.Server/ServerIoC.cs
+++ b/Robust.Server/ServerIoC.cs
@@ -15,7 +15,6 @@
using Robust.Server.Upload;
using Robust.Server.ViewVariables;
using Robust.Shared;
-using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
@@ -27,7 +26,6 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Replays;
-using Robust.Shared.ResourceManagement;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
using Robust.Shared.Upload;
@@ -66,7 +64,6 @@ internal static void RegisterIoC(IDependencyCollection deps)
deps.Register();
deps.Register();
deps.Register();
- deps.Register();
deps.Register();
deps.Register();
deps.Register();
@@ -95,7 +92,6 @@ internal static void RegisterIoC(IDependencyCollection deps)
deps.Register();
deps.Register();
deps.Register();
- deps.Register();
}
}
}
diff --git a/Robust.Server/ServerStatus/DefaultMagicAczProvider.cs b/Robust.Server/ServerStatus/DefaultMagicAczProvider.cs
index 87b266aa8db..8d3e6545e78 100644
--- a/Robust.Server/ServerStatus/DefaultMagicAczProvider.cs
+++ b/Robust.Server/ServerStatus/DefaultMagicAczProvider.cs
@@ -34,12 +34,12 @@ public async Task Package(
var inputPass = graph.Input;
var contentDir = FindContentRootPath(_deps);
- await RobustClientPackaging.WriteContentAssemblies(
+ await RobustSharedPackaging.WriteContentAssemblies(
inputPass,
contentDir,
binFolderPath,
assemblyNames,
- cancel);
+ cancel: cancel);
await RobustClientPackaging.WriteClientResources(contentDir, inputPass, cancel);
diff --git a/Robust.Shared.CompNetworkGenerator/ComponentNetworkGenerator.cs b/Robust.Shared.CompNetworkGenerator/ComponentNetworkGenerator.cs
index f51722c1d9a..71da4a70054 100644
--- a/Robust.Shared.CompNetworkGenerator/ComponentNetworkGenerator.cs
+++ b/Robust.Shared.CompNetworkGenerator/ComponentNetworkGenerator.cs
@@ -167,7 +167,7 @@ private static string GenerateSource(in GeneratorExecutionContext context, IName
getStateInit.Append($@"
{name} = GetNetEntitySet(component.{name}),");
handleStateSetters.Append($@"
- component.{name} = EnsureEntitySet<{componentName}>(state.{name}, uid);");
+ EnsureEntitySet<{componentName}>(state.{name}, uid, component.{name});");
break;
case GlobalEntityUidListName:
@@ -177,7 +177,7 @@ private static string GenerateSource(in GeneratorExecutionContext context, IName
getStateInit.Append($@"
{name} = GetNetEntityList(component.{name}),");
handleStateSetters.Append($@"
- component.{name} = EnsureEntityList<{componentName}>(state.{name}, uid);");
+ EnsureEntityList<{componentName}>(state.{name}, uid, component.{name});");
break;
default:
diff --git a/Robust.Shared.Maths/Box2.cs b/Robust.Shared.Maths/Box2.cs
index 4083bf24e94..a5124a6041b 100644
--- a/Robust.Shared.Maths/Box2.cs
+++ b/Robust.Shared.Maths/Box2.cs
@@ -87,8 +87,6 @@ public readonly Vector2 Extents
get => (TopRight - BottomLeft) * 0.5f;
}
- public static Box2 Empty = new Box2();
-
///
/// A 1x1 unit box with the origin centered.
///
diff --git a/Robust.Shared/Audio/AudioParams.cs b/Robust.Shared/Audio/AudioParams.cs
index a8db8910cc3..47d9a541319 100644
--- a/Robust.Shared/Audio/AudioParams.cs
+++ b/Robust.Shared/Audio/AudioParams.cs
@@ -1,7 +1,6 @@
using Robust.Shared.Serialization;
using System;
using System.Diagnostics.Contracts;
-using Robust.Shared.Audio.Systems;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.GameObjects;
@@ -12,7 +11,10 @@ public enum Attenuation : int
{
// https://hackage.haskell.org/package/OpenAL-1.7.0.5/docs/Sound-OpenAL-AL-Attenuation.html
- Invalid = 0,
+ ///
+ /// Default to the overall attenuation. If set project-wide will use InverseDistanceClamped. This is what you typically want for an audio source.
+ ///
+ Default = 0,
NoAttenuation = 1 << 0,
InverseDistance = 1 << 1,
InverseDistanceClamped = 1 << 2,
@@ -32,56 +34,54 @@ public partial struct AudioParams
///
/// The DistanceModel to use for this specific source.
///
- [DataField]
- public Attenuation Attenuation { get; set; } = Attenuation.LinearDistanceClamped;
+ [DataField("attenuation")]
+ public Attenuation Attenuation { get; set; } = Default.Attenuation;
///
/// Base volume to play the audio at, in dB.
///
- [DataField]
+ [DataField("volume")]
public float Volume { get; set; } = Default.Volume;
///
/// Scale for the audio pitch.
///
- [DataField]
- public float Pitch { get; set; } = Default.Pitch;
+ [DataField("pitchscale")]
+ public float PitchScale { get; set; } = Default.PitchScale;
///
/// Audio bus to play on.
///
- [DataField]
+ [DataField("busname")]
public string BusName { get; set; } = Default.BusName;
///
/// Only applies to positional audio.
/// The maximum distance from which the audio is hearable.
///
- [DataField]
+ [DataField("maxdistance")]
public float MaxDistance { get; set; } = Default.MaxDistance;
///
/// Used for distance attenuation calculations. Set to 0f to make a sound exempt from distance attenuation.
///
- [DataField]
+ [DataField("rolloffFactor")]
public float RolloffFactor { get; set; } = Default.RolloffFactor;
///
/// Equivalent of the minimum distance to use for an audio source.
///
- [DataField]
+ [DataField("referenceDistance")]
public float ReferenceDistance { get; set; } = Default.ReferenceDistance;
- [DataField]
- public bool Loop { get; set; } = Default.Loop;
+ [DataField("loop")] public bool Loop { get; set; } = Default.Loop;
- [DataField]
- public float PlayOffsetSeconds { get; set; } = Default.PlayOffsetSeconds;
+ [DataField("playoffset")] public float PlayOffsetSeconds { get; set; } = Default.PlayOffsetSeconds;
///
/// If not null, this will randomly modify the pitch scale by adding a number drawn from a normal distribution with this deviation.
///
- [DataField]
+ [DataField("variation")]
public float? Variation { get; set; } = null;
// For the max distance value: it's 2000 in Godot, but I assume that's PIXELS due to the 2D positioning,
@@ -96,21 +96,21 @@ public AudioParams() { }
public AudioParams(
float volume,
- float pitch,
+ float pitchScale,
string busName,
float maxDistance,
float refDistance,
bool loop,
float playOffsetSeconds,
float? variation = null)
- : this(volume, pitch, busName, maxDistance, 1, refDistance, loop, playOffsetSeconds, variation)
+ : this(volume, pitchScale, busName, maxDistance, 1, refDistance, loop, playOffsetSeconds, variation)
{
}
- public AudioParams(float volume, float pitch, string busName, float maxDistance,float rolloffFactor, float refDistance, bool loop, float playOffsetSeconds, float? variation = null) : this()
+ public AudioParams(float volume, float pitchScale, string busName, float maxDistance,float rolloffFactor, float refDistance, bool loop, float playOffsetSeconds, float? variation = null) : this()
{
Volume = volume;
- Pitch = pitch;
+ PitchScale = pitchScale;
BusName = busName;
MaxDistance = maxDistance;
RolloffFactor = rolloffFactor;
@@ -163,7 +163,7 @@ public readonly AudioParams WithVariation(float? variation)
public readonly AudioParams WithPitchScale(float pitch)
{
var me = this;
- me.Pitch = pitch;
+ me.PitchScale = pitch;
return me;
}
diff --git a/Robust.Shared/Audio/AudioPresetPrototype.cs b/Robust.Shared/Audio/AudioPresetPrototype.cs
deleted file mode 100644
index 9e5fe916d3c..00000000000
--- a/Robust.Shared/Audio/AudioPresetPrototype.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using Robust.Shared.Maths;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization.Manager.Attributes;
-
-namespace Robust.Shared.Audio;
-
-///
-/// Contains audio defaults to set for sounds.
-/// This can be used by to apply an audio preset.
-///
-[Prototype("audioPreset")]
-public sealed class AudioPresetPrototype : IPrototype
-{
- [IdDataField]
- public string ID { get; } = default!;
-
- ///
- /// Should the engine automatically create an auxiliary audio effect slot for this.
- ///
- [DataField]
- public bool CreateAuxiliary;
-
- [DataField]
- public float Density;
-
- [DataField]
- public float Diffusion;
-
- [DataField]
- public float Gain;
-
- [DataField("gainHf")]
- public float GainHF;
-
- [DataField("gainLf")]
- public float GainLF;
-
- [DataField]
- public float DecayTime;
-
- [DataField("decayHfRatio")]
- public float DecayHFRatio;
-
- [DataField("decayLfRatio")]
- public float DecayLFRatio;
-
- [DataField]
- public float ReflectionsGain;
-
- [DataField]
- public float ReflectionsDelay;
-
- [DataField]
- public Vector3 ReflectionsPan;
-
- [DataField]
- public float LateReverbGain;
-
- [DataField]
- public float LateReverbDelay;
-
- [DataField]
- public Vector3 LateReverbPan;
-
- [DataField]
- public float EchoTime;
-
- [DataField]
- public float EchoDepth;
-
- [DataField]
- public float ModulationTime;
-
- [DataField]
- public float ModulationDepth;
-
- [DataField("airAbsorptionGainHf")]
- public float AirAbsorptionGainHF;
-
- [DataField("hfReference")]
- public float HFReference;
-
- [DataField("lfReference")]
- public float LFReference;
-
- [DataField]
- public float RoomRolloffFactor;
-
- [DataField("decayHfLimit")]
- public int DecayHFLimit;
-}
diff --git a/Robust.Shared/Audio/Components/AudioAuxiliaryComponent.cs b/Robust.Shared/Audio/Components/AudioAuxiliaryComponent.cs
deleted file mode 100644
index a1648d655b5..00000000000
--- a/Robust.Shared/Audio/Components/AudioAuxiliaryComponent.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.GameObjects;
-using Robust.Shared.GameStates;
-using Robust.Shared.Serialization.Manager.Attributes;
-using Robust.Shared.ViewVariables;
-
-namespace Robust.Shared.Audio.Components;
-
-///
-/// Can have Audio passed to it to apply effects or filters.
-///
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(SharedAudioSystem))]
-public sealed partial class AudioAuxiliaryComponent : Component
-{
- ///
- /// Audio effect to attach to this auxiliary audio slot.
- ///
- [DataField, AutoNetworkedField]
- public EntityUid? Effect;
-
- [ViewVariables]
- internal IAuxiliaryAudio Auxiliary = new DummyAuxiliaryAudio();
-}
diff --git a/Robust.Shared/Audio/Components/AudioComponent.cs b/Robust.Shared/Audio/Components/AudioComponent.cs
deleted file mode 100644
index 76bb5b28f8c..00000000000
--- a/Robust.Shared/Audio/Components/AudioComponent.cs
+++ /dev/null
@@ -1,236 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.GameObjects;
-using Robust.Shared.GameStates;
-using Robust.Shared.Serialization.Manager.Attributes;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
-using Robust.Shared.ViewVariables;
-
-namespace Robust.Shared.Audio.Components;
-
-///
-/// Stores the audio data for an audio entity.
-///
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedAudioSystem))]
-public sealed partial class AudioComponent : Component, IAudioSource
-{
- #region Filter
-
- public override bool SessionSpecific => true;
-
- ///
- /// Used for synchronising audio on client that comes into PVS range.
- ///
- [DataField(customTypeSerializer:typeof(TimeOffsetSerializer)), AutoNetworkedField]
- public TimeSpan AudioStart;
-
- #region Filters
-
- // Don't need to network these as client doesn't care.
-
- ///
- /// If this sound was predicted do we exclude it from a specific entity.
- /// Useful for predicted audio.
- ///
- [DataField]
- public EntityUid? ExcludedEntity;
-
- ///
- /// If the sound was filtered what entities were included.
- ///
- [DataField]
- public HashSet? IncludedEntities;
-
- #endregion
-
- #endregion
-
- // We can't just start playing on audio creation as we don't have the correct position yet.
- // As such we'll wait for FrameUpdate before we start playing to avoid the position being cooked.
- public bool Started = false;
-
- [AutoNetworkedField]
- [DataField(required: true)]
- public string FileName = string.Empty;
-
- ///
- /// Audio params. Set this if you want to adjust default volume, max distance, etc.
- ///
- [AutoNetworkedField]
- [DataField]
- public AudioParams Params = AudioParams.Default;
-
- ///
- /// Audio source that interacts with OpenAL.
- ///
- [ViewVariables(VVAccess.ReadOnly)]
- internal IAudioSource Source = default!;
-
- ///
- /// Auxiliary entity to pass audio to.
- ///
- [DataField, AutoNetworkedField]
- public EntityUid? Auxiliary;
-
- /*
- * Values for IAudioSource stored on the component and sent to IAudioSource as applicable.
- * Most of these aren't networked as they double AudioParams data and these just interact with IAudioSource.
- */
-
- #region Source
-
- public void Pause() => Source.Pause();
-
- ///
- public void StartPlaying() => Source.StartPlaying();
-
- ///
- public void StopPlaying() => Source.StopPlaying();
-
- ///
- ///
- ///
- [ViewVariables]
- public bool Playing
- {
- get => Source.Playing;
- set => Source.Playing = value;
- }
-
- ///
- ///
- ///
- [ViewVariables]
- public bool Looping
- {
- get => Source.Looping;
- set => Source.Looping = value;
- }
-
- ///
- ///
- ///
- [AutoNetworkedField]
- public bool Global { get; set; }
-
- ///
- ///
- ///
- public float Pitch
- {
- get => Source.Pitch;
- set => Source.Pitch = value;
- }
-
- ///
- ///
- ///
- public float MaxDistance
- {
- get => Source.MaxDistance;
- set => Source.MaxDistance = value;
- }
-
- ///
- ///
- ///
- public float RolloffFactor
- {
- get => Source.RolloffFactor;
- set => Source.RolloffFactor = value;
- }
-
- ///
- ///
- ///
- public float ReferenceDistance
- {
- get => Source.ReferenceDistance;
- set => Source.ReferenceDistance = value;
- }
-
- ///
- ///
- ///
- ///
- /// Not replicated as audio always tracks the entity's position.
- ///
- [ViewVariables]
- public Vector2 Position
- {
- get => Source.Position;
- set => Source.Position = value;
- }
-
- ///
- ///
- ///
- [ViewVariables]
- [Access(Other = AccessPermissions.ReadWriteExecute)]
- public float Volume
- {
- get => Source.Volume;
- set => Source.Volume = value;
- }
-
- ///
- ///
- ///
- [ViewVariables]
- [Access(Other = AccessPermissions.ReadWriteExecute)]
- public float Gain
- {
- get => Source.Gain;
- set => Source.Gain = value;
- }
-
- ///
- ///
- ///
- [ViewVariables]
- [Access(Other = AccessPermissions.ReadWriteExecute)]
- public float Occlusion
- {
- get => Source.Occlusion;
- set => Source.Occlusion = value;
- }
-
- ///
- ///
- ///
- [ViewVariables]
- public float PlaybackPosition
- {
- get => Source.PlaybackPosition;
- set => Source.PlaybackPosition = value;
- }
-
- ///
- ///
- ///
- ///
- /// Not replicated.
- ///
- [ViewVariables]
- public Vector2 Velocity
- {
- get => Source.Velocity;
- set => Source.Velocity = value;
- }
-
- void IAudioSource.SetAuxiliary(IAuxiliaryAudio? audio)
- {
- Source.SetAuxiliary(audio);
- }
-
- #endregion
-
- public void Dispose()
- {
- Source.Dispose();
- }
-}
diff --git a/Robust.Shared/Audio/Components/AudioEffectComponent.cs b/Robust.Shared/Audio/Components/AudioEffectComponent.cs
deleted file mode 100644
index 4ce5bf716be..00000000000
--- a/Robust.Shared/Audio/Components/AudioEffectComponent.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-using System;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.GameObjects;
-using Robust.Shared.GameStates;
-using Robust.Shared.Maths;
-using Robust.Shared.Serialization.Manager.Attributes;
-using Robust.Shared.ViewVariables;
-
-namespace Robust.Shared.Audio.Components;
-
-///
-/// Stores OpenAL audio effect data that can be bound to an .
-///
-[RegisterComponent, NetworkedComponent, Access(typeof(SharedAudioSystem)), AutoGenerateComponentState]
-public sealed partial class AudioEffectComponent : Component, IAudioEffect
-{
- [ViewVariables]
- internal IAudioEffect Effect = new DummyAudioEffect();
-
- ///
- [DataField, AutoNetworkedField]
- public float Density
- {
- get => Effect.Density;
- set => Effect.Density = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float Diffusion
- {
- get => Effect.Diffusion;
- set => Effect.Diffusion = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float Gain
- {
- get => Effect.Gain;
- set => Effect.Gain = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float GainHF
- {
- get => Effect.GainHF;
- set => Effect.GainHF = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float GainLF
- {
- get => Effect.GainLF;
- set => Effect.GainLF = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float DecayTime
- {
- get => Effect.DecayTime;
- set => Effect.DecayTime = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float DecayHFRatio
- {
- get => Effect.DecayHFRatio;
- set => Effect.DecayHFRatio = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float DecayLFRatio
- {
- get => Effect.DecayLFRatio;
- set => Effect.DecayLFRatio = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float ReflectionsGain
- {
- get => Effect.ReflectionsGain;
- set => Effect.ReflectionsGain = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float ReflectionsDelay
- {
- get => Effect.ReflectionsDelay;
- set => Effect.ReflectionsDelay = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public Vector3 ReflectionsPan
- {
- get => Effect.ReflectionsPan;
- set => Effect.ReflectionsPan = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float LateReverbGain
- {
- get => Effect.LateReverbGain;
- set => Effect.LateReverbGain = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float LateReverbDelay
- {
- get => Effect.LateReverbDelay;
- set => Effect.LateReverbDelay = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public Vector3 LateReverbPan
- {
- get => Effect.LateReverbPan;
- set => Effect.LateReverbPan = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float EchoTime
- {
- get => Effect.EchoTime;
- set => Effect.EchoTime = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float EchoDepth
- {
- get => Effect.EchoDepth;
- set => Effect.EchoDepth = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float ModulationTime
- {
- get => Effect.ModulationTime;
- set => Effect.ModulationTime = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float ModulationDepth
- {
- get => Effect.ModulationDepth;
- set => Effect.ModulationDepth = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float AirAbsorptionGainHF
- {
- get => Effect.AirAbsorptionGainHF;
- set => Effect.AirAbsorptionGainHF = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float HFReference
- {
- get => Effect.HFReference;
- set => Effect.HFReference = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float LFReference
- {
- get => Effect.LFReference;
- set => Effect.LFReference = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public float RoomRolloffFactor
- {
- get => Effect.RoomRolloffFactor;
- set => Effect.RoomRolloffFactor = value;
- }
-
- ///
- [DataField, AutoNetworkedField]
- public int DecayHFLimit
- {
- get => Effect.DecayHFLimit;
- set => Effect.DecayHFLimit = value;
- }
-}
diff --git a/Robust.Shared/Audio/Components/AudioPresetComponent.cs b/Robust.Shared/Audio/Components/AudioPresetComponent.cs
deleted file mode 100644
index c9723ed6fdc..00000000000
--- a/Robust.Shared/Audio/Components/AudioPresetComponent.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.GameObjects;
-using Robust.Shared.GameStates;
-
-namespace Robust.Shared.Audio.Components;
-
-///
-/// Marks this entity as being spawned for audio presets in case we need to reload.
-///
-[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedAudioSystem))]
-public sealed partial class AudioPresetComponent : Component
-{
- [AutoNetworkedField]
- public string Preset = string.Empty;
-}
diff --git a/Robust.Shared/Audio/Effects/DummyAudioEffect.cs b/Robust.Shared/Audio/Effects/DummyAudioEffect.cs
deleted file mode 100644
index 1c90d3c3253..00000000000
--- a/Robust.Shared/Audio/Effects/DummyAudioEffect.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using Robust.Shared.Audio.Components;
-using Robust.Shared.Maths;
-
-namespace Robust.Shared.Audio.Effects;
-
-///
-internal sealed class DummyAudioEffect : IAudioEffect
-{
- public void Dispose()
- {
- }
-
- ///
- public float Density { get; set; }
-
- ///
- public float Diffusion { get; set; }
-
- ///
- public float Gain { get; set; }
-
- ///
- public float GainHF { get; set; }
-
- ///
- public float GainLF { get; set; }
-
- ///
- public float DecayTime { get; set; }
-
- ///
- public float DecayHFRatio { get; set; }
-
- ///
- public float DecayLFRatio { get; set; }
-
- ///
- public float ReflectionsGain { get; set; }
-
- ///
- public float ReflectionsDelay { get; set; }
-
- ///
- public Vector3 ReflectionsPan { get; set; }
-
- ///
- public float LateReverbGain { get; set; }
-
- ///
- public float LateReverbDelay { get; set; }
-
- ///
- public Vector3 LateReverbPan { get; set; }
-
- ///
- public float EchoTime { get; set; }
-
- ///
- public float EchoDepth { get; set; }
-
- ///
- public float ModulationTime { get; set; }
-
- ///
- public float ModulationDepth { get; set; }
-
- ///
- public float AirAbsorptionGainHF { get; set; }
-
- ///
- public float HFReference { get; set; }
-
- ///
- public float LFReference { get; set; }
-
- ///
- public float RoomRolloffFactor { get; set; }
-
- ///
- public int DecayHFLimit { get; set; }
-}
diff --git a/Robust.Shared/Audio/Effects/DummyAuxiliaryAudio.cs b/Robust.Shared/Audio/Effects/DummyAuxiliaryAudio.cs
deleted file mode 100644
index b685288cda7..00000000000
--- a/Robust.Shared/Audio/Effects/DummyAuxiliaryAudio.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Robust.Shared.Audio.Effects;
-
-///
-internal sealed class DummyAuxiliaryAudio : IAuxiliaryAudio
-{
- public void Dispose()
- {
- }
-
- ///
- public void SetEffect(IAudioEffect? effect)
- {
- }
-}
diff --git a/Robust.Shared/Audio/Effects/IAudioEffect.cs b/Robust.Shared/Audio/Effects/IAudioEffect.cs
deleted file mode 100644
index 59d8cc948f6..00000000000
--- a/Robust.Shared/Audio/Effects/IAudioEffect.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using System;
-using Robust.Shared.Maths;
-
-namespace Robust.Shared.Audio.Effects;
-
-internal interface IAudioEffect
-{
- ///
- /// Gets the preset value for .
- ///
- public float Density { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float Diffusion { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float Gain { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float GainHF { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float GainLF { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float DecayTime { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float DecayHFRatio { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float DecayLFRatio { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float ReflectionsGain { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float ReflectionsDelay { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public Vector3 ReflectionsPan { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float LateReverbGain { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float LateReverbDelay { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public Vector3 LateReverbPan { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float EchoTime { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float EchoDepth { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float ModulationTime { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float ModulationDepth { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float AirAbsorptionGainHF { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float HFReference { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float LFReference { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public float RoomRolloffFactor { get; set; }
-
- ///
- /// Gets the preset value for .
- ///
- public int DecayHFLimit { get; set; }
-}
diff --git a/Robust.Shared/Audio/Effects/IAuxiliaryAudio.cs b/Robust.Shared/Audio/Effects/IAuxiliaryAudio.cs
deleted file mode 100644
index 43e72a6ae40..00000000000
--- a/Robust.Shared/Audio/Effects/IAuxiliaryAudio.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-
-namespace Robust.Shared.Audio.Effects;
-
-internal interface IAuxiliaryAudio : IDisposable
-{
- ///
- /// Sets the audio effect for this auxiliary audio slot.
- ///
- void SetEffect(IAudioEffect? effect);
-}
diff --git a/Robust.Shared/Audio/Effects/ReverbPresets.cs b/Robust.Shared/Audio/Effects/ReverbPresets.cs
deleted file mode 100644
index c94eedb1f3b..00000000000
--- a/Robust.Shared/Audio/Effects/ReverbPresets.cs
+++ /dev/null
@@ -1,3435 +0,0 @@
-//
-// ReverbPresets.cs
-//
-// Copyright (C) 2019 OpenTK
-//
-// This software may be modified and distributed under the terms
-// of the MIT license. See the LICENSE file for details.
-//
-
-
-using Robust.Shared.Maths;
-
-namespace Robust.Shared.Audio.Effects;
-
-///
-/// A set of reverb presets that can be used with the extension.
-///
-public static class ReverbPresets
-{
- ///
- /// A reverb preset (approximating a generic location).
- ///
- public static readonly ReverbProperties Generic = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.8913f,
- 1.0000f,
- 1.4900f,
- 0.8300f,
- 1.0000f,
- 0.0500f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a padded cell).
- ///
- public static readonly ReverbProperties PaddedCell = new ReverbProperties
- (
- 0.1715f,
- 1.0000f,
- 0.3162f,
- 0.0010f,
- 1.0000f,
- 0.1700f,
- 0.1000f,
- 1.0000f,
- 0.2500f,
- 0.0010f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2691f,
- 0.0020f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a room).
- ///
- public static readonly ReverbProperties Room = new ReverbProperties
- (
- 0.4287f,
- 1.0000f,
- 0.3162f,
- 0.5929f,
- 1.0000f,
- 0.4000f,
- 0.8300f,
- 1.0000f,
- 0.1503f,
- 0.0020f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.0629f,
- 0.0030f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a bathroom).
- ///
- public static readonly ReverbProperties Bathroom = new ReverbProperties
- (
- 0.1715f,
- 1.0000f,
- 0.3162f,
- 0.2512f,
- 1.0000f,
- 1.4900f,
- 0.5400f,
- 1.0000f,
- 0.6531f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 3.2734f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a living room).
- ///
- public static readonly ReverbProperties LivingRoom = new ReverbProperties
- (
- 0.9766f,
- 1.0000f,
- 0.3162f,
- 0.0010f,
- 1.0000f,
- 0.5000f,
- 0.1000f,
- 1.0000f,
- 0.2051f,
- 0.0030f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2805f,
- 0.0040f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a stone room).
- ///
- public static readonly ReverbProperties StoneRoom = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.7079f,
- 1.0000f,
- 2.3100f,
- 0.6400f,
- 1.0000f,
- 0.4411f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1003f,
- 0.0170f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an auditorium).
- ///
- public static readonly ReverbProperties Auditorium = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.5781f,
- 1.0000f,
- 4.3200f,
- 0.5900f,
- 1.0000f,
- 0.4032f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7170f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a concert hall).
- ///
- public static readonly ReverbProperties ConcertHall = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.5623f,
- 1.0000f,
- 3.9200f,
- 0.7000f,
- 1.0000f,
- 0.2427f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.9977f,
- 0.0290f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a cave).
- ///
- public static readonly ReverbProperties Cave = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 1.0000f,
- 1.0000f,
- 2.9100f,
- 1.3000f,
- 1.0000f,
- 0.5000f,
- 0.0150f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7063f,
- 0.0220f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating an arena).
- ///
- public static readonly ReverbProperties Arena = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.4477f,
- 1.0000f,
- 7.2400f,
- 0.3300f,
- 1.0000f,
- 0.2612f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.0186f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hangar).
- ///
- public static readonly ReverbProperties Hangar = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.3162f,
- 1.0000f,
- 10.0500f,
- 0.2300f,
- 1.0000f,
- 0.5000f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2560f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a carpeted hallway).
- ///
- public static readonly ReverbProperties CarpetedHallway = new ReverbProperties
- (
- 0.4287f,
- 1.0000f,
- 0.3162f,
- 0.0100f,
- 1.0000f,
- 0.3000f,
- 0.1000f,
- 1.0000f,
- 0.1215f,
- 0.0020f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1531f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hallway).
- ///
- public static readonly ReverbProperties Hallway = new ReverbProperties
- (
- 0.3645f,
- 1.0000f,
- 0.3162f,
- 0.7079f,
- 1.0000f,
- 1.4900f,
- 0.5900f,
- 1.0000f,
- 0.2458f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.6615f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a stone corridor).
- ///
- public static readonly ReverbProperties StoneCorridor = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.7612f,
- 1.0000f,
- 2.7000f,
- 0.7900f,
- 1.0000f,
- 0.2472f,
- 0.0130f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.5758f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an alley).
- ///
- public static readonly ReverbProperties Alley = new ReverbProperties
- (
- 1.0000f,
- 0.3000f,
- 0.3162f,
- 0.7328f,
- 1.0000f,
- 1.4900f,
- 0.8600f,
- 1.0000f,
- 0.2500f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.9954f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1250f,
- 0.9500f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a forest).
- ///
- public static readonly ReverbProperties Forest = new ReverbProperties
- (
- 1.0000f,
- 0.3000f,
- 0.3162f,
- 0.0224f,
- 1.0000f,
- 1.4900f,
- 0.5400f,
- 1.0000f,
- 0.0525f,
- 0.1620f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7682f,
- 0.0880f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1250f,
- 1.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a city).
- ///
- public static readonly ReverbProperties City = new ReverbProperties
- (
- 1.0000f,
- 0.5000f,
- 0.3162f,
- 0.3981f,
- 1.0000f,
- 1.4900f,
- 0.6700f,
- 1.0000f,
- 0.0730f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1427f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a mountain).
- ///
- public static readonly ReverbProperties Mountains = new ReverbProperties
- (
- 1.0000f,
- 0.2700f,
- 0.3162f,
- 0.0562f,
- 1.0000f,
- 1.4900f,
- 0.2100f,
- 1.0000f,
- 0.0407f,
- 0.3000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1919f,
- 0.1000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 1.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a quarry).
- ///
- public static readonly ReverbProperties Quarry = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.3162f,
- 1.0000f,
- 1.4900f,
- 0.8300f,
- 1.0000f,
- 0.0000f,
- 0.0610f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.7783f,
- 0.0250f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1250f,
- 0.7000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a plain).
- ///
- public static readonly ReverbProperties Plain = new ReverbProperties
- (
- 1.0000f,
- 0.2100f,
- 0.3162f,
- 0.1000f,
- 1.0000f,
- 1.4900f,
- 0.5000f,
- 1.0000f,
- 0.0585f,
- 0.1790f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1089f,
- 0.1000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 1.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a parking lot).
- ///
- public static readonly ReverbProperties ParkingLot = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 1.0000f,
- 1.0000f,
- 1.6500f,
- 1.5000f,
- 1.0000f,
- 0.2082f,
- 0.0080f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2652f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a sewer pipe).
- ///
- public static readonly ReverbProperties Sewerpipe = new ReverbProperties
- (
- 0.3071f,
- 0.8000f,
- 0.3162f,
- 0.3162f,
- 1.0000f,
- 2.8100f,
- 0.1400f,
- 1.0000f,
- 1.6387f,
- 0.0140f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 3.2471f,
- 0.0210f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an underwater location).
- ///
- public static readonly ReverbProperties Underwater = new ReverbProperties
- (
- 0.3645f,
- 1.0000f,
- 0.3162f,
- 0.0100f,
- 1.0000f,
- 1.4900f,
- 0.1000f,
- 1.0000f,
- 0.5963f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 7.0795f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 1.1800f,
- 0.3480f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a drugged state).
- ///
- public static readonly ReverbProperties Drugged = new ReverbProperties
- (
- 0.4287f,
- 0.5000f,
- 0.3162f,
- 1.0000f,
- 1.0000f,
- 8.3900f,
- 1.3900f,
- 1.0000f,
- 0.8760f,
- 0.0020f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 3.1081f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 1.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a dizzy state).
- ///
- public static readonly ReverbProperties Dizzy = new ReverbProperties
- (
- 0.3645f,
- 0.6000f,
- 0.3162f,
- 0.6310f,
- 1.0000f,
- 17.2300f,
- 0.5600f,
- 1.0000f,
- 0.1392f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.4937f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 1.0000f,
- 0.8100f,
- 0.3100f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a psychotic state).
- ///
- public static readonly ReverbProperties Psychotic = new ReverbProperties
- (
- 0.0625f,
- 0.5000f,
- 0.3162f,
- 0.8404f,
- 1.0000f,
- 7.5600f,
- 0.9100f,
- 1.0000f,
- 0.4864f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 2.4378f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 4.0000f,
- 1.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- /* Castle Presets */
-
- ///
- /// A reverb preset (approximating a small room in a castle).
- ///
- public static readonly ReverbProperties CastleSmallRoom = new ReverbProperties
- (
- 1.0000f,
- 0.8900f,
- 0.3162f,
- 0.3981f,
- 0.1000f,
- 1.2200f,
- 0.8300f,
- 0.3100f,
- 0.8913f,
- 0.0220f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.9953f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1380f,
- 0.0800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a short passage in a castle).
- ///
- public static readonly ReverbProperties CastleShortPassage = new ReverbProperties
- (
- 1.0000f,
- 0.8900f,
- 0.3162f,
- 0.3162f,
- 0.1000f,
- 2.3200f,
- 0.8300f,
- 0.3100f,
- 0.8913f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0230f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1380f,
- 0.0800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a medium room in a castle).
- ///
- public static readonly ReverbProperties CastleMediumRoom = new ReverbProperties
- (
- 1.0000f,
- 0.9300f,
- 0.3162f,
- 0.2818f,
- 0.1000f,
- 2.0400f,
- 0.8300f,
- 0.4600f,
- 0.6310f,
- 0.0220f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.5849f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1550f,
- 0.0300f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a large room in a castle).
- ///
- public static readonly ReverbProperties CastleLargeRoom = new ReverbProperties
- (
- 1.0000f,
- 0.8200f,
- 0.3162f,
- 0.2818f,
- 0.1259f,
- 2.5300f,
- 0.8300f,
- 0.5000f,
- 0.4467f,
- 0.0340f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0160f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1850f,
- 0.0700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a long passage in a castle).
- ///
- public static readonly ReverbProperties CastleLongPassage = new ReverbProperties
- (
- 1.0000f,
- 0.8900f,
- 0.3162f,
- 0.3981f,
- 0.1000f,
- 3.4200f,
- 0.8300f,
- 0.3100f,
- 0.8913f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0230f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1380f,
- 0.0800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hall in a castle).
- ///
- public static readonly ReverbProperties CastleHall = new ReverbProperties
- (
- 1.0000f,
- 0.8100f,
- 0.3162f,
- 0.2818f,
- 0.1778f,
- 3.1400f,
- 0.7900f,
- 0.6200f,
- 0.1778f,
- 0.0560f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0240f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a cupboard in a castle).
- ///
- public static readonly ReverbProperties CastleCupboard = new ReverbProperties
- (
- 1.0000f,
- 0.8900f,
- 0.3162f,
- 0.2818f,
- 0.1000f,
- 0.6700f,
- 0.8700f,
- 0.3100f,
- 1.4125f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 3.5481f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1380f,
- 0.0800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a castle courtyard).
- ///
- public static readonly ReverbProperties CastleCourtyard = new ReverbProperties
- (
- 1.0000f,
- 0.4200f,
- 0.3162f,
- 0.4467f,
- 0.1995f,
- 2.1300f,
- 0.6100f,
- 0.2300f,
- 0.2239f,
- 0.1600f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7079f,
- 0.0360f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.3700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating an alcove in a castle).
- ///
- public static readonly ReverbProperties CastleAlcove = new ReverbProperties
- (
- 1.0000f,
- 0.8900f,
- 0.3162f,
- 0.5012f,
- 0.1000f,
- 1.6400f,
- 0.8700f,
- 0.3100f,
- 1.0000f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0340f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1380f,
- 0.0800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5168.6001f,
- 139.5000f,
- 0.0000f,
- 0x1
- );
-
- /* Factory Presets */
-
- ///
- /// A reverb preset (approximating a small room in a factory).
- ///
- public static readonly ReverbProperties FactorySmallRoom = new ReverbProperties
- (
- 0.3645f,
- 0.8200f,
- 0.3162f,
- 0.7943f,
- 0.5012f,
- 1.7200f,
- 0.6500f,
- 1.3100f,
- 0.7079f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.7783f,
- 0.0240f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1190f,
- 0.0700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a short passage in a factory).
- ///
- public static readonly ReverbProperties FactoryShortPassage = new ReverbProperties
- (
- 0.3645f,
- 0.6400f,
- 0.2512f,
- 0.7943f,
- 0.5012f,
- 2.5300f,
- 0.6500f,
- 1.3100f,
- 1.0000f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0380f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1350f,
- 0.2300f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a medium room in a factory).
- ///
- public static readonly ReverbProperties FactoryMediumRoom = new ReverbProperties
- (
- 0.4287f,
- 0.8200f,
- 0.2512f,
- 0.7943f,
- 0.5012f,
- 2.7600f,
- 0.6500f,
- 1.3100f,
- 0.2818f,
- 0.0220f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0230f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1740f,
- 0.0700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a large room in a factory).
- ///
- public static readonly ReverbProperties FactoryLargeRoom = new ReverbProperties
- (
- 0.4287f,
- 0.7500f,
- 0.2512f,
- 0.7079f,
- 0.6310f,
- 4.2400f,
- 0.5100f,
- 1.3100f,
- 0.1778f,
- 0.0390f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0230f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2310f,
- 0.0700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a long passage in a factory).
- ///
- public static readonly ReverbProperties FactoryLongPassage = new ReverbProperties
- (
- 0.3645f,
- 0.6400f,
- 0.2512f,
- 0.7943f,
- 0.5012f,
- 4.0600f,
- 0.6500f,
- 1.3100f,
- 1.0000f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0370f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1350f,
- 0.2300f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hall in a factory).
- ///
- public static readonly ReverbProperties FactoryHall = new ReverbProperties
- (
- 0.4287f,
- 0.7500f,
- 0.3162f,
- 0.7079f,
- 0.6310f,
- 7.4300f,
- 0.5100f,
- 1.3100f,
- 0.0631f,
- 0.0730f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.8913f,
- 0.0270f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a cupboard in a factory).
- ///
- public static readonly ReverbProperties FactoryCupboard = new ReverbProperties
- (
- 0.3071f,
- 0.6300f,
- 0.2512f,
- 0.7943f,
- 0.5012f,
- 0.4900f,
- 0.6500f,
- 1.3100f,
- 1.2589f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.9953f,
- 0.0320f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1070f,
- 0.0700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a factory courtyard).
- ///
- public static readonly ReverbProperties FactoryCourtyard = new ReverbProperties
- (
- 0.3071f,
- 0.5700f,
- 0.3162f,
- 0.3162f,
- 0.6310f,
- 2.3200f,
- 0.2900f,
- 0.5600f,
- 0.2239f,
- 0.1400f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.3981f,
- 0.0390f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.2900f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an alcove in a factory).
- ///
- public static readonly ReverbProperties FactoryAlcove = new ReverbProperties
- (
- 0.3645f,
- 0.5900f,
- 0.2512f,
- 0.7943f,
- 0.5012f,
- 3.1400f,
- 0.6500f,
- 1.3100f,
- 1.4125f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.0000f,
- 0.0380f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1140f,
- 0.1000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3762.6001f,
- 362.5000f,
- 0.0000f,
- 0x1
- );
-
- /* Ice Palace Presets */
-
- ///
- /// A reverb preset (approximating a small room in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceSmallRoom = new ReverbProperties
- (
- 1.0000f,
- 0.8400f,
- 0.3162f,
- 0.5623f,
- 0.2818f,
- 1.5100f,
- 1.5300f,
- 0.2700f,
- 0.8913f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1640f,
- 0.1400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a short passage in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceShortPassage = new ReverbProperties
- (
- 1.0000f,
- 0.7500f,
- 0.3162f,
- 0.5623f,
- 0.2818f,
- 1.7900f,
- 1.4600f,
- 0.2800f,
- 0.5012f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0190f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1770f,
- 0.0900f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a medium room in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceMediumRoom = new ReverbProperties
- (
- 1.0000f,
- 0.8700f,
- 0.3162f,
- 0.5623f,
- 0.4467f,
- 2.2200f,
- 1.5300f,
- 0.3200f,
- 0.3981f,
- 0.0390f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0270f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1860f,
- 0.1200f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a large room in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceLargeRoom = new ReverbProperties
- (
- 1.0000f,
- 0.8100f,
- 0.3162f,
- 0.5623f,
- 0.4467f,
- 3.1400f,
- 1.5300f,
- 0.3200f,
- 0.2512f,
- 0.0390f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.0000f,
- 0.0270f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2140f,
- 0.1100f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a long passage in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceLongPassage = new ReverbProperties
- (
- 1.0000f,
- 0.7700f,
- 0.3162f,
- 0.5623f,
- 0.3981f,
- 3.0100f,
- 1.4600f,
- 0.2800f,
- 0.7943f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0250f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1860f,
- 0.0400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hall in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceHall = new ReverbProperties
- (
- 1.0000f,
- 0.7600f,
- 0.3162f,
- 0.4467f,
- 0.5623f,
- 5.4900f,
- 1.5300f,
- 0.3800f,
- 0.1122f,
- 0.0540f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.6310f,
- 0.0520f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2260f,
- 0.1100f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a cupboard in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceCupboard = new ReverbProperties
- (
- 1.0000f,
- 0.8300f,
- 0.3162f,
- 0.5012f,
- 0.2239f,
- 0.7600f,
- 1.5300f,
- 0.2600f,
- 1.1220f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.9953f,
- 0.0160f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1430f,
- 0.0800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an ice palace courtyard).
- ///
- public static readonly ReverbProperties IcePalaceCourtyard = new ReverbProperties
- (
- 1.0000f,
- 0.5900f,
- 0.3162f,
- 0.2818f,
- 0.3162f,
- 2.0400f,
- 1.2000f,
- 0.3800f,
- 0.3162f,
- 0.1730f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.3162f,
- 0.0430f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2350f,
- 0.4800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an alcove in an ice palace).
- ///
- public static readonly ReverbProperties IcePalaceAlcove = new ReverbProperties
- (
- 1.0000f,
- 0.8400f,
- 0.3162f,
- 0.5623f,
- 0.2818f,
- 2.7600f,
- 1.4600f,
- 0.2800f,
- 1.1220f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.8913f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1610f,
- 0.0900f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 12428.5000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- /* Space Station Presets */
-
- ///
- /// A reverb preset (approximating a small room in a space station).
- ///
- public static readonly ReverbProperties SpaceStationSmallRoom = new ReverbProperties
- (
- 0.2109f,
- 0.7000f,
- 0.3162f,
- 0.7079f,
- 0.8913f,
- 1.7200f,
- 0.8200f,
- 0.5500f,
- 0.7943f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0130f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1880f,
- 0.2600f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a short passage in a space station).
- ///
- public static readonly ReverbProperties SpaceStationShortPassage = new ReverbProperties
- (
- 0.2109f,
- 0.8700f,
- 0.3162f,
- 0.6310f,
- 0.8913f,
- 3.5700f,
- 0.5000f,
- 0.5500f,
- 1.0000f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0160f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1720f,
- 0.2000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a medium room in a space station).
- ///
- public static readonly ReverbProperties SpaceStationMediumRoom = new ReverbProperties
- (
- 0.2109f,
- 0.7500f,
- 0.3162f,
- 0.6310f,
- 0.8913f,
- 3.0100f,
- 0.5000f,
- 0.5500f,
- 0.3981f,
- 0.0340f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0350f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2090f,
- 0.3100f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a large room in a space station).
- ///
- public static readonly ReverbProperties SpaceStationLargeRoom = new ReverbProperties
- (
- 0.3645f,
- 0.8100f,
- 0.3162f,
- 0.6310f,
- 0.8913f,
- 3.8900f,
- 0.3800f,
- 0.6100f,
- 0.3162f,
- 0.0560f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.8913f,
- 0.0350f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2330f,
- 0.2800f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a long passage in a space station).
- ///
- public static readonly ReverbProperties SpaceStationLongPassage = new ReverbProperties
- (
- 0.4287f,
- 0.8200f,
- 0.3162f,
- 0.6310f,
- 0.8913f,
- 4.6200f,
- 0.6200f,
- 0.5500f,
- 1.0000f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0310f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.2300f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hall in a space station).
- ///
- public static readonly ReverbProperties SpaceStationHall = new ReverbProperties
- (
- 0.4287f,
- 0.8700f,
- 0.3162f,
- 0.6310f,
- 0.8913f,
- 7.1100f,
- 0.3800f,
- 0.6100f,
- 0.1778f,
- 0.1000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.6310f,
- 0.0470f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.2500f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a cupboard in a space station).
- ///
- public static readonly ReverbProperties SpaceStationCupboard = new ReverbProperties
- (
- 0.1715f,
- 0.5600f,
- 0.3162f,
- 0.7079f,
- 0.8913f,
- 0.7900f,
- 0.8100f,
- 0.5500f,
- 1.4125f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.7783f,
- 0.0180f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1810f,
- 0.3100f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an alcove in a space station).
- ///
- public static readonly ReverbProperties SpaceStationAlcove = new ReverbProperties
- (
- 0.2109f,
- 0.7800f,
- 0.3162f,
- 0.7079f,
- 0.8913f,
- 1.1600f,
- 0.8100f,
- 0.5500f,
- 1.4125f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.0000f,
- 0.0180f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1920f,
- 0.2100f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 3316.1001f,
- 458.2000f,
- 0.0000f,
- 0x1
- );
-
- /* Wooden Galleon Presets */
-
- ///
- /// A reverb preset (approximating a small room in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonSmallRoom = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.1122f,
- 0.3162f,
- 0.7900f,
- 0.3200f,
- 0.8700f,
- 1.0000f,
- 0.0320f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.8913f,
- 0.0290f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a short passage in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonShortPassage = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.1259f,
- 0.3162f,
- 1.7500f,
- 0.5000f,
- 0.8700f,
- 0.8913f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.6310f,
- 0.0240f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a medium room in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonMediumRoom = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.1000f,
- 0.2818f,
- 1.4700f,
- 0.4200f,
- 0.8200f,
- 0.8913f,
- 0.0490f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.8913f,
- 0.0290f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a large room in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonLargeRoom = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.0891f,
- 0.2818f,
- 2.6500f,
- 0.3300f,
- 0.8200f,
- 0.8913f,
- 0.0660f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7943f,
- 0.0490f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a long passsage in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonLongPassage = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.1000f,
- 0.3162f,
- 1.9900f,
- 0.4000f,
- 0.7900f,
- 1.0000f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.4467f,
- 0.0360f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hall in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonHall = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.0794f,
- 0.2818f,
- 3.4500f,
- 0.3000f,
- 0.8200f,
- 0.8913f,
- 0.0880f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7943f,
- 0.0630f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a cupboard in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonCupboard = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.1413f,
- 0.3162f,
- 0.5600f,
- 0.4600f,
- 0.9100f,
- 1.1220f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0280f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a courtyard on a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonCourtyard = new ReverbProperties
- (
- 1.0000f,
- 0.6500f,
- 0.3162f,
- 0.0794f,
- 0.3162f,
- 1.7900f,
- 0.3500f,
- 0.7900f,
- 0.5623f,
- 0.1230f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1000f,
- 0.0320f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an alcove in a wooden galleon).
- ///
- public static readonly ReverbProperties WoodenGalleonAlcove = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.1259f,
- 0.3162f,
- 1.2200f,
- 0.6200f,
- 0.9100f,
- 1.1220f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7079f,
- 0.0240f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4705.0000f,
- 99.6000f,
- 0.0000f,
- 0x1
- );
-
- /* Sports Presets */
-
- ///
- /// A reverb preset (approximating an empty sports stadium).
- ///
- public static readonly ReverbProperties SportEmptyStadium = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.4467f,
- 0.7943f,
- 6.2600f,
- 0.5100f,
- 1.1000f,
- 0.0631f,
- 0.1830f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.3981f,
- 0.0380f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a squash court).
- ///
- public static readonly ReverbProperties SportSquashCourt = new ReverbProperties
- (
- 1.0000f,
- 0.7500f,
- 0.3162f,
- 0.3162f,
- 0.7943f,
- 2.2200f,
- 0.9100f,
- 1.1600f,
- 0.4467f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7943f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1260f,
- 0.1900f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 7176.8999f,
- 211.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a small swimming pool).
- ///
- public static readonly ReverbProperties SportSmallSwimmingPool = new ReverbProperties
- (
- 1.0000f,
- 0.7000f,
- 0.3162f,
- 0.7943f,
- 0.8913f,
- 2.7600f,
- 1.2500f,
- 1.1400f,
- 0.6310f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7943f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1790f,
- 0.1500f,
- 0.8950f,
- 0.1900f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a large swimming pool).
- ///
- public static readonly ReverbProperties SportLargeSwimmingPool = new ReverbProperties
- (
- 1.0000f,
- 0.8200f,
- 0.3162f,
- 0.7943f,
- 1.0000f,
- 5.4900f,
- 1.3100f,
- 1.1400f,
- 0.4467f,
- 0.0390f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.5012f,
- 0.0490f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2220f,
- 0.5500f,
- 1.1590f,
- 0.2100f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a gymnasium).
- ///
- public static readonly ReverbProperties SportGymnasium = new ReverbProperties
- (
- 1.0000f,
- 0.8100f,
- 0.3162f,
- 0.4467f,
- 0.8913f,
- 3.1400f,
- 1.0600f,
- 1.3500f,
- 0.3981f,
- 0.0290f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.5623f,
- 0.0450f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1460f,
- 0.1400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 7176.8999f,
- 211.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a full stadium).
- ///
- public static readonly ReverbProperties SportFullStadium = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.0708f,
- 0.7943f,
- 5.2500f,
- 0.1700f,
- 0.8000f,
- 0.1000f,
- 0.1880f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2818f,
- 0.0380f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a tannoy stadium).
- ///
- public static readonly ReverbProperties SportStadiumTannoy = new ReverbProperties
- (
- 1.0000f,
- 0.7800f,
- 0.3162f,
- 0.5623f,
- 0.5012f,
- 2.5300f,
- 0.8800f,
- 0.6800f,
- 0.2818f,
- 0.2300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.5012f,
- 0.0630f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.2000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- /* Prefab Presets */
-
- ///
- /// A reverb preset (approximating a workshop).
- ///
- public static readonly ReverbProperties PrefabWorkshop = new ReverbProperties
- (
- 0.4287f,
- 1.0000f,
- 0.3162f,
- 0.1413f,
- 0.3981f,
- 0.7600f,
- 1.0000f,
- 1.0000f,
- 1.0000f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a school room).
- ///
- public static readonly ReverbProperties PrefabSchoolRoom = new ReverbProperties
- (
- 0.4022f,
- 0.6900f,
- 0.3162f,
- 0.6310f,
- 0.5012f,
- 0.9800f,
- 0.4500f,
- 0.1800f,
- 1.4125f,
- 0.0170f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0150f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.0950f,
- 0.1400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 7176.8999f,
- 211.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a practise room).
- ///
- public static readonly ReverbProperties PrefabPractiseRoom = new ReverbProperties
- (
- 0.4022f,
- 0.8700f,
- 0.3162f,
- 0.3981f,
- 0.5012f,
- 1.1200f,
- 0.5600f,
- 0.1800f,
- 1.2589f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0110f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.0950f,
- 0.1400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 7176.8999f,
- 211.2000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an outhouse).
- ///
- public static readonly ReverbProperties PrefabOuthouse = new ReverbProperties
- (
- 1.0000f,
- 0.8200f,
- 0.3162f,
- 0.1122f,
- 0.1585f,
- 1.3800f,
- 0.3800f,
- 0.3500f,
- 0.8913f,
- 0.0240f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.6310f,
- 0.0440f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1210f,
- 0.1700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 107.5000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a caravan).
- ///
- public static readonly ReverbProperties PrefabCaravan = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.0891f,
- 0.1259f,
- 0.4300f,
- 1.5000f,
- 1.0000f,
- 1.0000f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.9953f,
- 0.0120f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- /* Dome and Pipe Presets */
-
- ///
- /// A reverb preset (approximating a dome in a tomb).
- ///
- public static readonly ReverbProperties DomeTomb = new ReverbProperties
- (
- 1.0000f,
- 0.7900f,
- 0.3162f,
- 0.3548f,
- 0.2239f,
- 4.1800f,
- 0.2100f,
- 0.1000f,
- 0.3868f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.6788f,
- 0.0220f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1770f,
- 0.1900f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 20.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a small pipe).
- ///
- public static readonly ReverbProperties PipeSmall = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.3548f,
- 0.2239f,
- 5.0400f,
- 0.1000f,
- 0.1000f,
- 0.5012f,
- 0.0320f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 2.5119f,
- 0.0150f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 20.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating the dome in St. Paul's Cathedral, London).
- ///
- public static readonly ReverbProperties DomeSaintPauls = new ReverbProperties
- (
- 1.0000f,
- 0.8700f,
- 0.3162f,
- 0.3548f,
- 0.2239f,
- 10.4800f,
- 0.1900f,
- 0.1000f,
- 0.1778f,
- 0.0900f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0420f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.1200f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 20.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a long, thin pipe).
- ///
- public static readonly ReverbProperties PipeLongThin = new ReverbProperties
- (
- 0.2560f,
- 0.9100f,
- 0.3162f,
- 0.4467f,
- 0.2818f,
- 9.2100f,
- 0.1800f,
- 0.1000f,
- 0.7079f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7079f,
- 0.0220f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 20.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a large pipe).
- ///
- public static readonly ReverbProperties PipeLarge = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.3548f,
- 0.2239f,
- 8.4500f,
- 0.1000f,
- 0.1000f,
- 0.3981f,
- 0.0460f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.5849f,
- 0.0320f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 20.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a resonant pipe).
- ///
- public static readonly ReverbProperties PipeResonant = new ReverbProperties
- (
- 0.1373f,
- 0.9100f,
- 0.3162f,
- 0.4467f,
- 0.2818f,
- 6.8100f,
- 0.1800f,
- 0.1000f,
- 0.7079f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.0000f,
- 0.0220f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 20.0000f,
- 0.0000f,
- 0x0
- );
-
- /* Outdoors Presets */
-
- ///
- /// A reverb preset (approximating an outdoors backyard).
- ///
- public static readonly ReverbProperties OutdoorsBackyard = new ReverbProperties
- (
- 1.0000f,
- 0.4500f,
- 0.3162f,
- 0.2512f,
- 0.5012f,
- 1.1200f,
- 0.3400f,
- 0.4600f,
- 0.4467f,
- 0.0690f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.7079f,
- 0.0230f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2180f,
- 0.3400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4399.1001f,
- 242.9000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating rolling plains).
- ///
- public static readonly ReverbProperties OutdoorsRollingPlains = new ReverbProperties
- (
- 1.0000f,
- 0.0000f,
- 0.3162f,
- 0.0112f,
- 0.6310f,
- 2.1300f,
- 0.2100f,
- 0.4600f,
- 0.1778f,
- 0.3000f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.4467f,
- 0.0190f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 1.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4399.1001f,
- 242.9000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a deep canyon).
- ///
- public static readonly ReverbProperties OutdoorsDeepCanyon = new ReverbProperties
- (
- 1.0000f,
- 0.7400f,
- 0.3162f,
- 0.1778f,
- 0.6310f,
- 3.8900f,
- 0.2100f,
- 0.4600f,
- 0.3162f,
- 0.2230f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.3548f,
- 0.0190f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 1.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4399.1001f,
- 242.9000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a creek).
- ///
- public static readonly ReverbProperties OutdoorsCreek = new ReverbProperties
- (
- 1.0000f,
- 0.3500f,
- 0.3162f,
- 0.1778f,
- 0.5012f,
- 2.1300f,
- 0.2100f,
- 0.4600f,
- 0.3981f,
- 0.1150f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.1995f,
- 0.0310f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2180f,
- 0.3400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 4399.1001f,
- 242.9000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a valley).
- ///
- public static readonly ReverbProperties OutdoorsValley = new ReverbProperties
- (
- 1.0000f,
- 0.2800f,
- 0.3162f,
- 0.0282f,
- 0.1585f,
- 2.8800f,
- 0.2600f,
- 0.3500f,
- 0.1413f,
- 0.2630f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.3981f,
- 0.1000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.3400f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 107.5000f,
- 0.0000f,
- 0x0
- );
-
- /* Mood Presets */
-
- ///
- /// A reverb preset (approximating a heavenly mood).
- ///
- public static readonly ReverbProperties MoodHeaven = new ReverbProperties
- (
- 1.0000f,
- 0.9400f,
- 0.3162f,
- 0.7943f,
- 0.4467f,
- 5.0400f,
- 1.1200f,
- 0.5600f,
- 0.2427f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0290f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0800f,
- 2.7420f,
- 0.0500f,
- 0.9977f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a hellish mood).
- ///
- public static readonly ReverbProperties MoodHell = new ReverbProperties
- (
- 1.0000f,
- 0.5700f,
- 0.3162f,
- 0.3548f,
- 0.4467f,
- 3.5700f,
- 0.4900f,
- 2.0000f,
- 0.0000f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1100f,
- 0.0400f,
- 2.1090f,
- 0.5200f,
- 0.9943f,
- 5000.0000f,
- 139.5000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating an abstract memory).
- ///
- public static readonly ReverbProperties MoodMemory = new ReverbProperties
- (
- 1.0000f,
- 0.8500f,
- 0.3162f,
- 0.6310f,
- 0.3548f,
- 4.0600f,
- 0.8200f,
- 0.5600f,
- 0.0398f,
- 0.0000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.1220f,
- 0.0000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.4740f,
- 0.4500f,
- 0.9886f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- /* Driving Presets */
-
- ///
- /// A reverb preset (approximating a person in the commentator's seat).
- ///
- public static readonly ReverbProperties DrivingCommentator = new ReverbProperties
- (
- 1.0000f,
- 0.0000f,
- 0.3162f,
- 0.5623f,
- 0.5012f,
- 2.4200f,
- 0.8800f,
- 0.6800f,
- 0.1995f,
- 0.0930f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2512f,
- 0.0170f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 1.0000f,
- 0.2500f,
- 0.0000f,
- 0.9886f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a pit or garage).
- ///
- public static readonly ReverbProperties DrivingPitGarage = new ReverbProperties
- (
- 0.4287f,
- 0.5900f,
- 0.3162f,
- 0.7079f,
- 0.5623f,
- 1.7200f,
- 0.9300f,
- 0.8700f,
- 0.5623f,
- 0.0000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0160f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.1100f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating driving in a race car).
- ///
- public static readonly ReverbProperties DrivingInCarRacer = new ReverbProperties
- (
- 0.0832f,
- 0.8000f,
- 0.3162f,
- 1.0000f,
- 0.7943f,
- 0.1700f,
- 2.0000f,
- 0.4100f,
- 1.7783f,
- 0.0070f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7079f,
- 0.0150f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 10268.2002f,
- 251.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating driving in a sports car).
- ///
- public static readonly ReverbProperties DrivingInCarSports = new ReverbProperties
- (
- 0.0832f,
- 0.8000f,
- 0.3162f,
- 0.6310f,
- 1.0000f,
- 0.1700f,
- 0.7500f,
- 0.4100f,
- 1.0000f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.5623f,
- 0.0000f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 10268.2002f,
- 251.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating driving in a luxury car).
- ///
- public static readonly ReverbProperties DrivingInCarLuxury = new ReverbProperties
- (
- 0.2560f,
- 1.0000f,
- 0.3162f,
- 0.1000f,
- 0.5012f,
- 0.1300f,
- 0.4100f,
- 0.4600f,
- 0.7943f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.5849f,
- 0.0100f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 10268.2002f,
- 251.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating driving on a course with a full grand stand).
- ///
- public static readonly ReverbProperties DrivingFullGrandStand = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 0.2818f,
- 0.6310f,
- 3.0100f,
- 1.3700f,
- 1.2800f,
- 0.3548f,
- 0.0900f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1778f,
- 0.0490f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 10420.2002f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating an empty grand stand).
- ///
- public static readonly ReverbProperties DrivingEmptyGrandStand = new ReverbProperties
- (
- 1.0000f,
- 1.0000f,
- 0.3162f,
- 1.0000f,
- 0.7943f,
- 4.6200f,
- 1.7500f,
- 1.4000f,
- 0.2082f,
- 0.0900f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2512f,
- 0.0490f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 10420.2002f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating driving in a tunnel).
- ///
- public static readonly ReverbProperties DrivingTunnel = new ReverbProperties
- (
- 1.0000f,
- 0.8100f,
- 0.3162f,
- 0.3981f,
- 0.8913f,
- 3.4200f,
- 0.9400f,
- 1.3100f,
- 0.7079f,
- 0.0510f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7079f,
- 0.0470f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2140f,
- 0.0500f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 155.3000f,
- 0.0000f,
- 0x1
- );
-
- /* City Presets */
-
- ///
- /// A reverb preset (approximating city streets).
- ///
- public static readonly ReverbProperties CityStreets = new ReverbProperties
- (
- 1.0000f,
- 0.7800f,
- 0.3162f,
- 0.7079f,
- 0.8913f,
- 1.7900f,
- 1.1200f,
- 0.9100f,
- 0.2818f,
- 0.0460f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1995f,
- 0.0280f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.2000f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a subway).
- ///
- public static readonly ReverbProperties CitySubway = new ReverbProperties
- (
- 1.0000f,
- 0.7400f,
- 0.3162f,
- 0.7079f,
- 0.8913f,
- 3.0100f,
- 1.2300f,
- 0.9100f,
- 0.7079f,
- 0.0460f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0280f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1250f,
- 0.2100f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a museum).
- ///
- public static readonly ReverbProperties CityMuseum = new ReverbProperties
- (
- 1.0000f,
- 0.8200f,
- 0.3162f,
- 0.1778f,
- 0.1778f,
- 3.2800f,
- 1.4000f,
- 0.5700f,
- 0.2512f,
- 0.0390f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.8913f,
- 0.0340f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1300f,
- 0.1700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 107.5000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating a library).
- ///
- public static readonly ReverbProperties CityLibrary = new ReverbProperties
- (
- 1.0000f,
- 0.8200f,
- 0.3162f,
- 0.2818f,
- 0.0891f,
- 2.7600f,
- 0.8900f,
- 0.4100f,
- 0.3548f,
- 0.0290f,
- new Vector3(0.0000f, 0.0000f, -0.0000f),
- 0.8913f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1300f,
- 0.1700f,
- 0.2500f,
- 0.0000f,
- 0.9943f,
- 2854.3999f,
- 107.5000f,
- 0.0000f,
- 0x0
- );
-
- ///
- /// A reverb preset (approximating an underpass).
- ///
- public static readonly ReverbProperties CityUnderpass = new ReverbProperties
- (
- 1.0000f,
- 0.8200f,
- 0.3162f,
- 0.4467f,
- 0.8913f,
- 3.5700f,
- 1.1200f,
- 0.9100f,
- 0.3981f,
- 0.0590f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.8913f,
- 0.0370f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.1400f,
- 0.2500f,
- 0.0000f,
- 0.9920f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating an abandoned location).
- ///
- public static readonly ReverbProperties CityAbandoned = new ReverbProperties
- (
- 1.0000f,
- 0.6900f,
- 0.3162f,
- 0.7943f,
- 0.8913f,
- 3.2800f,
- 1.1700f,
- 0.9100f,
- 0.4467f,
- 0.0440f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2818f,
- 0.0240f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.2000f,
- 0.2500f,
- 0.0000f,
- 0.9966f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- /* Misc. Presets */
-
- ///
- /// A reverb preset (approximating a dusty room).
- ///
- public static readonly ReverbProperties DustyRoom = new ReverbProperties
- (
- 0.3645f,
- 0.5600f,
- 0.3162f,
- 0.7943f,
- 0.7079f,
- 1.7900f,
- 0.3800f,
- 0.2100f,
- 0.5012f,
- 0.0020f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.2589f,
- 0.0060f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2020f,
- 0.0500f,
- 0.2500f,
- 0.0000f,
- 0.9886f,
- 13046.0000f,
- 163.3000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a chapel).
- ///
- public static readonly ReverbProperties Chapel = new ReverbProperties
- (
- 1.0000f,
- 0.8400f,
- 0.3162f,
- 0.5623f,
- 1.0000f,
- 4.6200f,
- 0.6400f,
- 1.2300f,
- 0.4467f,
- 0.0320f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.7943f,
- 0.0490f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.2500f,
- 0.0000f,
- 0.2500f,
- 0.1100f,
- 0.9943f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x1
- );
-
- ///
- /// A reverb preset (approximating a small, water-filled room).
- ///
- public static readonly ReverbProperties SmallWaterRoom = new ReverbProperties
- (
- 1.0000f,
- 0.7000f,
- 0.3162f,
- 0.4477f,
- 1.0000f,
- 1.5100f,
- 1.2500f,
- 1.1400f,
- 0.8913f,
- 0.0200f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 1.4125f,
- 0.0300f,
- new Vector3(0.0000f, 0.0000f, 0.0000f),
- 0.1790f,
- 0.1500f,
- 0.8950f,
- 0.1900f,
- 0.9920f,
- 5000.0000f,
- 250.0000f,
- 0.0000f,
- 0x0
- );
-}
diff --git a/Robust.Shared/Audio/Effects/ReverbProperties.cs b/Robust.Shared/Audio/Effects/ReverbProperties.cs
deleted file mode 100644
index 508cf1893e2..00000000000
--- a/Robust.Shared/Audio/Effects/ReverbProperties.cs
+++ /dev/null
@@ -1,211 +0,0 @@
-//
-// ReverbProperties.cs
-//
-// Copyright (C) 2019 OpenTK
-//
-// This software may be modified and distributed under the terms
-// of the MIT license. See the LICENSE file for details.
-//
-
-using Robust.Shared.Maths;
-
-namespace Robust.Shared.Audio.Effects;
-
-///
-/// Defines a set of predefined reverb properties.
-///
-public record struct ReverbProperties
-{
- ///
- /// Gets the preset value for .
- ///
- public float Density;
-
- ///
- /// Gets the preset value for .
- ///
- public float Diffusion;
-
- ///
- /// Gets the preset value for .
- ///
- public float Gain;
-
- ///
- /// Gets the preset value for .
- ///
- public float GainHF;
-
- ///
- /// Gets the preset value for .
- ///
- public float GainLF;
-
- ///
- /// Gets the preset value for .
- ///
- public float DecayTime;
-
- ///
- /// Gets the preset value for .
- ///
- public float DecayHFRatio;
-
- ///
- /// Gets the preset value for .
- ///
- public float DecayLFRatio;
-
- ///
- /// Gets the preset value for .
- ///
- public float ReflectionsGain;
-
- ///
- /// Gets the preset value for .
- ///
- public float ReflectionsDelay;
-
- ///
- /// Gets the preset value for .
- ///
- public Vector3 ReflectionsPan;
-
- ///
- /// Gets the preset value for .
- ///
- public float LateReverbGain;
-
- ///
- /// Gets the preset value for .
- ///
- public float LateReverbDelay;
-
- ///
- /// Gets the preset value for .
- ///
- public Vector3 LateReverbPan;
-
- ///
- /// Gets the preset value for .
- ///
- public float EchoTime;
-
- ///
- /// Gets the preset value for .
- ///
- public float EchoDepth;
-
- ///
- /// Gets the preset value for .
- ///
- public float ModulationTime;
-
- ///
- /// Gets the preset value for .
- ///
- public float ModulationDepth;
-
- ///
- /// Gets the preset value for .
- ///
- public float AirAbsorptionGainHF;
-
- ///
- /// Gets the preset value for .
- ///
- public float HFReference;
-
- ///
- /// Gets the preset value for .
- ///
- public float LFReference;
-
- ///
- /// Gets the preset value for .
- ///
- public float RoomRolloffFactor;
-
- ///
- /// Gets the preset value for .
- ///
- public int DecayHFLimit;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- /// See .
- public ReverbProperties
- (
- float density,
- float diffusion,
- float gain,
- float gainHF,
- float gainLF,
- float decayTime,
- float decayHFRatio,
- float decayLFRatio,
- float reflectionsGain,
- float reflectionsDelay,
- Vector3 reflectionsPan,
- float lateReverbGain,
- float lateReverbDelay,
- Vector3 lateReverbPan,
- float echoTime,
- float echoDepth,
- float modulationTime,
- float modulationDepth,
- float airAbsorptionGainHF,
- float hfReference,
- float lfReference,
- float roomRolloffFactor,
- int decayHFLimit
- )
- {
- Density = density;
- Diffusion = diffusion;
- Gain = gain;
- GainHF = gainHF;
- GainLF = gainLF;
- DecayTime = decayTime;
- DecayHFRatio = decayHFRatio;
- DecayLFRatio = decayLFRatio;
- ReflectionsGain = reflectionsGain;
- ReflectionsDelay = reflectionsDelay;
- ReflectionsPan = reflectionsPan;
- LateReverbGain = lateReverbGain;
- LateReverbDelay = lateReverbDelay;
- LateReverbPan = lateReverbPan;
- EchoTime = echoTime;
- EchoDepth = echoDepth;
- ModulationTime = modulationTime;
- ModulationDepth = modulationDepth;
- AirAbsorptionGainHF = airAbsorptionGainHF;
- HFReference = hfReference;
- LFReference = lfReference;
- RoomRolloffFactor = roomRolloffFactor;
- DecayHFLimit = decayHFLimit;
- }
-}
diff --git a/Robust.Shared/Audio/HeadlessAudioManager.cs b/Robust.Shared/Audio/HeadlessAudioManager.cs
deleted file mode 100644
index 6f81ad32f51..00000000000
--- a/Robust.Shared/Audio/HeadlessAudioManager.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System.Numerics;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Maths;
-
-namespace Robust.Shared.Audio;
-
-///
-/// Headless client audio.
-///
-internal sealed class HeadlessAudioManager : SharedAudioManager, IAudioInternal
-{
- ///
- public void InitializePostWindowing()
- {
- }
-
- ///
- public void Shutdown()
- {
- }
-
- ///
- public void FlushALDisposeQueues()
- {
- }
-
- ///
- public IAudioSource? CreateAudioSource(AudioStream stream)
- {
- return DummyAudioSource.Instance;
- }
-
- ///
- public IBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio = false)
- {
- return DummyBufferedAudioSource.Instance;
- }
-
- ///
- public void SetPosition(Vector2 position)
- {
- }
-
- ///
- public void SetRotation(Angle angle)
- {
- }
-
- ///
- public void SetMasterVolume(float value)
- {
- }
-
- ///
- public void SetAttenuation(Attenuation attenuation)
- {
- }
-
- ///
- public void StopAllAudio()
- {
- }
-
- ///
- public void SetZOffset(float f)
- {
- }
-
- ///
- public void _checkAlError(string callerMember = "", int callerLineNumber = -1)
- {
- }
-
- ///
- public float GetAttenuationGain(float distance, float rolloffFactor, float referenceDistance, float maxDistance)
- {
- return 0f;
- }
-}
diff --git a/Robust.Shared/Audio/IAudioInternal.cs b/Robust.Shared/Audio/IAudioInternal.cs
deleted file mode 100644
index 28c3c55158e..00000000000
--- a/Robust.Shared/Audio/IAudioInternal.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using Robust.Shared.Audio.Sources;
-using Robust.Shared.Maths;
-
-namespace Robust.Shared.Audio;
-
-///
-/// Handles clientside audio.
-///
-internal interface IAudioInternal
-{
- void InitializePostWindowing();
- void Shutdown();
-
- ///
- /// Flushes all pending queues for disposing of AL sources.
- ///
- void FlushALDisposeQueues();
-
- IAudioSource? CreateAudioSource(AudioStream stream);
-
- IBufferedAudioSource CreateBufferedAudioSource(int buffers, bool floatAudio=false);
-
- ///
- /// Sets position for the audio listener.
- ///
- void SetPosition(Vector2 position);
-
- ///
- /// Sets rotation for the audio listener.
- ///
- void SetRotation(Angle angle);
-
- void SetMasterVolume(float value);
- void SetAttenuation(Attenuation attenuation);
-
- ///
- /// Stops all audio from playing.
- ///
- void StopAllAudio();
-
- ///
- /// Sets the Z-offset for the audio listener.
- ///
- void SetZOffset(float f);
-
- void _checkAlError([CallerMemberName] string callerMember = "", [CallerLineNumber] int callerLineNumber = -1);
-
- ///
- /// Manually calculates the specified gain for an attenuation source with the specified distance.
- ///
- float GetAttenuationGain(float distance, float rolloffFactor, float referenceDistance, float maxDistance);
-}
diff --git a/Robust.Shared/Audio/IPlayingAudioStream.cs b/Robust.Shared/Audio/IPlayingAudioStream.cs
new file mode 100644
index 00000000000..4315a5dcbc1
--- /dev/null
+++ b/Robust.Shared/Audio/IPlayingAudioStream.cs
@@ -0,0 +1,5 @@
+namespace Robust.Shared.Audio;
+public interface IPlayingAudioStream
+{
+ void Stop();
+}
diff --git a/Robust.Shared/Audio/SharedAudioManager.cs b/Robust.Shared/Audio/SharedAudioManager.cs
deleted file mode 100644
index f08f73a7227..00000000000
--- a/Robust.Shared/Audio/SharedAudioManager.cs
+++ /dev/null
@@ -1,215 +0,0 @@
-using System;
-using System.IO;
-using Robust.Shared.Utility;
-
-namespace Robust.Shared.Audio;
-
-internal abstract class SharedAudioManager
-{
- #region Loading
-
- public virtual AudioStream LoadAudioOggVorbis(Stream stream, string? name = null)
- {
- var vorbis = _readOggVorbis(stream);
- var length = TimeSpan.FromSeconds(vorbis.TotalSamples / (double) vorbis.SampleRate);
- return new AudioStream(null, length, (int) vorbis.Channels, name, vorbis.Title, vorbis.Artist);
- }
-
- public virtual AudioStream LoadAudioWav(Stream stream, string? name = null)
- {
- var wav = _readWav(stream);
- var length = TimeSpan.FromSeconds(wav.Data.Length / (double) wav.BlockAlign / wav.SampleRate);
- return new AudioStream(null, length, wav.NumChannels, name);
- }
-
- public virtual AudioStream LoadAudioRaw(ReadOnlySpan samples, int channels, int sampleRate, string? name = null)
- {
- var length = TimeSpan.FromSeconds((double) samples.Length / channels / sampleRate);
- return new AudioStream(null, length, channels, name);
- }
-
- #endregion
-
- #region Loading Data
-
- protected OggVorbisData _readOggVorbis(Stream stream)
- {
- using (var vorbis = new NVorbis.VorbisReader(stream, false))
- {
- var sampleRate = vorbis.SampleRate;
- var channels = vorbis.Channels;
- var totalSamples = vorbis.TotalSamples;
-
- var readSamples = 0;
- var buffer = new float[totalSamples * channels];
-
- while (readSamples < totalSamples)
- {
- var read = vorbis.ReadSamples(buffer, readSamples * channels, buffer.Length - readSamples);
- if (read == 0)
- {
- break;
- }
-
- readSamples += read;
- }
-
- return new OggVorbisData(totalSamples, sampleRate, channels, buffer, vorbis.Tags.Title, vorbis.Tags.Artist);
- }
- }
-
- internal readonly struct OggVorbisData
- {
- public readonly long TotalSamples;
- public readonly long SampleRate;
- public readonly long Channels;
- public readonly ReadOnlyMemory Data;
- public readonly string Title;
- public readonly string Artist;
-
- public OggVorbisData(long totalSamples, long sampleRate, long channels, ReadOnlyMemory data, string title, string artist)
- {
- TotalSamples = totalSamples;
- SampleRate = sampleRate;
- Channels = channels;
- Data = data;
- Title = title;
- Artist = artist;
- }
- }
-
- ///
- /// Load up a WAVE file.
- ///
- protected static WavData _readWav(Stream stream)
- {
- var reader = new BinaryReader(stream, EncodingHelpers.UTF8, true);
-
- void SkipChunk()
- {
- var length = reader.ReadUInt32();
- stream.Position += length;
- }
-
- // Read outer most chunks.
- Span fourCc = stackalloc byte[4];
- while (true)
- {
- _readFourCC(reader, fourCc);
-
- if (!fourCc.SequenceEqual("RIFF"u8))
- {
- SkipChunk();
- continue;
- }
-
- return _readRiffChunk(reader);
- }
- }
-
- private static void _skipChunk(BinaryReader reader)
- {
- var length = reader.ReadUInt32();
- reader.BaseStream.Position += length;
- }
-
- private static void _readFourCC(BinaryReader reader, Span fourCc)
- {
- fourCc[0] = reader.ReadByte();
- fourCc[1] = reader.ReadByte();
- fourCc[2] = reader.ReadByte();
- fourCc[3] = reader.ReadByte();
- }
-
- private static WavData _readRiffChunk(BinaryReader reader)
- {
- Span format = stackalloc byte[4];
- reader.ReadUInt32();
- _readFourCC(reader, format);
- if (!format.SequenceEqual("WAVE"u8))
- {
- throw new InvalidDataException("File is not a WAVE file.");
- }
-
- _readFourCC(reader, format);
- if (!format.SequenceEqual("fmt "u8))
- {
- throw new InvalidDataException("Expected fmt chunk.");
- }
-
- // Read fmt chunk.
-
- var size = reader.ReadInt32();
- var afterFmtPos = reader.BaseStream.Position + size;
-
- var audioType = (WavAudioFormatType) reader.ReadInt16();
- var channels = reader.ReadInt16();
- var sampleRate = reader.ReadInt32();
- var byteRate = reader.ReadInt32();
- var blockAlign = reader.ReadInt16();
- var bitsPerSample = reader.ReadInt16();
-
- if (audioType != WavAudioFormatType.PCM)
- {
- throw new NotImplementedException("Unable to support audio types other than PCM.");
- }
-
- DebugTools.Assert(byteRate == sampleRate * channels * bitsPerSample / 8);
-
- // Fmt is not of guaranteed size, so use the size header to skip to the end.
- reader.BaseStream.Position = afterFmtPos;
-
- while (true)
- {
- _readFourCC(reader, format);
- if (!format.SequenceEqual("data"u8))
- {
- _skipChunk(reader);
- continue;
- }
-
- break;
- }
-
- // We are in the data chunk.
- size = reader.ReadInt32();
- var data = reader.ReadBytes(size);
-
- return new WavData(audioType, channels, sampleRate, byteRate, blockAlign, bitsPerSample, data);
- }
-
- ///
- /// See http://soundfile.sapp.org/doc/WaveFormat/ for reference.
- ///
- internal readonly struct WavData
- {
- public readonly WavAudioFormatType AudioType;
- public readonly short NumChannels;
- public readonly int SampleRate;
- public readonly int ByteRate;
- public readonly short BlockAlign;
- public readonly short BitsPerSample;
- public readonly ReadOnlyMemory Data;
-
- public WavData(WavAudioFormatType audioType, short numChannels, int sampleRate, int byteRate,
- short blockAlign, short bitsPerSample, ReadOnlyMemory data)
- {
- AudioType = audioType;
- NumChannels = numChannels;
- SampleRate = sampleRate;
- ByteRate = byteRate;
- BlockAlign = blockAlign;
- BitsPerSample = bitsPerSample;
- Data = data;
- }
- }
-
- internal enum WavAudioFormatType : short
- {
- Unknown = 0,
- PCM = 1,
- // There's a bunch of other types, those are all unsupported.
- }
-
- #endregion
-}
diff --git a/Robust.Shared/Audio/SoundSystem.cs b/Robust.Shared/Audio/SoundSystem.cs
new file mode 100644
index 00000000000..dcb5dc05854
--- /dev/null
+++ b/Robust.Shared/Audio/SoundSystem.cs
@@ -0,0 +1,69 @@
+using Robust.Shared.GameObjects;
+using Robust.Shared.IoC;
+using Robust.Shared.Map;
+using Robust.Shared.Player;
+using System;
+
+namespace Robust.Shared.Audio
+{
+ ///
+ /// A static proxy class for interfacing with the AudioSystem.
+ ///
+ public static class SoundSystem
+ {
+ // These functions are obsolete and I CBF adding new arguments to them.
+ private static bool _recordReplay = false;
+
+ ///
+ /// Play an audio file globally, without position.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ /// The set of players that will hear the sound.
+ /// Audio parameters to apply when playing the sound.
+ [Obsolete("Use SharedAudioSystem.PlayGlobal()")]
+ public static IPlayingAudioStream? Play(string filename, Filter playerFilter, AudioParams? audioParams = null)
+ {
+ var entSystMan = IoCManager.Resolve();
+
+ // Some timers try to play audio after the system has shut down?
+ entSystMan.TryGetEntitySystem(out SharedAudioSystem? audio);
+ return audio?.PlayGlobal(filename, playerFilter, _recordReplay, audioParams);
+ }
+
+ ///
+ /// Play an audio file following an entity.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ /// The set of players that will hear the sound.
+ /// The UID of the entity "emitting" the audio.
+ /// Audio parameters to apply when playing the sound.
+ [Obsolete("Use SharedAudioSystem")]
+ public static IPlayingAudioStream? Play(string filename, Filter playerFilter, EntityUid uid,
+ AudioParams? audioParams = null)
+ {
+ var entSystMan = IoCManager.Resolve();
+
+ // Some timers try to play audio after the system has shut down?
+ entSystMan.TryGetEntitySystem(out SharedAudioSystem? audio);
+ return audio?.Play(filename, playerFilter, uid, _recordReplay, audioParams);
+ }
+
+ ///
+ /// Play an audio file at a static position.
+ ///
+ /// The resource path to the OGG Vorbis file to play.
+ /// The set of players that will hear the sound.
+ /// The coordinates at which to play the audio.
+ /// Audio parameters to apply when playing the sound.
+ [Obsolete("Use SharedAudioSystem")]
+ public static IPlayingAudioStream? Play(string filename, Filter playerFilter, EntityCoordinates coordinates,
+ AudioParams? audioParams = null)
+ {
+ var entSystMan = IoCManager.Resolve();
+
+ // Some timers try to play audio after the system has shut down?
+ entSystMan.TryGetEntitySystem(out SharedAudioSystem? audio);
+ return audio?.Play(filename, playerFilter, coordinates, _recordReplay, audioParams);
+ }
+ }
+}
diff --git a/Robust.Shared/Audio/Sources/DummyAudioSource.cs b/Robust.Shared/Audio/Sources/DummyAudioSource.cs
deleted file mode 100644
index 75338b61cea..00000000000
--- a/Robust.Shared/Audio/Sources/DummyAudioSource.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using System.Numerics;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.Serialization.Manager.Attributes;
-
-namespace Robust.Shared.Audio.Sources;
-
-///
-/// Hey look, it's AudioSource's evil twin brother!
-///
-[Virtual]
-[DataDefinition]
-internal partial class DummyAudioSource : IAudioSource
-{
- public static DummyAudioSource Instance { get; } = new();
-
- public void Dispose()
- {
- }
-
- ///
- public void Pause()
- {
- }
-
- ///
- public void StartPlaying()
- {
- }
-
- ///
- public void StopPlaying()
- {
- }
-
- ///
- public bool Playing { get; set; }
-
- ///
- [DataField]
- public bool Looping { get; set; }
-
- ///
- [DataField]
- public bool Global { get; set; }
-
- ///
- public Vector2 Position { get; set; }
-
- ///
- [DataField]
- public float Pitch { get; set; }
-
- ///
- public float Volume { get; set; }
-
- ///
- public float Gain { get; set; }
-
- ///
- [DataField]
- public float MaxDistance { get; set; }
-
- ///
- [DataField]
- public float RolloffFactor { get; set; }
-
- ///
- [DataField]
- public float ReferenceDistance { get; set; }
-
- ///
- public float Occlusion { get; set; }
-
- ///
- public float PlaybackPosition { get; set; }
-
- ///
- public Vector2 Velocity { get; set; }
-
- public void SetAuxiliary(IAuxiliaryAudio? audio)
- {
- }
-}
diff --git a/Robust.Shared/Audio/Sources/IAudioSource.cs b/Robust.Shared/Audio/Sources/IAudioSource.cs
deleted file mode 100644
index f81f8505330..00000000000
--- a/Robust.Shared/Audio/Sources/IAudioSource.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System;
-using System.Numerics;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.GameObjects;
-
-namespace Robust.Shared.Audio.Sources;
-
-///
-/// Engine audio source that directly interacts with OpenAL.
-///
-///
-/// This just exists so client can interact with OpenAL and server can interact with nothing.
-///
-internal interface IAudioSource : IDisposable
-{
- void Pause();
-
- ///
- /// Tries to start playing the audio if not already playing.
- ///
- void StartPlaying();
-
- ///
- /// Stops playing a source if it is currently playing.
- ///
- void StopPlaying();
-
- ///
- /// Is the audio source currently playing.
- ///
- bool Playing { get; set; }
-
- ///
- /// Will the audio source loop when finished playing?
- ///
- bool Looping { get; set; }
-
- ///
- /// Is the audio source relative to the listener or to the world (global or local).
- ///
- bool Global { get; set; }
-
- ///
- /// Position of the audio relative to listener.
- ///
- Vector2 Position { get; set; }
-
- float Pitch { get; set; }
-
- ///
- /// Decibels of the audio. Converted to gain when setting.
- ///
- float Volume { get; set; }
-
- ///
- /// Direct gain for audio.
- ///
- float Gain { get; set; }
-
- float MaxDistance { get; set; }
-
- float RolloffFactor { get; set; }
-
- float ReferenceDistance { get; set; }
-
- float Occlusion { get; set; }
-
- ///
- /// Current playback position.
- ///
- float PlaybackPosition { get; set; }
-
- ///
- /// Audio source velocity. Used for the doppler effect.
- ///
- Vector2 Velocity { get; set; }
-
- ///
- /// Set the auxiliary sendfilter for this audio source.
- ///
- void SetAuxiliary(IAuxiliaryAudio? audio);
-}
diff --git a/Robust.Shared/Audio/Sources/IBufferedAudioSource.cs b/Robust.Shared/Audio/Sources/IBufferedAudioSource.cs
deleted file mode 100644
index 41c7fefba4b..00000000000
--- a/Robust.Shared/Audio/Sources/IBufferedAudioSource.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-
-namespace Robust.Shared.Audio.Sources;
-
-internal interface IBufferedAudioSource : IAudioSource
-{
- int SampleRate { get; set; }
- int GetNumberOfBuffersProcessed();
- void GetBuffersProcessed(Span handles);
- void WriteBuffer(int handle, ReadOnlySpan data);
- void WriteBuffer(int handle, ReadOnlySpan data);
- void QueueBuffers(ReadOnlySpan handles);
- void EmptyBuffers();
-}
diff --git a/Robust.Shared/Audio/Systems/SharedAudioSystem.Effects.cs b/Robust.Shared/Audio/Systems/SharedAudioSystem.Effects.cs
deleted file mode 100644
index 9e5eca6dfa5..00000000000
--- a/Robust.Shared/Audio/Systems/SharedAudioSystem.Effects.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-using System.Collections.Generic;
-using Robust.Shared.Audio.Components;
-using Robust.Shared.Audio.Effects;
-using Robust.Shared.GameObjects;
-using Robust.Shared.Map;
-using Robust.Shared.Utility;
-
-namespace Robust.Shared.Audio.Systems;
-
-public abstract partial class SharedAudioSystem
-{
- /*
- * This is somewhat limiting but also is the easiest way to expose it to content for now.
- */
-
- ///
- /// Pre-calculated auxiliary effect slots for audio presets.
- ///
- public IReadOnlyDictionary Auxiliaries => _auxiliaries;
-
- protected readonly Dictionary _auxiliaries = new();
-
- protected virtual void InitializeEffect()
- {
- SubscribeLocalEvent(OnPresetStartup);
- SubscribeLocalEvent(OnPresetShutdown);
- }
-
- private void OnPresetStartup(EntityUid uid, AudioPresetComponent component, ComponentStartup args)
- {
- _auxiliaries[component.Preset] = uid;
- }
-
- private void OnPresetShutdown(EntityUid uid, AudioPresetComponent component, ComponentShutdown args)
- {
- _auxiliaries.Remove(component.Preset);
- }
-
- ///
- /// Creates an auxiliary audio slot that can have an audio source or audio effect applied to it.
- ///
- public virtual (EntityUid Entity, AudioAuxiliaryComponent Component) CreateAuxiliary()
- {
- var ent = Spawn(null, MapCoordinates.Nullspace);
- var comp = AddComp(ent);
- return (ent, comp);
- }
-
- ///
- /// Creates an audio effect that can be used with an auxiliary audio slot.
- ///
- public virtual (EntityUid Entity, AudioEffectComponent Component) CreateEffect()
- {
- var ent = Spawn(null, MapCoordinates.Nullspace);
- var comp = AddComp(ent);
- return (ent, comp);
- }
-
- ///
- /// Sets the auxiliary effect slot for a specified audio source.
- ///
- public virtual void SetAuxiliary(EntityUid uid, AudioComponent audio, EntityUid? auxUid)
- {
- DebugTools.Assert(auxUid == null || HasComp(auxUid));
- audio.Auxiliary = auxUid;
- Dirty(uid, audio);
- }
-
- ///
- /// Sets the audio effect for a specified auxiliary effect slot.
- ///
- public virtual void SetEffect(EntityUid auxUid, AudioAuxiliaryComponent aux, EntityUid? effectUid)
- {
- DebugTools.Assert(effectUid == null || HasComp(effectUid));
- aux.Effect = effectUid;
- Dirty(auxUid, aux);
- }
-
- public void SetEffect(EntityUid? audioUid, AudioComponent? component, string effectProto)
- {
- if (audioUid == null || component == null)
- return;
-
- SetAuxiliary(audioUid.Value, component, _auxiliaries[effectProto]);
- }
-
- ///
- /// Applies an audio preset prototype to an audio effect entity.
- ///
- public void SetEffectPreset(EntityUid effectUid, AudioEffectComponent effectComp, AudioPresetPrototype preset)
- {
- effectComp.Density = preset.Density;
- effectComp.Diffusion = preset.Diffusion;
- effectComp.Gain = preset.Gain;
- effectComp.GainHF = preset.GainHF;
- effectComp.GainLF = preset.GainLF;
- effectComp.DecayTime = preset.DecayTime;
- effectComp.DecayHFRatio = preset.DecayHFRatio;
- effectComp.DecayLFRatio = preset.DecayLFRatio;
- effectComp.ReflectionsGain = preset.ReflectionsGain;
- effectComp.ReflectionsDelay = preset.ReflectionsDelay;
- effectComp.ReflectionsPan = preset.ReflectionsPan;
- effectComp.LateReverbGain = preset.LateReverbGain;
- effectComp.LateReverbDelay = preset.LateReverbDelay;
- effectComp.LateReverbPan = preset.LateReverbPan;
- effectComp.EchoTime = preset.EchoTime;
- effectComp.EchoDepth = preset.EchoDepth;
- effectComp.ModulationTime = preset.ModulationTime;
- effectComp.ModulationDepth = preset.ModulationDepth;
- effectComp.AirAbsorptionGainHF = preset.AirAbsorptionGainHF;
- effectComp.HFReference = preset.HFReference;
- effectComp.LFReference = preset.LFReference;
- effectComp.RoomRolloffFactor = preset.RoomRolloffFactor;
- effectComp.DecayHFLimit = preset.DecayHFLimit;
-
- Dirty(effectUid, effectComp);
- }
-
- ///
- /// Applies an EAX reverb effect preset to an audio effect.
- ///
- public void SetEffectPreset(EntityUid effectUid, AudioEffectComponent effectComp, ReverbProperties preset)
- {
- effectComp.Density = preset.Density;
- effectComp.Diffusion = preset.Diffusion;
- effectComp.Gain = preset.Gain;
- effectComp.GainHF = preset.GainHF;
- effectComp.GainLF = preset.GainLF;
- effectComp.DecayTime = preset.DecayTime;
- effectComp.DecayHFRatio = preset.DecayHFRatio;
- effectComp.DecayLFRatio = preset.DecayLFRatio;
- effectComp.ReflectionsGain = preset.ReflectionsGain;
- effectComp.ReflectionsDelay = preset.ReflectionsDelay;
- effectComp.ReflectionsPan = preset.ReflectionsPan;
- effectComp.LateReverbGain = preset.LateReverbGain;
- effectComp.LateReverbDelay = preset.LateReverbDelay;
- effectComp.LateReverbPan = preset.LateReverbPan;
- effectComp.EchoTime = preset.EchoTime;
- effectComp.EchoDepth = preset.EchoDepth;
- effectComp.ModulationTime = preset.ModulationTime;
- effectComp.ModulationDepth = preset.ModulationDepth;
- effectComp.AirAbsorptionGainHF = preset.AirAbsorptionGainHF;
- effectComp.HFReference = preset.HFReference;
- effectComp.LFReference = preset.LFReference;
- effectComp.RoomRolloffFactor = preset.RoomRolloffFactor;
- effectComp.DecayHFLimit = preset.DecayHFLimit;
-
- Dirty(effectUid, effectComp);
- }
-}
diff --git a/Robust.Shared/Audio/Systems/SharedAudioSystem.cs b/Robust.Shared/Audio/Systems/SharedAudioSystem.cs
deleted file mode 100644
index 9649e239134..00000000000
--- a/Robust.Shared/Audio/Systems/SharedAudioSystem.cs
+++ /dev/null
@@ -1,489 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using Robust.Shared.Audio.Components;
-using Robust.Shared.Configuration;
-using Robust.Shared.GameObjects;
-using Robust.Shared.GameStates;
-using Robust.Shared.IoC;
-using Robust.Shared.Map;
-using Robust.Shared.Network;
-using Robust.Shared.Player;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Random;
-using Robust.Shared.ResourceManagement.ResourceTypes;
-using Robust.Shared.Serialization;
-using Robust.Shared.Spawners;
-using Robust.Shared.Timing;
-using Robust.Shared.Utility;
-
-namespace Robust.Shared.Audio.Systems;
-
-///
-/// Handles audio for robust toolbox inside of the sim.
-///
-///
-/// Interacts with AudioManager internally.
-///
-public abstract partial class SharedAudioSystem : EntitySystem
-{
- [Dependency] protected readonly IConfigurationManager CfgManager = default!;
- [Dependency] protected readonly IGameTiming Timing = default!;
- [Dependency] private readonly INetManager _netManager = default!;
- [Dependency] protected readonly IPrototypeManager ProtoMan = default!;
- [Dependency] private readonly IResourceCache _resource = default!;
- [Dependency] protected readonly IRobustRandom RandMan = default!;
-
- ///
- /// Default max range at which the sound can be heard.
- ///
- public const float DefaultSoundRange = 20;
-
- ///
- /// Used in the PAS to designate the physics collision mask of occluders.
- ///
- public int OcclusionCollisionMask { get; set; }
-
- public float ZOffset;
-
- public override void Initialize()
- {
- base.Initialize();
- InitializeEffect();
- ZOffset = CfgManager.GetCVar(CVars.AudioZOffset);
- CfgManager.OnValueChanged(CVars.AudioZOffset, SetZOffset);
- SubscribeLocalEvent(OnAudioGetStateAttempt);
- SubscribeLocalEvent(OnAudioUnpaused);
- }
-
- public override void Shutdown()
- {
- base.Shutdown();
- CfgManager.UnsubValueChanged(CVars.AudioZOffset, SetZOffset);
- }
-
- protected virtual void SetZOffset(float value)
- {
- var query = AllEntityQuery();
- var oldZOffset = ZOffset;
- ZOffset = value;
-
- while (query.MoveNext(out var uid, out var audio))
- {
- // Pythagoras back to normal then adjust.
- var maxDistance = MathF.Pow(audio.Params.MaxDistance, 2) - oldZOffset;
- var refDistance = MathF.Pow(audio.Params.ReferenceDistance, 2) - oldZOffset;
-
- audio.Params.MaxDistance = maxDistance;
- audio.Params.ReferenceDistance = refDistance;
- audio.Params = GetAdjustedParams(audio.Params);
- Dirty(uid, audio);
- }
- }
-
- protected virtual void OnAudioUnpaused(EntityUid uid, AudioComponent component, ref EntityUnpausedEvent args)
- {
- component.AudioStart += args.PausedTime;
- }
-
- private void OnAudioGetStateAttempt(EntityUid uid, AudioComponent component, ref ComponentGetStateAttemptEvent args)
- {
- var playerEnt = args.Player?.AttachedEntity;
-
- if ((component.ExcludedEntity != null && playerEnt == component.ExcludedEntity) ||
- (playerEnt != null && component.IncludedEntities != null && !component.IncludedEntities.Contains(playerEnt.Value)))
- {
- args.Cancelled = true;
- }
- }
-
- ///
- /// Considers Z-offset for audio and gets the adjusted distance.
- ///
- ///
- /// Really it's just doing pythagoras for you.
- ///
- public float GetAudioDistance(float length)
- {
- return MathF.Sqrt(MathF.Pow(length, 2) + MathF.Pow(ZOffset, 2));
- }
-
- ///
- /// Resolves the filepath to a sound file.
- ///
- public string GetSound(SoundSpecifier specifier)
- {
- switch (specifier)
- {
- case SoundPathSpecifier path:
- return path.Path == default ? string.Empty : path.Path.ToString();
-
- case SoundCollectionSpecifier collection:
- {
- if (collection.Collection == null)
- return string.Empty;
-
- var soundCollection = ProtoMan.Index(collection.Collection);
- return RandMan.Pick(soundCollection.PickFiles).ToString();
- }
- }
-
- return string.Empty;
- }
-
- #region AudioParams
-
- protected AudioComponent SetupAudio(EntityUid uid, string fileName, AudioParams? audioParams)
- {
- DebugTools.Assert(!string.IsNullOrEmpty(fileName));
- audioParams ??= AudioParams.Default;
- var comp = AddComp(uid);
- comp.FileName = fileName;
- comp.Params = GetAdjustedParams(audioParams.Value);
- comp.AudioStart = Timing.CurTime;
-
- if (!audioParams.Value.Loop)
- {
- var length = GetAudioLength(fileName);
-
- var despawn = AddComp(uid);
- // Don't want to clip audio too short due to imprecision.
- despawn.Lifetime = (float) length.TotalSeconds + 0.01f;
- }
-
- return comp;
- }
-
- ///
- /// Accounts for ZOffset on audio distance.
- ///
- private AudioParams GetAdjustedParams(AudioParams audioParams)
- {
- var maxDistance = GetAudioDistance(audioParams.MaxDistance);
- var refDistance = GetAudioDistance(audioParams.ReferenceDistance);
-
- return audioParams
- .WithMaxDistance(maxDistance)
- .WithReferenceDistance(refDistance);
- }
-
- ///
- /// Sets the audio params volume for an entity.
- ///
- public void SetVolume(EntityUid? entity, float value, Components.AudioComponent? component = null)
- {
- if (entity == null || !Resolve(entity.Value, ref component))
- return;
-
- if (component.Params.Volume.Equals(value))
- return;
-
- component.Params.Volume = value;
- Dirty(entity.Value, component);
- }
-
- #endregion
-
- ///
- /// Gets the timespan of the specified audio.
- ///
- public TimeSpan GetAudioLength(string filename)
- {
- var resource = _resource.GetResource(filename);
- return resource.AudioStream.Length;
- }
-
- ///
- /// Stops the specified audio entity from playing.
- ///
- ///
- /// Returns null so you can inline the call.
- ///
- public EntityUid? Stop(EntityUid? uid, Components.AudioComponent? component = null)
- {
- // One morbillion warnings for logging missing.
- if (uid == null || !Resolve(uid.Value, ref component, false))
- return null;
-
- if (!Timing.IsFirstTimePredicted || (_netManager.IsClient && !IsClientSide(uid.Value)))
- return null;
-
- QueueDel(uid);
- return null;
- }
-
- ///
- /// Play an audio file globally, without position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The set of players that will hear the sound.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayGlobal(string filename, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file globally, without position.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The set of players that will hear the sound.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayGlobal(SoundSpecifier? sound, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayGlobal(GetSound(sound), playerFilter, recordReplay, sound.Params);
- }
-
- ///
- /// Play an audio file globally, without position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The player that will hear the sound.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayGlobal(string filename, ICommonSession recipient, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file globally, without position.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The player that will hear the sound.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayGlobal(SoundSpecifier? sound, ICommonSession recipient)
- {
- return sound == null ? null : PlayGlobal(GetSound(sound), recipient, sound.Params);
- }
-
- ///
- /// Play an audio file globally, without position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The player that will hear the sound.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayGlobal(string filename, EntityUid recipient, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file globally, without position.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The player that will hear the sound.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayGlobal(SoundSpecifier? sound, EntityUid recipient, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayGlobal(GetSound(sound), recipient, sound.Params);
- }
-
- ///
- /// Play an audio file following an entity.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The set of players that will hear the sound.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayEntity(string filename, Filter playerFilter, EntityUid uid, bool recordReplay, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file following an entity.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The player that will hear the sound.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayEntity(string filename, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file following an entity.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The player that will hear the sound.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayEntity(string filename, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file following an entity.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The set of players that will hear the sound.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayEntity(SoundSpecifier? sound, Filter playerFilter, EntityUid uid, bool recordReplay, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayEntity(GetSound(sound), playerFilter, uid, recordReplay, audioParams ?? sound.Params);
- }
-
- ///
- /// Play an audio file following an entity.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The player that will hear the sound.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayEntity(SoundSpecifier? sound, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayEntity(GetSound(sound), recipient, uid, audioParams ?? sound.Params);
- }
-
- ///
- /// Play an audio file following an entity.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The player that will hear the sound.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayEntity(SoundSpecifier? sound, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayEntity(GetSound(sound), recipient, uid, audioParams ?? sound.Params);
- }
-
- ///
- /// Play an audio file following an entity for every entity in PVS range.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayPvs(SoundSpecifier? sound, EntityUid uid, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayPvs(GetSound(sound), uid, audioParams ?? sound.Params);
- }
-
- ///
- /// Play an audio file at the specified EntityCoordinates for every entity in PVS range.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The EntityCoordinates to attach the audio source to.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayPvs(SoundSpecifier? sound, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayPvs(GetSound(sound), coordinates, audioParams ?? sound.Params);
- }
-
- ///
- /// Play an audio file at the specified EntityCoordinates for every entity in PVS range.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The EntityCoordinates to attach the audio source to.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayPvs(string filename,
- EntityCoordinates coordinates, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file following an entity for every entity in PVS range.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The UID of the entity "emitting" the audio.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayPvs(string filename, EntityUid uid,
- AudioParams? audioParams = null);
-
- ///
- /// Plays a predicted sound following an entity. The server will send the sound to every player in PVS range,
- /// unless that player is attached to the "user" entity that initiated the sound. The client-side system plays
- /// this sound as normal
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The UID of the entity "emitting" the audio.
- /// The UID of the user that initiated this sound. This is usually some player's controlled entity.
- [return: NotNullIfNotNull("sound")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayPredicted(SoundSpecifier? sound, EntityUid source, EntityUid? user, AudioParams? audioParams = null);
-
- ///
- /// Plays a predicted sound following an EntityCoordinates. The server will send the sound to every player in PVS range,
- /// unless that player is attached to the "user" entity that initiated the sound. The client-side system plays
- /// this sound as normal
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The entitycoordinates "emitting" the audio
- /// The UID of the user that initiated this sound. This is usually some player's controlled entity.
- [return: NotNullIfNotNull("sound")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayPredicted(SoundSpecifier? sound, EntityCoordinates coordinates, EntityUid? user, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file at a static position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The set of players that will hear the sound.
- /// The coordinates at which to play the audio.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayStatic(string filename, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file at a static position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The player that will hear the sound.
- /// The coordinates at which to play the audio.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayStatic(string filename, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file at a static position.
- ///
- /// The resource path to the OGG Vorbis file to play.
- /// The player that will hear the sound.
- /// The coordinates at which to play the audio.
- [return: NotNullIfNotNull("filename")]
- public abstract (EntityUid Entity, Components.AudioComponent Component)? PlayStatic(string filename, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null);
-
- ///
- /// Play an audio file at a static position.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The set of players that will hear the sound.
- /// The coordinates at which to play the audio.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayStatic(SoundSpecifier? sound, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayStatic(GetSound(sound), playerFilter, coordinates, recordReplay);
- }
-
- ///
- /// Play an audio file at a static position.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The player that will hear the sound.
- /// The coordinates at which to play the audio.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayStatic(SoundSpecifier? sound, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayStatic(GetSound(sound), recipient, coordinates, audioParams ?? sound.Params);
- }
-
- ///
- /// Play an audio file at a static position.
- ///
- /// The sound specifier that points the audio file(s) that should be played.
- /// The player that will hear the sound.
- /// The coordinates at which to play the audio.
- [return: NotNullIfNotNull("sound")]
- public (EntityUid Entity, Components.AudioComponent Component)? PlayStatic(SoundSpecifier? sound, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
- {
- return sound == null ? null : PlayStatic(GetSound(sound), recipient, coordinates, audioParams ?? sound.Params);
- }
-
- // These are just here for replays now.
- // We don't actually need them in shared, or netserializable, but this makes net serialization
- // and replays happy
-
- // TODO: This is quite bandwidth intensive.
- // Sending bus names and file names as strings is expensive and can be optimized.
- // Also there's redundant fields in AudioParams in most cases.
- [NetSerializable, Serializable]
- protected abstract class AudioMessage : EntityEventArgs
- {
- public string FileName = string.Empty;
- public AudioParams AudioParams;
- }
-
- [NetSerializable, Serializable]
- protected sealed class PlayAudioGlobalMessage : AudioMessage
- {
- }
-
- [NetSerializable, Serializable]
- protected sealed class PlayAudioPositionalMessage : AudioMessage
- {
- public NetCoordinates Coordinates;
- }
-
- [NetSerializable, Serializable]
- protected sealed class PlayAudioEntityMessage : AudioMessage
- {
- public NetEntity NetEntity;
- }
-}
diff --git a/Robust.Shared/CVars.cs b/Robust.Shared/CVars.cs
index 484357e944f..d05eb795812 100644
--- a/Robust.Shared/CVars.cs
+++ b/Robust.Shared/CVars.cs
@@ -3,7 +3,6 @@
using System.Threading;
using Lidgren.Network;
using Robust.Shared.Audio;
-using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.Log;
@@ -54,6 +53,16 @@ protected CVars()
public static readonly CVarDef NetReceiveBufferSize =
CVarDef.Create("net.receivebuffersize", 131071, CVar.ARCHIVE);
+ ///
+ /// Size of the pool for Lidgren's array buffers to send messages.
+ /// Set to 0 to disable pooling; max is 8192.
+ ///
+ ///
+ /// Higher just means more potentially wasted space and slower pool retrieval.
+ ///
+ public static readonly CVarDef NetPoolSize =
+ CVarDef.Create("net.pool_size", 512, CVar.CLIENT | CVar.SERVER);
+
///
/// Maximum UDP payload size to send.
///
@@ -120,6 +129,13 @@ protected CVars()
public static readonly CVarDef NetBufferSize =
CVarDef.Create("net.buffer_size", 2, CVar.ARCHIVE | CVar.CLIENTONLY);
+ ///
+ /// The maximum size of the game state buffer. If this is exceeded the client will request a full game state.
+ /// Values less than will be ignored.
+ ///
+ public static readonly CVarDef NetMaxBufferSize =
+ CVarDef.Create("net.max_buffer_size", 512, CVar.ARCHIVE | CVar.CLIENTONLY);
+
///
/// Enable verbose game state/networking logging.
///
@@ -1001,7 +1017,7 @@ protected CVars()
*/
public static readonly CVarDef AudioAttenuation =
- CVarDef.Create("audio.attenuation", (int) Attenuation.LinearDistanceClamped, CVar.REPLICATED | CVar.ARCHIVE);
+ CVarDef.Create("audio.attenuation", (int) Attenuation.Default, CVar.REPLICATED | CVar.ARCHIVE);
///
/// Audio device to try to output audio to by default.
@@ -1021,10 +1037,6 @@ protected CVars()
public static readonly CVarDef AudioRaycastLength =
CVarDef.Create("audio.raycast_length", SharedAudioSystem.DefaultSoundRange, CVar.ARCHIVE | CVar.CLIENTONLY);
- public static readonly CVarDef AudioZOffset =
- CVarDef.Create("audio.z_offset", -1f, CVar.REPLICATED);
-
-
/*
* PLAYER
*/
diff --git a/Robust.Shared/Console/Commands/MapCommands.cs b/Robust.Shared/Console/Commands/MapCommands.cs
index e0ff05b29f8..b9dfe0be647 100644
--- a/Robust.Shared/Console/Commands/MapCommands.cs
+++ b/Robust.Shared/Console/Commands/MapCommands.cs
@@ -131,6 +131,7 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
internal sealed class ListMapsCommand : LocalizedCommands
{
+ [Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IMapManager _map = default!;
public override string Command => "lsmap";
@@ -144,10 +145,13 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args)
foreach (var mapId in _map.GetAllMapIds().OrderBy(id => id.Value))
{
- msg.AppendFormat("{0}: init: {1}, paused: {2}, ent: {3}, grids: {4}\n",
- mapId, _map.IsMapInitialized(mapId),
+ var mapUid = _map.GetMapEntityId(mapId);
+
+ msg.AppendFormat("{0}: {1}, init: {2}, paused: {3}, nent: {4}, grids: {5}\n",
+ mapId, _entManager.GetComponent(mapUid).EntityName,
+ _map.IsMapInitialized(mapId),
_map.IsMapPaused(mapId),
- _map.GetMapEntityId(mapId),
+ _entManager.GetNetEntity(_map.GetMapEntityId(mapId)),
string.Join(",", _map.GetAllGrids(mapId).Select(grid => grid.Owner)));
}
diff --git a/Robust.Shared/Containers/BaseContainer.cs b/Robust.Shared/Containers/BaseContainer.cs
index 8108930b571..5e07ae6c8cc 100644
--- a/Robust.Shared/Containers/BaseContainer.cs
+++ b/Robust.Shared/Containers/BaseContainer.cs
@@ -79,20 +79,7 @@ internal void Init(string id, EntityUid owner, ContainerManagerComponent compone
Owner = owner;
}
- ///
- /// Attempts to insert the entity into this container.
- ///
- ///
- /// If the insertion is successful, the inserted entity will end up parented to the
- /// container entity, and the inserted entity's local position will be set to the zero vector.
- ///
- /// The entity to insert.
- ///
- /// False if the entity could not be inserted.
- ///
- /// Thrown if this container is a child of the entity,
- /// which would cause infinite loops.
- ///
+ [Obsolete("Use container system method")]
public bool Insert(
EntityUid toinsert,
IEntityManager? entMan = null,
@@ -138,16 +125,23 @@ public bool Insert(
return false;
}
+ transform ??= transformQuery.GetComponent(toinsert);
+
//Verify we can insert into this container
- if (!force && !containerSys.CanInsert(toinsert, this))
+ if (!force && !containerSys.CanInsert(toinsert, this, containerXform: ownerTransform))
return false;
// Please somebody ecs containers
var lookupSys = entMan.EntitySysManager.GetEntitySystem();
var xformSys = entMan.EntitySysManager.GetEntitySystem();
- transform ??= transformQuery.GetComponent(toinsert);
meta ??= entMan.GetComponent(toinsert);
+ if (meta.EntityLifeStage >= EntityLifeStage.Terminating)
+ {
+ Logger.ErrorS("container",
+ $"Attempted to insert a terminating entity {entMan.ToPrettyString(toinsert)} into a container {ID} in entity: {entMan.ToPrettyString(Owner)}.");
+ return false;
+ }
// remove from any old containers.
if ((meta.Flags & MetaDataFlags.InContainer) != 0 &&
@@ -270,16 +264,7 @@ internal void RecursivelyUpdateJoints(
/// Whether to assume that the container is currently empty.
protected internal virtual bool CanInsert(EntityUid toInsert, bool assumeEmpty, IEntityManager entMan) => true;
- ///
- /// Attempts to remove the entity from this container.
- ///
- /// If false, this operation will not rigger a move or parent change event. Ignored if
- /// destination is not null
- /// If true, this will not perform can-remove checks.
- /// Where to place the entity after removing. Avoids unnecessary broadphase updates.
- /// If not specified, and reparent option is true, then the entity will either be inserted into a parent
- /// container, the grid, or the map.
- /// Optional final local rotation after removal. Avoids redundant move events.
+ [Obsolete("Use container system method")]
public bool Remove(
EntityUid toRemove,
IEntityManager? entMan = null,
@@ -359,7 +344,7 @@ public bool Remove(
return true;
}
- [Obsolete("use force option in Remove()")]
+ [Obsolete("Use container system method")]
public void ForceRemove(EntityUid toRemove, IEntityManager? entMan = null, MetaDataComponent? meta = null)
=> Remove(toRemove, entMan, meta: meta, reparent: false, force: true);
diff --git a/Robust.Shared/Containers/SharedContainerSystem.Insert.cs b/Robust.Shared/Containers/SharedContainerSystem.Insert.cs
index 681696fb699..62bd224d201 100644
--- a/Robust.Shared/Containers/SharedContainerSystem.Insert.cs
+++ b/Robust.Shared/Containers/SharedContainerSystem.Insert.cs
@@ -1,10 +1,41 @@
+using System;
using Robust.Shared.GameObjects;
-using Robust.Shared.Utility;
+using Robust.Shared.Physics.Components;
namespace Robust.Shared.Containers;
public abstract partial class SharedContainerSystem
{
+
+ ///
+ /// Attempts to insert the entity into this container.
+ ///
+ ///
+ /// If the insertion is successful, the inserted entity will end up parented to the
+ /// container entity, and the inserted entity's local position will be set to the zero vector.
+ ///
+ /// The entity to insert.
+ /// The container to insert into.
+ /// The container's transform component.
+ /// Whether to bypass normal insertion checks.
+ /// False if the entity could not be inserted.
+ ///
+ /// Thrown if this container is a child of the entity,
+ /// which would cause infinite loops.
+ ///
+ public bool Insert(Entity toInsert,
+ BaseContainer container,
+ TransformComponent? containerXform = null,
+ bool force = false)
+ {
+ // Cannot Use Resolve(ref toInsert) as the physics component is optional
+ if (!Resolve(toInsert.Owner, ref toInsert.Comp1, ref toInsert.Comp2))
+ return false;
+
+ // TODO move logic over to the system.
+ return container.Insert(toInsert, EntityManager, toInsert, containerXform, toInsert, toInsert, force);
+ }
+
///
/// Checks if the entity can be inserted into the given container.
///
@@ -13,8 +44,8 @@ public abstract partial class SharedContainerSystem
public bool CanInsert(
EntityUid toInsert,
BaseContainer container,
- TransformComponent? toInsertXform = null,
- bool assumeEmpty = false)
+ bool assumeEmpty = false,
+ TransformComponent? containerXform = null)
{
if (container.Owner == toInsert)
return false;
@@ -25,15 +56,12 @@ public bool CanInsert(
if (!container.CanInsert(toInsert, assumeEmpty, EntityManager))
return false;
- if (!TransformQuery.Resolve(toInsert, ref toInsertXform))
- return false;
-
// no, you can't put maps or grids into containers
if (_mapQuery.HasComponent(toInsert) || _gridQuery.HasComponent(toInsert))
return false;
// Prevent circular insertion.
- if (_transform.ContainsEntity(toInsertXform, container.Owner))
+ if (_transform.ContainsEntity(toInsert, (container.Owner, containerXform)))
return false;
var insertAttemptEvent = new ContainerIsInsertingAttemptEvent(container, toInsert, assumeEmpty);
diff --git a/Robust.Shared/Containers/SharedContainerSystem.Remove.cs b/Robust.Shared/Containers/SharedContainerSystem.Remove.cs
index 7662ae7b50f..512136abcd7 100644
--- a/Robust.Shared/Containers/SharedContainerSystem.Remove.cs
+++ b/Robust.Shared/Containers/SharedContainerSystem.Remove.cs
@@ -1,9 +1,43 @@
using Robust.Shared.GameObjects;
+using Robust.Shared.Map;
+using Robust.Shared.Maths;
namespace Robust.Shared.Containers;
public abstract partial class SharedContainerSystem
{
+ ///
+ /// Attempts to remove the entity from this container.
+ ///
+ ///
+ /// If the insertion is successful, the inserted entity will end up parented to the
+ /// container entity, and the inserted entity's local position will be set to the zero vector.
+ ///
+ /// The entity to remove.
+ /// The container to remove from.
+ /// If false, this operation will not rigger a move or parent change event. Ignored if
+ /// destination is not null
+ /// If true, this will not perform can-remove checks.
+ /// Where to place the entity after removing. Avoids unnecessary broadphase updates.
+ /// If not specified, and reparent option is true, then the entity will either be inserted into a parent
+ /// container, the grid, or the map.
+ /// Optional final local rotation after removal. Avoids redundant move events.
+ public bool Remove(
+ Entity toRemove,
+ BaseContainer container,
+ bool reparent = true,
+ bool force = false,
+ EntityCoordinates? destination = null,
+ Angle? localRotation = null)
+ {
+ // Cannot Use Resolve(ref toInsert) as the physics component is optional
+ if (!Resolve(toRemove.Owner, ref toRemove.Comp1, ref toRemove.Comp2))
+ return false;
+
+ // TODO move logic over to the system.
+ return container.Remove(toRemove, EntityManager, toRemove, toRemove, reparent, force, destination, localRotation);
+ }
+
///
/// Checks if the entity can be removed from this container.
///
diff --git a/Robust.Shared/Containers/SharedContainerSystem.cs b/Robust.Shared/Containers/SharedContainerSystem.cs
index ad348b061b4..113c1731352 100644
--- a/Robust.Shared/Containers/SharedContainerSystem.cs
+++ b/Robust.Shared/Containers/SharedContainerSystem.cs
@@ -216,35 +216,27 @@ public bool IsEntityInContainer(EntityUid uid, MetaDataComponent? meta = null)
}
///
- /// Recursively if the entity, or any parent entity, is inside of a container.
+ /// Recursively check if the entity or any parent is inside of a container.
///
/// If the entity is inside of a container.
public bool IsEntityOrParentInContainer(
EntityUid uid,
MetaDataComponent? meta = null,
- TransformComponent? xform = null,
- EntityQuery? metas = null,
- EntityQuery? xforms = null)
+ TransformComponent? xform = null)
{
- if (meta == null)
- {
- metas ??= GetEntityQuery();
- meta = metas.Value.GetComponent(uid);
- }
+ if (!MetaQuery.Resolve(uid, ref meta))
+ return false;
if ((meta.Flags & MetaDataFlags.InContainer) == MetaDataFlags.InContainer)
return true;
- if (xform == null)
- {
- xforms ??= GetEntityQuery();
- xform = xforms.Value.GetComponent(uid);
- }
+ if (!TransformQuery.Resolve(uid, ref xform))
+ return false;
if (!xform.ParentUid.Valid)
return false;
- return IsEntityOrParentInContainer(xform.ParentUid, metas: metas, xforms: xforms);
+ return IsEntityOrParentInContainer(xform.ParentUid);
}
///
diff --git a/Robust.Shared/ContentPack/Sandbox.yml b/Robust.Shared/ContentPack/Sandbox.yml
index bb55fa1a523..c895dfcafff 100644
--- a/Robust.Shared/ContentPack/Sandbox.yml
+++ b/Robust.Shared/ContentPack/Sandbox.yml
@@ -73,6 +73,12 @@ WhitelistedNamespaces:
# * The API is not *relevant* to content. e.g. System.Type.IsAnsiClass.
# * I am lazy these API lists are huge dude.
Types:
+ NetSerializer:
+ NetListAsArray`1:
+ Fields:
+ - "System.Collections.Generic.IReadOnlyCollection`1 Value"
+ Methods:
+ - "bool get_HasContents()"
Lidgren.Network:
NetBuffer:
All: True
diff --git a/Robust.Shared/GameObjects/ComponentEventArgs.cs b/Robust.Shared/GameObjects/ComponentEventArgs.cs
index 82ac345d32d..367cb2570e8 100644
--- a/Robust.Shared/GameObjects/ComponentEventArgs.cs
+++ b/Robust.Shared/GameObjects/ComponentEventArgs.cs
@@ -31,9 +31,9 @@ public ComponentEventArgs(IComponent component, EntityUid owner)
public readonly struct AddedComponentEventArgs
{
public readonly ComponentEventArgs BaseArgs;
- public readonly CompIdx ComponentType;
+ public readonly ComponentRegistration ComponentType;
- public AddedComponentEventArgs(ComponentEventArgs baseArgs, CompIdx componentType)
+ public AddedComponentEventArgs(ComponentEventArgs baseArgs, ComponentRegistration componentType)
{
BaseArgs = baseArgs;
ComponentType = componentType;
diff --git a/Robust.Shared/GameObjects/Components/Eye/EyeComponent.cs b/Robust.Shared/GameObjects/Components/Eye/EyeComponent.cs
index 13eb1354926..4f2684f2886 100644
--- a/Robust.Shared/GameObjects/Components/Eye/EyeComponent.cs
+++ b/Robust.Shared/GameObjects/Components/Eye/EyeComponent.cs
@@ -12,16 +12,10 @@ namespace Robust.Shared.GameObjects
[RegisterComponent, NetworkedComponent, Access(typeof(SharedEyeSystem)), AutoGenerateComponentState(true)]
public sealed partial class EyeComponent : Component
{
- #region Client
-
- [ViewVariables] internal Eye? _eye = default!;
-
- public IEye? Eye => _eye;
+ public const int DefaultVisibilityMask = 1;
[ViewVariables]
- public MapCoordinates? Position => _eye?.Position;
-
- #endregion
+ public readonly Eye Eye = new();
///
/// If not null, this entity is used to update the eye's position instead of just using the component's owner.
@@ -37,6 +31,9 @@ public sealed partial class EyeComponent : Component
[ViewVariables(VVAccess.ReadWrite), DataField("drawFov"), AutoNetworkedField]
public bool DrawFov = true;
+ [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
+ public bool DrawLight = true;
+
// yes it's not networked, don't ask.
[ViewVariables(VVAccess.ReadWrite), DataField("rotation")]
public Angle Rotation;
@@ -47,8 +44,6 @@ public sealed partial class EyeComponent : Component
[ViewVariables(VVAccess.ReadWrite), DataField("offset"), AutoNetworkedField]
public Vector2 Offset;
- public const int DefaultVisibilityMask = 1;
-
///
/// The visibility mask for this eye.
/// The player will be able to get updates for entities whose layers match the mask.
@@ -58,7 +53,7 @@ public sealed partial class EyeComponent : Component
}
///
- /// Single layer used for Eye visiblity. Controls what entities they are allowed to see.
+ /// Single layer used for Eye visibility. Controls what entities they are allowed to see.
///
public sealed class VisibilityMaskLayer {}
}
diff --git a/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs b/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs
index 214a73fc7e3..b02cfa5d98d 100644
--- a/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs
+++ b/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs
@@ -311,6 +311,7 @@ public EntityCoordinates Coordinates
/// This is effectively a more complete version of
///
[ViewVariables(VVAccess.ReadWrite)]
+ [Obsolete("Use TransformSystem.GetMapCoordinates")]
public MapCoordinates MapPosition => new(WorldPosition, MapID);
///
diff --git a/Robust.Shared/GameObjects/EntityEventBus.Directed.cs b/Robust.Shared/GameObjects/EntityEventBus.Directed.cs
index bf495ad42cb..3f8da6f0672 100644
--- a/Robust.Shared/GameObjects/EntityEventBus.Directed.cs
+++ b/Robust.Shared/GameObjects/EntityEventBus.Directed.cs
@@ -346,7 +346,7 @@ public void OnComponentAdded(in AddedComponentEventArgs e)
{
_subscriptionLock = true;
- EntAddComponent(e.BaseArgs.Owner, e.ComponentType);
+ EntAddComponent(e.BaseArgs.Owner, e.ComponentType.Idx);
}
public void OnComponentRemoved(in RemovedComponentEventArgs e)
diff --git a/Robust.Shared/GameObjects/EntityManager.Components.cs b/Robust.Shared/GameObjects/EntityManager.Components.cs
index 9f3e3fa08c8..7d1b538a75f 100644
--- a/Robust.Shared/GameObjects/EntityManager.Components.cs
+++ b/Robust.Shared/GameObjects/EntityManager.Components.cs
@@ -258,7 +258,7 @@ internal void AddComponentInternal(EntityUid uid, T component, ComponentRegis
component.Networked = false;
}
- var eventArgs = new AddedComponentEventArgs(new ComponentEventArgs(component, uid), reg.Idx);
+ var eventArgs = new AddedComponentEventArgs(new ComponentEventArgs(component, uid), reg);
ComponentAdded?.Invoke(eventArgs);
_eventBus.OnComponentAdded(eventArgs);
@@ -1196,6 +1196,15 @@ public TComp1 GetComponent(EntityUid uid)
: (TComp1)_manager.GetComponent(uid, _type.Value.Type);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
+ public Entity Get(EntityUid uid)
+ {
+ if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted)
+ return new Entity(uid, (TComp1) comp);
+
+ throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}");
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out TComp1? component)
@@ -1269,6 +1278,12 @@ public bool Resolve(EntityUid uid, [NotNullWhen(true)] ref TComp1? component, bo
return false;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining), Pure]
+ public bool Resolve(ref Entity entity, bool logMissing = true)
+ {
+ return Resolve(entity.Owner, ref entity.Comp, logMissing);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Pure]
public TComp1? CompOrNull(EntityUid uid)
diff --git a/Robust.Shared/GameObjects/EntityManager.Network.cs b/Robust.Shared/GameObjects/EntityManager.Network.cs
index f2aa154dacd..cd0285bb336 100644
--- a/Robust.Shared/GameObjects/EntityManager.Network.cs
+++ b/Robust.Shared/GameObjects/EntityManager.Network.cs
@@ -256,8 +256,7 @@ public virtual EntityCoordinates EnsureCoordinates(NetCoordinates netCoordina
///
public HashSet GetEntitySet(HashSet netEntities)
{
- var entities = new HashSet();
- entities.EnsureCapacity(netEntities.Count);
+ var entities = new HashSet(netEntities.Count);
foreach (var netEntity in netEntities)
{
@@ -292,6 +291,16 @@ public HashSet EnsureEntitySet(HashSet netEntities, Ent
return entities;
}
+ public void EnsureEntitySet(HashSet netEntities, EntityUid callerEntity, HashSet entities)
+ {
+ entities.Clear();
+ entities.EnsureCapacity(netEntities.Count);
+ foreach (var netEntity in netEntities)
+ {
+ entities.Add(EnsureEntity(netEntity, callerEntity));
+ }
+ }
+
///
public List EnsureEntityList(List netEntities, EntityUid callerEntity)
{
@@ -305,6 +314,16 @@ public List EnsureEntityList(List netEntities, EntityUi
return entities;
}
+ public void EnsureEntityList(List netEntities, EntityUid callerEntity, List entities)
+ {
+ entities.Clear();
+ entities.EnsureCapacity(netEntities.Count);
+ foreach (var netEntity in netEntities)
+ {
+ entities.Add(EnsureEntity(netEntity, callerEntity));
+ }
+ }
+
///
public List GetEntityList(ICollection netEntities)
{
diff --git a/Robust.Shared/GameObjects/EntitySystem.Proxy.cs b/Robust.Shared/GameObjects/EntitySystem.Proxy.cs
index d9a706d838d..ce2ba0bd558 100644
--- a/Robust.Shared/GameObjects/EntitySystem.Proxy.cs
+++ b/Robust.Shared/GameObjects/EntitySystem.Proxy.cs
@@ -154,9 +154,26 @@ protected void Dirty(EntityUid uid, IComponent component, MetaDataComponent? met
/// Marks a component as dirty. This also implicitly dirties the entity this component belongs to.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- protected void Dirty(Entity ent, MetaDataComponent? meta = null) where T : IComponent
+ protected void Dirty(Entity ent, MetaDataComponent? meta = null) where T : IComponent?
{
- EntityManager.Dirty(ent.Owner, ent.Comp, meta);
+ var comp = ent.Comp;
+ if (comp == null && !EntityManager.TryGetComponent(ent.Owner, out comp))
+ return;
+
+ EntityManager.Dirty(ent.Owner, comp, meta);
+ }
+
+ ///
+ /// Marks a component as dirty. This also implicitly dirties the entity this component belongs to.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected void Dirty(Entity ent) where T : IComponent?
+ {
+ var comp = ent.Comp1;
+ if (comp == null && !EntityManager.TryGetComponent(ent.Owner, out comp))
+ return;
+
+ EntityManager.Dirty(ent.Owner, comp, ent.Comp2);
}
///
@@ -993,12 +1010,24 @@ protected HashSet EnsureEntitySet(HashSet netEntities,
return EntityManager.EnsureEntitySet(netEntities, callerEntity);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected void EnsureEntitySet(HashSet netEntities, EntityUid callerEntity, HashSet entities)
+ {
+ EntityManager.EnsureEntitySet(netEntities, callerEntity, entities);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected List EnsureEntityList(List netEntities, EntityUid callerEntity)
{
return EntityManager.EnsureEntityList(netEntities, callerEntity);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected void EnsureEntityList(List netEntities, EntityUid callerEntity, List entities)
+ {
+ EntityManager.EnsureEntityList(netEntities, callerEntity, entities);
+ }
+
///
/// Returns the of a . Returns if it doesn't exist.
///
diff --git a/Robust.Shared/GameObjects/EntitySystem.Resolve.cs b/Robust.Shared/GameObjects/EntitySystem.Resolve.cs
index c1750ee0976..1f54929faf0 100644
--- a/Robust.Shared/GameObjects/EntitySystem.Resolve.cs
+++ b/Robust.Shared/GameObjects/EntitySystem.Resolve.cs
@@ -32,7 +32,7 @@ protected bool Resolve(EntityUid uid, [NotNullWhen(true)] ref TComp? comp
return found;
}
- ///
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected bool Resolve(EntityUid uid, [NotNullWhen(true)] ref MetaDataComponent? component,
bool logMissing = true)
@@ -40,7 +40,7 @@ protected bool Resolve(EntityUid uid, [NotNullWhen(true)] ref MetaDataComponent?
return EntityManager.MetaQuery.Resolve(uid, ref component);
}
- ///
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected bool Resolve(EntityUid uid, [NotNullWhen(true)] ref TransformComponent? component,
bool logMissing = true)
diff --git a/Robust.Shared/GameObjects/EntitySystemMessages/AudioMessages.cs b/Robust.Shared/GameObjects/EntitySystemMessages/AudioMessages.cs
new file mode 100644
index 00000000000..cbc5e56f31b
--- /dev/null
+++ b/Robust.Shared/GameObjects/EntitySystemMessages/AudioMessages.cs
@@ -0,0 +1,44 @@
+using Robust.Shared.Audio;
+using Robust.Shared.Map;
+using Robust.Shared.Serialization;
+using System;
+
+#nullable disable
+
+namespace Robust.Shared.GameObjects;
+// TODO: This is quite bandwidth intensive.
+// Sending bus names and file names as strings is expensive and can be optimized.
+// Also there's redundant fields in AudioParams in most cases.
+[Serializable, NetSerializable]
+public abstract class AudioMessage : EntityEventArgs
+{
+ public uint Identifier { get; set; }
+ public string FileName { get; set; }
+ public AudioParams AudioParams { get; set; }
+}
+
+[Serializable, NetSerializable]
+public sealed class StopAudioMessageClient : EntityEventArgs
+{
+ public uint Identifier {get; set;}
+}
+
+[Serializable, NetSerializable]
+public sealed class PlayAudioGlobalMessage : AudioMessage
+{
+}
+
+[Serializable, NetSerializable]
+public sealed class PlayAudioPositionalMessage : AudioMessage
+{
+ public NetCoordinates Coordinates { get; set; }
+ public NetCoordinates FallbackCoordinates { get; set; }
+}
+
+[Serializable, NetSerializable]
+public sealed class PlayAudioEntityMessage : AudioMessage
+{
+ public NetEntity NetEntity { get; set; }
+ public NetCoordinates Coordinates { get; set; }
+ public NetCoordinates FallbackCoordinates { get; set; }
+}
diff --git a/Robust.Shared/GameObjects/IResourceCache.cs b/Robust.Shared/GameObjects/IResourceCache.cs
deleted file mode 100644
index d3431b0b83e..00000000000
--- a/Robust.Shared/GameObjects/IResourceCache.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using Robust.Shared.ResourceManagement;
-using Robust.Shared.Utility;
-
-namespace Robust.Shared.GameObjects;
-
-///
-/// Handles caching of
-///
-public interface IResourceCache
-{
- T GetResource(string path, bool useFallback = true)
- where T : BaseResource, new();
-
- T GetResource(ResPath path, bool useFallback = true)
- where T : BaseResource, new();
-
- bool TryGetResource(string path, [NotNullWhen(true)] out T? resource)
- where T : BaseResource, new();
-
- bool TryGetResource(ResPath path, [NotNullWhen(true)] out T? resource)
- where T : BaseResource, new();
-
- void ReloadResource(string path)
- where T : BaseResource, new();
-
- void ReloadResource(ResPath path)
- where T : BaseResource, new();
-
- void CacheResource(string path, T resource)
- where T : BaseResource, new();
-
- void CacheResource(ResPath path, T resource)
- where T : BaseResource, new();
-
- T GetFallback()
- where T : BaseResource, new();
-
- IEnumerable> GetAllResources() where T : BaseResource, new();
-}
-
diff --git a/Robust.Shared/GameObjects/Systems/EntityLookup.Queries.cs b/Robust.Shared/GameObjects/Systems/EntityLookup.Queries.cs
index c75b3bd02af..163c7a69a01 100644
--- a/Robust.Shared/GameObjects/Systems/EntityLookup.Queries.cs
+++ b/Robust.Shared/GameObjects/Systems/EntityLookup.Queries.cs
@@ -171,11 +171,16 @@ private bool AnyEntitiesIntersecting(EntityUid lookupUid,
private void RecursiveAdd(EntityUid uid, ref ValueList toAdd)
{
- var childEnumerator = _xformQuery.GetComponent(uid).ChildEnumerator;
+ if (!_xformQuery.TryGetComponent(uid, out var xform))
+ {
+ Log.Error($"Encountered deleted entity {uid} while performing entity lookup.");
+ return;
+ }
+ toAdd.Add(uid);
+ var childEnumerator = xform.ChildEnumerator;
while (childEnumerator.MoveNext(out var child))
{
- toAdd.Add(child.Value);
RecursiveAdd(child.Value, ref toAdd);
}
}
@@ -185,6 +190,11 @@ private void AddContained(HashSet intersecting, LookupFlags flags)
if ((flags & LookupFlags.Contained) == 0x0 || intersecting.Count == 0)
return;
+ // TODO PERFORMANCE.
+ // toAdd only exists because we can't add directly to intersecting w/o enumeration issues.
+ // If we assume that there are more entities in containers than there are entities in the intersecting set, then
+ // we would be better off creating a fixed-size EntityUid array and coping all intersecting entities into that
+ // instead of creating a value list here that needs to be resized.
var toAdd = new ValueList();
foreach (var uid in intersecting)
@@ -196,7 +206,6 @@ private void AddContained(HashSet intersecting, LookupFlags flags)
{
foreach (var contained in con.ContainedEntities)
{
- toAdd.Add(contained);
RecursiveAdd(contained, ref toAdd);
}
}
diff --git a/Robust.Shared/GameObjects/Systems/EntityLookupSystem.ComponentQueries.cs b/Robust.Shared/GameObjects/Systems/EntityLookupSystem.ComponentQueries.cs
index 83d0aaaaa69..c91b5609024 100644
--- a/Robust.Shared/GameObjects/Systems/EntityLookupSystem.ComponentQueries.cs
+++ b/Robust.Shared/GameObjects/Systems/EntityLookupSystem.ComponentQueries.cs
@@ -6,7 +6,11 @@
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Maths;
+using Robust.Shared.Physics;
+using Robust.Shared.Physics.Collision;
+using Robust.Shared.Physics.Collision.Shapes;
using Robust.Shared.Physics.Dynamics;
+using Robust.Shared.Physics.Systems;
using Robust.Shared.Utility;
namespace Robust.Shared.GameObjects;
@@ -15,18 +19,6 @@ public sealed partial class EntityLookupSystem
{
#region Private
- private void AddComponentsIntersecting(
- EntityUid lookupUid,
- HashSet intersecting,
- Box2 worldAABB,
- LookupFlags flags,
- EntityQuery query) where T : IComponent
- {
- var intersectingEntities = new HashSet>();
- AddEntitiesIntersecting(lookupUid, intersectingEntities, worldAABB, flags, query);
- intersecting.UnionWith(intersectingEntities.Select(e => e.Comp));
- }
-
private void AddEntitiesIntersecting(
EntityUid lookupUid,
HashSet> intersecting,
@@ -88,6 +80,155 @@ private void AddEntitiesIntersecting(
}
}
+ private void AddEntitiesIntersecting(
+ EntityUid lookupUid,
+ HashSet> intersecting,
+ IPhysShape shape,
+ Box2 worldAABB,
+ LookupFlags flags,
+ EntityQuery query) where T : IComponent
+ {
+ var lookup = _broadQuery.GetComponent(lookupUid);
+ var invMatrix = _transform.GetInvWorldMatrix(lookupUid);
+ var localAABB = invMatrix.TransformBox(worldAABB);
+ var transform = new Transform(0);
+ var state = new QueryState(
+ intersecting,
+ shape,
+ transform,
+ _fixtures,
+ _physics,
+ _transform,
+ _manifoldManager,
+ query,
+ _fixturesQuery,
+ (flags & LookupFlags.Sensors) != 0
+ );
+
+ if ((flags & LookupFlags.Dynamic) != 0x0)
+ {
+ lookup.DynamicTree.QueryAabb(ref state, static (ref QueryState state, in FixtureProxy value) =>
+ {
+ if (!state.Sensors && !value.Fixture.Hard)
+ return true;
+
+ if (!state.Query.TryGetComponent(value.Entity, out var comp))
+ return true;
+
+ var intersectingTransform = state.Physics.GetPhysicsTransform(value.Entity);
+ if (!state.Manifolds.TestOverlap(state.Shape, 0, value.Fixture.Shape, value.ChildIndex, state.Transform, intersectingTransform))
+ {
+ return true;
+ }
+
+ state.Intersecting.Add((value.Entity, comp));
+ return true;
+ }, localAABB, (flags & LookupFlags.Approximate) != 0x0);
+ }
+
+ if ((flags & (LookupFlags.Static)) != 0x0)
+ {
+ lookup.StaticTree.QueryAabb(ref state, static (ref QueryState state, in FixtureProxy value) =>
+ {
+ if (!state.Sensors && !value.Fixture.Hard)
+ return true;
+
+ if (!state.Query.TryGetComponent(value.Entity, out var comp))
+ return true;
+
+ var intersectingTransform = state.Physics.GetPhysicsTransform(value.Entity);
+ if (!state.Manifolds.TestOverlap(state.Shape, 0, value.Fixture.Shape, value.ChildIndex, state.Transform, intersectingTransform))
+ {
+ return true;
+ }
+
+ state.Intersecting.Add((value.Entity, comp));
+ return true;
+ }, localAABB, (flags & LookupFlags.Approximate) != 0x0);
+ }
+
+ if ((flags & LookupFlags.StaticSundries) == LookupFlags.StaticSundries)
+ {
+ lookup.StaticSundriesTree.QueryAabb(ref state, static (ref QueryState state, in EntityUid value) =>
+ {
+ if (!state.Query.TryGetComponent(value, out var comp))
+ return true;
+
+ var intersectingTransform = state.Physics.GetPhysicsTransform(value);
+
+ if (state.FixturesQuery.TryGetComponent(value, out var fixtures))
+ {
+ bool anyFixture = false;
+ foreach (var fixture in fixtures.Fixtures.Values)
+ {
+ if (!state.Sensors && !fixture.Hard)
+ continue;
+
+ anyFixture = true;
+ for (var i = 0; i < fixture.Shape.ChildCount; i++)
+ {
+ if (state.Manifolds.TestOverlap(state.Shape, 0, fixture.Shape, i, state.Transform,
+ intersectingTransform))
+ {
+ state.Intersecting.Add((value, comp));
+ return true;
+ }
+ }
+ }
+
+ if (anyFixture)
+ return true;
+ }
+
+ if (state.Fixtures.TestPoint(state.Shape, state.Transform, intersectingTransform.Position))
+ state.Intersecting.Add((value, comp));
+
+ return true;
+ }, localAABB, (flags & LookupFlags.Approximate) != 0x0);
+ }
+
+ if ((flags & LookupFlags.Sundries) != 0x0)
+ {
+ lookup.SundriesTree.QueryAabb(ref state, static (ref QueryState state,
+ in EntityUid value) =>
+ {
+ if (!state.Query.TryGetComponent(value, out var comp))
+ return true;
+
+ var intersectingTransform = state.Physics.GetPhysicsTransform(value);
+
+ if (state.FixturesQuery.TryGetComponent(value, out var fixtures))
+ {
+ bool anyFixture = false;
+ foreach (var fixture in fixtures.Fixtures.Values)
+ {
+ if (!state.Sensors && !fixture.Hard)
+ continue;
+
+ anyFixture = true;
+ for (var i = 0; i < fixture.Shape.ChildCount; i++)
+ {
+ if (state.Manifolds.TestOverlap(state.Shape, 0, fixture.Shape, i, state.Transform,
+ intersectingTransform))
+ {
+ state.Intersecting.Add((value, comp));
+ return true;
+ }
+ }
+ }
+
+ if (anyFixture)
+ return true;
+ }
+
+ if (state.Fixtures.TestPoint(state.Shape, state.Transform, intersectingTransform.Position))
+ state.Intersecting.Add((value, comp));
+
+ return true;
+ }, localAABB, (flags & LookupFlags.Approximate) != 0x0);
+ }
+ }
+
private bool AnyComponentsIntersecting(
EntityUid lookupUid,
Box2 worldAABB,
@@ -270,7 +411,7 @@ public bool AnyComponentsIntersecting(Type type, MapId mapId, Box2 worldAABB, En
if (xform.MapID != mapId ||
!worldAABB.Contains(_transform.GetWorldPosition(xform)) ||
((flags & LookupFlags.Contained) == 0x0 &&
- _container.IsEntityOrParentInContainer(uid, _metaQuery.GetComponent(uid), xform, _metaQuery, _xformQuery)))
+ _container.IsEntityOrParentInContainer(uid, null, xform)))
{
continue;
}
@@ -308,15 +449,6 @@ public bool AnyComponentsIntersecting(Type type, MapId mapId, Box2 worldAABB, En
return false;
}
- [Obsolete]
- public HashSet GetComponentsIntersecting(Type type, MapId mapId, Box2 worldAABB, LookupFlags flags = DefaultFlags)
- {
- var intersectingEntities = new HashSet>();
- GetEntitiesIntersecting(type, mapId, worldAABB, intersectingEntities, flags);
- var intersecting = new HashSet(intersectingEntities.Select(e => e.Comp));
- return intersecting;
- }
-
public void GetEntitiesIntersecting(Type type, MapId mapId, Box2 worldAABB, HashSet> intersecting, LookupFlags flags = DefaultFlags)
{
DebugTools.Assert(typeof(IComponent).IsAssignableFrom(type));
@@ -332,7 +464,7 @@ public void GetEntitiesIntersecting(Type type, MapId mapId, Box2 worldAABB, Hash
if (xform.MapID != mapId ||
!worldAABB.Contains(_transform.GetWorldPosition(xform)) ||
((flags & LookupFlags.Contained) == 0x0 &&
- _container.IsEntityOrParentInContainer(uid, _metaQuery.GetComponent(uid), xform, _metaQuery, _xformQuery)))
+ _container.IsEntityOrParentInContainer(uid, _metaQuery.GetComponent(uid), xform)))
{
continue;
}
@@ -366,14 +498,6 @@ public void GetEntitiesIntersecting(Type type, MapId mapId, Box2 worldAABB, Hash
}
}
- [Obsolete]
- public HashSet GetComponentsIntersecting(MapId mapId, Box2 worldAABB, LookupFlags flags = DefaultFlags) where T : IComponent
- {
- var intersectingEntities = new HashSet>();
- GetEntitiesIntersecting(mapId, worldAABB, intersectingEntities, flags);
- return new HashSet(intersectingEntities.Select(e => e.Comp));
- }
-
public void GetEntitiesIntersecting(MapId mapId, Box2 worldAABB, HashSet> entities, LookupFlags flags = DefaultFlags) where T : IComponent
{
if (mapId == MapId.Nullspace) return;
@@ -416,14 +540,163 @@ public void GetEntitiesIntersecting(MapId mapId, Box2 worldAABB, HashSet GetComponentsInRange(EntityCoordinates coordinates, float range) where T : IComponent
+ public void GetEntitiesIntersecting(Type type, MapId mapId, IPhysShape shape, HashSet> intersecting, LookupFlags flags = DefaultFlags)
{
- var mapPos = coordinates.ToMap(EntityManager, _transform);
- return GetComponentsInRange(mapPos, range);
+ DebugTools.Assert(typeof(IComponent).IsAssignableFrom(type));
+ if (mapId == MapId.Nullspace)
+ return;
+
+ var shapeTransform = new Transform(0);
+ var worldAABB = shape.ComputeAABB(shapeTransform, 0);
+ var sensors = (flags & LookupFlags.Sensors) != 0;
+ if (!UseBoundsQuery(type, worldAABB.Height * worldAABB.Width))
+ {
+ foreach (var (uid, comp) in EntityManager.GetAllComponents(type, true))
+ {
+ var xform = _xformQuery.GetComponent(uid);
+ var (pos, rot) = _transform.GetWorldPositionRotation(xform);
+
+ if (xform.MapID != mapId ||
+ !worldAABB.Contains(pos) ||
+ ((flags & LookupFlags.Contained) == 0x0 &&
+ _container.IsEntityOrParentInContainer(uid, _metaQuery.GetComponent(uid), xform)))
+ {
+ continue;
+ }
+
+ if (_fixturesQuery.TryGetComponent(uid, out var fixtures))
+ {
+ var transform = new Transform(pos, rot);
+
+ bool anyFixture = false;
+ foreach (var fixture in fixtures.Fixtures.Values)
+ {
+ if (!sensors && !fixture.Hard)
+ continue;
+
+ anyFixture = true;
+ for (var i = 0; i < fixture.Shape.ChildCount; i++)
+ {
+ if (_manifoldManager.TestOverlap(shape, 0, fixture.Shape, i, shapeTransform, transform))
+ {
+ goto found;
+ }
+ }
+ }
+
+ if (anyFixture)
+ continue;
+ }
+
+ if (!_fixtures.TestPoint(shape, shapeTransform, pos))
+ continue;
+
+ found:
+ intersecting.Add((uid, comp));
+ }
+ }
+ else
+ {
+ var query = EntityManager.GetEntityQuery(type);
+
+ // Get grid entities
+ var state = new GridQueryState(intersecting, shape, worldAABB, this, flags, query);
+
+ _mapManager.FindGridsIntersecting(mapId, worldAABB, ref state,
+ static (EntityUid uid, MapGridComponent grid, ref GridQueryState state) =>
+ {
+ state.Lookup.AddEntitiesIntersecting(uid, state.Intersecting, state.Shape, state.WorldAABB, state.Flags, state.Query);
+ return true;
+ }, (flags & LookupFlags.Approximate) != 0x0);
+
+ // Get map entities
+ var mapUid = _mapManager.GetMapEntityId(mapId);
+ AddEntitiesIntersecting(mapUid, intersecting, shape, worldAABB, flags, query);
+ AddContained(intersecting, flags, query);
+ }
+ }
+
+ public void GetEntitiesIntersecting(MapId mapId, IPhysShape shape, HashSet> entities, LookupFlags flags = DefaultFlags) where T : IComponent
+ {
+ if (mapId == MapId.Nullspace) return;
+
+ var shapeTransform = new Transform(0);
+ var worldAABB = shape.ComputeAABB(shapeTransform, 0);
+ var sensors = (flags & LookupFlags.Sensors) != 0;
+ if (!UseBoundsQuery(worldAABB.Height * worldAABB.Width))
+ {
+ var query = AllEntityQuery();
+
+ while (query.MoveNext(out var uid, out var comp, out var xform))
+ {
+ var (pos, rot) = _transform.GetWorldPositionRotation(xform);
+
+ if (xform.MapID != mapId || !worldAABB.Contains(pos))
+ continue;
+
+ if (_fixturesQuery.TryGetComponent(uid, out var fixtures))
+ {
+ var transform = new Transform(pos, rot);
+ bool anyFixture = false;
+ foreach (var fixture in fixtures.Fixtures.Values)
+ {
+ if (!sensors && !fixture.Hard)
+ continue;
+
+ anyFixture = true;
+ for (var i = 0; i < fixture.Shape.ChildCount; i++)
+ {
+ if (_manifoldManager.TestOverlap(shape, 0, fixture.Shape, i, shapeTransform, transform))
+ {
+ goto found;
+ }
+ }
+ }
+
+ if (anyFixture)
+ continue;
+ }
+
+ if (!_fixtures.TestPoint(shape, shapeTransform, pos))
+ continue;
+
+ found:
+ entities.Add((uid, comp));
+ }
+ }
+ else
+ {
+ var query = GetEntityQuery();
+
+ // Get grid entities
+ var state = (this, shape, worldAABB, flags, query, entities);
+
+ _mapManager.FindGridsIntersecting(mapId, worldAABB, ref state,
+ static (EntityUid uid, MapGridComponent grid,
+ ref (EntityLookupSystem system,
+ IPhysShape shape,
+ Box2 worldAABB,
+ LookupFlags flags,
+ EntityQuery query,
+ HashSet> intersecting) tuple) =>
+ {
+ tuple.system.AddEntitiesIntersecting(uid, tuple.intersecting, tuple.shape, tuple.worldAABB, tuple.flags, tuple.query);
+ return true;
+ }, (flags & LookupFlags.Approximate) != 0x0);
+
+ // Get map entities
+ var mapUid = _mapManager.GetMapEntityId(mapId);
+ AddEntitiesIntersecting(mapUid, entities, shape, worldAABB, flags, query);
+ AddContained(entities, flags, query);
+ }
}
+ #endregion
+
+ #region EntityCoordinates
+
public void GetEntitiesInRange(EntityCoordinates coordinates, float range, HashSet> entities) where T : IComponent
{
var mapPos = coordinates.ToMap(EntityManager, _transform);
@@ -441,35 +714,34 @@ public HashSet> GetEntitiesInRange(EntityCoordinates coordinates, f
#region MapCoordinates
- [Obsolete]
- public HashSet GetComponentsInRange(Type type, MapCoordinates coordinates, float range)
+ public HashSet> GetEntitiesInRange(Type type, MapCoordinates coordinates, float range)
{
- DebugTools.Assert(typeof(IComponent).IsAssignableFrom(type));
- return GetComponentsInRange(type, coordinates.MapId, coordinates.Position, range);
+ var entities = new HashSet>();
+ GetEntitiesInRange(type, coordinates, range, entities);
+ return entities;
}
- public HashSet> GetEntitiesInRange(Type type, MapCoordinates coordinates, float range)
+ public void GetEntitiesInRange(Type type, MapCoordinates coordinates, float range, HashSet> entities)
{
DebugTools.Assert(typeof(IComponent).IsAssignableFrom(type));
- var entities = new HashSet>();
GetEntitiesInRange(type, coordinates.MapId, coordinates.Position, range, entities);
- return entities;
}
+ [Obsolete]
public HashSet GetComponentsInRange(MapCoordinates coordinates, float range) where T : IComponent
{
return GetComponentsInRange(coordinates.MapId, coordinates.Position, range);
}
- public void GetEntitiesInRange(MapCoordinates coordinates, float range, HashSet> entities) where T : IComponent
+ public void GetEntitiesInRange(MapCoordinates coordinates, float range, HashSet> entities, LookupFlags flags = DefaultFlags) where T : IComponent
{
- GetEntitiesInRange(coordinates.MapId, coordinates.Position, range, entities);
+ GetEntitiesInRange(coordinates.MapId, coordinates.Position, range, entities, flags);
}
- public HashSet> GetEntitiesInRange