Skip to content

Commit 4fcdc2c

Browse files
committed
Switch to JSON serialization
1 parent 933e0d0 commit 4fcdc2c

15 files changed

Lines changed: 196 additions & 166 deletions

src/client/kotlin/com/github/fdh911/modules/ModuleGardenMacro.kt

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.github.fdh911.modules
22

3-
import com.github.fdh911.modules.macro.nodeactions.INodeAction
3+
import com.github.fdh911.modules.macro.nodeactions.NodeAction
44
import com.github.fdh911.modules.macro.Node
55
import com.github.fdh911.modules.macro.nodeactions.NodeActionLockMouse
66
import com.github.fdh911.modules.macro.nodeactions.NodeActionRotateDelta
@@ -22,6 +22,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi
2222
import kotlinx.coroutines.GlobalScope
2323
import kotlinx.coroutines.delay
2424
import kotlinx.coroutines.launch
25+
import kotlinx.serialization.json.Json
2526
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext
2627
import net.minecraft.client.MinecraftClient
2728
import net.minecraft.util.math.BlockPos
@@ -36,10 +37,11 @@ import kotlin.math.min
3637
import kotlin.text.get
3738

3839
@OptIn(DelicateCoroutinesApi::class)
39-
object ModuleGardenMacro: Module("Garden Macro") {
40+
object ModuleGardenMacro: Module("Garden Macro")
41+
{
4042
var currentScene: NodeScene? = null
4143
var currentNode: Node? = null
42-
private val actionQueue: Queue<INodeAction> = LinkedList()
44+
private val actionQueue: Queue<NodeAction> = LinkedList()
4345

4446
init {
4547
GlobalScope.launch {
@@ -141,7 +143,7 @@ object ModuleGardenMacro: Module("Garden Macro") {
141143
var sceneCreation = false
142144
val sceneCreationNameEdit = ImString()
143145
var nodePtr: Node? = null
144-
var actionPtr: INodeAction? = null
146+
var actionPtr: NodeAction? = null
145147
val nodeNameEdit = ImString()
146148
val nodeX = ImInt()
147149
val nodeY = ImInt()
@@ -178,7 +180,7 @@ object ModuleGardenMacro: Module("Garden Macro") {
178180
else UIState.sceneCreation = false
179181

180182
if(ImGui.button("Save scene")) {
181-
currentScene!!.saveToFile()
183+
currentScene?.saveToFile()
182184
}
183185
ImGui.sameLine()
184186
if(ImGui.button("Load scene") || UIState.sceneLoading) {
@@ -188,9 +190,12 @@ object ModuleGardenMacro: Module("Garden Macro") {
188190
val files = File(".").listFiles()
189191
for(i in files.indices) {
190192
val subfile = files[i]
191-
if(!subfile.name.matches(".*mysecondmod[.]scene[.]txt".toRegex())) continue
192-
if(ImGui.selectable("${subfile.nameWithoutExtension}##_file$i")) {
193-
currentScene = NodeScene.Companion.loadFromFile(subfile)
193+
val fileSearchRegex = "(?<scenename>[^.]+)[.]msmscene[.]json".toRegex()
194+
val match = fileSearchRegex.matchEntire(subfile.name)
195+
?: continue
196+
val sceneName = match.groups["scenename"]!!.value
197+
if(ImGui.selectable("$sceneName##_file$i")) {
198+
currentScene = NodeScene.loadFromFile(subfile)
194199
UIState.sceneLoading = false
195200
}
196201
}
@@ -273,7 +278,7 @@ object ModuleGardenMacro: Module("Garden Macro") {
273278

274279
ImGui.setNextItemWidth(-Float.MIN_VALUE)
275280
if(ImGui.collapsingHeader("Add a new action ")) {
276-
var actionToAdd: INodeAction? = null
281+
var actionToAdd: NodeAction? = null
277282
ImGui.setNextItemWidth(-Float.MIN_VALUE)
278283
if(ImGui.beginListBox("##_addActionList")) {
279284
if(ImGui.selectable("Key action"))

src/client/kotlin/com/github/fdh911/modules/macro/KeySimulator.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
11
package com.github.fdh911.modules.macro
22

33
import com.github.fdh911.modules.ModuleGardenMacro
4+
import net.minecraft.client.MinecraftClient
45
import net.minecraft.client.option.KeyBinding
56

67
object KeySimulator {
7-
val toHold = mutableSetOf<KeyBinding>()
8-
val toPress = mutableSetOf<KeyBinding>()
9-
val toRelease = mutableSetOf<KeyBinding>()
8+
private val toHold = mutableSetOf<KeyBinding>()
9+
private val toPress = mutableSetOf<KeyBinding>()
10+
private val toRelease = mutableSetOf<KeyBinding>()
1011

1112
private val finishedPress = mutableSetOf<KeyBinding>()
1213

14+
private val translationKeyToKeybinding = MinecraftClient.getInstance().options.allKeys.associateBy { it.translationKey }
15+
16+
fun hold(key: KeyBinding) = toHold.add(key)
17+
fun press(key: KeyBinding) = toPress.add(key)
18+
fun release(key: KeyBinding) = toRelease.add(key)
19+
20+
fun hold(translationKey: String) = toHold.add(translationKeyToKeybinding[translationKey]!!)
21+
fun press(translationKey: String) = toPress.add(translationKeyToKeybinding[translationKey]!!)
22+
fun release(translationKey: String) = toRelease.add(translationKeyToKeybinding[translationKey]!!)
23+
1324
fun update() {
1425
if(!ModuleGardenMacro.toggled) {
1526
for(key in toHold)

src/client/kotlin/com/github/fdh911/modules/macro/Node.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
package com.github.fdh911.modules.macro
22

3-
import com.github.fdh911.modules.macro.nodeactions.INodeAction
3+
import com.github.fdh911.modules.macro.nodeactions.NodeAction
4+
import com.github.fdh911.modules.macro.serialization.BlockPosSerializer
5+
import kotlinx.serialization.Polymorphic
6+
import kotlinx.serialization.Serializable
47
import net.minecraft.util.math.BlockPos
58

6-
data class Node(var pos: BlockPos, var name: String, val actions: MutableList<INodeAction> = mutableListOf()): Cloneable {
7-
public override fun clone() = copy(actions = mutableListOf<INodeAction>().apply {
9+
@Serializable
10+
data class Node(
11+
@Serializable(with = BlockPosSerializer::class)
12+
var pos: BlockPos,
13+
var name: String,
14+
val actions: MutableList<@Polymorphic NodeAction> = mutableListOf()
15+
): Cloneable
16+
{
17+
public override fun clone() = copy(actions = mutableListOf<NodeAction>().apply {
818
for(action in actions)
919
add(action.clone())
1020
})
Lines changed: 30 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,55 @@
11
package com.github.fdh911.modules.macro
22

3-
import com.github.fdh911.modules.macro.nodeactions.INodeAction
3+
import com.github.fdh911.modules.macro.nodeactions.NodeAction
44
import com.github.fdh911.modules.macro.nodeactions.NodeActionKey
55
import com.github.fdh911.modules.macro.nodeactions.NodeActionLockMouse
66
import com.github.fdh911.modules.macro.nodeactions.NodeActionRotateDelta
77
import com.github.fdh911.modules.macro.nodeactions.NodeActionRotateExact
88
import com.github.fdh911.modules.macro.nodeactions.NodeActionSendMessage
99
import com.github.fdh911.modules.macro.nodeactions.NodeActionUnlockMouse
1010
import com.github.fdh911.modules.macro.nodeactions.NodeActionWait
11-
import imgui.type.ImFloat
12-
import imgui.type.ImInt
13-
import imgui.type.ImString
14-
import net.minecraft.client.MinecraftClient
15-
import net.minecraft.client.option.KeyBinding
16-
import net.minecraft.util.math.BlockPos
11+
import kotlinx.serialization.Serializable
12+
import kotlinx.serialization.json.Json
13+
import kotlinx.serialization.modules.SerializersModule
14+
import kotlinx.serialization.modules.polymorphic
1715
import java.io.File
1816

19-
class NodeScene(var name: String) {
17+
@Serializable
18+
class NodeScene(var name: String)
19+
{
2020
companion object {
21-
fun loadFromFile(file: File): NodeScene {
22-
val br = file.bufferedReader()
23-
val name = br.readLine()
24-
val scene = NodeScene(name)
25-
val nodeCount = br.readLine().toInt()
26-
repeat(nodeCount) {
27-
val nodeName = br.readLine()
28-
val nodeX = br.readLine().toInt()
29-
val nodeY = br.readLine().toInt()
30-
val nodeZ = br.readLine().toInt()
31-
val nodeActionCnt = br.readLine().toInt()
32-
val node = Node(BlockPos(nodeX, nodeY, nodeZ), nodeName)
33-
repeat(nodeActionCnt) {
34-
val actionType = br.readLine()
35-
var action: INodeAction? = null
36-
if(actionType == "hold" || actionType == "press" || actionType == "release") {
37-
val keyTranslation = br.readLine()
38-
var nodeKey: KeyBinding? = null
39-
for(key in MinecraftClient.getInstance().options.allKeys)
40-
if(key.translationKey == keyTranslation) {
41-
nodeKey = key
42-
break
43-
}
44-
if(nodeKey == null)
45-
throw RuntimeException("No such key exists: $keyTranslation")
46-
val keyActionType = when(actionType) {
47-
"hold" -> NodeActionKey.Action.HOLD
48-
"press" -> NodeActionKey.Action.PRESS
49-
"release" -> NodeActionKey.Action.RELEASE
50-
else -> throw RuntimeException("Unknown action type: $actionType")
51-
}
52-
action = NodeActionKey(nodeKey, keyActionType)
53-
}
54-
action = when(actionType) {
55-
"hold" -> action
56-
"press" -> action
57-
"release" -> action
58-
"send" -> {
59-
val msg = br.readLine()
60-
NodeActionSendMessage(ImString().apply { set(msg) })
61-
}
62-
"wait" -> {
63-
val ms = br.readLine().toInt()
64-
NodeActionWait(ImInt(ms))
65-
}
66-
"rotateexact" -> {
67-
val yaw = br.readLine().toFloat()
68-
val pitch = br.readLine().toFloat()
69-
NodeActionRotateExact(ImFloat(yaw), ImFloat(pitch))
70-
}
71-
"rotatedelta" -> {
72-
val yawDelta = br.readLine().toFloat()
73-
val pitchDelta = br.readLine().toFloat()
74-
NodeActionRotateDelta(ImFloat(yawDelta), ImFloat(pitchDelta))
75-
}
76-
"lockMouse" -> NodeActionLockMouse()
77-
"unlockMouse" -> NodeActionUnlockMouse()
78-
else -> null
79-
}
80-
if(action == null)
81-
throw RuntimeException("Unknown action: $actionType")
82-
node.actions.add(action)
83-
}
84-
scene.nodeList.add(node)
21+
val serializerModule = SerializersModule {
22+
polymorphic(NodeAction::class) {
23+
subclass(NodeActionKey::class, NodeActionKey.serializer())
24+
subclass(NodeActionLockMouse::class, NodeActionLockMouse.serializer())
25+
subclass(NodeActionUnlockMouse::class, NodeActionUnlockMouse.serializer())
26+
subclass(NodeActionRotateExact::class, NodeActionRotateExact.serializer())
27+
subclass(NodeActionRotateDelta::class, NodeActionRotateDelta.serializer())
28+
subclass(NodeActionSendMessage::class, NodeActionSendMessage.serializer())
29+
subclass(NodeActionWait::class, NodeActionWait.serializer())
8530
}
86-
return scene
31+
}
32+
33+
val json = Json {
34+
serializersModule = serializerModule
35+
prettyPrint = true
36+
encodeDefaults = true
37+
}
38+
39+
fun loadFromFile(file: File): NodeScene {
40+
val objectJson = file.readText()
41+
return json.decodeFromString<NodeScene>(objectJson)
8742
}
8843
}
8944

9045
val nodeList = mutableListOf<Node>()
9146

9247
fun saveToFile() {
93-
val file = File("$name.mysecondmod.scene.txt")
48+
val file = File("$name.msmscene.json")
9449
if(file.exists()) {
9550
file.delete()
9651
file.createNewFile()
9752
}
98-
file.appendText("$name\n${nodeList.size}\n")
99-
for(node in nodeList) {
100-
file.appendText("${node.name}\n")
101-
file.appendText("${node.pos.x}\n")
102-
file.appendText("${node.pos.y}\n")
103-
file.appendText("${node.pos.z}\n")
104-
file.appendText("${node.actions.size}\n")
105-
for(action in node.actions)
106-
file.appendText("${action.fileFormat}\n")
107-
}
53+
file.writeText(json.encodeToString(serializer(), this))
10854
}
10955
}

src/client/kotlin/com/github/fdh911/modules/macro/nodeactions/INodeAction.kt

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.github.fdh911.modules.macro.nodeactions
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
sealed class NodeAction: Cloneable
7+
{
8+
abstract suspend fun execute()
9+
abstract fun renderUI(): Boolean
10+
public abstract override fun clone(): NodeAction
11+
abstract override fun toString(): String
12+
}

src/client/kotlin/com/github/fdh911/modules/macro/nodeactions/NodeActionKey.kt

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import com.github.fdh911.modules.macro.KeySimulator
44
import com.github.fdh911.render.UserInterface
55
import com.github.fdh911.utils.translate
66
import imgui.ImGui
7+
import kotlinx.serialization.Serializable
78
import net.minecraft.client.MinecraftClient
8-
import net.minecraft.client.option.KeyBinding
99
import java.util.Locale.getDefault
1010

11+
@Serializable
1112
class NodeActionKey(
12-
private var keyToAffect: KeyBinding = MinecraftClient.getInstance().options.forwardKey,
13+
private var kbTranslationKey: String = MinecraftClient.getInstance().options.forwardKey.translationKey,
1314
private var action: Action = Action.HOLD
14-
): INodeAction
15+
): NodeAction()
1516
{
1617
enum class Action(val string: String) {
1718
HOLD("hold"),
@@ -24,24 +25,24 @@ class NodeActionKey(
2425

2526
override suspend fun execute() {
2627
when(action) {
27-
Action.HOLD -> KeySimulator.toHold.add(keyToAffect)
28-
Action.RELEASE -> KeySimulator.toRelease.add(keyToAffect)
29-
Action.PRESS -> KeySimulator.toPress.add(keyToAffect)
28+
Action.HOLD -> KeySimulator.hold(kbTranslationKey)
29+
Action.RELEASE -> KeySimulator.release(kbTranslationKey)
30+
Action.PRESS -> KeySimulator.press(kbTranslationKey)
3031
}
3132
}
3233

3334
override fun renderUI(): Boolean {
3435
var keepRendering = true
3536
UserInterface.newWindow("${action.capitalizedString()} key action") {
3637
ImGui.separatorText("Currently selected")
37-
ImGui.text(keyToAffect.translationKey.translate())
38+
ImGui.text(kbTranslationKey.translate())
3839
ImGui.separatorText("Select another key")
3940
if(ImGui.beginListBox("##_possibleKeys")) {
4041
val keyArray = MinecraftClient.getInstance().options.allKeys
4142
for(i in keyArray.indices) {
42-
val key = keyArray[i]
43-
if(ImGui.selectable("${key.translationKey.translate()}##_key$i"))
44-
keyToAffect = key
43+
val key = keyArray[i].translationKey
44+
if(ImGui.selectable("${key.translate()}##_key$i"))
45+
kbTranslationKey = key
4546
}
4647
ImGui.endListBox()
4748
}
@@ -52,9 +53,7 @@ class NodeActionKey(
5253
return keepRendering
5354
}
5455

55-
override fun clone() = NodeActionKey(keyToAffect, action)
56+
override fun clone() = NodeActionKey(kbTranslationKey, action)
5657

57-
override fun toString() = "${action.capitalizedString()}: ${keyToAffect.translationKey.translate()}"
58-
59-
override val fileFormat = "${action.string}\n${keyToAffect.translationKey}"
58+
override fun toString() = "${action.capitalizedString()}: ${kbTranslationKey.translate()}"
6059
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.github.fdh911.modules.macro.nodeactions
22

33
import com.github.fdh911.modules.macro.MouseLock
4+
import kotlinx.serialization.Serializable
45

5-
class NodeActionLockMouse: INodeAction {
6+
@Serializable
7+
class NodeActionLockMouse: NodeAction()
8+
{
69
override suspend fun execute() {
710
MouseLock.isLocked = true
811
}
@@ -13,8 +16,5 @@ class NodeActionLockMouse: INodeAction {
1316

1417
override fun clone() = NodeActionLockMouse()
1518

16-
override val fileFormat: String
17-
get() = "lockMouse"
18-
1919
override fun toString() = "Lock yaw & pitch"
2020
}

0 commit comments

Comments
 (0)