-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bw localization plugin v6 on frosty1.6 (#211)
* Commit full version 1.1.0.5 of the BW Localization Plugin # Conflicts: # Plugins/BiowareLocalizationPlugin/BiowareLocalizedStringDatabase.cs # Plugins/BiowareLocalizationPlugin/LocalizedStringResource.cs * Add option to search with decimal text ids * Prepare data structure for editing declinated adjectives * Implement DragonAgeDeclinatedAdjectiveTuples- functions missing from last commit * Prepare writing capability for DA:I declinated crafting name adjectives, bump plugin version to reflect major change in produced mod file * Add setter and remove methods in resource, fix test method * Fix incorrectly stated number of declinations * Add adjective getters to text resources * Refactor xml export, write declinated adjectives. * Allow Importing of declinated adjectives from xml file * Add Toggle and (currently non functional) resource selector in ui * Fix switching to adjectives * Enable display of declinated adjectives * Add first sign of adjective edit window * Working Edit dialog for adjectives * Try formatting code in accordance with frosty codingstandards * Small fixes to the adjective edit window * Add ReplaceWindow * Fix higlighting and display issues * Make replacement window available form generic string editor * Add settings for xml export
- Loading branch information
1 parent
5a67f9e
commit 90dd6ae
Showing
33 changed files
with
7,592 additions
and
287 deletions.
There are no files selected for viewing
68 changes: 68 additions & 0 deletions
68
Plugins/BiowareLocalizationPlugin/BW LocaliziationResourceBits.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
Part: Type and what Byte position after this | ||
|
||
MetaData (16 bytes, located in Frosty at Resource.resMeta, not part of the byte count ) | ||
{ | ||
uint dataOffset | ||
3x byte value 0x0 | ||
} | ||
Header | ||
{ | ||
uint magic = 0xd78b40eb (pos 4) | ||
uint ??? (pos 8) // doesn't seem to affect anything | ||
uint dataOffset (pos 12) // not actually used, instead the one from the metadata is the base for the game | ||
3x uint ??? (pos 24) // doens't seem to affect anything | ||
|
||
uint nodeCount (pos 28) | ||
// nodeCount is an even integer! The rootNode as would-be last node in the node list is *not* actually part of the list! | ||
|
||
uint nodeOffset (pos 32) | ||
|
||
uint stringsCount (pos 36) | ||
uint stringsOffset (pos 40) | ||
|
||
// Until the nodeOffset is reached | ||
// If there are three or more entries in here, | ||
// then the corresponding 8ByteBlockData after the second one contain ids and bit offsets for the declinated adjectives for text parts used for crafted items in DA:I (Note that these ids are not the same accross languages!) | ||
N times Unknown8ByteBlockCountAndOffset | ||
{ | ||
uint unknownCounts | ||
uint unknownOffset | ||
} | ||
} | ||
|
||
// Position = nodeOffset -> pos most likely either 56 or 64 | ||
HuffmanCoding | ||
{ | ||
nodeCount x uint value == bitFlip char | ||
} | ||
(size = 4 per node) | ||
|
||
// Position = stringsOffset | ||
StringData | ||
{ | ||
stringsCount x | ||
{ | ||
uint stringId | ||
int stringIndex / positionOffset | ||
} | ||
(size = 8 per string) | ||
} | ||
|
||
// Position = Unknown8ByteBlockCountAndOffset[0].unknownOffset | ||
// The next data blocks appears the same N times as their Unknown8ByteBlockCountAndOffset counterpart in the header | ||
// Everything past the second of these blocks contains the bit offsets of the text pieces used for crafted item names in DA:I | ||
N times 8ByteBlockData | ||
{ | ||
// Position = Unknown8ByteBlockCountAndOffset[index].unknownOffset | ||
byte[].Length = Unknown8ByteBlockCountAndOffset[index].unknownCounts * 8 | ||
} | ||
|
||
// Position = dataOffset | ||
Strings | ||
{ | ||
stringsCount * HuffmanEncodedChars | ||
} | ||
// stringIndex / positionOffset = bit offset from dataOffset == textBefore bitOffset + textBefore bitlentgh | ||
// last symbol (only symbol of empty string) is huffman node with letter 0x00! I.e., _value_ = 0xFF | ||
|
||
Remaining positions to full byte filled with 0s |
28 changes: 28 additions & 0 deletions
28
Plugins/BiowareLocalizationPlugin/BioWareLocalizedStringEditorMenuExtension.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using BiowareLocalizationPlugin.Controls; | ||
using Frosty.Core; | ||
using FrostySdk; | ||
|
||
namespace BiowareLocalizationPlugin | ||
{ | ||
public class BioWareLocalizedStringEditorMenuExtension : MenuExtension | ||
{ | ||
|
||
private const string ITEM_NAME = "Bioware Localized String Editor"; | ||
|
||
public override string TopLevelMenuName => "View"; | ||
|
||
public override string SubLevelMenuName => null; | ||
public override string MenuItemName => ITEM_NAME; | ||
|
||
public override RelayCommand MenuItemClicked => new RelayCommand((o) => | ||
{ | ||
if (ProfilesLibrary.DataVersion == (int)ProfileVersion.Anthem) | ||
{ | ||
App.Logger.Log("Not applicable for Anthem, sorry for the inconvenience!"); | ||
return; | ||
} | ||
var textDb = (BiowareLocalizedStringDatabase) LocalizedStringDatabase.Current; | ||
App.EditorWindow.OpenEditor(ITEM_NAME, new BiowareLocalizedStringEditor(textDb)); | ||
}); | ||
} | ||
} |
188 changes: 188 additions & 0 deletions
188
Plugins/BiowareLocalizationPlugin/BiowareLocalizationCustomActionHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
using BiowareLocalizationPlugin.LocalizedResources; | ||
using Frosty.Core; | ||
using Frosty.Core.IO; | ||
using Frosty.Core.Mod; | ||
using Frosty.Hash; | ||
using FrostySdk; | ||
using FrostySdk.IO; | ||
using FrostySdk.Managers; | ||
using FrostySdk.Resources; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace BiowareLocalizationPlugin | ||
{ | ||
public class BiowareLocalizationCustomActionHandler : ICustomActionHandler | ||
{ | ||
|
||
public HandlerUsage Usage => HandlerUsage.Merge; | ||
|
||
// A mod is comprised of a series of base resources, embedded, ebx, res, and chunks. Embedded are used internally | ||
// for the icon and images of a mod. Ebx/Res/Chunks are the core resources used for applying data to the game. | ||
// When you create a custom handler, you need to provide your own resources for your custom handled data. This | ||
// resource is unique however it is based on one of the three core types. | ||
private class BiowareLocalizationModResource : EditorModResource | ||
{ | ||
|
||
// Defines which type of resource this resource is. | ||
public override ModResourceType Type => ModResourceType.Res; | ||
|
||
|
||
// The resType is vital to be kept (its always LocalizedStringResource, but whatever) | ||
private readonly uint m_resType; | ||
|
||
// these other two fields may have to be written to the mod as well | ||
private readonly ulong m_resRid; | ||
private readonly byte[] m_resMeta; | ||
|
||
|
||
public BiowareLocalizationModResource(ResAssetEntry inEntry, FrostyModWriter.Manifest inManifest) : base(inEntry) | ||
{ | ||
|
||
// This constructor does the exact same thing as the ones in the TestPlugin | ||
|
||
// obtain the modified data | ||
ModifiedLocalizationResource md = inEntry.ModifiedEntry.DataObject as ModifiedLocalizationResource; | ||
byte[] data = md.Save(); | ||
|
||
// store data and details about resource | ||
name = inEntry.Name.ToLower(); | ||
sha1 = Utils.GenerateSha1(data); | ||
resourceIndex = inManifest.Add(sha1, data); | ||
size = data.Length; | ||
|
||
// set the handler hash to the hash of the res type name | ||
handlerHash = Fnv1.HashString(inEntry.Type.ToLower()); | ||
|
||
m_resType = inEntry.ResType; | ||
m_resRid = inEntry.ResRid; | ||
m_resMeta = inEntry.ResMeta; | ||
} | ||
|
||
/// <summary> | ||
/// This method is calles when writing the mod. For Res Types it is vital that some additional information is persisted that is not written by the base method. | ||
/// Mainly that is the ResourceType as uint | ||
/// Additional data that is read, but I'm not sure whether it is actually necessary: | ||
/// <ul> | ||
/// <li>ResRid as ulong (not sure if this is really necessary, i.e., actually read) | ||
/// <li>resMeta length | ||
/// <li>resMeta as byte array | ||
/// </ul> | ||
/// </summary> | ||
/// <param name="writer"></param> | ||
public override void Write(NativeWriter writer) | ||
{ | ||
base.Write(writer); | ||
|
||
// write the required res type: | ||
writer.Write(m_resType); | ||
|
||
writer.Write(m_resRid); | ||
writer.Write((m_resMeta != null) ? m_resMeta.Length : 0); | ||
if (m_resMeta != null) | ||
{ | ||
writer.Write(m_resMeta); | ||
} | ||
} | ||
} | ||
|
||
#region -- Editor Specific -- | ||
|
||
// This function is for writing resources to the mod file, this is where you would add your custom | ||
// resources to be written. | ||
public void SaveToMod(FrostyModWriter writer, AssetEntry entry) | ||
{ | ||
writer.AddResource(new BiowareLocalizationModResource(entry as ResAssetEntry, writer.ResourceManifest)); | ||
} | ||
#endregion | ||
|
||
#region -- Mod Specific -- | ||
|
||
// This function is for the mod managers action view, to allow a handler to describe detailed actions performed | ||
// format of the action string is <ResourceName>;<ResourceType>;<Action> where action can be Modify or Merge (or Add!) | ||
// and ResourceType can be Ebx,Res,Chunk | ||
public IEnumerable<string> GetResourceActions(string name, byte[] data) | ||
{ | ||
|
||
if( !Config.Get(BiowareLocalizationPluginOptions.SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME, false, ConfigScope.Global)) | ||
{ | ||
return new List<string>(); | ||
} | ||
|
||
ModifiedLocalizationResource modified = ModifiedResource.Read(data) as ModifiedLocalizationResource; | ||
|
||
List<uint> textIds = new List<uint>(modified.AlteredTexts.Keys); | ||
textIds.Sort(); | ||
|
||
List<string> resourceActions = new List<string>(textIds.Count); | ||
foreach (uint textId in textIds) | ||
{ | ||
string resourceName = new StringBuilder(name).Append(" (0x").Append(textId.ToString("X8")).Append(')').ToString(); | ||
string resourceType = "res"; | ||
string action = "Modify"; | ||
|
||
resourceActions.Add(resourceName + ";" + resourceType + ";" + action); | ||
} | ||
|
||
return resourceActions; | ||
} | ||
|
||
// This function is invoked when a mod with such a handler is loaded, if a previous mod with a handler for this | ||
// particular asset was loaded previously, then existing will be populated with that data, allowing this function | ||
// the chance to merge the two datasets together | ||
public object Load(object existing, byte[] newData) | ||
{ | ||
|
||
ModifiedLocalizationResource edited = (ModifiedLocalizationResource)existing; | ||
ModifiedLocalizationResource newTexts = (ModifiedLocalizationResource) ModifiedResource.Read(newData); | ||
|
||
if(edited == null) | ||
{ | ||
return newTexts; | ||
} | ||
|
||
edited.Merge(newTexts); | ||
|
||
return edited; | ||
} | ||
|
||
// This function is invoked at the end of the mod loading, to actually modify the existing game data with the end | ||
// result of the mod loaded data, it also allows for a handler to add new Resources to be replaced. | ||
// ie. an Ebx handler might want to add a new Chunk resource that it is dependent on. | ||
public void Modify(AssetEntry origEntry, AssetManager am, RuntimeResources runtimeResources, object data, out byte[] outData) | ||
{ | ||
|
||
// no idea what frosty does if the resource does not exist in the local game, so first check for null: | ||
if(origEntry == null) | ||
{ | ||
outData = System.Array.Empty<byte>(); | ||
return; | ||
} | ||
|
||
// load the original resource | ||
ResAssetEntry originalResAsset = am.GetResEntry(origEntry.Name); | ||
ModifiedLocalizationResource modified = data as ModifiedLocalizationResource; | ||
LocalizedStringResource resource = am.GetResAs<LocalizedStringResource>(originalResAsset, modified); | ||
|
||
// read about some weird null reference exception in here, so _maybe_ it was the resource? | ||
if(resource == null) | ||
{ | ||
throw new ArgumentNullException("resource", string.Format("Resource in BwLocalizationHandler Modify(...) is null after GetResAs call for <{0}>!", origEntry.Name)); | ||
} | ||
|
||
byte[] uncompressedData = resource.SaveBytes(); | ||
outData = Utils.CompressFile(uncompressedData); | ||
|
||
// update the metadata | ||
byte[] alteredMetaData = resource.ResourceMeta; | ||
((ResAssetEntry)origEntry).ResMeta = alteredMetaData; | ||
|
||
// update relevant asset entry values | ||
origEntry.OriginalSize = uncompressedData.Length; | ||
origEntry.Size = outData.Length; | ||
origEntry.Sha1 = Utils.GenerateSha1(outData); | ||
} | ||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
Plugins/BiowareLocalizationPlugin/BiowareLocalizationPluginModManagerOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
| ||
using Frosty.Core; | ||
using FrostySdk.Attributes; | ||
|
||
namespace BiowareLocalizationPlugin | ||
{ | ||
[DisplayName("Bioware Localization Options")] | ||
public class BiowareLocalizationPluginOptions : OptionsExtension | ||
{ | ||
|
||
// The name for the global mod manager variable. | ||
public static readonly string SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME = "BwLoMoShowIndividualTextIds"; | ||
|
||
public static readonly string ASK_XML_EXPORT_OPTIONS = "BwLoEoAskXmlExportOptions"; | ||
|
||
[Category("Mod Manager Options")] | ||
[Description("If enabled, all individual text ids in each resource (res) are shown in the mod manager's Actions tab. Otherwise only the resource iteself is shown as merged. This setting is only for the mod manager and has no effect in the editor.")] | ||
[DisplayName("Show Individual Text Ids")] | ||
[EbxFieldMeta(FrostySdk.IO.EbxFieldType.Boolean)] | ||
public bool ShowIndividualTextIds { get; set; } = false; | ||
|
||
[Category("Editor Options")] | ||
[DisplayName("Ask for Xml Export Options")] | ||
[Description("If enabled, a popup prompt allows selecting whether to export all texts or only modified ones. If this value is false, then the default from below is used. This setting is only for the editor and has no effect in the mod manager.")] | ||
[EbxFieldMeta(FrostySdk.IO.EbxFieldType.Boolean)] | ||
public bool AskForXmlExportOptions { get; set; } = false; | ||
|
||
public override void Load() | ||
{ | ||
// mod manager | ||
ShowIndividualTextIds = Config.Get(SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME, false, ConfigScope.Global); | ||
|
||
// editor | ||
AskForXmlExportOptions = Config.Get(ASK_XML_EXPORT_OPTIONS, false, ConfigScope.Global); | ||
} | ||
|
||
public override void Save() | ||
{ | ||
// mod manager | ||
Config.Add(SHOW_INDIVIDUAL_TEXTIDS_OPTION_NAME, ShowIndividualTextIds, ConfigScope.Global); | ||
|
||
// editor | ||
Config.Add(ASK_XML_EXPORT_OPTIONS, AskForXmlExportOptions, ConfigScope.Global); | ||
} | ||
} | ||
} |
Oops, something went wrong.