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