using System; using System.Linq; using Barotrauma.Items.Components; namespace Barotrauma; [AttributeUsage(AttributeTargets.Property)] sealed class ConditionallyEditable : Editable { public ConditionallyEditable(ConditionType conditionType, bool onlyInEditors = true) { this.conditionType = conditionType; this.onlyInEditors = onlyInEditors; } private readonly ConditionType conditionType; private readonly bool onlyInEditors; public enum ConditionType { //These need to exist at compile time, so it is a little awkward //I would love to see a better way to do this AllowLinkingWifiToChat, IsSwappableItem, AllowRotating, Attachable, /// /// Does the entity currently have a physics body? /// HasBody, /// /// Does the entity normally have a physics body? Can be used if a property should be enabled on a wall whose collisions have been disabled. /// HasBodyByDefault, Pickable, OnlyByStatusEffectsAndNetwork, HasIntegratedButtons, IsToggleableController, HasConnectionPanel, DeteriorateUnderStress, ReceivesSubmarineImpacts } public bool IsEditable(ISerializableEntity entity) { if (onlyInEditors && Screen.Selected is { IsEditor: false }) { return false; } return conditionType switch { ConditionType.AllowLinkingWifiToChat => GameMain.NetworkMember is not { ServerSettings.AllowLinkingWifiToChat: false }, ConditionType.IsSwappableItem => entity is Item item && item.Prefab.SwappableItem != null, ConditionType.AllowRotating => (entity is Item item && (item.body == null || item.body.BodyType == FarseerPhysics.BodyType.Static) && item.Prefab.AllowRotatingInEditor) || (entity is Structure structure && structure.Prefab.AllowRotatingInEditor), ConditionType.Attachable => GetComponent(entity) is Holdable { Attachable: true }, ConditionType.HasBody => entity is Structure { HasBody: true } or Item { body: not null }, ConditionType.HasBodyByDefault => entity is Structure { Prefab.Body: true } or Item { body: not null }, ConditionType.Pickable => entity is Item item && item.GetComponent() != null, ConditionType.OnlyByStatusEffectsAndNetwork => GameMain.NetworkMember is { IsServer: true }, ConditionType.HasIntegratedButtons => GetComponent(entity) is { HasIntegratedButtons: true }, ConditionType.IsToggleableController => GetComponent(entity) is Controller { IsToggle: true } controller && controller.Item.GetComponent() != null, ConditionType.HasConnectionPanel => GetComponent(entity) != null, ConditionType.DeteriorateUnderStress => entity is Item repairableItem && repairableItem.Components.Any(c => c is IDeteriorateUnderStress), ConditionType.ReceivesSubmarineImpacts => entity is Item { Prefab.ReceiveSubmarineImpacts: true }, _ => false }; static T GetComponent(ISerializableEntity e) where T : ItemComponent { if (e is T t) { return t; } if (e is Item item) { return item.GetComponent(); } if (e is ItemComponent ic) { return ic.Item.GetComponent(); } return null; } } }