Moves HumanoidAppearanceComponent to ECS (#4855)
* Moves HumanoidCharacterAppearance to ECS * Makes HumanoidAppearanceSystem work over networks * Makes HumanoidAppearanceSystem more efficient * Cleans up the files * Updates privacy on a couple of functions * Fixes a few using references, renames a file * Makes HumanoidAppearanceSystem more cleaner * Fixes Magic Mirror * Cleanup * HumanoidAppearanceComponent now has a friend SharedHumanoidAppearanceSystem is only allowed to act on this, now * Fixes the Body-HumanoidAppearance ECS scaffolding * a little cleanup never hurt anybody * quick fix for magic mirror appearance access * Replaces a networked event with a local one This one was... causing bugs
This commit is contained in:
@@ -1,85 +1,61 @@
|
|||||||
using Content.Client.Cuffs.Components;
|
using Content.Client.Cuffs.Components;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Body.Part;
|
|
||||||
using Content.Shared.CharacterAppearance;
|
using Content.Shared.CharacterAppearance;
|
||||||
using Content.Shared.CharacterAppearance.Components;
|
using Content.Shared.CharacterAppearance.Components;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Client.CharacterAppearance
|
namespace Content.Client.CharacterAppearance.Systems
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
public class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||||
public sealed class HumanoidAppearanceComponent : SharedHumanoidAppearanceComponent, IBodyPartAdded, IBodyPartRemoved
|
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SpriteAccessoryManager _accessoryManager = default!;
|
[Dependency] private readonly SpriteAccessoryManager _accessoryManager = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
public override HumanoidCharacterAppearance Appearance
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
get => base.Appearance;
|
base.Initialize();
|
||||||
set
|
|
||||||
{
|
SubscribeLocalEvent<HumanoidAppearanceComponent, ChangedHumanoidAppearanceEvent>(UpdateLooks);
|
||||||
base.Appearance = value;
|
SubscribeLocalEvent<HumanoidAppearanceBodyPartAddedEvent>(BodyPartAdded);
|
||||||
UpdateLooks();
|
SubscribeLocalEvent<HumanoidAppearanceBodyPartRemovedEvent>(BodyPartRemoved);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Sex Sex
|
private void UpdateLooks(EntityUid uid, HumanoidAppearanceComponent component, ChangedHumanoidAppearanceEvent args)
|
||||||
{
|
{
|
||||||
get => base.Sex;
|
if(!EntityManager.TryGetComponent(uid, out SpriteComponent? sprite))
|
||||||
set
|
|
||||||
{
|
|
||||||
base.Sex = value;
|
|
||||||
UpdateLooks();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Startup()
|
|
||||||
{
|
|
||||||
base.Startup();
|
|
||||||
|
|
||||||
UpdateLooks();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateLooks()
|
|
||||||
{
|
|
||||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
|
||||||
if (Appearance == null ||
|
|
||||||
!Owner.TryGetComponent(out SpriteComponent? sprite))
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out SharedBodyComponent? body))
|
if (EntityManager.TryGetComponent(uid, out SharedBodyComponent? body))
|
||||||
{
|
{
|
||||||
foreach (var (part, _) in body.Parts)
|
foreach (var (part, _) in body.Parts)
|
||||||
{
|
{
|
||||||
if (!part.Owner.TryGetComponent(out SpriteComponent? partSprite))
|
if (part.Owner.TryGetComponent(out SpriteComponent? partSprite))
|
||||||
{
|
{
|
||||||
continue;
|
partSprite!.Color = component.Appearance.SkinColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
partSprite.Color = Appearance.SkinColor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite.LayerSetColor(HumanoidVisualLayers.Hair,
|
sprite.LayerSetColor(HumanoidVisualLayers.Hair,
|
||||||
CanColorHair ? Appearance.HairColor : Color.White);
|
component.CanColorHair ? component.Appearance.HairColor : Color.White);
|
||||||
sprite.LayerSetColor(HumanoidVisualLayers.FacialHair,
|
sprite.LayerSetColor(HumanoidVisualLayers.FacialHair,
|
||||||
CanColorFacialHair ? Appearance.FacialHairColor : Color.White);
|
component.CanColorFacialHair ? component.Appearance.FacialHairColor : Color.White);
|
||||||
|
|
||||||
sprite.LayerSetColor(HumanoidVisualLayers.Eyes, Appearance.EyeColor);
|
sprite.LayerSetColor(HumanoidVisualLayers.Eyes, component.Appearance.EyeColor);
|
||||||
|
|
||||||
sprite.LayerSetState(HumanoidVisualLayers.Chest, Sex == Sex.Male ? "torso_m" : "torso_f");
|
sprite.LayerSetState(HumanoidVisualLayers.Chest, component.Sex == Sex.Male ? "torso_m" : "torso_f");
|
||||||
sprite.LayerSetState(HumanoidVisualLayers.Head, Sex == Sex.Male ? "head_m" : "head_f");
|
sprite.LayerSetState(HumanoidVisualLayers.Head, component.Sex == Sex.Male ? "head_m" : "head_f");
|
||||||
|
|
||||||
if (sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out _))
|
if (sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out _))
|
||||||
sprite.LayerSetVisible(HumanoidVisualLayers.StencilMask, Sex == Sex.Female);
|
sprite.LayerSetVisible(HumanoidVisualLayers.StencilMask, component.Sex == Sex.Female);
|
||||||
|
|
||||||
if (Owner.TryGetComponent<CuffableComponent>(out var cuffed))
|
if (EntityManager.TryGetComponent<CuffableComponent>(uid, out var cuffed))
|
||||||
{
|
{
|
||||||
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, !cuffed.CanStillInteract);
|
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, !cuffed.CanStillInteract);
|
||||||
}
|
}
|
||||||
@@ -88,16 +64,16 @@ namespace Content.Client.CharacterAppearance
|
|||||||
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, false);
|
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var hairStyle = Appearance.HairStyleId;
|
var hairStyle = component.Appearance.HairStyleId;
|
||||||
if (string.IsNullOrWhiteSpace(hairStyle) ||
|
if (string.IsNullOrWhiteSpace(hairStyle) ||
|
||||||
!_accessoryManager.IsValidAccessoryInCategory(hairStyle, CategoriesHair))
|
!_accessoryManager.IsValidAccessoryInCategory(hairStyle, component.CategoriesHair))
|
||||||
{
|
{
|
||||||
hairStyle = HairStyles.DefaultHairStyle;
|
hairStyle = HairStyles.DefaultHairStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
var facialHairStyle = Appearance.FacialHairStyleId;
|
var facialHairStyle = component.Appearance.FacialHairStyleId;
|
||||||
if (string.IsNullOrWhiteSpace(facialHairStyle) ||
|
if (string.IsNullOrWhiteSpace(facialHairStyle) ||
|
||||||
!_accessoryManager.IsValidAccessoryInCategory(facialHairStyle, CategoriesFacialHair))
|
!_accessoryManager.IsValidAccessoryInCategory(facialHairStyle, component.CategoriesFacialHair))
|
||||||
{
|
{
|
||||||
facialHairStyle = HairStyles.DefaultFacialHairStyle;
|
facialHairStyle = HairStyles.DefaultFacialHairStyle;
|
||||||
}
|
}
|
||||||
@@ -109,37 +85,40 @@ namespace Content.Client.CharacterAppearance
|
|||||||
sprite.LayerSetSprite(HumanoidVisualLayers.FacialHair, facialHairPrototype.Sprite);
|
sprite.LayerSetSprite(HumanoidVisualLayers.FacialHair, facialHairPrototype.Sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BodyPartAdded(BodyPartAddedEventArgs args)
|
// Scaffolding until Body is moved to ECS.
|
||||||
|
private void BodyPartAdded(HumanoidAppearanceBodyPartAddedEvent args)
|
||||||
{
|
{
|
||||||
if (!Owner.TryGetComponent(out SpriteComponent? sprite))
|
if(!EntityManager.TryGetEntity(args.Uid, out var owner)) return;
|
||||||
|
if (!owner.TryGetComponent(out SpriteComponent? sprite))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.Part.Owner.HasComponent<SpriteComponent>())
|
if (!args.Args.Part.Owner.HasComponent<SpriteComponent>())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var layers = args.Part.ToHumanoidLayers();
|
var layers = args.Args.Part.ToHumanoidLayers();
|
||||||
// TODO BODY Layer color, sprite and state
|
// TODO BODY Layer color, sprite and state
|
||||||
foreach (var layer in layers)
|
foreach (var layer in layers)
|
||||||
sprite.LayerSetVisible(layer, true);
|
sprite.LayerSetVisible(layer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BodyPartRemoved(BodyPartRemovedEventArgs args)
|
private void BodyPartRemoved(HumanoidAppearanceBodyPartRemovedEvent args)
|
||||||
{
|
{
|
||||||
if (!Owner.TryGetComponent(out SpriteComponent? sprite))
|
if(!EntityManager.TryGetEntity(args.Uid, out var owner)) return;
|
||||||
|
if (!owner.TryGetComponent(out SpriteComponent? sprite))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.Part.Owner.HasComponent<SpriteComponent>())
|
if (!args.Args.Part.Owner.HasComponent<SpriteComponent>())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var layers = args.Part.ToHumanoidLayers();
|
var layers = args.Args.Part.ToHumanoidLayers();
|
||||||
// TODO BODY Layer color, sprite and state
|
// TODO BODY Layer color, sprite and state
|
||||||
foreach (var layer in layers)
|
foreach (var layer in layers)
|
||||||
sprite.LayerSetVisible(layer, false);
|
sprite.LayerSetVisible(layer, false);
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Client.CharacterAppearance;
|
|
||||||
using Content.Client.HUD.UI;
|
using Content.Client.HUD.UI;
|
||||||
using Content.Client.Inventory;
|
using Content.Client.Inventory;
|
||||||
using Content.Client.Preferences;
|
using Content.Client.Preferences;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
@@ -130,9 +130,7 @@ namespace Content.Client.Lobby.UI
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_summaryLabel.Text = selectedCharacter.Summary;
|
_summaryLabel.Text = selectedCharacter.Summary;
|
||||||
var component = _previewDummy.GetComponent<HumanoidAppearanceComponent>();
|
EntitySystem.Get<SharedHumanoidAppearanceSystem>().UpdateFromProfile(_previewDummy.Uid, selectedCharacter);
|
||||||
component.UpdateFromProfile(selectedCharacter);
|
|
||||||
|
|
||||||
GiveDummyJobClothes(_previewDummy, selectedCharacter);
|
GiveDummyJobClothes(_previewDummy, selectedCharacter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Client.CharacterAppearance;
|
|
||||||
using Content.Client.Info;
|
using Content.Client.Info;
|
||||||
using Content.Client.Lobby.UI;
|
using Content.Client.Lobby.UI;
|
||||||
using Content.Client.Parallax;
|
using Content.Client.Parallax;
|
||||||
using Content.Client.Resources;
|
using Content.Client.Resources;
|
||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
@@ -157,7 +157,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
Group = group;
|
Group = group;
|
||||||
|
|
||||||
_previewDummy = entityManager.SpawnEntity("MobHumanDummy", MapCoordinates.Nullspace);
|
_previewDummy = entityManager.SpawnEntity("MobHumanDummy", MapCoordinates.Nullspace);
|
||||||
_previewDummy.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(profile);
|
EntitySystem.Get<SharedHumanoidAppearanceSystem>().UpdateFromProfile(_previewDummy.Uid, profile);
|
||||||
var humanoid = profile as HumanoidCharacterProfile;
|
var humanoid = profile as HumanoidCharacterProfile;
|
||||||
if (humanoid != null)
|
if (humanoid != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Client.Lobby.UI;
|
|||||||
using Content.Client.Message;
|
using Content.Client.Message;
|
||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
using Content.Shared.CharacterAppearance;
|
using Content.Shared.CharacterAppearance;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
@@ -596,7 +597,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
if (Profile is null)
|
if (Profile is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_previewDummy.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(Profile);
|
EntitySystem.Get<SharedHumanoidAppearanceSystem>().UpdateFromProfile(_previewDummy.Uid, Profile);
|
||||||
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, Profile);
|
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, Profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using Content.Server.CharacterAppearance.Components;
|
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.Actions.Behaviors;
|
using Content.Shared.Actions.Behaviors;
|
||||||
using Content.Shared.Actions.Components;
|
using Content.Shared.Actions.Components;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.CharacterAppearance;
|
using Content.Shared.CharacterAppearance;
|
||||||
|
using Content.Shared.CharacterAppearance.Components;
|
||||||
using Content.Shared.Cooldown;
|
using Content.Shared.Cooldown;
|
||||||
using Content.Shared.Sound;
|
using Content.Shared.Sound;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
using Content.Shared.Body.Components;
|
|
||||||
using Content.Shared.CharacterAppearance;
|
|
||||||
using Content.Shared.CharacterAppearance.Components;
|
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Server.CharacterAppearance.Components
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class HumanoidAppearanceComponent : SharedHumanoidAppearanceComponent
|
|
||||||
{
|
|
||||||
public override HumanoidCharacterAppearance Appearance
|
|
||||||
{
|
|
||||||
get => base.Appearance;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
base.Appearance = value;
|
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out SharedBodyComponent? body))
|
|
||||||
{
|
|
||||||
foreach (var (part, _) in body.Parts)
|
|
||||||
{
|
|
||||||
if (!part.Owner.TryGetComponent(out SpriteComponent? sprite))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprite.Color = value.SkinColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Startup()
|
|
||||||
{
|
|
||||||
base.Startup();
|
|
||||||
|
|
||||||
if (Appearance != null! && Owner.TryGetComponent(out SharedBodyComponent? body))
|
|
||||||
{
|
|
||||||
foreach (var (part, _) in body.Parts)
|
|
||||||
{
|
|
||||||
if (!part.Owner.TryGetComponent(out SpriteComponent? sprite))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprite.Color = Appearance.SkinColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.CharacterAppearance.Systems;
|
||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
using Content.Shared.CharacterAppearance;
|
using Content.Shared.CharacterAppearance;
|
||||||
using Content.Shared.CharacterAppearance.Components;
|
using Content.Shared.CharacterAppearance.Components;
|
||||||
@@ -89,6 +90,8 @@ namespace Content.Server.CharacterAppearance.Components
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntitySystem.Get<HumanoidAppearanceSystem>().ForceAppearanceUpdate(obj.Session.AttachedEntity.Uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using Content.Shared.Body.Components;
|
||||||
|
using Content.Shared.CharacterAppearance.Components;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.CharacterAppearance.Systems
|
||||||
|
{
|
||||||
|
public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<HumanoidAppearanceComponent, ChangedHumanoidAppearanceEvent>(UpdateSkinColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSkinColor(EntityUid uid, HumanoidAppearanceComponent component, ChangedHumanoidAppearanceEvent _)
|
||||||
|
{
|
||||||
|
if (EntityManager.TryGetComponent<SharedBodyComponent>(uid, out SharedBodyComponent? body))
|
||||||
|
{
|
||||||
|
foreach (var (part, _) in body.Parts)
|
||||||
|
{
|
||||||
|
if (part.Owner.TryGetComponent(out SpriteComponent? sprite))
|
||||||
|
{
|
||||||
|
sprite!.Color = component.Appearance.SkinColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using Content.Server.EUI;
|
|||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
using Content.Shared.Cloning;
|
using Content.Shared.Cloning;
|
||||||
using Content.Shared.MobState;
|
using Content.Shared.MobState;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
@@ -136,7 +137,8 @@ namespace Content.Server.Cloning.Components
|
|||||||
|
|
||||||
var mob = Owner.EntityManager.SpawnEntity("MobHuman", Owner.Transform.MapPosition);
|
var mob = Owner.EntityManager.SpawnEntity("MobHuman", Owner.Transform.MapPosition);
|
||||||
|
|
||||||
mob.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(dna.Profile);
|
|
||||||
|
EntitySystem.Get<SharedHumanoidAppearanceSystem>().UpdateFromProfile(mob.Uid, dna.Profile);
|
||||||
mob.Name = dna.Profile.Name;
|
mob.Name = dna.Profile.Name;
|
||||||
|
|
||||||
var cloneMindReturn = mob.AddComponent<BeingClonedComponent>();
|
var cloneMindReturn = mob.AddComponent<BeingClonedComponent>();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Content.Server.Access.Components;
|
using Content.Server.Access.Components;
|
||||||
using Content.Server.CharacterAppearance.Components;
|
|
||||||
using Content.Server.Ghost.Components;
|
using Content.Server.Ghost.Components;
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Inventory.Components;
|
using Content.Server.Inventory.Components;
|
||||||
@@ -12,6 +11,7 @@ using Content.Server.Players;
|
|||||||
using Content.Server.Roles;
|
using Content.Server.Roles;
|
||||||
using Content.Server.Spawners.Components;
|
using Content.Server.Spawners.Components;
|
||||||
using Content.Server.Speech.Components;
|
using Content.Server.Speech.Components;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
using Content.Shared.GameTicking;
|
using Content.Shared.GameTicking;
|
||||||
using Content.Shared.Ghost;
|
using Content.Shared.Ghost;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
@@ -171,7 +171,7 @@ namespace Content.Server.GameTicking
|
|||||||
|
|
||||||
if (profile != null)
|
if (profile != null)
|
||||||
{
|
{
|
||||||
entity.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(profile);
|
EntitySystem.Get<SharedHumanoidAppearanceSystem>().UpdateFromProfile(entity.Uid, profile);
|
||||||
entity.Name = profile.Name;
|
entity.Name = profile.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Content.Shared.Body.Part.Property;
|
|||||||
using Content.Shared.Body.Preset;
|
using Content.Shared.Body.Preset;
|
||||||
using Content.Shared.Body.Slot;
|
using Content.Shared.Body.Slot;
|
||||||
using Content.Shared.Body.Template;
|
using Content.Shared.Body.Template;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Damage.Prototypes;
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
@@ -151,6 +152,7 @@ namespace Content.Shared.Body.Components
|
|||||||
|
|
||||||
var argsAdded = new BodyPartAddedEventArgs(slot.Id, part);
|
var argsAdded = new BodyPartAddedEventArgs(slot.Id, part);
|
||||||
|
|
||||||
|
EntitySystem.Get<SharedHumanoidAppearanceSystem>().BodyPartAdded(Owner.Uid, argsAdded);
|
||||||
foreach (var component in Owner.GetAllComponents<IBodyPartAdded>().ToArray())
|
foreach (var component in Owner.GetAllComponents<IBodyPartAdded>().ToArray())
|
||||||
{
|
{
|
||||||
component.BodyPartAdded(argsAdded);
|
component.BodyPartAdded(argsAdded);
|
||||||
@@ -177,6 +179,8 @@ namespace Content.Shared.Body.Components
|
|||||||
|
|
||||||
var args = new BodyPartRemovedEventArgs(slot.Id, part);
|
var args = new BodyPartRemovedEventArgs(slot.Id, part);
|
||||||
|
|
||||||
|
|
||||||
|
EntitySystem.Get<SharedHumanoidAppearanceSystem>().BodyPartRemoved(Owner.Uid, args);
|
||||||
foreach (var component in Owner.GetAllComponents<IBodyPartRemoved>())
|
foreach (var component in Owner.GetAllComponents<IBodyPartRemoved>())
|
||||||
{
|
{
|
||||||
component.BodyPartRemoved(args);
|
component.BodyPartRemoved(args);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Body.Part
|
namespace Content.Shared.Body.Part
|
||||||
{
|
{
|
||||||
@@ -17,6 +18,8 @@ namespace Content.Shared.Body.Part
|
|||||||
void BodyPartAdded(BodyPartAddedEventArgs args);
|
void BodyPartAdded(BodyPartAddedEventArgs args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
public class BodyPartAddedEventArgs : EventArgs
|
public class BodyPartAddedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public BodyPartAddedEventArgs(string slot, SharedBodyPartComponent part)
|
public BodyPartAddedEventArgs(string slot, SharedBodyPartComponent part)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Body.Part
|
namespace Content.Shared.Body.Part
|
||||||
{
|
{
|
||||||
@@ -16,6 +17,7 @@ namespace Content.Shared.Body.Part
|
|||||||
void BodyPartRemoved(BodyPartRemovedEventArgs args);
|
void BodyPartRemoved(BodyPartRemovedEventArgs args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
public class BodyPartRemovedEventArgs : EventArgs
|
public class BodyPartRemovedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public BodyPartRemovedEventArgs(string slot, SharedBodyPartComponent part)
|
public BodyPartRemovedEventArgs(string slot, SharedBodyPartComponent part)
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Shared.CharacterAppearance;
|
||||||
|
using Content.Shared.CharacterAppearance.Systems;
|
||||||
|
using Robust.Shared.Analyzers;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Shared.CharacterAppearance.Components
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
[Friend(typeof(SharedHumanoidAppearanceSystem), typeof(SharedMagicMirrorComponent))]
|
||||||
|
[NetworkedComponent]
|
||||||
|
public class HumanoidAppearanceComponent : Component
|
||||||
|
{
|
||||||
|
public override string Name => "HumanoidAppearance";
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public HumanoidCharacterAppearance Appearance { get; set; } = HumanoidCharacterAppearance.Default();
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public Sex Sex { get; set; } = default!;
|
||||||
|
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public Gender Gender { get; set; } = default!;
|
||||||
|
|
||||||
|
[DataField("categoriesHair")]
|
||||||
|
[ViewVariables]
|
||||||
|
public SpriteAccessoryCategories CategoriesHair { get; set; } = SpriteAccessoryCategories.HumanHair;
|
||||||
|
|
||||||
|
[DataField("categoriesFacialHair")]
|
||||||
|
[ViewVariables]
|
||||||
|
public SpriteAccessoryCategories CategoriesFacialHair { get; set; } = SpriteAccessoryCategories.HumanFacialHair;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("canColorHair")]
|
||||||
|
public bool CanColorHair { get; set; } = true;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("canColorFacialHair")]
|
||||||
|
public bool CanColorFacialHair { get; set; } = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class HumanoidAppearanceComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public HumanoidCharacterAppearance Appearance { get; }
|
||||||
|
public Sex Sex { get; }
|
||||||
|
public Gender Gender { get; }
|
||||||
|
|
||||||
|
public HumanoidAppearanceComponentState(HumanoidCharacterAppearance appearance,
|
||||||
|
Sex sex,
|
||||||
|
Gender gender)
|
||||||
|
{
|
||||||
|
Appearance = appearance;
|
||||||
|
Sex = sex;
|
||||||
|
Gender = gender;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Content.Shared.Preferences;
|
|
||||||
using Robust.Shared.Enums;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.GameObjects.Components.Localization;
|
|
||||||
using Robust.Shared.GameStates;
|
|
||||||
using Robust.Shared.Players;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
using Robust.Shared.Serialization.Manager.Attributes;
|
|
||||||
using Robust.Shared.ViewVariables;
|
|
||||||
|
|
||||||
namespace Content.Shared.CharacterAppearance.Components
|
|
||||||
{
|
|
||||||
[NetworkedComponent()]
|
|
||||||
public abstract class SharedHumanoidAppearanceComponent : Component
|
|
||||||
{
|
|
||||||
private HumanoidCharacterAppearance _appearance = HumanoidCharacterAppearance.Default();
|
|
||||||
private Sex _sex;
|
|
||||||
private Gender _gender;
|
|
||||||
|
|
||||||
public sealed override string Name => "HumanoidAppearance";
|
|
||||||
|
|
||||||
[DataField("categoriesHair")]
|
|
||||||
[ViewVariables]
|
|
||||||
public SpriteAccessoryCategories CategoriesHair { get; set; } = SpriteAccessoryCategories.HumanHair;
|
|
||||||
|
|
||||||
[DataField("categoriesFacialHair")]
|
|
||||||
[ViewVariables]
|
|
||||||
public SpriteAccessoryCategories CategoriesFacialHair { get; set; } = SpriteAccessoryCategories.HumanFacialHair;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
[DataField("canColorHair")]
|
|
||||||
public bool CanColorHair { get; set; } = true;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
[DataField("canColorFacialHair")]
|
|
||||||
public bool CanColorFacialHair { get; set; } = true;
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public virtual HumanoidCharacterAppearance Appearance
|
|
||||||
{
|
|
||||||
get => _appearance;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_appearance = value;
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public virtual Sex Sex
|
|
||||||
{
|
|
||||||
get => _sex;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_sex = value;
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
|
||||||
public virtual Gender Gender
|
|
||||||
{
|
|
||||||
get => _gender;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_gender = value;
|
|
||||||
|
|
||||||
if (Owner.TryGetComponent(out GrammarComponent? g))
|
|
||||||
{
|
|
||||||
g.Gender = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ComponentState GetComponentState(ICommonSession player)
|
|
||||||
{
|
|
||||||
return new HumanoidAppearanceComponentState(Appearance, Sex, Gender);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
|
||||||
{
|
|
||||||
base.HandleComponentState(curState, nextState);
|
|
||||||
|
|
||||||
if (curState is not HumanoidAppearanceComponentState cast)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Appearance = cast.Appearance;
|
|
||||||
Sex = cast.Sex;
|
|
||||||
Gender = cast.Gender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateFromProfile(ICharacterProfile profile)
|
|
||||||
{
|
|
||||||
var humanoid = (HumanoidCharacterProfile) profile;
|
|
||||||
Appearance = (HumanoidCharacterAppearance) humanoid.CharacterAppearance;
|
|
||||||
Sex = humanoid.Sex;
|
|
||||||
Gender = humanoid.Gender;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
[NetSerializable]
|
|
||||||
private sealed class HumanoidAppearanceComponentState : ComponentState
|
|
||||||
{
|
|
||||||
public HumanoidAppearanceComponentState(HumanoidCharacterAppearance appearance, Sex sex, Gender gender)
|
|
||||||
{
|
|
||||||
Appearance = appearance;
|
|
||||||
Sex = sex;
|
|
||||||
Gender = gender;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HumanoidCharacterAppearance Appearance { get; }
|
|
||||||
public Sex Sex { get; }
|
|
||||||
public Gender Gender { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
using System;
|
||||||
|
using Content.Shared.Body.Part;
|
||||||
|
using Content.Shared.CharacterAppearance.Components;
|
||||||
|
using Content.Shared.Preferences;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.CharacterAppearance.Systems
|
||||||
|
{
|
||||||
|
public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<HumanoidAppearanceComponent, ComponentGetState>(OnAppearanceGetState);
|
||||||
|
SubscribeLocalEvent<HumanoidAppearanceComponent, ComponentHandleState>(OnAppearanceHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateFromProfile(EntityUid uid, ICharacterProfile profile)
|
||||||
|
{
|
||||||
|
var humanoid = (HumanoidCharacterProfile) profile;
|
||||||
|
UpdateAppearance(uid, humanoid.Appearance, humanoid.Sex, humanoid.Gender);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The magic mirror otherwise wouldn't work. (it directly modifies the component server-side)
|
||||||
|
public void ForceAppearanceUpdate(EntityUid uid, HumanoidAppearanceComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component)) return;
|
||||||
|
component.Dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAppearance(EntityUid uid, HumanoidCharacterAppearance appearance, Sex sex, Gender gender, HumanoidAppearanceComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component)) return;
|
||||||
|
|
||||||
|
component.Appearance = appearance;
|
||||||
|
component.Sex = sex;
|
||||||
|
component.Gender = gender;
|
||||||
|
|
||||||
|
component.Dirty();
|
||||||
|
|
||||||
|
RaiseLocalEvent(uid, new ChangedHumanoidAppearanceEvent(appearance, sex, gender));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAppearanceGetState(EntityUid uid, HumanoidAppearanceComponent component, ref ComponentGetState args)
|
||||||
|
{
|
||||||
|
args.State = new HumanoidAppearanceComponentState(component.Appearance, component.Sex, component.Gender);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAppearanceHandleState(EntityUid uid, HumanoidAppearanceComponent component, ref ComponentHandleState args)
|
||||||
|
{
|
||||||
|
if (args.Current is not HumanoidAppearanceComponentState state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UpdateAppearance(uid, state.Appearance, state.Sex, state.Gender);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scaffolding until Body is moved to ECS.
|
||||||
|
public void BodyPartAdded(EntityUid uid, BodyPartAddedEventArgs args)
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(new HumanoidAppearanceBodyPartAddedEvent(uid, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BodyPartRemoved(EntityUid uid, BodyPartRemovedEventArgs args)
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(new HumanoidAppearanceBodyPartRemovedEvent(uid, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scaffolding until Body is moved to ECS.
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class HumanoidAppearanceBodyPartAddedEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public EntityUid Uid { get; }
|
||||||
|
public BodyPartAddedEventArgs Args { get; }
|
||||||
|
|
||||||
|
public HumanoidAppearanceBodyPartAddedEvent(EntityUid uid, BodyPartAddedEventArgs args)
|
||||||
|
{
|
||||||
|
Uid = uid;
|
||||||
|
Args = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class HumanoidAppearanceBodyPartRemovedEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public EntityUid Uid { get; }
|
||||||
|
public BodyPartRemovedEventArgs Args { get; }
|
||||||
|
|
||||||
|
public HumanoidAppearanceBodyPartRemovedEvent(EntityUid uid, BodyPartRemovedEventArgs args)
|
||||||
|
{
|
||||||
|
Uid = uid;
|
||||||
|
Args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class ChangedHumanoidAppearanceEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public HumanoidCharacterAppearance Appearance { get; }
|
||||||
|
public Sex Sex { get; }
|
||||||
|
public Gender Gender { get; }
|
||||||
|
|
||||||
|
public ChangedHumanoidAppearanceEvent(HumanoidCharacterProfile profile)
|
||||||
|
{
|
||||||
|
Appearance = profile.Appearance;
|
||||||
|
Sex = profile.Sex;
|
||||||
|
Gender = profile.Gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChangedHumanoidAppearanceEvent(HumanoidCharacterAppearance appearance, Sex sex, Gender gender)
|
||||||
|
{
|
||||||
|
Appearance = appearance;
|
||||||
|
Sex = sex;
|
||||||
|
Gender = gender;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using Content.Shared.CharacterAppearance;
|
using Content.Shared.CharacterAppearance;
|
||||||
|
|
||||||
|
|
||||||
namespace Content.Shared.Preferences
|
namespace Content.Shared.Preferences
|
||||||
{
|
{
|
||||||
public interface ICharacterProfile
|
public interface ICharacterProfile
|
||||||
|
|||||||
Reference in New Issue
Block a user