feat(IconExporter): blocks/items 폴더 구분 및 ZIP 압축 기능 추가
- BlockItem 여부로 blocks/items 폴더 자동 분류 - 추출 완료 후 icons_<mod>_<timestamp>.zip 자동 생성 - README 업데이트
This commit is contained in:
parent
bf8f980fed
commit
27888c557d
2 changed files with 98 additions and 19 deletions
|
|
@ -48,19 +48,27 @@
|
|||
|
||||
## 📁 출력 구조
|
||||
|
||||
추출된 아이콘은 `.minecraft/icons/` 폴더에 저장됩니다.
|
||||
아이콘은 `.minecraft/icons/` 폴더에 **blocks/items**로 구분되어 저장됩니다.
|
||||
완료 후 자동으로 ZIP 파일이 생성됩니다.
|
||||
|
||||
```
|
||||
.minecraft/
|
||||
└── icons/
|
||||
├── minecraft/
|
||||
│ ├── diamond.png
|
||||
│ ├── iron_ingot.png
|
||||
│ └── ...
|
||||
└── create/
|
||||
├── mechanical_press.png
|
||||
├── brass_ingot.png
|
||||
└── ...
|
||||
├── icons/
|
||||
│ ├── minecraft/
|
||||
│ │ ├── blocks/
|
||||
│ │ │ ├── stone.png
|
||||
│ │ │ └── ...
|
||||
│ │ └── items/
|
||||
│ │ ├── diamond.png
|
||||
│ │ └── ...
|
||||
│ └── create/
|
||||
│ ├── blocks/
|
||||
│ │ ├── brass_casing.png
|
||||
│ │ └── ...
|
||||
│ └── items/
|
||||
│ ├── brass_ingot.png
|
||||
│ └── ...
|
||||
└── icons_create_20251226_181500.zip ← 자동 생성
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -2,20 +2,27 @@ package com.beemer.iconexporter.export
|
|||
|
||||
import com.beemer.iconexporter.IconExporter
|
||||
import com.beemer.iconexporter.render.IconRenderer
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.name
|
||||
import kotlin.io.path.pathString
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* 아이콘 추출 관리자
|
||||
*
|
||||
* 대량의 아이템을 처리할 때 게임 프리즈를 방지하기 위해 틱 기반 큐 시스템으로 아이템을 순차적으로 처리합니다.
|
||||
* 대량의 아이템을 처리할 때 게임 프리즈를 방지하기 위해 틱 기반 큐 시스템으로 아이템을 순차적으로 처리합니다. 완료 후 icons 폴더를 ZIP으로 압축합니다.
|
||||
*/
|
||||
object IconExportManager {
|
||||
// 틱당 처리할 아이템 수 (너무 높으면 랙, 너무 낮으면 느림)
|
||||
|
|
@ -127,8 +134,12 @@ object IconExportManager {
|
|||
}
|
||||
|
||||
try {
|
||||
// 아이템이 블록인지 확인 (BlockItem이면 블록, 아니면 아이템)
|
||||
val isBlock = item is BlockItem
|
||||
val type = if (isBlock) "blocks" else "items"
|
||||
|
||||
// 저장 경로 생성
|
||||
val outputPath = getOutputPath(itemId.namespace, itemId.path)
|
||||
val outputPath = getOutputPath(itemId.namespace, type, itemId.path)
|
||||
|
||||
// 이미 파일이 존재하고 덮어쓰기가 비활성화된 경우 스킵
|
||||
if (outputPath.exists() && !overwrite) {
|
||||
|
|
@ -162,13 +173,16 @@ object IconExportManager {
|
|||
}
|
||||
}
|
||||
|
||||
/** 아이템 ID로 출력 경로 생성 */
|
||||
private fun getOutputPath(namespace: String, path: String): java.nio.file.Path {
|
||||
/**
|
||||
* 아이템 ID로 출력 경로 생성 형식: icons/<namespace>/<type>/<path>.png 예:
|
||||
* icons/create/blocks/brass_casing.png
|
||||
*/
|
||||
private fun getOutputPath(namespace: String, type: String, path: String): Path {
|
||||
val mc = Minecraft.getInstance()
|
||||
val gameDir = mc.gameDirectory.toPath()
|
||||
|
||||
// icons/<namespace>/<path>.png
|
||||
return gameDir.resolve("icons").resolve(namespace).resolve("$path.png")
|
||||
// icons/<namespace>/<type>/<path>.png
|
||||
return gameDir.resolve("icons").resolve(namespace).resolve(type).resolve("$path.png")
|
||||
}
|
||||
|
||||
/** 진행률 로그 출력 */
|
||||
|
|
@ -199,6 +213,17 @@ object IconExportManager {
|
|||
isRunning = false
|
||||
val elapsed = System.currentTimeMillis() - startTime
|
||||
|
||||
val mc = Minecraft.getInstance()
|
||||
val iconsDir = mc.gameDirectory.toPath().resolve("icons")
|
||||
|
||||
// ZIP 압축 생성
|
||||
var zipPath: Path? = null
|
||||
try {
|
||||
zipPath = createZipArchive(iconsDir)
|
||||
} catch (e: Exception) {
|
||||
IconExporter.LOGGER.error("ZIP 압축 실패: {}", e.message)
|
||||
}
|
||||
|
||||
val summary =
|
||||
"""
|
||||
§a=== 추출 완료 ===
|
||||
|
|
@ -221,17 +246,63 @@ object IconExportManager {
|
|||
}
|
||||
|
||||
// 게임 내 메시지
|
||||
val mc = Minecraft.getInstance()
|
||||
mc.player?.let { player ->
|
||||
player.displayClientMessage(Component.literal(summary), false)
|
||||
|
||||
// 저장 위치 안내
|
||||
val outputDir = mc.gameDirectory.toPath().resolve("icons")
|
||||
// ZIP 경로 안내
|
||||
if (zipPath != null) {
|
||||
player.displayClientMessage(
|
||||
Component.literal("§7저장 위치: §f${outputDir.toAbsolutePath()}"),
|
||||
Component.literal("§7ZIP 파일: §f${zipPath.toAbsolutePath()}"),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
// 저장 위치 안내
|
||||
player.displayClientMessage(
|
||||
Component.literal("§7아이콘 폴더: §f${iconsDir.toAbsolutePath()}"),
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** icons 폴더를 ZIP으로 압축 파일명: icons_<modFilter>_<timestamp>.zip */
|
||||
private fun createZipArchive(iconsDir: Path): Path? {
|
||||
if (!iconsDir.exists()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val mc = Minecraft.getInstance()
|
||||
val gameDir = mc.gameDirectory.toPath()
|
||||
|
||||
// ZIP 파일명 생성
|
||||
val timestamp =
|
||||
java.time.LocalDateTime.now()
|
||||
.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))
|
||||
val modName = currentModFilter ?: "all"
|
||||
val zipFileName = "icons_${modName}_$timestamp.zip"
|
||||
val zipPath = gameDir.resolve(zipFileName)
|
||||
|
||||
IconExporter.LOGGER.info("ZIP 압축 생성 중: {}", zipPath)
|
||||
|
||||
ZipOutputStream(FileOutputStream(zipPath.toFile())).use { zos ->
|
||||
Files.walk(iconsDir).use { paths ->
|
||||
paths.filter { Files.isRegularFile(it) && it.name.endsWith(".png") }.forEach { file
|
||||
->
|
||||
try {
|
||||
// ZIP 내 상대 경로: <namespace>/<type>/<item>.png
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IconExporter.LOGGER.info("ZIP 압축 완료: {}", zipPath)
|
||||
return zipPath
|
||||
}
|
||||
|
||||
/** 작업 취소 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue