package io.gitlab.jfronny.respackopts.mixin; import io.gitlab.jfronny.respackopts.RespackoptsConfig; import io.gitlab.jfronny.respackopts.integration.SaveHook; import io.gitlab.jfronny.respackopts.model.cache.CacheKey; import io.gitlab.jfronny.respackopts.util.MetaCache; import io.gitlab.jfronny.respackopts.Respackopts; import io.gitlab.jfronny.respackopts.model.PackMeta; import net.minecraft.resource.*; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.io.*; import java.nio.file.Path; import java.util.HashSet; import java.util.Map; import java.util.Set; @Mixin(ResourcePackManager.class) public class ResourcePackManagerMixin { @Shadow private Map profiles; @Unique private final Set dataLocations = new HashSet<>(); @Inject(at = @At("TAIL"), method = "scanPacks()V") private void scanPacks(CallbackInfo info) { Set toRemove = new HashSet<>(dataLocations); dataLocations.clear(); profiles.forEach((s, v) -> { try (ResourcePack rpi = v.createResourcePack()) { rpo$checkProfile(s, v.getDisplayName().getString(), rpi, toRemove); } }); for (Path s : toRemove) { CacheKey k = MetaCache.getKeyByDataLocation(s); if (k != null) MetaCache.remove(k); } MetaCache.save(SaveHook.Arguments.DO_NOTHING); } private void rpo$checkProfile(String profileName, String displayName, ResourcePack rpi, Set toRemove) { Path dataLocation = null; if (rpi instanceof DirectoryResourcePack drp) { Path pack = ((DirectoryResourcePackAccessor) drp).getRoot(); if (pack != null) dataLocation = pack.getParent().resolve(pack.getFileName() + Respackopts.FILE_EXTENSION); else Respackopts.LOGGER.warn("Base path of directory resource pack " + rpi.getName() + " is null. This shouldn't happen!"); } else if (rpi instanceof ZipResourcePack zrp) { File pack = ((ZipResourcePackAccessor) zrp).getBackingZipFile(); if (pack != null) dataLocation = pack.toPath().getParent().resolve(pack.getName() + Respackopts.FILE_EXTENSION); else Respackopts.LOGGER.warn("Base path of zip resource pack " + rpi.getName() + " is null. This shouldn't happen!"); } var conf = rpi.openRoot(Respackopts.ID + ".json5"); if (conf != null) { try (InputStream is = conf.get()) { rpo$readConfiguration(is, dataLocation, rpi.getName(), displayName, toRemove); return; } catch (IOException e) { String message = "Could not read respackopts config in root for " + profileName; if (RespackoptsConfig.debugLogs) Respackopts.LOGGER.error(message, e); else Respackopts.LOGGER.error(message); } } Identifier confId = new Identifier(Respackopts.ID, "conf.json"); for (ResourceType type : ResourceType.values()) { conf = rpi.open(type, confId); if (conf != null) { try (InputStream is = conf.get()) { rpo$readConfiguration(is, dataLocation, rpi.getName(), displayName, toRemove); return; } catch (Throwable e) { Respackopts.LOGGER.error("Could not initialize pack meta for " + profileName, e); } } } } private void rpo$readConfiguration(InputStream is, Path dataLocation, String packName, String displayName, Set toRemove) throws IOException { try (InputStreamReader isr = new InputStreamReader(is)) { PackMeta conf = Respackopts.GSON.fromJson(isr, PackMeta.class); if (RespackoptsConfig.debugLogs) Respackopts.LOGGER.info("Discovered pack: " + conf.id); if (Respackopts.META_VERSION < conf.version) { Respackopts.LOGGER.error(displayName + " was not loaded as it specifies a newer respackopts version than is installed"); return; } if (dataLocation == null) dataLocation = Respackopts.FALLBACK_CONF_DIR.resolve(conf.id + ".json"); MetaCache.addFromScan(displayName, packName, conf, dataLocation); dataLocations.add(dataLocation); toRemove.remove(dataLocation); } } }