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();
}
}