Holopad networking rework (#34112)
* Initial commit * Finalizing main changes * Addressed reviews * Fixed a few issues * Switched to using global overrides * Removed unnecessary references
This commit is contained in:
@@ -2,45 +2,38 @@ using Content.Shared.Chat.TypingIndicator;
|
||||
using Content.Shared.Holopad;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using System.Linq;
|
||||
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
|
||||
|
||||
namespace Content.Client.Holopad;
|
||||
|
||||
public sealed class HolopadSystem : SharedHolopadSystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<HolopadHologramComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<HolopadHologramComponent, ComponentStartup>(OnComponentStartup);
|
||||
SubscribeLocalEvent<HolopadHologramComponent, BeforePostShaderRenderEvent>(OnShaderRender);
|
||||
SubscribeAllEvent<TypingChangedEvent>(OnTypingChanged);
|
||||
|
||||
SubscribeNetworkEvent<PlayerSpriteStateRequest>(OnPlayerSpriteStateRequest);
|
||||
SubscribeNetworkEvent<PlayerSpriteStateMessage>(OnPlayerSpriteStateMessage);
|
||||
}
|
||||
|
||||
private void OnComponentInit(EntityUid uid, HolopadHologramComponent component, ComponentInit ev)
|
||||
private void OnComponentStartup(Entity<HolopadHologramComponent> entity, ref ComponentStartup ev)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
UpdateHologramSprite(uid);
|
||||
UpdateHologramSprite(entity, entity.Comp.LinkedEntity);
|
||||
}
|
||||
|
||||
private void OnShaderRender(EntityUid uid, HolopadHologramComponent component, BeforePostShaderRenderEvent ev)
|
||||
private void OnShaderRender(Entity<HolopadHologramComponent> entity, ref BeforePostShaderRenderEvent ev)
|
||||
{
|
||||
if (ev.Sprite.PostShader == null)
|
||||
return;
|
||||
|
||||
ev.Sprite.PostShader.SetParameter("t", (float)_timing.CurTime.TotalSeconds * component.ScrollRate);
|
||||
UpdateHologramSprite(entity, entity.Comp.LinkedEntity);
|
||||
}
|
||||
|
||||
private void OnTypingChanged(TypingChangedEvent ev, EntitySessionEventArgs args)
|
||||
@@ -57,100 +50,66 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
RaiseNetworkEvent(netEv);
|
||||
}
|
||||
|
||||
private void OnPlayerSpriteStateRequest(PlayerSpriteStateRequest ev)
|
||||
private void UpdateHologramSprite(EntityUid hologram, EntityUid? target)
|
||||
{
|
||||
var targetPlayer = GetEntity(ev.TargetPlayer);
|
||||
var player = _playerManager.LocalSession?.AttachedEntity;
|
||||
|
||||
// Ignore the request if received by a player who isn't the target
|
||||
if (targetPlayer != player)
|
||||
return;
|
||||
|
||||
if (!TryComp<SpriteComponent>(player, out var playerSprite))
|
||||
return;
|
||||
|
||||
var spriteLayerData = new List<PrototypeLayerData>();
|
||||
|
||||
if (playerSprite.Visible)
|
||||
{
|
||||
// Record the RSI paths, state names and shader paramaters of all visible layers
|
||||
for (int i = 0; i < playerSprite.AllLayers.Count(); i++)
|
||||
{
|
||||
if (!playerSprite.TryGetLayer(i, out var layer))
|
||||
continue;
|
||||
|
||||
if (!layer.Visible ||
|
||||
string.IsNullOrEmpty(layer.ActualRsi?.Path.ToString()) ||
|
||||
string.IsNullOrEmpty(layer.State.Name))
|
||||
continue;
|
||||
|
||||
var layerDatum = new PrototypeLayerData();
|
||||
layerDatum.RsiPath = layer.ActualRsi.Path.ToString();
|
||||
layerDatum.State = layer.State.Name;
|
||||
|
||||
if (layer.CopyToShaderParameters != null)
|
||||
{
|
||||
var key = (string)layer.CopyToShaderParameters.LayerKey;
|
||||
|
||||
if (playerSprite.LayerMapTryGet(key, out var otherLayerIdx) &&
|
||||
playerSprite.TryGetLayer(otherLayerIdx, out var otherLayer) &&
|
||||
otherLayer.Visible)
|
||||
{
|
||||
layerDatum.MapKeys = new() { key };
|
||||
|
||||
layerDatum.CopyToShaderParameters = new PrototypeCopyToShaderParameters()
|
||||
{
|
||||
LayerKey = key,
|
||||
ParameterTexture = layer.CopyToShaderParameters.ParameterTexture,
|
||||
ParameterUV = layer.CopyToShaderParameters.ParameterUV
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
spriteLayerData.Add(layerDatum);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the recorded data to the server
|
||||
var evResponse = new PlayerSpriteStateMessage(ev.TargetPlayer, spriteLayerData.ToArray());
|
||||
RaiseNetworkEvent(evResponse);
|
||||
}
|
||||
|
||||
private void OnPlayerSpriteStateMessage(PlayerSpriteStateMessage ev)
|
||||
{
|
||||
UpdateHologramSprite(GetEntity(ev.SpriteEntity), ev.SpriteLayerData);
|
||||
}
|
||||
|
||||
private void UpdateHologramSprite(EntityUid uid, PrototypeLayerData[]? layerData = null)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(uid, out var hologramSprite))
|
||||
return;
|
||||
|
||||
if (!TryComp<HolopadHologramComponent>(uid, out var holopadhologram))
|
||||
// Get required components
|
||||
if (!TryComp<SpriteComponent>(hologram, out var hologramSprite) ||
|
||||
!TryComp<HolopadHologramComponent>(hologram, out var holopadhologram))
|
||||
return;
|
||||
|
||||
// Remove all sprite layers
|
||||
for (int i = hologramSprite.AllLayers.Count() - 1; i >= 0; i--)
|
||||
hologramSprite.RemoveLayer(i);
|
||||
|
||||
if (layerData == null || layerData.Length == 0)
|
||||
if (TryComp<SpriteComponent>(target, out var targetSprite))
|
||||
{
|
||||
layerData = new PrototypeLayerData[1];
|
||||
layerData[0] = new PrototypeLayerData()
|
||||
// Use the target's holographic avatar (if available)
|
||||
if (TryComp<HolographicAvatarComponent>(target, out var targetAvatar) &&
|
||||
targetAvatar.LayerData != null)
|
||||
{
|
||||
RsiPath = holopadhologram.RsiPath,
|
||||
State = holopadhologram.RsiState
|
||||
};
|
||||
for (int i = 0; i < targetAvatar.LayerData.Length; i++)
|
||||
{
|
||||
var layer = targetAvatar.LayerData[i];
|
||||
hologramSprite.AddLayer(targetAvatar.LayerData[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise copy the target's current physical appearance
|
||||
else
|
||||
{
|
||||
hologramSprite.CopyFrom(targetSprite);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < layerData.Length; i++)
|
||||
// There is no target, display a default sprite instead (if available)
|
||||
else
|
||||
{
|
||||
var layer = layerData[i];
|
||||
layer.Shader = "unshaded";
|
||||
if (string.IsNullOrEmpty(holopadhologram.RsiPath) || string.IsNullOrEmpty(holopadhologram.RsiState))
|
||||
return;
|
||||
|
||||
hologramSprite.AddLayer(layerData[i], i);
|
||||
var layer = new PrototypeLayerData();
|
||||
layer.RsiPath = holopadhologram.RsiPath;
|
||||
layer.State = holopadhologram.RsiState;
|
||||
|
||||
hologramSprite.AddLayer(layer);
|
||||
}
|
||||
|
||||
UpdateHologramShader(uid, hologramSprite, holopadhologram);
|
||||
// Override specific values
|
||||
hologramSprite.Color = Color.White;
|
||||
hologramSprite.Offset = holopadhologram.Offset;
|
||||
hologramSprite.DrawDepth = (int)DrawDepth.Mobs;
|
||||
hologramSprite.NoRotation = true;
|
||||
hologramSprite.DirectionOverride = Direction.South;
|
||||
hologramSprite.EnableDirectionOverride = true;
|
||||
|
||||
// Remove shading from all layers (except displacement maps)
|
||||
for (int i = 0; i < hologramSprite.AllLayers.Count(); i++)
|
||||
{
|
||||
if (hologramSprite.TryGetLayer(i, out var layer) && layer.ShaderPrototype != "DisplacedStencilDraw")
|
||||
hologramSprite.LayerSetShader(i, "unshaded");
|
||||
}
|
||||
|
||||
UpdateHologramShader(hologram, hologramSprite, holopadhologram);
|
||||
}
|
||||
|
||||
private void UpdateHologramShader(EntityUid uid, SpriteComponent sprite, HolopadHologramComponent holopadHologram)
|
||||
|
||||
@@ -15,6 +15,7 @@ using Content.Shared.Telephone;
|
||||
using Content.Shared.UserInterface;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -35,22 +36,15 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly PvsOverrideSystem _pvs = default!;
|
||||
|
||||
private float _updateTimer = 1.0f;
|
||||
|
||||
private const float UpdateTime = 1.0f;
|
||||
private const float MinTimeBetweenSyncRequests = 0.5f;
|
||||
private TimeSpan _minTimeSpanBetweenSyncRequests;
|
||||
|
||||
private HashSet<EntityUid> _pendingRequestsForSpriteState = new();
|
||||
private HashSet<EntityUid> _recentlyUpdatedHolograms = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_minTimeSpanBetweenSyncRequests = TimeSpan.FromSeconds(MinTimeBetweenSyncRequests);
|
||||
|
||||
// Holopad UI and bound user interface messages
|
||||
SubscribeLocalEvent<HolopadComponent, BeforeActivatableUIOpenEvent>(OnUIOpen);
|
||||
SubscribeLocalEvent<HolopadComponent, HolopadStartNewCallMessage>(OnHolopadStartNewCall);
|
||||
@@ -68,7 +62,6 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
|
||||
// Networked events
|
||||
SubscribeNetworkEvent<HolopadUserTypingChangedEvent>(OnTypingChanged);
|
||||
SubscribeNetworkEvent<PlayerSpriteStateMessage>(OnPlayerSpriteStateMessage);
|
||||
|
||||
// Component start/shutdown events
|
||||
SubscribeLocalEvent<HolopadComponent, ComponentInit>(OnHolopadInit);
|
||||
@@ -268,16 +261,11 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
if (source.Comp.Hologram == null)
|
||||
GenerateHologram(source);
|
||||
|
||||
// Receiver holopad holograms have to be generated now instead of waiting for their own event
|
||||
// to fire because holographic avatars get synced immediately
|
||||
if (TryComp<HolopadComponent>(args.Receiver, out var receivingHolopad) && receivingHolopad.Hologram == null)
|
||||
GenerateHologram((args.Receiver, receivingHolopad));
|
||||
|
||||
if (source.Comp.User != null)
|
||||
{
|
||||
// Re-link the user to refresh the sprite data
|
||||
LinkHolopadToUser(source, source.Comp.User.Value);
|
||||
}
|
||||
// Re-link the user to refresh the sprite data
|
||||
LinkHolopadToUser(source, source.Comp.User);
|
||||
}
|
||||
|
||||
private void OnHoloCallEnded(Entity<HolopadComponent> entity, ref TelephoneCallEndedEvent args)
|
||||
@@ -323,22 +311,6 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerSpriteStateMessage(PlayerSpriteStateMessage ev, EntitySessionEventArgs args)
|
||||
{
|
||||
var uid = args.SenderSession.AttachedEntity;
|
||||
|
||||
if (!Exists(uid))
|
||||
return;
|
||||
|
||||
if (!_pendingRequestsForSpriteState.Remove(uid.Value))
|
||||
return;
|
||||
|
||||
if (!TryComp<HolopadUserComponent>(uid, out var holopadUser))
|
||||
return;
|
||||
|
||||
SyncHolopadUserWithLinkedHolograms((uid.Value, holopadUser), ev.SpriteLayerData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region: Component start/shutdown events
|
||||
@@ -485,8 +457,6 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_recentlyUpdatedHolograms.Clear();
|
||||
}
|
||||
|
||||
public void UpdateUIState(Entity<HolopadComponent> entity, TelephoneComponent? telephone = null)
|
||||
@@ -555,10 +525,16 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
QueueDel(hologram);
|
||||
}
|
||||
|
||||
private void LinkHolopadToUser(Entity<HolopadComponent> entity, EntityUid user)
|
||||
private void LinkHolopadToUser(Entity<HolopadComponent> entity, EntityUid? user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
UnlinkHolopadFromUser(entity, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp<HolopadUserComponent>(user, out var holopadUser))
|
||||
holopadUser = AddComp<HolopadUserComponent>(user);
|
||||
holopadUser = AddComp<HolopadUserComponent>(user.Value);
|
||||
|
||||
if (user != entity.Comp.User?.Owner)
|
||||
{
|
||||
@@ -567,51 +543,44 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
|
||||
// Assigns the new user in their place
|
||||
holopadUser.LinkedHolopads.Add(entity);
|
||||
entity.Comp.User = (user, holopadUser);
|
||||
entity.Comp.User = (user.Value, holopadUser);
|
||||
}
|
||||
|
||||
if (TryComp<HolographicAvatarComponent>(user, out var avatar))
|
||||
{
|
||||
SyncHolopadUserWithLinkedHolograms((user, holopadUser), avatar.LayerData);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have no apriori sprite data for the hologram, request
|
||||
// the current appearance of the user from the client
|
||||
RequestHolopadUserSpriteUpdate((user, holopadUser));
|
||||
// Add the new user to PVS and sync their appearance with any
|
||||
// holopads connected to the one they are using
|
||||
_pvs.AddGlobalOverride(user.Value);
|
||||
SyncHolopadHologramAppearanceWithTarget(entity, entity.Comp.User);
|
||||
}
|
||||
|
||||
private void UnlinkHolopadFromUser(Entity<HolopadComponent> entity, Entity<HolopadUserComponent>? user)
|
||||
{
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
entity.Comp.User = null;
|
||||
SyncHolopadHologramAppearanceWithTarget(entity, null);
|
||||
|
||||
foreach (var linkedHolopad in GetLinkedHolopads(entity))
|
||||
{
|
||||
if (linkedHolopad.Comp.Hologram != null)
|
||||
{
|
||||
_appearanceSystem.SetData(linkedHolopad.Comp.Hologram.Value.Owner, TypingIndicatorVisuals.IsTyping, false);
|
||||
|
||||
// Send message with no sprite data to the client
|
||||
// This will set the holgram sprite to a generic icon
|
||||
var ev = new PlayerSpriteStateMessage(GetNetEntity(linkedHolopad.Comp.Hologram.Value));
|
||||
RaiseNetworkEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
if (!HasComp<HolopadUserComponent>(user))
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
user.Value.Comp.LinkedHolopads.Remove(entity);
|
||||
|
||||
if (!user.Value.Comp.LinkedHolopads.Any())
|
||||
if (!user.Value.Comp.LinkedHolopads.Any() &&
|
||||
user.Value.Comp.LifeStage < ComponentLifeStage.Stopping)
|
||||
{
|
||||
_pendingRequestsForSpriteState.Remove(user.Value);
|
||||
_pvs.RemoveGlobalOverride(user.Value);
|
||||
RemComp<HolopadUserComponent>(user.Value);
|
||||
}
|
||||
}
|
||||
private void SyncHolopadHologramAppearanceWithTarget(Entity<HolopadComponent> entity, Entity<HolopadUserComponent>? user)
|
||||
{
|
||||
foreach (var linkedHolopad in GetLinkedHolopads(entity))
|
||||
{
|
||||
if (linkedHolopad.Comp.Hologram == null)
|
||||
continue;
|
||||
|
||||
if (user.Value.Comp.LifeStage < ComponentLifeStage.Stopping)
|
||||
RemComp<HolopadUserComponent>(user.Value);
|
||||
if (user == null)
|
||||
_appearanceSystem.SetData(linkedHolopad.Comp.Hologram.Value.Owner, TypingIndicatorVisuals.IsTyping, false);
|
||||
|
||||
linkedHolopad.Comp.Hologram.Value.Comp.LinkedEntity = user;
|
||||
Dirty(linkedHolopad.Comp.Hologram.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,31 +615,6 @@ public sealed class HolopadSystem : SharedHolopadSystem
|
||||
Dirty(entity);
|
||||
}
|
||||
|
||||
private void RequestHolopadUserSpriteUpdate(Entity<HolopadUserComponent> user)
|
||||
{
|
||||
if (!_pendingRequestsForSpriteState.Add(user))
|
||||
return;
|
||||
|
||||
var ev = new PlayerSpriteStateRequest(GetNetEntity(user));
|
||||
RaiseNetworkEvent(ev);
|
||||
}
|
||||
|
||||
private void SyncHolopadUserWithLinkedHolograms(Entity<HolopadUserComponent> entity, PrototypeLayerData[]? spriteLayerData)
|
||||
{
|
||||
foreach (var linkedHolopad in entity.Comp.LinkedHolopads)
|
||||
{
|
||||
foreach (var receivingHolopad in GetLinkedHolopads(linkedHolopad))
|
||||
{
|
||||
if (receivingHolopad.Comp.Hologram == null || !_recentlyUpdatedHolograms.Add(receivingHolopad.Comp.Hologram.Value))
|
||||
continue;
|
||||
|
||||
var netHologram = GetNetEntity(receivingHolopad.Comp.Hologram.Value);
|
||||
var ev = new PlayerSpriteStateMessage(netHologram, spriteLayerData);
|
||||
RaiseNetworkEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ActivateProjector(Entity<HolopadComponent> entity, EntityUid user)
|
||||
{
|
||||
if (!TryComp<TelephoneComponent>(entity, out var receiverTelephone))
|
||||
|
||||
@@ -2,12 +2,12 @@ using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Holopad;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class HolographicAvatarComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The prototype sprite layer data for the hologram
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField, AutoNetworkedField]
|
||||
public PrototypeLayerData[] LayerData;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Shared.Holopad;
|
||||
@@ -6,7 +7,7 @@ namespace Content.Shared.Holopad;
|
||||
/// <summary>
|
||||
/// Holds data pertaining to holopad holograms
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class HolopadHologramComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
@@ -64,8 +65,8 @@ public sealed partial class HolopadHologramComponent : Component
|
||||
public Vector2 Offset = new Vector2();
|
||||
|
||||
/// <summary>
|
||||
/// A user that are linked to this hologram
|
||||
/// An entity that is linked to this hologram
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public Entity<HolopadComponent>? LinkedHolopad;
|
||||
[ViewVariables, AutoNetworkedField]
|
||||
public EntityUid? LinkedEntity = null;
|
||||
}
|
||||
|
||||
@@ -20,29 +20,6 @@ public sealed partial class HolopadUserComponent : Component
|
||||
public HashSet<Entity<HolopadComponent>> LinkedHolopads = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A networked event raised when the visual state of a hologram is being updated
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class HolopadHologramVisualsUpdateEvent : EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The hologram being updated
|
||||
/// </summary>
|
||||
public readonly NetEntity Hologram;
|
||||
|
||||
/// <summary>
|
||||
/// The target the hologram is copying
|
||||
/// </summary>
|
||||
public readonly NetEntity? Target;
|
||||
|
||||
public HolopadHologramVisualsUpdateEvent(NetEntity hologram, NetEntity? target = null)
|
||||
{
|
||||
Hologram = hologram;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A networked event raised when the visual state of a hologram is being updated
|
||||
/// </summary>
|
||||
@@ -65,40 +42,3 @@ public sealed class HolopadUserTypingChangedEvent : EntityEventArgs
|
||||
IsTyping = isTyping;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A networked event raised by the server to request the current visual state of a target player entity
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class PlayerSpriteStateRequest : EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The player entity in question
|
||||
/// </summary>
|
||||
public readonly NetEntity TargetPlayer;
|
||||
|
||||
public PlayerSpriteStateRequest(NetEntity targetPlayer)
|
||||
{
|
||||
TargetPlayer = targetPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The client's response to a <see cref="PlayerSpriteStateRequest"/>
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class PlayerSpriteStateMessage : EntityEventArgs
|
||||
{
|
||||
public readonly NetEntity SpriteEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Data needed to reconstruct the player's sprite component layers
|
||||
/// </summary>
|
||||
public readonly PrototypeLayerData[]? SpriteLayerData;
|
||||
|
||||
public PlayerSpriteStateMessage(NetEntity spriteEntity, PrototypeLayerData[]? spriteLayerData = null)
|
||||
{
|
||||
SpriteEntity = spriteEntity;
|
||||
SpriteLayerData = spriteLayerData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,12 +155,7 @@
|
||||
components:
|
||||
- type: Transform
|
||||
anchored: true
|
||||
- type: Sprite
|
||||
noRot: true
|
||||
drawdepth: Mobs
|
||||
offset: -0.02, 0.45
|
||||
overrideDir: South
|
||||
enableOverrideDir: true
|
||||
- type: Sprite # Sprite data is dynamically set in Client.HolopadSystem
|
||||
- type: Appearance
|
||||
- type: TypingIndicator
|
||||
proto: robot
|
||||
@@ -177,6 +172,7 @@
|
||||
alpha: 0.9
|
||||
intensity: 2
|
||||
scrollRate: 0.125
|
||||
offset: -0.02, 0.45
|
||||
- type: Tag
|
||||
tags:
|
||||
- HideContextMenu
|
||||
|
||||
Reference in New Issue
Block a user