-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Plugins] Extracts DifficultyWeaponTableData from test plugin (#247)
- Loading branch information
1 parent
1397880
commit 54931ee
Showing
9 changed files
with
513 additions
and
4 deletions.
There are no files selected for viewing
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
70 changes: 70 additions & 0 deletions
70
Plugins/DifficultyWeaponTableDataPlugin/Controls/DifficultyWeaponTableEditor.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,70 @@ | ||
using DifficultyWeaponTableDataPlugin.Resources; | ||
using Frosty.Core; | ||
using Frosty.Core.Controls; | ||
using FrostySdk.Interfaces; | ||
using FrostySdk.IO; | ||
using FrostySdk.Managers; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using System.Windows; | ||
|
||
namespace DifficultyWeaponTableDataPlugin.Controls | ||
{ | ||
// Classes that derive from FrostyAssetEditor are used to edit assets specifically, they have a lot of boiler plate | ||
// code for loading assets and their dependencies. | ||
|
||
// This editor is used to edit assets of type DifficultyWeaponTableData, it is instantiated from the GetEditor | ||
// function of the corresponding AssetDefinition | ||
[TemplatePart(Name = "PART_AssetPropertyGrid", Type = typeof(FrostyPropertyGrid))] | ||
public class DifficultyWeaponTableEditor : FrostyAssetEditor | ||
{ | ||
private FrostyPropertyGrid propertyGrid; | ||
|
||
static DifficultyWeaponTableEditor() | ||
{ | ||
DefaultStyleKeyProperty.OverrideMetadata(typeof(DifficultyWeaponTableEditor), new FrameworkPropertyMetadata(typeof(DifficultyWeaponTableEditor))); | ||
} | ||
|
||
public DifficultyWeaponTableEditor(ILogger inLogger) | ||
: base(inLogger) | ||
{ | ||
} | ||
|
||
public override void OnApplyTemplate() | ||
{ | ||
base.OnApplyTemplate(); | ||
|
||
propertyGrid = GetTemplateChild("PART_AssetPropertyGrid") as FrostyPropertyGrid; | ||
propertyGrid.OnModified += PropertyGrid_OnModified; | ||
} | ||
|
||
// This function is used to override the editors load function to ensure that the asset is loaded | ||
// with a specific subclass of EbxAsset | ||
protected override EbxAsset LoadAsset(EbxAssetEntry entry) | ||
{ | ||
DifficultyWeaponTableData loadedAsset = App.AssetManager.GetEbxAs<DifficultyWeaponTableData>(entry); | ||
return loadedAsset; | ||
} | ||
|
||
// Functionality to perform when a property in the property grid is modified, in this case | ||
// the modified binding has been removed, as the editor will handle the modified data specifically | ||
// and then invoke the OnAssetModified function manually | ||
private void PropertyGrid_OnModified(object sender, ItemModifiedEventArgs e) | ||
{ | ||
// obtain the row and column of the edit via the item property paths | ||
string colIndex = e.Item.Parent.Name.Trim('[', ']'); | ||
string rowIndex = e.Item.Parent.Parent.Parent.Name.Trim('[', ']'); | ||
|
||
// add or modify the value on the asset | ||
DifficultyWeaponTableData assetData = asset as DifficultyWeaponTableData; | ||
assetData.ModifyValue(int.Parse(rowIndex), int.Parse(colIndex), (float)e.NewValue); | ||
|
||
// invoke the OnAssetModified function | ||
App.AssetManager.ModifyEbx(AssetEntry.Name, assetData); | ||
InvokeOnAssetModified(); | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
...s/DifficultyWeaponTableDataPlugin/Definitions/DifficultyWeaponTableDataAssetDefinition.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,31 @@ | ||
using DifficultyWeaponTableDataPlugin.Controls; | ||
using Frosty.Core; | ||
using Frosty.Core.Controls; | ||
using FrostySdk.Interfaces; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using System.Windows.Media; | ||
|
||
namespace DifficultyWeaponTableDataPlugin.Definitions | ||
{ | ||
// This asset defintion is about as simple as they come. It defines a generic icon that will be used in all cases | ||
// for all instances of the registered asset type. And provides its own custom editor. | ||
|
||
public class DifficultyWeaponTableDataAssetDefinition : AssetDefinition | ||
{ | ||
protected static ImageSource imageSource = new ImageSourceConverter().ConvertFromString("pack://application:,,,/TestPlugin;component/Images/SpreadsheetFileType.png") as ImageSource; | ||
|
||
public override ImageSource GetIcon() | ||
{ | ||
return imageSource; | ||
} | ||
|
||
public override FrostyAssetEditor GetEditor(ILogger logger) | ||
{ | ||
return new DifficultyWeaponTableEditor(logger); | ||
} | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
Plugins/DifficultyWeaponTableDataPlugin/DifficultyWeaponTableDataPlugin.csproj
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,66 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> | ||
<PropertyGroup> | ||
<Configurations>Developer - Debug;Release - Alpha;Release - Beta;Release - Final</Configurations> | ||
<Platforms>x64</Platforms> | ||
<TargetFrameworks>net48</TargetFrameworks> | ||
<AssemblyTitle>DifficultyWeaponTableDataPlugin</AssemblyTitle> | ||
<Product>DifficultyWeaponTableDataPlugin</Product> | ||
<Copyright>Copyright © 2020</Copyright> | ||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> | ||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> | ||
<UseWPF>true</UseWPF> | ||
<OutputType>Library</OutputType> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Developer - Debug|x64' "> | ||
<DebugSymbols>true</DebugSymbols> | ||
<OutputPath>bin\Developer\Debug\</OutputPath> | ||
<DefineConstants>DEBUG;TRACE</DefineConstants> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release - Alpha|x64' "> | ||
<OutputPath>bin\Release\Alpha\</OutputPath> | ||
<DefineConstants>TRACE</DefineConstants> | ||
<Optimize>true</Optimize> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release - Beta|x64'"> | ||
<OutputPath>bin\Release\Beta\</OutputPath> | ||
<DefineConstants>TRACE</DefineConstants> | ||
<Optimize>true</Optimize> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release - Final|x64'"> | ||
<OutputPath>bin\Release\Final\</OutputPath> | ||
<DefineConstants>TRACE</DefineConstants> | ||
<Optimize>true</Optimize> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Reference Include="PresentationCore" /> | ||
<Reference Include="PresentationFramework" /> | ||
<Reference Include="System.Xaml" /> | ||
<Reference Include="WindowsBase" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\FrostyControls\FrostyControls.csproj"> | ||
<Private>false</Private> | ||
</ProjectReference> | ||
<ProjectReference Include="..\..\FrostyHash\FrostyHash.vcxproj"> | ||
<Private>false</Private> | ||
</ProjectReference> | ||
<ProjectReference Include="..\..\FrostyPlugin\FrostyCore.csproj"> | ||
<Private>false</Private> | ||
</ProjectReference> | ||
<ProjectReference Include="..\..\FrostySdk\FrostySdk.csproj"> | ||
<Private>false</Private> | ||
</ProjectReference> | ||
</ItemGroup> | ||
|
||
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> | ||
<Exec Command="xcopy /Y $(TargetPath) $(SolutionDir)$(OutDir)Plugins\" /> | ||
<Exec Command="xcopy /Y $(TargetPath) $(SolutionDir)..\FrostyModManager\$(OutDir)Plugins\" /> | ||
</Target> | ||
|
||
</Project> |
150 changes: 150 additions & 0 deletions
150
Plugins/DifficultyWeaponTableDataPlugin/Handlers/DifficultyWeaponTableActionHandler.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,150 @@ | ||
using DifficultyWeaponTableDataPlugin.Resources; | ||
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.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace DifficultyWeaponTableDataPlugin.Handlers | ||
{ | ||
public class DifficultyWeaponTableActionHandler : ICustomActionHandler | ||
{ | ||
// This is purely for the mod managers action view and has no impact on how the handler actually executes. | ||
// It tells the mod manager actions view what type of action this handler performs, wether it replaces (Modify) | ||
// data from one mod with another, or does it merge the two together. | ||
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 DifficultyWeaponTableResource : EditorModResource | ||
{ | ||
// Defines which type of resource this resource is. | ||
public override ModResourceType Type => ModResourceType.Ebx; | ||
|
||
// Creates a new resource of the specified type and adds its data to the mod manifest. | ||
public DifficultyWeaponTableResource(EbxAssetEntry entry, FrostyModWriter.Manifest manifest) | ||
: base(entry) | ||
{ | ||
// obtain the modified data | ||
ModifiedResource md = entry.ModifiedEntry.DataObject as ModifiedResource; | ||
byte[] data = md.Save(); | ||
|
||
// store data and details about resource | ||
name = entry.Name.ToLower(); | ||
sha1 = Utils.GenerateSha1(data); | ||
resourceIndex = manifest.Add(sha1, data); | ||
size = data.Length; | ||
|
||
// set the handler hash to the hash of the ebx type name | ||
handlerHash = Fnv1.HashString(entry.Type.ToLower()); | ||
} | ||
} | ||
|
||
// The below functions are specific to the editor, it is used to save the modified data to a mod. | ||
|
||
#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 DifficultyWeaponTableResource(entry as EbxAssetEntry, writer.ResourceManifest)); | ||
} | ||
|
||
#endregion | ||
|
||
// The below functions are specific to the mod manager, it revolves around loading and potentially merging | ||
// of the data loaded from a mod. | ||
|
||
#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 | ||
// and ResourceType can be Ebx,Res,Chunk @todo | ||
public IEnumerable<string> GetResourceActions(string name, byte[] data) | ||
{ | ||
var newTable = ModifiedResource.Read(data) as ModifiedDifficultyWeaponTableData; | ||
List<string> resourceActions = new List<string>(); | ||
|
||
foreach (var value in newTable.Values) | ||
{ | ||
string resourceName = name + " (Row: " + value.Row + "/Col: " + value.Column + ")"; | ||
string resourceType = "ebx"; | ||
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) | ||
{ | ||
// load the existing modified data (from any previous mods) | ||
var oldTable = (ModifiedDifficultyWeaponTableData)existing; | ||
|
||
// load the new modified data from the current mod | ||
var newTable = ModifiedResource.Read(newData) as ModifiedDifficultyWeaponTableData; | ||
|
||
// return the new data if there was no previous data | ||
if (oldTable == null) | ||
return newTable; | ||
|
||
// otherwise merge the two together | ||
foreach (var value in newTable.Values) | ||
{ | ||
// each change is stored as a row/column/value set, when merged with another mod, each individual | ||
// row/column change is merged with the previous changes | ||
oldTable.ModifyValue(value.Row, value.Column, value.Value); | ||
} | ||
|
||
return oldTable; | ||
} | ||
|
||
// 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) | ||
{ | ||
// obtain the modified data that has been loaded and merged from the mods | ||
ModifiedDifficultyWeaponTableData modifiedData = data as ModifiedDifficultyWeaponTableData; | ||
|
||
// load the original game ebx asset | ||
EbxAsset asset = am.GetEbx(am.GetEbxEntry(origEntry.Name)); | ||
dynamic rootTable = asset.RootObject; | ||
|
||
// replace data from the game ebx data with the modified data | ||
foreach (var value in modifiedData.Values) | ||
{ | ||
rootTable.WeaponTable[value.Row].Values[value.Column].Value = value.Value; | ||
} | ||
|
||
// write out the new ebx data | ||
using (EbxBaseWriter writer = EbxBaseWriter.CreateWriter(new MemoryStream())) | ||
{ | ||
writer.WriteAsset(asset); | ||
origEntry.OriginalSize = writer.Length; | ||
outData = Utils.CompressFile(writer.ToByteArray()); | ||
} | ||
|
||
// update relevant asset entry values | ||
origEntry.Size = outData.Length; | ||
origEntry.Sha1 = Utils.GenerateSha1(outData); | ||
} | ||
|
||
#endregion | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
Plugins/DifficultyWeaponTableDataPlugin/Properties/AssemblyInfo.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,32 @@ | ||
using DifficultyWeaponTableDataPlugin.Definitions; | ||
using DifficultyWeaponTableDataPlugin.Handlers; | ||
using Frosty.Core.Attributes; | ||
using System.Reflection; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using System.Windows; | ||
|
||
// Setting ComVisible to false makes the types in this assembly not visible | ||
// to COM components. If you need to access a type in this assembly from | ||
// COM, set the ComVisible attribute to true on that type. | ||
[assembly: ComVisible(false)] | ||
|
||
[assembly: ThemeInfo( | ||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located | ||
//(used if a resource is not found in the page, | ||
// or application resource dictionaries) | ||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located | ||
//(used if a resource is not found in the page, | ||
// app, or any theme specific resource dictionaries) | ||
)] | ||
|
||
// The following GUID is for the ID of the typelib if this project is exposed to COM | ||
[assembly: Guid("4b612468-9b6a-4304-88a5-055c3575eb3d")] | ||
|
||
[assembly: PluginDisplayName("DifficultyWeaponTableDataPlugin")] | ||
[assembly: PluginAuthor("GalaxyMan2015")] | ||
[assembly: PluginVersion("1.0.0.0")] | ||
|
||
[assembly: RegisterAssetDefinition("DifficultyWeaponTableData", typeof(DifficultyWeaponTableDataAssetDefinition))] | ||
[assembly: RegisterCustomHandler(CustomHandlerType.Ebx, typeof(DifficultyWeaponTableActionHandler), ebxType: "DifficultyWeaponTableData")] | ||
|
Oops, something went wrong.