Second commit
This commit is contained in:
commit
36840f3ad4
999 files changed
+61364
No files matched your search
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public static class MapCompiler
|
||||
{
|
||||
public static MapBsp BuildBsp(TrembleSyncSettings syncSettings, string mapPath, string extraCommandLineArgs, out Q3Map2Result result,
|
||||
Action<string> onOutputMessage = null)
|
||||
{
|
||||
string mapName = Path.GetFileNameWithoutExtension(mapPath);
|
||||
string stagingFolder = Path.Combine(Application.temporaryCachePath, $"Build_{mapName}");
|
||||
|
||||
try
|
||||
{
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Copy to staging folder
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
DirectoryUtil.EmptyAndCreateDirectory(stagingFolder);
|
||||
|
||||
string stageMapPath = Path.Combine(stagingFolder, Path.GetFileName(mapPath));
|
||||
CopyMapToStagingFolder(mapPath, stageMapPath, out MapGroupData[] foundGroups);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Run Q3Map2
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
Q3Map2Result? overrideResult;
|
||||
|
||||
using (TrembleTimerScope __ = new(TrembleTimer.Context.RunQ3Map2))
|
||||
{
|
||||
// Combine all args
|
||||
string[] extraArgs = extraCommandLineArgs.Split(" ", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// Get output filename
|
||||
MapCompilerOutputHandler.Init(onOutputMessage);
|
||||
{
|
||||
int returnCode = Q3Map2Dll.ConvertMap(stageMapPath, MapCompilerOutputHandler.HandleOutput, extraArgs);
|
||||
result = returnCode == 0 ? Q3Map2Result.Succeeded : Q3Map2Result.Failed;
|
||||
}
|
||||
overrideResult = MapCompilerOutputHandler.DeInit();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Parse BSP
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
string bspPath = Path.ChangeExtension(stageMapPath, "bsp");
|
||||
if (!File.Exists(bspPath))
|
||||
{
|
||||
result = Q3Map2Result.Failed;
|
||||
return null;
|
||||
}
|
||||
|
||||
result = overrideResult ?? result;
|
||||
|
||||
using TrembleTimerScope _ = new(TrembleTimer.Context.ParseBsp);
|
||||
return BspParser.Parse(bspPath, syncSettings.ImportScale, foundGroups: foundGroups);
|
||||
}
|
||||
catch (DllNotFoundException dll)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
Debug.LogException(dll);
|
||||
EditorUtility.DisplayDialog("DLL Not Found", "Tremble's DLL was not found or couldn't be loaded. You should try to reinstall it from the Asset Store, or visit our Discord if this keeps happening!", "Okay");
|
||||
#else
|
||||
Debug.LogException(dll);
|
||||
Debug.LogError($"Missing q3map2 DLL file for platform: {Application.platform}");
|
||||
#endif
|
||||
|
||||
result = Q3Map2Result.Failed;
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Directory.Exists(stagingFolder))
|
||||
{
|
||||
Directory.Delete(stagingFolder, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void CopyMapToStagingFolder(string inputMap, string buildMap, out MapGroupData[] groups)
|
||||
{
|
||||
using TrembleTimerScope _ = new(TrembleTimer.Context.ExportMapToStaging);
|
||||
|
||||
// Open map
|
||||
using FileStream file = new(inputMap, FileMode.Open, FileAccess.Read);
|
||||
using StreamReader sr = new(file, Encoding.ASCII);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Pass 1 - Gather groups
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
groups = new MapGroupData[32]; // Start with 32 groups, but can grow
|
||||
groups[0] = new() { Name = "Default", IsNoExport = false };
|
||||
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine();
|
||||
|
||||
if (line == null || !line.ContainsInvariant(FgdConsts.PROPERTY_CLASSNAME, caseSensitive: true) || !line.ContainsInvariant("func_group", caseSensitive: true))
|
||||
continue;
|
||||
|
||||
int groupIdx = 0;
|
||||
string groupName = "Default";
|
||||
bool isNoExport = false;
|
||||
bool isLayer = false;
|
||||
|
||||
while (!sr.EndOfStream && line != null && !line.Trim().EqualsInvariant("}", caseSensitive: true) && !line.StartsWithInvariant("//", caseSensitive: true))
|
||||
{
|
||||
TokenParser tokenParser = new(line);
|
||||
ReadOnlySpan<char> key = tokenParser.ReadToken();
|
||||
ReadOnlySpan<char> value = tokenParser.ReadToken();
|
||||
|
||||
if (key.EqualsInvariant(TBConsts.ID, caseSensitive: true))
|
||||
{
|
||||
groupIdx = int.Parse(value);
|
||||
}
|
||||
else if (key.EqualsInvariant(TBConsts.NAME, caseSensitive: true))
|
||||
{
|
||||
groupName = value.ToString();
|
||||
}
|
||||
else if (key.EqualsInvariant(TBConsts.TYPE, caseSensitive: true))
|
||||
{
|
||||
isLayer = value.EqualsInvariant(TBConsts.LAYER, caseSensitive: true);
|
||||
}
|
||||
else if (key.EqualsInvariant(TBConsts.OMIT_FROM_EXPORT, caseSensitive: true) && int.TryParse(value, out int noExportInt))
|
||||
{
|
||||
isNoExport = noExportInt == 1;
|
||||
}
|
||||
|
||||
line = sr.ReadLine();
|
||||
}
|
||||
|
||||
// Resize groups array if needed
|
||||
if (groupIdx >= groups.Length)
|
||||
{
|
||||
Array.Resize(ref groups, groupIdx + 1);
|
||||
}
|
||||
|
||||
groups[groupIdx] = new() { Name = groupName, IsNoExport = isNoExport, IsLayer = isLayer };
|
||||
}
|
||||
|
||||
int numGroups = groups.Length - 1;
|
||||
while (groups[numGroups].Name == null)
|
||||
{
|
||||
numGroups--;
|
||||
}
|
||||
|
||||
Array.Resize(ref groups, numGroups + 1);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Pass 2 - Copy map into staging folder without "omit from export" layers
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
using FileStream outputStream = new(buildMap, FileMode.Create, FileAccess.Write);
|
||||
using StreamWriter writer = new(outputStream, Encoding.ASCII);
|
||||
|
||||
// Copy each line from reader -> writer, ignoring no export layers
|
||||
StringBuilder entity = new();
|
||||
bool wroteKeepLights = false;
|
||||
int depth = 0;
|
||||
int thisLayerOrGroupIdx = 0;
|
||||
|
||||
sr.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
while (!sr.EndOfStream)
|
||||
{
|
||||
string line = sr.ReadLine();
|
||||
if (line == null)
|
||||
break;
|
||||
|
||||
if (line.IsNullOrEmpty())
|
||||
continue;
|
||||
|
||||
entity.AppendLine(line);
|
||||
|
||||
if (line[0] == '{') depth++;
|
||||
else if (line[0] == '}') depth--;
|
||||
|
||||
// Ensure "_keepLights" is 1
|
||||
if (depth == 1 && !wroteKeepLights)
|
||||
{
|
||||
entity.AppendLine("\"_keepLights\" \"1\"");
|
||||
wroteKeepLights = true;
|
||||
}
|
||||
|
||||
if (line.ContainsInvariant(TBConsts.ID, caseSensitive: true))
|
||||
{
|
||||
TokenParser tokenParser = new(line);
|
||||
tokenParser.ReadToken(); // skip id
|
||||
ReadOnlySpan<char> value = tokenParser.ReadToken();
|
||||
|
||||
if (int.TryParse(value, out int layerOrGroupIdx))
|
||||
{
|
||||
thisLayerOrGroupIdx = layerOrGroupIdx;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth == 0)
|
||||
{
|
||||
if (thisLayerOrGroupIdx >= groups.Length || !groups[thisLayerOrGroupIdx].IsNoExport)
|
||||
{
|
||||
writer.WriteLine(entity);
|
||||
}
|
||||
|
||||
entity.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// This is lame. We add a fake entity called ent_mapfix which the importer
|
||||
// is set to ignore. Without this, sometimes map builds fail on Mac!
|
||||
if (!TrembleSyncSettings.Get().UseClassicQuakeCulling)
|
||||
{
|
||||
writer.WriteLine("// fix for q3map2");
|
||||
writer.WriteLine("{");
|
||||
writer.WriteLine($"\"classname\" \"{TrembleConsts.MAPFIX_ENTITY_NAME}\"");
|
||||
writer.WriteLine("\"origin\" \"32000 32000 32000\"");
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bce55202224c4dc69f433ae5c1a51aa5
|
||||
timeCreated: 1713266083
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Import/MapCompiler.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using AOT;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
// This class encapsulates the logic of parsing messages from Q3Map2, passing them on and
|
||||
// retaining any overrides to the end result.
|
||||
//
|
||||
// It used to be a nice lambda in MapCompiler.cs, but IL2CPP does not support instance method callbacks
|
||||
// from native code :(
|
||||
public static class MapCompilerOutputHandler
|
||||
{
|
||||
private static Action<string> s_OnOutputMessage;
|
||||
private static Q3Map2Result? s_OverrideResult;
|
||||
|
||||
public static void Init(Action<string> onOutputMessage)
|
||||
{
|
||||
s_OnOutputMessage = onOutputMessage;
|
||||
s_OverrideResult = null;
|
||||
}
|
||||
|
||||
public static Q3Map2Result? DeInit()
|
||||
{
|
||||
s_OnOutputMessage = null;
|
||||
return s_OverrideResult;
|
||||
}
|
||||
|
||||
[MonoPInvokeCallback(typeof(Action<string>))]
|
||||
public static void HandleOutput(string message)
|
||||
{
|
||||
if (message.ContainsInvariant("Couldn't find image"))
|
||||
{
|
||||
if (!message.ContainsInvariant("__TB") &&
|
||||
!message.ContainsInvariant("special/") &&
|
||||
!message.ContainsInvariant(TBConsts.CLIP_TEXTURE) &&
|
||||
!message.ContainsInvariant(TBConsts.SKIP_TEXTURE) &&
|
||||
!message.ContainsInvariant(TBConsts.TRIGGER_TEXTURE))
|
||||
{
|
||||
s_OverrideResult = Q3Map2Result.FailedWithMissingTextures;
|
||||
}
|
||||
}
|
||||
else if (message.StartsWithInvariant("WARNING:") &&
|
||||
!message.ContainsInvariant("Unknown option") &&
|
||||
!message.ContainsInvariant("90 percent structural map"))
|
||||
{
|
||||
Debug.LogWarning($"Q3Map2: {message}");
|
||||
s_OverrideResult = Q3Map2Result.SucceededWithWarnings;
|
||||
}
|
||||
|
||||
s_OnOutputMessage?.Invoke(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96f77a2ed09c4489b7ddc58dddd66940
|
||||
timeCreated: 1720944183
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Import/MapCompilerOutputHandler.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Scripting;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public abstract class MapProcessorBase
|
||||
{
|
||||
[Preserve]
|
||||
public static string Description => null;
|
||||
|
||||
private Transform m_RootTransform;
|
||||
public Transform RootTransform
|
||||
{
|
||||
get => m_RootTransform;
|
||||
set => m_RootTransform = value;
|
||||
}
|
||||
|
||||
public virtual void ProcessWorldSpawnProperties(MapBsp mapBsp, BspEntity entity, GameObject rootGameObject) { }
|
||||
public virtual void ProcessPrefabEntity(MapBsp mapBsp, BspEntity entity, GameObject prefab) { }
|
||||
public virtual void ProcessBrushEntity(MapBsp mapBsp, BspEntity entity, GameObject brush) { }
|
||||
public virtual void ProcessPointEntity(MapBsp mapBsp, BspEntity entity, GameObject point) { }
|
||||
|
||||
public virtual void OnProcessingStarted(GameObject root, MapBsp mapBsp) { }
|
||||
public virtual void OnProcessingCompleted(GameObject root, MapBsp mapBsp) { }
|
||||
|
||||
|
||||
public TWorldspawn GetWorldspawn<TWorldspawn>() where TWorldspawn : Worldspawn
|
||||
=> m_RootTransform.GetComponentInChildren<TWorldspawn>();
|
||||
|
||||
public GameObject InstantiatePrefab(GameObject prefab, Transform parent = null)
|
||||
=> PrefabUtil.InstantiatePrefab(prefab, parent ?? m_RootTransform);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1780f2d2510242499740fb1f7fbf0205
|
||||
timeCreated: 1699005929
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Import/MapProcessorBase.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Actual DLL call
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
public enum Q3Map2Result
|
||||
{
|
||||
Succeeded,
|
||||
SucceededWithWarnings,
|
||||
FailedWithMissingTextures,
|
||||
Failed,
|
||||
}
|
||||
public static class Q3Map2Dll
|
||||
{
|
||||
private static bool s_IsLoaded = false;
|
||||
public static bool IsLoaded => s_IsLoaded;
|
||||
|
||||
// Callback function signature
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void MessageHandlerFunc(string output);
|
||||
|
||||
// Change lib name based on platform
|
||||
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_LINUX || UNITY_STANDALONE_LINUX || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
|
||||
private const string Q3MAP2_LIB_NAME = "q3map2";
|
||||
#else
|
||||
//TODO(jwf): ATV: No q3map2 - solution: use "__Internal" as the name and build as static lib
|
||||
#warning Unknown platform - libq3map must be built as a static lib!
|
||||
private const string Q3MAP2_LIB_NAME = "__Internal";
|
||||
#endif
|
||||
|
||||
#if UNITY_WEBGL || UNITY_TVOS
|
||||
// Stub for WebGL, tvOS
|
||||
public static int DLL_ConvertMap(
|
||||
string mapFile,
|
||||
string fsPath,
|
||||
MessageHandlerFunc functionCallback,
|
||||
string[] inArgs,
|
||||
int inArgCount)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
// DLL entry point for conversion
|
||||
[DllImport(Q3MAP2_LIB_NAME, EntryPoint = "convert_map_unity", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int DLL_ConvertMap(
|
||||
[MarshalAs(UnmanagedType.LPStr)] string mapFile,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string fsPath,
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)] MessageHandlerFunc functionCallback,
|
||||
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 4)] string[] inArgs,
|
||||
[MarshalAs(UnmanagedType.SysInt)] int inArgCount);
|
||||
#endif
|
||||
|
||||
public static int ConvertMap(string mapFile, MessageHandlerFunc functionCallback, string[] inArgs)
|
||||
=> ConvertMap(mapFile, "Library", functionCallback, inArgs);
|
||||
|
||||
public static int ConvertMap(string mapFile, string fsPath, MessageHandlerFunc functionCallback, string[] inArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
s_IsLoaded = true;
|
||||
|
||||
// Use another thread to do the actual compilation,
|
||||
// so that we can control the stack size.
|
||||
const int STACK_SIZE_MB = 8;
|
||||
|
||||
int exitCode = 0;
|
||||
void CompileOnOtherThread()
|
||||
=> exitCode = DLL_ConvertMap(mapFile, fsPath, functionCallback, inArgs, inArgs.Length);
|
||||
|
||||
Thread compilerThread = new(
|
||||
start: CompileOnOtherThread,
|
||||
maxStackSize: STACK_SIZE_MB * 1024 * 1024
|
||||
);
|
||||
compilerThread.Start();
|
||||
compilerThread.Join();
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
s_IsLoaded = false;
|
||||
return -0xdead;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Plugins Folder
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
#if UNITY_EDITOR
|
||||
private static string PluginsFolder => Path.Combine(TrembleConsts.EDITOR_GetTrembleInstallFolder(), "Plugins");
|
||||
public static bool EDITOR_PluginsFolderExists() => Directory.Exists(PluginsFolder);
|
||||
|
||||
public static void EDITOR_DeletePluginsFolder()
|
||||
{
|
||||
if (!EDITOR_PluginsFolderExists())
|
||||
return;
|
||||
|
||||
EDITOR_IsPluginsFolderFlaggedForDeletion = false;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(PluginsFolder, true);
|
||||
|
||||
string metaFile = PluginsFolder + ".meta";
|
||||
if (File.Exists(metaFile))
|
||||
{
|
||||
File.Delete(PluginsFolder + ".meta");
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
EDITOR_IsPluginsFolderFlaggedForDeletion = true;
|
||||
|
||||
EditorUtility.DisplayDialog(
|
||||
title: "Q3Map2 Upgrade",
|
||||
message: $"Unfortunately, the auto-upgrader has encountered an error. Please quit Unity, and manually delete {PluginsFolder} in your file explorer. Sorry!",
|
||||
ok: "Got it, no worries!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool EDITOR_IsPluginsFolderFlaggedForDeletion
|
||||
{
|
||||
get => EditorPrefs.GetBool($"Tremble_{Application.productName}_DeletePluginsNow", false);
|
||||
set => EditorPrefs.SetBool($"Tremble_{Application.productName}_DeletePluginsNow", value);
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Version Info
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
public static Q3Map2VersionInfo GetTinyGooseVersionInfo()
|
||||
{
|
||||
const string LIB_Q3_MAP2 = "libQ3Map2 (Tiny Goose)";
|
||||
|
||||
Dictionary<string, string> info = GetVersionInfo();
|
||||
return Q3Map2VersionInfo.Parse(info.GetValueOrDefault(LIB_Q3_MAP2, null)); // e.g. v2.5.1n-git-f278fa
|
||||
}
|
||||
|
||||
public static Dictionary<string, string> GetVersionInfo()
|
||||
{
|
||||
string[] args = { "-v" };
|
||||
List<string> outputLines = new();
|
||||
|
||||
ConvertMap("", line => outputLines.Add(line), args);
|
||||
|
||||
Dictionary<string, string> info = new();
|
||||
foreach (string line in outputLines)
|
||||
{
|
||||
if (!TrySplitLineIntoKeyValue(line, out string key, out string value))
|
||||
continue;
|
||||
|
||||
info[key] = value;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private static bool TrySplitLineIntoKeyValue(string line, out string key, out string value)
|
||||
{
|
||||
Span<char> separators = stackalloc char[2];
|
||||
separators[0] = '-';
|
||||
separators[1] = ':';
|
||||
|
||||
foreach (char separator in separators)
|
||||
{
|
||||
int sepIdx = line.IndexOf(separator);
|
||||
if (sepIdx == -1)
|
||||
continue;
|
||||
|
||||
key = line.Substring(0, sepIdx).Trim();
|
||||
value = line.Substring(sepIdx + 1).Trim();
|
||||
return true;
|
||||
}
|
||||
|
||||
key = value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71dcd1e650e444787a70e52840cf86f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Import/Q3Map2Dll.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public struct Q3Map2VersionInfo
|
||||
{
|
||||
public int Major;
|
||||
public int Minor;
|
||||
public int Patch;
|
||||
public char Letter;
|
||||
public string GitHash;
|
||||
|
||||
public override string ToString() => $"v{Major}.{Minor}.{Patch}{Letter}-git-{GitHash}";
|
||||
|
||||
private static Q3Map2VersionInfo Empty => new() { Major = 0, Minor = 0, Patch = 0, Letter = 'x', GitHash = "deadbeef" };
|
||||
|
||||
public static Q3Map2VersionInfo Parse(string version)
|
||||
{
|
||||
if (String.IsNullOrEmpty(version) || !version.ContainsInvariant("-") || !version.ContainsInvariant("."))
|
||||
return Empty;
|
||||
|
||||
string[] rootVersionInfo = version.Split('-');
|
||||
if (rootVersionInfo.Length != 3)
|
||||
return Empty;
|
||||
|
||||
string[] versionParts = rootVersionInfo[0].Split('.');
|
||||
if (versionParts.Length != 3)
|
||||
return Empty;
|
||||
|
||||
Q3Map2VersionInfo info;
|
||||
info.Major = int.Parse(versionParts[0].Substring(1));
|
||||
info.Minor = int.Parse(versionParts[1]);
|
||||
info.Patch = int.Parse(versionParts[2].Substring(0, versionParts[2].Length - 1));
|
||||
info.Letter = versionParts[2][^1];
|
||||
info.GitHash = rootVersionInfo[2];
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11da1594d9414433b92548628283ce8e
|
||||
timeCreated: 1735838685
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Import/Q3Map2VersionInfo.cs
|
||||
uploadId: 939664
|
||||
Reference in new issue
Block a user