Files
Test-Multiplayer/Library/PackageCache/com.unity.dedicated-server@5a2666836321/MultiplayerRoles/Editor/AutomaticSelectionOptions.cs
pelpanagiotis 329b7d3183 First Commit
2025-12-21 18:31:02 +02:00

247 lines
8.4 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEditor;
namespace Unity.Multiplayer.Editor
{
[Serializable]
internal struct AutomaticSelectionOptions
{
private Dictionary<Type, MultiplayerRoleFlags> m_CompleteComponentsList;
internal Dictionary<Type, MultiplayerRoleFlags> CompleteComponentsList
{
get
{
if (m_CompleteComponentsList == null)
BakeCompleteComponentsList();
return m_CompleteComponentsList;
}
}
[SerializeField] private bool m_StripRenderComponents;
[SerializeField] private bool m_StripUIComponents;
[SerializeField] private bool m_StripAudioComponents;
public bool StripRenderingComponents
{
get => m_StripRenderComponents;
set
{
// Don't bake if value didn't change
if (m_StripRenderComponents == value)
return;
m_StripRenderComponents = value;
BakeCompleteComponentsList();
}
}
public bool StripUIComponents
{
get => m_StripUIComponents;
set
{
// Don't bake if value didn't change
if (m_StripUIComponents == value)
return;
m_StripUIComponents = value;
BakeCompleteComponentsList();
}
}
public bool StripAudioComponents
{
get => m_StripAudioComponents;
set
{
// Don't bake if value didn't change
if (m_StripAudioComponents == value)
return;
m_StripAudioComponents = value;
BakeCompleteComponentsList();
}
}
[SerializeField] private SerializedDictionary<SerializedType, MultiplayerRoleFlags> m_CustomComponentsList;
private SerializedDictionary<SerializedType, MultiplayerRoleFlags> CustomComponentsList
{
get
{
if (m_CustomComponentsList == null)
m_CustomComponentsList = new();
return m_CustomComponentsList;
}
set
{
m_CustomComponentsList = value;
BakeCompleteComponentsList();
}
}
public Dictionary<Type, MultiplayerRoleFlags> GetCustomComponents()
{
var dictionary = new Dictionary<Type, MultiplayerRoleFlags>();
foreach (var kvp in CustomComponentsList)
{
// This will happen if the script was deleted.
if (kvp.Key.Value == null)
continue;
dictionary[kvp.Key.Value] = kvp.Value;
}
return dictionary;
}
public void SetCustomComponents(Dictionary<Type, MultiplayerRoleFlags> customComponents)
{
CustomComponentsList.Clear();
if (customComponents != null)
foreach (var kvp in customComponents)
SetCustomComponentMultiplayerRoleFlags(kvp.Key, kvp.Value, false);
BakeCompleteComponentsList();
}
public MultiplayerRoleFlags GetMultiplayerRoleMaskForComponentType(Type type)
=> GetMultiplayerRoleFlagsForType(type);
public void SetMultiplayerRoleMaskForComponentType(Type type, MultiplayerRoleFlags mask)
=> SetCustomComponentMultiplayerRoleFlags(type, mask, true);
internal void SetCustomComponentMultiplayerRoleFlags(Type type, MultiplayerRoleFlags target, bool bake = true)
{
if (!type.IsSubclassOf(typeof(Component)))
throw new ArgumentException("Only subclasses of Component can be selected.");
if (target == MultiplayerRoleFlags.ClientAndServer)
CustomComponentsList.Remove(new SerializedType(type));
else
CustomComponentsList[new SerializedType(type)] = target;
if (bake)
BakeCompleteComponentsList();
}
internal AutomaticSelectionOptions Clone()
{
var options = this;
options.m_CustomComponentsList = null;
options.m_CompleteComponentsList = null;
options.SetCustomComponents(this.GetCustomComponents());
return options;
}
internal static void GetBuiltinStrippingComponentsForServer(in AutomaticSelectionOptions options, List<Type> types)
{
if (options.StripRenderingComponents)
{
var components = TypeCache.GetTypesDerivedFrom<Renderer>()
.Concat(new[]
{
typeof(Camera),
typeof(Light),
typeof(ReflectionProbe),
typeof(LightProbeGroup),
typeof(LightProbeProxyVolume)
});
#if UNITY_RENDER_PIPELINE_PRESENT
components = components.Concat(TypeCache.GetTypesDerivedFrom<UnityEngine.Rendering.IAdditionalData>());
#endif
foreach (var component in components)
types.Add(component);
}
if (options.StripUIComponents)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where
(
a =>
a.GetName().Name == "UnityEngine.UI" ||
a.GetName().Name == "UnityEngine.Canvas" ||
a.GetName().Name == "UnityEngine.UIElementsModule"
);
var components = assemblies.SelectMany(a => a.GetTypes().Where(t => IsClassOrSubclassOf(t, typeof(Component))));
foreach (var component in components)
types.Add(component);
}
if (options.StripAudioComponents)
{
var assembly = typeof(AudioClip).Assembly;
var components = assembly.GetTypes().Where(t => IsClassOrSubclassOf(t, typeof(Component)));
foreach (var component in components)
types.Add(component);
}
}
private void BakeCompleteComponentsList()
{
if (m_CompleteComponentsList == null)
m_CompleteComponentsList = new();
m_CompleteComponentsList.Clear();
var builtinServerTypes = new List<Type>();
GetBuiltinStrippingComponentsForServer(this, builtinServerTypes);
foreach (var type in builtinServerTypes)
{
m_CompleteComponentsList[type] = MultiplayerRoleFlags.ClientAndServer & ~MultiplayerRoleFlags.Server;
}
foreach (var component in CustomComponentsList)
{
if (component.Key.Value == null)
continue;
if (!m_CompleteComponentsList.TryGetValue(component.Key.Value, out var maskValue))
maskValue = MultiplayerRoleFlags.ClientAndServer;
maskValue &= component.Value;
m_CompleteComponentsList[component.Key.Value] = maskValue;
}
}
internal static bool IsClassOrSubclassOf(Type type, Type parentType)
=> type == parentType || type.IsSubclassOf(parentType);
internal bool IsComponentSelected(Type type)
=> CompleteComponentsList.Keys.Any(selectedType => IsClassOrSubclassOf(type, selectedType));
internal IEnumerable<KeyValuePair<Type, MultiplayerRoleFlags>> GetSelectedParentComponents(Type type)
=> CompleteComponentsList.Where(selectionValue => AutomaticSelectionOptions.IsClassOrSubclassOf(type, selectionValue.Key));
internal MultiplayerRoleFlags GetMultiplayerRoleFlagsForType(Type type)
{
if (!CompleteComponentsList.TryGetValue(type, out var target))
target = MultiplayerRoleFlags.ClientAndServer;
return target;
}
internal MultiplayerRoleFlags GetInheritMultiplayerRoleFlagsForType(System.Type type)
{
var parentTypes = CompleteComponentsList.Where(kvp => IsClassOrSubclassOf(type, kvp.Key));
var target = MultiplayerRoleFlags.ClientAndServer;
foreach (var item in parentTypes)
target &= item.Value;
return target;
}
}
}