@@ -27,6 +27,7 @@ import org.bukkit.plugin.java.JavaPlugin
2727import org.bukkit.util.Vector
2828import java.io.File
2929import java.util.UUID
30+ import java.util.concurrent.ConcurrentHashMap
3031import java.util.concurrent.Executors
3132import java.util.concurrent.atomic.AtomicLong
3233import kotlin.math.ceil
@@ -488,7 +489,7 @@ class LifeCoreUtilCommand(val plugin: LifeCore) : TabExecutor {
488489 override fun execute (plugin : LifeCore , player : CommandSender , args : Array <String >) {
489490 player as Player
490491 if (tempChunkProcessingStats != null ) {
491- player.sendMessage(" ${ChatColor .RED } すでにスキャン中です。" )
492+ player.sendMessage(" ${ChatColor .RED } すでにスキャン中です。( ${tempChunkProcessingStats?.second?.get()} / ${tempChunkProcessingStats?.first} ) " )
492493 return
493494 }
494495 if (args.isEmpty()) {
@@ -500,35 +501,45 @@ class LifeCoreUtilCommand(val plugin: LifeCore) : TabExecutor {
500501 return
501502 }
502503 if (world.loadedChunks.size != 0 ) {
503- player.sendMessage(" ${ChatColor .RED } チャンクが読み込まれているため、処理できません" )
504- return
504+ player.sendMessage(" ${ChatColor .RED } 警告:1個以上のチャンクが読み込まれています。" )
505505 }
506- val worldName = player. world.name
507- val regionContainer = File (Bukkit .getWorldContainer(), " ${player. world.name} /region" )
508- val referenceRegionContainer = File (Bukkit .getWorldContainer(), " ${player. world.name} /region.backup_exclude" )
509- val newRegionContainer = File (Bukkit .getWorldContainer(), " ${player. world.name} /region-new.backup_exclude" )
506+ val worldName = world.name
507+ val regionContainer = File (Bukkit .getWorldContainer(), " ${world.name} /region" )
508+ val referenceRegionContainer = File (Bukkit .getWorldContainer(), " ${world.name} /region.backup_exclude" )
509+ val newRegionContainer = File (Bukkit .getWorldContainer(), " ${world.name} /region-new.backup_exclude" )
510510 val chunkLocations = mutableListOf<ChunkCoordIntPair >()
511511 val regex = Regex (" ^r.(-?\\ d+).(-?\\ d+).mca$" )
512- regionContainer.listFiles()!! .forEach { file ->
513- try {
514- val groups = regex.find(file.name)?.groupValues ? : return @forEach
515- val regionX = groups[1 ].toInt()
516- val regionZ = groups[2 ].toInt()
517- for (x in 0 .. 31 ) {
518- for (z in 0 .. 31 ) {
519- val chunkX = regionX * 32 + x
520- val chunkZ = regionZ * 32 + z
521- chunkLocations.add(ChunkCoordIntPair (chunkX, chunkZ))
512+ if (args.getOrNull(1 ) == " here" ) {
513+ chunkLocations.add(ChunkCoordIntPair (player.location.chunk.x, player.location.chunk.z))
514+ } else {
515+ regionContainer.listFiles()!! .forEach { file ->
516+ try {
517+ val groups = regex.find(file.name)?.groupValues ? : return @forEach
518+ val regionX = groups[1 ].toInt()
519+ val regionZ = groups[2 ].toInt()
520+ for (x in 0 .. 31 ) {
521+ for (z in 0 .. 31 ) {
522+ val chunkX = regionX * 32 + x
523+ val chunkZ = regionZ * 32 + z
524+ chunkLocations.add(ChunkCoordIntPair (chunkX, chunkZ))
525+ }
522526 }
527+ } catch (_: Exception ) {
523528 }
524- } catch (_ : Exception ) {}
529+ }
525530 }
526531 val mapCount = AtomicLong (0 )
527532 val count = AtomicLong (0 )
528533 val ignoredChunks = AtomicLong (0 )
529534 tempChunkProcessingStats = Pair (chunkLocations.size.toLong(), count)
530535 val regionFileCacheConstructor = RegionFileCache ::class .java.getDeclaredConstructor(File ::class .java).apply { isAccessible = true }
531536 val regionFileCacheWrite = RegionFileCache ::class .java.getDeclaredMethod(" write" , ChunkCoordIntPair ::class .java, NBTTagCompound ::class .java).apply { isAccessible = true }
537+ val newCache = regionFileCacheConstructor.newInstance(newRegionContainer)
538+ fun write (coord : ChunkCoordIntPair , tag : NBTTagCompound ) {
539+ synchronized(newCache) {
540+ regionFileCacheWrite.invoke(newCache, coord, tag)
541+ }
542+ }
532543 player.sendMessage(" ${ChatColor .GREEN }${chunkLocations.size} 個のチャンクをスキャン中です。" )
533544 JavaPlugin .getPlugin(LifeCore ::class .java).logger.info(" Starting scan of $worldName (${chunkLocations.size} chunks) using up to ${Runtime .getRuntime().availableProcessors()} threads" )
534545 Bukkit .getScheduler().runTaskAsynchronously(JavaPlugin .getPlugin(LifeCore ::class .java), Runnable {
@@ -537,67 +548,65 @@ class LifeCoreUtilCommand(val plugin: LifeCore) : TabExecutor {
537548 chunkScannerExecutor.submit {
538549 regionFileCacheConstructor.newInstance(regionContainer).use { cache ->
539550 regionFileCacheConstructor.newInstance(referenceRegionContainer).use { referenceCache ->
540- regionFileCacheConstructor.newInstance(newRegionContainer).use { newCache ->
541- chunksToProcess.forEach { pair ->
542- if (Thread .currentThread().isInterrupted) {
543- return @forEach
544- }
545- try {
546- val pair = ChunkCoordIntPair (pair.x, pair.z)
547- val nbt = cache.read(pair)
548- ? : run {
549- ignoredChunks.incrementAndGet()
550- return @forEach
551- }
552- val root = nbt.getCompound(" Level" )
553- val entitiesTag = root.getList(" Entities" , 10 )
554- if (entitiesTag.isEmpty()) {
551+ chunksToProcess.forEach { pair ->
552+ if (Thread .currentThread().isInterrupted) {
553+ return @forEach
554+ }
555+ try {
556+ val pair = ChunkCoordIntPair (pair.x, pair.z)
557+ val nbt = cache.read(pair)
558+ ? : run {
555559 ignoredChunks.incrementAndGet()
556560 return @forEach
557561 }
558- val referenceNbt = referenceCache.read(pair )
559- ? : run {
560- ignoredChunks.incrementAndGet()
561- return @forEach
562- }
563- val referenceRoot = referenceNbt.getCompound( " Level " )
564- val referenceEntitiesTag = referenceRoot.getList( " Entities " , 10 )
565- if (referenceEntitiesTag.isEmpty()) {
562+ val root = nbt.getCompound( " Level " )
563+ val entitiesTag = root.getList( " Entities " , 10 )
564+ if (entitiesTag.isEmpty()) {
565+ ignoredChunks.incrementAndGet()
566+ return @forEach
567+ }
568+ val referenceNbt = referenceCache.read(pair )
569+ ? : run {
566570 ignoredChunks.incrementAndGet()
567571 return @forEach
568572 }
569- val refEntitiesMap =
570- referenceEntitiesTag.map { it as NBTTagCompound }
571- .associate e@{ entityTag ->
572- val uuidMost = entityTag.getLong(" UUIDMost" )
573- val uuidLeast = entityTag.getLong(" UUIDLeast" )
574- val uuid = UUID (uuidMost, uuidLeast)
575- Pair (uuid, entityTag)
576- }
577- // process entities
578- entitiesTag.map { it as NBTTagCompound }.forEach e@{ entityTag ->
579- if (entityTag.getString(" id" ) != " minecraft:item_frame" ) {
580- return @e
581- }
582- val itemTag = entityTag.getCompound(" Item" )
583- if (itemTag.getString(" id" ) != " minecraft:filled_map" ) {
584- return @e
573+ val referenceRoot = referenceNbt.getCompound(" Level" )
574+ val referenceEntitiesTag = referenceRoot.getList(" Entities" , 10 )
575+ if (referenceEntitiesTag.isEmpty()) {
576+ ignoredChunks.incrementAndGet()
577+ return @forEach
578+ }
579+ val refEntitiesMap =
580+ referenceEntitiesTag.map { it as NBTTagCompound }
581+ .associate e@{ entityTag ->
582+ val uuidMost = entityTag.getLong(" UUIDMost" )
583+ val uuidLeast = entityTag.getLong(" UUIDLeast" )
584+ val uuid = UUID (uuidMost, uuidLeast)
585+ Pair (uuid, entityTag)
585586 }
586- val uuidMost = entityTag.getLong(" UUIDMost" )
587- val uuidLeast = entityTag.getLong(" UUIDLeast" )
588- val uuid = UUID (uuidMost, uuidLeast)
589- val refEntity = refEntitiesMap[uuid] ? : return @e
590- entityTag.set(" Item" , refEntity.getCompound(" Item" ))
591- mapCount.incrementAndGet()
587+ // process entities
588+ entitiesTag.map { it as NBTTagCompound }.forEach e@{ entityTag ->
589+ if (entityTag.getString(" id" ) != " minecraft:item_frame" ) {
590+ return @e
591+ }
592+ val itemTag = entityTag.getCompound(" Item" )
593+ if (itemTag.getString(" id" ) != " minecraft:filled_map" ) {
594+ return @e
592595 }
593- // save chunk
594- regionFileCacheWrite.invoke(newCache, pair, nbt)
595- } catch (e: Exception ) {
596- JavaPlugin .getPlugin(LifeCore ::class .java).logger.severe(" Failed to scan chunk ${pair.x} , ${pair.z} " )
597- e.printStackTrace()
598- } finally {
599- count.incrementAndGet()
596+ val uuidMost = entityTag.getLong(" UUIDMost" )
597+ val uuidLeast = entityTag.getLong(" UUIDLeast" )
598+ val uuid = UUID (uuidMost, uuidLeast)
599+ val refEntity = refEntitiesMap[uuid] ? : return @e
600+ entityTag.set(" Item" , refEntity.getCompound(" Item" ))
601+ mapCount.incrementAndGet()
600602 }
603+ // save chunk
604+ write(pair, nbt)
605+ } catch (e: Exception ) {
606+ JavaPlugin .getPlugin(LifeCore ::class .java).logger.severe(" Failed to scan chunk ${pair.x} , ${pair.z} " )
607+ e.printStackTrace()
608+ } finally {
609+ count.incrementAndGet()
601610 }
602611 }
603612 }
0 commit comments