Skip to content
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
30 changes: 0 additions & 30 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,3 @@ jobs:
- uses: actions/checkout@v4
- name: Build Plugin
uses: redstrate/build-dalamud-plugin@main
with:
solution-dir: dalamud

build-webassembly:
name: "Build"
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name

steps:
- uses: actions/checkout@v4
- name: Add WebAssembly Target
run: |
rustup target add wasm32-unknown-unknown
- uses: actions/cache@v4
id: cache-deps
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install wasm-pack
if: steps.cache-deps.outputs.cache-hit != 'true'
run: |
cargo install wasm-pack
- name: Build
run: |
./scripts/build-web.sh
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions Auracite/Auracite.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Author": "redstrate",
"Name": "Auracite",
"Punchline": "Archive your character in a portable, generic format",
"Description": "Archive your character in a portable, generic format",
"Tags": [],
"RepoUrl": "https://github.com/redstrate/Auracite",
"IconUrl": "https://raw.githubusercontent.com/redstrate/Auracite/refs/heads/main/images/icon.png"
}
42 changes: 42 additions & 0 deletions Auracite/IStep.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using InteropGenerator.Runtime;
using Lumina.Excel;
using Lumina.Text.ReadOnly;

namespace Auracite;

public interface IStep : IDisposable
{
public event CompletedDelegate Completed;

void Run();

string StepName();
string StepDescription();
bool IsEnd()
{
return false;
}
bool NeedsUpdateEveryFrame()
{
return false;
}

delegate void CompletedDelegate();

public static NameValue SaveNameValue<T>(uint key, Func<T, ReadOnlySeString> fieldSelector) where T : struct, IExcelRow<T> {
var newValue = new NameValue();
var row = Plugin.DataManager.GetExcelSheet<T>()?.GetRow(key);
if (row != null) {
newValue.name = fieldSelector(row.Value).ToString();
}
newValue.value = key;

return newValue;
}

public static unsafe List<byte> ConsumeBitArray(BitArray array) {
return new List<byte>(new ReadOnlySpan<byte>(array.Pointer, array.ByteLength).ToArray());
}
}
197 changes: 197 additions & 0 deletions Auracite/Package.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

namespace Auracite;

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class InventoryItem
{
public int slot;
public uint quantity;
public uint id;
public ulong crafter_content_id;
public byte item_flags;
public ushort condition;
public ushort spiritbond_or_collectability;
public uint glamour_id;
public List<ushort> materia;

Check warning on line 17 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'materia' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public List<byte> materia_grades;

Check warning on line 18 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'materia_grades' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public List<byte> stains;

Check warning on line 19 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'stains' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
}

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class InventoryContainer
{
public List<InventoryItem> items;

Check warning on line 25 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'items' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
}

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class NameValue
{
public string name;

Check warning on line 31 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public uint value;
}

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class DayMonthValue
{
// TODO: add back datetime name once I can figure out how to calculate it
public int day;
public int month;
}

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class ClassJobLevel
{
public string name;

Check warning on line 46 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public int level;
public int exp;
public uint value;
}

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class Appearance
{
public int model_type;
public int height;
public int face_type;
public int hair_style;
public bool has_highlights;
public int skin_color;
public int eye_color;
public int hair_color;
public int hair_color2;
public int face_features;
public int face_features_color;
public int eyebrows;
public int eye_color2;
public int eye_shape;
public int nose_shape;
public int jaw_shape;
public int lip_style;
public int lip_color;
public int race_feature_size;
public int race_feature_type;
public int bust_size;
public int facepaint;
public int facepaint_color;
}

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class CharacterJson
{
public string name;

Check warning on line 83 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public NameValue world;

Check warning on line 84 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'world' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public NameValue data_center;

Check warning on line 85 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'data_center' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public NameValue city_state;

Check warning on line 86 in Auracite/Package.cs

View workflow job for this annotation

GitHub Actions / Build Plugin

Non-nullable field 'city_state' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
public DayMonthValue nameday;
public NameValue guardian;
public NameValue gender;
public NameValue tribe;
public NameValue race;
public List<ClassJobLevel> classjob_levels = new List<ClassJobLevel>();
public NameValue grand_company;
public List<byte> grand_company_ranks = new List<byte>(); // TODO: introduce as a NameValue
public NameValue title;
public string playtime;
public int voice;

// adventurer plate
public string? plate_title;
public bool? plate_title_is_prefix;
public string? plate_class_job;
public int plate_class_job_level;
public string? search_comment;

public bool is_battle_mentor;
public bool is_trade_mentor;
public bool is_novice;
public bool is_returner;
public short player_commendations;

// Appearance
public Appearance appearance = new Appearance();

// inventory
public InventoryContainer inventory1;
public InventoryContainer inventory2;
public InventoryContainer inventory3;
public InventoryContainer inventory4;

public InventoryContainer equipped;

public InventoryContainer currency;

public InventoryContainer armory_off_hand;
public InventoryContainer armory_head;
public InventoryContainer armory_body;
public InventoryContainer armory_hands;
public InventoryContainer armory_waist;
public InventoryContainer armory_legs;
public InventoryContainer armory_ear;
public InventoryContainer armory_neck;
public InventoryContainer armory_wrist;
public InventoryContainer armory_rings;
public InventoryContainer armory_soul_crystal;
public InventoryContainer armory_main_hand;

// unlocks
public List<byte> unlocks;
public List<byte> seen_active_help;
public List<byte> minions;
public List<byte> mounts;
public List<byte> orchestrion_rolls;
public List<byte> cutscene_seen;
public List<byte> ornaments;
public List<byte> caught_fish;
public List<byte> caught_spearfish;
public List<byte> adventures;
public List<byte> triple_triad_cards;
public List<byte> glasses_styles;
public List<byte> chocobo_taxi_stands;
public List<byte> titles;
public List<byte> unlocked_companion_equip;

// aether currents
public List<byte> comp_flg_set;
public List<byte> unlocked_aether_currents;

// aetheryte
public List<byte> unlocked_aetherytes;
public int homepoint;
public List<ushort> favorite_aetherytes;
public int free_aetheryte;

// classjob
public int current_class;
public int first_class;
public int rested_exp;

// content
public List<byte> unlocked_special_content;
public List<byte> unlocked_raids;
public List<byte> unlocked_dungeons;
public List<byte> unlocked_guildhests;
public List<byte> unlocked_trials;
public List<byte> unlocked_crystalline_conflicts;
public List<byte> unlocked_frontlines;
public List<byte> cleared_raids;
public List<byte> cleared_dungeons;
public List<byte> cleared_guildhests;
public List<byte> cleared_trials;
public List<byte> cleared_crystalline_conflicts;
public List<byte> cleared_frontlines;
public List<byte> cleared_masked_carnivale;
public List<byte> unlocked_misc_content;
public List<byte> cleared_misc_content;

// quest
public List<byte> completed_quests;

// volatile
public float position_x;
public float position_y;
public float position_z;
public float rotation;
public ushort zone_id;
}
108 changes: 108 additions & 0 deletions Auracite/Plugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using Dalamud.Game.Command;
using Dalamud.Interface.Windowing;
using Dalamud.IoC;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using SixLabors.ImageSharp;

