Skip to content

Commit f8c592a

Browse files
committed
- Enabled basic Furniture Dependency support.
- Improved Character Tab dependency support. (Still disabled for character-body elements)
1 parent bc3bd84 commit f8c592a

File tree

9 files changed

+127
-53
lines changed

9 files changed

+127
-53
lines changed

xivModdingFramework/Cache/XivCache.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static class XivCache
2727
private static GameInfo _gameInfo;
2828
private static DirectoryInfo _dbPath;
2929
private static DirectoryInfo _rootCachePath;
30-
public static readonly Version CacheVersion = new Version("1.0.1.0");
30+
public static readonly Version CacheVersion = new Version("1.0.1.1");
3131
private const string dbFileName = "mod_cache.db";
3232
private const string rootCacheFileName = "item_sets.db";
3333
private const string creationScript = "CreateCacheDB.sql";
@@ -437,7 +437,7 @@ private static async Task RebuildFurnitureCache()
437437
{
438438

439439
var query = @"
440-
insert into housing ( name, category, subcategory, primary_id, icon_id, root)
440+
insert into furniture ( name, category, subcategory, primary_id, icon_id, root)
441441
values($name, $category, $subcategory, $primary_id, $icon_id, $root)";
442442

443443
var root = item.GetRootInfo();
@@ -724,7 +724,7 @@ internal static async Task<List<XivFurniture>> GetCachedFurnitureList(string sub
724724
where.Value = "%" + substring + "%";
725725
}
726726

727-
return await BuildListFromTable("housing", where, async (reader) =>
727+
return await BuildListFromTable("furniture", where, async (reader) =>
728728
{
729729
return MakeFurniture(reader);
730730
});

xivModdingFramework/Cache/XivDependencyGraph.cs

Lines changed: 81 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using xivModdingFramework.General.Enums;
1010
using xivModdingFramework.Helpers;
1111
using xivModdingFramework.Items;
12+
using xivModdingFramework.Items.Categories;
1213
using xivModdingFramework.Items.DataContainers;
1314
using xivModdingFramework.Items.Enums;
1415
using xivModdingFramework.Items.Interfaces;
@@ -67,9 +68,10 @@ public static async Task<List<IItemModel>> GetSharedMaterialItems(this IItemMode
6768
var sameModelItems = new List<IItemModel>();
6869
sameModelItems = await item.GetSharedModelItems();
6970

70-
var sameMaterialItems = new List<IItemModel>();
7171
try
7272
{
73+
var sameMaterialItems = new List<IItemModel>();
74+
7375
var imc = new Imc(XivCache.GameInfo.GameDirectory);
7476
var originalInfo = await imc.GetImcInfo(item);
7577
foreach (var i in sameModelItems)
@@ -80,14 +82,15 @@ public static async Task<List<IItemModel>> GetSharedMaterialItems(this IItemMode
8082
sameMaterialItems.Add(i);
8183
}
8284
}
85+
86+
sameMaterialItems = sameMaterialItems.OrderBy(x => x.Name, new ItemNameComparer()).ToList();
87+
return sameMaterialItems;
8388
} catch
8489
{
85-
// No IMC file exists for this item.
86-
// It is by requirement the only item of its type then.
87-
sameMaterialItems.Add((IItemModel) item.Clone());
90+
// No IMC file exists for this item.
91+
// In this case, it affects all items in the same root.
92+
return sameModelItems;
8893
}
89-
sameMaterialItems = sameMaterialItems.OrderBy(x => x.Name, new ItemNameComparer()).ToList();
90-
return sameMaterialItems;
9194
}
9295
public static async Task<List<IItemModel>> GetSharedModelItems(this IItemModel item)
9396
{
@@ -189,14 +192,16 @@ public bool IsValid()
189192
// Type -> TypeCode -> Id
190193
private static readonly string RootFolderFormatSecondary = "obj/{0}/{1}{2}/";
191194

195+
private static readonly string HousingRootFolderFormat = "bgcommon/hou/{0}/general/{1}/";
196+
197+
192198
// pPrefix => pId => sPrefix => sId => Slot
193199
private static readonly string BaseFileFormatWithSlot = "{0}{1}{2}{3}_{4}";
194200
private static readonly string BaseFileFormatNoSlot = "{0}{1}{2}{3}";
195201

196202
// {0} = BaseFileFormat
197203
private static readonly string ModelNameFormat = "{0}.mdl";
198204

199-
200205
/// <summary>
201206
/// Gets the file name base for this root.
202207
/// Ex c0101f0001_fac
@@ -225,11 +230,6 @@ public string GetBaseFileName()
225230
}
226231

227232
public string GetRootFile()
228-
{
229-
return GetRootFolder() + GetBaseFileName() + ".root";
230-
}
231-
232-
public string GetMetaFile()
233233
{
234234
return GetRootFolder() + GetBaseFileName() + ".meta";
235235
}
@@ -240,23 +240,33 @@ public string GetMetaFile()
240240
/// <returns></returns>
241241
public string GetRootFolder()
242242
{
243-
var pId = PrimaryId.ToString().PadLeft(4, '0');
244-
var primary = String.Format(RootFolderFormatPrimary, new string[] { XivItemTypes.GetSystemName(PrimaryType), XivItemTypes.GetSystemPrefix(PrimaryType), pId });
245-
246-
var secondary = "";
247-
if (SecondaryType != null)
243+
if (PrimaryType == XivItemType.indoor || PrimaryType == XivItemType.outdoor)
248244
{
249-
var sId = SecondaryId.ToString().PadLeft(4, '0');
250-
var sType = (XivItemType)SecondaryType;
251-
secondary = String.Format(RootFolderFormatSecondary, new string[] { XivItemTypes.GetSystemName(sType), XivItemTypes.GetSystemPrefix(sType), sId });
245+
// BGCommon Dat stuff.
246+
var pId = PrimaryId.ToString().PadLeft(4, '0');
247+
return String.Format(HousingRootFolderFormat, new string[] { XivItemTypes.GetSystemName(PrimaryType), pId });
252248
}
249+
else
250+
{
251+
// All the Dat 4 stuff.
252+
var pId = PrimaryId.ToString().PadLeft(4, '0');
253+
var primary = String.Format(RootFolderFormatPrimary, new string[] { XivItemTypes.GetSystemName(PrimaryType), XivItemTypes.GetSystemPrefix(PrimaryType), pId });
254+
255+
var secondary = "";
256+
if (SecondaryType != null)
257+
{
258+
var sId = SecondaryId.ToString().PadLeft(4, '0');
259+
var sType = (XivItemType)SecondaryType;
260+
secondary = String.Format(RootFolderFormatSecondary, new string[] { XivItemTypes.GetSystemName(sType), XivItemTypes.GetSystemPrefix(sType), sId });
261+
}
253262

254-
return primary + secondary;
263+
return primary + secondary;
264+
}
255265
}
256266

257267
public string GetSimpleModelName()
258268
{
259-
if (SecondaryType == null)
269+
if (PrimaryType == XivItemType.equipment || PrimaryType == XivItemType.accessory)
260270
{
261271
throw new NotSupportedException("Cannot generate simple model name for this type. EQDP file must Be used.");
262272
}
@@ -406,6 +416,13 @@ public XivDependencyRoot(XivDependencyRootInfo info)
406416
// initial crawls up the tree are janky.
407417
Info.Slot = "top";
408418
}
419+
} else if(Info.PrimaryType == XivItemType.indoor)
420+
{
421+
Info.Slot = "fun";
422+
423+
} else if(Info.PrimaryType == XivItemType.outdoor)
424+
{
425+
Info.Slot = "gar";
409426
}
410427
}
411428

