diff --git a/src/main/java/de/bixilon/minosoft/assets/AssetsLoader.kt b/src/main/java/de/bixilon/minosoft/assets/AssetsLoader.kt index ac328402c..662b7c023 100644 --- a/src/main/java/de/bixilon/minosoft/assets/AssetsLoader.kt +++ b/src/main/java/de/bixilon/minosoft/assets/AssetsLoader.kt @@ -8,14 +8,18 @@ import de.bixilon.minosoft.assets.properties.version.AssetsVersionProperties import de.bixilon.minosoft.assets.properties.version.AssetsVersionProperty import de.bixilon.minosoft.config.profile.profiles.resources.ResourcesProfile import de.bixilon.minosoft.data.registries.versions.Version +import de.bixilon.minosoft.util.CountUpAndDownLatch object AssetsLoader { - fun create(profile: ResourcesProfile, version: Version, property: AssetsVersionProperty = AssetsVersionProperties[version] ?: throw IllegalAccessException("$version has no assets!")): AssetsManager { + fun create(profile: ResourcesProfile, version: Version, latch: CountUpAndDownLatch, property: AssetsVersionProperty = AssetsVersionProperties[version] ?: throw IllegalAccessException("$version has no assets!")): AssetsManager { val assetsManager = PriorityAssetsManager() for (resourcePack in profile.assets.resourcePacks) { - assetsManager += resourcePack.type.creator(resourcePack) + resourcePack.type.creator(resourcePack).let { + it.load(latch) + assetsManager += it + } } if (!profile.assets.disableIndexAssets) { diff --git a/src/main/java/de/bixilon/minosoft/assets/AssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/AssetsManager.kt index 2f130edf0..c84b62384 100644 --- a/src/main/java/de/bixilon/minosoft/assets/AssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/AssetsManager.kt @@ -20,6 +20,7 @@ import java.io.FileNotFoundException import java.io.InputStream interface AssetsManager : Iterable> { + /** * All namespaces this assets-manager can provide */ @@ -37,6 +38,7 @@ interface AssetsManager : Iterable> { val properties: AssetsManagerProperties? get() = null + val loaded: Boolean /** * Returns the input stream of an asset or throws FileNotFoundException diff --git a/src/main/java/de/bixilon/minosoft/assets/directory/DirectoryAssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/directory/DirectoryAssetsManager.kt index 220a5bb58..1d186c106 100644 --- a/src/main/java/de/bixilon/minosoft/assets/directory/DirectoryAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/directory/DirectoryAssetsManager.kt @@ -32,6 +32,8 @@ class DirectoryAssetsManager( ) : AssetsManager { override val namespaces: MutableSet = mutableSetOf() private var assets: MutableSet = mutableSetOf() + override var loaded: Boolean = false + private set private val ResourceLocation.filePath: String get() = "$basePath/$namespace/$path" @@ -51,11 +53,14 @@ class DirectoryAssetsManager( } override fun load(latch: CountUpAndDownLatch) { + check(!loaded) { "Already loaded!" } scanDirectory(File(basePath)) + loaded = true } override fun unload() { assets.clear() + loaded = false } override fun iterator(): Iterator> { diff --git a/src/main/java/de/bixilon/minosoft/assets/file/FileAssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/file/FileAssetsManager.kt index c6c2b132e..64eb5f433 100644 --- a/src/main/java/de/bixilon/minosoft/assets/file/FileAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/file/FileAssetsManager.kt @@ -21,6 +21,8 @@ import java.io.FileNotFoundException import java.io.InputStream abstract class FileAssetsManager : AssetsManager { + override var loaded: Boolean = false + protected set override var image: ByteArray? = null protected set override var properties: AssetsManagerProperties? = null @@ -40,6 +42,7 @@ abstract class FileAssetsManager : AssetsManager { override fun unload() { assets.clear() + loaded = false } override fun iterator(): Iterator> { diff --git a/src/main/java/de/bixilon/minosoft/assets/file/ZipAssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/file/ZipAssetsManager.kt index e5c00795b..edd0b30be 100644 --- a/src/main/java/de/bixilon/minosoft/assets/file/ZipAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/file/ZipAssetsManager.kt @@ -29,22 +29,28 @@ class ZipAssetsManager( ) : FileAssetsManager() { override fun load(latch: CountUpAndDownLatch) { + check(!loaded) { "Already loaded!" } + val namespaces: MutableSet = mutableSetOf() while (true) { val entry = inputStream.nextEntry ?: break + if (entry.isDirectory) { + continue + } when (val name = entry.name) { "pack.png" -> image = inputStream.readAllBytes() - "pack.mcmeta" -> properties = inputStream.readJson() + "pack.mcmeta" -> properties = inputStream.readJson(false) else -> { val resourceLocation = name.toAssetName() ?: continue namespaces += resourceLocation.namespace assets[resourceLocation] = inputStream.readAllBytes() } } - inputStream.closeEntry() } + inputStream.close() this.namespaces = namespaces + loaded = true } constructor(file: File) : this(ZipInputStream(FileInputStream(file))) diff --git a/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt index e0599129a..4d2069ed5 100644 --- a/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/minecraft/JarAssetsManager.kt @@ -40,10 +40,14 @@ class JarAssetsManager( val profile: ResourcesProfile, val version: Version, ) : MinecraftAssetsManager { + override var loaded: Boolean = false + private set override val namespaces = setOf(ProtocolDefinition.DEFAULT_NAMESPACE) private var jarAssets: MutableMap = mutableMapOf() override fun load(latch: CountUpAndDownLatch) { + check(!loaded) { "Already loaded!" } + val jarAssetFile = File(FileAssetsUtil.getPath(jarAssetsHash)) if (FileAssetsUtil.verifyAsset(jarAssetsHash, jarAssetFile, profile.verify)) { val jarAssets = FileUtil.readFile(jarAssetFile).readArchive() @@ -100,6 +104,7 @@ class JarAssetsManager( this.jarAssets = buildingJarAsset } + loaded = true } override fun get(path: ResourceLocation): InputStream { @@ -116,6 +121,7 @@ class JarAssetsManager( override fun unload() { jarAssets = mutableMapOf() + loaded = false } override fun iterator(): Iterator> { diff --git a/src/main/java/de/bixilon/minosoft/assets/minecraft/index/IndexAssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/minecraft/index/IndexAssetsManager.kt index 92d7e0981..f01f6ca8f 100644 --- a/src/main/java/de/bixilon/minosoft/assets/minecraft/index/IndexAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/minecraft/index/IndexAssetsManager.kt @@ -50,6 +50,8 @@ class IndexAssetsManager( private val verify: Boolean = profile.verify private val assets: MutableMap = synchronizedMapOf() override val namespaces: Set = setOf(ProtocolDefinition.DEFAULT_NAMESPACE) + override var loaded: Boolean = false + private set private fun downloadAssetsIndex(): Map { return Jackson.MAPPER.readValue(FileAssetsUtil.downloadAndGetAsset(Util.formatString(profile.source.mojangPackages, @@ -77,6 +79,8 @@ class IndexAssetsManager( } override fun load(latch: CountUpAndDownLatch) { + check(!loaded) { "Already loaded!" } + var assets = FileUtil.saveReadFile(FileAssetsUtil.getPath(indexHash))?.readJsonObject() ?: downloadAssetsIndex() assets["objects"].let { assets = it.asCompound() } @@ -120,13 +124,17 @@ class IndexAssetsManager( } } assetsLatch.await() + loaded = true } override fun iterator(): Iterator> { TODO("Not yet implemented") } - override fun unload() {} + override fun unload() { + assets.clear() + loaded = false + } override fun get(path: ResourceLocation): InputStream { return FileUtil.readFile(FileAssetsUtil.getPath(assets[path]?.hash ?: throw FileNotFoundException("Could not find asset $path"))) diff --git a/src/main/java/de/bixilon/minosoft/assets/multi/PriorityAssetsManager.kt b/src/main/java/de/bixilon/minosoft/assets/multi/PriorityAssetsManager.kt index f309b2d41..2889d934b 100644 --- a/src/main/java/de/bixilon/minosoft/assets/multi/PriorityAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/assets/multi/PriorityAssetsManager.kt @@ -27,6 +27,17 @@ class PriorityAssetsManager( ) : MultiAssetsManager { private val managers: MutableMap> = mutableMapOf() override val namespaces: MutableSet = mutableSetOf() + override val loaded: Boolean + get() { + for (managers in managers.values) { + for (manager in managers) { + if (!manager.loaded) { + return false + } + } + } + return true + } init { for (manager in managers) { @@ -67,6 +78,9 @@ class PriorityAssetsManager( override fun load(latch: CountUpAndDownLatch) { for ((_, managers) in managers) { for (manager in managers) { + if (manager.loaded) { + continue + } manager.load(latch) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt index 7620034f6..87d3ace61 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/texture/PNGTexture.kt @@ -22,7 +22,11 @@ import de.matthiasmann.twl.utils.PNGDecoder import glm_.vec2.Vec2 import glm_.vec2.Vec2i import org.lwjgl.BufferUtils +import java.awt.image.BufferedImage +import java.io.ByteArrayOutputStream +import java.io.DataOutputStream import java.nio.ByteBuffer +import javax.imageio.ImageIO class PNGTexture(override val resourceLocation: ResourceLocation) : AbstractTexture { @@ -49,7 +53,22 @@ class PNGTexture(override val resourceLocation: ResourceLocation) : AbstractText val decoder = PNGDecoder(assetsManager[resourceLocation]) val data = BufferUtils.createByteBuffer(decoder.width * decoder.height * PNGDecoder.Format.RGBA.numComponents) - decoder.decode(data, decoder.width * PNGDecoder.Format.RGBA.numComponents, PNGDecoder.Format.RGBA) + try { + decoder.decode(data, decoder.width * PNGDecoder.Format.RGBA.numComponents, PNGDecoder.Format.RGBA) + } catch (exception: Throwable) { + // ToDo: This somehow crashes with some resource packs + // exception.printStackTrace() + val image: BufferedImage = ImageIO.read(assetsManager[resourceLocation]) + val rgb = image.getRGB(0, 0, image.width, image.height, null, 0, image.width) + + val byteOutput = ByteArrayOutputStream() + val dataOutput = DataOutputStream(byteOutput) + for (color in rgb) { + dataOutput.writeInt(color) + } + + data.put(byteOutput.toByteArray()) + } size = Vec2i(decoder.width, decoder.height) transparency = TextureTransparencies.OPAQUE diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt index 249f5bd9e..b2bba669a 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt @@ -220,8 +220,8 @@ class PlayConnection( version.load(profiles.resources) registries.parentRegistries = version.registries - assetsManager = AssetsLoader.create(profiles.resources, version) Log.log(LogMessageType.ASSETS, LogLevels.INFO) { "Downloading and verifying assets. This might take a while..." } + assetsManager = AssetsLoader.create(profiles.resources, version, latch) assetsManager.load(latch) Log.log(LogMessageType.ASSETS, LogLevels.INFO) { "Assets verified!" } diff --git a/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt b/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt index 411bead5b..b4c9e0c48 100644 --- a/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt +++ b/src/main/java/de/bixilon/minosoft/util/json/Jackson.kt @@ -1,5 +1,6 @@ package de.bixilon.minosoft.util.json +import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.PropertyNamingStrategies @@ -21,6 +22,7 @@ object Jackson { .registerModule(RGBColorSerializer) .registerModule(ChatComponentColorSerializer) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .disable(JsonParser.Feature.AUTO_CLOSE_SOURCE) .setDefaultMergeable(true)