1-
2- using System . Linq ;
3- using System . Reflection . Metadata ;
4- using System . Reflection . Metadata . Ecma335 ;
5- using System . Text ;
6- using System . Windows . Forms ;
7- using System . Xml . Linq ;
8- using static System . Windows . Forms . VisualStyles . VisualStyleElement . TextBox ;
1+ using System . Xml . Linq ;
92
103namespace PathOfBuildingMerge
114{
@@ -24,26 +17,35 @@ internal struct SetType
2417 static SetType Tree = new ( ) { Node = "Tree" , Element = "Spec" , Active = "activeSpec" } ;
2518
2619
27- internal static void Merge ( string mainPob , string pobToAdd , string newLoadoutName , string pobResult )
20+ internal static void Merge ( string mainPob , string pobToAdd , string newLoadoutName , string pobResult , bool onlyAddUsedItems = true , bool reuseExistingItems = true )
2821 {
2922 var baseFileName = Path . GetFileName ( mainPob ) ;
3023 var baseDoc = XDocument . Load ( mainPob ) ;
3124
3225 var baseTreeNode = GetRootNode ( baseDoc , baseFileName , Tree . Node ) ;
3326 var baseSkillsNode = GetRootNode ( baseDoc , baseFileName , Skills . Node ) ;
34- var baseConfigNode = GetRootNode ( baseDoc , baseFileName , Config . Node ) ;
3527 var baseItemsNode = GetRootNode ( baseDoc , baseFileName , Items . Node ) ;
28+ var baseConfigNode = GetRootNode ( baseDoc , baseFileName , Config . Node ) ;
3629
3730 RemoveTreeSpec ( baseTreeNode , newLoadoutName ) ;
3831 RemoveSkillSet ( baseSkillsNode , newLoadoutName ) ;
39- RemoveConfigSet ( baseConfigNode , newLoadoutName ) ;
4032 RemoveItemSet ( baseItemsNode , newLoadoutName ) ;
33+ RemoveConfigSet ( baseConfigNode , newLoadoutName ) ;
4134
4235 var addFileName = Path . GetFileName ( pobToAdd ) ;
4336 var docToAdd = XDocument . Load ( pobToAdd ) ;
4437 var addItemsNode = GetRootNode ( docToAdd , addFileName , Items . Node ) ;
4538 var itemsToAdd = addItemsNode . Elements ( "Item" ) ;
4639
40+ List < int > usedItemIds = [ ] ;
41+ if ( onlyAddUsedItems )
42+ {
43+ CollectUsedItemIds ( usedItemIds , GetActiveTreeSpec ( docToAdd , addFileName ) ) ;
44+ CollectUsedItemIds ( usedItemIds , GetActiveSkillSet ( docToAdd , addFileName ) ) ;
45+ CollectUsedItemIds ( usedItemIds , GetActiveItemSet ( docToAdd , addFileName ) ) ;
46+ CollectUsedItemIds ( usedItemIds , GetActiveConfigSet ( docToAdd , addFileName ) ) ;
47+ }
48+
4749 var addedItemsIdDictionary = new Dictionary < int , int > ( ) ;
4850
4951 var normalizedBaseItems = baseItemsNode . Elements ( "Item" ) . Select ( x => XmlUtils . NormalizeElement ( x , false ) ) ;
@@ -63,16 +65,22 @@ internal static void Merge(string mainPob, string pobToAdd, string newLoadoutNam
6365 var id = ( int ? ) item . Attribute ( "id" ) ?? 0 ;
6466 if ( id <= 0 ) continue ;
6567
66- // check if item is a duplicate and if so continue
67- //
68+ if ( onlyAddUsedItems && ! usedItemIds . Contains ( id ) )
69+ continue ;
70+
6871 var normalizedItem = XmlUtils . NormalizeElement ( item , false ) ;
6972 normalizedItem . SetAttributeValue ( "id" , null ) ;
7073
71- var foundItem = normalizedItemsDictionary . FirstOrDefault ( x => ( XNode . DeepEquals ( x . Value , normalizedItem ) ) ) ;
72- if ( foundItem . Value != null )
74+ // check if item is a duplicate and if so continue
75+ //
76+ if ( reuseExistingItems )
7377 {
74- addedItemsIdDictionary [ id ] = foundItem . Key ;
75- continue ;
78+ var foundItem = normalizedItemsDictionary . FirstOrDefault ( x => ( XNode . DeepEquals ( x . Value , normalizedItem ) ) ) ;
79+ if ( foundItem . Value != null )
80+ {
81+ addedItemsIdDictionary [ id ] = foundItem . Key ;
82+ continue ;
83+ }
7684 }
7785
7886 // renumber ids of added items so they don't clash with existing items.
@@ -91,14 +99,25 @@ internal static void Merge(string mainPob, string pobToAdd, string newLoadoutNam
9199 baseItemsNode . Add ( item ) ;
92100 }
93101
94- AddConfigSet ( docToAdd , addFileName , baseConfigNode , newLoadoutName , addedItemsIdDictionary ) ;
102+ AddTreeSpec ( docToAdd , addFileName , baseTreeNode , newLoadoutName , addedItemsIdDictionary ) ;
95103 AddSkillSet ( docToAdd , addFileName , baseSkillsNode , newLoadoutName , addedItemsIdDictionary ) ;
96104 AddItemSet ( docToAdd , addFileName , baseItemsNode , newLoadoutName , addedItemsIdDictionary ) ;
97- AddTreeSpec ( docToAdd , addFileName , baseTreeNode , newLoadoutName , addedItemsIdDictionary ) ;
105+ AddConfigSet ( docToAdd , addFileName , baseConfigNode , newLoadoutName , addedItemsIdDictionary ) ;
98106
99107 XmlUtils . SaveXDocumentWithoutBom ( baseDoc , pobResult ) ;
100108 }
101109
110+ private static void CollectUsedItemIds ( List < int > usedItemIds , XElement node )
111+ {
112+ foreach ( var child in node . Descendants ( ) )
113+ {
114+ if ( ! child . HasAttributes ) continue ;
115+ var itemId = ( int ? ) child . Attribute ( "itemId" ) ?? 0 ;
116+ if ( itemId > 0 )
117+ usedItemIds . Add ( itemId ) ;
118+ }
119+ }
120+
102121 private static void UpdateItemIds ( XElement node , Dictionary < int , int > idDictionary )
103122 {
104123 foreach ( var child in node . Descendants ( ) )
@@ -111,29 +130,50 @@ private static void UpdateItemIds(XElement node, Dictionary<int, int> idDictiona
111130 }
112131
113132 private static void AddTreeSpec ( XDocument doc , string fileName , XElement destinationNode , string newLoadoutName , Dictionary < int , int > idDictionary )
133+ {
134+ XElement found = GetActiveTreeSpec ( doc , fileName ) ;
135+ found . SetAttributeValue ( "title" , newLoadoutName ) ;
136+ UpdateItemIds ( found , idDictionary ) ;
137+ destinationNode . Add ( found ) ;
138+ }
139+
140+ private static XElement GetActiveTreeSpec ( XDocument doc , string fileName )
114141 {
115142 var treeNode = GetRootNode ( doc , fileName , Tree . Node ) ;
116- var activeSpec = ( int ? ) treeNode . Attribute ( Tree . Active ) ?? 1 ;
143+ var activeSpec = ( int ? ) treeNode . Attribute ( Tree . Active ) ?? 1 ;
117144
118145 var specs = treeNode . Elements ( Tree . Element ) ;
119146
120147 if ( activeSpec > 1 && specs . Count ( ) >= activeSpec ) specs = specs . Skip ( activeSpec - 1 ) ;
121- var found = specs . FirstOrDefault ( ) ?? throw new Exception ( $ "No tree spec found in '{ fileName } ' to add") ;
122- found . SetAttributeValue ( "title" , newLoadoutName ) ;
123- UpdateItemIds ( found , idDictionary ) ;
124- destinationNode . Add ( found ) ;
148+ var found = specs . FirstOrDefault ( ) ?? throw new Exception ( $ "No tree spec found in '{ fileName } ' to add") ;
149+ return found ;
125150 }
126151
127- private static void AddItemSet ( XDocument doc , string fileName , XElement destinationNode , string newLoadoutName , Dictionary < int , int > idDictionary )
152+ private static XElement GetActiveSkillSet ( XDocument doc , string fileName )
128153 {
129- AddNodeWithUniqueId ( doc , fileName , destinationNode , newLoadoutName , idDictionary , Items ) ;
154+ return GetChildByActiveIndex ( doc , fileName , Skills ) ;
155+ }
156+
157+ private static XElement GetActiveItemSet ( XDocument doc , string fileName )
158+ {
159+ return GetChildByActiveIndex ( doc , fileName , Items ) ;
160+ }
161+
162+ private static XElement GetActiveConfigSet ( XDocument doc , string fileName )
163+ {
164+ return GetChildByActiveIndex ( doc , fileName , Config ) ;
130165 }
131166
132167 private static void AddSkillSet ( XDocument doc , string fileName , XElement destinationNode , string newLoadoutName , Dictionary < int , int > idDictionary )
133168 {
134169 AddNodeWithUniqueId ( doc , fileName , destinationNode , newLoadoutName , idDictionary , Skills ) ;
135170 }
136171
172+ private static void AddItemSet ( XDocument doc , string fileName , XElement destinationNode , string newLoadoutName , Dictionary < int , int > idDictionary )
173+ {
174+ AddNodeWithUniqueId ( doc , fileName , destinationNode , newLoadoutName , idDictionary , Items ) ;
175+ }
176+
137177 private static void AddConfigSet ( XDocument doc , string fileName , XElement destinationNode , string newLoadoutName , Dictionary < int , int > idDictionary )
138178 {
139179 AddNodeWithUniqueId ( doc , fileName , destinationNode , newLoadoutName , idDictionary , Config ) ;
@@ -142,10 +182,10 @@ private static void AddConfigSet(XDocument doc, string fileName, XElement destin
142182 private static void AddNodeWithUniqueId ( XDocument doc , string fileName , XElement destinationNode , string newLoadoutName , Dictionary < int , int > idDictionary , SetType setType )
143183 {
144184 var result = GetChildByActiveIndex ( doc , fileName , setType ) ;
185+ UpdateItemIds ( result , idDictionary ) ;
186+ result . SetAttributeValue ( "title" , newLoadoutName ) ;
145187 var newId = GetFirstAvailableId ( destinationNode , setType . Element ) ;
146188 result . SetAttributeValue ( "id" , newId ) ;
147- result . SetAttributeValue ( "title" , newLoadoutName ) ;
148- UpdateItemIds ( result , idDictionary ) ;
149189 destinationNode . Add ( result ) ;
150190 }
151191
0 commit comments