Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_PrefabTemplateClassCheckPlugin.c
Go to the documentation of this file.
1#ifdef WORKBENCH
3 name: "Prefab Template Class Check",
4 description: "PrefabsLibrary templates must not have a different class than their Prefabs counterpart; this tool verifies this.",
5 wbModules: { "ResourceManager" },
6 category: SCR_PluginCategory.RESOURCEMANAGER_PREFABS,
7 awesomeFontCode: 0xF560)]
8class SCR_PrefabTemplateClassCheckPlugin : WorkbenchPlugin
9{
10 [Attribute(defvalue: "0", desc: "Tries and replaces wrong classes (difference between Template declared class and parent Prefab class)")]
11 protected bool m_bFixTemplateClasses;
12
13 protected static const int MIN_DESCRIPTION_WIDTH = 110; // chars for Prefab path alignment
14
15 //------------------------------------------------------------------------------------------------
16 override void Run()
17 {
18 FindAndPrintDiscrepancies();
19 }
20
21 //------------------------------------------------------------------------------------------------
23 protected void FindAndPrintDiscrepancies()
24 {
25 array<string> addonGUIDs = {};
26 GameProject.GetLoadedAddons(addonGUIDs);
27
28 array<ResourceName> resourceNames = {};
29
30 foreach (string addonGUID : addonGUIDs)
31 {
32 string addonID = GameProject.GetAddonID(addonGUID);
33 if (addonID == "core")
34 continue;
35
36 Print("Looking into " + addonID + "/PrefabLibrary", LogLevel.NORMAL);
37 resourceNames.InsertAll(SCR_WorkbenchHelper.SearchWorkbenchResources({ "et" }, null, SCR_AddonTool.ToFileSystem(addonID) + "PrefabLibrary"));
38 }
39
40 int count = resourceNames.Count();
41 Print("Processing " + count + " Templates class check", LogLevel.NORMAL);
42
43 Resource resource;
44 BaseContainer baseContainer;
45 BaseContainer baseContainerAncestor;
46
48 array<ResourceName> invalidTemplates = {}; // templates that cannot be loaded with Resource.Load (broken, etc)
49 array<ResourceName> orphanTemplates = {}; // templates that are not from a Prefab (should NEVER happen?!)
50 array<ref Tuple3<ResourceName, string, string>> classMismatches = {}; // class = Template/Prefab .et class names do not match
51 array<ref Tuple3<ResourceName, string, string>> selfMismatches = {}; // self = Prefab.GetClassName() returns a different class name from file
52
53 Debug.BeginTimeMeasure();
54
55 foreach (ResourceName resourceName : resourceNames)
56 {
57 resource = Resource.Load(resourceName);
58 if (!resource.IsValid())
59 {
60 invalidTemplates.Insert(resourceName);
61 continue;
62 }
63
64 baseContainer = resource.GetResource().ToBaseContainer();
65 if (!baseContainer)
66 {
67 invalidTemplates.Insert(resourceName);
68 continue;
69 }
70
71 baseContainerAncestor = baseContainer.GetAncestor();
72 if (!baseContainerAncestor)
73 {
74 orphanTemplates.Insert(resourceName);
75 continue;
76 }
77
78 string childClassName = classnameCache.Get(resourceName);
79 if (!childClassName) // not cached? let's find it
80 {
81 childClassName = GetClassNameFromPrefabFile(resourceName);
82 if (!childClassName) // could not get it
83 continue; // GetClassNameFromPrefabFile already warns in case of failure
84
85 classnameCache.Insert(resourceName, childClassName);
86 }
87
88 ResourceName ancestorResourceName = baseContainerAncestor.GetResourceName();
89 string ancestorClassName = classnameCache.Get(ancestorResourceName);
90 if (!ancestorClassName) // not cached? let's find it
91 {
92 ancestorClassName = GetClassNameFromPrefabFile(ancestorResourceName);
93 if (!ancestorResourceName) // could not get it
94 continue; // GetClassNameFromPrefabFile already warns in case of failure
95
96 classnameCache.Insert(ancestorResourceName, ancestorClassName);
97 }
98
99 if (childClassName != ancestorClassName)
100 {
101 classMismatches.Insert(new Tuple3<ResourceName, string, string>(resourceName, childClassName, ancestorClassName));
102 continue;
103 }
104 }
105
106 Debug.EndTimeMeasure("Processed " + count + " Templates");
107
108 foreach (ResourceName resourceName : invalidTemplates)
109 {
110 Print(SCR_StringHelper.PadRight("Template could not be loaded: ", MIN_DESCRIPTION_WIDTH) + resourceName, LogLevel.ERROR);
111 }
112
113 foreach (ResourceName resourceName : invalidTemplates)
114 {
115 Print(SCR_StringHelper.PadRight("Template is not a child: ", MIN_DESCRIPTION_WIDTH) + resourceName, LogLevel.ERROR);
116 }
117
118 int fixedClassMismatches;
119 foreach (Tuple3<ResourceName, string, string> tuple : classMismatches)
120 {
121 Print(SCR_StringHelper.PadRight(string.Format("Template class (%1) differs from ancestor Prefab class (%2): ", tuple.param2, tuple.param3), MIN_DESCRIPTION_WIDTH) + tuple.param1, LogLevel.WARNING);
122 if (m_bFixTemplateClasses)
123 {
124 if (ChangeTemplateClass(tuple.param1, tuple.param3))
125 {
126 Print("Successfully changed class " + tuple.param2 + " to " + tuple.param3, LogLevel.NORMAL);
127 fixedClassMismatches++;
128 }
129 else
130 {
131 Print("Could not change class " + tuple.param2 + " to " + tuple.param3, LogLevel.WARNING);
132 }
133 }
134 }
135
136 Print("Found " + invalidTemplates.Count() + " invalid, " +
137 orphanTemplates.Count() + " orphans, " +
138 classMismatches.Count() + " class mismatches (" + fixedClassMismatches + " fixed), " +
139 "over " + count + " Templates", LogLevel.NORMAL);
140 }
141
142 //------------------------------------------------------------------------------------------------
147 protected string GetClassNameFromPrefabFile(ResourceName resourceName)
148 {
149 if (!resourceName || !resourceName.EndsWith(".et"))
150 {
151 Print("Cannot read class name from a file other than Prefab: " + resourceName, LogLevel.WARNING);
152 return string.Empty;
153 }
154
155 string absoluteFilePath;
156 if (!Workbench.GetAbsolutePath(resourceName.GetPath(), absoluteFilePath, true))
157 {
158 Print("Cannot find Prefab file to read class name: " + resourceName, LogLevel.ERROR);
159 return string.Empty;
160 }
161
162 FileHandle fileHandle = FileIO.OpenFile(absoluteFilePath, FileMode.READ);
163 if (!fileHandle)
164 {
165 Print("Cannot open Prefab file to read class name: " + resourceName, LogLevel.ERROR);
166 return string.Empty;
167 }
168
169 string firstLine;
170 fileHandle.ReadLine(firstLine);
171 fileHandle.Close();
172
173 int spaceIndex = firstLine.IndexOf(" "); // Thomas Pesquet's finger
174 if (spaceIndex < 1) // at least... one character?
175 {
176 Print("Cannot read class from Prefab file: " + resourceName, LogLevel.ERROR);
177 return string.Empty;
178 }
179
180 return firstLine.Substring(0, spaceIndex);
181 }
182
183 //------------------------------------------------------------------------------------------------
189 protected bool ChangeTemplateClass(ResourceName resourceName, string newClassName)
190 {
191 if (SCR_StringHelper.IsEmptyOrWhiteSpace(newClassName))
192 {
193 Print("No class provided to write in Prefab: " + resourceName, LogLevel.WARNING);
194 return string.Empty;
195 }
196
197 newClassName.TrimInPlace(); // juuust in case.
198
199 if (!resourceName || !resourceName.EndsWith(".et"))
200 {
201 Print("Cannot write class name in a file other than Prefab: " + resourceName, LogLevel.WARNING);
202 return string.Empty;
203 }
204
205 string absoluteFilePath;
206 if (!Workbench.GetAbsolutePath(resourceName.GetPath(), absoluteFilePath, true))
207 {
208 Print("Cannot find Prefab file to write class name: " + resourceName, LogLevel.ERROR);
209 return string.Empty;
210 }
211
212 FileHandle fileHandle = FileIO.OpenFile(absoluteFilePath, FileMode.READ);
213 if (!fileHandle)
214 {
215 Print("Cannot open Prefab file to write class name: " + resourceName, LogLevel.ERROR);
216 return string.Empty;
217 }
218
219 string lineContent;
220 array<string> lines = {};
221 while (!fileHandle.IsEOF())
222 {
223 fileHandle.ReadLine(lineContent);
224 lines.Insert(lineContent);
225 }
226
227 fileHandle.Close();
228
229 int spaceIndex = lines[0].IndexOf(" "); // Thomas Pesquet's finger
230 if (spaceIndex < 1) // at least... one character?
231 {
232 Print("Cannot find class from Prefab file: " + resourceName, LogLevel.ERROR);
233 return string.Empty;
234 }
235
236 lines[0] = newClassName + lines[0].Substring(spaceIndex, lines[0].Length() - spaceIndex);
237
238 fileHandle = FileIO.OpenFile(absoluteFilePath, FileMode.WRITE);
239 if (!fileHandle)
240 {
241 Print("Cannot write new class in Prefab file: " + resourceName, LogLevel.WARNING);
242 return false;
243 }
244
245 foreach (int lineNumber, string line : lines)
246 {
247 fileHandle.WriteLine(line);
248 }
249
250 fileHandle.Close();
251
252 return true;
253 }
254
255 //------------------------------------------------------------------------------------------------
256 override void Configure()
257 {
258 Workbench.ScriptDialog("bweh", "Settings", this);
259 }
260
261 //------------------------------------------------------------------------------------------------
262 [ButtonAttribute("OK", true)]
263 protected bool ButtonOK()
264 {
265 return true;
266 }
267}
268#endif // WORKBENCH
GenerateFlowMaps WorkbenchPlugin WorkbenchPluginAttribute("Regenerate river flow-maps", "Generate and save/overwrite river flow-maps", "", "", {"WorldEditor"}, "", 0xf773)
Definition FlowmapTool.c:59
ResourceName resourceName
Definition SCR_AIGroup.c:66
override void Run()
bool ButtonOK()
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
override void Configure()
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
Definition Debug.c:13
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
static string PadRight(string input, int length, string padding=SPACE)
static bool IsEmptyOrWhiteSpace(string input)
static array< ResourceName > SearchWorkbenchResources(array< string > fileExtensions=null, array< string > searchStrArray=null, string rootPath="", bool recursive=true)
Definition Types.c:486
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
FileMode
Mode for opening file. See FileSystem::Open.
Definition FileMode.c:14
void Tuple3(T1 p1, T2 p2, T3 p3)
Definition tuple.c:95