From d0e69ae979039ea6f3d90fdff195a1c0aa958b38 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Fri, 13 Sep 2024 16:33:54 +0900 Subject: [PATCH 01/29] :bookmark: 1.16 changes --- gradle.properties | 20 +- .../kyhsgeekcode/minecraft_env/ActionSpace.kt | 3 - .../minecraft_env/CaptureFramebuffer.kt | 56 ---- .../minecraft_env/EnvironmentInitializer.kt | 285 +++++------------- .../minecraft_env/MinecraftSoundListener.kt | 10 +- .../minecraft_env/Minecraft_env.kt | 88 +++--- .../kyhsgeekcode/minecraft_env/Point3D.java | 5 - .../mixin/CacheBiomeAccessMixin.java | 72 ----- .../mixin/ChatVisibleMessageAccessor.java | 3 +- ...entCommonNetworkHandlerClientAccessor.java | 2 +- .../mixin/ClientDoAttackInvoker.java | 11 - .../mixin/ClientDoItemUseInvoker.java | 11 - .../mixin/ClientPlayNetworkHandlerMixin.java | 10 +- .../ClientRenderTickCounterAccessor.java | 12 + .../mixin/DisableRegionalComplianceMixin.java | 19 -- .../minecraft_env/mixin/GammaMixin.java | 64 ---- ...ntoryScreenDrawBackgroundLoggingMixin.java | 34 --- .../mixin/MinecraftServer_tickspeedMixin.java | 256 ++++++---------- .../minecraft_env/mixin/MouseMixin.java | 17 -- .../minecraft_env/mixin/RenderMixin.java | 7 +- .../mixin/RenderSystemPollEventsInvoker.java | 12 - .../mixin/RenderTickCounterAccessor.java | 2 +- .../minecraft_env/mixin/SaveWorldMixin.java | 15 - ...rPlayNetworkHandlerDisableSpamChecker.java | 4 +- .../minecraft_env/mixin/TickSpeedMixin.java | 15 +- .../WorldListWidgetLevelSummaryAccessor.java | 11 + .../com.kyhsgeekcode.minecraft_env.mixin.json | 12 +- 27 files changed, 284 insertions(+), 772 deletions(-) delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/ActionSpace.kt delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/CaptureFramebuffer.kt delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/Point3D.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CacheBiomeAccessMixin.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoAttackInvoker.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoItemUseInvoker.java create mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientRenderTickCounterAccessor.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/DisableRegionalComplianceMixin.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/GammaMixin.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InventoryScreenDrawBackgroundLoggingMixin.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MouseMixin.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderSystemPollEventsInvoker.java delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/SaveWorldMixin.java create mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/WorldListWidgetLevelSummaryAccessor.java diff --git a/gradle.properties b/gradle.properties index b7aa154..e1a57dd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,15 +5,15 @@ org.gradle.jvmargs=-Xmx1G kotlin.code.style=official # Fabric Properties -minecraft_version=1.21 -yarn_mappings=1.21+build.9 -loader_version=0.15.11 +# https://fabricmc.net/develop/ +minecraft_version=1.16.5 +yarn_mappings=1.16.5+build.10 +loader_version=0.16.5 -# Mod Properties - mod_version = 1.0-SNAPSHOT - maven_group = com.yhs0602 - archives_base_name = craftground +# Fabric API +fabric_version=0.42.0+1.16 -# Dependencies - # check this on https://modmuss50.me/fabric.html - fabric_version=0.100.6+1.21 +# Mod Properties +mod_version = 1.0-SNAPSHOT +maven_group = com.yhs0602 +archives_base_name = craftground diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/ActionSpace.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/ActionSpace.kt deleted file mode 100644 index dae40a6..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/ActionSpace.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.kyhsgeekcode.minecraft_env - -data class ActionSpace(val action: IntArray, val command: String) \ No newline at end of file diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/CaptureFramebuffer.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/CaptureFramebuffer.kt deleted file mode 100644 index 3fef5f7..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/CaptureFramebuffer.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.kyhsgeekcode.minecraft_env - -import com.google.protobuf.ByteString -import com.mojang.blaze3d.platform.GlConst -import com.mojang.blaze3d.platform.GlStateManager -import com.mojang.blaze3d.systems.RenderSystem -import net.minecraft.client.gl.Framebuffer -import org.lwjgl.opengl.GL11 -import java.awt.RenderingHints -import java.awt.image.BufferedImage -import java.awt.image.ComponentColorModel -import java.awt.image.DataBufferByte -import java.awt.image.Raster -import java.nio.ByteBuffer - - -fun captureFramebuffer( - framebuffer: Framebuffer, - targetSizeX: Int, - targetSizeY: Int -): ByteString { - val i = framebuffer.textureWidth - val j = framebuffer.textureHeight - RenderSystem.bindTexture(framebuffer.colorAttachment) - RenderSystem.assertOnRenderThread() - GlStateManager._pixelStore(GlConst.GL_PACK_ALIGNMENT, 3) - val byteBuffer = ByteBuffer.allocateDirect(3 * i * j) - GL11.glGetTexImage(GlConst.GL_TEXTURE_2D, 0, GlConst.GL_RGB, GlConst.GL_UNSIGNED_BYTE, byteBuffer) - val dataBuffer = DataBufferByte(byteBuffer.array(), 3 * i * j) - val raster = Raster.createInterleavedRaster(dataBuffer, i, j, 3 * i, 3, intArrayOf(2, 1, 0), null) - val cm = ComponentColorModel( - ComponentColorModel.getRGBdefault().colorSpace, - false, - false, - ComponentColorModel.OPAQUE, - DataBufferByte.TYPE_BYTE - ) - val image = BufferedImage(cm, raster, false, null) - // resize if needed - val resizedImage: BufferedImage - if (i != targetSizeX || j != targetSizeY) { - resizedImage = BufferedImage(targetSizeX, targetSizeY, image.type) - val graphics = resizedImage.createGraphics() - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR) - // resize and mirror - graphics.drawImage(image, 0, targetSizeY, targetSizeX, -targetSizeY, null) - graphics.dispose() - } else { - // TODO: only mirror - resizedImage = image - } - // convert to protobuf ByteString - // FIXME -// return ByteString.copyFrom(resizedImage.bytes) - return ByteString.copyFrom(byteBuffer) -} \ No newline at end of file diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt index df0293b..4e4be79 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt @@ -2,15 +2,13 @@ package com.kyhsgeekcode.minecraft_env import com.kyhsgeekcode.minecraft_env.mixin.ChatVisibleMessageAccessor import com.kyhsgeekcode.minecraft_env.mixin.WindowSizeAccessor +import com.kyhsgeekcode.minecraft_env.mixin.WorldListWidgetLevelSummaryAccessor import com.kyhsgeekcode.minecraft_env.proto.InitialEnvironment import com.kyhsgeekcode.minecraft_env.proto.InitialEnvironment.InitialEnvironmentMessage import net.minecraft.client.MinecraftClient -import net.minecraft.client.gui.Element import net.minecraft.client.gui.hud.ChatHud -import net.minecraft.client.gui.screen.MessageScreen import net.minecraft.client.gui.screen.TitleScreen import net.minecraft.client.gui.screen.world.CreateWorldScreen -import net.minecraft.client.gui.screen.world.CustomizeFlatLevelScreen import net.minecraft.client.gui.screen.world.SelectWorldScreen import net.minecraft.client.gui.screen.world.WorldListWidget import net.minecraft.client.gui.widget.* @@ -54,8 +52,9 @@ class EnvironmentInitializer( } val window = MinecraftClient.getInstance().window val windowSizeGetter = (window as WindowSizeAccessor) - if (windowSizeGetter.windowedWidth != initialEnvironment.imageSizeX || windowSizeGetter.windowedHeight != initialEnvironment.imageSizeY) - window.setWindowedSize(initialEnvironment.imageSizeX, initialEnvironment.imageSizeY) + // Skip in 1.16 +// if (windowSizeGetter.windowedWidth != initialEnvironment.imageSizeX || windowSizeGetter.windowedHeight != initialEnvironment.imageSizeY) +// window.set(initialEnvironment.imageSizeX, initialEnvironment.imageSizeY) if (!hasMinimizedWindow) { GLFW.glfwIconifyWindow(window.handle) hasMinimizedWindow = true @@ -99,19 +98,15 @@ class EnvironmentInitializer( } if (levelList != null) { for (child in levelList.children()) { - if (child is WorldListWidget.LoadingEntry) { + if (child !is WorldListWidget.Entry) { return } - if (child is WorldListWidget.WorldEntry) { - if (!child.isLevelSelectable) { - continue - } - if (child.levelDisplayName == levelDisplayName) { - child.play() - return - } else { - println("Level display name: ${child.levelDisplayName}!= $levelDisplayName") - } + val childDisplayName = (child as WorldListWidgetLevelSummaryAccessor).getLevel()?.displayName + if (childDisplayName == levelDisplayName) { + child.play() + return + } else { + println("Level display name: ${childDisplayName}!= $levelDisplayName") } } } else { @@ -119,15 +114,6 @@ class EnvironmentInitializer( } } - is MessageScreen -> { - for (child in screen.children()) { - println("Message screen child: $child") - if (child is NarratedMultilineTextWidget) { - println("Button widget: ${child.message.string}") - } - } - } - is CreateWorldScreen -> { } @@ -175,23 +161,11 @@ class EnvironmentInitializer( // println("Create world screen") var createButton: ButtonWidget? = null val cheatRequested = true - var indexOfWorldSettingTab = -1 - var cheatButton: CyclingButtonWidget<*>? = null - var settingTabWidget: TabNavigationWidget? = null - var worldTypeButton: CyclingButtonWidget<*>? = null + var cheatButton: ButtonWidget? = null + var worldTypeButton: ButtonWidget? = null + var moreWorldOptionButton: ButtonWidget? = null for (child in screen.children()) { // search for tab navigation widget, to find index of world settings tab - if (indexOfWorldSettingTab == -1 && child is TabNavigationWidget) { - settingTabWidget = child - for (i in child.children().indices) { - val tabChild: Element = child.children()[i] - if (tabChild is TabButtonWidget) { - if (tabChild.message.string == "World") { - indexOfWorldSettingTab = i - } - } - } - } // search for create button if (createButton == null && child is ButtonWidget) { if (child.message.string == "Create New World") { @@ -199,13 +173,18 @@ class EnvironmentInitializer( } } // search for cheat button - if (cheatButton == null && child is CyclingButtonWidget<*>) { - if (child.message.string.startsWith("Allow Commands")) { + if (cheatButton == null && child is ButtonWidget) { + if (child.message.string.startsWith("Allow Cheats")) { cheatButton = child } else { println("Cheat button is not found, and the text is ${child.message.string}") } } + if (moreWorldOptionButton == null && child is ButtonWidget) { + if (child.message.string.startsWith("More World Options")) { + moreWorldOptionButton = child + } + } } // Set allow cheats to requested if (cheatButton != null) @@ -214,167 +193,53 @@ class EnvironmentInitializer( println("Cheat button not found") throw Exception("Cheat button not found") } - // Select world settings tab - settingTabWidget!!.selectTab(indexOfWorldSettingTab, false) // Search for seed input - if (initialEnvironment.seed.isNotEmpty()) { - for (child in screen.children()) { - // println(child) - if (child is TextFieldWidget) { - // println("Found text field") - child.text = initialEnvironment.seed.toString() - } + if (initialEnvironment.seed.isNotEmpty() || initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { + if (moreWorldOptionButton == null) { + println("More world option button not found") + throw Exception("More world option button not found") } - } - if (initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { - for (child in screen.children()) { - // println(child) - if (worldTypeButton == null && child is CyclingButtonWidget<*>) { - if (child.message.string.startsWith("World Type")) { - worldTypeButton = child + moreWorldOptionButton.onPress() + if (initialEnvironment.seed.isNotEmpty()) { + for (child in screen.children()) { + println(child) + if (child is TextFieldWidget) { + println("Found text field") + child.text = initialEnvironment.seed.toString() } } } - if (worldTypeButton != null) { - while (!worldTypeButton.message.string.endsWith("flat")) { - worldTypeButton.onPress() - } - } - } - createButton?.onPress() - } - } - } - - private fun createEmptyWorldAndEnterUsingGUI(client: MinecraftClient) { - when (val screen = client.currentScreen) { - is TitleScreen -> { - screen.children().find { - it is ButtonWidget && it.message.string == "Singleplayer" - }?.let { - it as ButtonWidget - it.onPress() - return - } - } - - is SelectWorldScreen -> { - // println("Select world screen1") - var widget: WorldListWidget? = null - var deleteButton: ButtonWidget? = null - var createButton: ButtonWidget? = null - for (child in screen.children()) { - // println(child) - if (child is WorldListWidget) { - widget = child - } else if (child is ButtonWidget) { - if (child.message.string == "Delete Selected World") { - deleteButton = child - } else if (child.message.string == "Create New World") { - createButton = child - } - } - } - createButton?.onPress() - } - - is CreateWorldScreen -> { - // println("Create world screen") - var createButton: ButtonWidget? = null - val cheatRequested = true - var indexOfWorldSettingTab = -1 - var cheatButton: CyclingButtonWidget<*>? = null - var settingTabWidget: TabNavigationWidget? = null - var worldTypeButton: CyclingButtonWidget<*>? = null - var customizeFlatmapButton: ButtonWidget? = null - for (child in screen.children()) { - // search for tab navigation widget, to find index of world settings tab - if (indexOfWorldSettingTab == -1 && child is TabNavigationWidget) { - settingTabWidget = child - for (i in child.children().indices) { - val tabChild: Element = child.children()[i] - if (tabChild is TabButtonWidget) { - if (tabChild.message.string == "World") { - indexOfWorldSettingTab = i + if (initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { + for (child in screen.children()) { + // println(child) + if (worldTypeButton == null && child is ButtonWidget) { + if (child.message.string.startsWith("World Type")) { + worldTypeButton = child + } + } + if (worldTypeButton != null) { + while (!worldTypeButton.message.string.endsWith("flat")) { + worldTypeButton.onPress() } } } } - // search for create button - if (createButton == null && child is ButtonWidget) { - if (child.message.string == "Create New World") { - createButton = child - } - } - // search for cheat button - if (cheatButton == null && child is CyclingButtonWidget<*>) { - if (child.message.string.startsWith("Allow Commands")) { - cheatButton = child - } else { - println("Cheat button is not found, and the text is ${child.message.string}") - } - } - } - // Set allow cheats to requested - if (cheatButton != null) - setupAllowCheats(cheatButton, cheatRequested) - else { - println("Cheat button not found") - throw Exception("Cheat button not found") - } - // Select world settings tab - settingTabWidget!!.selectTab(indexOfWorldSettingTab, false) - // Search for seed input - if (initialEnvironment.seed != null) { - for (child in screen.children()) { - // println(child) - if (child is TextFieldWidget) { - // println("Found text field") - child.text = initialEnvironment.seed.toString() - } - } - } - if (initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { - for (child in screen.children()) { - // println(child) - if (worldTypeButton == null && child is CyclingButtonWidget<*> - && child.message.string.startsWith("World Type") - ) { - worldTypeButton = child - } - if (customizeFlatmapButton == null && child is ButtonWidget && child.message.string.startsWith("Customize")) { - customizeFlatmapButton = child - } - } - if (worldTypeButton != null) { - while (!worldTypeButton.message.string.endsWith("flat")) { - worldTypeButton.onPress() - } - } - if (customizeFlatmapButton != null) { - customizeFlatmapButton.onPress() - } } createButton?.onPress() } - - is CustomizeFlatLevelScreen -> { - - } } } + private fun disableSound(client: MinecraftClient) { - client.options?.let { - it.getSoundVolumeOption(SoundCategory.MASTER).value = 0.0 - } + client.options?.setSoundVolume(SoundCategory.MASTER, 0.0f) } private fun disableNarrator(client: MinecraftClient) { val options = client.options if (options != null) { - if (options.narrator.value != NarratorMode.OFF) { - options.narrator.value = NarratorMode.OFF + if (options.narrator != NarratorMode.OFF) { + options.narrator = NarratorMode.OFF options.write() println("Disabled narrator") } @@ -388,8 +253,8 @@ class EnvironmentInitializer( private fun disableVSync(client: MinecraftClient) { val options = client.options if (options != null) { - if (options.enableVsync.value) { - options.enableVsync.value = false + if (options.enableVsync) { + options.enableVsync = false client.options.write() println("Disabled VSync") } @@ -397,21 +262,22 @@ class EnvironmentInitializer( } private fun setSimulationDistance(client: MinecraftClient, simulationDistance: Int) { - val options = client.options - if (options != null) { - if (options.simulationDistance.value != simulationDistance) { - options.simulationDistance.value = simulationDistance - client.options.write() - println("Set simulation distance to $simulationDistance") - } - } + // No such option in 1.16 +// val options = client.options +// if (options != null) { +// if (options.viewDistance != simulationDistance) { +// options.viewDistance.value = simulationDistance +// client.options.write() +// println("Set simulation distance to $simulationDistance") +// } +// } } private fun setRenderDistance(client: MinecraftClient, renderDistance: Int) { val options = client.options if (options != null) { - if (options.viewDistance.value != renderDistance) { - options.viewDistance.value = renderDistance + if (options.viewDistance != renderDistance) { + options.viewDistance = renderDistance client.options.write() println("Set render distance to $renderDistance") } @@ -435,7 +301,7 @@ class EnvironmentInitializer( player = MinecraftClient.getInstance().player ?: return val messages = ArrayList((chatHud as ChatVisibleMessageAccessor).visibleMessages) val hasInitFinishMessage = messages.find { - val text = it.content + val text = it.text val builder = StringBuilder() text.accept { index, style, codePoint -> val ch = codePoint.toChar() @@ -489,7 +355,7 @@ class EnvironmentInitializer( } private fun setupAllowCheats( - cheatButton: CyclingButtonWidget<*>, + cheatButton: ButtonWidget, cheatRequested: Boolean ) { val testString = if (cheatRequested) "ON" else "OFF" @@ -499,7 +365,7 @@ class EnvironmentInitializer( } private fun setupGameMode( - gameModeButton: CyclingButtonWidget<*>, + gameModeButton: ButtonWidget, gameModeRequested: GameMode ) { val testString = gameModeRequested.name @@ -529,14 +395,15 @@ class EnvironmentInitializer( } private fun disableOnboardAccessibility(client: MinecraftClient) { - val options = client.options - if (options != null) { - if (options.onboardAccessibility) { - println("Disabled onboardAccessibility") - options.onboardAccessibility = false - client.options.write() - } - } + // No such option in 1.16 +// val options = client.options +// if (options != null) { +// if (options.onboardAccessibility) { +// println("Disabled onboardAccessibility") +// options.onboardAccessibility = false +// client.options.write() +// } +// } } private fun setHudHidden(client: MinecraftClient, hudHidden: Boolean) { @@ -556,8 +423,8 @@ class EnvironmentInitializer( private fun setMaxFPSToUnlimited(client: MinecraftClient) { val options = client.options if (options != null) { - if (options.maxFps.value < 260) { // unlimited - options.maxFps.value = 260 + if (options.maxFps < 260) { // unlimited + options.maxFps = 260 client.options.write() println("Set max fps to 260") } @@ -567,8 +434,8 @@ class EnvironmentInitializer( private fun setFovEffectDisabled(client: MinecraftClient) { val options = client.options if (options != null) { - if (options.fovEffectScale.value != 0.0) { - options.fovEffectScale.value = 0.0 + if (options.fovEffectScale != 0.0f) { + options.fovEffectScale = 0.0f client.options.write() println("Disabled fov effect") } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MinecraftSoundListener.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MinecraftSoundListener.kt index 5f282cb..cf1e74d 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MinecraftSoundListener.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MinecraftSoundListener.kt @@ -5,7 +5,6 @@ import net.minecraft.client.sound.SoundInstance import net.minecraft.client.sound.SoundInstanceListener import net.minecraft.client.sound.SoundManager import net.minecraft.client.sound.WeightedSoundSet -import net.minecraft.text.TranslatableTextContent data class SoundEntry(val translateKey: String, var age: Long, var x: Double, var y: Double, var z: Double) { fun reset(x: Double, y: Double, z: Double) { @@ -31,16 +30,11 @@ class MinecraftSoundListener(soundManager: SoundManager) : SoundInstanceListener private val _entries: MutableList = mutableListOf() val entries = _entries as List - override fun onSoundPlayed(sound: SoundInstance?, soundSet: WeightedSoundSet?, range: Float) { + override fun onSoundPlayed(sound: SoundInstance?, soundSet: WeightedSoundSet?) { if (sound == null) return if (soundSet == null) return val subtitle = soundSet.subtitle ?: return - val content = subtitle.content - if (content !is TranslatableTextContent) { - println("content is not TranslatableTextContent: $content") - return - } - val translateKey = content.key + val translateKey = subtitle.string if (this._entries.isNotEmpty()) { for (subtitleEntry in this._entries) { if (subtitleEntry.translateKey != translateKey) continue diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 53896cd..4d47114 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -3,10 +3,10 @@ package com.kyhsgeekcode.minecraft_env import com.google.protobuf.ByteString +import com.kyhsgeekcode.minecraft_env.mixin.ClientRenderTickCounterAccessor import com.kyhsgeekcode.minecraft_env.proto.* import com.kyhsgeekcode.minecraft_env.proto.ActionSpace.ActionSpaceMessageV2 import com.kyhsgeekcode.minecraft_env.proto.ObservationSpace -import com.mojang.blaze3d.platform.GlConst import com.mojang.blaze3d.systems.RenderSystem import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents @@ -20,11 +20,9 @@ import net.minecraft.client.network.ClientPlayerEntity import net.minecraft.client.option.KeyBinding import net.minecraft.client.render.BackgroundRenderer import net.minecraft.client.util.InputUtil -import net.minecraft.client.util.ScreenshotRecorder import net.minecraft.client.world.ClientWorld import net.minecraft.entity.EntityType import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket -import net.minecraft.registry.Registries import net.minecraft.server.MinecraftServer import net.minecraft.stat.Stats import net.minecraft.util.Identifier @@ -33,11 +31,12 @@ import net.minecraft.util.WorldSavePath import net.minecraft.util.function.BooleanBiFunction import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Box -import net.minecraft.util.math.MathHelper import net.minecraft.util.math.Vec3d +import net.minecraft.util.registry.Registry import net.minecraft.util.shape.VoxelShapes import net.minecraft.world.World import org.lwjgl.glfw.GLFW +import org.lwjgl.opengl.GL11 import java.io.IOException import java.net.SocketTimeoutException import java.net.StandardProtocolFamily @@ -345,7 +344,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { } private fun sendSetScreenNull(client: MinecraftClient) { - client.setScreen(null) + client.openScreen(null) } @@ -578,16 +577,19 @@ class Minecraft_env : ModInitializer, CommandExecutor { printWithTime("New left position: ${left.x}, ${left.y}, ${left.z} ${player.prevX}, ${player.prevY}, ${player.prevZ}") // (client as ClientRenderInvoker).invokeRender(true) render(client) - val image1ByteArray = ScreenshotRecorder.takeScreenshot(buffer).use { screenshot -> - encodeImageToBytes( - screenshot, - initialEnvironment.imageSizeX, - initialEnvironment.imageSizeY, - initialEnvironment.imageSizeX, - initialEnvironment.imageSizeY - ) - } - image_1 = ByteString.copyFrom(image1ByteArray) + image_1 = FramebufferCapturer.captureFramebuffer( + buffer.colorAttachment, + buffer.fbo, + buffer.textureWidth, + buffer.textureHeight, + initialEnvironment.imageSizeX, + initialEnvironment.imageSizeY, + initialEnvironment.screenEncodingMode, + false, + MouseInfo.showCursor, // FramebufferCapturer.isExtensionAvailable + MouseInfo.mouseX.toInt(), + MouseInfo.mouseY.toInt(), + ) player.prevX = right.x player.prevY = right.y player.prevZ = right.z @@ -595,16 +597,19 @@ class Minecraft_env : ModInitializer, CommandExecutor { printWithTime("New right position: ${right.x}, ${right.y}, ${right.z} ${player.prevX}, ${player.prevY}, ${player.prevZ}") // (client as ClientRenderInvoker).invokeRender(true) render(client) - val image2ByteArray = ScreenshotRecorder.takeScreenshot(buffer).use { screenshot -> - encodeImageToBytes( - screenshot, - initialEnvironment.imageSizeX, - initialEnvironment.imageSizeY, - initialEnvironment.imageSizeX, - initialEnvironment.imageSizeY - ) - } - image_2 = ByteString.copyFrom(image2ByteArray) + image_2 = FramebufferCapturer.captureFramebuffer( + buffer.colorAttachment, + buffer.fbo, + buffer.textureWidth, + buffer.textureHeight, + initialEnvironment.imageSizeX, + initialEnvironment.imageSizeY, + initialEnvironment.screenEncodingMode, + false, + MouseInfo.showCursor, // FramebufferCapturer.isExtensionAvailable + MouseInfo.mouseX.toInt(), + MouseInfo.mouseY.toInt(), + ) // return to the original position player.prevX = oldPrevX player.prevY = oldPrevY @@ -688,12 +693,12 @@ class Minecraft_env : ModInitializer, CommandExecutor { killedStatistics[killStatKey] = stat } for (mineStatKey in initialEnvironment.minedStatKeysList) { - val key = Registries.BLOCK.get(Identifier.of("minecraft", mineStatKey)) + val key = Registry.BLOCK.get(Identifier("minecraft", mineStatKey)) val stat = player.statHandler.getStat(Stats.MINED.getOrCreateStat(key)) minedStatistics[mineStatKey] = stat } for (miscStatKey in initialEnvironment.miscStatKeysList) { - val key = Registries.CUSTOM_STAT.get(Identifier.of("minecraft", miscStatKey)) + val key = Registry.CUSTOM_STAT.get(Identifier("minecraft", miscStatKey)) miscStatistics[miscStatKey] = player.statHandler.getStat(Stats.CUSTOM.getOrCreateStat(key)) } entityListener?.run { @@ -724,9 +729,9 @@ class Minecraft_env : ModInitializer, CommandExecutor { if (initialEnvironment.requiresSurroundingBlocks) { val blocks = mutableListOf() - for (i in (player.blockX - 1)..(player.blockX + 1)) { - for (j in player.blockY - 1..player.blockY + 1) { - for (k in player.blockZ - 1..player.blockZ + 1) { + for (i in (player.blockPos.x - 1)..(player.blockPos.x + 1)) { + for (j in player.blockPos.y - 1..player.blockPos.y + 1) { + for (k in player.blockPos.z - 1..player.blockPos.z + 1) { val block = world.getBlockState(BlockPos(i, j, k)) blocks.add( blockInfo { @@ -787,7 +792,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { if (command.startsWith("/")) { command = command.substring(1) } - player.networkHandler.sendChatCommand(command) + player.sendChatMessage(command) printWithTime("End send command: $command") csvLogger.log("End send command: $command") } @@ -795,8 +800,16 @@ class Minecraft_env : ModInitializer, CommandExecutor { } fun ClientPlayerEntity.checkIfCameraBlocked(): Boolean { - val f: Float = EntityType.PLAYER.dimensions.width() * 0.8f - val box = Box.of(this.eyePos, f.toDouble(), 1.0E-6, f.toDouble()) + val f: Float = EntityType.PLAYER.dimensions.width * 0.8f + eyeY + val box = Box( + x, + eyeY, + z, + x + f, + eyeY + 1e-6, + z + f + ) return BlockPos.stream(box).anyMatch { pos: BlockPos -> val blockState: BlockState = this.world.getBlockState(pos) !blockState.isAir && VoxelShapes.matchesAnywhere( @@ -811,14 +824,15 @@ fun ClientPlayerEntity.checkIfCameraBlocked(): Boolean { fun render(client: MinecraftClient) { - RenderSystem.clear(GlConst.GL_DEPTH_BUFFER_BIT or GlConst.GL_COLOR_BUFFER_BIT, IS_SYSTEM_MAC) + RenderSystem.clear(GL11.GL_DEPTH_BUFFER_BIT or GL11.GL_COLOR_BUFFER_BIT, IS_SYSTEM_MAC) client.framebuffer.beginWrite(true) - BackgroundRenderer.clearFog() + BackgroundRenderer.method_23792() RenderSystem.enableCull() val l = Util.getMeasuringTimeNano() client.gameRenderer.render( - client.renderTickCounter,// client.renderTickCounter.tickDelta, - true // tick + (client as ClientRenderTickCounterAccessor).renderTickCounter.tickDelta, + l, + false // tick ) client.framebuffer.endWrite() client.framebuffer.draw(client.window.framebufferWidth, client.window.framebufferHeight) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Point3D.java b/src/main/java/com/kyhsgeekcode/minecraft_env/Point3D.java deleted file mode 100644 index b8db0b0..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Point3D.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.kyhsgeekcode.minecraft_env; - -public record Point3D(int x, int y, int z) { - -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CacheBiomeAccessMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CacheBiomeAccessMixin.java deleted file mode 100644 index 9b222ae..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CacheBiomeAccessMixin.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; -import com.kyhsgeekcode.minecraft_env.Point3D; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.BiomeAccess; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -@Mixin(net.minecraft.world.biome.source.BiomeAccess.class) -public class CacheBiomeAccessMixin { - // Thread safe LRU cache - @Unique - private final Cache coordsCache = Caffeine.newBuilder() - .maximumSize(4096) // Max cache size - .build(); - - @Final - @Shadow - private BiomeAccess.Storage storage; - - @Inject( - method = "getBiome", - at = @At(value = "HEAD"), - cancellable = true - ) - private void getBiomeHead(BlockPos pos, CallbackInfoReturnable> cir) { - // BlockPos is mutable - var blockPos = new Point3D(pos.getX(), pos.getY(), pos.getZ()); - var pwx = coordsCache.getIfPresent(blockPos); - if (pwx != null) { - cir.setReturnValue(storage.getBiomeForNoiseGen(pwx.x(), pwx.y(), pwx.z())); - cir.cancel(); - } - } - - @Inject( - method = "getBiome", - at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/biome/source/BiomeAccess$Storage;getBiomeForNoiseGen(III)Lnet/minecraft/registry/entry/RegistryEntry;"), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void getBiome( - BlockPos pos, - CallbackInfoReturnable> cir, - int i, - int j, - int k, - int l, - int m, - int n, - double d, - double e, - double f, - int o, - double g, - int p, - int w, - int x - ) { - coordsCache.put(new Point3D(pos.getX(), pos.getY(), pos.getZ()), new Point3D(p, w, x)); - } -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ChatVisibleMessageAccessor.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ChatVisibleMessageAccessor.java index 31f342f..3e0102d 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ChatVisibleMessageAccessor.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ChatVisibleMessageAccessor.java @@ -1,6 +1,7 @@ package com.kyhsgeekcode.minecraft_env.mixin; import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.text.OrderedText; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -9,5 +10,5 @@ @Mixin(net.minecraft.client.gui.hud.ChatHud.class) public interface ChatVisibleMessageAccessor { @Accessor("visibleMessages") - List getVisibleMessages(); + List> getVisibleMessages(); } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientCommonNetworkHandlerClientAccessor.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientCommonNetworkHandlerClientAccessor.java index f0eaf20..a30b180 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientCommonNetworkHandlerClientAccessor.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientCommonNetworkHandlerClientAccessor.java @@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(net.minecraft.client.network.ClientCommonNetworkHandler.class) +@Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class) public interface ClientCommonNetworkHandlerClientAccessor { @Accessor("client") MinecraftClient getClient(); diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoAttackInvoker.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoAttackInvoker.java deleted file mode 100644 index efb64a7..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoAttackInvoker.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import net.minecraft.client.MinecraftClient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(MinecraftClient.class) -public interface ClientDoAttackInvoker { - @Invoker("doAttack") - boolean invokeDoAttack(); -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoItemUseInvoker.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoItemUseInvoker.java deleted file mode 100644 index e0dbf4e..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientDoItemUseInvoker.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import net.minecraft.client.MinecraftClient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(MinecraftClient.class) -public interface ClientDoItemUseInvoker { - @Invoker("doItemUse") - void invokeDoItemUse(); -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientPlayNetworkHandlerMixin.java index 6f5ee43..5a83c19 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientPlayNetworkHandlerMixin.java @@ -4,7 +4,7 @@ import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; -import net.minecraft.network.packet.s2c.play.DeathMessageS2CPacket; +import net.minecraft.network.packet.s2c.play.CombatEventS2CPacket; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -16,11 +16,11 @@ public class ClientPlayNetworkHandlerMixin implements GetMessagesInterface { @Shadow private ClientWorld world; - @Inject(method = "onDeathMessage", at = @At("HEAD"), cancellable = false) - public void onDeathMessage(DeathMessageS2CPacket packet, CallbackInfo ci) { - Entity entity = this.world.getEntityById(packet.playerId()); + @Inject(method = "onCombatEvent", at = @At("HEAD"), cancellable = false) + public void onCombatEvent(CombatEventS2CPacket packet, CallbackInfo ci) { + Entity entity = this.world.getEntityById(packet.entityId); if (entity == ((ClientCommonNetworkHandlerClientAccessor) this).getClient().player) { - var message = packet.message(); + var message = packet.deathMessage; this.lastDeathMessage.clear(); this.lastDeathMessage.add(message.getString()); } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientRenderTickCounterAccessor.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientRenderTickCounterAccessor.java new file mode 100644 index 0000000..ebbd6c5 --- /dev/null +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ClientRenderTickCounterAccessor.java @@ -0,0 +1,12 @@ +package com.kyhsgeekcode.minecraft_env.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.RenderTickCounter; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(MinecraftClient.class) +public interface ClientRenderTickCounterAccessor { + @Accessor("renderTickCounter") + RenderTickCounter getRenderTickCounter(); +} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/DisableRegionalComplianceMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/DisableRegionalComplianceMixin.java deleted file mode 100644 index ff764fb..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/DisableRegionalComplianceMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import net.minecraft.client.resource.PeriodicNotificationManager; -import net.minecraft.resource.ReloadableResourceManagerImpl; -import net.minecraft.resource.ResourceReloader; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ReloadableResourceManagerImpl.class) -public class DisableRegionalComplianceMixin { - @Inject(method = "registerReloader", at = @At("HEAD"), cancellable = true) - private void registerReloader(ResourceReloader reloader, CallbackInfo ci) { - if (reloader instanceof PeriodicNotificationManager) { - ci.cancel(); // cancel the reload - } - } -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/GammaMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/GammaMixin.java deleted file mode 100644 index 938b48b..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/GammaMixin.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -/* - * This file is part of the Gamma Utils project and is licensed under the GNU Lesser General Public License v3.0. - * - * Copyright (C) 2021 Sjouwer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -import com.mojang.serialization.Codec; -import net.minecraft.client.option.SimpleOption; -import net.minecraft.client.resource.language.I18n; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(SimpleOption.class) -public class GammaMixin { - - @Shadow - @Final - Text text; - - @Shadow - T value; - - /** - * Mixin to allow saving "invalid" gamma values into the options file - */ - @Inject(method = "getCodec", at = @At("HEAD"), cancellable = true) - private void returnFakeCodec(CallbackInfoReturnable> info) { - if (text.getString().equals(I18n.translate("options.gamma"))) { - info.setReturnValue(Codec.DOUBLE); - } - } - - /** - * Mixin to allow setting "invalid" gamma values - */ - @Inject(method = "setValue", at = @At("HEAD"), cancellable = true) - private void setRealValue(T value, CallbackInfo info) { - if (text.getString().equals(I18n.translate("options.gamma"))) { - this.value = value; - info.cancel(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InventoryScreenDrawBackgroundLoggingMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InventoryScreenDrawBackgroundLoggingMixin.java deleted file mode 100644 index 18c3ae3..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InventoryScreenDrawBackgroundLoggingMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import com.kyhsgeekcode.minecraft_env.MouseInfo; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -@Mixin(net.minecraft.client.gui.screen.ingame.InventoryScreen.class) -public class InventoryScreenDrawBackgroundLoggingMixin { - @Shadow - private float mouseX; - @Shadow - private float mouseY; - - @Inject(at = @At("TAIL"), method = "drawBackground", locals = LocalCapture.CAPTURE_FAILSOFT) - private void drawBackground(DrawContext context, float delta, int mouseX, int mouseY, CallbackInfo ci, int i, int j) { -// System.out.println( -// "drawBackground: " + this.mouseX + "," + this.mouseY + ", " + delta + ", " + mouseX + ", " + mouseY + "," + i + ", " + j -// ); -// MinecraftClient client = MinecraftClient.getInstance(); -// double mouseInfomouseX = MouseInfo.INSTANCE.getMouseX(); -// double mouseInfomouseY = MouseInfo.INSTANCE.getMouseY(); -// int convertedX = (int) (mouseInfomouseX * client.getWindow().getScaledWidth() / client.getWindow().getWidth()); -// int convertedY = (int) (mouseInfomouseY * client.getWindow().getScaledHeight() / client.getWindow().getHeight()); -// System.out.println( -// "MouseInfo:" + mouseInfomouseX + "," + mouseInfomouseY + ",converted:" + convertedX + "," + convertedY -// ); - } -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java index 920f198..ffa652b 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java @@ -3,15 +3,12 @@ import com.kyhsgeekcode.minecraft_env.TickSpeed; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ServerTask; -import net.minecraft.server.ServerTickManager; import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.TimeHelper; +import net.minecraft.util.TickDurationMonitor; import net.minecraft.util.Util; import net.minecraft.util.profiler.Profiler; -import net.minecraft.util.profiling.jfr.FlightProfiler; import net.minecraft.util.thread.ReentrantThreadExecutor; -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; +import org.apache.logging.log4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -23,199 +20,138 @@ import java.util.function.BooleanSupplier; -// https://github.com/gnembon/fabric-carpet/blob/master/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java +// https://github.com/gnembon/fabric-carpet/blob/1.16.5/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java @Mixin(value = MinecraftServer.class, priority = Integer.MAX_VALUE - 10) public abstract class MinecraftServer_tickspeedMixin extends ReentrantThreadExecutor { - @Shadow - @Final - private static Logger LOGGER; - // just because profilerTimings class is public - Pair profilerTimings = null; @Shadow private volatile boolean running; - // @Shadow -// private long timeReference; - @Shadow - private Profiler profiler; - // @Shadow -// private long nextTickTimestamp; - @Shadow - private volatile boolean loading; - // @Shadow -// private long lastTimeReference; - @Shadow - private boolean waitingForNextTick; + @Shadow - private int ticks; + private long timeReference; + @Shadow - private boolean needsDebugSetup; - @Unique - private float carpetMsptAccum = 0.0f; + @Final + private static Logger LOGGER; @Shadow - private long lastOverloadWarningNanos; + private Profiler profiler; public MinecraftServer_tickspeedMixin(String name) { super(name); } @Shadow - public abstract void tick(BooleanSupplier booleanSupplier_1); + protected abstract void tick(BooleanSupplier booleanSupplier_1); @Shadow protected abstract boolean shouldKeepTicking(); @Shadow - public abstract Iterable getWorlds(); - - @Shadow - protected abstract void runTasksTillTickEnd(); - - @Shadow - protected abstract void startTickMetrics(); - - @Shadow - protected abstract void endTickMetrics(); - - @Shadow - public abstract boolean isPaused(); + private long field_19248; @Shadow - public abstract ServerTickManager getTickManager(); + protected abstract void method_16208(); @Shadow - private long tickStartTimeNanos = Util.getMeasuringTimeNano(); + private volatile boolean loading; @Shadow - private static final long OVERLOAD_THRESHOLD_NANOS = 20L * TimeHelper.SECOND_IN_NANOS / 20L; + protected abstract void startMonitor(TickDurationMonitor monitor); @Shadow - private long tickEndTimeNanos; + private long lastTimeReference; @Shadow - private void startTaskPerformanceLog() { - } + private boolean waitingForNextTick; @Shadow - private void pushPerformanceLogs() { - } + public abstract Iterable getWorlds(); - @Shadow - private void pushFullTickLog() { - } + private float carpetMsptAccum = 0.0f; - @Shadow - private float averageTickTime; + /** + * To ensure compatibility with other mods we should allow milliseconds + */ -// // Cancel the while statement -// @Redirect(method = "runServer", at = @At(value = "FIELD", target = "Lnet/minecraft/server/MinecraftServer;running:Z")) -// private boolean cancelRunLoop(MinecraftServer server) { -// return false; -// } // target run() + // Cancel a while statement + @Redirect(method = "runServer", at = @At(value = "FIELD", target = "Lnet/minecraft/server/MinecraftServer;running:Z")) + private boolean cancelRunLoop(MinecraftServer server) { + return false; + } // target run() // Replaced the above cancelled while statement with this one // could possibly just inject that mspt selection at the beginning of the loop, but then adding all mspt's to // replace 50L will be a hassle -// @Inject(method = "runServer", at = @At(value = "INVOKE", shift = At.Shift.AFTER, -// target = "Lnet/minecraft/server/MinecraftServer;createMetadata()Lnet/minecraft/server/ServerMetadata;")) -// private void modifiedRunLoop(CallbackInfo ci) { -//// while (this.running) { -//// //long long_1 = Util.getMeasuringTimeMs() - this.timeReference; -//// //CM deciding on tick speed -//// long msThisTick = 0L; -//// long long_1 = 0L; -//// -//// msThisTick = (long) carpetMsptAccum; // regular tick -//// carpetMsptAccum += TickSpeed.INSTANCE.getMspt() - msThisTick; -//// -//// long_1 = Util.getMeasuringTimeMs() - this.timeReference; -//// -//// //end tick deciding -//// //smoothed out delay to include mcpt component. With 50L gives defaults. -//// if (long_1 > /*2000L*/1000L + 20 * TickSpeed.INSTANCE.getMspt() && this.timeReference - this.lastTimeReference >= /*15000L*/10000L + 100 * TickSpeed.INSTANCE.getMspt()) { -//// long long_2 = long_1 / TickSpeed.INSTANCE.getMspt();//50L; -//// LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", long_1, long_2); -//// this.timeReference += long_2 * TickSpeed.INSTANCE.getMspt();//50L; -//// this.lastTimeReference = this.timeReference; -//// } -//// -//// if (this.needsDebugSetup) { -//// this.needsDebugSetup = false; -//// this.profilerTimings = Pair.of(Util.getMeasuringTimeNano(), ticks); -//// //this.field_33978 = new MinecraftServer.class_6414(Util.getMeasuringTimeNano(), this.ticks); -//// } -//// this.timeReference += msThisTick;//50L; -//// //TickDurationMonitor tickDurationMonitor = TickDurationMonitor.create("Server"); -//// //this.startMonitor(tickDurationMonitor); -//// this.startTickMetrics(); -//// this.profiler.push("tick"); -//// this.tick(this::shouldKeepTicking); -//// this.profiler.swap("nextTickWait"); -//// while (this.runEveryTask()) { -//// Thread.yield(); -//// } // ? -//// this.waitingForNextTick = true; -//// this.nextTickTimestamp = Math.max(Util.getMeasuringTimeMs() + /*50L*/ msThisTick, this.timeReference); -//// // run all tasks (this will not do a lot when warping), but that's fine since we already run them -//// this.runTasksTillTickEnd();// this.runTasks(); -////// this.runTasks(); -//// this.profiler.pop(); -//// this.endTickMetrics(); -//// this.loading = true; -// -// boolean bl; -// long l; -// var tickManager = this.getTickManager(); -// if (!this.isPaused() && tickManager.isSprinting() && tickManager.sprint()) { -// l = 0L; -// this.lastOverloadWarningNanos = this.tickStartTimeNanos = Util.getMeasuringTimeNano(); + @Inject(method = "runServer", at = @At(value = "INVOKE", shift = At.Shift.AFTER, + target = "Lnet/minecraft/server/MinecraftServer;setFavicon(Lnet/minecraft/server/ServerMetadata;)V")) + private void modifiedRunLoop(CallbackInfo ci) { + while (this.running) { + //long long_1 = Util.getMeasuringTimeMs() - this.timeReference; + //CM deciding on tick speed + long msThisTick = 0L; + long long_1 = 0L; +// if (TickSpeed.time_warp_start_time != 0) { +// //making sure server won't flop after the warp or if the warp is interrupted +// this.timeReference = this.lastTimeReference = Util.getMeasuringTimeMs(); +// carpetMsptAccum = TickSpeed.INSTANCE.getMspt(); // } else { -// l = tickManager.getNanosPerTick(); -// long m = Util.getMeasuringTimeNano() - this.tickStartTimeNanos; -// if (m > OVERLOAD_THRESHOLD_NANOS + 20L * l && this.tickStartTimeNanos - this.lastOverloadWarningNanos >= OVERLOAD_WARNING_INTERVAL_NANOS + 100L * l) { -// long n = m / l; -// LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", (Object) (m / TimeHelper.MILLI_IN_NANOS), (Object) n); -// this.tickStartTimeNanos += n * l; -// this.lastOverloadWarningNanos = this.tickStartTimeNanos; -// } -// } -// boolean bl2 = bl = l == 0L; -// if (this.needsDebugSetup) { -// this.needsDebugSetup = false; -// } -// this.tickStartTimeNanos += l; -// this.startTickMetrics(); -// this.profiler.push("tick"); -// this.tick(bl ? () -> false : this::shouldKeepTicking); -// this.profiler.swap("nextTickWait"); -// this.waitingForNextTick = true; -// this.tickEndTimeNanos = Math.max(Util.getMeasuringTimeNano() + l, this.tickStartTimeNanos); -// this.startTaskPerformanceLog(); -// this.runTasksTillTickEnd(); -// this.pushPerformanceLogs(); -// if (bl) { -// tickManager.updateSprintTime(); -// } -// this.profiler.pop(); -// this.pushFullTickLog(); -// this.endTickMetrics(); -// this.loading = true; -// FlightProfiler.INSTANCE.onTick(this.averageTickTime); -// } -// } - -// private boolean runEveryTask() { -// if (super.runTask()) { -// return true; -// } else { -// if (true) { // unconditionally this time -// for (ServerWorld serverlevel : getWorlds()) { -// if (serverlevel.getChunkManager().executeQueuedTasks()) { -// return true; -// } -// } + if (Math.abs(carpetMsptAccum - TickSpeed.INSTANCE.getMspt()) > 1.0f) { + // Tickrate changed. Ensure that we use the correct value. + carpetMsptAccum = TickSpeed.INSTANCE.getMspt(); + } + + msThisTick = (long) carpetMsptAccum; // regular tick + carpetMsptAccum += TickSpeed.INSTANCE.getMspt() - msThisTick; + + long_1 = Util.getMeasuringTimeMs() - this.timeReference; // } -// return false; -// } -// } + //end tick deciding + //smoothed out delay to include mcpt component. With 50L gives defaults. + if (long_1 > /*2000L*/1000L + 20 * TickSpeed.INSTANCE.getMspt() && this.timeReference - this.lastTimeReference >= /*15000L*/10000L + 100 * TickSpeed.INSTANCE.getMspt()) { + long long_2 = (long) (long_1 / TickSpeed.INSTANCE.getMspt());//50L; + LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", long_1, long_2); + this.timeReference += (long) (long_2 * TickSpeed.INSTANCE.getMspt());//50L; + this.lastTimeReference = this.timeReference; + } + + this.timeReference += msThisTick;//50L; + TickDurationMonitor tickDurationMonitor = TickDurationMonitor.create("Server"); + this.startMonitor(tickDurationMonitor); + this.profiler.startTick(); + this.profiler.push("tick"); + this.tick(this::shouldKeepTicking); + this.profiler.swap("nextTickWait"); +// if (TickSpeed.time_warp_start_time != 0) // clearing all hanging tasks no matter what when warping + { + while (this.runEveryTask()) { + Thread.yield(); + } + } + this.waitingForNextTick = true; + this.field_19248 = Math.max(Util.getMeasuringTimeMs() + /*50L*/ msThisTick, this.timeReference); + // run all tasks (this will not do a lot when warping), but that's fine since we already run them + this.method_16208(); + this.profiler.pop(); + this.profiler.endTick(); + this.loading = true; + } + } + + + @Unique + private boolean runEveryTask() { + if (super.runTask()) { + return true; + } else { + if (true) { // unconditionally this time + for (ServerWorld serverlevel : getWorlds()) { + if (serverlevel.getChunkManager().executeQueuedTasks()) { + return true; + } + } + } + + return false; + } + } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MouseMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MouseMixin.java deleted file mode 100644 index 5e5cf6b..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MouseMixin.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import com.kyhsgeekcode.minecraft_env.MouseInfo; -import net.minecraft.client.Mouse; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - - -@Mixin(Mouse.class) -abstract public class MouseMixin { - @Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true) - private void isCursorLocked(CallbackInfoReturnable cir) { -// cir.setReturnValue(!MouseInfo.INSTANCE.getShowCursor()); - } -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderMixin.java index b902d1c..dda1298 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderMixin.java @@ -5,6 +5,7 @@ import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.render.Tessellator; import net.minecraft.client.util.Window; +import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -23,10 +24,10 @@ private void frameBufferDraw(Framebuffer instance, int width, int height) { @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/Window;swapBuffers()V")) private void windowSwapBuffers(Window instance) { - RenderSystemPollEventsInvoker.pollEvents(); + GLFW.glfwPollEvents(); RenderSystem.replayQueue(); - Tessellator.getInstance().clear(); + Tessellator.getInstance().getBuffer().clear(); // GLFW.glfwSwapBuffers(window); - RenderSystemPollEventsInvoker.pollEvents(); + GLFW.glfwPollEvents(); } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderSystemPollEventsInvoker.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderSystemPollEventsInvoker.java deleted file mode 100644 index bedcb5a..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderSystemPollEventsInvoker.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(com.mojang.blaze3d.systems.RenderSystem.class) -public interface RenderSystemPollEventsInvoker { - @Invoker("pollEvents") - static void pollEvents() { - - } -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderTickCounterAccessor.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderTickCounterAccessor.java index 7d3d0ff..0a1a32a 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderTickCounterAccessor.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/RenderTickCounterAccessor.java @@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(RenderTickCounter.Dynamic.class) +@Mixin(RenderTickCounter.class) public interface RenderTickCounterAccessor { @Accessor("prevTimeMillis") void setPrevTimeMillis(long prevTimeMillis); diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/SaveWorldMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/SaveWorldMixin.java deleted file mode 100644 index 17de639..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/SaveWorldMixin.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import net.minecraft.server.MinecraftServer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(MinecraftServer.class) -public class SaveWorldMixin { - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;saveAll(ZZZ)Z")) - private boolean saveAll(MinecraftServer server, boolean bl, boolean bl2, boolean bl3) { - return false; // disable saving - } -} diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ServerPlayNetworkHandlerDisableSpamChecker.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ServerPlayNetworkHandlerDisableSpamChecker.java index f7f4b9a..c071d7e 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ServerPlayNetworkHandlerDisableSpamChecker.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/ServerPlayNetworkHandlerDisableSpamChecker.java @@ -8,8 +8,8 @@ @Mixin(ServerPlayNetworkHandler.class) public class ServerPlayNetworkHandlerDisableSpamChecker { - @Inject(method = "checkForSpam", at = @At("HEAD"), cancellable = true) - private void checkForSpam(CallbackInfo ci) { + @Inject(method = "disconnect", at = @At("HEAD"), cancellable = true) + private void disconnect(CallbackInfo ci) { ci.cancel(); } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/TickSpeedMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/TickSpeedMixin.java index 02bdfcb..a108ed4 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/TickSpeedMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/TickSpeedMixin.java @@ -1,25 +1,26 @@ package com.kyhsgeekcode.minecraft_env.mixin; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.RenderTickCounter; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -@Mixin(RenderTickCounter.Dynamic.class) +@Mixin(MinecraftClient.class) public class TickSpeedMixin { @Redirect( - method = "beginRenderTick(JZ)I", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderTickCounter$Dynamic;beginRenderTick(J)I") + method = "render(Z)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderTickCounter;beginRenderTick(J)I") ) - private int beginRenderTick(RenderTickCounter.Dynamic renderTickCounter, long timeMillis) { + private int beginRenderTick(RenderTickCounter renderTickCounter, long timeMillis) { ((RenderTickCounterAccessor) renderTickCounter).setLastFrameDuration(1);// (float)(timeMillis - this.prevTimeMillis) / this.tickTime; ((RenderTickCounterAccessor) renderTickCounter).setPrevTimeMillis(timeMillis); ((RenderTickCounterAccessor) renderTickCounter).setTickDelta( - renderTickCounter.getTickDelta(true) + renderTickCounter.getLastFrameDuration() + (renderTickCounter).tickDelta + renderTickCounter.lastFrameDuration ); - int i = (int) renderTickCounter.getTickDelta(true); - ((RenderTickCounterAccessor) renderTickCounter).setTickDelta((renderTickCounter.getTickDelta(true) - (float) i)); + int i = (int) renderTickCounter.tickDelta; + ((RenderTickCounterAccessor) renderTickCounter).setTickDelta((renderTickCounter.tickDelta - (float) i)); return i; } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/WorldListWidgetLevelSummaryAccessor.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/WorldListWidgetLevelSummaryAccessor.java new file mode 100644 index 0000000..8492da6 --- /dev/null +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/WorldListWidgetLevelSummaryAccessor.java @@ -0,0 +1,11 @@ +package com.kyhsgeekcode.minecraft_env.mixin; + +import net.minecraft.world.level.storage.LevelSummary; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(net.minecraft.client.gui.screen.world.WorldListWidget.Entry.class) +public interface WorldListWidgetLevelSummaryAccessor { + @Accessor("level") + LevelSummary getLevel(); +} diff --git a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json index 717cdce..1c0d77b 100644 --- a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json +++ b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json @@ -4,33 +4,27 @@ "package": "com.kyhsgeekcode.minecraft_env.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "CacheBiomeAccessMixin", - "DisableRegionalComplianceMixin", + "MinecraftServer_tickspeedMixin", "RenderMixin", - "SaveWorldMixin", "ServerPlayNetworkHandlerDisableSpamChecker" ], "client": [ "ChatVisibleMessageAccessor", "ClientCommonNetworkHandlerClientAccessor", - "ClientDoAttackInvoker", - "ClientDoItemUseInvoker", "ClientEntityRenderDispatcherAccessor", "ClientIsWindowFocusedMixin", "ClientPlayNetworkHandlerMixin", "ClientRenderInvoker", + "ClientRenderTickCounterAccessor", "ClientWorldMixin", - "GammaMixin", "InputUtilMixin", - "InventoryScreenDrawBackgroundLoggingMixin", "KeyboardMixin", - "MouseMixin", "MouseXYAccessor", - "RenderSystemPollEventsInvoker", "RenderTickCounterAccessor", "TickSpeedMixin", "WindowOffScreenMixin", "WindowSizeAccessor", + "WorldListWidgetLevelSummaryAccessor", "WorldRendererCallEntityRenderMixin" ], "server": [], From 602c927600560497c9dcde5c09dd3668f5ee82ed Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Fri, 13 Sep 2024 18:55:22 +0900 Subject: [PATCH 02/29] :sparkles: Handle shift click --- .../minecraft_env/Minecraft_env.kt | 8 ++++---- .../kyhsgeekcode/minecraft_env/MouseInfo.kt | 20 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 4d47114..18f10d6 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -457,20 +457,20 @@ class Minecraft_env : ModInitializer, CommandExecutor { if (currentScreen != null) { if (actionDict.use) { if (!wasUsing) - MouseInfo.clickRightButton() + MouseInfo.clickRightButton(wasSneaking) wasUsing = true } else { if (wasUsing) - MouseInfo.releaseRightButton() + MouseInfo.releaseRightButton(wasSneaking) wasUsing = false } if (actionDict.attack) { if (!wasAttacking) - MouseInfo.clickLeftButton() + MouseInfo.clickLeftButton(wasSneaking) wasAttacking = true } else { if (wasAttacking) - MouseInfo.releaseLeftButton() + MouseInfo.releaseLeftButton(wasSneaking) wasAttacking = false } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt index c64a1d3..cf790d4 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt @@ -59,23 +59,27 @@ object MouseInfo { // TODO: Mods (shift click, etc) - fun clickLeftButton() { - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_PRESS, 0) + fun clickLeftButton(shift: Boolean) { + val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 + mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_PRESS, mods) leftButtonPressed = true } - fun releaseLeftButton() { - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_RELEASE, 0) + fun releaseLeftButton(shift: Boolean) { + val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 + mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_RELEASE, mods) leftButtonPressed = false } - fun clickRightButton() { - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_RIGHT, GLFW.GLFW_PRESS, 0) + fun clickRightButton(shift: Boolean) { + val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 + mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_RIGHT, GLFW.GLFW_PRESS, mods) rightButtonPressed = true } - fun releaseRightButton() { - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_RIGHT, GLFW.GLFW_RELEASE, 0) + fun releaseRightButton(shift: Boolean) { + val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 + mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_RIGHT, GLFW.GLFW_RELEASE, mods) rightButtonPressed = false } } \ No newline at end of file From 0338d20667ec87dbc6904d9c14febbd61b196753 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 08:22:37 +0900 Subject: [PATCH 03/29] :bug: Fix set seed --- .../minecraft_env/EnvironmentInitializer.kt | 83 ++++++++++--------- .../CreateWorldScreenMoreOptionsAccessor.java | 10 +++ .../com.kyhsgeekcode.minecraft_env.mixin.json | 1 + 3 files changed, 57 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CreateWorldScreenMoreOptionsAccessor.java diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt index 4e4be79..ee1db14 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt @@ -1,6 +1,7 @@ package com.kyhsgeekcode.minecraft_env import com.kyhsgeekcode.minecraft_env.mixin.ChatVisibleMessageAccessor +import com.kyhsgeekcode.minecraft_env.mixin.CreateWorldScreenMoreOptionsAccessor import com.kyhsgeekcode.minecraft_env.mixin.WindowSizeAccessor import com.kyhsgeekcode.minecraft_env.mixin.WorldListWidgetLevelSummaryAccessor import com.kyhsgeekcode.minecraft_env.proto.InitialEnvironment @@ -11,7 +12,8 @@ import net.minecraft.client.gui.screen.TitleScreen import net.minecraft.client.gui.screen.world.CreateWorldScreen import net.minecraft.client.gui.screen.world.SelectWorldScreen import net.minecraft.client.gui.screen.world.WorldListWidget -import net.minecraft.client.gui.widget.* +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.gui.widget.TextFieldWidget import net.minecraft.client.network.ClientPlayerEntity import net.minecraft.client.option.NarratorMode import net.minecraft.client.tutorial.TutorialStep @@ -42,6 +44,12 @@ class EnvironmentInitializer( private lateinit var player: ClientPlayerEntity var hasMinimizedWindow: Boolean = false + var createButton: ButtonWidget? = null + var createWorldButton: ButtonWidget? = null + var cheatButton: ButtonWidget? = null + var moreWorldOptionButton: ButtonWidget? = null + var worldTypeButton: ButtonWidget? = null + fun onClientTick(client: MinecraftClient) { csvLogger.profileStartPrint("Minecraft_env/onInitialize/ClientTick/EnvironmentInitializer/onClientTick") disableNarrator(client) @@ -141,7 +149,6 @@ class EnvironmentInitializer( // println("Select world screen1") var widget: WorldListWidget? = null var deleteButton: ButtonWidget? = null - var createButton: ButtonWidget? = null for (child in screen.children()) { // println(child) if (child is WorldListWidget) { @@ -159,17 +166,13 @@ class EnvironmentInitializer( is CreateWorldScreen -> { // println("Create world screen") - var createButton: ButtonWidget? = null val cheatRequested = true - var cheatButton: ButtonWidget? = null - var worldTypeButton: ButtonWidget? = null - var moreWorldOptionButton: ButtonWidget? = null for (child in screen.children()) { // search for tab navigation widget, to find index of world settings tab // search for create button - if (createButton == null && child is ButtonWidget) { + if (createWorldButton == null && child is ButtonWidget) { if (child.message.string == "Create New World") { - createButton = child + createWorldButton = child } } // search for cheat button @@ -186,40 +189,46 @@ class EnvironmentInitializer( } } } - // Set allow cheats to requested - if (cheatButton != null) - setupAllowCheats(cheatButton, cheatRequested) - else { - println("Cheat button not found") - throw Exception("Cheat button not found") + if (createWorldButton == null) { + println("Create button not found") + throw Exception("Create button not found") } - // Search for seed input - if (initialEnvironment.seed.isNotEmpty() || initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { - if (moreWorldOptionButton == null) { - println("More world option button not found") - throw Exception("More world option button not found") + if (cheatRequested) { + cheatButton?.apply { + setupAllowCheats(this, cheatRequested) + } ?: run { + println("Cheat button not found") + throw Exception("Cheat button not found") } - moreWorldOptionButton.onPress() - if (initialEnvironment.seed.isNotEmpty()) { - for (child in screen.children()) { - println(child) - if (child is TextFieldWidget) { - println("Found text field") - child.text = initialEnvironment.seed.toString() - } + } + // Search for seed input + if ( + initialEnvironment.seed.isNotEmpty() || initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT + ) { + if (!(screen as CreateWorldScreenMoreOptionsAccessor).moreOptionsOpen) { + moreWorldOptionButton?.onPress() ?: run { + println("More world option button not found") + throw Exception("More world option button not found") } - } - if (initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { - for (child in screen.children()) { - // println(child) - if (worldTypeButton == null && child is ButtonWidget) { - if (child.message.string.startsWith("World Type")) { - worldTypeButton = child + } else { + // More options already open + if (initialEnvironment.seed.isNotEmpty()) { + for (child in screen.children()) { + if (child is TextFieldWidget && child.visible) { + println("Found visible text field, setting seed to ${initialEnvironment.seed}") + child.text = initialEnvironment.seed.toString() } } - if (worldTypeButton != null) { - while (!worldTypeButton.message.string.endsWith("flat")) { - worldTypeButton.onPress() + } + if (initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { + for (child in screen.children()) { + if (worldTypeButton == null && child is ButtonWidget) { + if (child.message.string.startsWith("World Type")) { + worldTypeButton = child + while (!child.message.string.endsWith("flat")) { + child.onPress() + } + } } } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CreateWorldScreenMoreOptionsAccessor.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CreateWorldScreenMoreOptionsAccessor.java new file mode 100644 index 0000000..c7dafff --- /dev/null +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/CreateWorldScreenMoreOptionsAccessor.java @@ -0,0 +1,10 @@ +package com.kyhsgeekcode.minecraft_env.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(net.minecraft.client.gui.screen.world.CreateWorldScreen.class) +public interface CreateWorldScreenMoreOptionsAccessor { + @Accessor("moreOptionsOpen") + boolean getMoreOptionsOpen(); +} diff --git a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json index 1c0d77b..f6b2993 100644 --- a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json +++ b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json @@ -17,6 +17,7 @@ "ClientRenderInvoker", "ClientRenderTickCounterAccessor", "ClientWorldMixin", + "CreateWorldScreenMoreOptionsAccessor", "InputUtilMixin", "KeyboardMixin", "MouseXYAccessor", From 0f80929e059dbf9574639742749ab7ed5abbff36 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 08:53:43 +0900 Subject: [PATCH 04/29] :bug: Fix world gen --- .../minecraft_env/EnvironmentInitializer.kt | 50 ++++++------------- ...oreOptionsDialogSeedTextFieldAccessor.java | 15 ++++++ .../com.kyhsgeekcode.minecraft_env.mixin.json | 1 + 3 files changed, 31 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MoreOptionsDialogSeedTextFieldAccessor.java diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt index ee1db14..927c4e3 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt @@ -1,7 +1,7 @@ package com.kyhsgeekcode.minecraft_env import com.kyhsgeekcode.minecraft_env.mixin.ChatVisibleMessageAccessor -import com.kyhsgeekcode.minecraft_env.mixin.CreateWorldScreenMoreOptionsAccessor +import com.kyhsgeekcode.minecraft_env.mixin.MoreOptionsDialogSeedTextFieldAccessor import com.kyhsgeekcode.minecraft_env.mixin.WindowSizeAccessor import com.kyhsgeekcode.minecraft_env.mixin.WorldListWidgetLevelSummaryAccessor import com.kyhsgeekcode.minecraft_env.proto.InitialEnvironment @@ -13,7 +13,6 @@ import net.minecraft.client.gui.screen.world.CreateWorldScreen import net.minecraft.client.gui.screen.world.SelectWorldScreen import net.minecraft.client.gui.screen.world.WorldListWidget import net.minecraft.client.gui.widget.ButtonWidget -import net.minecraft.client.gui.widget.TextFieldWidget import net.minecraft.client.network.ClientPlayerEntity import net.minecraft.client.option.NarratorMode import net.minecraft.client.tutorial.TutorialStep @@ -179,8 +178,7 @@ class EnvironmentInitializer( if (cheatButton == null && child is ButtonWidget) { if (child.message.string.startsWith("Allow Cheats")) { cheatButton = child - } else { - println("Cheat button is not found, and the text is ${child.message.string}") + println("Cheat button found") } } if (moreWorldOptionButton == null && child is ButtonWidget) { @@ -202,39 +200,21 @@ class EnvironmentInitializer( } } // Search for seed input - if ( - initialEnvironment.seed.isNotEmpty() || initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT - ) { - if (!(screen as CreateWorldScreenMoreOptionsAccessor).moreOptionsOpen) { - moreWorldOptionButton?.onPress() ?: run { - println("More world option button not found") - throw Exception("More world option button not found") - } - } else { - // More options already open - if (initialEnvironment.seed.isNotEmpty()) { - for (child in screen.children()) { - if (child is TextFieldWidget && child.visible) { - println("Found visible text field, setting seed to ${initialEnvironment.seed}") - child.text = initialEnvironment.seed.toString() - } - } - } - if (initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { - for (child in screen.children()) { - if (worldTypeButton == null && child is ButtonWidget) { - if (child.message.string.startsWith("World Type")) { - worldTypeButton = child - while (!child.message.string.endsWith("flat")) { - child.onPress() - } - } - } - } - } + if (initialEnvironment.seed.isNotEmpty()) { + (screen.moreOptionsDialog as MoreOptionsDialogSeedTextFieldAccessor).seedTextField?.text = + initialEnvironment.seed.toString() + println("Set seed to ${initialEnvironment.seed}") + } + if (initialEnvironment.worldType == InitialEnvironment.WorldType.SUPERFLAT) { + val mapTypeButton = + (screen.moreOptionsDialog as MoreOptionsDialogSeedTextFieldAccessor).mapTypeButton + while (!mapTypeButton.message.string.endsWith("flat")) { + mapTypeButton.onPress() } + println("Set world type to superflat") } - createButton?.onPress() + createWorldButton?.onPress() + println("Create world button pressed") } } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MoreOptionsDialogSeedTextFieldAccessor.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MoreOptionsDialogSeedTextFieldAccessor.java new file mode 100644 index 0000000..8aeb110 --- /dev/null +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MoreOptionsDialogSeedTextFieldAccessor.java @@ -0,0 +1,15 @@ +package com.kyhsgeekcode.minecraft_env.mixin; + +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(net.minecraft.client.gui.screen.world.MoreOptionsDialog.class) +public interface MoreOptionsDialogSeedTextFieldAccessor { + @Accessor("seedTextField") + TextFieldWidget getSeedTextField(); + + @Accessor("mapTypeButton") + ButtonWidget getMapTypeButton(); +} diff --git a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json index f6b2993..c8e0377 100644 --- a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json +++ b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json @@ -20,6 +20,7 @@ "CreateWorldScreenMoreOptionsAccessor", "InputUtilMixin", "KeyboardMixin", + "MoreOptionsDialogSeedTextFieldAccessor", "MouseXYAccessor", "RenderTickCounterAccessor", "TickSpeedMixin", From cb9ec7b7266a855da8049d2d46df41fab308550b Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 09:33:46 +0900 Subject: [PATCH 05/29] :bug: Fix command 1.16 --- src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 18f10d6..0a7c05f 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -792,6 +792,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { if (command.startsWith("/")) { command = command.substring(1) } + command = "/$command" player.sendChatMessage(command) printWithTime("End send command: $command") csvLogger.log("End send command: $command") From b889e609c19b181caf32bb859762a1c5bada37cd Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 09:36:23 +0900 Subject: [PATCH 06/29] :bug: There are no tick command in 1.16 --- .../com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt index 927c4e3..c764b28 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt @@ -340,7 +340,7 @@ class EnvironmentInitializer( // Set the TPS to virtually unlimited private fun setUnlimitedTPS(commandExecutor: (ClientPlayerEntity, String) -> Unit) { - commandExecutor(player, "/tick rate 10000") +// commandExecutor(player, "/tick rate 10000") } private fun setupAllowCheats( From 3821e9f1731073cc1bd3a82e2536a93a053cfba5 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 12:57:30 +0900 Subject: [PATCH 07/29] :bug: Subtle mouse --- .../kyhsgeekcode/minecraft_env/MouseInfo.kt | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt index cf790d4..bf1e3d2 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt @@ -35,24 +35,21 @@ object MouseInfo { } fun moveMouseBy(dx: Double, dy: Double) { - // 쪼개는 단위 크기 설정 (예: 1 픽셀씩 움직임) - val stepSize = 1.0 - // dx와 dy의 절대값 계산 - val stepsX = Math.abs(dx / stepSize).toInt() - val stepsY = Math.abs(dy / stepSize).toInt() - - // 가장 큰 움직임에 대한 총 단계 계산 (둘 중 더 큰 값) - val totalSteps = Math.max(stepsX, stepsY) + val stepsX = Math.abs(dx).toInt() + val stepsY = Math.abs(dy).toInt() - // 각 단계에서 움직일 dx, dy 비율 계산 - val stepDx = dx / totalSteps - val stepDy = dy / totalSteps + // 가로로 이동 (dx 방향) + val stepX = if (dx > 0) 1 else -1 + for (i in 0 until stepsX) { + mouseX += stepX + cursorPosCallback?.invoke(handle, mouseX, mouseY) + } - // 단계별로 커서를 이동 - for (i in 0 until totalSteps) { - mouseX += stepDx - mouseY += stepDy + // 세로로 이동 (dy 방향) + val stepY = if (dy > 0) 1 else -1 + for (i in 0 until stepsY) { + mouseY += stepY cursorPosCallback?.invoke(handle, mouseX, mouseY) } } From bddd9a789c668d70d243455c84f13b23441f9f00 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 13:06:57 +0900 Subject: [PATCH 08/29] :bug: Disable early --- .../java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 0a7c05f..d7b721b 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -440,9 +440,9 @@ class Minecraft_env : ModInitializer, CommandExecutor { ) wasPressingInventory = actionDict.inventory wasPressingDrop = actionDict.drop - if (handled) { - return false - } +// if (handled) { +// return false +// } } } From 0c85ea452ff2bab8b3d1fce3b94412f72e356507 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 13:57:00 +0900 Subject: [PATCH 09/29] :sparkles: Wait for chunk loading --- src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index d7b721b..93c067b 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -38,6 +38,7 @@ import net.minecraft.world.World import org.lwjgl.glfw.GLFW import org.lwjgl.opengl.GL11 import java.io.IOException +import java.lang.Thread.sleep import java.net.SocketTimeoutException import java.net.StandardProtocolFamily import java.net.UnixDomainSocketAddress @@ -300,6 +301,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { csvLogger.log("Waiting for the initialization ends") if (initializer.initWorldFinished) { sendSetScreenNull(client) // clear death screen + sleep(1000) // Wait for chunk loading resetPhase = ResetPhase.END_RESET } return From e526c0a8c67a93434f09c834e91be951591608e3 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 14:14:41 +0900 Subject: [PATCH 10/29] :necktie: Integer dxdy --- .../java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 8 +++++--- src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 93c067b..076cb5f 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -504,9 +504,11 @@ class Minecraft_env : ModInitializer, CommandExecutor { // To raise head, pitch should be decreased // Move mouse up, pitch should be decreased // Move mouse up = y axis decrease & pitch decrease - val dy = actionDict.cameraPitch * 20.0 / 3 - val dx = actionDict.cameraYaw * 20.0 / 3 - MouseInfo.moveMouseBy(dx, dy) // Invert y axis + if (actionDict.cameraYaw != 0.0f || actionDict.cameraYaw != 0.0f) { + val dy = actionDict.cameraPitch * 20.0 / 3 + val dx = actionDict.cameraYaw * 20.0 / 3 + MouseInfo.moveMouseBy(dx.toInt(), dy.toInt()) + } // } else { // // pitch: 0: -90 degree, 24: 90 degree // val deltaPitchInDeg = actionDict.cameraPitch diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt index bf1e3d2..7076b18 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt @@ -34,10 +34,10 @@ object MouseInfo { showCursor = show } - fun moveMouseBy(dx: Double, dy: Double) { + fun moveMouseBy(dx: Int, dy: Int) { // dx와 dy의 절대값 계산 - val stepsX = Math.abs(dx).toInt() - val stepsY = Math.abs(dy).toInt() + val stepsX = Math.abs(dx) + val stepsY = Math.abs(dy) // 가로로 이동 (dx 방향) val stepX = if (dx > 0) 1 else -1 From 26d1eb8e755decb13b34e1b69fd4d374dbba8056 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 14:44:19 +0900 Subject: [PATCH 11/29] :bug: Fix earl --- .../java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 076cb5f..301b399 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -442,9 +442,9 @@ class Minecraft_env : ModInitializer, CommandExecutor { ) wasPressingInventory = actionDict.inventory wasPressingDrop = actionDict.drop -// if (handled) { -// return false -// } + if (handled) { + return false + } } } From 94c0fbd7a22e469eba06be697611277c41082d6c Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 15:05:28 +0900 Subject: [PATCH 12/29] :bug: Disable movement while screen --- .../java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 301b399..2d7c1e1 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -430,6 +430,13 @@ class Minecraft_env : ModInitializer, CommandExecutor { Triple(actionDict.hotbar7, false, GLFW.GLFW_KEY_7), Triple(actionDict.hotbar8, false, GLFW.GLFW_KEY_8), Triple(actionDict.hotbar9, false, GLFW.GLFW_KEY_9), + Triple(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT), + Triple(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL), + Triple(actionDict.jump, wasJumping, GLFW.GLFW_KEY_SPACE), + Triple(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W), + Triple(actionDict.back, wasPressingBack, GLFW.GLFW_KEY_S), + Triple(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A), + Triple(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D), ) for ((action, wasPressing, keyCode) in keys) { val handled = handleScreenKeyPress( From a3ca130a7afffa73e1749e3d25fc46d8b27b698c Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 15:35:53 +0900 Subject: [PATCH 13/29] :bug: Fix mouse screen --- .../minecraft_env/Minecraft_env.kt | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 2d7c1e1..7c1911f 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -57,6 +57,7 @@ enum class ResetPhase { WAIT_PLAYER_DEATH, WAIT_PLAYER_RESPAWN, WAIT_INIT_ENDS, + WAIT_CHUNK_LOADING, END_RESET, } @@ -148,6 +149,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { private var wasAttacking = false private var wasPressingInventory = false private var wasPressingDrop = false + private var waitLoadingCounter = 0 override fun onInitialize() { val ld_preload = System.getenv("LD_PRELOAD") @@ -301,7 +303,17 @@ class Minecraft_env : ModInitializer, CommandExecutor { csvLogger.log("Waiting for the initialization ends") if (initializer.initWorldFinished) { sendSetScreenNull(client) // clear death screen - sleep(1000) // Wait for chunk loading + waitLoadingCounter = 3 // wait for 3 ticks + resetPhase = ResetPhase.WAIT_CHUNK_LOADING + } + return + } + + ResetPhase.WAIT_CHUNK_LOADING -> { + waitLoadingCounter-- + if (waitLoadingCounter <= 0) { + printWithTime("Chunk loading ends") + csvLogger.log("Chunk loading ends") resetPhase = ResetPhase.END_RESET } return @@ -438,8 +450,9 @@ class Minecraft_env : ModInitializer, CommandExecutor { Triple(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A), Triple(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D), ) + var handled = false for ((action, wasPressing, keyCode) in keys) { - val handled = handleScreenKeyPress( + handled = handled || handleScreenKeyPress( action, wasPressing, keyCode, @@ -449,21 +462,14 @@ class Minecraft_env : ModInitializer, CommandExecutor { ) wasPressingInventory = actionDict.inventory wasPressingDrop = actionDict.drop - if (handled) { - return false - } + wasSneaking = actionDict.sneak + wasSprinting = actionDict.sprint + wasJumping = actionDict.jump + wasPressingForward = actionDict.forward + wasPressingBack = actionDict.back + wasPressingLeft = actionDict.left + wasPressingRight = actionDict.right } - } - - wasPressingForward = handleKeyPress(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W) - wasPressingBack = handleKeyPress(actionDict.back, wasPressingBack, GLFW.GLFW_KEY_S) - wasPressingLeft = handleKeyPress(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A) - wasPressingRight = handleKeyPress(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D) - wasJumping = handleKeyPress(actionDict.jump, wasJumping, GLFW.GLFW_KEY_SPACE) - wasSneaking = handleKeyPress(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT) - wasSprinting = handleKeyPress(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL) - - if (currentScreen != null) { if (actionDict.use) { if (!wasUsing) MouseInfo.clickRightButton(wasSneaking) @@ -482,6 +488,20 @@ class Minecraft_env : ModInitializer, CommandExecutor { MouseInfo.releaseLeftButton(wasSneaking) wasAttacking = false } + if (handled) { + return false + } + } + + wasPressingForward = handleKeyPress(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W) + wasPressingBack = handleKeyPress(actionDict.back, wasPressingBack, GLFW.GLFW_KEY_S) + wasPressingLeft = handleKeyPress(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A) + wasPressingRight = handleKeyPress(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D) + wasJumping = handleKeyPress(actionDict.jump, wasJumping, GLFW.GLFW_KEY_SPACE) + wasSneaking = handleKeyPress(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT) + wasSprinting = handleKeyPress(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL) + + if (currentScreen != null) { // wasUsing = false // wasAttacking = false From e67702b8f9df7c8112edf80c5f9575424765b431 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 16:51:34 +0900 Subject: [PATCH 14/29] :bug: Fix keys --- .../minecraft_env/Minecraft_env.kt | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 7c1911f..5e8c79a 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -460,16 +460,16 @@ class Minecraft_env : ModInitializer, CommandExecutor { 0, currentScreen ) - wasPressingInventory = actionDict.inventory - wasPressingDrop = actionDict.drop - wasSneaking = actionDict.sneak - wasSprinting = actionDict.sprint - wasJumping = actionDict.jump - wasPressingForward = actionDict.forward - wasPressingBack = actionDict.back - wasPressingLeft = actionDict.left - wasPressingRight = actionDict.right } + wasPressingInventory = actionDict.inventory + wasPressingDrop = actionDict.drop + wasSneaking = actionDict.sneak + wasSprinting = actionDict.sprint + wasJumping = actionDict.jump + wasPressingForward = actionDict.forward + wasPressingBack = actionDict.back + wasPressingLeft = actionDict.left + wasPressingRight = actionDict.right if (actionDict.use) { if (!wasUsing) MouseInfo.clickRightButton(wasSneaking) @@ -488,9 +488,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { MouseInfo.releaseLeftButton(wasSneaking) wasAttacking = false } - if (handled) { - return false - } + return false } wasPressingForward = handleKeyPress(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W) From df0838ad0576d699509809e09c9382940b1a9358 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 17:07:21 +0900 Subject: [PATCH 15/29] :bug: Handle mouse move first --- .../com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 5e8c79a..831d290 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -428,6 +428,11 @@ class Minecraft_env : ModInitializer, CommandExecutor { ): Boolean { csvLogger.profileStartPrint("Minecraft_env/onInitialize/ClientWorldTick/ReadAction/ApplyAction") MouseInfo.handle = client.window.handle + if (actionDict.cameraYaw != 0.0f || actionDict.cameraYaw != 0.0f) { + val dy = actionDict.cameraPitch * 20.0 / 3 + val dx = actionDict.cameraYaw * 20.0 / 3 + MouseInfo.moveMouseBy(dx.toInt(), dy.toInt()) + } val currentScreen = client.currentScreen if (currentScreen != null) { val keys = listOf( @@ -529,11 +534,6 @@ class Minecraft_env : ModInitializer, CommandExecutor { // To raise head, pitch should be decreased // Move mouse up, pitch should be decreased // Move mouse up = y axis decrease & pitch decrease - if (actionDict.cameraYaw != 0.0f || actionDict.cameraYaw != 0.0f) { - val dy = actionDict.cameraPitch * 20.0 / 3 - val dx = actionDict.cameraYaw * 20.0 / 3 - MouseInfo.moveMouseBy(dx.toInt(), dy.toInt()) - } // } else { // // pitch: 0: -90 degree, 24: 90 degree // val deltaPitchInDeg = actionDict.cameraPitch From d4cccff89b2b2c8d72137b6fa6c66da44f7233f0 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 17:28:48 +0900 Subject: [PATCH 16/29] :bug: Fix mouse --- .../minecraft_env/Minecraft_env.kt | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 831d290..d0396e0 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -504,20 +504,14 @@ class Minecraft_env : ModInitializer, CommandExecutor { wasSneaking = handleKeyPress(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT) wasSprinting = handleKeyPress(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL) - if (currentScreen != null) { - -// wasUsing = false -// wasAttacking = false - } else { - wasUsing = handleKeyPress(actionDict.use, wasUsing, GLFW.GLFW_MOUSE_BUTTON_RIGHT, mouse = true) - wasAttacking = handleKeyPress(actionDict.attack, wasAttacking, GLFW.GLFW_MOUSE_BUTTON_LEFT, mouse = true) - } +// wasUsing = handleKeyPress(actionDict.use, wasUsing, GLFW.GLFW_MOUSE_BUTTON_RIGHT, mouse = true) +// wasAttacking = handleKeyPress(actionDict.attack, wasAttacking, GLFW.GLFW_MOUSE_BUTTON_LEFT, mouse = true) // Should handle screen keys for inventory, drop, hotbars // TODO: Handle swap // handleKeyPress(actionDict.swap, false, GLFW.GLFW_KEY_F) wasPressingDrop = handleKeyPress(actionDict.drop, wasPressingDrop, GLFW.GLFW_KEY_Q) - handleKeyPress(actionDict.inventory, false, GLFW.GLFW_KEY_E) + wasPressingInventory = handleKeyPress(actionDict.inventory, false, GLFW.GLFW_KEY_E) handleKeyPress(actionDict.hotbar1, false, GLFW.GLFW_KEY_1) handleKeyPress(actionDict.hotbar2, false, GLFW.GLFW_KEY_2) handleKeyPress(actionDict.hotbar3, false, GLFW.GLFW_KEY_3) @@ -527,8 +521,24 @@ class Minecraft_env : ModInitializer, CommandExecutor { handleKeyPress(actionDict.hotbar7, false, GLFW.GLFW_KEY_7) handleKeyPress(actionDict.hotbar8, false, GLFW.GLFW_KEY_8) handleKeyPress(actionDict.hotbar9, false, GLFW.GLFW_KEY_9) - - // TODO: Translate delta camera to mouse movement + if (actionDict.use) { + if (!wasUsing) + MouseInfo.clickRightButton(wasSneaking) + wasUsing = true + } else { + if (wasUsing) + MouseInfo.releaseRightButton(wasSneaking) + wasUsing = false + } + if (actionDict.attack) { + if (!wasAttacking) + MouseInfo.clickLeftButton(wasSneaking) + wasAttacking = true + } else { + if (wasAttacking) + MouseInfo.releaseLeftButton(wasSneaking) + wasAttacking = false + } // if (currentScreen != null) { // To raise head, pitch should be decreased From 79e88f06acc5989d6f13576368d9454d254c4265 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 17:30:15 +0900 Subject: [PATCH 17/29] :bug: Fix comparisn --- src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index d0396e0..f722488 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -428,7 +428,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { ): Boolean { csvLogger.profileStartPrint("Minecraft_env/onInitialize/ClientWorldTick/ReadAction/ApplyAction") MouseInfo.handle = client.window.handle - if (actionDict.cameraYaw != 0.0f || actionDict.cameraYaw != 0.0f) { + if (actionDict.cameraYaw != 0.0f || actionDict.cameraPitch != 0.0f) { val dy = actionDict.cameraPitch * 20.0 / 3 val dx = actionDict.cameraYaw * 20.0 / 3 MouseInfo.moveMouseBy(dx.toInt(), dy.toInt()) From 20d8c5f8f1890d2e242778049ea4f73585496e68 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 17:35:46 +0900 Subject: [PATCH 18/29] :bug: Fix mouse handling --- .../minecraft_env/Minecraft_env.kt | 94 ++++++++----------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index f722488..cc5b8d2 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -494,65 +494,51 @@ class Minecraft_env : ModInitializer, CommandExecutor { wasAttacking = false } return false - } - - wasPressingForward = handleKeyPress(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W) - wasPressingBack = handleKeyPress(actionDict.back, wasPressingBack, GLFW.GLFW_KEY_S) - wasPressingLeft = handleKeyPress(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A) - wasPressingRight = handleKeyPress(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D) - wasJumping = handleKeyPress(actionDict.jump, wasJumping, GLFW.GLFW_KEY_SPACE) - wasSneaking = handleKeyPress(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT) - wasSprinting = handleKeyPress(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL) + } else { + wasPressingForward = handleKeyPress(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W) + wasPressingBack = handleKeyPress(actionDict.back, wasPressingBack, GLFW.GLFW_KEY_S) + wasPressingLeft = handleKeyPress(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A) + wasPressingRight = handleKeyPress(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D) + wasJumping = handleKeyPress(actionDict.jump, wasJumping, GLFW.GLFW_KEY_SPACE) + wasSneaking = handleKeyPress(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT) + wasSprinting = handleKeyPress(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL) // wasUsing = handleKeyPress(actionDict.use, wasUsing, GLFW.GLFW_MOUSE_BUTTON_RIGHT, mouse = true) // wasAttacking = handleKeyPress(actionDict.attack, wasAttacking, GLFW.GLFW_MOUSE_BUTTON_LEFT, mouse = true) - // Should handle screen keys for inventory, drop, hotbars - // TODO: Handle swap - // handleKeyPress(actionDict.swap, false, GLFW.GLFW_KEY_F) - wasPressingDrop = handleKeyPress(actionDict.drop, wasPressingDrop, GLFW.GLFW_KEY_Q) - wasPressingInventory = handleKeyPress(actionDict.inventory, false, GLFW.GLFW_KEY_E) - handleKeyPress(actionDict.hotbar1, false, GLFW.GLFW_KEY_1) - handleKeyPress(actionDict.hotbar2, false, GLFW.GLFW_KEY_2) - handleKeyPress(actionDict.hotbar3, false, GLFW.GLFW_KEY_3) - handleKeyPress(actionDict.hotbar4, false, GLFW.GLFW_KEY_4) - handleKeyPress(actionDict.hotbar5, false, GLFW.GLFW_KEY_5) - handleKeyPress(actionDict.hotbar6, false, GLFW.GLFW_KEY_6) - handleKeyPress(actionDict.hotbar7, false, GLFW.GLFW_KEY_7) - handleKeyPress(actionDict.hotbar8, false, GLFW.GLFW_KEY_8) - handleKeyPress(actionDict.hotbar9, false, GLFW.GLFW_KEY_9) - if (actionDict.use) { - if (!wasUsing) - MouseInfo.clickRightButton(wasSneaking) - wasUsing = true - } else { - if (wasUsing) - MouseInfo.releaseRightButton(wasSneaking) - wasUsing = false - } - if (actionDict.attack) { - if (!wasAttacking) - MouseInfo.clickLeftButton(wasSneaking) - wasAttacking = true - } else { - if (wasAttacking) - MouseInfo.releaseLeftButton(wasSneaking) - wasAttacking = false + // Should handle screen keys for inventory, drop, hotbars + // TODO: Handle swap + // handleKeyPress(actionDict.swap, false, GLFW.GLFW_KEY_F) + wasPressingDrop = handleKeyPress(actionDict.drop, wasPressingDrop, GLFW.GLFW_KEY_Q) + wasPressingInventory = handleKeyPress(actionDict.inventory, false, GLFW.GLFW_KEY_E) + handleKeyPress(actionDict.hotbar1, false, GLFW.GLFW_KEY_1) + handleKeyPress(actionDict.hotbar2, false, GLFW.GLFW_KEY_2) + handleKeyPress(actionDict.hotbar3, false, GLFW.GLFW_KEY_3) + handleKeyPress(actionDict.hotbar4, false, GLFW.GLFW_KEY_4) + handleKeyPress(actionDict.hotbar5, false, GLFW.GLFW_KEY_5) + handleKeyPress(actionDict.hotbar6, false, GLFW.GLFW_KEY_6) + handleKeyPress(actionDict.hotbar7, false, GLFW.GLFW_KEY_7) + handleKeyPress(actionDict.hotbar8, false, GLFW.GLFW_KEY_8) + handleKeyPress(actionDict.hotbar9, false, GLFW.GLFW_KEY_9) + if (actionDict.use) { + if (!wasUsing) + MouseInfo.clickRightButton(wasSneaking) + wasUsing = true + } else { + if (wasUsing) + MouseInfo.releaseRightButton(wasSneaking) + wasUsing = false + } + if (actionDict.attack) { + if (!wasAttacking) + MouseInfo.clickLeftButton(wasSneaking) + wasAttacking = true + } else { + if (wasAttacking) + MouseInfo.releaseLeftButton(wasSneaking) + wasAttacking = false + } } - -// if (currentScreen != null) { - // To raise head, pitch should be decreased - // Move mouse up, pitch should be decreased - // Move mouse up = y axis decrease & pitch decrease -// } else { -// // pitch: 0: -90 degree, 24: 90 degree -// val deltaPitchInDeg = actionDict.cameraPitch -// // yaw: 0: -180 degree, 24: 180 degree -// val deltaYawInDeg = actionDict.cameraYaw -// player.pitch += deltaPitchInDeg -// player.yaw += deltaYawInDeg -// player.pitch = MathHelper.clamp(player.pitch, -90.0f, 90.0f) -// } csvLogger.profileEndPrint("Minecraft_env/onInitialize/ClientWorldTick/ReadAction/ApplyAction") return false } From d21bb7275b92962031654be4b8f52cabacaebd1e Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 18:24:22 +0900 Subject: [PATCH 19/29] :bug: Fix screen key press --- .../minecraft_env/Minecraft_env.kt | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index cc5b8d2..b0d8621 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -38,7 +38,6 @@ import net.minecraft.world.World import org.lwjgl.glfw.GLFW import org.lwjgl.opengl.GL11 import java.io.IOException -import java.lang.Thread.sleep import java.net.SocketTimeoutException import java.net.StandardProtocolFamily import java.net.UnixDomainSocketAddress @@ -73,14 +72,8 @@ fun handleKeyPress( currentState: Boolean, wasPressing: Boolean, keyCode: Int, - mouse: Boolean = false ): Boolean { - val key = if (!mouse) { - InputUtil.fromKeyCode(keyCode, 0) - } else { - InputUtil.Type.MOUSE.createFromCode(keyCode) - } - + val key = InputUtil.fromKeyCode(keyCode, 0) // 키가 눌린 상태인지 확인 if (currentState) { KeyBinding.setKeyPressed(key, true) @@ -89,11 +82,6 @@ fun handleKeyPress( KeyBinding.onKeyPressed(key) } } else { - if (mouse) { -// if (wasPressing) { -//// println("Releasing $key") -// } - } KeyBinding.setKeyPressed(key, false) keyMap[keyCode] = false } @@ -455,9 +443,8 @@ class Minecraft_env : ModInitializer, CommandExecutor { Triple(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A), Triple(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D), ) - var handled = false for ((action, wasPressing, keyCode) in keys) { - handled = handled || handleScreenKeyPress( + val handled = handleScreenKeyPress( action, wasPressing, keyCode, @@ -465,6 +452,18 @@ class Minecraft_env : ModInitializer, CommandExecutor { 0, currentScreen ) + if (handled) { + wasPressingInventory = actionDict.inventory + wasPressingDrop = actionDict.drop + wasSneaking = actionDict.sneak + wasSprinting = actionDict.sprint + wasJumping = actionDict.jump + wasPressingForward = actionDict.forward + wasPressingBack = actionDict.back + wasPressingLeft = actionDict.left + wasPressingRight = actionDict.right + return false + } } wasPressingInventory = actionDict.inventory wasPressingDrop = actionDict.drop @@ -503,14 +502,11 @@ class Minecraft_env : ModInitializer, CommandExecutor { wasSneaking = handleKeyPress(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT) wasSprinting = handleKeyPress(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL) -// wasUsing = handleKeyPress(actionDict.use, wasUsing, GLFW.GLFW_MOUSE_BUTTON_RIGHT, mouse = true) -// wasAttacking = handleKeyPress(actionDict.attack, wasAttacking, GLFW.GLFW_MOUSE_BUTTON_LEFT, mouse = true) - // Should handle screen keys for inventory, drop, hotbars // TODO: Handle swap // handleKeyPress(actionDict.swap, false, GLFW.GLFW_KEY_F) wasPressingDrop = handleKeyPress(actionDict.drop, wasPressingDrop, GLFW.GLFW_KEY_Q) - wasPressingInventory = handleKeyPress(actionDict.inventory, false, GLFW.GLFW_KEY_E) + wasPressingInventory = handleKeyPress(actionDict.inventory, wasPressingInventory, GLFW.GLFW_KEY_E) handleKeyPress(actionDict.hotbar1, false, GLFW.GLFW_KEY_1) handleKeyPress(actionDict.hotbar2, false, GLFW.GLFW_KEY_2) handleKeyPress(actionDict.hotbar3, false, GLFW.GLFW_KEY_3) From 55d7f52f53f78aaedee529e0df26f8a7d9eda94b Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 19:56:24 +0900 Subject: [PATCH 20/29] :bug: Fix key --- .../java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index b0d8621..b72260e 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -97,12 +97,17 @@ fun handleScreenKeyPress( modifiers: Int, screen: Screen ): Boolean { + val key = InputUtil.fromKeyCode(keyCode, 0) + keyMap[keyCode] = currentState + KeyBinding.setKeyPressed(key, currentState) if (currentState) { if (!wasPressing) { return screen.keyPressed(keyCode, scanCode, modifiers) } - } else if (wasPressing) { - return screen.keyReleased(keyCode, scanCode, modifiers) + } else { + if (wasPressing) { + return screen.keyReleased(keyCode, scanCode, modifiers) + } } return false } From 333ef64af7cf72896967ce36378ae7bc1b508be7 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 20:30:59 +0900 Subject: [PATCH 21/29] :bug: Fix keybinding --- src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index b72260e..e5965ec 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -99,7 +99,7 @@ fun handleScreenKeyPress( ): Boolean { val key = InputUtil.fromKeyCode(keyCode, 0) keyMap[keyCode] = currentState - KeyBinding.setKeyPressed(key, currentState) +// KeyBinding.setKeyPressed(key, currentState) if (currentState) { if (!wasPressing) { return screen.keyPressed(keyCode, scanCode, modifiers) From 5b225db4c63a38f4b123a816258936107d39cf7e Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 22:48:45 +0900 Subject: [PATCH 22/29] :bug: Fix mouse, disable vsync --- .../minecraft_env/EnvironmentInitializer.kt | 2 +- .../minecraft_env/Minecraft_env.kt | 2 +- .../kyhsgeekcode/minecraft_env/MouseInfo.kt | 19 ++++++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt index c764b28..f4a13ff 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt @@ -71,7 +71,7 @@ class EnvironmentInitializer( setHudHidden(client, initialEnvironment.hudHidden) setRenderDistance(client, initialEnvironment.renderDistance) setSimulationDistance(client, initialEnvironment.simulationDistance) - disableVSync(client) +// disableVSync(client) disableSound(client) disableTutorial(client) setMaxFPSToUnlimited(client) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index e5965ec..0608cbb 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -424,7 +424,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { if (actionDict.cameraYaw != 0.0f || actionDict.cameraPitch != 0.0f) { val dy = actionDict.cameraPitch * 20.0 / 3 val dx = actionDict.cameraYaw * 20.0 / 3 - MouseInfo.moveMouseBy(dx.toInt(), dy.toInt()) + MouseInfo.moveMouseBy(dx, dy) } val currentScreen = client.currentScreen if (currentScreen != null) { diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt index 7076b18..3463b1c 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt @@ -34,27 +34,32 @@ object MouseInfo { showCursor = show } - fun moveMouseBy(dx: Int, dy: Int) { + fun moveMouseBy(dx: Double, dy: Double) { // dx와 dy의 절대값 계산 - val stepsX = Math.abs(dx) - val stepsY = Math.abs(dy) + val absDx = Math.abs(dx) + val absDy = Math.abs(dy) // 가로로 이동 (dx 방향) - val stepX = if (dx > 0) 1 else -1 - for (i in 0 until stepsX) { + val stepX = if (dx > 0) 0.1 else -0.1 // Double 단위로 0.1씩 이동 + var currentX = 0.0 + while (currentX < absDx) { mouseX += stepX + currentX += Math.abs(stepX) cursorPosCallback?.invoke(handle, mouseX, mouseY) } // 세로로 이동 (dy 방향) - val stepY = if (dy > 0) 1 else -1 - for (i in 0 until stepsY) { + val stepY = if (dy > 0) 0.1 else -0.1 // Double 단위로 0.1씩 이동 + var currentY = 0.0 + while (currentY < absDy) { mouseY += stepY + currentY += Math.abs(stepY) cursorPosCallback?.invoke(handle, mouseX, mouseY) } } + // TODO: Mods (shift click, etc) fun clickLeftButton(shift: Boolean) { val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 From 6da5fa5ea74603ac8422d9e1c53cfb01291af41a Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sat, 14 Sep 2024 23:25:01 +0900 Subject: [PATCH 23/29] :necktie: Do not disable tutorial --- .../com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt index f4a13ff..aee1617 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/EnvironmentInitializer.kt @@ -73,7 +73,7 @@ class EnvironmentInitializer( setSimulationDistance(client, initialEnvironment.simulationDistance) // disableVSync(client) disableSound(client) - disableTutorial(client) +// disableTutorial(client) setMaxFPSToUnlimited(client) if (initialEnvironment.noFovEffect) { setFovEffectDisabled(client) From 651e3dc7cce5a8b4cb117122075ff61c522aa095 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sun, 15 Sep 2024 00:36:00 +0900 Subject: [PATCH 24/29] :necktie: Disable mouse center --- .../com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java index 625d1d8..88d12b3 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java @@ -22,7 +22,7 @@ public static void setMouseCallbacks(long handle, GLFWCursorPosCallbackI cursorP @Overwrite public static void setCursorParameters(long handler, int inputModeValue, double x, double y) { - MouseInfo.INSTANCE.setCursorPos(x, y); +// MouseInfo.INSTANCE.setCursorPos(x, y); MouseInfo.INSTANCE.setCursorShown(inputModeValue == GLFW.GLFW_CURSOR_NORMAL); } } From 0ef65ca0b1890c464be8239db5230bf40c4f2dc9 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sun, 15 Sep 2024 00:44:39 +0900 Subject: [PATCH 25/29] :bug: Mix dx dy in mouse,call center mouse agian --- .../minecraft_env/Minecraft_env.kt | 2 +- .../kyhsgeekcode/minecraft_env/MouseInfo.kt | 43 +++++++++++-------- .../minecraft_env/mixin/InputUtilMixin.java | 2 +- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 0608cbb..e5965ec 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -424,7 +424,7 @@ class Minecraft_env : ModInitializer, CommandExecutor { if (actionDict.cameraYaw != 0.0f || actionDict.cameraPitch != 0.0f) { val dy = actionDict.cameraPitch * 20.0 / 3 val dx = actionDict.cameraYaw * 20.0 / 3 - MouseInfo.moveMouseBy(dx, dy) + MouseInfo.moveMouseBy(dx.toInt(), dy.toInt()) } val currentScreen = client.currentScreen if (currentScreen != null) { diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt index 3463b1c..9813842 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt @@ -34,27 +34,32 @@ object MouseInfo { showCursor = show } - fun moveMouseBy(dx: Double, dy: Double) { - // dx와 dy의 절대값 계산 - val absDx = Math.abs(dx) - val absDy = Math.abs(dy) + fun moveMouseBy(dx: Int, dy: Int) { + // dx와 dy의 절대값 계산 (정수로 변환) + val stepsX = Math.abs(dx) + val stepsY = Math.abs(dy) - // 가로로 이동 (dx 방향) - val stepX = if (dx > 0) 0.1 else -0.1 // Double 단위로 0.1씩 이동 - var currentX = 0.0 - while (currentX < absDx) { - mouseX += stepX - currentX += Math.abs(stepX) - cursorPosCallback?.invoke(handle, mouseX, mouseY) - } + // dx와 dy의 이동 방향 계산 + val stepX = if (dx > 0) 1 else -1 + val stepY = if (dy > 0) 1 else -1 + + // 최대 이동 횟수 계산 (더 큰 쪽을 기준으로 반복) + val maxSteps = Math.max(stepsX, stepsY) - // 세로로 이동 (dy 방향) - val stepY = if (dy > 0) 0.1 else -0.1 // Double 단위로 0.1씩 이동 - var currentY = 0.0 - while (currentY < absDy) { - mouseY += stepY - currentY += Math.abs(stepY) - cursorPosCallback?.invoke(handle, mouseX, mouseY) + // X와 Y를 번갈아 가며 이동 + var movedX = 0 + var movedY = 0 + for (i in 0 until maxSteps) { + if (movedX < stepsX) { + mouseX += stepX + cursorPosCallback?.invoke(handle, mouseX, mouseY) + movedX++ + } + if (movedY < stepsY) { + mouseY += stepY + cursorPosCallback?.invoke(handle, mouseX, mouseY) + movedY++ + } } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java index 88d12b3..625d1d8 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java @@ -22,7 +22,7 @@ public static void setMouseCallbacks(long handle, GLFWCursorPosCallbackI cursorP @Overwrite public static void setCursorParameters(long handler, int inputModeValue, double x, double y) { -// MouseInfo.INSTANCE.setCursorPos(x, y); + MouseInfo.INSTANCE.setCursorPos(x, y); MouseInfo.INSTANCE.setCursorShown(inputModeValue == GLFW.GLFW_CURSOR_NORMAL); } } From c7cd83bfd7eafd21813a8029a83b3c029912c6f9 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sun, 15 Sep 2024 13:00:19 +0900 Subject: [PATCH 26/29] :recycle: Refactor inputs --- .../minecraft_env/KeyboardInfo.kt | 84 ++++++++ .../minecraft_env/Minecraft_env.kt | 180 +----------------- .../kyhsgeekcode/minecraft_env/MouseInfo.kt | 64 ++++--- .../minecraft_env/mixin/InputUtilMixin.java | 13 +- .../minecraft_env/mixin/KeyboardMixin.java | 20 -- .../com.kyhsgeekcode.minecraft_env.mixin.json | 1 - 6 files changed, 131 insertions(+), 231 deletions(-) create mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/KeyboardInfo.kt delete mode 100644 src/main/java/com/kyhsgeekcode/minecraft_env/mixin/KeyboardMixin.java diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/KeyboardInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/KeyboardInfo.kt new file mode 100644 index 0000000..8542d14 --- /dev/null +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/KeyboardInfo.kt @@ -0,0 +1,84 @@ +package com.kyhsgeekcode.minecraft_env + +import com.kyhsgeekcode.minecraft_env.proto.ActionSpace +import org.lwjgl.glfw.GLFW.* +import org.lwjgl.glfw.GLFWCharModsCallbackI +import org.lwjgl.glfw.GLFWKeyCallbackI + +object KeyboardInfo { + var charModsCallback: GLFWCharModsCallbackI? = null + var keyCallback: GLFWKeyCallbackI? = null + var handle: Long = 0 + + var currentState: MutableMap = mutableMapOf() + + val keyMappings = mapOf( + "W" to GLFW_KEY_W, + "A" to GLFW_KEY_A, + "S" to GLFW_KEY_S, + "D" to GLFW_KEY_D, + "LShift" to GLFW_KEY_LEFT_SHIFT, + "Ctrl" to GLFW_KEY_LEFT_CONTROL, + "Space" to GLFW_KEY_SPACE, + "E" to GLFW_KEY_E, + "Q" to GLFW_KEY_Q, +// "F" to GLFW_KEY_F, + "Hotbar1" to GLFW_KEY_1, + "Hotbar2" to GLFW_KEY_2, + "Hotbar3" to GLFW_KEY_3, + "Hotbar4" to GLFW_KEY_4, + "Hotbar5" to GLFW_KEY_5, + "Hotbar6" to GLFW_KEY_6, + "Hotbar7" to GLFW_KEY_7, + "Hotbar8" to GLFW_KEY_8, + "Hotbar9" to GLFW_KEY_9, + ) + + fun onAction(actionDict: ActionSpace.ActionSpaceMessageV2) { + val actions = mapOf( + "W" to actionDict.forward, + "A" to actionDict.left, + "S" to actionDict.back, + "D" to actionDict.right, + "LShift" to actionDict.sneak, + "Ctrl" to actionDict.sprint, + "Space" to actionDict.jump, + "E" to actionDict.inventory, + "Q" to actionDict.drop, +// "F" to actionDict.swapHands, + "Hotbar1" to actionDict.hotbar1, + "Hotbar2" to actionDict.hotbar2, + "Hotbar3" to actionDict.hotbar3, + "Hotbar4" to actionDict.hotbar4, + "Hotbar5" to actionDict.hotbar5, + "Hotbar6" to actionDict.hotbar6, + "Hotbar7" to actionDict.hotbar7, + "Hotbar8" to actionDict.hotbar8, + "Hotbar9" to actionDict.hotbar9, + ) + + // 각 키의 상태를 비교하여 변화가 있으면 keyCallback 호출 + for ((key, glfwKey) in keyMappings) { + val previousState = currentState[glfwKey] ?: false + val currentState = actions[key] ?: false + + if (!previousState && currentState) { + // 키가 처음 눌렸을 때 GLFW_PRESS 호출 + keyCallback?.invoke(handle, glfwKey, 0, GLFW_PRESS, 0) + } else if (previousState && currentState) { + // 키가 계속 눌린 상태라면 GLFW_REPEAT 호출 + keyCallback?.invoke(handle, glfwKey, 0, GLFW_REPEAT, 0) + } else if (previousState && !currentState) { + // 키가 떼졌을 때 GLFW_RELEASE 호출 + keyCallback?.invoke(handle, glfwKey, 0, GLFW_RELEASE, 0) + } + + // 현재 상태 갱신 + this.currentState[glfwKey] = currentState + } + } + + fun isKeyPressed(key: Int): Boolean { + return currentState[key] ?: false + } +} \ No newline at end of file diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index e5965ec..237ce1a 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -15,11 +15,8 @@ import net.minecraft.block.BlockState import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient.IS_SYSTEM_MAC import net.minecraft.client.gui.screen.DeathScreen -import net.minecraft.client.gui.screen.Screen import net.minecraft.client.network.ClientPlayerEntity -import net.minecraft.client.option.KeyBinding import net.minecraft.client.render.BackgroundRenderer -import net.minecraft.client.util.InputUtil import net.minecraft.client.world.ClientWorld import net.minecraft.entity.EntityType import net.minecraft.network.packet.c2s.play.ClientStatusC2SPacket @@ -35,7 +32,6 @@ import net.minecraft.util.math.Vec3d import net.minecraft.util.registry.Registry import net.minecraft.util.shape.VoxelShapes import net.minecraft.world.World -import org.lwjgl.glfw.GLFW import org.lwjgl.opengl.GL11 import java.io.IOException import java.net.SocketTimeoutException @@ -68,52 +64,6 @@ enum class IOPhase { SENT_OBSERVATION_SHOULD_READ_ACTION, } -fun handleKeyPress( - currentState: Boolean, - wasPressing: Boolean, - keyCode: Int, -): Boolean { - val key = InputUtil.fromKeyCode(keyCode, 0) - // 키가 눌린 상태인지 확인 - if (currentState) { - KeyBinding.setKeyPressed(key, true) - keyMap[keyCode] = true - if (!wasPressing) { - KeyBinding.onKeyPressed(key) - } - } else { - KeyBinding.setKeyPressed(key, false) - keyMap[keyCode] = false - } - - return currentState -} - -fun handleScreenKeyPress( - currentState: Boolean, - wasPressing: Boolean, - keyCode: Int, - scanCode: Int, - modifiers: Int, - screen: Screen -): Boolean { - val key = InputUtil.fromKeyCode(keyCode, 0) - keyMap[keyCode] = currentState -// KeyBinding.setKeyPressed(key, currentState) - if (currentState) { - if (!wasPressing) { - return screen.keyPressed(keyCode, scanCode, modifiers) - } - } else { - if (wasPressing) { - return screen.keyReleased(keyCode, scanCode, modifiers) - } - } - return false -} - - -val keyMap = java.util.HashMap() class Minecraft_env : ModInitializer, CommandExecutor { private lateinit var initialEnvironment: InitialEnvironment.InitialEnvironmentMessage @@ -130,18 +80,6 @@ class Minecraft_env : ModInitializer, CommandExecutor { private var skipSync = false private var ioPhase = IOPhase.BEGINNING - // Difference matters - private var wasPressingForward = false - private var wasPressingBack = false - private var wasPressingLeft = false - private var wasPressingRight = false - private var wasJumping = false - private var wasSneaking = false - private var wasSprinting = false - private var wasUsing = false - private var wasAttacking = false - private var wasPressingInventory = false - private var wasPressingDrop = false private var waitLoadingCounter = 0 override fun onInitialize() { @@ -420,126 +358,14 @@ class Minecraft_env : ModInitializer, CommandExecutor { client: MinecraftClient ): Boolean { csvLogger.profileStartPrint("Minecraft_env/onInitialize/ClientWorldTick/ReadAction/ApplyAction") - MouseInfo.handle = client.window.handle if (actionDict.cameraYaw != 0.0f || actionDict.cameraPitch != 0.0f) { val dy = actionDict.cameraPitch * 20.0 / 3 val dx = actionDict.cameraYaw * 20.0 / 3 MouseInfo.moveMouseBy(dx.toInt(), dy.toInt()) } - val currentScreen = client.currentScreen - if (currentScreen != null) { - val keys = listOf( - Triple(actionDict.inventory, wasPressingInventory, GLFW.GLFW_KEY_E), - Triple(actionDict.drop, wasPressingDrop, GLFW.GLFW_KEY_Q), - Triple(actionDict.hotbar1, false, GLFW.GLFW_KEY_1), - Triple(actionDict.hotbar2, false, GLFW.GLFW_KEY_2), - Triple(actionDict.hotbar3, false, GLFW.GLFW_KEY_3), - Triple(actionDict.hotbar4, false, GLFW.GLFW_KEY_4), - Triple(actionDict.hotbar5, false, GLFW.GLFW_KEY_5), - Triple(actionDict.hotbar6, false, GLFW.GLFW_KEY_6), - Triple(actionDict.hotbar7, false, GLFW.GLFW_KEY_7), - Triple(actionDict.hotbar8, false, GLFW.GLFW_KEY_8), - Triple(actionDict.hotbar9, false, GLFW.GLFW_KEY_9), - Triple(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT), - Triple(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL), - Triple(actionDict.jump, wasJumping, GLFW.GLFW_KEY_SPACE), - Triple(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W), - Triple(actionDict.back, wasPressingBack, GLFW.GLFW_KEY_S), - Triple(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A), - Triple(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D), - ) - for ((action, wasPressing, keyCode) in keys) { - val handled = handleScreenKeyPress( - action, - wasPressing, - keyCode, - 0, - 0, - currentScreen - ) - if (handled) { - wasPressingInventory = actionDict.inventory - wasPressingDrop = actionDict.drop - wasSneaking = actionDict.sneak - wasSprinting = actionDict.sprint - wasJumping = actionDict.jump - wasPressingForward = actionDict.forward - wasPressingBack = actionDict.back - wasPressingLeft = actionDict.left - wasPressingRight = actionDict.right - return false - } - } - wasPressingInventory = actionDict.inventory - wasPressingDrop = actionDict.drop - wasSneaking = actionDict.sneak - wasSprinting = actionDict.sprint - wasJumping = actionDict.jump - wasPressingForward = actionDict.forward - wasPressingBack = actionDict.back - wasPressingLeft = actionDict.left - wasPressingRight = actionDict.right - if (actionDict.use) { - if (!wasUsing) - MouseInfo.clickRightButton(wasSneaking) - wasUsing = true - } else { - if (wasUsing) - MouseInfo.releaseRightButton(wasSneaking) - wasUsing = false - } - if (actionDict.attack) { - if (!wasAttacking) - MouseInfo.clickLeftButton(wasSneaking) - wasAttacking = true - } else { - if (wasAttacking) - MouseInfo.releaseLeftButton(wasSneaking) - wasAttacking = false - } - return false - } else { - wasPressingForward = handleKeyPress(actionDict.forward, wasPressingForward, GLFW.GLFW_KEY_W) - wasPressingBack = handleKeyPress(actionDict.back, wasPressingBack, GLFW.GLFW_KEY_S) - wasPressingLeft = handleKeyPress(actionDict.left, wasPressingLeft, GLFW.GLFW_KEY_A) - wasPressingRight = handleKeyPress(actionDict.right, wasPressingRight, GLFW.GLFW_KEY_D) - wasJumping = handleKeyPress(actionDict.jump, wasJumping, GLFW.GLFW_KEY_SPACE) - wasSneaking = handleKeyPress(actionDict.sneak, wasSneaking, GLFW.GLFW_KEY_LEFT_SHIFT) - wasSprinting = handleKeyPress(actionDict.sprint, wasSprinting, GLFW.GLFW_KEY_LEFT_CONTROL) - - // Should handle screen keys for inventory, drop, hotbars - // TODO: Handle swap - // handleKeyPress(actionDict.swap, false, GLFW.GLFW_KEY_F) - wasPressingDrop = handleKeyPress(actionDict.drop, wasPressingDrop, GLFW.GLFW_KEY_Q) - wasPressingInventory = handleKeyPress(actionDict.inventory, wasPressingInventory, GLFW.GLFW_KEY_E) - handleKeyPress(actionDict.hotbar1, false, GLFW.GLFW_KEY_1) - handleKeyPress(actionDict.hotbar2, false, GLFW.GLFW_KEY_2) - handleKeyPress(actionDict.hotbar3, false, GLFW.GLFW_KEY_3) - handleKeyPress(actionDict.hotbar4, false, GLFW.GLFW_KEY_4) - handleKeyPress(actionDict.hotbar5, false, GLFW.GLFW_KEY_5) - handleKeyPress(actionDict.hotbar6, false, GLFW.GLFW_KEY_6) - handleKeyPress(actionDict.hotbar7, false, GLFW.GLFW_KEY_7) - handleKeyPress(actionDict.hotbar8, false, GLFW.GLFW_KEY_8) - handleKeyPress(actionDict.hotbar9, false, GLFW.GLFW_KEY_9) - if (actionDict.use) { - if (!wasUsing) - MouseInfo.clickRightButton(wasSneaking) - wasUsing = true - } else { - if (wasUsing) - MouseInfo.releaseRightButton(wasSneaking) - wasUsing = false - } - if (actionDict.attack) { - if (!wasAttacking) - MouseInfo.clickLeftButton(wasSneaking) - wasAttacking = true - } else { - if (wasAttacking) - MouseInfo.releaseLeftButton(wasSneaking) - wasAttacking = false - } - } + // Handle key press + KeyboardInfo.onAction(actionDict) + MouseInfo.onAction(actionDict) csvLogger.profileEndPrint("Minecraft_env/onInitialize/ClientWorldTick/ReadAction/ApplyAction") return false } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt index 9813842..5e32955 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt @@ -1,8 +1,9 @@ package com.kyhsgeekcode.minecraft_env import com.kyhsgeekcode.minecraft_env.mixin.MouseXYAccessor +import com.kyhsgeekcode.minecraft_env.proto.ActionSpace import net.minecraft.client.MinecraftClient -import org.lwjgl.glfw.GLFW +import org.lwjgl.glfw.GLFW.* import org.lwjgl.glfw.GLFWCursorPosCallbackI import org.lwjgl.glfw.GLFWMouseButtonCallbackI @@ -12,10 +13,40 @@ object MouseInfo { var mouseButtonCallback: GLFWMouseButtonCallbackI? = null var mouseX: Double = 0.0 var mouseY: Double = 0.0 - var leftButtonPressed: Boolean = false - var rightButtonPressed: Boolean = false var showCursor: Boolean = false + var currentState: MutableMap = mutableMapOf() + + val buttonMappings = mapOf( + "use" to GLFW_MOUSE_BUTTON_LEFT, + "attack" to GLFW_MOUSE_BUTTON_RIGHT + ) + + fun onAction(actionDict: ActionSpace.ActionSpaceMessageV2) { + val actions = mapOf( + "use" to actionDict.use, + "attack" to actionDict.attack + ) + val shift = KeyboardInfo.isKeyPressed(GLFW_KEY_LEFT_SHIFT) + val mods = if (shift) GLFW_MOD_SHIFT else 0 + // 각 마우스 버튼 상태를 비교하여 변화가 있으면 mouseCallback 호출 + for ((action, glfwButton) in buttonMappings) { + val previousState = currentState[glfwButton] ?: false + val currentState = actions[action] ?: false + + if (!previousState && currentState) { + // 마우스 버튼이 처음 눌렸을 때 GLFW_PRESS 호출 + mouseButtonCallback?.invoke(handle, glfwButton, GLFW_PRESS, mods) + } else if (previousState && !currentState) { + // 마우스 버튼을 뗐을 때 GLFW_RELEASE 호출 + mouseButtonCallback?.invoke(handle, glfwButton, GLFW_RELEASE, mods) + } + + // 현재 상태 갱신 + this.currentState[glfwButton] = currentState + } + } + fun getMousePos(): Pair { return Pair(mouseX, mouseY) } @@ -62,31 +93,4 @@ object MouseInfo { } } } - - - - // TODO: Mods (shift click, etc) - fun clickLeftButton(shift: Boolean) { - val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_PRESS, mods) - leftButtonPressed = true - } - - fun releaseLeftButton(shift: Boolean) { - val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_RELEASE, mods) - leftButtonPressed = false - } - - fun clickRightButton(shift: Boolean) { - val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_RIGHT, GLFW.GLFW_PRESS, mods) - rightButtonPressed = true - } - - fun releaseRightButton(shift: Boolean) { - val mods = if (shift) GLFW.GLFW_MOD_SHIFT else 0 - mouseButtonCallback?.invoke(handle, GLFW.GLFW_MOUSE_BUTTON_RIGHT, GLFW.GLFW_RELEASE, mods) - rightButtonPressed = false - } } \ No newline at end of file diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java index 625d1d8..9d668b2 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/InputUtilMixin.java @@ -1,23 +1,23 @@ package com.kyhsgeekcode.minecraft_env.mixin; +import com.kyhsgeekcode.minecraft_env.KeyboardInfo; import com.kyhsgeekcode.minecraft_env.MouseInfo; import org.lwjgl.glfw.*; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; -import static com.kyhsgeekcode.minecraft_env.Minecraft_envKt.getKeyMap; - @Mixin(net.minecraft.client.util.InputUtil.class) public class InputUtilMixin { @Overwrite public static boolean isKeyPressed(long handle, int code) { - return getKeyMap().getOrDefault(code, false); + return KeyboardInfo.INSTANCE.isKeyPressed(code); } @Overwrite public static void setMouseCallbacks(long handle, GLFWCursorPosCallbackI cursorPosCallback, GLFWMouseButtonCallbackI mouseButtonCallback, GLFWScrollCallbackI scrollCallback, GLFWDropCallbackI dropCallback) { MouseInfo.INSTANCE.setCursorPosCallback(cursorPosCallback); MouseInfo.INSTANCE.setMouseButtonCallback(mouseButtonCallback); + MouseInfo.INSTANCE.setHandle(handle); } @Overwrite @@ -25,4 +25,11 @@ public static void setCursorParameters(long handler, int inputModeValue, double MouseInfo.INSTANCE.setCursorPos(x, y); MouseInfo.INSTANCE.setCursorShown(inputModeValue == GLFW.GLFW_CURSOR_NORMAL); } + + @Overwrite + public static void setKeyboardCallbacks(long handle, GLFWKeyCallbackI keyCallback, GLFWCharModsCallbackI charModsCallback) { + KeyboardInfo.INSTANCE.setKeyCallback(keyCallback); + KeyboardInfo.INSTANCE.setCharModsCallback(charModsCallback); + KeyboardInfo.INSTANCE.setHandle(handle); + } } diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/KeyboardMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/KeyboardMixin.java deleted file mode 100644 index 67ee6ef..0000000 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/KeyboardMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.kyhsgeekcode.minecraft_env.mixin; - -import net.minecraft.client.Keyboard; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Keyboard.class) -public class KeyboardMixin { - @Inject(method = "setup", at = @At("HEAD"), cancellable = true) - private void setKeyboardCallbacks(CallbackInfo ci) { - ci.cancel(); - // Call onKey, onChar directly to handle inputs, no external keyboard inputs - } -} - - - - diff --git a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json index c8e0377..6ae4897 100644 --- a/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json +++ b/src/main/resources/com.kyhsgeekcode.minecraft_env.mixin.json @@ -19,7 +19,6 @@ "ClientWorldMixin", "CreateWorldScreenMoreOptionsAccessor", "InputUtilMixin", - "KeyboardMixin", "MoreOptionsDialogSeedTextFieldAccessor", "MouseXYAccessor", "RenderTickCounterAccessor", From 993cf1170c0f1e0bc9e5d48ff453d5b189c24589 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Sun, 15 Sep 2024 13:40:50 +0900 Subject: [PATCH 27/29] :bug: Fix mouse rl --- src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt index 5e32955..4cb604b 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/MouseInfo.kt @@ -18,8 +18,8 @@ object MouseInfo { var currentState: MutableMap = mutableMapOf() val buttonMappings = mapOf( - "use" to GLFW_MOUSE_BUTTON_LEFT, - "attack" to GLFW_MOUSE_BUTTON_RIGHT + "use" to GLFW_MOUSE_BUTTON_RIGHT, + "attack" to GLFW_MOUSE_BUTTON_LEFT ) fun onAction(actionDict: ActionSpace.ActionSpaceMessageV2) { From fc9d69f4d34db07a6e7ee3e931d2b9cc81a8a782 Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Mon, 16 Sep 2024 12:28:48 +0900 Subject: [PATCH 28/29] :bug: Disable clicking disconnect --- .../minecraft_env/Minecraft_env.kt | 5 +++ .../mixin/MinecraftServer_tickspeedMixin.java | 32 ++++--------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt index 237ce1a..4a1b5ce 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/Minecraft_env.kt @@ -365,6 +365,11 @@ class Minecraft_env : ModInitializer, CommandExecutor { } // Handle key press KeyboardInfo.onAction(actionDict) + val currentScreen = client.currentScreen + if (currentScreen != null && currentScreen is DeathScreen) { + // Disable disconnect button + return false + } MouseInfo.onAction(actionDict) csvLogger.profileEndPrint("Minecraft_env/onInitialize/ClientWorldTick/ReadAction/ApplyAction") return false diff --git a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java index ffa652b..da395db 100644 --- a/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/com/kyhsgeekcode/minecraft_env/mixin/MinecraftServer_tickspeedMixin.java @@ -90,49 +90,29 @@ private void modifiedRunLoop(CallbackInfo ci) { //CM deciding on tick speed long msThisTick = 0L; long long_1 = 0L; -// if (TickSpeed.time_warp_start_time != 0) { -// //making sure server won't flop after the warp or if the warp is interrupted -// this.timeReference = this.lastTimeReference = Util.getMeasuringTimeMs(); -// carpetMsptAccum = TickSpeed.INSTANCE.getMspt(); -// } else { - if (Math.abs(carpetMsptAccum - TickSpeed.INSTANCE.getMspt()) > 1.0f) { - // Tickrate changed. Ensure that we use the correct value. - carpetMsptAccum = TickSpeed.INSTANCE.getMspt(); - } - msThisTick = (long) carpetMsptAccum; // regular tick carpetMsptAccum += TickSpeed.INSTANCE.getMspt() - msThisTick; - long_1 = Util.getMeasuringTimeMs() - this.timeReference; -// } //end tick deciding //smoothed out delay to include mcpt component. With 50L gives defaults. if (long_1 > /*2000L*/1000L + 20 * TickSpeed.INSTANCE.getMspt() && this.timeReference - this.lastTimeReference >= /*15000L*/10000L + 100 * TickSpeed.INSTANCE.getMspt()) { - long long_2 = (long) (long_1 / TickSpeed.INSTANCE.getMspt());//50L; + long long_2 = long_1 / TickSpeed.INSTANCE.getMspt();//50L; LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", long_1, long_2); - this.timeReference += (long) (long_2 * TickSpeed.INSTANCE.getMspt());//50L; + this.timeReference += long_2 * TickSpeed.INSTANCE.getMspt();//50L; this.lastTimeReference = this.timeReference; } this.timeReference += msThisTick;//50L; - TickDurationMonitor tickDurationMonitor = TickDurationMonitor.create("Server"); - this.startMonitor(tickDurationMonitor); - this.profiler.startTick(); - this.profiler.push("tick"); this.tick(this::shouldKeepTicking); - this.profiler.swap("nextTickWait"); -// if (TickSpeed.time_warp_start_time != 0) // clearing all hanging tasks no matter what when warping - { - while (this.runEveryTask()) { - Thread.yield(); - } + while (this.runEveryTask()) { + Thread.yield(); } this.waitingForNextTick = true; this.field_19248 = Math.max(Util.getMeasuringTimeMs() + /*50L*/ msThisTick, this.timeReference); // run all tasks (this will not do a lot when warping), but that's fine since we already run them this.method_16208(); - this.profiler.pop(); - this.profiler.endTick(); +// this.profiler.pop(); +// this.profiler.endTick(); this.loading = true; } } From 828ade9606986ea0eadb136158cd3a3170fcd77c Mon Sep 17 00:00:00 2001 From: yhs0602 Date: Tue, 17 Sep 2024 12:49:40 +0900 Subject: [PATCH 29/29] :bug: Fix sigsegv --- src/main/cpp/framebuffer_capturer.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/cpp/framebuffer_capturer.cpp b/src/main/cpp/framebuffer_capturer.cpp index 9f3590c..858bc45 100644 --- a/src/main/cpp/framebuffer_capturer.cpp +++ b/src/main/cpp/framebuffer_capturer.cpp @@ -222,19 +222,21 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_kyhsgeekcode_minecraft_1env_Frameb // Invert y axis int index = ((targetSizeY - pixelY) * targetSizeX + pixelX) * 3; // 픽셀 인덱스 계산 - // 비트맵 값이 2면 검은색(테두리)로 그립니다. - if (cursor[dy][dx] == 2) { - pixels[index] = 0; // Red - pixels[index + 1] = 0; // Green - pixels[index + 2] = 0; // Blue + if (index >= 0 && index + 2 < textureWidth * textureHeight * 3) { + // 비트맵 값이 2면 검은색(테두리)로 그립니다. + if (cursor[dy][dx] == 2) { + pixels[index] = 0; // Red + pixels[index + 1] = 0; // Green + pixels[index + 2] = 0; // Blue + } + // 비트맵 값이 1이면 흰색(내부)로 그립니다. + else if (cursor[dy][dx] == 1) { + pixels[index] = 255; // Red + pixels[index + 1] = 255; // Green + pixels[index + 2] = 255; // Blue + } + // 비트맵 값이 0이면 투명, 기존 픽셀을 유지합니다. } - // 비트맵 값이 1이면 흰색(내부)로 그립니다. - else if (cursor[dy][dx] == 1) { - pixels[index] = 255; // Red - pixels[index + 1] = 255; // Green - pixels[index + 2] = 255; // Blue - } - // 비트맵 값이 0이면 투명, 기존 픽셀을 유지합니다. } } }