Skip to content

Commit

Permalink
Merge pull request #488 from sailro/refactor-commands
Browse files Browse the repository at this point in the history
Refactor commands
  • Loading branch information
sailro authored Apr 25, 2024
2 parents 89c6d6b + 53a1818 commit 21868b3
Show file tree
Hide file tree
Showing 30 changed files with 873 additions and 477 deletions.
144 changes: 144 additions & 0 deletions ConsoleCommands/BaseListCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using EFT.InventoryLogic;
using EFT.Trainer.Extensions;
using EFT.Trainer.Features;
using JsonType;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System;
using System.Linq;
using Comfort.Common;
using EFT.Interactive;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal abstract class BaseListCommand : LootItemsRelatedCommand
{
public override string Pattern => OptionalArgumentPattern;
protected virtual ELootRarity? Rarity => null;

public override void Execute(Match match)
{
ListLootItems(match, Rarity);
}

private void ListLootItems(Match match, ELootRarity? rarityFilter = null)
{
var search = string.Empty;
var matchGroup = match.Groups[ValueGroup];
if (matchGroup is {Success: true})
{
search = matchGroup.Value.Trim();
if (search == TrackedItem.MatchAll)
search = string.Empty;
}

var world = Singleton<GameWorld>.Instance;
if (world == null)
return;

var itemsPerName = new Dictionary<string, List<Item>>();

// Step 1 - look outside containers and inside corpses (loot items)
FindLootItems(world, itemsPerName);

// Step 2 - look inside containers (items)
if (LootItems.SearchInsideContainers)
FindItemsInContainers(world, itemsPerName);

var names = itemsPerName.Keys.ToList();
names.Sort();
names.Reverse();

var count = 0;
foreach (var itemName in names)
{
if (itemName.IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0)
continue;

var list = itemsPerName[itemName];
var rarity = list.First().Template.GetEstimatedRarity();
if (rarityFilter.HasValue && rarityFilter.Value != rarity)
continue;

var extra = rarity != ELootRarity.Not_exist ? $" ({rarity.Color()})" : string.Empty;
AddConsoleLog($"{itemName} [{list.Count.ToString().Cyan()}]{extra}");

count += list.Count;
}

AddConsoleLog("------");
AddConsoleLog($"found {count.ToString().Cyan()} item(s)");
}

private static void FindItemsInRootItem(Dictionary<string, List<Item>> itemsPerName, Item? rootItem)
{
var items = rootItem?
.GetAllItems()?
.ToArray();

if (items == null)
return;

IndexItems(items, itemsPerName);
}

private void FindLootItems(GameWorld world, Dictionary<string, List<Item>> itemsPerName)
{
var lootItems = world.LootItems;
var filteredItems = new List<Item>();
for (var i = 0; i < lootItems.Count; i++)
{
var lootItem = lootItems.GetByIndex(i);
if (!lootItem.IsValid())
continue;

if (lootItem is Corpse corpse)
{
if (LootItems.SearchInsideCorpses)
FindItemsInRootItem(itemsPerName, corpse.ItemOwner?.RootItem);

continue;
}

filteredItems.Add(lootItem.Item);
}

IndexItems(filteredItems, itemsPerName);
}

private static void IndexItems(IEnumerable<Item> items, Dictionary<string, List<Item>> itemsPerName)
{
foreach (var item in items)
{
if (!item.IsValid() || item.IsFiltered())
continue;

var itemName = item.ShortName.Localized();
if (!itemsPerName.TryGetValue(itemName, out var pnList))
{
pnList = [];
itemsPerName[itemName] = pnList;
}

pnList.Add(item);
}
}

private static void FindItemsInContainers(GameWorld world, Dictionary<string, List<Item>> itemsPerName)
{
var owners = world.ItemOwners; // contains all containers: corpses, LootContainers, ...
foreach (var owner in owners)
{
var rootItem = owner.Key.RootItem;
if (rootItem is not { IsContainer: true })
continue;

if (!rootItem.IsValid() || rootItem.IsFiltered()) // filter default inventory container here, given we special case the corpse container
continue;

FindItemsInRootItem(itemsPerName, rootItem);
}
}
}
34 changes: 34 additions & 0 deletions ConsoleCommands/BaseTemplateCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using EFT.InventoryLogic;
using System.Collections.Generic;
using System.Linq;
using Comfort.Common;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal abstract class BaseTemplateCommand : ConsoleCommandWithArgument
{
public override string Pattern => RequiredArgumentPattern;

protected static IEnumerable<ItemTemplate> FindTemplates(string searchShortNameOrTemplateId)
{
if (!Singleton<ItemFactory>.Instantiated)
return [];

var templates = Singleton<ItemFactory>
.Instance
.ItemTemplates;

// Match by TemplateId
if (templates.TryGetValue(searchShortNameOrTemplateId, out var template))
return [template];

// Match by short name(s)
return templates
.Values
.Where(t => t.ShortNameLocalizationKey.Localized().IndexOf(searchShortNameOrTemplateId, StringComparison.OrdinalIgnoreCase) >= 0
|| t.NameLocalizationKey.Localized().IndexOf(searchShortNameOrTemplateId, StringComparison.OrdinalIgnoreCase) >= 0);
}
}
35 changes: 35 additions & 0 deletions ConsoleCommands/BaseTrackCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using EFT.Trainer.Configuration;
using EFT.Trainer.Extensions;
using JsonType;
using System.Text.RegularExpressions;
using UnityEngine;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal abstract class BaseTrackCommand : LootItemsRelatedCommand
{
private static string ColorNames => string.Join("|", ColorConverter.ColorNames());
public override string Pattern => $"(?<{ValueGroup}>.+?)(?<{ExtraGroup}> ({ColorNames}|\\[[\\.,\\d ]*\\]{{1}}))?";
protected virtual ELootRarity? Rarity => null;

public override void Execute(Match match)
{
TrackLootItem(match, Rarity);
}

private void TrackLootItem(Match match, ELootRarity? rarity = null)
{
var matchGroup = match.Groups[ValueGroup];
if (matchGroup is not {Success: true})
return;

Color? color = null;
var extraGroup = match.Groups[ExtraGroup];
if (extraGroup is {Success: true})
color = ColorConverter.Parse(extraGroup.Value);

TrackList.ShowTrackList(this, LootItems, LootItems.Track(matchGroup.Value, color, rarity));
}
}
31 changes: 31 additions & 0 deletions ConsoleCommands/BaseTrackListCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text.RegularExpressions;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal abstract class BaseTrackListCommand : LootItemsRelatedCommand
{
public override string Pattern => RequiredArgumentPattern;

protected static bool TryGetTrackListFilename(Match match, [NotNullWhen(true)] out string? filename)
{
filename = null;

var matchGroup = match.Groups[ValueGroup];
if (matchGroup is not {Success: true})
return false;

filename = matchGroup.Value;

if (!Path.IsPathRooted(filename))
filename = Path.Combine(Context.UserPath, filename);

if (!Path.HasExtension(filename))
filename += ".tl";

return true;
}
}
15 changes: 15 additions & 0 deletions ConsoleCommands/BuiltInCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal class BuiltInCommand(string name, Action action) : ConsoleCommandWithoutArgument
{
public override string Name => name;

public override void Execute()
{
action();
}
}
18 changes: 18 additions & 0 deletions ConsoleCommands/ConsoleCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using EFT.UI;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal abstract class ConsoleCommand
{
public abstract string Name { get; }

internal void AddConsoleLog(string log)
{
if (PreloaderUI.Instantiated)
ConsoleScreen.Log(log);
}

public abstract void Register();
}
38 changes: 38 additions & 0 deletions ConsoleCommands/ConsoleCommandWithArgument.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Text.RegularExpressions;
using EFT.UI;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal abstract class ConsoleCommandWithArgument : ConsoleCommand
{
public abstract string Pattern { get; }

public abstract void Execute(Match match);

protected const string ValueGroup = "value";
protected const string ExtraGroup = "extra";

protected const string RequiredArgumentPattern = $"(?<{ValueGroup}>.+)";
protected const string OptionalArgumentPattern = $"(?<{ValueGroup}>.*)";

public override void Register()
{
#if DEBUG
AddConsoleLog($"Registering {Name} command with arguments...");
#endif
ConsoleScreen.Processor.RegisterCommand(Name, (string args) =>
{
var regex = new Regex("^" + Pattern + "$");
if (regex.IsMatch(args))
{
Execute(regex.Match(args));
}
else
{
ConsoleScreen.LogError("Invalid arguments");
}
});
}
}
18 changes: 18 additions & 0 deletions ConsoleCommands/ConsoleCommandWithoutArgument.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using EFT.UI;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

