diff --git a/.gitignore b/.gitignore
index db41fce..37fd804 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
/target
.idea/
-config.json
\ No newline at end of file
+config.json
+.vs/
+obj/
+bin/
+*.user
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 52532dd..3415466 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -100,6 +100,7 @@ dependencies = [
"scraper",
"serde",
"serde_json",
+ "touche",
]
[[package]]
@@ -123,6 +124,12 @@ dependencies = [
"windows-targets",
]
+[[package]]
+name = "base64"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
[[package]]
name = "base64"
version = "0.22.1"
@@ -135,6 +142,15 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "bumpalo"
version = "3.16.0"
@@ -230,6 +246,25 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+[[package]]
+name = "cpufeatures"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
[[package]]
name = "cssparser"
version = "0.31.2"
@@ -264,6 +299,16 @@ dependencies = [
"syn",
]
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
[[package]]
name = "downloader"
version = "0.2.8"
@@ -452,6 +497,16 @@ dependencies = [
"byteorder",
]
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
[[package]]
name = "getopts"
version = "0.2.21"
@@ -478,6 +533,30 @@ version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
+[[package]]
+name = "headers"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
+dependencies = [
+ "base64 0.21.7",
+ "bytes",
+ "headers-core",
+ "http 0.2.12",
+ "httpdate",
+ "mime",
+ "sha1",
+]
+
+[[package]]
+name = "headers-core"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
+dependencies = [
+ "http 0.2.12",
+]
+
[[package]]
name = "heck"
version = "0.5.0"
@@ -504,6 +583,17 @@ dependencies = [
"syn",
]
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
[[package]]
name = "http"
version = "1.1.0"
@@ -522,7 +612,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
- "http",
+ "http 1.1.0",
]
[[package]]
@@ -533,7 +623,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [
"bytes",
"futures-util",
- "http",
+ "http 1.1.0",
"http-body",
"pin-project-lite",
]
@@ -544,6 +634,12 @@ version = "1.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
[[package]]
name = "hyper"
version = "1.4.1"
@@ -553,7 +649,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
- "http",
+ "http 1.1.0",
"http-body",
"httparse",
"itoa",
@@ -588,7 +684,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
- "http",
+ "http 1.1.0",
"http-body",
"hyper",
"pin-project-lite",
@@ -748,6 +844,16 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
[[package]]
name = "object"
version = "0.36.4"
@@ -1051,11 +1157,11 @@ version = "0.12.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63"
dependencies = [
- "base64",
+ "base64 0.22.1",
"bytes",
"futures-core",
"futures-util",
- "http",
+ "http 1.1.0",
"http-body",
"http-body-util",
"hyper",
@@ -1109,7 +1215,7 @@ version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
dependencies = [
- "base64",
+ "base64 0.22.1",
"rustls-pki-types",
]
@@ -1251,6 +1357,17 @@ dependencies = [
"stable_deref_trait",
]
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
[[package]]
name = "shlex"
version = "1.3.0"
@@ -1390,6 +1507,15 @@ dependencies = [
"syn",
]
+[[package]]
+name = "threadpool"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
+dependencies = [
+ "num_cpus",
+]
+
[[package]]
name = "tinyvec"
version = "1.8.0"
@@ -1430,6 +1556,18 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "touche"
+version = "0.0.10"
+source = "git+https://github.com/redstrate/touche#8979a3367dcf79d605d818157ea187a52608fed9"
+dependencies = [
+ "headers",
+ "http 0.2.12",
+ "httparse",
+ "thiserror",
+ "threadpool",
+]
+
[[package]]
name = "tower-service"
version = "0.3.3"
@@ -1461,6 +1599,12 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
[[package]]
name = "unicode-bidi"
version = "0.3.15"
diff --git a/Cargo.toml b/Cargo.toml
index 7bd33c3..ffc8ec4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,4 +23,9 @@ clap_derive = "4.5"
downloader = "0.2"
# Used to generate the HTML page to easily preview your exported data
-minijinja = "2.0"
\ No newline at end of file
+minijinja = "2.0"
+
+# Used to communicate with the Dalamud plugin
+# Needs my fork for allowing server shutdown
+# TODO: upstream this or poke upstream to add this
+touche = { git = "https://github.com/redstrate/touche" }
\ No newline at end of file
diff --git a/dalamud/Auracite.sln b/dalamud/Auracite.sln
new file mode 100644
index 0000000..2369872
--- /dev/null
+++ b/dalamud/Auracite.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29709.97
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Auracite", "Auracite\Auracite.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.ActiveCfg = Debug|x64
+ {13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.Build.0 = Debug|x64
+ {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.ActiveCfg = Release|x64
+ {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64
+ {4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Debug|x64.ActiveCfg = Debug|x64
+ {4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Debug|x64.Build.0 = Debug|x64
+ {4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Release|x64.ActiveCfg = Release|x64
+ {4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B17E85B1-5F60-4440-9F9A-3DDE877E8CDF}
+ EndGlobalSection
+EndGlobal
diff --git a/dalamud/Auracite/Auracite.csproj b/dalamud/Auracite/Auracite.csproj
new file mode 100644
index 0000000..43f8a48
--- /dev/null
+++ b/dalamud/Auracite/Auracite.csproj
@@ -0,0 +1,9 @@
+
+
+
+
+
+ 1.0.0.0
+ NeoVARC
+
+
diff --git a/dalamud/Auracite/Auracite.json b/dalamud/Auracite/Auracite.json
new file mode 100644
index 0000000..2a06978
--- /dev/null
+++ b/dalamud/Auracite/Auracite.json
@@ -0,0 +1,8 @@
+{
+ "Author": "redstrate",
+ "Name": "Auracite",
+ "Punchline": "Export your FFXIV character in portable, generic formats",
+ "Description": "Export your FFXIV character in portable, generic formats.",
+ "Tags": [],
+ "RepoUrl": "https://github.com/redstrate/Auracite"
+}
diff --git a/dalamud/Auracite/Dalamud.Plugin.Bootstrap.targets b/dalamud/Auracite/Dalamud.Plugin.Bootstrap.targets
new file mode 100644
index 0000000..d9fe281
--- /dev/null
+++ b/dalamud/Auracite/Dalamud.Plugin.Bootstrap.targets
@@ -0,0 +1,12 @@
+
+
+
+ $(appdata)\XIVLauncher\addon\Hooks\dev\
+ $(HOME)/.xlcore/dalamud/Hooks/dev/
+ $(HOME)/.local/share/astra/dalamud/local/
+ $(HOME)/Library/Application Support/XIV on Mac/dalamud/Hooks/dev/
+ $(DALAMUD_HOME)/
+
+
+
+
diff --git a/dalamud/Auracite/IStep.cs b/dalamud/Auracite/IStep.cs
new file mode 100644
index 0000000..79245a6
--- /dev/null
+++ b/dalamud/Auracite/IStep.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Auracite;
+
+public interface IStep
+{
+ public event CompletedDelegate Completed;
+
+ string StepName();
+ string StepDescription();
+
+ delegate void CompletedDelegate();
+}
\ No newline at end of file
diff --git a/dalamud/Auracite/PlaytimeStep.cs b/dalamud/Auracite/PlaytimeStep.cs
new file mode 100644
index 0000000..c910f46
--- /dev/null
+++ b/dalamud/Auracite/PlaytimeStep.cs
@@ -0,0 +1,41 @@
+using System;
+using Dalamud.Game.Text;
+using Dalamud.Game.Text.SeStringHandling;
+
+namespace Auracite;
+
+public class PlaytimeStep : IStep, IDisposable
+{
+ public PlaytimeStep()
+ {
+ Plugin.ChatGui.ChatMessage += OnChatMessage;
+ }
+
+ public void Dispose()
+ {
+ Plugin.ChatGui.ChatMessage -= OnChatMessage;
+ }
+
+ public event IStep.CompletedDelegate? Completed;
+
+ public string StepName()
+ {
+ return "Playtime";
+ }
+
+ public string StepDescription()
+ {
+ return "Type /playtime into the chat window.";
+ }
+
+ private void OnChatMessage(XivChatType type, int timestamp, ref SeString sender, ref SeString message,
+ ref bool ishandled)
+ {
+ var msgString = message.ToString();
+ if (msgString.Contains("Total Play Time:") && type == XivChatType.SystemMessage)
+ {
+ Plugin.package.playtime = msgString.Split(": ")[1]; // TODO: lol
+ Completed?.Invoke();
+ }
+ }
+}
\ No newline at end of file
diff --git a/dalamud/Auracite/Plugin.cs b/dalamud/Auracite/Plugin.cs
new file mode 100644
index 0000000..4c62bbf
--- /dev/null
+++ b/dalamud/Auracite/Plugin.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using Dalamud.Game.Command;
+using Dalamud.Interface.Windowing;
+using Dalamud.IoC;
+using Dalamud.Plugin;
+using Dalamud.Plugin.Services;
+using Newtonsoft.Json;
+
+namespace Auracite;
+
+public sealed class Plugin : IDalamudPlugin
+{
+ public static IStep? CurrentStep;
+ private readonly WindowSystem WindowSystem = new("Auracite");
+
+ private readonly List _steps =
+ [typeof(PlaytimeStep)];
+
+ private int _stepIndex;
+
+ private readonly StepWindow StepWindow;
+
+ public class Package
+ {
+ public string playtime;
+ }
+
+ public static Package? package;
+
+ public Plugin()
+ {
+ CommandManager.AddHandler("/auracite", new CommandInfo(OnAuraciteCommand)
+ {
+ HelpMessage = "Start the server."
+ });
+
+ StepWindow = new StepWindow();
+ WindowSystem.AddWindow(StepWindow);
+
+ PluginInterface.UiBuilder.Draw += WindowSystem.Draw;
+ }
+
+ [PluginService] internal static IClientState ClientState { 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!;
+
+ public void Dispose()
+ {
+ WindowSystem.RemoveAllWindows();
+ }
+
+ private void OnAuraciteCommand(string command, string arguments)
+ {
+ if (arguments == "begin" && CurrentStep == null)
+ {
+ _stepIndex = -1;
+ package = new Package();
+ NextStep();
+ StepWindow.IsOpen = true;
+ }
+ }
+
+ private void NextStep()
+ {
+ _stepIndex++;
+ if (_stepIndex >= _steps.Count)
+ {
+ CurrentStep = null;
+ StepWindow.IsOpen = false;
+ SendPackage();
+ return;
+ }
+ CurrentStep = (IStep)Activator.CreateInstance(_steps[_stepIndex])!;
+ CurrentStep.Completed += NextStep;
+ }
+
+ private void SendPackage()
+ {
+ var client = new HttpClient();
+ client.PostAsync("http://127.0.0.1:8000/package", new StringContent(JsonConvert.SerializeObject(package)));
+ package = null;
+ }
+}
\ No newline at end of file
diff --git a/dalamud/Auracite/StepWindow.cs b/dalamud/Auracite/StepWindow.cs
new file mode 100644
index 0000000..377cbc6
--- /dev/null
+++ b/dalamud/Auracite/StepWindow.cs
@@ -0,0 +1,28 @@
+using System;
+using Dalamud.Interface.Windowing;
+using ImGuiNET;
+
+namespace Auracite;
+
+public class StepWindow()
+ : Window("Step Window"), IDisposable
+{
+ public void Dispose()
+ {
+ }
+
+ public override void Draw()
+ {
+ if (Plugin.CurrentStep != null)
+ {
+ ImGui.Text(Plugin.CurrentStep.StepName());
+ ImGui.Text(Plugin.CurrentStep.StepDescription());
+
+ ImGui.TextDisabled("Step requires manual user action.");
+ }
+ else
+ {
+ ImGui.Text("Auracite is not running.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/dalamud/Auracite/packages.lock.json b/dalamud/Auracite/packages.lock.json
new file mode 100644
index 0000000..19fcea9
--- /dev/null
+++ b/dalamud/Auracite/packages.lock.json
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "dependencies": {
+ "net8.0-windows7.0": {
+ "DalamudPackager": {
+ "type": "Direct",
+ "requested": "[2.1.13, )",
+ "resolved": "2.1.13",
+ "contentHash": "rMN1omGe8536f4xLMvx9NwfvpAc9YFFfeXJ1t4P4PE6Gu8WCIoFliR1sh07hM+bfODmesk/dvMbji7vNI+B/pQ=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dalamud/global.json b/dalamud/global.json
new file mode 100644
index 0000000..9e5e1fd
--- /dev/null
+++ b/dalamud/global.json
@@ -0,0 +1,7 @@
+{
+ "sdk": {
+ "version": "6.0.0",
+ "rollForward": "latestMajor",
+ "allowPrerelease": true
+ }
+}
\ No newline at end of file
diff --git a/src/data.rs b/src/data.rs
index dae535c..f854e53 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -17,6 +17,7 @@ pub struct CharacterData {
pub nameday: String,
pub guardian: String,
pub currencies: Currencies,
+ pub playtime: String,
#[serde(skip)]
pub face_url: String,
diff --git a/src/main.rs b/src/main.rs
index ffed92d..984f768 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,8 +7,13 @@ use crate::downloader::download;
use crate::html::write_html;
use crate::parser::{parse_lodestone, parse_search};
use clap::Parser;
+use serde::Deserialize;
+use std::convert::Infallible;
use std::fs::{read, write};
use std::path::Path;
+use std::sync::{Arc, Mutex};
+use touche::server::Service;
+use touche::{Body, HttpBody, Request, Response, Server, StatusCode};
const LODESTONE_HOST: &str = "https://na.finalfantasyxiv.com";
@@ -17,6 +22,41 @@ const LODESTONE_HOST: &str = "https://na.finalfantasyxiv.com";
struct Args {
#[arg(short, long, help = "The character's name.")]
name: String,
+
+ #[arg(short, long, help = "Whether to import more data from the Auracite Dalamud plugin.")]
+ dalamud: bool,
+}
+
+#[derive(Default, Deserialize, Clone)]
+struct Package {
+ playtime: String,
+}
+
+#[derive(Clone)]
+struct PackageService<'a> {
+ wants_stop: Arc>, // TODO: THIS IS TERRIBLE STOP STOP STOP
+ package: &'a Arc>,
+}
+
+impl Service for PackageService<'_> {
+ type Body = &'static str;
+ type Error = Infallible;
+
+ fn call(&self, req: Request) -> Result, Self::Error> {
+ *self.package.lock().unwrap() = serde_json::from_str(&String::from_utf8(req.into_body().into_bytes().unwrap()).unwrap()).unwrap();
+
+ *self.wants_stop.lock().unwrap() = true;
+
+ Ok(Response::builder()
+ .status(StatusCode::OK)
+ .body("")
+ .unwrap())
+ }
+
+ // TODO: NO NO NO NO
+ fn wants_stop(&self) -> bool {
+ *self.wants_stop.lock().unwrap()
+ }
}
fn main() {
@@ -29,7 +69,7 @@ fn main() {
&format!("{LODESTONE_HOST}/lodestone/character/?q={}", args.name),
search_page_path,
)
- .expect("Failed to download the search page from the Lodestone.");
+ .expect("Failed to download the search page from the Lodestone.");
let href = parse_search(&String::from_utf8(read(search_page_path).unwrap()).unwrap());
if href.is_empty() {
@@ -40,7 +80,7 @@ fn main() {
download(&format!("{LODESTONE_HOST}{}", href), char_page_path)
.expect("Failed to download the character page from the Lodestone.");
- let char_data = parse_lodestone(&String::from_utf8(read(char_page_path).unwrap()).unwrap());
+ let mut char_data = parse_lodestone(&String::from_utf8(read(char_page_path).unwrap()).unwrap());
let character_folder = Path::new(&args.name);
if !character_folder.exists() {
@@ -52,13 +92,25 @@ fn main() {
&char_data.portrait_url,
&character_folder.join("portrait.jpg"),
)
- .expect("Failed to download the character portrait image.");
+ .expect("Failed to download the character portrait image.");
}
if !char_data.face_url.is_empty() {
download(&char_data.face_url, &character_folder.join("face.jpg"))
.expect("Failed to download the character face image.");
}
+ if args.dalamud {
+ println!("Now waiting for the Dalamud plugin. Type /auracite begin in chat.");
+
+ let package = Arc::new(Mutex::new(Package::default()));
+
+ Server::bind("0.0.0.0:8000").serve_single_thread(PackageService { wants_stop: Arc::new(Mutex::new(false)), package: &package }).unwrap();
+
+ let package = &*package.lock().unwrap();
+
+ char_data.playtime = package.playtime.parse().unwrap();
+ }
+
let serialized = serde_json::to_string(&char_data).unwrap();
write(character_folder.join("character.json"), serialized)
.expect("Failed to write the character JSON file.");
@@ -76,5 +128,5 @@ fn main() {
.into_string()
.unwrap(),
)
- .expect("Failed to write the character HTML file.");
+ .expect("Failed to write the character HTML file.");
}