feat(IconExporter): 폴더 구분 제거 - 단일 폴더로 통합

- blocks/items 폴더 구분 제거
- 모든 아이콘을 icons/<name>.png로 저장
- ZIP 구조 단순화 (metadata.json + 파일명.png)
- 압축 후 PNG 파일만 삭제
This commit is contained in:
Caadiq 2025-12-26 19:16:29 +09:00
parent 4949a7071e
commit 215baf9361

View file

@ -11,11 +11,9 @@ import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
import kotlin.io.path.exists import kotlin.io.path.exists
import kotlin.io.path.name import kotlin.io.path.name
import kotlin.io.path.pathString
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
@ -134,12 +132,8 @@ object IconExportManager {
} }
try { try {
// 아이템이 블록인지 확인 (BlockItem이면 블록, 아니면 아이템) // 저장 경로 생성 (blocks/items 구분 없이 단일 폴더)
val isBlock = item is BlockItem val outputPath = getOutputPath(itemId.namespace, itemId.path)
val type = if (isBlock) "blocks" else "items"
// 저장 경로 생성
val outputPath = getOutputPath(itemId.namespace, type, itemId.path)
// 이미 파일이 존재하고 덮어쓰기가 비활성화된 경우 스킵 // 이미 파일이 존재하고 덮어쓰기가 비활성화된 경우 스킵
if (outputPath.exists() && !overwrite) { if (outputPath.exists() && !overwrite) {
@ -173,16 +167,13 @@ object IconExportManager {
} }
} }
/** /** 아이템 ID로 출력 경로 생성 형식: icons/<path>.png 예: icons/brass_casing.png */
* 아이템 ID로 출력 경로 생성 형식: icons/<namespace>/<type>/<path>.png : private fun getOutputPath(namespace: String, path: String): Path {
* icons/create/blocks/brass_casing.png
*/
private fun getOutputPath(namespace: String, type: String, path: String): Path {
val mc = Minecraft.getInstance() val mc = Minecraft.getInstance()
val gameDir = mc.gameDirectory.toPath() val gameDir = mc.gameDirectory.toPath()
// icons/<namespace>/<type>/<path>.png // icons/<path>.png (단일 폴더)
return gameDir.resolve("icons").resolve(namespace).resolve(type).resolve("$path.png") return gameDir.resolve("icons").resolve("$path.png")
} }
/** 진행률 로그 출력 */ /** 진행률 로그 출력 */
@ -283,19 +274,6 @@ object IconExportManager {
IconExporter.LOGGER.info("ZIP 압축 생성 중: {}", zipPath) IconExporter.LOGGER.info("ZIP 압축 생성 중: {}", zipPath)
// 압축할 모드 폴더 경로 (특정 모드 또는 전체)
val targetDir =
if (currentModFilter != null) {
iconsDir.resolve(currentModFilter!!)
} else {
iconsDir
}
if (!targetDir.exists()) {
IconExporter.LOGGER.error("대상 폴더가 없습니다: {}", targetDir)
return null
}
ZipOutputStream(FileOutputStream(zipPath.toFile())).use { zos -> ZipOutputStream(FileOutputStream(zipPath.toFile())).use { zos ->
// metadata.json 추가 // metadata.json 추가
val metadata = buildString { val metadata = buildString {
@ -311,38 +289,17 @@ object IconExportManager {
zos.write(metadata.toByteArray(Charsets.UTF_8)) zos.write(metadata.toByteArray(Charsets.UTF_8))
zos.closeEntry() zos.closeEntry()
// PNG 파일 추가 // PNG 파일 추가 (모든 파일을 단순히 파일명만으로 압축)
if (currentModFilter != null) { Files.walk(iconsDir).use { paths ->
// 특정 모드만 압축 paths.filter { Files.isRegularFile(it) && it.name.endsWith(".png") }.forEach { file
Files.walk(targetDir).use { paths -> ->
paths.filter { Files.isRegularFile(it) && it.name.endsWith(".png") }.forEach { try {
file -> // ZIP 내 경로: 파일명만 사용 (예: brass_casing.png)
try { zos.putNextEntry(ZipEntry(file.name))
// ZIP 내 상대 경로: blocks/<item>.png 또는 items/<item>.png Files.copy(file, zos)
val relativePath = zos.closeEntry()
targetDir.relativize(file).pathString.replace("\\", "/") } catch (e: Exception) {
zos.putNextEntry(ZipEntry(relativePath)) IconExporter.LOGGER.error("ZIP에 파일 추가 실패: {} - {}", file, e.message)
Files.copy(file, zos)
zos.closeEntry()
} catch (e: Exception) {
IconExporter.LOGGER.error("ZIP에 파일 추가 실패: {} - {}", file, e.message)
}
}
}
} else {
// 전체 압축
Files.walk(iconsDir).use { paths ->
paths.filter { Files.isRegularFile(it) && it.name.endsWith(".png") }.forEach {
file ->
try {
val relativePath =
iconsDir.relativize(file).pathString.replace("\\", "/")
zos.putNextEntry(ZipEntry(relativePath))
Files.copy(file, zos)
zos.closeEntry()
} catch (e: Exception) {
IconExporter.LOGGER.error("ZIP에 파일 추가 실패: {} - {}", file, e.message)
}
} }
} }
} }
@ -350,21 +307,21 @@ object IconExportManager {
IconExporter.LOGGER.info("ZIP 압축 완료: {}", zipPath) IconExporter.LOGGER.info("ZIP 압축 완료: {}", zipPath)
// 압축 완료 후 원본 폴더 삭제 // 압축 완료 후 원본 PNG 파일 삭제 (ZIP 파일 제외)
try { try {
if (currentModFilter != null) { Files.list(iconsDir).use { files ->
// 특정 모드 폴더만 삭제 files.filter { Files.isRegularFile(it) && it.name.endsWith(".png") }.forEach { file
deleteDirectory(targetDir) ->
IconExporter.LOGGER.info("원본 폴더 삭제됨: {}", targetDir) try {
} else { Files.delete(file)
// 전체 모드인 경우 각 모드 폴더 삭제 (ZIP 파일 제외) } catch (e: Exception) {
Files.list(iconsDir).use { dirs -> IconExporter.LOGGER.error("파일 삭제 실패: {} - {}", file, e.message)
dirs.filter { Files.isDirectory(it) }.forEach { dir -> deleteDirectory(dir) } }
} }
IconExporter.LOGGER.info("모든 원본 폴더 삭제됨")
} }
IconExporter.LOGGER.info("원본 PNG 파일 삭제됨")
} catch (e: Exception) { } catch (e: Exception) {
IconExporter.LOGGER.error("원본 폴더 삭제 실패: {}", e.message) IconExporter.LOGGER.error("원본 파일 삭제 실패: {}", e.message)
} }
return zipPath return zipPath