source: AE/installer2/src/net/oni2/aeinstaller/backend/mods/Mod.java@ 634

Last change on this file since 634 was 631, checked in by alloc, 12 years ago

AEI2 0.90:

  • Added blank persist.dat for UnlockLevel to always work
  • Made local paths use the sanitized mod-name
  • Added mod-state column to mod table
File size: 10.5 KB
Line 
1package net.oni2.aeinstaller.backend.mods;
2
3import java.io.BufferedReader;
4import java.io.File;
5import java.io.FileInputStream;
6import java.io.FileNotFoundException;
7import java.io.FilenameFilter;
8import java.io.IOException;
9import java.io.InputStreamReader;
10import java.util.HashSet;
11
12import net.oni2.aeinstaller.backend.Paths;
13import net.oni2.aeinstaller.backend.Settings;
14import net.oni2.aeinstaller.backend.Settings.Platform;
15import net.oni2.aeinstaller.backend.depot.DepotConfig;
16import net.oni2.aeinstaller.backend.depot.DepotManager;
17import net.oni2.aeinstaller.backend.depot.model.NodeMod;
18import net.oni2.aeinstaller.backend.depot.model.TaxonomyTerm;
19
20/**
21 * @author Christian Illy
22 */
23public class Mod implements Comparable<Mod> {
24 private String name = "";
25 private int packageNumber = 0;
26
27 private HashSet<Type> types = new HashSet<Type>();
28 private boolean tool = false;
29 private ECompatiblePlatform platform = null;
30 private String version = "";
31 private String creator = "";
32 private EBSLInstallType bslInstallType = EBSLInstallType.NORMAL;
33 private String description = "";
34 private double aeVersion = 0;
35 private int zipSize = 0;
36 private NodeMod node = null;
37 private net.oni2.aeinstaller.backend.depot.model.File file = null;
38
39 private File exeFile = null;
40 private File iconFile = null;
41 private String workingDir = "Base";
42
43 private HashSet<Integer> incompatibilities = new HashSet<Integer>();
44 private HashSet<Integer> dependencies = new HashSet<Integer>();
45 private HashSet<Integer> unlockLevel = new HashSet<Integer>();
46
47 private long localTimestamp = 0;
48
49 /**
50 * Create a new Mod entry from a given Mod-Node
51 *
52 * @param nm
53 * Mod-Node
54 */
55 public Mod(NodeMod nm) {
56 node = nm;
57 name = nm.getTitle();
58 packageNumber = nm.getPackageNumber();
59 platform = nm.getPlatform();
60 tool = nm.isTool();
61 for (TaxonomyTerm tt : nm.getTypes()) {
62 Type t = ModManager.getInstance().getTypeByName(tt.getName());
63 types.add(t);
64 if (!tool && !isMandatoryMod() && isValidOnPlatform())
65 t.addEntry(this);
66 }
67 version = nm.getVersion();
68 creator = nm.getCreator();
69 if (nm.getBody() != null)
70 description = nm.getBody().getSafe_value();
71 file = DepotManager.getInstance().getFile(
72 nm.getUploads().firstElement().getFid());
73 zipSize = file.getFilesize();
74
75 if (isLocalAvailable())
76 updateLocalData();
77 }
78
79 /**
80 * Update information for local package existence
81 */
82 public void updateLocalData() {
83 File config = new File(getLocalPath(), "Mod_Info.cfg");
84 File aeicfg = new File(getLocalPath(), "aei.cfg");
85 File plain = new File(getLocalPath(), "plain");
86 if (config.exists()) {
87 try {
88 FileInputStream fstream = new FileInputStream(config);
89 InputStreamReader isr = new InputStreamReader(fstream);
90 BufferedReader br = new BufferedReader(isr);
91 String strLine;
92 while ((strLine = br.readLine()) != null) {
93 if (strLine.indexOf("->") < 1)
94 continue;
95 if (strLine.indexOf("//") >= 0)
96 strLine = strLine.substring(0, strLine.indexOf("//"));
97 String[] split = strLine.split("->", 2);
98 String sName = split[0].trim();
99 String sVal = split[1].trim();
100 if (sName.equalsIgnoreCase("AEInstallVersion")) {
101 aeVersion = Double.parseDouble(sVal);
102 } else if (sName.equalsIgnoreCase("NameOfMod")) {
103 if (node == null)
104 name = sVal;
105 } else if (sName.equalsIgnoreCase("Creator")) {
106 if (node == null)
107 creator = sVal;
108 } else if (sName.equalsIgnoreCase("HasBsl")) {
109 if (sVal.equalsIgnoreCase("addon"))
110 bslInstallType = EBSLInstallType.ADDON;
111 } else if (sName.equalsIgnoreCase("ModVersion")) {
112 if (node == null)
113 version = sVal;
114 } else if (sName.equalsIgnoreCase("Readme")) {
115 if (node == null)
116 description = sVal.replaceAll("\\\\n", "<br>");
117 } else if (sName.equalsIgnoreCase("DependsOn")) {
118 String[] depsS = sVal.split(",");
119 for (String s : depsS) {
120 try {
121 int dep = Integer.parseInt(s);
122 dependencies.add(dep);
123 } catch (NumberFormatException e) {
124 System.err
125 .format("Mod %05d does contain a non-number dependency: '%s'\n",
126 packageNumber, s);
127 }
128 }
129 } else if (sName.equalsIgnoreCase("IncompatibleWith")) {
130 String[] confS = sVal.split(",");
131 for (String s : confS) {
132 try {
133 int conf = Integer.parseInt(s);
134 incompatibilities.add(conf);
135 } catch (NumberFormatException e) {
136 System.err
137 .format("Mod %05d does contain a non-number incompatibility: '%s'\n",
138 packageNumber, s);
139 }
140 }
141 } else if (sName.equalsIgnoreCase("UnlockLevel")) {
142 String[] levelsS = sVal.split(",");
143 for (String s : levelsS) {
144 try {
145 int level = Integer.parseInt(s);
146 unlockLevel.add(level);
147 } catch (NumberFormatException e) {
148 System.err
149 .format("Mod %05d does contain a non-number UnlockLevel value: '%s'\n",
150 packageNumber, s);
151 }
152 }
153 } else if (sName.equalsIgnoreCase("ExeName")) {
154 exeFile = new File(Paths.getEditionBasePath(), sVal);
155 } else if (sName.equalsIgnoreCase("WorkingDir")) {
156 workingDir = sVal;
157 } else if (sName.equalsIgnoreCase("IconName")) {
158 iconFile = new File(Paths.getEditionBasePath(), sVal);
159 }
160 }
161 isr.close();
162 } catch (FileNotFoundException e) {
163 } catch (IOException e) {
164 e.printStackTrace();
165 }
166 } else {
167 System.err.println("No config found for mod folder: "
168 + getLocalPath().getPath());
169 }
170 if (aeicfg.exists()) {
171 try {
172 FileInputStream fstream = new FileInputStream(aeicfg);
173 InputStreamReader isr = new InputStreamReader(fstream);
174 BufferedReader br = new BufferedReader(isr);
175 String strLine;
176 while ((strLine = br.readLine()) != null) {
177 if (strLine.indexOf("->") < 1)
178 continue;
179 if (strLine.indexOf("//") >= 0)
180 strLine = strLine.substring(0, strLine.indexOf("//"));
181 String[] split = strLine.split("->", 2);
182 String sName = split[0].trim();
183 String sVal = split[1].trim();
184 if (sName.equalsIgnoreCase("Timestamp")) {
185 localTimestamp = Long.parseLong(sVal);
186 }
187 }
188 isr.close();
189 } catch (FileNotFoundException e) {
190 } catch (IOException e) {
191 e.printStackTrace();
192 }
193 }
194 if (node == null)
195 tool = plain.exists();
196 }
197
198 /**
199 * Create a new Mod entry from the given local mod folder
200 *
201 * @param folder
202 * Mod folder with Mod_Info.cfg
203 */
204 public Mod(File folder) {
205 packageNumber = Integer.parseInt(folder.getName().substring(0, 5));
206 updateLocalData();
207
208 platform = ECompatiblePlatform.BOTH;
209 }
210
211 /**
212 * @return has separate paths for win/mac/common or not
213 */
214 public boolean hasSeparatePlatformDirs() {
215 return aeVersion >= 2;
216 }
217
218 private String getSanitizedPathName() {
219 return name.replaceAll("[^a-zA-Z0-9_.-]", "_");
220 }
221
222 /**
223 * @return Path to local mod folder
224 */
225 public File getLocalPath() {
226 final String folderStart = String.format("%05d", packageNumber);
227
228 if (Paths.getModsPath().exists()) {
229 for (File f : Paths.getModsPath().listFiles(new FilenameFilter() {
230 @Override
231 public boolean accept(File d, String fn) {
232 return fn.startsWith(folderStart);
233 }
234 })) {
235 return f;
236 }
237 }
238
239 return new File(Paths.getModsPath(), folderStart
240 + getSanitizedPathName());
241 }
242
243 /**
244 * @return Is there a newer version on the depot?
245 */
246 public boolean isNewerAvailable() {
247 if (file != null)
248 return file.getTimestamp() > localTimestamp;
249 else
250 return false;
251 }
252
253 /**
254 * @return Mod exists within mods folder
255 */
256 public boolean isLocalAvailable() {
257 return getLocalPath().exists();
258 }
259
260 /**
261 * @return Is mod installed?
262 */
263 public boolean isInstalled() {
264 return ModManager.getInstance().isModInstalled(this);
265 }
266
267 /**
268 * @return Name of mod
269 */
270 public String getName() {
271 return name;
272 }
273
274 /**
275 * @return the package number
276 */
277 public int getPackageNumber() {
278 return packageNumber;
279 }
280
281 /**
282 * @return the package number as 5 digit string
283 */
284 public String getPackageNumberString() {
285 return String.format("%05d", packageNumber);
286 }
287
288 /**
289 * @return Types of mod
290 */
291 public HashSet<Type> getTypes() {
292 return types;
293 }
294
295 /**
296 * @return Is this mod actually a tool?
297 */
298 public boolean isTool() {
299 return tool;
300 }
301
302 /**
303 * @return Compatible platforms
304 */
305 public ECompatiblePlatform getPlatform() {
306 return platform;
307 }
308
309 /**
310 * @return Version of mod
311 */
312 public String getVersion() {
313 return version;
314 }
315
316 /**
317 * @return Creator of mod
318 */
319 public String getCreator() {
320 return creator;
321 }
322
323 /**
324 * @return Installation type of BSL files
325 */
326 public EBSLInstallType getBSLInstallType() {
327 return bslInstallType;
328 }
329
330 /**
331 * @return Description of mod
332 */
333 public String getDescription() {
334 return description;
335 }
336
337 /**
338 * @return Size of Zip file on Depot
339 */
340 public int getZipSize() {
341 return zipSize;
342 }
343
344 /**
345 * @return Is a mod that is always installed?
346 */
347 public boolean isMandatoryMod() {
348 return packageNumber < DepotConfig.getMandatoryLimit();
349 }
350
351 /**
352 * @return Get the depot file entry
353 */
354 public net.oni2.aeinstaller.backend.depot.model.File getFile() {
355 return file;
356 }
357
358 @Override
359 public String toString() {
360 return name;
361 }
362
363 /**
364 * @return the incompabitilities
365 */
366 public HashSet<Integer> getIncompabitilities() {
367 return incompatibilities;
368 }
369
370 /**
371 * @return the dependencies
372 */
373 public HashSet<Integer> getDependencies() {
374 return dependencies;
375 }
376
377 /**
378 * @return the levels this mod will unlock
379 */
380 public HashSet<Integer> getUnlockLevels() {
381 return unlockLevel;
382 }
383
384 /**
385 * @return Executable name of this tool
386 */
387 public File getExeFile() {
388 return exeFile;
389 }
390
391 /**
392 * @return Icon file of this tool
393 */
394 public File getIconFile() {
395 return iconFile;
396 }
397
398 /**
399 * @return Working directory of this tool
400 */
401 public File getWorkingDir() {
402 if (workingDir.equalsIgnoreCase("Exe")) {
403 if (exeFile != null)
404 return exeFile.getParentFile();
405 else
406 return Paths.getEditionGDF();
407 } else if (workingDir.equalsIgnoreCase("GDF"))
408 return Paths.getEditionGDF();
409 else
410 return Paths.getEditionBasePath();
411 }
412
413 /**
414 * @return Is this mod valid on the running platform?
415 */
416 public boolean isValidOnPlatform() {
417 switch (platform) {
418 case BOTH:
419 return true;
420 case MACOS:
421 return (Settings.getPlatform() == Platform.MACOS);
422 case WIN:
423 return (Settings.getPlatform() == Platform.WIN)
424 || (Settings.getPlatform() == Platform.LINUX);
425 }
426 return false;
427 }
428
429 @Override
430 public int compareTo(Mod o) {
431 return getPackageNumber() - o.getPackageNumber();
432 }
433}
Note: See TracBrowser for help on using the repository browser.