Skip to content

Commit e9baf54

Browse files
P529P529
andauthored
Initial commit kekw (#312)
Co-authored-by: P529 <thep529@live.de>
1 parent ac3baee commit e9baf54

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.lambda.client.module.modules.misc
2+
3+
import com.lambda.client.event.SafeClientEvent
4+
import com.lambda.client.module.Category
5+
import com.lambda.client.module.Module
6+
import com.lambda.client.util.TickTimer
7+
import com.lambda.client.util.TimeUnit
8+
import com.lambda.client.util.text.MessageSendHelper
9+
import com.lambda.client.util.threads.defaultScope
10+
import com.lambda.client.util.threads.runSafe
11+
import com.lambda.client.util.threads.safeListener
12+
import kotlinx.coroutines.launch
13+
import net.minecraft.block.material.MapColor
14+
import net.minecraft.entity.item.EntityItemFrame
15+
import net.minecraft.init.Items
16+
import net.minecraft.item.ItemMap
17+
import net.minecraft.world.storage.MapData
18+
import net.minecraftforge.fml.common.gameevent.TickEvent
19+
import java.awt.Color
20+
import java.awt.RenderingHints
21+
import java.awt.image.BufferedImage
22+
import java.io.File
23+
import java.io.IOException
24+
import java.security.MessageDigest
25+
import javax.imageio.ImageIO
26+
27+
internal object MapDownloader : Module(
28+
name = "Map Downloader",
29+
category = Category.MISC,
30+
description = "Downloads maps in item frames in your render distance to file."
31+
) {
32+
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)
35+
private val pendingHashes = mutableSetOf<String>()
36+
private var existingHashes = mutableSetOf<String>()
37+
private var pendingTasks = mutableSetOf<Triple<MapData, String, Int>>()
38+
private val mapPath = "mapImages${File.separator}"
39+
private val secTimer = TickTimer(TimeUnit.SECONDS)
40+
private val milliSecTimer = TickTimer(TimeUnit.MILLISECONDS)
41+
42+
init {
43+
val directory = File(mapPath)
44+
if (!directory.exists()) {
45+
directory.mkdir()
46+
}
47+
48+
existingHashes = getExistingHashes()
49+
50+
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+
}
60+
}
61+
pendingTasks.remove(triple)
62+
}
63+
}
64+
65+
getMaps()
66+
}
67+
}
68+
}
69+
70+
private fun getExistingHashes(): MutableSet<String> {
71+
val alreadyConverted = mutableSetOf<String>()
72+
73+
File(mapPath).walk().filter {
74+
it.name.endsWith(".png")
75+
}.forEach { file ->
76+
val nameArr = file.name.split("_")
77+
if (nameArr.isNotEmpty()) {
78+
alreadyConverted.add(nameArr[0])
79+
}
80+
}
81+
return alreadyConverted
82+
}
83+
84+
private fun mapColor(byteColor: UByte): Color {
85+
val color = MapColor.COLORS[(byteColor / 4u).toInt()]
86+
return if (color == MapColor.AIR) {
87+
Color(0,0,0,0)
88+
} else {
89+
Color(color.getMapColor((byteColor % 4u).toInt()))
90+
}
91+
}
92+
93+
private fun SafeClientEvent.getMaps() {
94+
world.loadedEntityList
95+
.filterIsInstance<EntityItemFrame>()
96+
.filter { it.displayedItem.item == Items.FILLED_MAP }
97+
.forEach {
98+
(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()
101+
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+
}
110+
}
111+
}
112+
}
113+
114+
private fun SafeClientEvent.renderAndSaveMapImage(mapData: MapData, hash: String, mapID: Int) {
115+
val finalSize = 128 * scale
116+
117+
var countPos = 0
118+
val img = BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB)
119+
val g1 = img.createGraphics()
120+
121+
g1.background = Color(0, 0, 0, 0)
122+
123+
repeat(128) { i ->
124+
repeat(128) { j ->
125+
mapData.colors[countPos].toUByte().let { mapColor(it).let { it1 -> img.setRGB(j, i, it1.rgb) } }
126+
countPos++
127+
}
128+
}
129+
130+
try {
131+
val resized = BufferedImage(finalSize, finalSize, img.type)
132+
val g = resized.createGraphics()
133+
val loc = "${mapPath}${hash}_id_${mapID}_server_${player.connection.networkManager.remoteAddress.toString().split('/')[0]?:"local"}.png"
134+
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
135+
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)
136+
g.drawImage(img, 0, 0, finalSize, finalSize, 0, 0, img.width,
137+
img.height, null)
138+
g.dispose()
139+
ImageIO.write(resized, "png", File(loc))
140+
} catch (ex: IOException) {
141+
ex.printStackTrace()
142+
}
143+
144+
pendingHashes.remove(hash)
145+
existingHashes.add(hash)
146+
}
147+
148+
private fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte -> "%02x".format(eachByte) }
149+
}

0 commit comments

Comments
 (0)