diff --git a/gradle.properties b/gradle.properties index a407796..07d7c09 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version = 0.6.0 \ No newline at end of file +version = 0.7.0 \ No newline at end of file diff --git a/src/main/kotlin/de/skyrising/mc/scanner/inventories.kt b/src/main/kotlin/de/skyrising/mc/scanner/inventories.kt index f7b1714..a921937 100644 --- a/src/main/kotlin/de/skyrising/mc/scanner/inventories.kt +++ b/src/main/kotlin/de/skyrising/mc/scanner/inventories.kt @@ -61,6 +61,10 @@ fun scanInventory(slots: ListTag, needles: Collection, st } } if (bestMatch != null) { + if (slot.has("tag", Tag.COMPOUND)) { + val tag = slot.getCompound("tag") + bestMatch = bestMatch.withTag(tag) + } result.addTo(bestMatch, slot.getInt("Count").toLong()) } } diff --git a/src/main/kotlin/de/skyrising/mc/scanner/io.kt b/src/main/kotlin/de/skyrising/mc/scanner/io.kt index b09cbd3..2ec600c 100644 --- a/src/main/kotlin/de/skyrising/mc/scanner/io.kt +++ b/src/main/kotlin/de/skyrising/mc/scanner/io.kt @@ -65,7 +65,7 @@ class ByteBufferDataInput(private val buf: ByteBuffer) : DataInput { var count = start var char2: Int var char3: Int - var chararrCount = 0 + var chararrCount = start while (count < len) { val c = buf[pos + count].toInt() and 0xff when (c shr 4) { diff --git a/src/main/kotlin/de/skyrising/mc/scanner/needles.kt b/src/main/kotlin/de/skyrising/mc/scanner/needles.kt index 582b46b..a8b7130 100644 --- a/src/main/kotlin/de/skyrising/mc/scanner/needles.kt +++ b/src/main/kotlin/de/skyrising/mc/scanner/needles.kt @@ -123,13 +123,17 @@ data class BlockIdMask(val id: Int, val metaMask: Int, val blockState: BlockStat } } -data class ItemType(val id: Identifier, val damage: Int = -1, val flattened: Boolean = damage < 0) : Needle, Comparable { +data class ItemType(val id: Identifier, val damage: Int = -1, val flattened: Boolean = damage < 0, val tag: CompoundTag? = null) : Needle, Comparable { + fun withTag(newTag: CompoundTag? = null): ItemType { + return ItemType(id, damage, flattened, newTag) + } + fun flatten(): ItemType { if (this.flattened) return this var flattened = ITEM_MAP[this] if (flattened == null) flattened = ITEM_MAP[ItemType(id, 0)] - if (flattened == null) return ItemType(id, damage, true) - return ItemType(flattened, -1, true) + if (flattened == null) return ItemType(id, damage, true, tag) + return ItemType(flattened, -1, true, tag) } fun unflatten(): List { @@ -144,7 +148,7 @@ data class ItemType(val id: Identifier, val damage: Int = -1, val flattened: Boo } override fun toString(): String { - return "ItemType(${format()})" + return "ItemType(${format()})${tag?.value?:""}" } fun format() = if (damage < 0 || (flattened && damage == 0)) "$id" else "$id.$damage" @@ -152,6 +156,8 @@ data class ItemType(val id: Identifier, val damage: Int = -1, val flattened: Boo override fun compareTo(other: ItemType): Int { val idComp = id.compareTo(other.id) if (idComp != 0) return idComp + val tagComp = tag.toString().compareTo(other.tag.toString()) + if (tagComp != 0) return tagComp return damage.compareTo(other.damage) } diff --git a/src/main/kotlin/de/skyrising/mc/scanner/region.kt b/src/main/kotlin/de/skyrising/mc/scanner/region.kt index e3283ff..a88cfb5 100644 --- a/src/main/kotlin/de/skyrising/mc/scanner/region.kt +++ b/src/main/kotlin/de/skyrising/mc/scanner/region.kt @@ -147,7 +147,7 @@ private fun scanChunkItems(version: Int, data: CompoundTag, itemNeedles: Set= DataVersion.REMOVE_LEVEL_TAG) "entities" else "Entities" +for (entitiesTag in listOf("entities", "Entities")) { if (data.has(entitiesTag, Tag.LIST)) { for (entity in data.getList(entitiesTag)) { val id = entity.getString("id") @@ -167,6 +167,7 @@ private fun scanChunkItems(version: Int, data: CompoundTag, itemNeedles: Set, blockStates: LongArray, paletteSize: Int, packed: Boolean): Object2IntMap { val counts = Object2IntOpenHashMap() diff --git a/src/main/kotlin/de/skyrising/mc/scanner/scanner.kt b/src/main/kotlin/de/skyrising/mc/scanner/scanner.kt index aae2188..65a60da 100644 --- a/src/main/kotlin/de/skyrising/mc/scanner/scanner.kt +++ b/src/main/kotlin/de/skyrising/mc/scanner/scanner.kt @@ -6,7 +6,7 @@ import it.unimi.dsi.fastutil.objects.* import joptsimple.OptionException import joptsimple.OptionParser import joptsimple.ValueConverter -import java.io.PrintStream +import java.io.InputStream import java.net.URI import java.nio.file.* import java.util.* @@ -15,7 +15,6 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicLong -import java.util.function.ToIntFunction import kotlin.script.experimental.api.* import kotlin.script.experimental.host.toScriptSource import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost @@ -47,7 +46,7 @@ fun main(args: Array) { val path: Path val outPath: Path val zip: FileSystem? - val script: Path + val script: InputStream try { val options = parser.parse(*args) if (options.has(helpArg)) { @@ -77,7 +76,7 @@ fun main(args: Array) { script = when { options.has(statsArg) -> builtinScript("stats") options.has(geode) -> builtinScript("geode") - paths.isNotEmpty() && paths[0].endsWith(".scan.kts") -> Paths.get(paths.removeAt(0)) + paths.isNotEmpty() && paths[0].endsWith(".scan.kts") -> Paths.get(paths.removeAt(0)).toFile().inputStream() else -> builtinScript("search") } if (paths.size > 2 || paths.isEmpty()) throw IllegalArgumentException("Expected 1 or 2 paths") @@ -144,7 +143,8 @@ fun getHaystack(path: Path): Set { for (dim in listOf(".", "DIM-1", "DIM1")) { val dimPath = path.resolve(dim) if (!Files.exists(dimPath)) continue - val dimRegionPath = dimPath.resolve("region") +for (subdir in listOf("region", "entities")) { + val dimRegionPath = dimPath.resolve(subdir) if (!Files.exists(dimRegionPath)) continue Files.list(dimRegionPath).forEach { if (it.fileName.toString().endsWith(".mca")) { @@ -154,24 +154,26 @@ fun getHaystack(path: Path): Set { e.printStackTrace() } } +} } } return haystack } -fun builtinScript(name: String): Path { - val url = ScannerScript::class.java.getResource("/scripts/$name.scan.kts") - return Paths.get(url?.toURI() ?: throw IllegalArgumentException("Script not found: $name")) +fun builtinScript(name: String): InputStream { + val stream = ScannerScript::class.java.getResourceAsStream("/scripts/$name.scan.kts") + ?: throw IllegalArgumentException("Script not found: $name") + return stream } -fun evalScript(path: Path, scan: Scan): ResultWithDiagnostics { - val source = Files.readAllBytes(path).toString(Charsets.UTF_8).toScriptSource(path.fileName.toString()) +fun evalScript(stream: InputStream, scan: Scan): ResultWithDiagnostics { + val source = stream.reader().readText().toScriptSource() return BasicJvmScriptingHost().evalWithTemplate(source, evaluation = { constructorArgs(scan) }) } -fun runScript(path: Path, outPath: Path, executor: ExecutorService, needles: List, script: Path) { +fun runScript(path: Path, outPath: Path, executor: ExecutorService, needles: List, script: InputStream) { val scan = Scan(outPath, needles) evalScript(script, scan).valueOrThrow() val haystack = getHaystack(path).filterTo(mutableSetOf(), scan.haystackPredicate)