@@ -482,6 +499,11 @@ public async Task<List<string>> GetModelFiles()
482499
models.Add(Info.GetRootFolder() + "model/" + Info.GetRacialModelName(race));
483500
}
484501
return models;
502+
} else if(Info.PrimaryType == XivItemType.indoor || Info.PrimaryType == XivItemType.outdoor)
503+
{
504+
var _housing = new Housing(XivCache.GameInfo.GameDirectory, XivCache.GameInfo.GameLanguage);
505+
var housingAssets = await _housing.GetFurnitureModelParts(Info.PrimaryId, Info.PrimaryType);
506+
return housingAssets.Select(x => x.Value).ToList();
485507
} else {
486508
// The rest of the types just have a single, calculateable model path.
487509
var folder = Info.GetRootFolder();
@@ -560,6 +582,13 @@ public async Task<List<string>> GetTextureFiles(int materialVariant = -1)
560582
public string GetRawImcFilePath()
561583
{
562584
var imcPath = "";
585+
if(Info.PrimaryType == XivItemType.indoor || Info.PrimaryType == XivItemType.outdoor)
586+
{
587+
// These types can never have IMC entries.
588+
return null;
589+
}
590+
591+
563592
if (Info.SecondaryType == null)
564593
{
565594
var iPrefix = XivItemTypes.GetSystemPrefix(Info.PrimaryType);
@@ -889,6 +918,11 @@ public async Task<List<IItemModel>> GetAllItems(int imcSubset = -1)
889918
items = items.Where(x => x.ModelInfo.ImcSubsetID == imcSubset).ToList();
890919
}
891920

921+
if (items.Count == 0) {
922+
// May as well make a raw item.
923+
items.Add(ToRawItem());
924+
}
925+
892926
items = items.OrderBy(x => x.Name, new ItemNameComparer()).ToList();
893927

894928
return items;
@@ -955,18 +989,8 @@ internal static class XivDependencyGraph
955989
XivItemType.monster,
956990
XivItemType.demihuman,
957991
XivItemType.human,
958-
959-
// XivItemType.body, // Needs some extra custom handling still for skin materials.
960-
961-
/*
962-
// These types need more work for dependency suppport.
963-
964-
// Furniture primarily needs the appropriate function for resolving the model files,
965-
// and the meta sgd(sp?) file that they have instead of an IMC file.
966992
XivItemType.indoor,
967993
XivItemType.outdoor,
968-
*/
969-
970994
};
971995

972996
// Captures the file extension of a file (even if it has a binary extension)
@@ -993,6 +1017,12 @@ internal static class XivDependencyGraph
9931017

9941018
private static readonly Regex PrimaryExtractionRegex = new Regex("^chara\\/([a-z]+)\\/[a-z]([0-9]{4})(?:\\/obj\\/([a-z]+)\\/[a-z]([0-9]{4})\\/?)?.*$");
9951019

1020+
1021+
// Group 0 == Full File path
1022+
// Group 1 == Type (indoor/outdoor)
1023+
// Group 2 == Primary Id
1024+
private static readonly Regex HousingExtractionRegex = new Regex("^bgcommon/hou/([a-z]+)/general/([0-9]+)/?.*$");
1025+
9961026
/// <summary>
9971027
/// Returns all parent files that this child file depends on as part of its rendering process.
9981028
/// </summary>
@@ -1110,6 +1140,12 @@ public static async Task<List<string>> GetSiblingFiles(string internalFilePath)
11101140
siblings.Add(c);
11111141
}
11121142
}
1143+
1144+
if(siblings.Count == 0)
1145+
{
1146+
siblings.Add(internalFilePath);
1147+
}
1148+
11131149
return siblings.ToList();
11141150
}
11151151

