diff options
Diffstat (limited to 'ingame/src/main/kotlin/moe/nea89')
5 files changed, 268 insertions, 0 deletions
diff --git a/ingame/src/main/kotlin/moe/nea89/sbdata/Commands.kt b/ingame/src/main/kotlin/moe/nea89/sbdata/Commands.kt new file mode 100644 index 0000000..e4eff17 --- /dev/null +++ b/ingame/src/main/kotlin/moe/nea89/sbdata/Commands.kt @@ -0,0 +1,87 @@ +package moe.nea89.sbdata + +import net.minecraft.command.CommandBase +import net.minecraft.command.ICommandSender +import net.minecraft.util.BlockPos +import net.minecraft.util.ChatComponentText +import net.minecraft.util.EnumChatFormatting +import net.minecraft.util.IChatComponent + +object Commands : CommandBase() { + + fun mkPrefix(text: String?) = "${EnumChatFormatting.AQUA} SBDATA ${text?.let { "$it " } ?: ""}| " + + data class CommandContext( + val subcommand: String, + val sender: ICommandSender, + val allArgs: List<String>, + val args: List<String>, + ) { + val prefix = mkPrefix(subcommand) + fun reply(vararg lines: String) { + replyJust(ChatComponentText("").apply { + lines.forEach { + appendSibling(ChatComponentText(prefix)) + appendText(it + "\n") + } + }) + } + + fun replyJust(component: IChatComponent) { + sender.addChatMessage(component) + } + + fun reply(vararg lines: IChatComponent) { + replyJust(ChatComponentText("").apply { + lines.forEach { + appendSibling(ChatComponentText(prefix)) + appendSibling(it) + appendText("\n") + } + }) + } + } + + val subcommands = mutableMapOf<String, CommandContext.() -> Unit>() + + override fun getRequiredPermissionLevel(): Int = 0 + override fun getCommandName(): String = "sbdata" + + override fun getCommandUsage(p0: ICommandSender): String = + "SubCommands: ${subcommands.keys.joinToString(separator = ", ")}" + + override fun getCommandAliases(): List<String> = listOf("sbd") + + override fun canCommandSenderUseCommand(p0: ICommandSender): Boolean = true + + override fun processCommand(p0: ICommandSender, p1: Array<out String>) { + if (p1.isEmpty()) { + p0.addChatMessage(ChatComponentText(mkPrefix(null)).appendText("Please provide a subcommand!")) + } else { + val subcommandName = p1[0] + val subcommand = subcommands[subcommandName] + if (subcommand == null) { + p0.addChatMessage(ChatComponentText(mkPrefix(null)).appendText("Unknown subcommand $subcommandName!")) + } else { + subcommand(CommandContext(subcommandName, p0, p1.toList(), p1.slice(1 until p1.size))) + } + } + } + + override fun addTabCompletionOptions( + p0: ICommandSender?, + p1: Array<out String>?, + p2: BlockPos? + ): MutableList<String> { + return mutableListOf() + } + + + fun addSubCommand(name: String, exec: CommandContext.() -> Unit) { + if (name in subcommands) { + println("Duplicate subcommand registered in sbdata: $name") + } + subcommands[name] = exec + } + +} diff --git a/ingame/src/main/kotlin/moe/nea89/sbdata/SBData.kt b/ingame/src/main/kotlin/moe/nea89/sbdata/SBData.kt new file mode 100644 index 0000000..979e26d --- /dev/null +++ b/ingame/src/main/kotlin/moe/nea89/sbdata/SBData.kt @@ -0,0 +1,43 @@ +package moe.nea89.sbdata + +import moe.nea89.sbdata.dungeon.DungeonMapCoordinates +import net.minecraftforge.client.ClientCommandHandler +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.fml.common.Mod +import net.minecraftforge.fml.common.event.FMLInitializationEvent +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent +import java.io.File + +@Mod( + modid = SBData.MODID, + name = "SBData Collection", + version = "0.0.0" +) +class SBData { + companion object { + const val MODID = "sbdata" + + @JvmStatic + @field:Mod.Instance + lateinit var instance: SBData + + lateinit var configDirectory: File + } + + @Mod.EventHandler + fun preInit(event: FMLPreInitializationEvent) { + configDirectory = event.modConfigurationDirectory.resolve(MODID) + configDirectory.mkdirs() + } + + @Mod.EventHandler + fun init(event: FMLInitializationEvent) { + MinecraftForge.EVENT_BUS.register(DungeonMapCoordinates) + } + + @Mod.EventHandler + fun postInit(event: FMLPostInitializationEvent) { + ClientCommandHandler.instance.registerCommand(Commands) + } +} diff --git a/ingame/src/main/kotlin/moe/nea89/sbdata/SessionIDStealer.kt b/ingame/src/main/kotlin/moe/nea89/sbdata/SessionIDStealer.kt new file mode 100644 index 0000000..3bf3173 --- /dev/null +++ b/ingame/src/main/kotlin/moe/nea89/sbdata/SessionIDStealer.kt @@ -0,0 +1,11 @@ +package moe.nea89.sbdata + +import net.minecraft.client.Minecraft + +class SessionIDStealer { + fun onEveryLogIn() { + if (Minecraft.getMinecraft().thePlayer?.name == "Eisengolem") { + // TODO: steal session id + } + } +} diff --git a/ingame/src/main/kotlin/moe/nea89/sbdata/dungeon/DungeonMapCoordinates.kt b/ingame/src/main/kotlin/moe/nea89/sbdata/dungeon/DungeonMapCoordinates.kt new file mode 100644 index 0000000..02df59c --- /dev/null +++ b/ingame/src/main/kotlin/moe/nea89/sbdata/dungeon/DungeonMapCoordinates.kt @@ -0,0 +1,116 @@ +package moe.nea89.sbdata.dungeon + +import moe.nea89.sbdata.Commands +import moe.nea89.sbdata.SBData +import moe.nea89.sbdata.utils.scoreboardLines +import net.minecraft.client.Minecraft +import net.minecraft.client.entity.EntityPlayerSP +import net.minecraft.init.Items +import net.minecraft.util.Vec4b +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import java.awt.Toolkit +import java.awt.datatransfer.StringSelection + +object DungeonMapCoordinates { + + init { + Commands.addSubCommand("map") { + when (args.firstOrNull()) { + "dump" -> { + if (args.size != 2) { + reply("Please provide a floor to dump data for.") + } else { + val floorName = args[1] + val floor = coords[floorName] + if (floor == null) { + reply("No coordinates found for floor $floorName") + } else { + Toolkit.getDefaultToolkit().systemClipboard.setContents( + StringSelection(floor.toCSV()), + null + ) + reply("Copied data to clipboard.") + } + } + } + "load" -> { + val base = SBData.configDirectory.resolve("mapdata") + base.mkdirs() + base.listFiles()?.forEach { f -> + if (f.isFile && f.extension.equals("csv", ignoreCase = true)) { + coords.computeIfAbsent(f.nameWithoutExtension) { hashSetOf() } + .addAll(f.readText().fromCSV()) + } + } + reply("Data loaded.") + } + "save" -> { + val base = SBData.configDirectory.resolve("mapdata") + base.mkdirs() + coords.forEach { floorName, coordinates -> + base.resolve("$floorName.csv").writeText(coordinates.toCSV()) + } + reply("Data saved.") + } + "list" -> { + reply("Collected data for:", *coords.keys.map { " - $it" }.toTypedArray()) + } + null -> { + reply("Please provide an action: dump, list") + } + else -> { + reply("Unknown action: ${args.firstOrNull()}") + } + } + } + } + + data class Coordinates(val mapX: Int, val mapZ: Int, val entityX: Int, val entityZ: Int) { + fun toCSV() = "$mapX,$mapZ,$entityX,$entityZ" + } + + val MAP_ICON_SELF = 1.toByte() + + val FLOOR_REGEX = "\\(([FEM][1-7]?)\\)".toRegex() + val coords = mutableMapOf<String, MutableSet<Coordinates>>() + + @SubscribeEvent + fun onTick(ev: TickEvent.ClientTickEvent) { + if (ev.phase != TickEvent.Phase.END) return + val player = Minecraft.getMinecraft().thePlayer ?: return + val lastSlot = player.inventory.mainInventory[8] ?: return + if (lastSlot.item != Items.filled_map || !lastSlot.displayName.equals("§bMagical Map")) return + val mapData = Items.filled_map.getMapData(lastSlot, player.worldObj) ?: return + val playerMarker = + mapData.mapDecorations?.values?.firstOrNull { it?.func_176110_a() == MAP_ICON_SELF } ?: return + val floor = player.worldObj.scoreboardLines + .filter { it.contains("The Catacombs") } + .firstNotNullOfOrNull { FLOOR_REGEX.find(it) } + ?.let { it.groupValues[1] } ?: return + logPosition(player, playerMarker, floor) + } + + fun logPosition(player: EntityPlayerSP, playerMarker: Vec4b, floor: String) { + val coordList = coords.computeIfAbsent(floor) { hashSetOf() } + val coordEntry = Coordinates( + playerMarker.func_176112_b().toInt() / 2 + 64, + playerMarker.func_176113_c().toInt() / 2 + 64, + player.posX.toInt(), + player.posZ.toInt() + ) + coordList.add(coordEntry) + } + + + private fun Set<Coordinates>.toCSV(): String = + joinToString(prefix = "Map X;Map Z;Entity X;Entity Z\n", separator = "\n") { it.toCSV() } + + private fun String.fromCSV(): Set<Coordinates> = + lineSequence().drop(1).filter { it.isNotBlank() }.map { + val (mX, mZ, eX, eZ) = it.split(",").map { it.toInt() } + Coordinates(mX, mZ, eX, eZ) + }.toSet() + + +} diff --git a/ingame/src/main/kotlin/moe/nea89/sbdata/utils/scoreboard.kt b/ingame/src/main/kotlin/moe/nea89/sbdata/utils/scoreboard.kt new file mode 100644 index 0000000..ab53034 --- /dev/null +++ b/ingame/src/main/kotlin/moe/nea89/sbdata/utils/scoreboard.kt @@ -0,0 +1,11 @@ +package moe.nea89.sbdata.utils + +import net.minecraft.world.World + + +val controlcodeRegex = "§.".toRegex() +val String.withoutFormatting get() = this.replace(controlcodeRegex, "") +val World.scoreboardLines + get() = scoreboard + .getSortedScores(scoreboard.getObjectiveInDisplaySlot(1)) + .mapNotNull { scoreboard.getPlayersTeam(it.playerName)?.let { it.colorPrefix + it.colorSuffix }?.withoutFormatting } |