-
Notifications
You must be signed in to change notification settings - Fork 105
Expand file tree
/
Copy pathFileHandler.java
More file actions
232 lines (199 loc) · 7.13 KB
/
Copy pathFileHandler.java
File metadata and controls
232 lines (199 loc) · 7.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
* SPDX-FileCopyrightText: 2011-2024 Minicraft+ contributors
* SPDX-License-Identifier: GPL-3.0-only
*/
package minicraft.core.io;
import minicraft.core.CrashHandler;
import minicraft.core.Game;
import minicraft.saveload.Save;
import minicraft.util.Logging;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import java.util.stream.Stream;
public class FileHandler extends Game {
private FileHandler() {
}
public static final int REPLACE_EXISTING = 0;
public static final int RENAME_COPY = 1;
public static final int SKIP = 2;
public static final String OS;
private static final String localGameDir;
static final String systemGameDir;
static {
OS = System.getProperty("os.name").toLowerCase();
String local = "playminicraft/mods/Minicraft_Plus";
if (OS.contains("windows")) // windows
systemGameDir = System.getenv("APPDATA");
else {
systemGameDir = System.getProperty("user.home");
if (!OS.contains("mac"))
local = "." + local; // linux
}
localGameDir = "/" + local;
}
/**
* Determines the path the game will use to store worlds, settings, resource packs, etc.
* If saveDir is not null, use it as the game directory. Otherwise use the default path.
* <p>
* If the default path is used, check if old default path exists and if so move it to the new path.
* @param saveDir Value from --savedir argument. Null if it was not set.
*/
public static void determineGameDir(@Nullable String saveDir) {
if (saveDir != null) {
gameDir = saveDir;
Logging.GAMEHANDLER.debug("Determined gameDir: " + gameDir);
File gameDirFile = new File(gameDir);
gameDirFile.mkdirs();
} else {
saveDir = FileHandler.getSystemGameDir();
gameDir = saveDir + localGameDir;
Logging.GAMEHANDLER.debug("Determined gameDir: " + gameDir);
File testFile = new File(gameDir);
testFile.mkdirs();
File oldFolder = new File(saveDir + "/.playminicraft/mods/Minicraft Plus");
if (oldFolder.exists()) {
try {
copyFolderContents(oldFolder.toPath(), testFile.toPath(), RENAME_COPY, true);
} catch (IOException e) {
CrashHandler.errorHandle(e);
}
}
if (OS.contains("mac")) {
oldFolder = new File(saveDir + "/.playminicraft");
if (oldFolder.exists()) {
try {
copyFolderContents(oldFolder.toPath(), testFile.toPath(), RENAME_COPY, true);
} catch (IOException e) {
CrashHandler.errorHandle(e);
}
}
}
}
}
public static String getSystemGameDir() {
return systemGameDir;
}
public static String getLocalGameDir() {
return localGameDir;
}
private static void deleteFolder(File top) {
if (top == null) return;
if (top.isDirectory()) {
File[] subfiles = top.listFiles();
if (subfiles != null)
for (File subfile : subfiles)
deleteFolder(subfile);
}
//noinspection ResultOfMethodCallIgnored
top.delete();
}
public static void copyFolderContents(Path origFolder, Path newFolder, int ifExisting, boolean deleteOriginal) throws IOException {
// I can determine the local folder structure with origFolder.relativize(file), then use newFolder.resolve(relative).
Logging.RESOURCEHANDLER.info("Copying contents of folder " + origFolder + " to new folder " + newFolder);
Files.walkFileTree(origFolder, new FileVisitor<Path>() {
public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
String newFilename = newFolder.resolve(origFolder.relativize(file)).toString();
if (new File(newFilename).exists()) {
if (ifExisting == SKIP)
return FileVisitResult.CONTINUE;
else if (ifExisting == RENAME_COPY) {
newFilename = newFilename.substring(0, newFilename.lastIndexOf("."));
do {
newFilename += "(Old)";
} while (new File(newFilename).exists());
newFilename += Save.extension;
}
}
Path newFile = new File(newFilename).toPath();
newFile.getParent().toFile().mkdirs();
try {
Files.copy(file, newFile, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
CrashHandler.errorHandle(ex);
}
return FileVisitResult.CONTINUE;
}
public FileVisitResult preVisitDirectory(Path p, BasicFileAttributes bfa) {
return FileVisitResult.CONTINUE;
}
public FileVisitResult postVisitDirectory(Path p, IOException ex) {
return FileVisitResult.CONTINUE;
}
public FileVisitResult visitFileFailed(Path p, IOException ex) {
return FileVisitResult.CONTINUE;
}
});
if (deleteOriginal)
deleteFolder(origFolder.toFile());
}
public static ArrayList<String> listAssets() {
Path path;
try {
path = Paths.get(Objects.requireNonNull(Game.class.getResource("/assets/")).toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e); // CRITICAL ERROR (GAME ASSETS)
} catch (FileSystemNotFoundException e) {
try {
FileSystem fs = FileSystems.newFileSystem(Objects.requireNonNull(Game.class.getResource("/assets/")).toURI(), Collections.emptyMap());
path = fs.getPath("/assets/");
} catch (URISyntaxException | IOException ee1) {
throw new RuntimeException(ee1); // CRITICAL ERROR (GAME ASSETS)
}
}
ArrayList<String> names = new ArrayList<>();
try (Stream<Path> paths = Files.walk(path)) {
Path finalPath = path;
paths.forEach(p -> names.add(finalPath.getParent().relativize(p).toString().replace('\\', '/') +
(p.toFile().isDirectory() ? "/" : "")));
return names;
} catch (IOException e) {
throw new RuntimeException(e); // CRITICAL ERROR (GAME ASSETS)
}
}
/**
* Gets a list of paths to where the localization files are located on your disk, and adds them to the "localizationFiles" HashMap.
* The path is relative to the "resources" folder.
* Will not work if we are running this from a jar.
*/
private static ArrayList<String> listResourcesUsingIDE() {
ArrayList<String> names = new ArrayList<>();
try {
URL fUrl = Game.class.getResource("/");
if (fUrl == null) {
Logging.RESOURCEHANDLER_LOCALIZATION.error("Could not find localization folder.");
return names;
}
Path folderPath = Paths.get(fUrl.toURI());
Files.walk(folderPath)
.forEach(p -> {
names.add(folderPath.relativize(p).toString().replace('\\', '/') + (p.toFile().isDirectory() ? "/" : ""));
});
if (!names.contains("resources")) { // Providing a simple resolution when the previous location is invalid, the gradle build path is used.
Path fPath = folderPath.resolve("../../../resources/main");
Files.walk(fPath)
.forEach(p -> {
names.add(fPath.relativize(p).toString().replace('\\', '/') + (p.toFile().isDirectory() ? "/" : ""));
});
}
} catch (IOException | URISyntaxException e) {
CrashHandler.errorHandle(e);
}
return names;
}
}