@@ -1162,7 +1198,7 @@ public static async Task<List<string>> GetChildFiles(string internalFilePath)
11621198
{
11631199
var dataFile = IOUtil.GetDataFileFromPath(internalFilePath);
11641200
var _mtrl = new Mtrl(XivCache.GameInfo.GameDirectory, dataFile, XivCache.GameInfo.GameLanguage);
1165-
var mtrlChildren = await _mtrl.GetTexturePathsFromMtrlPath(internalFilePath, false);
1201+
var mtrlChildren = await _mtrl.GetTexturePathsFromMtrlPath(internalFilePath, false, false);
11661202
return mtrlChildren;
11671203
} catch
11681204
{
@@ -1291,7 +1327,6 @@ public static XivDependencyRoot CreateDependencyRoot(XivDependencyRootInfo info)
12911327
// they'll have their root resolved via modlist, if one exists for them.
12921328
if (info.PrimaryType == XivItemType.equipment
12931329
|| info.PrimaryType == XivItemType.accessory
1294-
|| info.PrimaryType == XivItemType.human
12951330
|| info.PrimaryType == XivItemType.demihuman)
12961331
{
12971332
return null;
@@ -1300,7 +1335,7 @@ public static XivDependencyRoot CreateDependencyRoot(XivDependencyRootInfo info)
13001335

13011336
// Only these types can get away without a secondary type.
13021337
if(info.SecondaryType == null) {
1303-
if (info.PrimaryType != XivItemType.equipment && info.PrimaryType != XivItemType.accessory) {
1338+
if (info.PrimaryType != XivItemType.equipment && info.PrimaryType != XivItemType.accessory && info.PrimaryType != XivItemType.indoor && info.PrimaryType != XivItemType.outdoor) {
13041339
return null;
13051340
}
13061341
}
@@ -1384,7 +1419,18 @@ public static XivDependencyRootInfo ExtractRootInfo(string internalFilePath)
13841419
info.Slot = match.Groups[1].Value;
13851420
}
13861421
}
1422+
else
1423+
{
1424+
// Might be a housing item.
1425+
match = HousingExtractionRegex.Match(internalFilePath);
1426+
if (match.Success)
1427+
{
1428+
info.PrimaryType = XivItemTypes.FromSystemName(match.Groups[1].Value);
1429+
info.PrimaryId = Int32.Parse(match.Groups[2].Value);
13871430

1431+
info.Slot = info.PrimaryType == XivItemType.indoor ? "fun" : "gar";
1432+
}
1433+
}
13881434

13891435
return info;
13901436
}

