Skip to content

Commit c359e55

Browse files
committed
Download maps from inventory too and folder name convention
1 parent e6ad3b4 commit c359e55

File tree

4 files changed

+95
-95
lines changed

4 files changed

+95
-95
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.lambda.client.module.modules.misc
22

3+
import com.lambda.client.LambdaMod
34
import com.lambda.client.event.SafeClientEvent
45
import com.lambda.client.module.Category
56
import com.lambda.client.module.Module
7+
import com.lambda.client.util.FolderUtils
68
import com.lambda.client.util.TickTimer
79
import com.lambda.client.util.TimeUnit
10+
import com.lambda.client.util.items.inventorySlots
811
import com.lambda.client.util.text.MessageSendHelper
912
import com.lambda.client.util.threads.defaultScope
1013
import com.lambda.client.util.threads.runSafe
@@ -25,59 +28,73 @@ import java.security.MessageDigest
2528
import javax.imageio.ImageIO
2629

2730
internal object MapDownloader : Module(
28-
name = "Map Downloader",
31+
name = "MapDownloader",
2932
category = Category.MISC,
3033
description = "Downloads maps in item frames in your render distance to file."
3134
) {
3235

33-
private var scale by setting("Scale", 1, 1..20, 1)
34-
private var saveDelay by setting("Save delay", 0.2, 0.1..2.0, 0.1)
36+
private val scale by setting("Scale", 1, 1..20, 1, description = "Higher scale results in higher storage use!")
37+
private val saveMapsFromEntity by setting("Save maps from entity", true)
38+
private val saveMapsFromInventory by setting("Save maps from inventory", true, description = "When rendering a new map it will save one image for every map update!")
39+
private val saveDelay by setting("Save delay", 0.2, 0.1..2.0, 0.1, unit = " s")
40+
private val openImageFolder = setting("Open Image Folder...", false)
3541
private val pendingHashes = mutableSetOf<String>()
3642
private var existingHashes = mutableSetOf<String>()
37-
private var pendingTasks = mutableSetOf<Triple<MapData, String, Int>>()
38-
private val mapPath = "mapImages${File.separator}"
43+
private var pendingTasks = mutableSetOf<MapInfo>()
3944
private val secTimer = TickTimer(TimeUnit.SECONDS)
4045
private val milliSecTimer = TickTimer(TimeUnit.MILLISECONDS)
4146

4247
init {
43-
val directory = File(mapPath)
44-
if (!directory.exists()) {
45-
directory.mkdir()
46-
}
47-
4848
existingHashes = getExistingHashes()
4949

5050
safeListener<TickEvent.ClientTickEvent> {
51-
if (it.phase == TickEvent.Phase.START) {
52-
if (secTimer.tick(10)) existingHashes = getExistingHashes()
53-
if (pendingTasks.isNotEmpty()
54-
&& milliSecTimer.tick((saveDelay * 1000).toInt())) {
55-
pendingTasks.firstOrNull()?.let { triple ->
56-
defaultScope.launch {
57-
runSafe {
58-
renderAndSaveMapImage(triple.first, triple.second, triple.third)
59-
}
51+
if (it.phase != TickEvent.Phase.START) return@safeListener
52+
53+
if (secTimer.tick(10)) existingHashes = getExistingHashes()
54+
55+
if (pendingTasks.isNotEmpty()
56+
&& milliSecTimer.tick((saveDelay * 1000).toInt())
57+
) {
58+
val directory = File(FolderUtils.mapImagesFolder)
59+
if (!directory.exists()) {
60+
directory.mkdir()
61+
}
62+
63+
pendingTasks.firstOrNull()?.let { mapInfo ->
64+
defaultScope.launch {
65+
runSafe {
66+
renderAndSaveMapImage(mapInfo)
67+
LambdaMod.LOG.info("Saved map - name: ${mapInfo.name} id: ${mapInfo.id}")
6068
}
61-
pendingTasks.remove(triple)
6269
}
70+
pendingTasks.remove(mapInfo)
6371
}
64-
65-
getMaps()
6672
}
73+
74+
getMaps()
75+
}
76+
77+
openImageFolder.consumers.add { _, it ->
78+
if (it) FolderUtils.openFolder(FolderUtils.mapImagesFolder)
79+
false
6780
}
6881
}
6982

7083
private fun getExistingHashes(): MutableSet<String> {
7184
val alreadyConverted = mutableSetOf<String>()
7285

73-
File(mapPath).walk().filter {
86+
File(FolderUtils.mapImagesFolder).walk().filter {
7487
it.name.endsWith(".png")
7588
}.forEach { file ->
7689
val nameArr = file.name.split("_")
7790
if (nameArr.isNotEmpty()) {
7891
alreadyConverted.add(nameArr[0])
7992
}
8093
}
94+
95+
// to exclude the empty map
96+
alreadyConverted.add("ce338fe6899778aacfc28414f2d9498b")
97+
8198
return alreadyConverted
8299
}
83100

@@ -91,27 +108,39 @@ internal object MapDownloader : Module(
91108
}
92109

93110
private fun SafeClientEvent.getMaps() {
94-
world.loadedEntityList
111+
if (saveMapsFromEntity) world.loadedEntityList
95112
.filterIsInstance<EntityItemFrame>()
96113
.filter { it.displayedItem.item == Items.FILLED_MAP }
97114
.forEach {
98115
(it.displayedItem.item as ItemMap).getMapData(it.displayedItem, world)?.let { mapData ->
99-
MessageDigest.getInstance("MD5")?.let { md ->
100-
val hash = md.digest(mapData.colors).toHex()
116+
handleMap(mapData, it.displayedItem.displayName, it.displayedItem.itemDamage)
117+
}
118+
}
101119

102-
if (!existingHashes.contains(hash) && !pendingHashes.contains(hash)) {
103-
pendingHashes.add(hash)
104-
pendingTasks.add(Triple(mapData, hash, it.displayedItem.itemDamage))
105-
}
106-
} ?: run {
107-
MessageSendHelper.sendChatMessage("$chatName Can't find MD5 instance.")
108-
disable()
109-
}
120+
if (saveMapsFromInventory) player.inventorySlots.forEach {
121+
if (it.stack.item is ItemMap) {
122+
(it.stack.item as ItemMap).getMapData(it.stack, world)?.let { mapData ->
123+
handleMap(mapData, it.stack.displayName, it.stack.itemDamage)
110124
}
111125
}
126+
}
127+
}
128+
129+
private fun handleMap(data: MapData, name: String, id: Int) {
130+
MessageDigest.getInstance("MD5")?.let { md ->
131+
val hash = md.digest(data.colors).toHex()
132+
133+
if (!existingHashes.contains(hash) && !pendingHashes.contains(hash)) {
134+
pendingHashes.add(hash)
135+
pendingTasks.add(MapInfo(data, name, id, hash))
136+
}
137+
} ?: run {
138+
MessageSendHelper.sendChatMessage("$chatName Can't find MD5 instance.")
139+
disable()
140+
}
112141
}
113142

114-
private fun SafeClientEvent.renderAndSaveMapImage(mapData: MapData, hash: String, mapID: Int) {
143+
private fun SafeClientEvent.renderAndSaveMapImage(mapInfo: MapInfo) {
115144
val finalSize = 128 * scale
116145

117146
var countPos = 0
@@ -122,15 +151,17 @@ internal object MapDownloader : Module(
122151

123152
repeat(128) { i ->
124153
repeat(128) { j ->
125-
mapData.colors[countPos].toUByte().let { mapColor(it).let { it1 -> img.setRGB(j, i, it1.rgb) } }
154+
mapInfo.data.colors[countPos].toUByte().let {
155+
mapColor(it).let { color -> img.setRGB(j, i, color.rgb) }
156+
}
126157
countPos++
127158
}
128159
}
129160

130161
try {
131162
val resized = BufferedImage(finalSize, finalSize, img.type)
132163
val g = resized.createGraphics()
133-
val loc = "${mapPath}${hash}_id_${mapID}_server_${player.connection.networkManager.remoteAddress.toString().split('/')[0]?:"local"}.png"
164+
val loc = "${FolderUtils.mapImagesFolder}${mapInfo.hash}_name_${mapInfo.name.replace(File.separator, "")}_id_${mapInfo.id}_${if (mc.isIntegratedServerRunning) "local" else "server_${player.connection.networkManager.remoteAddress.toString().replace("/", "_").replace(":", "_")}"}.png"
134165
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
135166
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)
136167
g.drawImage(img, 0, 0, finalSize, finalSize, 0, 0, img.width,
@@ -141,9 +172,11 @@ internal object MapDownloader : Module(
141172
ex.printStackTrace()
142173
}
143174

144-
pendingHashes.remove(hash)
145-
existingHashes.add(hash)
175+
pendingHashes.remove(mapInfo.hash)
176+
existingHashes.add(mapInfo.hash)
146177
}
147178

148179
private fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte -> "%02x".format(eachByte) }
180+
181+
data class MapInfo(val data: MapData, val name: String, val id: Int, val hash: String)
149182
}

src/main/kotlin/com/lambda/client/module/modules/player/PacketLogger.kt

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.lambda.client.event.listener.listener
88
import com.lambda.client.mixin.extension.*
99
import com.lambda.client.module.Category
1010
import com.lambda.client.module.Module
11+
import com.lambda.client.module.modules.misc.MapDownloader.setting
1112
import com.lambda.client.util.FolderUtils
1213
import com.lambda.client.util.TickTimer
1314
import com.lambda.client.util.TimeUnit
@@ -42,6 +43,7 @@ object PacketLogger : Module(
4243
private val ignoreUnknown by setting("Ignore Unknown Packets", false, description = "Ignore packets that aren't explicitly handled.")
4344
private val ignoreChat by setting("Ignore Chat", true, description = "Ignore chat packets.")
4445
private val ignoreCancelled by setting("Ignore Cancelled", true, description = "Ignore cancelled packets.")
46+
private val openLogFolder = setting("Open Log Folder...", false)
4547

4648
private val fileTimeFormatter = DateTimeFormatter.ofPattern("HH-mm-ss_SSS")
4749

@@ -133,6 +135,11 @@ object PacketLogger : Module(
133135

134136
sendPacket(it.packet)
135137
}
138+
139+
openLogFolder.consumers.add { _, it ->
140+
if (it) FolderUtils.openFolder(FolderUtils.logFolder)
141+
false
142+
}
136143
}
137144

138145
private fun receivePacket(packet: Packet<*>) {

src/main/kotlin/com/lambda/client/module/modules/render/NewChunks.kt

+11-55
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ object NewChunks : Module(
5050
private val saveOption by setting("Save Option", SaveOption.EXTRA_FOLDER, { saveNewChunks })
5151
private val saveInRegionFolder by setting("In Region", false, { saveNewChunks })
5252
private val alsoSaveNormalCoords by setting("Save Normal Coords", false, { saveNewChunks })
53-
private val closeFile = setting("CloseFile", false, { saveNewChunks })
53+
private val closeFile = setting("Close file", false, { saveNewChunks })
54+
private val openNewChunksFolder = setting("Open NewChunks Folder...", false, { saveNewChunks })
5455
private val yOffset by setting("Y Offset", 0, -256..256, 4, fineStep = 1, description = "Render offset in Y axis")
5556
private val color by setting("Color", ColorHolder(255, 64, 64, 200), description = "Highlighting color")
5657
private val thickness by setting("Thickness", 1.5f, 0.1f..4.0f, 0.1f, description = "Thickness of the highlighting square")
@@ -249,7 +250,8 @@ object NewChunks : Module(
249250
if (saveInRegionFolder) {
250251
file = File(file, "region")
251252
}
252-
file = File(file, "newChunkLogs")
253+
254+
file = File(file, "logs")
253255
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(Date())
254256
file = File(file, mc.session.username + "_" + date + ".csv") // maybe don't safe the name, actually. But I also don't want to make another option...
255257
val filePath = file.toPath()
@@ -284,45 +286,10 @@ object NewChunks : Module(
284286
rV = File(rV, "saves")
285287
rV = File(rV, folderName)
286288
}
287-
SaveOption.NHACK_WDL -> {
288-
folderName = nHackInetName
289-
rV = File(rV, "config")
290-
rV = File(rV, "wdl-saves")
291-
rV = File(rV, folderName)
292-
293-
// extra because name might be different
294-
if (!rV.exists()) {
295-
MessageSendHelper.sendWarningMessage("$chatName nhack wdl directory doesnt exist: $folderName")
296-
MessageSendHelper.sendWarningMessage("$chatName creating the directory now. It is recommended to update the ip")
297-
}
298-
}
299289
}
300290
return rV.toPath()
301291
}
302292

303-
// if there is no port then we have to manually include the standard port..
304-
private val nHackInetName: String
305-
get() {
306-
var folderName = mc.currentServerData?.serverIP ?: "Offline"
307-
if (SystemUtils.IS_OS_WINDOWS) {
308-
folderName = folderName.replace(":", "_")
309-
}
310-
if (hasNoPort(folderName)) {
311-
folderName += "_25565" // if there is no port then we have to manually include the standard port..
312-
}
313-
return folderName
314-
}
315-
316-
private fun hasNoPort(ip: String): Boolean {
317-
if (!ip.contains("_")) {
318-
return true
319-
}
320-
val sp = ip.split("_").toTypedArray()
321-
val ending = sp[sp.size - 1]
322-
// if it is numeric it means it might be a port...
323-
return ending.toIntOrNull() != null
324-
}
325-
326293
// p2.x > p1.x and p2.y > p1.y is assumed
327294
private fun isSquareInRadius(p1: Vec2d, p2: Vec2d, radius: Float): Boolean {
328295
val x = if (p1.x + p2.x > 0) p2.x else p1.x
@@ -334,28 +301,12 @@ object NewChunks : Module(
334301
return Vec2d((x shl 4).toDouble(), (z shl 4).toDouble()).minus(playerOffset).div(scale.toDouble())
335302
}
336303

337-
fun getChunks(): ConcurrentHashMap<ChunkPos, Long> {
338-
return chunks
339-
}
340-
341-
fun addChunk(chunk: ChunkPos) {
342-
chunks[chunk] = System.currentTimeMillis()
343-
}
344-
345-
fun addChunk(chunk: ChunkPos, time: Long) {
346-
chunks[chunk] = time
347-
}
348-
349-
fun removeChunk(chunk: ChunkPos) {
350-
chunks.remove(chunk)
351-
}
352-
353304
private fun saveNewChunk(log: PrintWriter?, data: String) {
354305
log!!.println(data)
355306
}
356307

357308
private enum class SaveOption {
358-
EXTRA_FOLDER, LITE_LOADER_WDL, NHACK_WDL
309+
EXTRA_FOLDER, LITE_LOADER_WDL
359310
}
360311

361312
@Suppress("unused")
@@ -375,7 +326,7 @@ object NewChunks : Module(
375326
var ip: String? = null
376327
fun testChangeAndUpdate(event: SafeClientEvent): Boolean {
377328
if (testChange(event)) {
378-
// so we dont have to do this process again next time
329+
// so we don't have to do this process again next time
379330
update(event)
380331
return true
381332
}
@@ -409,5 +360,10 @@ object NewChunks : Module(
409360
closeFile.value = false
410361
}
411362
}
363+
364+
openNewChunksFolder.consumers.add { _, it ->
365+
if (it) FolderUtils.openFolder(FolderUtils.newChunksFolder)
366+
false
367+
}
412368
}
413369
}

src/main/kotlin/com/lambda/client/util/FolderUtils.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ object FolderUtils {
4444

4545
@JvmStatic
4646
val newChunksFolder
47-
get() = "${lambdaFolder}newChunks${File.separator}"
47+
get() = "${lambdaFolder}new-chunks${File.separator}"
48+
49+
@JvmStatic
50+
val mapImagesFolder
51+
get() = "${lambdaFolder}map-images${File.separator}"
4852

4953
/**
5054
* Opens the given path using the right library based on OS

0 commit comments

Comments
 (0)