internal abstract class ConsoleCommandWithoutArgument : ConsoleCommand
{
public abstract void Execute();

public override void Register()
{
#if DEBUG
AddConsoleLog($"Registering {Name} command...");
#endif
ConsoleScreen.Processor.RegisterCommand(Name, Execute);
}
}
54 changes: 54 additions & 0 deletions ConsoleCommands/Dump.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.IO;
using EFT.Trainer.Features;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.SceneManagement;

#nullable enable

namespace EFT.Trainer.ConsoleCommands;

[UsedImplicitly]
internal class Dump : ConsoleCommandWithoutArgument
{
public override string Name => "dump";

public override void Execute()
{
var dumpfolder = Path.Combine(Context.UserPath, "Dumps");
var thisDump = Path.Combine(dumpfolder, $"{DateTime.Now:yyyyMMdd-HHmmss}");

Directory.CreateDirectory(thisDump);

AddConsoleLog("Dumping scenes...");
for (int i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
if (!scene.isLoaded)
continue;

var json = SceneDumper.DumpScene(scene).ToPrettyJson();
File.WriteAllText(Path.Combine(thisDump, GetSafeFilename($"@scene - {scene.name}.txt")), json);
}

AddConsoleLog("Dumping game objects...");
foreach (var go in UnityEngine.Object.FindObjectsOfType<GameObject>())
{
if (go == null || go.transform.parent != null || !go.activeSelf)
continue;

var filename = GetSafeFilename(go.name + "-" + go.GetHashCode() + ".txt");
var json = SceneDumper.DumpGameObject(go).ToPrettyJson();
File.WriteAllText(Path.Combine(thisDump, filename), json);
}

AddConsoleLog($"Dump created in {thisDump}");
}

private static string GetSafeFilename(string filename)
{
return string.Join("_", filename.Split(Path.GetInvalidFileNameChars()));
}

}
Loading

0 comments on commit 21868b3

Please sign in to comment.