|
6 | 6 | import java.nio.file.Paths; |
7 | 7 | import java.util.ArrayList; |
8 | 8 | import java.util.List; |
9 | | -import java.util.Locale; |
10 | 9 |
|
11 | 10 | import com.mojang.blaze3d.systems.RenderSystem; |
12 | 11 | import net.minecraftforge.data.loading.DatagenModLoader; |
13 | 12 | import net.minecraftforge.event.server.ServerStartedEvent; |
14 | 13 | import net.minecraftforge.event.server.ServerStartingEvent; |
15 | | -import net.minecraft.network.chat.TextComponent; |
16 | 14 | import net.minecraft.server.packs.*; |
17 | | -import net.minecraft.server.packs.metadata.MetadataSectionSerializer; |
18 | | -import net.minecraft.server.packs.repository.Pack; |
19 | | -import net.minecraft.server.packs.repository.PackCompatibility; |
20 | | -import net.minecraft.server.packs.repository.PackSource; |
21 | 15 | import net.minecraft.server.packs.resources.ReloadableResourceManager; |
22 | | -import net.minecraft.server.packs.resources.Resource; |
23 | 16 |
|
24 | 17 | import java.util.*; |
25 | 18 |
|
26 | 19 | import net.minecraft.resources.*; |
27 | | -import net.minecraftforge.fml.ModList; |
28 | 20 | import org.apache.logging.log4j.LogManager; |
29 | 21 | import org.apache.logging.log4j.Logger; |
30 | 22 |
|
|
36 | 28 | import cam72cam.mod.net.Packet; |
37 | 29 | import cam72cam.mod.net.PacketDirection; |
38 | 30 | import cam72cam.mod.render.Light; |
| 31 | +import cam72cam.mod.resource.BuiltinPack; |
39 | 32 | import cam72cam.mod.resource.Identifier; |
40 | 33 | import cam72cam.mod.text.Command; |
41 | 34 | import cam72cam.mod.util.MinecraftFiles; |
42 | 35 | import cam72cam.mod.util.ModCoreCommand; |
43 | 36 | import cam72cam.mod.world.ChunkManager; |
44 | 37 | import net.minecraft.client.Minecraft; |
45 | | -import net.minecraft.resources.ResourceLocation; |
46 | 38 | import net.minecraft.server.packs.*; |
47 | 39 | import net.minecraft.util.Unit; |
48 | 40 | import net.minecraftforge.common.MinecraftForge; |
|
59 | 51 | import org.apache.commons.lang3.StringUtils; |
60 | 52 | import org.apache.commons.lang3.SystemUtils; |
61 | 53 |
|
62 | | -import javax.annotation.Nullable; |
63 | 54 | import java.io.File; |
64 | 55 | import java.io.IOException; |
65 | | -import java.util.function.Predicate; |
66 | | -import java.util.stream.Collectors; |
67 | 56 |
|
68 | 57 | /** UMC Mod, do not touch... */ |
69 | 58 | @net.minecraftforge.fml.common.Mod(ModCore.MODID) |
@@ -195,6 +184,10 @@ public static void catching(Throwable ex) { |
195 | 184 | } |
196 | 185 | } |
197 | 186 |
|
| 187 | + public List<Mod> getLoadedMods() { |
| 188 | + return mods; |
| 189 | + } |
| 190 | + |
198 | 191 | private static Proxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new); |
199 | 192 | /** Hooked into forge's proxy system and fires off corresponding events */ |
200 | 193 | public static class Proxy { |
@@ -238,199 +231,61 @@ public void setup() { |
238 | 231 | } |
239 | 232 | Config.getMaxTextureSize(); //populate |
240 | 233 |
|
241 | | - // Force first and last (and inject mod time) BUG: sounds can still be overridden by resource packs |
242 | | - Minecraft.getInstance().getResourcePackRepository().addPackFinder((consumer, packInfoFactory) -> { |
243 | | - List<PackResources> packs = new ArrayList<>(); |
244 | | - packs.add(new TranslationResourcePack()); |
245 | | - |
246 | | - for (Mod m : mods) { |
247 | | - PackResources modPack = createPack(ModList.get().getModFileById(m.modID()).getFile().getFilePath().toFile()); |
248 | | - packs.add(modPack); |
249 | | - String configDir = FMLPaths.CONFIGDIR.get().toString(); |
250 | | - new File(configDir).mkdirs(); |
251 | | - |
252 | | - File folder = new File(configDir + File.separator + m.modID()); |
253 | | - if (folder.exists()) { |
254 | | - if (folder.isDirectory()) { |
255 | | - File[] files = folder.listFiles((dir, name) -> name.endsWith(".zip")); |
256 | | - for (File file : files) { |
257 | | - packs.add(createPack(file)); |
258 | | - } |
| 234 | + BuiltinPack.loadClientResources(); |
259 | 235 |
|
260 | | - File[] folders = folder.listFiles((dir, name) -> dir.isDirectory()); |
261 | | - for (File dir : folders) { |
262 | | - packs.add(createPack(dir)); |
263 | | - } |
264 | | - } |
265 | | - } else { |
266 | | - folder.mkdirs(); |
267 | | - } |
268 | | - packs.add(modPack); |
| 236 | + //Wrapper for lang format language files |
| 237 | + BuiltinPack.conditional(ident -> { |
| 238 | + String path = ident.getPath(); |
| 239 | + if (!path.startsWith("lang/") || !path.endsWith(".json")) { |
| 240 | + return null; |
269 | 241 | } |
270 | 242 |
|
271 | | - |
272 | | - for (PackResources pack : packs) { |
273 | | - consumer.accept(new Pack(pack.getName(), |
274 | | - true, |
275 | | - () -> pack, |
276 | | - new TextComponent(""), |
277 | | - new TextComponent(""), |
278 | | - PackCompatibility.COMPATIBLE, |
279 | | - Pack.Position.TOP, |
280 | | - true, |
281 | | - PackSource.DEFAULT, |
282 | | - true)); |
| 243 | + Identifier lang = new Identifier(ident.toString().replace(".json", ".lang")); |
| 244 | + if (!lang.canLoad()) { |
| 245 | + return null; |
283 | 246 | } |
284 | | - }); |
285 | | - } |
286 | | - |
287 | | - @Override |
288 | | - public void event(ModEvent event, Mod m) { |
289 | | - super.event(event, m); |
290 | | - m.clientEvent(event); |
291 | | - } |
292 | 247 |
|
293 | | - private static class TranslationResourcePack extends AbstractPackResources { |
294 | | - public TranslationResourcePack() { |
295 | | - super(null); |
296 | | - } |
297 | | - |
298 | | - private ResourceLocation toLang(String path) { |
299 | | - // assets/mod/location |
300 | | - //return String.format("%s/%s/%s", type.getDirectoryName(), location.getNamespace(), location.getPath()); |
301 | | - String[] parts = path.split("/"); |
302 | | - String type = parts[0]; |
303 | | - String namespace = parts[1]; |
304 | | - String prefix = String.format("%s/%s/", type, namespace); |
305 | | - path = path.replace(prefix, "").replace(".json", ".lang"); |
306 | | - String lang = path.split("_")[1].replace(".lang", ""); |
307 | | - path = path.replace("_" + lang, "_" + lang.toUpperCase(Locale.ROOT)); |
308 | | - return new ResourceLocation(namespace, path.toLowerCase(Locale.ROOT)) { |
309 | | - @Override |
310 | | - public String getPath() { |
311 | | - // Very evil... |
312 | | - return path; |
313 | | - } |
314 | | - }; |
315 | | - } |
316 | | - |
317 | | - @Override |
318 | | - public boolean hasResource(String resourcePath) { |
319 | | - if (resourcePath.contains("/lang/") && resourcePath.endsWith(".json")) { |
320 | | - ResourceLocation lang = toLang(resourcePath); |
321 | | - return Minecraft.getInstance().getResourceManager().hasResource(lang); |
322 | | - } |
323 | | - return false; |
324 | | - } |
| 248 | + Map<String, String> translationMap = new HashMap<>(); |
| 249 | + try { |
| 250 | + for (InputStream stream : lang.getResourceStreamAll()) { |
| 251 | + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { |
| 252 | + String line; |
| 253 | + while ((line = reader.readLine()) != null) { |
| 254 | + //Remove comment |
| 255 | + line = line.trim(); |
| 256 | + if (line.isEmpty() || line.startsWith("#")) { |
| 257 | + continue; |
| 258 | + } |
325 | 259 |
|
326 | | - @Override |
327 | | - public InputStream getResource(String resourcePath) throws IOException { |
328 | | - if (resourcePath.contains("/lang/") && resourcePath.endsWith(".json")) { |
329 | | - // Magical Translations! |
330 | | - ResourceLocation lang = toLang(resourcePath); |
331 | | - if (Minecraft.getInstance().getResourceManager().hasResource(lang)) { |
332 | | - Map<String, String> translationMap = new HashMap<>(); |
333 | | - for (Resource resource : Minecraft.getInstance().getResourceManager().getResources(lang)) { |
334 | | - try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) { |
335 | | - String line; |
336 | | - while ((line = reader.readLine()) != null) { |
337 | | - //Remove comment |
338 | | - line = line.trim(); |
339 | | - int comment = line.indexOf("#"); |
340 | | - if (line.isEmpty() || comment == 0) { |
341 | | - continue; |
342 | | - } |
343 | | - |
344 | | - String[] splits = line.split("=", 2); |
345 | | - if (splits.length == 2) { |
346 | | - translationMap.put(splits[0].trim(), splits[1].trim()); |
347 | | - } |
| 260 | + String[] splits = line.split("=", 2); |
| 261 | + if (splits.length == 2) { |
| 262 | + translationMap.put(splits[0].trim(), splits[1].trim()); |
348 | 263 | } |
349 | 264 | } |
350 | 265 | } |
351 | | - |
352 | | - Set<String> translations = new HashSet<>(); |
353 | | - translationMap.forEach((key, value) -> { |
354 | | - if (!key.isEmpty()) { |
355 | | - translations.add(String.format("\"%s\": \"%s\"", key, value)); |
356 | | - translations.add(String.format("\"%s\": \"%s\"", key.replace(":", "."), value)); |
357 | | - translations.add(String.format("\"%s\": \"%s\"", key.replace(".name", ""), value)); |
358 | | - translations.add(String.format("\"%s\": \"%s\"", key.replace(".name", "").replace(":", "."), value)); |
359 | | - } |
360 | | - }); |
361 | | - String output = "{" + String.join(",", translations) + "}"; |
362 | | - return new ByteArrayInputStream(output.getBytes(StandardCharsets.UTF_8)); |
363 | 266 | } |
| 267 | + } catch (IOException e) { |
| 268 | + throw new RuntimeException(e); |
364 | 269 | } |
365 | | - return null; |
366 | | - } |
367 | | - |
368 | | - @Override |
369 | | - public Collection<ResourceLocation> getResources(PackType p_225637_1_, String p_225637_2_, String p_225637_3_, int p_225637_4_, Predicate<String> p_225637_5_) { |
370 | | - return Collections.emptyList(); |
371 | | - } |
372 | | - |
373 | | - @Override |
374 | | - public Set<String> getNamespaces(PackType p_195759_1_) { |
375 | | - return mods.stream().map(Mod::modID).collect(Collectors.toSet()); |
376 | | - } |
377 | 270 |
|
378 | | - @Override |
379 | | - public void close() { |
380 | | - |
381 | | - } |
382 | | - |
383 | | - @Override |
384 | | - public String getName() { |
385 | | - return "Translation Hackery"; |
386 | | - } |
387 | | - |
388 | | - @Nullable |
389 | | - @Override |
390 | | - public <T> T getMetadataSection(MetadataSectionSerializer<T> p_195760_1_) throws IOException { |
391 | | - return getMetadataFromStream(p_195760_1_, new ByteArrayInputStream("{}".getBytes())); |
392 | | - } |
393 | | - } |
394 | | - |
395 | | - private static class UMCFolderPack extends FolderPackResources { |
396 | | - public UMCFolderPack(File folder) { |
397 | | - super(folder); |
398 | | - } |
399 | | - |
400 | | - @Override |
401 | | - public InputStream getResource(String name) throws IOException { |
402 | | - InputStream stream = super.getResource(name); |
403 | | - File file = this.getFile(name); |
404 | | - return new Identifier.InputStreamMod(stream, file.lastModified()); |
405 | | - } |
406 | | - |
407 | | - @Override |
408 | | - public boolean hasResource(String resourcePath) { |
409 | | - return super.hasResource(resourcePath); |
410 | | - } |
411 | | - } |
412 | | - |
413 | | - private static class UMCFilePack extends FilePackResources { |
414 | | - private final File path; |
415 | | - |
416 | | - public UMCFilePack(File fileIn) { |
417 | | - super(fileIn); |
418 | | - this.path = fileIn; |
419 | | - } |
420 | | - |
421 | | - @Override |
422 | | - public InputStream getResource(String name) throws IOException { |
423 | | - return new Identifier.InputStreamMod(super.getResource(name), path.lastModified()); |
424 | | - } |
| 271 | + Set<String> translations = new HashSet<>(); |
| 272 | + translationMap.forEach((key, value) -> { |
| 273 | + if (!key.isEmpty()) { |
| 274 | + translations.add(String.format("\"%s\": \"%s\"", key, value)); |
| 275 | + translations.add(String.format("\"%s\": \"%s\"", key.replace(":", "."), value)); |
| 276 | + translations.add(String.format("\"%s\": \"%s\"", key.replace(".name", ""), value)); |
| 277 | + translations.add(String.format("\"%s\": \"%s\"", key.replace(".name", "").replace(":", "."), value)); |
| 278 | + } |
| 279 | + }); |
| 280 | + String output = "{" + String.join(",", translations) + "}"; |
| 281 | + return output.getBytes(StandardCharsets.UTF_8); |
| 282 | + }); |
425 | 283 | } |
426 | 284 |
|
427 | | - |
428 | | - private static PackResources createPack(File path) { |
429 | | - if (path.isDirectory()) { |
430 | | - return new UMCFolderPack(path); |
431 | | - } else { |
432 | | - return new UMCFilePack(path); |
433 | | - } |
| 285 | + @Override |
| 286 | + public void event(ModEvent event, Mod m) { |
| 287 | + super.event(event, m); |
| 288 | + m.clientEvent(event); |
434 | 289 | } |
435 | 290 | } |
436 | 291 |
|
@@ -485,8 +340,9 @@ public void clientEvent(ModEvent event) { |
485 | 340 | // Instance can be null during data gen |
486 | 341 | if (Minecraft.getInstance() != null) { |
487 | 342 | ((ReloadableResourceManager) Minecraft.getInstance().getResourceManager()).registerReloadListener((stage, resourceManager, preparationsProfiler, reloadProfiler, backgroundExecutor, gameExecutor) -> |
488 | | - stage.wait(Unit.INSTANCE).thenRun(ClientEvents::fireReload)); |
| 343 | + stage.wait(Unit.INSTANCE).thenRun(ClientEvents::fireReload).thenRun(BuiltinPack::reload)); |
489 | 344 | } |
| 345 | + break; |
490 | 346 | case SETUP: |
491 | 347 | try { |
492 | 348 | Minecraft.getInstance().createSearchTrees(); |
|
0 commit comments