using System; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces.GameObjects; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Inventory; using SS14.Server.GameObjects; using SS14.Server.GameObjects.Components.Container; using SS14.Server.GameObjects.EntitySystems; using SS14.Shared.Audio; using SS14.Shared.Enums; using SS14.Shared.GameObjects; using SS14.Shared.Interfaces.GameObjects; using SS14.Shared.Interfaces.Timing; using SS14.Shared.IoC; using SS14.Shared.Log; using SS14.Shared.Map; using SS14.Shared.Serialization; using SS14.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Power { /// /// Component that represents a wall light. It has a light bulb that can be replaced when broken. /// public class PoweredLightComponent : Component, IAttackHand, IAttackby { public override string Name => "PoweredLight"; private static readonly TimeSpan _thunkDelay = TimeSpan.FromSeconds(2); private TimeSpan _lastThunk; private LightBulbType BulbType = LightBulbType.Tube; [ViewVariables] private float Load = 40; [ViewVariables] private ContainerSlot _lightBulbContainer; [ViewVariables] private LightBulbComponent LightBulb { get { if (_lightBulbContainer.ContainedEntity == null) return null; _lightBulbContainer.ContainedEntity.TryGetComponent(out LightBulbComponent bulb); return bulb; } } bool IAttackby.Attackby(IEntity user, IEntity attackwith) { return InsertBulb(attackwith); } bool IAttackHand.Attackhand(IEntity user) { if (user.GetComponent().GetSlotItem(EquipmentSlotDefines.Slots.GLOVES) != null) { EjectBulb(user); UpdateLight(); return true; } if (!user.TryGetComponent(out DamageableComponent damageableComponent)) return false; damageableComponent.TakeDamage(DamageType.Heat, 20); return true; } /// /// Inserts the bulb if possible. /// /// True if it could insert it, false if it couldn't. private bool InsertBulb(IEntity bulb) { if (LightBulb != null) return false; if (!bulb.TryGetComponent(out LightBulbComponent lightBulb)) return false; if (lightBulb.Type != BulbType) return false; var inserted = _lightBulbContainer.Insert(bulb); lightBulb.OnLightBulbStateChange += UpdateLight; lightBulb.OnLightColorChange += UpdateLight; UpdateLight(); return inserted; } /// /// Ejects the bulb to a mob's hand if possible. /// private void EjectBulb(IEntity user) { if (LightBulb == null) return; var bulb = LightBulb; bulb.OnLightBulbStateChange -= UpdateLight; bulb.OnLightColorChange -= UpdateLight; if (!_lightBulbContainer.Remove(bulb.Owner)) return; if (!user.TryGetComponent(out HandsComponent hands) || !hands.PutInHand(bulb.Owner.GetComponent())) bulb.Owner.Transform.GridPosition = user.Transform.GridPosition; } public override void ExposeData(ObjectSerializer serializer) { serializer.DataField(ref Load, "load", 40); serializer.DataField(ref BulbType, "bulb", LightBulbType.Tube); } /// /// For attaching UpdateLight() to events. /// public void UpdateLight(object sender, EventArgs e) { UpdateLight(); } /// /// Updates the light's power drain, sprite and actual light state. /// public void UpdateLight() { var device = Owner.GetComponent(); var sprite = Owner.GetComponent(); var light = Owner.GetComponent(); if (LightBulb == null) // No light bulb. { device.Load = 0; sprite.LayerSetState(0, "empty"); light.State = LightState.Off; return; } switch (LightBulb.State) { case LightBulbState.Normal: device.Load = Load; if (device.Powered) { sprite.LayerSetState(0, "on"); light.State = LightState.On; light.Color = LightBulb.Color; var time = IoCManager.Resolve().CurTime; if (time > _lastThunk + _thunkDelay) { _lastThunk = time; IoCManager.Resolve().GetEntitySystem() .Play("/Audio/machines/light_tube_on.ogg", Owner, AudioParams.Default.WithVolume(-10f)); } } else { sprite.LayerSetState(0, "off"); light.State = LightState.Off; } break; case LightBulbState.Broken: device.Load = 0; sprite.LayerSetState(0, "broken"); light.State = LightState.Off; break; case LightBulbState.Burned: device.Load = 0; sprite.LayerSetState(0, "burned"); light.State = LightState.Off; break; } } public override void Initialize() { base.Initialize(); var device = Owner.GetComponent(); device.OnPowerStateChanged += UpdateLight; _lightBulbContainer = ContainerManagerComponent.Ensure("light_bulb", Owner, out var existed); if (!existed) // Insert a light tube if there wasn't any. { switch (BulbType) { case LightBulbType.Tube: _lightBulbContainer.Insert(Owner.EntityManager.SpawnEntity("LightTube")); break; case LightBulbType.Bulb: _lightBulbContainer.Insert(Owner.EntityManager.SpawnEntity("LightBulb")); break; } } } } }