Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ END TEMPLATE-->

### New features

*None yet*
* Added a new `WeakEntityReference` struct that is intended to be used by component data-fields to refer to entities that may or may not still exist.

### Bugfixes

Expand Down
44 changes: 43 additions & 1 deletion Robust.Shared/EntitySerialization/EntityDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ namespace Robust.Shared.EntitySerialization;
public sealed class EntityDeserializer :
ISerializationContext,
ITypeSerializer<EntityUid, ValueDataNode>,
ITypeSerializer<NetEntity, ValueDataNode>
ITypeSerializer<NetEntity, ValueDataNode>,
ITypeSerializer<WeakEntityReference, ValueDataNode>
{
// See the comments around EntitySerializer's version const for information about the different versions.
// TBH version three isn't even really fully supported anymore, simply due to changes in engine component serialization.
Expand Down Expand Up @@ -1218,5 +1219,46 @@ DataNode ITypeWriter<NetEntity>.Write(
: new ValueDataNode("invalid");
}

WeakEntityReference ITypeReader<WeakEntityReference, ValueDataNode>.Read(
ISerializationManager serializationManager,
ValueDataNode node,
IDependencyCollection dependencies,
SerializationHookContext hookCtx,
ISerializationContext? context,
ISerializationManager.InstantiationDelegate<WeakEntityReference>? instanceProvider)
{
var uid = serializationManager.Read<EntityUid>(node, context);
return EntMan.TryGetNetEntity(uid, out var nent)
? new(nent.Value)
: WeakEntityReference.Invalid;
}

DataNode ITypeWriter<WeakEntityReference>.Write(
ISerializationManager serializationManager,
WeakEntityReference value,
IDependencyCollection dependencies,
bool alwaysWrite,
ISerializationContext? context)
{
return value != WeakEntityReference.Invalid
? new ValueDataNode(value.Entity.Id.ToString(CultureInfo.InvariantCulture))
: new ValueDataNode("invalid");
}

ValidationNode ITypeValidator<WeakEntityReference, ValueDataNode>.Validate(
ISerializationManager serializationManager,
ValueDataNode node,
IDependencyCollection dependencies,
ISerializationContext? context)
{
if (node.Value is "invalid")
return new ValidatedValueNode(node);

if (!int.TryParse(node.Value, out _))
return new ErrorNode(node, "Invalid NetEntity");

return new ValidatedValueNode(node);
}

#endregion
}
66 changes: 54 additions & 12 deletions Robust.Shared/EntitySerialization/EntitySerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ namespace Robust.Shared.EntitySerialization;
/// </remarks>
public sealed class EntitySerializer : ISerializationContext,
ITypeSerializer<EntityUid, ValueDataNode>,
ITypeSerializer<NetEntity, ValueDataNode>
ITypeSerializer<NetEntity, ValueDataNode>,
ITypeSerializer<WeakEntityReference, ValueDataNode>
{
public const int MapFormatVersion = 7;
// v6->v7: PR #5572 - Added more metadata, List maps/grids/orphans, include some life-stage information
Expand Down Expand Up @@ -868,12 +869,12 @@ ValidationNode ITypeValidator<EntityUid, ValueDataNode>.Validate(
return new ValidatedValueNode(node);
}

public DataNode Write(
DataNode ITypeWriter<EntityUid>.Write(
ISerializationManager serializationManager,
EntityUid value,
IDependencyCollection dependencies,
bool alwaysWrite = false,
ISerializationContext? context = null)
bool alwaysWrite,
ISerializationContext? context)
{
if (YamlUidMap.TryGetValue(value, out var yamlId))
return new ValueDataNode(yamlId.ToString(CultureInfo.InvariantCulture));
Expand Down Expand Up @@ -947,11 +948,11 @@ EntityUid ITypeReader<EntityUid, ValueDataNode>.Read(
return node.Value == "invalid" ? EntityUid.Invalid : EntityUid.Parse(node.Value);
}

public ValidationNode Validate(
ValidationNode ITypeValidator<NetEntity, ValueDataNode>.Validate(
ISerializationManager serializationManager,
ValueDataNode node,
IDependencyCollection dependencies,
ISerializationContext? context = null)
ISerializationContext? context)
{
if (node.Value == "invalid")
return new ValidatedValueNode(node);
Expand All @@ -962,27 +963,68 @@ public ValidationNode Validate(
return new ValidatedValueNode(node);
}

public NetEntity Read(
NetEntity ITypeReader<NetEntity, ValueDataNode>.Read(
ISerializationManager serializationManager,
ValueDataNode node,
IDependencyCollection dependencies,
SerializationHookContext hookCtx,
ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<NetEntity>? instanceProvider = null)
ISerializationContext? context,
ISerializationManager.InstantiationDelegate<NetEntity>? instanceProvider)
{
return node.Value == "invalid" ? NetEntity.Invalid : NetEntity.Parse(node.Value);
}

public DataNode Write(
DataNode ITypeWriter<NetEntity>.Write(
ISerializationManager serializationManager,
NetEntity value,
IDependencyCollection dependencies,
bool alwaysWrite = false,
ISerializationContext? context = null)
bool alwaysWrite,
ISerializationContext? context)
{
var uid = EntMan.GetEntity(value);
return serializationManager.WriteValue(uid, alwaysWrite, context);
}

ValidationNode ITypeValidator<WeakEntityReference, ValueDataNode>.Validate(
ISerializationManager serializationManager,
ValueDataNode node,
IDependencyCollection dependencies,
ISerializationContext? context)
{
if (node.Value == "invalid")
return new ValidatedValueNode(node);

if (!int.TryParse(node.Value, out _))
return new ErrorNode(node, "Invalid NetEntity");

return new ValidatedValueNode(node);
}

WeakEntityReference ITypeReader<WeakEntityReference, ValueDataNode>.Read(
ISerializationManager serializationManager,
ValueDataNode node,
IDependencyCollection dependencies,
SerializationHookContext hookCtx,
ISerializationContext? context,
ISerializationManager.InstantiationDelegate<WeakEntityReference>? instanceProvider)
{
return node.Value == "invalid"
? WeakEntityReference.Invalid
: new(NetEntity.Parse(node.Value));
}

DataNode ITypeWriter<WeakEntityReference>.Write(
ISerializationManager serializationManager,
WeakEntityReference value,
IDependencyCollection dependencies,
bool alwaysWrite,
ISerializationContext? context)
{
if (EntMan.TryGetEntity(value.Entity, out var uid) && YamlUidMap.TryGetValue(uid.Value, out var yamlId))
return new ValueDataNode(yamlId.ToString(CultureInfo.InvariantCulture));

return new ValueDataNode("invalid");
}

#endregion
}
88 changes: 88 additions & 0 deletions Robust.Shared/GameObjects/EntityManager.Components.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,94 @@ public CompRegistryEntityEnumerator CompRegistryQueryEnumerator(ComponentRegistr
return new CompRegistryEntityEnumerator(this, trait1, registry);
}

#region WeakEntityReference

public WeakEntityReference GetWeakReference(EntityUid uid, MetaDataComponent? meta = null)
{
return new WeakEntityReference(GetNetEntity(uid, meta));
}

public WeakEntityReference? GetWeakReference(EntityUid? uid, MetaDataComponent? meta = null)
{
if (uid == null)
return null;

return new WeakEntityReference(GetNetEntity(uid.Value, meta));
}

/// <inheritdoc />
public EntityUid? Resolve(WeakEntityReference weakRef)
{
if (weakRef.Entity != NetEntity.Invalid
&& TryGetEntity(weakRef.Entity, out var ent))
{
return ent.Value;
}

return null;
}

/// <inheritdoc />
public EntityUid? Resolve(WeakEntityReference? weakRef)
{
return weakRef == null ? null : Resolve(weakRef.Value);
}

/// <inheritdoc />
public Entity<T>? Resolve<T>(WeakEntityReference<T> weakRef) where T : IComponent
{
if (weakRef.Entity != NetEntity.Invalid
&& TryGetEntity(weakRef.Entity, out var ent)
&& TryGetComponent(ent.Value, out T? comp))
{
return new(ent.Value, comp);
}

return null;
}

/// <inheritdoc />
public Entity<T>? Resolve<T>(WeakEntityReference<T>? weakRef) where T : IComponent
{
return weakRef == null ? null : Resolve(weakRef.Value);
}

public bool TryGetEntity(WeakEntityReference weakRef, [NotNullWhen(true)] out EntityUid? entity)
{
return TryGetEntity(weakRef.Entity, out entity);
}

public bool TryGetEntity([NotNullWhen(true)] WeakEntityReference? weakRef, [NotNullWhen(true)] out EntityUid? entity)
{
return TryGetEntity(weakRef?.Entity, out entity);
}

public bool TryGetEntity<T>(WeakEntityReference<T> weakRef, [NotNullWhen(true)] out Entity<T>? entity)
where T : IComponent
{
if (!TryGetEntity(weakRef.Entity, out var uid)
|| !TryGetComponent(uid.Value, out T? component))
{
entity = null;
return false;
}

entity = new(uid.Value, component);
return true;
}

public bool TryGetEntity<T>([NotNullWhen(true)] WeakEntityReference<T>? weakRef, [NotNullWhen(true)] out Entity<T>? entity)
where T : IComponent
{
if (weakRef != null)
return TryGetEntity(weakRef.Value, out entity);

entity = null;
return false;
}

#endregion

public AllEntityQueryEnumerator<IComponent> AllEntityQueryEnumerator(Type comp)
{
DebugTools.Assert(comp.IsAssignableTo(typeof(IComponent)));
Expand Down
4 changes: 2 additions & 2 deletions Robust.Shared/GameObjects/EntityManager.Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public bool TryGetEntityData(NetEntity nEntity, [NotNullWhen(true)] out EntityUi
}

/// <inheritdoc />
public bool TryGetEntity(NetEntity? nEntity, [NotNullWhen(true)] out EntityUid? entity)
public bool TryGetEntity([NotNullWhen(true)] NetEntity? nEntity, [NotNullWhen(true)] out EntityUid? entity)
{
if (nEntity == null)
{
Expand Down Expand Up @@ -121,7 +121,7 @@ public bool TryGetNetEntity(EntityUid uid, [NotNullWhen(true)] out NetEntity? ne
}

/// <inheritdoc />
public bool TryGetNetEntity(EntityUid? uid, [NotNullWhen(true)] out NetEntity? netEntity, MetaDataComponent? metadata = null)
public bool TryGetNetEntity([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out NetEntity? netEntity, MetaDataComponent? metadata = null)
{
if (uid == null)
{
Expand Down
13 changes: 13 additions & 0 deletions Robust.Shared/GameObjects/EntityManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,19 @@ public EntityStringRepresentation ToPrettyString(NetEntity netEntity)
return ToPrettyString(uid.Value, meta);
}

/// <inheritdoc />
[return: NotNullIfNotNull(nameof(weakRef))]
public EntityStringRepresentation? ToPrettyString(WeakEntityReference? weakRef)
{
return weakRef == null ? null : ToPrettyString(weakRef.Value);
}

/// <inheritdoc />
public EntityStringRepresentation ToPrettyString(WeakEntityReference weakRef)
{
return ToPrettyString(weakRef.Entity);
}

#endregion Entity Management

public virtual void RaisePredictiveEvent<T>(T msg) where T : EntityEventArgs
Expand Down
Loading
Loading