xivModdingFramework/Items/Categories/Housing.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -374,16 +374,29 @@ await Task.Run(() => Parallel.ForEach(housingDictionary.Values, (housingItem) =>
374374
return furnitureList;
375375
}
376376

377+
public async Task<Dictionary<string, string>> GetFurnitureModelParts(IItemModel itemModel)
378+
{
379+
380+
return await GetFurnitureModelParts(itemModel.ModelInfo.PrimaryID, itemModel.SecondaryCategory);
381+
}
382+
383+
384+
public async Task<Dictionary<string, string>> GetFurnitureModelParts(int modelID, XivItemType type)
385+
{
386+
var cat = type == XivItemType.indoor ? XivStrings.Furniture_Indoor : XivStrings.Furniture_Outdoor;
387+
return await GetFurnitureModelParts(modelID, cat);
388+
}
389+
377390
/// <summary>
378391
/// Gets the parts list for furniture
379392
/// </summary>
380393
/// <param name="itemModel">The item to get the parts for</param>
381394
/// <returns>A dictionary containing the part string and mdl path string</returns>
382-
public async Task<Dictionary<string, string>> GetFurnitureModelParts(IItemModel itemModel)
395+
public async Task<Dictionary<string, string>> GetFurnitureModelParts(int modelID, string category)
383396
{
384397
var furniturePartDict = new Dictionary<string, string>();
385398

386-
var assets = await GetFurnitureAssets(itemModel.ModelInfo.PrimaryID, itemModel.SecondaryCategory);
399+
var assets = await GetFurnitureAssets(modelID, category);
387400

388401
foreach (var mdl in assets.MdlList)
389402
{
@@ -432,11 +445,11 @@ public async Task<Dictionary<string, string>> GetFurnitureModelParts(IItemModel
432445
return furniturePartDict;
433446
}
434447

435-
/// <summary>
436-
/// Gets the assets for furniture
437-
/// </summary>
438-
/// <param name="modelID">The model id to get the assets for</param>
439-
/// <returns>A HousingAssets object containing the asset info</returns>
448+
/// <summary>
449+
/// Gets the assets for furniture
450+
/// </summary>
451+
/// <param name="modelID">The model id to get the assets for</param>
452+
/// <returns>A HousingAssets object containing the asset info</returns>
440453
private async Task<HousingAssets> GetFurnitureAssets(int modelID, string category)
441454
{
442455
var index = new Index(_gameDirectory);

xivModdingFramework/Items/DataContainers/XivCharacter.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,21 @@ internal static IItemModel FromDependencyRoot(XivDependencyRoot root)
7676
item.ModelInfo = new XivModelInfo();
7777
item.ModelInfo.PrimaryID = root.Info.PrimaryId;
7878
item.ModelInfo.SecondaryID = (int)root.Info.SecondaryId;
79-
item.Name = root.Info.GetBaseFileName();
8079
item.PrimaryCategory = XivStrings.Character;
8180

8281
if (root.Info.Slot != null)
8382
{
8483
item.SecondaryCategory = Mdl.SlotAbbreviationDictionary.FirstOrDefault(x => x.Value == root.Info.Slot).Key;
84+
85+
//var race = XivRaces.GetXivRace(root.Info.PrimaryId.ToString().PadLeft(4, '0')).GetDisplayName();
86+
item.Name = item.SecondaryCategory + " - " + root.Info.GetBaseFileName();
8587
} else
8688
{
89+
item.Name = root.Info.GetBaseFileName();
8790
item.SecondaryCategory = XivStrings.Body;
8891
}
8992

93+
9094
return item;
9195
}
9296

xivModdingFramework/Items/DataContainers/XivFurniture.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ internal static IItemModel FromDependencyRoot(XivDependencyRoot root)
7373
var item = new XivFurniture();
7474
item.ModelInfo = new XivModelInfo();
7575
item.ModelInfo.PrimaryID = root.Info.PrimaryId;
76-
item.ModelInfo.SecondaryID = (int)root.Info.SecondaryId;
7776
item.Name = root.Info.GetBaseFileName();
7877
item.PrimaryCategory = XivStrings.Housing;
7978
if (root.Info.PrimaryType == Enums.XivItemType.indoor)

xivModdingFramework/Items/Enums/XivItemType.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ public enum XivItemType
4343
[Description("")] decal,
4444
[Description("")] ui,
4545
[Description("")] furniture, // This one's a little vague and encompasses really all of /bgcommon/
46-
[Description("")] indoor, // These are the clearer versions, but only used by the dependency graph.
47-
[Description("")] outdoor
46+
[Description("indoor")] indoor, // These are the clearer versions, but only used by the dependency graph.
47+
[Description("outdoor")] outdoor
4848
}
4949

5050
public static class XivItemTypes {

0 commit comments

Comments
 (0)