mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2025-10-13 23:10:23 +03:00
improvements
This commit is contained in:
@@ -5,7 +5,7 @@ namespace Common;
|
|||||||
|
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static int ReadInt32LittleEndian(this FileStream fs)
|
public static int ReadInt32LittleEndian(this Stream fs)
|
||||||
{
|
{
|
||||||
Span<byte> buf = stackalloc byte[4];
|
Span<byte> buf = stackalloc byte[4];
|
||||||
fs.ReadExactly(buf);
|
fs.ReadExactly(buf);
|
||||||
@@ -13,7 +13,7 @@ public static class Extensions
|
|||||||
return BinaryPrimitives.ReadInt32LittleEndian(buf);
|
return BinaryPrimitives.ReadInt32LittleEndian(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint ReadUInt32LittleEndian(this FileStream fs)
|
public static uint ReadUInt32LittleEndian(this Stream fs)
|
||||||
{
|
{
|
||||||
Span<byte> buf = stackalloc byte[4];
|
Span<byte> buf = stackalloc byte[4];
|
||||||
fs.ReadExactly(buf);
|
fs.ReadExactly(buf);
|
||||||
@@ -21,7 +21,7 @@ public static class Extensions
|
|||||||
return BinaryPrimitives.ReadUInt32LittleEndian(buf);
|
return BinaryPrimitives.ReadUInt32LittleEndian(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float ReadFloatLittleEndian(this FileStream fs)
|
public static float ReadFloatLittleEndian(this Stream fs)
|
||||||
{
|
{
|
||||||
Span<byte> buf = stackalloc byte[4];
|
Span<byte> buf = stackalloc byte[4];
|
||||||
fs.ReadExactly(buf);
|
fs.ReadExactly(buf);
|
||||||
@@ -29,7 +29,7 @@ public static class Extensions
|
|||||||
return BinaryPrimitives.ReadSingleLittleEndian(buf);
|
return BinaryPrimitives.ReadSingleLittleEndian(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReadNullTerminatedString(this FileStream fs)
|
public static string ReadNullTerminatedString(this Stream fs)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
@@ -47,7 +47,25 @@ public static class Extensions
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReadLengthPrefixedString(this FileStream fs)
|
public static string ReadNullTerminated1251String(this Stream fs)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var b = (byte)fs.ReadByte();
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append(Encoding.GetEncoding("windows-1251").GetString([b]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ReadLengthPrefixedString(this Stream fs)
|
||||||
{
|
{
|
||||||
var len = fs.ReadInt32LittleEndian();
|
var len = fs.ReadInt32LittleEndian();
|
||||||
|
|
||||||
|
@@ -6,7 +6,26 @@ public record CpDatEntry(
|
|||||||
int Magic1,
|
int Magic1,
|
||||||
int Magic2,
|
int Magic2,
|
||||||
string Description,
|
string Description,
|
||||||
int Magic3,
|
DatEntryType Type,
|
||||||
int ChildCount, // игра не хранит это число в объекте, но оно есть в файле
|
int ChildCount, // игра не хранит это число в объекте, но оно есть в файле
|
||||||
List<CpDatEntry> Children
|
List<CpDatEntry> Children
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Magic3 seems to be a type
|
||||||
|
// 0 - chassis
|
||||||
|
// 1 - turret (у зданий почему-то дефлектор тоже 1), может быть потому, что дефлектор вращается так же как башня у юнитов
|
||||||
|
// 2 - armour
|
||||||
|
// 3 - part
|
||||||
|
// 4 - cannon
|
||||||
|
// 5 - ammo
|
||||||
|
|
||||||
|
public enum DatEntryType
|
||||||
|
{
|
||||||
|
Unspecified = -1,
|
||||||
|
Chassis = 0,
|
||||||
|
Turret = 1,
|
||||||
|
Armour = 2,
|
||||||
|
Part = 3,
|
||||||
|
Cannon = 4,
|
||||||
|
Ammo = 5,
|
||||||
|
}
|
@@ -6,10 +6,15 @@ public class CpDatParser
|
|||||||
{
|
{
|
||||||
public static CpDatParseResult Parse(string filePath)
|
public static CpDatParseResult Parse(string filePath)
|
||||||
{
|
{
|
||||||
Span<byte> f0f1 = stackalloc byte[4];
|
|
||||||
|
|
||||||
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
|
||||||
|
return Parse(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CpDatParseResult Parse(Stream fs)
|
||||||
|
{
|
||||||
|
Span<byte> f0f1 = stackalloc byte[4];
|
||||||
|
|
||||||
if (fs.Length < 8)
|
if (fs.Length < 8)
|
||||||
return new CpDatParseResult(null, "File too small to be a valid \"cp\" .dat file.");
|
return new CpDatParseResult(null, "File too small to be a valid \"cp\" .dat file.");
|
||||||
|
|
||||||
@@ -22,7 +27,8 @@ public class CpDatParser
|
|||||||
|
|
||||||
var schemeType = (SchemeType)fs.ReadInt32LittleEndian();
|
var schemeType = (SchemeType)fs.ReadInt32LittleEndian();
|
||||||
|
|
||||||
var entryLength = 0x6c + 4; // нам нужно прочитать 0x6c (108) байт - это root, и ещё 4 байта - кол-во вложенных объектов
|
var entryLength =
|
||||||
|
0x6c + 4; // нам нужно прочитать 0x6c (108) байт - это root, и ещё 4 байта - кол-во вложенных объектов
|
||||||
if ((fs.Length - 8) % entryLength != 0)
|
if ((fs.Length - 8) % entryLength != 0)
|
||||||
{
|
{
|
||||||
return new CpDatParseResult(null, "File size is not valid according to expected entry length.");
|
return new CpDatParseResult(null, "File size is not valid according to expected entry length.");
|
||||||
@@ -35,7 +41,7 @@ public class CpDatParser
|
|||||||
return new CpDatParseResult(scheme, null);
|
return new CpDatParseResult(scheme, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CpDatEntry ReadEntryRecursive(FileStream fs)
|
private static CpDatEntry ReadEntryRecursive(Stream fs)
|
||||||
{
|
{
|
||||||
var str1 = fs.ReadNullTerminatedString();
|
var str1 = fs.ReadNullTerminatedString();
|
||||||
|
|
||||||
@@ -47,10 +53,10 @@ public class CpDatParser
|
|||||||
var magic1 = fs.ReadInt32LittleEndian();
|
var magic1 = fs.ReadInt32LittleEndian();
|
||||||
var magic2 = fs.ReadInt32LittleEndian();
|
var magic2 = fs.ReadInt32LittleEndian();
|
||||||
|
|
||||||
var descriptionString = fs.ReadNullTerminatedString();
|
var descriptionString = fs.ReadNullTerminated1251String();
|
||||||
|
|
||||||
fs.Seek(32 - descriptionString.Length - 1, SeekOrigin.Current); // -1 ignore null terminator
|
fs.Seek(32 - descriptionString.Length - 1, SeekOrigin.Current); // -1 ignore null terminator
|
||||||
var magic3 = fs.ReadInt32LittleEndian();
|
var type = (DatEntryType)fs.ReadInt32LittleEndian();
|
||||||
|
|
||||||
// игра не читает количество внутрь схемы, вместо этого она сразу рекурсией читает нужно количество вложенных объектов
|
// игра не читает количество внутрь схемы, вместо этого она сразу рекурсией читает нужно количество вложенных объектов
|
||||||
var childCount = fs.ReadInt32LittleEndian();
|
var childCount = fs.ReadInt32LittleEndian();
|
||||||
@@ -63,6 +69,6 @@ public class CpDatParser
|
|||||||
children.Add(child);
|
children.Add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CpDatEntry(str1, str2, magic1, magic2, descriptionString, magic3, childCount, Children: children);
|
return new CpDatEntry(str1, str2, magic1, magic2, descriptionString, type, childCount, Children: children);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,6 +8,11 @@ public class MissionTmaParser
|
|||||||
{
|
{
|
||||||
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
|
||||||
|
return ReadFile(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MissionTmaParseResult ReadFile(Stream fs)
|
||||||
|
{
|
||||||
var arealData = LoadAreals(fs);
|
var arealData = LoadAreals(fs);
|
||||||
|
|
||||||
var clansData = LoadClans(fs);
|
var clansData = LoadClans(fs);
|
||||||
@@ -20,7 +25,7 @@ public class MissionTmaParser
|
|||||||
return new MissionTmaParseResult(missionDat, null);
|
return new MissionTmaParseResult(missionDat, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArealsFileData LoadAreals(FileStream fileStream)
|
private static ArealsFileData LoadAreals(Stream fileStream)
|
||||||
{
|
{
|
||||||
var unusedHeader = fileStream.ReadInt32LittleEndian();
|
var unusedHeader = fileStream.ReadInt32LittleEndian();
|
||||||
var arealCount = fileStream.ReadInt32LittleEndian();
|
var arealCount = fileStream.ReadInt32LittleEndian();
|
||||||
@@ -56,7 +61,7 @@ public class MissionTmaParser
|
|||||||
return new ArealsFileData(unusedHeader, arealCount, infos);
|
return new ArealsFileData(unusedHeader, arealCount, infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClansFileData? LoadClans(FileStream fileStream)
|
private static ClansFileData? LoadClans(Stream fileStream)
|
||||||
{
|
{
|
||||||
var clanFeatureSet = fileStream.ReadInt32LittleEndian();
|
var clanFeatureSet = fileStream.ReadInt32LittleEndian();
|
||||||
|
|
||||||
@@ -158,7 +163,7 @@ public class MissionTmaParser
|
|||||||
return clanInfo;
|
return clanInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GameObjectsFileData LoadGameObjects(FileStream fileStream)
|
private static GameObjectsFileData LoadGameObjects(Stream fileStream)
|
||||||
{
|
{
|
||||||
var gameObjectsFeatureSet = fileStream.ReadInt32LittleEndian();
|
var gameObjectsFeatureSet = fileStream.ReadInt32LittleEndian();
|
||||||
|
|
||||||
|
@@ -9,6 +9,11 @@ public static class NResParser
|
|||||||
{
|
{
|
||||||
using FileStream nResFs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
using FileStream nResFs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
|
||||||
|
return ReadFile(nResFs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NResParseResult ReadFile(Stream nResFs)
|
||||||
|
{
|
||||||
if (nResFs.Length < 16)
|
if (nResFs.Length < 16)
|
||||||
{
|
{
|
||||||
return new NResParseResult(null, "Файл не может быть NRes, менее 16 байт");
|
return new NResParseResult(null, "Файл не может быть NRes, менее 16 байт");
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NResUI.Abstractions;
|
using NResUI.Abstractions;
|
||||||
@@ -33,6 +34,8 @@ public class App
|
|||||||
|
|
||||||
public void Init(IWindow window, GL openGl, ImFontPtr openSansFont)
|
public void Init(IWindow window, GL openGl, ImFontPtr openSansFont)
|
||||||
{
|
{
|
||||||
|
// Call this once at program startup
|
||||||
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
ImGui.StyleColorsLight();
|
ImGui.StyleColorsLight();
|
||||||
|
|
||||||
IServiceCollection serviceCollection = new ServiceCollection();
|
IServiceCollection serviceCollection = new ServiceCollection();
|
||||||
|
@@ -34,22 +34,60 @@ public class CpDatSchemeExplorer : IImGuiPanel
|
|||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
if (ImGui.BeginTable("content", 7, ImGuiTableFlags.Borders | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoHostExtendX))
|
if (ImGui.BeginTable("content", 8, ImGuiTableFlags.Borders | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoHostExtendX | ImGuiTableFlags.Sortable))
|
||||||
{
|
{
|
||||||
|
ImGui.TableSetupColumn("Индекс");
|
||||||
ImGui.TableSetupColumn("Уровень вложенности");
|
ImGui.TableSetupColumn("Уровень вложенности");
|
||||||
ImGui.TableSetupColumn("Архив");
|
ImGui.TableSetupColumn("Архив");
|
||||||
ImGui.TableSetupColumn("Элемент");
|
ImGui.TableSetupColumn("Элемент");
|
||||||
ImGui.TableSetupColumn("Magic1");
|
ImGui.TableSetupColumn("Magic1");
|
||||||
ImGui.TableSetupColumn("Magic2");
|
ImGui.TableSetupColumn("Magic2");
|
||||||
ImGui.TableSetupColumn("Описание");
|
ImGui.TableSetupColumn("Описание");
|
||||||
ImGui.TableSetupColumn("Magic3");
|
ImGui.TableSetupColumn("Тип");
|
||||||
|
|
||||||
ImGui.TableHeadersRow();
|
ImGui.TableHeadersRow();
|
||||||
|
|
||||||
|
// Handle sorting
|
||||||
|
ImGuiTableSortSpecsPtr sortSpecs = ImGui.TableGetSortSpecs();
|
||||||
|
if (sortSpecs.SpecsDirty)
|
||||||
|
{
|
||||||
|
// Only handle the first sort spec for simplicity
|
||||||
|
var sortSpec = sortSpecs.Specs;
|
||||||
|
|
||||||
|
if (sortSpec.ColumnIndex == 0)
|
||||||
|
{
|
||||||
|
_viewModel.RebuildFlatList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
_viewModel.FlatList.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
switch (sortSpec.ColumnIndex)
|
||||||
|
{
|
||||||
|
case 1: result = a.Level.CompareTo(b.Level); break;
|
||||||
|
case 2: result = string.Compare(a.Entry.ArchiveFile, b.Entry.ArchiveFile, StringComparison.Ordinal); break;
|
||||||
|
case 3: result = string.Compare(a.Entry.ArchiveEntryName, b.Entry.ArchiveEntryName, StringComparison.Ordinal); break;
|
||||||
|
case 4: result = a.Entry.Magic1.CompareTo(b.Entry.Magic1); break;
|
||||||
|
case 5: result = a.Entry.Magic2.CompareTo(b.Entry.Magic2); break;
|
||||||
|
case 6: result = string.Compare(a.Entry.Description, b.Entry.Description, StringComparison.Ordinal); break;
|
||||||
|
case 7: result = a.Entry.Type.CompareTo(b.Entry.Type); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortSpec.SortDirection == ImGuiSortDirection.Descending ? -result : result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sortSpecs.SpecsDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _viewModel.FlatList.Count; i++)
|
for (int i = 0; i < _viewModel.FlatList.Count; i++)
|
||||||
{
|
{
|
||||||
ImGui.TableNextRow();
|
ImGui.TableNextRow();
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.Text(i.ToString());
|
||||||
|
ImGui.TableNextColumn();
|
||||||
ImGui.Text(_viewModel.FlatList[i].Level.ToString());
|
ImGui.Text(_viewModel.FlatList[i].Level.ToString());
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.Text(_viewModel.FlatList[i].Entry.ArchiveFile);
|
ImGui.Text(_viewModel.FlatList[i].Entry.ArchiveFile);
|
||||||
@@ -62,7 +100,7 @@ public class CpDatSchemeExplorer : IImGuiPanel
|
|||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.Text(_viewModel.FlatList[i].Entry.Description);
|
ImGui.Text(_viewModel.FlatList[i].Entry.Description);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.Text(_viewModel.FlatList[i].Entry.Magic3.ToString());
|
ImGui.Text(_viewModel.FlatList[i].Entry.Type.ToString("G"));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndTable();
|
ImGui.EndTable();
|
||||||
@@ -80,9 +118,9 @@ public class CpDatSchemeExplorer : IImGuiPanel
|
|||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Text(entry.Magic2.ToString());
|
ImGui.Text(entry.Magic2.ToString());
|
||||||
|
|
||||||
ImGui.Text("Magic3: ");
|
ImGui.Text("Тип: ");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Text(entry.Magic3.ToString());
|
ImGui.Text(entry.Type.ToString());
|
||||||
|
|
||||||
ImGui.Text("Кол-во дочерних элементов: ");
|
ImGui.Text("Кол-во дочерних элементов: ");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
@@ -1,23 +1,43 @@
|
|||||||
using ImGuiNET;
|
using CpDatLib;
|
||||||
|
using ImGuiNET;
|
||||||
|
using MissionTmaLib.Parsing;
|
||||||
|
using NResLib;
|
||||||
using NResUI.Abstractions;
|
using NResUI.Abstractions;
|
||||||
using NResUI.Models;
|
using NResUI.Models;
|
||||||
|
using ScrLib;
|
||||||
|
using TexmLib;
|
||||||
|
using VarsetLib;
|
||||||
|
|
||||||
namespace NResUI.ImGuiUI;
|
namespace NResUI.ImGuiUI;
|
||||||
|
|
||||||
public class NResExplorerPanel : IImGuiPanel
|
public class NResExplorerPanel : IImGuiPanel
|
||||||
{
|
{
|
||||||
private readonly NResExplorerViewModel _viewModel;
|
private readonly NResExplorerViewModel _viewModel;
|
||||||
|
private readonly TexmExplorerViewModel _texmExplorerViewModel;
|
||||||
|
private readonly VarsetViewModel _varsetViewModel;
|
||||||
|
private readonly CpDatSchemeViewModel _cpDatSchemeViewModel;
|
||||||
|
private readonly MissionTmaViewModel _missionTmaViewModel;
|
||||||
|
private readonly ScrViewModel _scrViewModel;
|
||||||
|
|
||||||
public NResExplorerPanel(NResExplorerViewModel viewModel)
|
public NResExplorerPanel(NResExplorerViewModel viewModel, TexmExplorerViewModel texmExplorerViewModel,
|
||||||
|
VarsetViewModel varsetViewModel, CpDatSchemeViewModel cpDatSchemeViewModel, MissionTmaViewModel missionTmaViewModel, ScrViewModel scrViewModel)
|
||||||
{
|
{
|
||||||
_viewModel = viewModel;
|
_viewModel = viewModel;
|
||||||
|
_texmExplorerViewModel = texmExplorerViewModel;
|
||||||
|
_varsetViewModel = varsetViewModel;
|
||||||
|
_cpDatSchemeViewModel = cpDatSchemeViewModel;
|
||||||
|
_missionTmaViewModel = missionTmaViewModel;
|
||||||
|
_scrViewModel = scrViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int contextMenuRow = -1;
|
||||||
|
|
||||||
public void OnImGuiRender()
|
public void OnImGuiRender()
|
||||||
{
|
{
|
||||||
if (ImGui.Begin("NRes Explorer"))
|
if (ImGui.Begin("NRes Explorer"))
|
||||||
{
|
{
|
||||||
ImGui.Text("NRes - это файл-архив. Они имеют разные расширения. Примеры - Textures.lib, weapon.rlb, object.dlb, behpsp.res");
|
ImGui.Text(
|
||||||
|
"NRes - это файл-архив. Они имеют разные расширения. Примеры - Textures.lib, weapon.rlb, object.dlb, behpsp.res");
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
if (!_viewModel.HasFile)
|
if (!_viewModel.HasFile)
|
||||||
@@ -48,8 +68,8 @@ public class NResExplorerPanel : IImGuiPanel
|
|||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Text(_viewModel.Archive.Header.TotalFileLengthBytes.ToString());
|
ImGui.Text(_viewModel.Archive.Header.TotalFileLengthBytes.ToString());
|
||||||
|
|
||||||
|
if (ImGui.BeginTable("content", 12,
|
||||||
if (ImGui.BeginTable("content", 12, ImGuiTableFlags.Borders | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoHostExtendX))
|
ImGuiTableFlags.Borders | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoHostExtendX))
|
||||||
{
|
{
|
||||||
ImGui.TableSetupColumn("Тип файла");
|
ImGui.TableSetupColumn("Тип файла");
|
||||||
ImGui.TableSetupColumn("Кол-во элементов");
|
ImGui.TableSetupColumn("Кол-во элементов");
|
||||||
@@ -70,6 +90,17 @@ public class NResExplorerPanel : IImGuiPanel
|
|||||||
{
|
{
|
||||||
ImGui.TableNextRow();
|
ImGui.TableNextRow();
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
|
||||||
|
ImGui.Selectable("##row_select" + i, false, ImGuiSelectableFlags.SpanAllColumns);
|
||||||
|
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Right))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Context menu for row " + i);
|
||||||
|
contextMenuRow = i;
|
||||||
|
ImGui.OpenPopup("row_context_menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
ImGui.Text(_viewModel.Archive.Files[i].FileType);
|
ImGui.Text(_viewModel.Archive.Files[i].FileType);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.Text(_viewModel.Archive.Files[i].ElementCount.ToString());
|
ImGui.Text(_viewModel.Archive.Files[i].ElementCount.ToString());
|
||||||
@@ -122,6 +153,130 @@ public class NResExplorerPanel : IImGuiPanel
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginPopup("row_context_menu"))
|
||||||
|
{
|
||||||
|
if (contextMenuRow == -1 || contextMenuRow > _viewModel.Archive.Files.Count)
|
||||||
|
{
|
||||||
|
ImGui.Text("Broken context menu :(. Reopen");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var file = _viewModel.Archive.Files[contextMenuRow];
|
||||||
|
ImGui.Text("Actions for file " + file.FileName);
|
||||||
|
ImGui.TextDisabled("Program has no understading of file format(");
|
||||||
|
ImGui.Separator();
|
||||||
|
if (ImGui.MenuItem("Open as Texture TEXM"))
|
||||||
|
{
|
||||||
|
using var fs = new FileStream(_viewModel.Path!, FileMode.Open, FileAccess.Read,
|
||||||
|
FileShare.Read);
|
||||||
|
fs.Seek(file.OffsetInFile, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
var buffer = new byte[file.FileLength];
|
||||||
|
|
||||||
|
fs.ReadExactly(buffer, 0, file.FileLength);
|
||||||
|
|
||||||
|
using var ms = new MemoryStream(buffer);
|
||||||
|
|
||||||
|
var parseResult = TexmParser.ReadFromStream(ms, file.FileName);
|
||||||
|
|
||||||
|
_texmExplorerViewModel.SetParseResult(parseResult, Path.Combine(_viewModel.Path!, file.FileName));
|
||||||
|
Console.WriteLine("Read TEXM from context menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Open as Archive NRes"))
|
||||||
|
{
|
||||||
|
using var fs = new FileStream(_viewModel.Path!, FileMode.Open, FileAccess.Read,
|
||||||
|
FileShare.Read);
|
||||||
|
fs.Seek(file.OffsetInFile, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
var buffer = new byte[file.FileLength];
|
||||||
|
|
||||||
|
fs.ReadExactly(buffer, 0, file.FileLength);
|
||||||
|
|
||||||
|
using var ms = new MemoryStream(buffer);
|
||||||
|
|
||||||
|
var parseResult = NResParser.ReadFile(ms);
|
||||||
|
|
||||||
|
_viewModel.SetParseResult(parseResult, Path.Combine(_viewModel.Path!, file.FileName));
|
||||||
|
Console.WriteLine("Read NRes from context menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Open as Varset .var"))
|
||||||
|
{
|
||||||
|
using var fs = new FileStream(_viewModel.Path!, FileMode.Open, FileAccess.Read,
|
||||||
|
FileShare.Read);
|
||||||
|
fs.Seek(file.OffsetInFile, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
var buffer = new byte[file.FileLength];
|
||||||
|
|
||||||
|
fs.ReadExactly(buffer, 0, file.FileLength);
|
||||||
|
|
||||||
|
using var ms = new MemoryStream(buffer);
|
||||||
|
|
||||||
|
var parseResult = VarsetParser.Parse(ms);
|
||||||
|
|
||||||
|
_varsetViewModel.Items = parseResult;
|
||||||
|
Console.WriteLine("Read Varset from context menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Open as Scheme cp.dat"))
|
||||||
|
{
|
||||||
|
using var fs = new FileStream(_viewModel.Path!, FileMode.Open, FileAccess.Read,
|
||||||
|
FileShare.Read);
|
||||||
|
fs.Seek(file.OffsetInFile, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
var buffer = new byte[file.FileLength];
|
||||||
|
|
||||||
|
fs.ReadExactly(buffer, 0, file.FileLength);
|
||||||
|
|
||||||
|
using var ms = new MemoryStream(buffer);
|
||||||
|
|
||||||
|
var parseResult = CpDatParser.Parse(ms);
|
||||||
|
|
||||||
|
_cpDatSchemeViewModel.SetParseResult(parseResult, file.FileName);
|
||||||
|
Console.WriteLine("Read cp.dat from context menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Open as Mission .tma"))
|
||||||
|
{
|
||||||
|
using var fs = new FileStream(_viewModel.Path!, FileMode.Open, FileAccess.Read,
|
||||||
|
FileShare.Read);
|
||||||
|
fs.Seek(file.OffsetInFile, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
var buffer = new byte[file.FileLength];
|
||||||
|
|
||||||
|
fs.ReadExactly(buffer, 0, file.FileLength);
|
||||||
|
|
||||||
|
using var ms = new MemoryStream(buffer);
|
||||||
|
|
||||||
|
var parseResult = MissionTmaParser.ReadFile(ms);
|
||||||
|
|
||||||
|
_missionTmaViewModel.SetParseResult(parseResult, Path.Combine(_viewModel.Path!, file.FileName));
|
||||||
|
Console.WriteLine("Read .tma from context menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.MenuItem("Open as Scripts .scr"))
|
||||||
|
{
|
||||||
|
using var fs = new FileStream(_viewModel.Path!, FileMode.Open, FileAccess.Read,
|
||||||
|
FileShare.Read);
|
||||||
|
fs.Seek(file.OffsetInFile, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
var buffer = new byte[file.FileLength];
|
||||||
|
|
||||||
|
fs.ReadExactly(buffer, 0, file.FileLength);
|
||||||
|
|
||||||
|
using var ms = new MemoryStream(buffer);
|
||||||
|
|
||||||
|
var parseResult = ScrParser.ReadFile(ms);
|
||||||
|
|
||||||
|
_scrViewModel.SetParseResult(parseResult, Path.Combine(_viewModel.Path!, file.FileName));
|
||||||
|
Console.WriteLine("Read .scr from context menu");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.EndTable();
|
ImGui.EndTable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ public class CpDatSchemeViewModel
|
|||||||
|
|
||||||
public CpDatScheme? CpDatScheme { get; set; }
|
public CpDatScheme? CpDatScheme { get; set; }
|
||||||
|
|
||||||
public List<(int Level, CpDatEntry Entry)> FlatList { get; set; }
|
public List<(int Level, CpDatEntry Entry)> FlatList { get; set; } = [];
|
||||||
|
|
||||||
public string? Path { get; set; }
|
public string? Path { get; set; }
|
||||||
|
|
||||||
@@ -23,17 +23,27 @@ public class CpDatSchemeViewModel
|
|||||||
|
|
||||||
if (CpDatScheme is not null)
|
if (CpDatScheme is not null)
|
||||||
{
|
{
|
||||||
FlatList = [];
|
RebuildFlatList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CollectEntries(CpDatScheme.Root, 0);
|
public void RebuildFlatList()
|
||||||
|
{
|
||||||
|
FlatList = [];
|
||||||
|
|
||||||
void CollectEntries(CpDatEntry entry, int level)
|
if (CpDatScheme is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectEntries(CpDatScheme.Root, 0);
|
||||||
|
|
||||||
|
void CollectEntries(CpDatEntry entry, int level)
|
||||||
|
{
|
||||||
|
FlatList.Add((level, entry));
|
||||||
|
foreach (var child in entry.Children)
|
||||||
{
|
{
|
||||||
FlatList.Add((level, entry));
|
CollectEntries(child, level + 1);
|
||||||
foreach (var child in entry.Children)
|
|
||||||
{
|
|
||||||
CollectEntries(child, level + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType Condition="'$(OS)' == 'Windows_NT'">WinExe</OutputType>
|
||||||
|
<OutputType Condition="'$(OS)' != 'Windows_NT'">Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -29,42 +29,42 @@ public static class Msh02
|
|||||||
var centerW = BinaryPrimitives.ReadSingleLittleEndian(header.Slice(0x6c));
|
var centerW = BinaryPrimitives.ReadSingleLittleEndian(header.Slice(0x6c));
|
||||||
|
|
||||||
var bb = new BoundingBox();
|
var bb = new BoundingBox();
|
||||||
bb.Vec1 = new Vector3(
|
bb.BottomFrontLeft = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(0)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(0)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(4)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(4)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(8))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(8))
|
||||||
);
|
);
|
||||||
bb.Vec2 = new Vector3(
|
bb.BottomFrontRight = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(12)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(12)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(16)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(16)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(20))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(20))
|
||||||
);
|
);
|
||||||
bb.Vec3 = new Vector3(
|
bb.BottomBackRight = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(24)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(24)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(28)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(28)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(32))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(32))
|
||||||
);
|
);
|
||||||
bb.Vec4 = new Vector3(
|
bb.BottomBackLeft = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(36)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(36)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(40)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(40)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(44))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(44))
|
||||||
);
|
);
|
||||||
bb.Vec5 = new Vector3(
|
bb.TopFrontLeft = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(48)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(48)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(52)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(52)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(56))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(56))
|
||||||
);
|
);
|
||||||
bb.Vec6 = new Vector3(
|
bb.TopFrontRight = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(60)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(60)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(64)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(64)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(68))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(68))
|
||||||
);
|
);
|
||||||
bb.Vec7 = new Vector3(
|
bb.TopBackRight = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(72)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(72)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(76)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(76)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(80))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(80))
|
||||||
);
|
);
|
||||||
bb.Vec8 = new Vector3(
|
bb.TopBackLeft = new Vector3(
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(84)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(84)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(88)),
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(88)),
|
||||||
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(92))
|
BinaryPrimitives.ReadSingleLittleEndian(header.Slice(92))
|
||||||
@@ -149,6 +149,9 @@ public static class Msh02
|
|||||||
public List<Msh02Element> Elements { get; set; }
|
public List<Msh02Element> Elements { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 140 байт в начале файла
|
||||||
|
/// </summary>
|
||||||
public class Msh02Header
|
public class Msh02Header
|
||||||
{
|
{
|
||||||
public BoundingBox BoundingBox { get; set; }
|
public BoundingBox BoundingBox { get; set; }
|
||||||
@@ -172,15 +175,19 @@ public static class Msh02
|
|||||||
public Vector3 Vector5 { get; set; }
|
public Vector3 Vector5 { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 96 bytes - bounding box (8 points each 3 float = 96 bytes)
|
||||||
|
/// 0x60 bytes or 0x18 by 4 bytes
|
||||||
|
/// </summary>
|
||||||
public class BoundingBox
|
public class BoundingBox
|
||||||
{
|
{
|
||||||
public Vector3 Vec1 { get; set; }
|
public Vector3 BottomFrontLeft { get; set; }
|
||||||
public Vector3 Vec2 { get; set; }
|
public Vector3 BottomFrontRight { get; set; }
|
||||||
public Vector3 Vec3 { get; set; }
|
public Vector3 BottomBackRight { get; set; }
|
||||||
public Vector3 Vec4 { get; set; }
|
public Vector3 BottomBackLeft { get; set; }
|
||||||
public Vector3 Vec5 { get; set; }
|
public Vector3 TopFrontLeft { get; set; }
|
||||||
public Vector3 Vec6 { get; set; }
|
public Vector3 TopFrontRight { get; set; }
|
||||||
public Vector3 Vec7 { get; set; }
|
public Vector3 TopBackRight { get; set; }
|
||||||
public Vector3 Vec8 { get; set; }
|
public Vector3 TopBackLeft { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
55
ParkanPlayground/Msh15.cs
Normal file
55
ParkanPlayground/Msh15.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using System.Buffers.Binary;
|
||||||
|
using NResLib;
|
||||||
|
|
||||||
|
namespace ParkanPlayground;
|
||||||
|
|
||||||
|
public static class Msh15
|
||||||
|
{
|
||||||
|
public static List<Msh15Element> ReadComponent(
|
||||||
|
FileStream mshFs, NResArchive archive)
|
||||||
|
{
|
||||||
|
var entry = archive.Files.FirstOrDefault(x => x.FileType == "15 00 00 00");
|
||||||
|
|
||||||
|
if (entry is null)
|
||||||
|
{
|
||||||
|
throw new Exception("Archive doesn't contain file (15)");
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = new byte[entry.ElementCount * entry.ElementSize];
|
||||||
|
mshFs.Seek(entry.OffsetInFile, SeekOrigin.Begin);
|
||||||
|
mshFs.ReadExactly(data, 0, data.Length);
|
||||||
|
|
||||||
|
var elementBytes = data.Chunk(28);
|
||||||
|
|
||||||
|
var elements = elementBytes.Select(x => new Msh15Element()
|
||||||
|
{
|
||||||
|
Flags = BinaryPrimitives.ReadUInt32LittleEndian(x.AsSpan(0)),
|
||||||
|
Magic04 = BinaryPrimitives.ReadUInt32LittleEndian(x.AsSpan(4)),
|
||||||
|
Vertex1Index = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(8)),
|
||||||
|
Vertex2Index = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(10)),
|
||||||
|
Vertex3Index = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(12)),
|
||||||
|
Magic0E = BinaryPrimitives.ReadUInt32LittleEndian(x.AsSpan(14)),
|
||||||
|
Magic12 = BinaryPrimitives.ReadUInt32LittleEndian(x.AsSpan(18)),
|
||||||
|
Magic16 = BinaryPrimitives.ReadUInt32LittleEndian(x.AsSpan(22)),
|
||||||
|
Magic1A = BinaryPrimitives.ReadUInt16LittleEndian(x.AsSpan(26)),
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Msh15Element
|
||||||
|
{
|
||||||
|
public uint Flags { get; set; }
|
||||||
|
|
||||||
|
public uint Magic04 { get; set; }
|
||||||
|
public ushort Vertex1Index { get; set; }
|
||||||
|
public ushort Vertex2Index { get; set; }
|
||||||
|
public ushort Vertex3Index { get; set; }
|
||||||
|
|
||||||
|
public uint Magic0E { get; set; }
|
||||||
|
public uint Magic12 { get; set; }
|
||||||
|
public uint Magic16 { get; set; }
|
||||||
|
public ushort Magic1A { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -15,6 +15,8 @@ public class MshConverter
|
|||||||
|
|
||||||
var component01 = Msh01.ReadComponent(mshFs, mshNres);
|
var component01 = Msh01.ReadComponent(mshFs, mshNres);
|
||||||
var component02 = Msh02.ReadComponent(mshFs, mshNres);
|
var component02 = Msh02.ReadComponent(mshFs, mshNres);
|
||||||
|
var component15 = Msh15.ReadComponent(mshFs, mshNres);
|
||||||
|
|
||||||
var component0A = Msh0A.ReadComponent(mshFs, mshNres);
|
var component0A = Msh0A.ReadComponent(mshFs, mshNres);
|
||||||
var component07 = Msh07.ReadComponent(mshFs, mshNres);
|
var component07 = Msh07.ReadComponent(mshFs, mshNres);
|
||||||
var component0D = Msh0D.ReadComponent(mshFs, mshNres);
|
var component0D = Msh0D.ReadComponent(mshFs, mshNres);
|
||||||
|
@@ -9,8 +9,8 @@ using ParkanPlayground;
|
|||||||
|
|
||||||
var converter = new MshConverter();
|
var converter = new MshConverter();
|
||||||
|
|
||||||
converter.Convert("E:\\ParkanUnpacked\\fortif.rlb\\133_fr_m_bunker.msh");
|
// converter.Convert("E:\\ParkanUnpacked\\fortif.rlb\\133_fr_m_bunker.msh");
|
||||||
// converter.Convert("C:\\Program Files (x86)\\Nikita\\Iron Strategy\\DATA\\MAPS\\SC_1\\Land.msh");
|
converter.Convert("C:\\Program Files (x86)\\Nikita\\Iron Strategy\\DATA\\MAPS\\SC_1\\Land.msh");
|
||||||
// converter.Convert("E:\\ParkanUnpacked\\fortif.rlb\\73_fr_m_brige.msh");
|
// converter.Convert("E:\\ParkanUnpacked\\fortif.rlb\\73_fr_m_brige.msh");
|
||||||
// converter.Convert("E:\\ParkanUnpacked\\intsys.rlb\\277_MESH_o_pws_l_01.msh");
|
// converter.Convert("E:\\ParkanUnpacked\\intsys.rlb\\277_MESH_o_pws_l_01.msh");
|
||||||
// converter.Convert("E:\\ParkanUnpacked\\static.rlb\\2_MESH_s_stn_0_01.msh");
|
// converter.Convert("E:\\ParkanUnpacked\\static.rlb\\2_MESH_s_stn_0_01.msh");
|
||||||
|
@@ -302,7 +302,7 @@ IComponent ** LoadSomething(undefined4, undefined4, undefined4, undefined4)
|
|||||||
- `4` - IShader
|
- `4` - IShader
|
||||||
- `5` - ITerrain
|
- `5` - ITerrain
|
||||||
- `6` - IGameObject (0x138)
|
- `6` - IGameObject (0x138)
|
||||||
- `7` - IShadeConfig (у меня в папке с игрой его не оказалось)
|
- `7` - IAtmosphereObject
|
||||||
- `8` - ICamera
|
- `8` - ICamera
|
||||||
- `9` - IQueue
|
- `9` - IQueue
|
||||||
- `10` - IControl
|
- `10` - IControl
|
||||||
@@ -329,6 +329,7 @@ IComponent ** LoadSomething(undefined4, undefined4, undefined4, undefined4)
|
|||||||
- `0x101` - 3DRender
|
- `0x101` - 3DRender
|
||||||
- `0x105` - NResFile
|
- `0x105` - NResFile
|
||||||
- `0x106` - NResFileMetadata
|
- `0x106` - NResFileMetadata
|
||||||
|
- `0x107` - 3DSound
|
||||||
- `0x201` - IWizard
|
- `0x201` - IWizard
|
||||||
- `0x202` - IItemManager
|
- `0x202` - IItemManager
|
||||||
- `0x203` - ICollManager
|
- `0x203` - ICollManager
|
||||||
|
@@ -6,8 +6,13 @@ public class ScrParser
|
|||||||
{
|
{
|
||||||
public static ScrFile ReadFile(string filePath)
|
public static ScrFile ReadFile(string filePath)
|
||||||
{
|
{
|
||||||
var fs = new FileStream(filePath, FileMode.Open);
|
using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
|
||||||
|
return ReadFile(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScrFile ReadFile(Stream fs)
|
||||||
|
{
|
||||||
var scrFile = new ScrFile();
|
var scrFile = new ScrFile();
|
||||||
|
|
||||||
scrFile.Magic = fs.ReadInt32LittleEndian();
|
scrFile.Magic = fs.ReadInt32LittleEndian();
|
||||||
|
@@ -4,65 +4,79 @@ public class VarsetParser
|
|||||||
{
|
{
|
||||||
public static List<VarsetItem> Parse(string path)
|
public static List<VarsetItem> Parse(string path)
|
||||||
{
|
{
|
||||||
FileStream fs = new FileStream(path, FileMode.Open);
|
using FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
|
||||||
var reader = new StreamReader(fs);
|
return Parse(fs);
|
||||||
|
}
|
||||||
|
|
||||||
List<VarsetItem> varsetItems = [];
|
public static List<VarsetItem> Parse(Stream fs)
|
||||||
|
{
|
||||||
var lineIndex = 1;
|
try
|
||||||
while (!reader.EndOfStream)
|
|
||||||
{
|
{
|
||||||
var line = reader.ReadLine()!;
|
var reader = new StreamReader(fs);
|
||||||
if (line.Length == 0)
|
|
||||||
|
List<VarsetItem> varsetItems = [];
|
||||||
|
|
||||||
|
var lineIndex = 1;
|
||||||
|
while (!reader.EndOfStream)
|
||||||
{
|
{
|
||||||
|
var line = reader.ReadLine()!;
|
||||||
|
if (line.Length == 0)
|
||||||
|
{
|
||||||
|
lineIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.StartsWith("//") || line.Trim().StartsWith("//"))
|
||||||
|
{
|
||||||
|
lineIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.StartsWith("VAR"))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error on line: {lineIndex}! Not starting with VAR");
|
||||||
|
lineIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var openParenthesisIndex = line.IndexOf("(");
|
||||||
|
var closeParenthesisIndex = line.IndexOf(")");
|
||||||
|
|
||||||
|
if (openParenthesisIndex == -1 || closeParenthesisIndex == -1 ||
|
||||||
|
closeParenthesisIndex <= openParenthesisIndex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error on line: {lineIndex}! VAR() format invalid");
|
||||||
|
lineIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var arguments = line.Substring(openParenthesisIndex + 1,
|
||||||
|
closeParenthesisIndex - openParenthesisIndex - 1);
|
||||||
|
|
||||||
|
var parts = arguments.Trim()
|
||||||
|
.Split(',');
|
||||||
|
|
||||||
|
var type = parts[0]
|
||||||
|
.Trim();
|
||||||
|
|
||||||
|
var name = parts[1]
|
||||||
|
.Trim();
|
||||||
|
|
||||||
|
var value = parts[2]
|
||||||
|
.Trim();
|
||||||
|
|
||||||
|
var item = new VarsetItem(type, name, value);
|
||||||
|
varsetItems.Add(item);
|
||||||
|
|
||||||
lineIndex++;
|
lineIndex++;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.StartsWith("//") || line.Trim().StartsWith("//"))
|
return varsetItems;
|
||||||
{
|
}
|
||||||
lineIndex++;
|
catch
|
||||||
continue;
|
{
|
||||||
}
|
return [];
|
||||||
|
|
||||||
if (!line.StartsWith("VAR"))
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error on line: {lineIndex}! Not starting with VAR");
|
|
||||||
lineIndex++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var openParenthesisIndex = line.IndexOf("(");
|
|
||||||
var closeParenthesisIndex = line.IndexOf(")");
|
|
||||||
|
|
||||||
if (openParenthesisIndex == -1 || closeParenthesisIndex == -1 || closeParenthesisIndex <= openParenthesisIndex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error on line: {lineIndex}! VAR() format invalid");
|
|
||||||
lineIndex++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var arguments = line.Substring(openParenthesisIndex + 1, closeParenthesisIndex - openParenthesisIndex - 1);
|
|
||||||
|
|
||||||
var parts = arguments.Trim()
|
|
||||||
.Split(',');
|
|
||||||
|
|
||||||
var type = parts[0]
|
|
||||||
.Trim();
|
|
||||||
|
|
||||||
var name = parts[1]
|
|
||||||
.Trim();
|
|
||||||
|
|
||||||
var value = parts[2]
|
|
||||||
.Trim();
|
|
||||||
|
|
||||||
var item = new VarsetItem(type, name, value);
|
|
||||||
varsetItems.Add(item);
|
|
||||||
|
|
||||||
lineIndex++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return varsetItems;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user