Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto replays #5

Merged
merged 6 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 additions & 0 deletions BossMod/Config/ConfigNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@ public PropertySliderAttribute(float min, float max)
}
}

// attribute that specifies slider should be used for displaying float property
[AttributeUsage(AttributeTargets.Field)]
public class PropertyIntSliderAttribute : Attribute
{
public float Speed = 1;
public int Min;
public int Max;
public bool Logarithmic;

public PropertyIntSliderAttribute(int min, int max)
{
Min = min;
Max = max;
}
}

// base class for configuration nodes
public abstract class ConfigNode
{
Expand Down
26 changes: 26 additions & 0 deletions BossMod/Config/ConfigUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ private void DrawNodes(List<UINode> nodes)
bool v => DrawProperty(props, n.Node, field, v),
Enum v => DrawProperty(props, n.Node, field, v),
float v => DrawProperty(props, n.Node, field, v),
int v => DrawProperty(props, n.Node, field, v),
GroupAssignment v => DrawProperty(props, n.Node, field, v),
_ => false
};
Expand Down Expand Up @@ -224,6 +225,31 @@ private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, Field
return true;
}

private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, int v)
{
var slider = member.GetCustomAttribute<PropertyIntSliderAttribute>();
if (slider != null)
{
var flags = ImGuiSliderFlags.None;
if (slider.Logarithmic)
flags |= ImGuiSliderFlags.Logarithmic;
if (ImGui.DragInt(props.Label, ref v, slider.Speed, slider.Min, slider.Max, "%d", flags))
{
member.SetValue(node, v);
node.NotifyModified();
}
}
else
{
if (ImGui.InputInt(props.Label, ref v))
{
member.SetValue(node, v);
node.NotifyModified();
}
}
return true;
}

private bool DrawProperty(PropertyDisplayAttribute props, ConfigNode node, FieldInfo member, GroupAssignment v)
{
var group = member.GetCustomAttribute<GroupDetailsAttribute>();
Expand Down
18 changes: 18 additions & 0 deletions BossMod/Framework/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Dalamud.IoC;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game;
using System;
using System.Reflection;

Expand Down Expand Up @@ -46,6 +47,7 @@ public Plugin(
Service.WindowSystem = new("vbm");
//Service.Device = pluginInterface.UiBuilder.Device;
Service.Condition.ConditionChange += OnConditionChanged;
Service.ClientState.TerritoryChanged += OnZoneChange;
MultiboxUnlock.Exec();
Network.IDScramble.Initialize();
Camera.Instance = new();
Expand Down Expand Up @@ -82,6 +84,7 @@ public Plugin(
public void Dispose()
{
Service.Condition.ConditionChange -= OnConditionChanged;
Service.ClientState.TerritoryChanged -= OnZoneChange;
_wndDebug.Dispose();
_wndReplay.Dispose();
_wndBossmodHints.Dispose();
Expand Down Expand Up @@ -160,5 +163,20 @@ private void OnConditionChanged(ConditionFlag flag, bool value)
{
Service.Log($"Condition chage: {flag}={value}");
}

private unsafe void OnZoneChange(ushort obj)
{
if (GameMain.Instance()->CurrentContentFinderConditionId != 0 && !_wndReplay.IsRecording() && Service.Config.Get<ReplayManagementConfig>().AutoRecord)
{
_wndReplay.StartRecording();
return;
}

if (_wndReplay.IsRecording() && Service.Config.Get<ReplayManagementConfig>().AutoStop)
{
_wndReplay.StopRecording();
return;
}
}
}
}
1 change: 1 addition & 0 deletions BossMod/Framework/Service.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class Service
[PluginService] public static IFramework Framework { get; private set; }
[PluginService] public static ITextureProvider Texture { get; private set; }
[PluginService] public static ICommandManager CommandManager { get; private set; }
[PluginService] public static IDutyState DutyState { get; private set; }
[PluginService] public static DalamudPluginInterface PluginInterface { get; private set; }
#pragma warning restore CS8618

Expand Down
10 changes: 10 additions & 0 deletions BossMod/Replay/ReplayManagementConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ public class ReplayManagementConfig : ConfigNode
[PropertyDisplay("Show replay management UI")]
public bool ShowUI = false;

[PropertyDisplay("Auto record replays on duty start")]
public bool AutoRecord = false;

[PropertyDisplay("Auto stop replays on duty end")]
public bool AutoStop = false;

[PropertyDisplay("Max replays to keep before removal")]
[PropertyIntSlider(0, 1000, Speed = 1f, Logarithmic = false)]
public int MaxReplays = 0;

[PropertyDisplay("Store server packets in the replay")]
public bool DumpServerPackets = false;

Expand Down
69 changes: 67 additions & 2 deletions BossMod/Replay/ReplayManagementWindow.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using ImGuiNET;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
using System;
using System.IO;
using System.Linq;

namespace BossMod
{
Expand Down Expand Up @@ -56,7 +59,7 @@ public override void Draw()
{
try
{
_recorder = new(_ws, _config.WorldLogFormat, true, _logDir, "World");
_recorder = new(_ws, _config.WorldLogFormat, true, _logDir, $"{GetPrefix()}");
}
catch (Exception ex)
{
Expand Down Expand Up @@ -86,12 +89,74 @@ public override void Draw()
_manager.Draw();
}

public void StartRecording()
{
if (_recorder == null)
{
try
{
if (_config.MaxReplays > 0)
{
var files = _logDir.GetFiles().OrderBy(f => f.LastWriteTime).ToList();
files.Take(files.Count - _config.MaxReplays).ToList().ForEach(f => f.Delete());
}
}
catch (Exception ex)
{
Service.Log($"Failed to delete old replays: {ex}");
}

try
{
_recorder = new(_ws, _config.WorldLogFormat, true, _logDir, $"{GetPrefix()}");
}
catch (Exception ex)
{
Service.Log($"Failed to start recording: {ex}");
}
}
}

public void StopRecording()
{
if (_recorder != null)
{
_recorder.Dispose();
_recorder = null;
}
}

public bool IsRecording() => _recorder != null;

public override void OnClose()
{
SetVisible(false);
}

private void ApplyConfig(object? sender, EventArgs args) => IsOpen = _config.ShowUI;
private void UpdateTitle() => WindowName = $"Replay recording: {(_recorder != null ? "in progress..." : "idle")}{_windowID}";
private static unsafe string GetPrefix()
{
var prefix = "World";
var row = Service.LuminaGameData!.GetExcelSheet<TerritoryType>()!.GetRow(Service.ClientState.TerritoryType);
if (row != null)
{
if (row.ContentFinderCondition.Value!.RowId != 0)
prefix = row.ContentFinderCondition.Value.Name.RawString;
else
prefix = row.PlaceName.Value?.NameNoArticle.RawString ?? prefix;
}

var cf = ContentsFinder.Instance();
var unrestricted = cf->IsUnrestrictedParty ? "U" : "";
var levelsync = cf->IsLevelSync ? "LS" : "";
var minilvl = cf->IsMinimalIL ? "MI" : "";
var noecho = cf->IsSilenceEcho ? "NE" : "";
var dfsettings = string.Join(", ", new[] { unrestricted, levelsync, minilvl, noecho }.Where(s => !string.IsNullOrEmpty(s)));
if (dfsettings != null)
prefix += $"_{dfsettings}";

return prefix;
}
}
}