namespace Auracite;

public sealed class Plugin : IDalamudPlugin
{
public static IStep? CurrentStep;
private readonly WindowSystem WindowSystem = new("Auracite");

private readonly List<Type> _steps =
[typeof(AppearanceStep), typeof(InventoryStep), typeof(MiscStep), typeof(PlaytimeStep), typeof(AdventurerPlateStep), typeof(TitleStep), typeof(EndStep)];

private int _stepIndex;

private readonly StepWindow StepWindow;

public static CharacterJson? package;
public static Image? portrait;
public static Image? base_plate;
public static Image? pattern_overlay;
public static Image? backing;
public static Image? top_border;
public static Image? bottom_border;
public static Image? portrait_frame;
public static Image? plate_frame;
public static Image? accent;

public Plugin()
{
CommandManager.AddHandler("/auracite", new CommandInfo(OnAuraciteCommand)
{
HelpMessage = "Start the archival process."
});

StepWindow = new StepWindow(this);
WindowSystem.AddWindow(StepWindow);

PluginInterface.UiBuilder.Draw += WindowSystem.Draw;
Framework.Update += CheckCurrentStep;
}

[PluginService] internal static IClientState ClientState { get; private set; } = null!;

[PluginService] internal static IObjectTable ObjectTable { get; private set; } = null!;

[PluginService] internal static IDalamudPluginInterface PluginInterface { get; private set; } = null!;

[PluginService] internal static IChatGui ChatGui { get; private set; } = null!;

[PluginService] internal static ICommandManager CommandManager { get; private set; } = null!;

[PluginService] internal static IDataManager DataManager { get; private set; } = null!;

[PluginService] internal static IFramework Framework { get; private set; } = null!;

public void Dispose()
{
CurrentStep?.Dispose();
WindowSystem.RemoveAllWindows();
}

private void OnAuraciteCommand(string command, string arguments)
{
if (CurrentStep == null)
{
_stepIndex = -1;
package = new CharacterJson();
NextStep();
StepWindow.IsOpen = true;
}
}

private void NextStep()
{
_stepIndex++;
if (_stepIndex >= _steps.Count)
{
CurrentStep?.Dispose();
CurrentStep = null;
StepWindow.IsOpen = false;
return;
}
CurrentStep = (IStep)Activator.CreateInstance(_steps[_stepIndex])!;
CurrentStep.Completed += NextStep;
CurrentStep.Run();
}

public void Stop()
{
CurrentStep = null;
StepWindow.IsOpen = false;
package = null;
}

private void CheckCurrentStep(IFramework framework)
{
if (CurrentStep != null && CurrentStep.NeedsUpdateEveryFrame()) {
CurrentStep.Run();
}
}
}
Loading
Loading