mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-10-17 07:59:19 +02:00
read rolling stock from dynamic/*/*/textures.txt, drop vehicles.json
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StarterNG.Classes;
|
||||
@@ -25,43 +26,25 @@ public sealed class GameData
|
||||
public bool Loaded { get; private set; }
|
||||
|
||||
public void Load(IProgress<LoadStatus>? progress = null,
|
||||
string vehiclesDir = "databases/vehicles/",
|
||||
string sceneryDir = "scenery/",
|
||||
string miniDir = "textures/mini/")
|
||||
string miniDir = "textures/mini/",
|
||||
string dynamicRoot = "dynamic")
|
||||
{
|
||||
if (Loaded)
|
||||
return;
|
||||
|
||||
var vehicleFiles = VehicleDatabase.EnumerateFiles(vehiclesDir);
|
||||
var scnFiles = EnumerateScenery(sceneryDir);
|
||||
int total = Math.Max(1, vehicleFiles.Count + scnFiles.Count);
|
||||
int total = Math.Max(1, scnFiles.Count);
|
||||
int done = 0;
|
||||
|
||||
Vehicles.BeginLoad();
|
||||
foreach (string file in vehicleFiles)
|
||||
{
|
||||
progress?.Report(new LoadStatus((double)done / total, LoadPhase.Vehicles,
|
||||
Path.GetFileName(file)));
|
||||
try { Vehicles.LoadFile(file); }
|
||||
catch { }
|
||||
done++;
|
||||
}
|
||||
try
|
||||
{
|
||||
int legacy = Vehicles.ImportLegacy();
|
||||
if (legacy > 0)
|
||||
Infrastructure.Diagnostics.Log($"textures.txt: wczytano {legacy} tekstur");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Infrastructure.Diagnostics.Log("textures.txt import", ex);
|
||||
}
|
||||
progress?.Report(new LoadStatus(0, LoadPhase.Vehicles, "textures.txt"));
|
||||
int vehicles = Vehicles.LoadFromTexturesTxt(dynamicRoot);
|
||||
if (vehicles == 0)
|
||||
Infrastructure.Diagnostics.Log($"{dynamicRoot}: brak plikow textures.txt");
|
||||
|
||||
Vehicles.EndLoad();
|
||||
|
||||
VehicleDatabase.PreloadMiniIndex(miniDir);
|
||||
|
||||
Physics.PreloadIndex();
|
||||
Parallel.Invoke(
|
||||
() => VehicleDatabase.PreloadMiniIndex(miniDir),
|
||||
() => Physics.PreloadIndex());
|
||||
|
||||
var sceneryLock = new object();
|
||||
var doneCount = done;
|
||||
@@ -79,7 +62,10 @@ public sealed class GameData
|
||||
Path.GetFileName(file)));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
StarterNG.Infrastructure.Diagnostics.Log($"scenery/{Path.GetFileName(file)}", ex);
|
||||
}
|
||||
});
|
||||
done = doneCount;
|
||||
|
||||
@@ -101,7 +87,10 @@ public sealed class GameData
|
||||
lock (sceneryLock)
|
||||
Sceneries.Add(scenery);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
StarterNG.Infrastructure.Diagnostics.Log($"scenery/{Path.GetFileName(file)}", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Text;
|
||||
|
||||
namespace StarterNG.Classes;
|
||||
|
||||
public static class LegacyTextureDatabase
|
||||
public static class TexturesTxt
|
||||
{
|
||||
public static List<string> EnumerateFiles(string dynamicRoot = "dynamic")
|
||||
{
|
||||
@@ -139,8 +139,7 @@ public static class LegacyTextureDatabase
|
||||
Id = groupId,
|
||||
Category = categorySign,
|
||||
Mini = first.Mini,
|
||||
Archived = archived,
|
||||
Implicit = true
|
||||
Archived = archived
|
||||
});
|
||||
|
||||
var texture = new VehicleTexture
|
||||
@@ -148,6 +147,8 @@ public static class LegacyTextureDatabase
|
||||
Uuid = $"legacy:{dir}{skin}",
|
||||
Directory = dir,
|
||||
Skinfile = skin,
|
||||
Wreck = skin.Contains("wreck", StringComparison.OrdinalIgnoreCase) ||
|
||||
skin.Contains("wrak", StringComparison.OrdinalIgnoreCase),
|
||||
Model = first.Model,
|
||||
Group = groupId,
|
||||
MiniRef = first.Mini,
|
||||
@@ -2,78 +2,68 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StarterNG.Classes;
|
||||
|
||||
public class VehicleEntry
|
||||
{
|
||||
[JsonPropertyName("uuid")] public string? Uuid { get; set; }
|
||||
[JsonPropertyName("schema_version")] public int SchemaVersion { get; set; }
|
||||
[JsonPropertyName("groups")] public List<VehicleGroup> Groups { get; set; } = new();
|
||||
[JsonPropertyName("textures")] public List<VehicleTexture> Textures { get; set; } = new();
|
||||
[JsonPropertyName("sets")] public List<VehicleSet> Sets { get; set; } = new();
|
||||
[JsonPropertyName("unknown")] public List<string> Unknown { get; set; } = new();
|
||||
}
|
||||
|
||||
public class VehicleEntryCollection
|
||||
{
|
||||
[JsonPropertyName("vehicles")] public List<VehicleEntry> Vehicles { get; set; } = new();
|
||||
public string? Uuid { get; set; }
|
||||
public List<VehicleGroup> Groups { get; set; } = new();
|
||||
public List<VehicleTexture> Textures { get; set; } = new();
|
||||
public List<VehicleSet> Sets { get; set; } = new();
|
||||
}
|
||||
|
||||
public class VehicleGroup
|
||||
{
|
||||
[JsonPropertyName("id")] public string Id { get; set; } = "";
|
||||
[JsonPropertyName("category")] public string? Category { get; set; }
|
||||
[JsonPropertyName("mini")] public string? Mini { get; set; }
|
||||
[JsonPropertyName("archived")] public bool Archived { get; set; }
|
||||
[JsonPropertyName("implicit")] public bool Implicit { get; set; }
|
||||
public string Id { get; set; } = "";
|
||||
public string? Category { get; set; }
|
||||
public string? Mini { get; set; }
|
||||
public bool Archived { get; set; }
|
||||
}
|
||||
|
||||
public class VehicleTexture
|
||||
{
|
||||
[JsonPropertyName("uuid")] public string? Uuid { get; set; }
|
||||
[JsonPropertyName("directory")] public string Directory { get; set; } = "";
|
||||
[JsonPropertyName("skinfile")] public string Skinfile { get; set; } = "";
|
||||
[JsonPropertyName("model")] public string? Model { get; set; }
|
||||
[JsonPropertyName("group")] public string? Group { get; set; }
|
||||
[JsonPropertyName("mini_ref")] public string? MiniRef { get; set; }
|
||||
[JsonPropertyName("texture_mini")] public string? TextureMini { get; set; }
|
||||
[JsonPropertyName("wreck")] public bool Wreck { get; set; }
|
||||
[JsonPropertyName("aliases")] public List<VehicleAlias> Aliases { get; set; } = new();
|
||||
[JsonPropertyName("meta")] public VehicleMeta? Meta { get; set; }
|
||||
public string? Uuid { get; set; }
|
||||
public string Directory { get; set; } = "";
|
||||
public string Skinfile { get; set; } = "";
|
||||
public string? Model { get; set; }
|
||||
public string? Group { get; set; }
|
||||
public string? MiniRef { get; set; }
|
||||
public string? TextureMini { get; set; }
|
||||
public bool Wreck { get; set; }
|
||||
public List<VehicleAlias> Aliases { get; set; } = new();
|
||||
public VehicleMeta? Meta { get; set; }
|
||||
|
||||
[JsonIgnore] public string FullPath => Directory + Skinfile;
|
||||
public string FullPath => Directory + Skinfile;
|
||||
|
||||
[JsonIgnore] public string ResolvedClass { get; internal set; } = "";
|
||||
public string ResolvedClass { get; internal set; } = "";
|
||||
|
||||
[JsonIgnore] public string? ResolvedCategory { get; internal set; }
|
||||
public string? ResolvedCategory { get; internal set; }
|
||||
|
||||
[JsonIgnore] public bool ResolvedArchived { get; internal set; }
|
||||
public bool ResolvedArchived { get; internal set; }
|
||||
}
|
||||
|
||||
public class VehicleAlias
|
||||
{
|
||||
[JsonPropertyName("model")] public string? Model { get; set; }
|
||||
[JsonPropertyName("group")] public string? Group { get; set; }
|
||||
[JsonPropertyName("mini_ref")] public string? MiniRef { get; set; }
|
||||
[JsonPropertyName("texture_mini")] public string? TextureMini { get; set; }
|
||||
public string? Model { get; set; }
|
||||
public string? Group { get; set; }
|
||||
public string? MiniRef { get; set; }
|
||||
public string? TextureMini { get; set; }
|
||||
}
|
||||
|
||||
public class VehicleMeta
|
||||
{
|
||||
[JsonPropertyName("raw")] public string? Raw { get; set; }
|
||||
[JsonPropertyName("version")] public string? Version { get; set; }
|
||||
[JsonPropertyName("vehicle")] public string? Vehicle { get; set; }
|
||||
[JsonPropertyName("operator")] public string? Operator { get; set; }
|
||||
[JsonPropertyName("depot")] public string? Depot { get; set; }
|
||||
[JsonPropertyName("revision_date")] public string? RevisionDate { get; set; }
|
||||
[JsonPropertyName("revision_place")] public string? RevisionPlace { get; set; }
|
||||
[JsonPropertyName("texture_author")] public string? TextureAuthor { get; set; }
|
||||
[JsonPropertyName("photo_author")] public string? PhotoAuthor { get; set; }
|
||||
[JsonPropertyName("extra")] public List<string> Extra { get; set; } = new();
|
||||
public string? Raw { get; set; }
|
||||
public string? Version { get; set; }
|
||||
public string? Vehicle { get; set; }
|
||||
public string? Operator { get; set; }
|
||||
public string? Depot { get; set; }
|
||||
public string? RevisionDate { get; set; }
|
||||
public string? RevisionPlace { get; set; }
|
||||
public string? TextureAuthor { get; set; }
|
||||
public string? PhotoAuthor { get; set; }
|
||||
public List<string> Extra { get; set; } = new();
|
||||
}
|
||||
|
||||
public class VehicleDatabase
|
||||
@@ -88,20 +78,22 @@ public class VehicleDatabase
|
||||
|
||||
public Dictionary<string, VehicleTexture> TextureBySkin { get; } = new();
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOpts = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
AllowTrailingCommas = true,
|
||||
TypeInfoResolver = VehicleJsonContext.Default,
|
||||
};
|
||||
|
||||
public void Load(string directory = "databases/vehicles/")
|
||||
public int LoadFromTexturesTxt(string dynamicRoot = "dynamic")
|
||||
{
|
||||
BeginLoad();
|
||||
foreach (string file in EnumerateFiles(directory))
|
||||
LoadFile(file);
|
||||
|
||||
int count = 0;
|
||||
foreach (string file in TexturesTxt.EnumerateFiles(dynamicRoot))
|
||||
{
|
||||
var entry = TexturesTxt.Parse(file, dynamicRoot);
|
||||
if (entry is null) continue;
|
||||
|
||||
count += entry.Textures.Count;
|
||||
Ingest(entry);
|
||||
}
|
||||
|
||||
EndLoad();
|
||||
return count;
|
||||
}
|
||||
|
||||
public void BeginLoad()
|
||||
@@ -120,79 +112,6 @@ public class VehicleDatabase
|
||||
BuildTextureIndex();
|
||||
}
|
||||
|
||||
public static List<string> EnumerateFiles(string directory = "databases/vehicles/")
|
||||
{
|
||||
if (!Directory.Exists(directory))
|
||||
return new List<string>();
|
||||
|
||||
string merged = Path.Combine(directory, "vehicles.json");
|
||||
if (File.Exists(merged))
|
||||
return new List<string> { merged };
|
||||
|
||||
return Directory.GetFiles(directory, "*.json").ToList();
|
||||
}
|
||||
|
||||
public void LoadFile(string file)
|
||||
{
|
||||
if (string.Equals(Path.GetFileName(file), "vehicles.json", StringComparison.OrdinalIgnoreCase))
|
||||
LoadMerged(file);
|
||||
else
|
||||
LoadEntryFile(file);
|
||||
}
|
||||
|
||||
private void LoadMerged(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
var collection = JsonSerializer.Deserialize(
|
||||
File.ReadAllText(file),
|
||||
(JsonTypeInfo<VehicleEntryCollection>)JsonOpts.GetTypeInfo(typeof(VehicleEntryCollection)));
|
||||
if (collection?.Vehicles is null) return;
|
||||
foreach (var entry in collection.Vehicles)
|
||||
Ingest(entry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadEntryFile(string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
var entry = JsonSerializer.Deserialize(
|
||||
File.ReadAllText(file),
|
||||
(JsonTypeInfo<VehicleEntry>)JsonOpts.GetTypeInfo(typeof(VehicleEntry)));
|
||||
if (entry is not null)
|
||||
Ingest(entry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public int ImportLegacy(string dynamicRoot = "dynamic")
|
||||
{
|
||||
int added = 0;
|
||||
foreach (string file in LegacyTextureDatabase.EnumerateFiles(dynamicRoot))
|
||||
{
|
||||
var entry = LegacyTextureDatabase.Parse(file, dynamicRoot);
|
||||
if (entry is null) continue;
|
||||
|
||||
entry.Textures.RemoveAll(t =>
|
||||
TextureBySkin.ContainsKey(
|
||||
Path.GetFileNameWithoutExtension(t.Skinfile).ToLowerInvariant()));
|
||||
|
||||
if (entry.Textures.Count == 0) continue;
|
||||
|
||||
added += entry.Textures.Count;
|
||||
Ingest(entry);
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
private void Ingest(VehicleEntry entry)
|
||||
{
|
||||
foreach (var group in entry.Groups)
|
||||
@@ -386,14 +305,8 @@ public class VehicleDatabase
|
||||
|
||||
public class VehicleSet
|
||||
{
|
||||
[JsonPropertyName("uuid")] public string? Uuid { get; set; }
|
||||
[JsonPropertyName("mode")] public string? Mode { get; set; }
|
||||
[JsonPropertyName("count")] public int Count { get; set; }
|
||||
[JsonPropertyName("texture_refs")] public List<string> TextureRefs { get; set; } = new();
|
||||
}
|
||||
|
||||
[JsonSerializable(typeof(VehicleEntry))]
|
||||
[JsonSerializable(typeof(VehicleEntryCollection))]
|
||||
internal partial class VehicleJsonContext : JsonSerializerContext
|
||||
{
|
||||
public string? Uuid { get; set; }
|
||||
public string? Mode { get; set; }
|
||||
public int Count { get; set; }
|
||||
public List<string> TextureRefs { get; set; } = new();
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<String key="Vehicle">Vozidlo</String>
|
||||
<String key="Crew">s osádkou</String>
|
||||
<String key="Reversed">otočeno</String>
|
||||
<String key="NoVehicles">Ve složce databases/vehicles/ nebyla nalezena žádná vozidla.</String>
|
||||
<String key="NoVehicles">Ve složce dynamic/**/textures.txt nebyla nalezena žádná vozidla.</String>
|
||||
<String key="ConsistEmpty">Přidejte vozidla z databáze vlevo nebo načtěte existující soupravu ze souboru scenérie.</String>
|
||||
<String key="TipMoveLeft">Posunout doleva</String>
|
||||
<String key="TipMoveRight">Posunout doprava</String>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<String key="Vehicle">Vehicle</String>
|
||||
<String key="Crew">with crew</String>
|
||||
<String key="Reversed">reversed</String>
|
||||
<String key="NoVehicles">No vehicles found in databases/vehicles/.</String>
|
||||
<String key="NoVehicles">No vehicles found in dynamic/**/textures.txt.</String>
|
||||
<String key="ConsistEmpty">Add vehicles from the database on the left, or load an existing consist from a scenery file.</String>
|
||||
<String key="TipMoveLeft">Move left</String>
|
||||
<String key="TipMoveRight">Move right</String>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<String key="Vehicle">Jármű</String>
|
||||
<String key="Crew">személyzettel</String>
|
||||
<String key="Reversed">megfordítva</String>
|
||||
<String key="NoVehicles">A databases/vehicles/ mappában nem található jármű.</String>
|
||||
<String key="NoVehicles">A dynamic/**/textures.txt fájlokban nem található jármű.</String>
|
||||
<String key="ConsistEmpty">Adjon hozzá járműveket a bal oldali adatbázisból, vagy töltsön be meglévő szerelvényt egy pályafájlból.</String>
|
||||
<String key="TipMoveLeft">Mozgatás balra</String>
|
||||
<String key="TipMoveRight">Mozgatás jobbra</String>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<String key="Vehicle">Pojazd</String>
|
||||
<String key="Crew">z obsadą</String>
|
||||
<String key="Reversed">obrócony</String>
|
||||
<String key="NoVehicles">Nie znaleziono pojazdów w databases/vehicles/.</String>
|
||||
<String key="NoVehicles">Nie znaleziono pojazdów w dynamic/**/textures.txt.</String>
|
||||
<String key="ConsistEmpty">Dodaj pojazdy z bazy po lewej stronie lub wczytaj istniejący skład z pliku scenerii.</String>
|
||||
<String key="TipMoveLeft">Przesuń w lewo</String>
|
||||
<String key="TipMoveRight">Przesuń w prawo</String>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<String key="Vehicle">Единица</String>
|
||||
<String key="Crew">с бригадой</String>
|
||||
<String key="Reversed">развёрнут</String>
|
||||
<String key="NoVehicles">В databases/vehicles/ подвижной состав не найден.</String>
|
||||
<String key="NoVehicles">В dynamic/**/textures.txt подвижной состав не найден.</String>
|
||||
<String key="ConsistEmpty">Добавьте единицы из базы слева или загрузите готовый состав из файла сценерии.</String>
|
||||
<String key="TipMoveLeft">Сдвинуть влево</String>
|
||||
<String key="TipMoveRight">Сдвинуть вправо</String>
|
||||
|
||||
Reference in New Issue
Block a user