Move to records for replay events

This commit is contained in:
D1GQ committed 2026-06-25 18:01:48 -05:00
1 parent 4c5d688233
commit 67d6a0d14d
11 files changed
+237 -100

No files matched your search

+19 -8
View File
@@ -1,33 +1,44 @@
using AmongUs.GameOptions;
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class AppearReplayEvent : IReplayEvent<(int playerId, bool animate)>
internal sealed class AppearReplayEvent : IReplayEvent<AppearReplayEvent.AppearReplayData, AppearReplayEvent.AppearReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "player_appear";
[JsonPropertyName("eventData")]
public (int playerId, bool animate) EventData { get; set; }
public AppearReplayData? EventData { get; set; }
public void Play()
{
var player = Utils.PlayerFromPlayerId(EventData.playerId);
if (EventData == null)
return;
var player = Utils.PlayerFromPlayerId(EventData.PlayerId);
if (player == null)
return;
if (player.Data.RoleType != RoleTypes.Phantom)
return;
player.SetRoleInvisibility(false, EventData.animate, true);
player.SetRoleInvisibility(false, EventData.Animate, true);
}
public void Record(PlayerControl player, bool animate)
public void Undo()
{
EventData = (player.PlayerId, animate);
}
}
public void Record(AppearReplayArgs args)
{
EventData = new AppearReplayData(args.Player.PlayerId, args.Animate);
}
internal record AppearReplayData(int PlayerId, bool Animate) : IReplayEvent.Data;
internal record AppearReplayArgs(PlayerControl Player, bool Animate) : IReplayEvent.Args;
}
+14 -6
View File
@@ -1,17 +1,17 @@
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class MurderReplayEvent : IReplayEvent<(int killerId, int targetId)>
internal sealed class MurderReplayEvent : IReplayEvent<MurderReplayEvent.MurderReplayData, MurderReplayEvent.MurderReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "player_murder";
[JsonPropertyName("eventData")]
public (int killerId, int targetId) EventData { get; set; }
public MurderReplayData? EventData { get; set; }
public void Play()
{
@@ -26,8 +26,16 @@ internal sealed class MurderReplayEvent : IReplayEvent<(int killerId, int target
killer.MurderPlayer(target, MurderResultFlags.Succeeded);
}
public void Record(PlayerControl killer, PlayerControl target)
public void Undo()
{
EventData = (killer.PlayerId, target.PlayerId);
}
public void Record(MurderReplayArgs murderReplayArgs)
{
EventData = new MurderReplayData(murderReplayArgs.killer.PlayerId, murderReplayArgs.target.PlayerId);
}
internal record MurderReplayData(int killerId, int targetId) : IReplayEvent.Data;
internal record MurderReplayArgs(PlayerControl killer, PlayerControl target) : IReplayEvent.Args;
}
+19 -8
View File
@@ -1,26 +1,29 @@
using AmongUs.GameOptions;
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class ProtectReplayEvent : IReplayEvent<(int playerId, int targetId)>
internal sealed class ProtectReplayEvent : IReplayEvent<ProtectReplayEvent.ProtectReplayData, ProtectReplayEvent.ProtectReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "protect_player";
[JsonPropertyName("eventData")]
public (int playerId, int targetId) EventData { get; set; }
public ProtectReplayData? EventData { get; set; }
public void Play()
{
var player = Utils.PlayerFromPlayerId(EventData.playerId);
if (EventData == null)
return;
var player = Utils.PlayerFromPlayerId(EventData.PlayerId);
if (player == null)
return;
var target = Utils.PlayerFromPlayerId(EventData.targetId);
var target = Utils.PlayerFromPlayerId(EventData.TargetId);
if (target == null)
return;
@@ -30,8 +33,16 @@ internal sealed class ProtectReplayEvent : IReplayEvent<(int playerId, int targe
player.ProtectPlayer(target, player.Data.DefaultOutfit.ColorId);
}
public void Record(PlayerControl player, PlayerControl target)
public void Undo()
{
EventData = (player.PlayerId, target.PlayerId);
}
}
public void Record(ProtectReplayArgs args)
{
EventData = new ProtectReplayData(args.Player.PlayerId, args.Target.PlayerId);
}
internal record ProtectReplayData(int PlayerId, int TargetId) : IReplayEvent.Data;
internal record ProtectReplayArgs(PlayerControl Player, PlayerControl Target) : IReplayEvent.Args;
}
+21 -8
View File
@@ -1,29 +1,42 @@
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class ProtectedReplayEvent : IReplayEvent<(int killerId, int targetId)>
internal sealed class ProtectedReplayEvent : IReplayEvent<ProtectedReplayEvent.ProtectedReplayData, ProtectedReplayEvent.ProtectedReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "player_protected";
[JsonPropertyName("eventData")]
public (int killerId, int targetId) EventData { get; set; }
public ProtectedReplayData? EventData { get; set; }
public void Play()
{
var target = Utils.PlayerFromPlayerId(EventData.targetId);
if (EventData == null)
return;
var target = Utils.PlayerFromPlayerId(EventData.TargetId);
if (target == null)
return;
RoleEffectAnimation roleEffectAnimation = UnityEngine.Object.Instantiate(RoleManager.Instance.protectAnim, target.transform);
roleEffectAnimation.SetMaskLayerBasedOnWhoShouldSee(true);
roleEffectAnimation.Play(target, null, target.cosmetics.FlipX, RoleEffectAnimation.SoundType.Global, 0f, true, 0f);
}
public void Record(PlayerControl killer, PlayerControl target)
public void Undo()
{
EventData = (killer.PlayerId, target.PlayerId);
}
}
public void Record(ProtectedReplayArgs args)
{
EventData = new ProtectedReplayData(args.Killer.PlayerId, args.Target.PlayerId);
}
internal record ProtectedReplayData(int KillerId, int TargetId) : IReplayEvent.Data;
internal record ProtectedReplayArgs(PlayerControl Killer, PlayerControl Target) : IReplayEvent.Args;
}
+23 -12
View File
@@ -1,31 +1,42 @@
using AmongUs.GameOptions;
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class SetRoleEvent : IReplayEvent<(int playerId, int roleType)>
internal sealed class SetRoleEvent : IReplayEvent<SetRoleEvent.SetRoleReplayData, SetRoleEvent.SetRoleReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "set_role";
[JsonPropertyName("eventData")]
public (int playerId, int roleType) EventData { get; set; }
public SetRoleReplayData? EventData { get; set; }
public void Play()
{
var player = Utils.PlayerFromPlayerId(EventData.playerId);
if (player != null)
{
var roleType = (RoleTypes)EventData.roleType;
player.RpcSetRole(roleType, true);
}
if (EventData == null)
return;
var player = Utils.PlayerFromPlayerId(EventData.PlayerId);
if (player == null)
return;
var roleType = (RoleTypes)EventData.RoleType;
player.RpcSetRole(roleType, true);
}
public void Record(PlayerControl player, RoleTypes roleType)
public void Undo()
{
EventData = (player.Data.PlayerId, (int)roleType);
}
}
public void Record(SetRoleReplayArgs args)
{
EventData = new SetRoleReplayData(args.Player.PlayerId, (int)args.RoleType);
}
internal record SetRoleReplayData(int PlayerId, int RoleType) : IReplayEvent.Data;
internal record SetRoleReplayArgs(PlayerControl Player, RoleTypes RoleType) : IReplayEvent.Args;
}
@@ -1,37 +1,48 @@
using AmongUs.GameOptions;
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class ShapeshiftReplayEvent : IReplayEvent<(int playerId, int targetId, bool animate)>
internal sealed class ShapeshiftReplayEvent : IReplayEvent<ShapeshiftReplayEvent.ShapeshiftReplayData, ShapeshiftReplayEvent.ShapeshiftReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "player_shapeshift";
[JsonPropertyName("eventData")]
public (int playerId, int targetId, bool animate) EventData { get; set; }
public ShapeshiftReplayData? EventData { get; set; }
public void Play()
{
var player = Utils.PlayerFromPlayerId(EventData.playerId);
if (EventData == null)
return;
var player = Utils.PlayerFromPlayerId(EventData.PlayerId);
if (player == null)
return;
var target = Utils.PlayerFromPlayerId(EventData.targetId);
var target = Utils.PlayerFromPlayerId(EventData.TargetId);
if (target == null)
return;
if (player.Data.RoleType != RoleTypes.Shapeshifter)
return;
player.Shapeshift(target, EventData.animate);
player.Shapeshift(target, EventData.Animate);
}
public void Record(PlayerControl killer, PlayerControl target, bool animate)
public void Undo()
{
EventData = (killer.PlayerId, target.PlayerId, animate);
}
}
public void Record(ShapeshiftReplayArgs args)
{
EventData = new ShapeshiftReplayData(args.Player.PlayerId, args.Target.PlayerId, args.Animate);
}
internal record ShapeshiftReplayData(int PlayerId, int TargetId, bool Animate) : IReplayEvent.Data;
internal record ShapeshiftReplayArgs(PlayerControl Player, PlayerControl Target, bool Animate) : IReplayEvent.Args;
}
@@ -4,20 +4,30 @@ using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class StartMeetingReplayEvent : IReplayEvent<(int playerId, int targetId)>
internal sealed class StartMeetingReplayEvent : IReplayEvent<StartMeetingReplayEvent.StartMeetingReplayData, StartMeetingReplayEvent.StartMeetingReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "start_meeting";
[JsonPropertyName("eventData")]
public (int playerId, int targetId) EventData { get; set; }
public StartMeetingReplayData? EventData { get; set; }
public void Play()
{
if (EventData == null)
return;
}
public void Record(PlayerControl player, PlayerControl? target)
public void Undo()
{
EventData = (player.PlayerId, target?.PlayerId ?? -1);
}
}
public void Record(StartMeetingReplayArgs args)
{
EventData = new StartMeetingReplayData(args.Player.PlayerId, args.Target?.PlayerId ?? -1);
}
internal record StartMeetingReplayData(int PlayerId, int TargetId) : IReplayEvent.Data;
internal record StartMeetingReplayArgs(PlayerControl Player, PlayerControl? Target) : IReplayEvent.Args;
}
@@ -1,32 +1,43 @@
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class UpdateSystemReplayEvent : IReplayEvent<(byte systemType, int playerId, byte amount)>
internal sealed class UpdateSystemReplayEvent : IReplayEvent<UpdateSystemReplayEvent.UpdateSystemReplayData, UpdateSystemReplayEvent.UpdateSystemReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "update_system";
[JsonPropertyName("eventData")]
public (byte systemType, int playerId, byte amount) EventData { get; set; }
public UpdateSystemReplayData? EventData { get; set; }
public void Play()
{
var player = Utils.PlayerFromPlayerId(EventData.playerId);
if (EventData == null)
return;
var player = Utils.PlayerFromPlayerId(EventData.PlayerId);
if (player == null)
return;
if (ShipStatus.Instance == null)
return;
ShipStatus.Instance?.UpdateSystem((SystemTypes)EventData.systemType, player, EventData.amount);
ShipStatus.Instance.UpdateSystem((SystemTypes)EventData.SystemType, player, EventData.Amount);
}
public void Record(SystemTypes system, PlayerControl player, byte amount)
public void Undo()
{
EventData = (checked((byte)system), player.PlayerId, amount);
}
}
public void Record(UpdateSystemReplayArgs args)
{
EventData = new UpdateSystemReplayData(checked((byte)args.System), args.Player.PlayerId, args.Amount);
}
internal record UpdateSystemReplayData(byte SystemType, int PlayerId, byte Amount) : IReplayEvent.Data;
internal record UpdateSystemReplayArgs(SystemTypes System, PlayerControl Player, byte Amount) : IReplayEvent.Args;
}
+18 -7
View File
@@ -1,22 +1,25 @@
using AmongUs.GameOptions;
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class VanishReplayEvent : IReplayEvent<int>
internal sealed class VanishReplayEvent : IReplayEvent<VanishReplayEvent.VanishReplayData, VanishReplayEvent.VanishReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "player_vanish";
[JsonPropertyName("eventData")]
public int EventData { get; set; }
public VanishReplayData? EventData { get; set; }
public void Play()
{
var player = Utils.PlayerFromPlayerId(EventData);
if (EventData == null)
return;
var player = Utils.PlayerFromPlayerId(EventData.PlayerId);
if (player == null)
return;
@@ -26,8 +29,16 @@ internal sealed class VanishReplayEvent : IReplayEvent<int>
player.SetRoleInvisibility(true, true, true);
}
public void Record(PlayerControl player)
public void Undo()
{
EventData = player.PlayerId;
}
}
public void Record(VanishReplayArgs args)
{
EventData = new VanishReplayData(args.Player.PlayerId);
}
internal record VanishReplayData(int PlayerId) : IReplayEvent.Data;
internal record VanishReplayArgs(PlayerControl Player) : IReplayEvent.Args;
}
+32 -18
View File
@@ -1,37 +1,51 @@
using BetterAmongUs.Utilities;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Interfaces;
using BetterAmongUs.Utilities;
using System.Text.Json.Serialization;
namespace BetterAmongUs.Data.Replay.Events;
[Serializable]
internal sealed class VentReplayEvent : IReplayEvent<(int playerId, bool exit, int ventId)>
internal sealed class VentReplayEvent : IReplayEvent<VentReplayEvent.VentReplayData, VentReplayEvent.VentReplayArgs>
{
[JsonPropertyName("id")]
public string Id => "player_vent";
[JsonPropertyName("eventData")]
public (int playerId, bool exit, int ventId) EventData { get; set; }
public VentReplayData? EventData { get; set; }
public void Play()
{
var vent = ShipStatus.Instance.AllVents.First(v => v.Id == EventData.ventId);
var player = Utils.PlayerFromPlayerId(EventData.playerId);
if (vent != null && player != null)
if (EventData == null)
return;
var player = Utils.PlayerFromPlayerId(EventData.PlayerId);
if (player == null)
return;
var vent = ShipStatus.Instance.AllVents.FirstOrDefault(v => v.Id == EventData.VentId);
if (vent == null)
return;
if (EventData.Exit)
{
if (EventData.exit)
{
vent.ExitVent(player);
}
else
{
vent.EnterVent(player);
}
vent.ExitVent(player);
}
else
{
vent.EnterVent(player);
}
}
public void Record(PlayerControl player, bool exit, int ventId)
public void Undo()
{
EventData = (player.PlayerId, exit, ventId);
}
}
public void Record(VentReplayArgs args)
{
EventData = new VentReplayData(args.Player.PlayerId, args.Exit, args.VentId);
}
internal record VentReplayData(int PlayerId, bool Exit, int VentId) : IReplayEvent.Data;
internal record VentReplayArgs(PlayerControl Player, bool Exit, int VentId) : IReplayEvent.Args;
}
+36 -10
View File
@@ -1,29 +1,55 @@
namespace BetterAmongUs.Interfaces;
/// <summary>
/// Interface for replay events in BetterAmongUs.
/// Base interface for all replay events.
/// </summary>
public interface IReplayEvent
{
/// <summary>
/// Gets the unique identifier for the replay event.
/// Base record for all replay event data.
/// </summary>
string Id { get; }
public abstract record Data;
/// <summary>
/// Plays or executes the replay event.
/// Base record for all replay event arguments.
/// </summary>
void Play();
public abstract record Args;
}
/// <summary>
/// Generic interface for replay events with associated data.
/// Generic interface for replay events with typed data and arguments.
/// </summary>
/// <typeparam name="T">The type of data associated with the event.</typeparam>
public interface IReplayEvent<T> : IReplayEvent
/// <typeparam name="EventDataType">The type of event data. Must inherit from <see cref="IReplayEvent.Data"/>.</typeparam>
/// <typeparam name="EventArgType">The type of event arguments. Must inherit from <see cref="IReplayEvent.Args"/>.</typeparam>
public interface IReplayEvent<EventDataType, EventArgType> : IReplayEvent
where EventDataType : IReplayEvent.Data
where EventArgType : IReplayEvent.Args
{
/// <summary>
/// Gets or sets the event data.
/// Gets the unique identifier for the event type.
/// </summary>
T? EventData { get; set; }
/// <value>A string that uniquely identifies this type of event.</value>
string Id { get; }
/// <summary>
/// Gets the stored event data.
/// </summary>
/// <value>The event data of type <typeparamref name="EventDataType"/>, or null if not recorded.</value>
EventDataType? EventData { get; }
/// <summary>
/// Records the event using the provided arguments.
/// </summary>
/// <param name="replayEventArg">The arguments used to construct the event data.</param>
void Record(EventArgType replayEventArg);
/// <summary>
/// Replays the event using the stored event data.
/// </summary>
void Play();
/// <summary>
/// Undoes the effects of the replayed event.
/// </summary>
void Undo();
}