aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/world/FirmWaypointManager.kt
blob: 6b68a945353475edca548c7cd77c0e293204ac5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package moe.nea.firmament.features.world

import kotlinx.serialization.serializer
import net.minecraft.text.Text
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.commands.DefaultSource
import moe.nea.firmament.commands.RestArgumentType
import moe.nea.firmament.commands.get
import moe.nea.firmament.commands.thenArgument
import moe.nea.firmament.commands.thenExecute
import moe.nea.firmament.commands.thenLiteral
import moe.nea.firmament.events.CommandEvent
import moe.nea.firmament.util.ClipboardUtils
import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.TemplateUtil
import moe.nea.firmament.util.data.MultiFileDataHolder
import moe.nea.firmament.util.tr

object FirmWaypointManager {
	object DataHolder : MultiFileDataHolder<FirmWaypoints>(serializer(), "waypoints")

	val SHARE_PREFIX = "FIRM_WAYPOINTS/"
	val ENCODED_SHARE_PREFIX = TemplateUtil.getPrefixComparisonSafeBase64Encoding(SHARE_PREFIX)

	fun createExportableCopy(
		waypoints: FirmWaypoints,
	): FirmWaypoints {
		val copy = waypoints.copy(waypoints = waypoints.waypoints.toMutableList())
		if (waypoints.isRelativeTo != null) {
			val origin = waypoints.lastRelativeImport
			if (origin != null) {
				copy.waypoints.replaceAll {
					it.copy(
						x = it.x - origin.x,
						y = it.y - origin.y,
						z = it.z - origin.z,
					)
				}
			} else {
				TODO("Add warning!")
			}
		}
		return copy
	}

	fun loadWaypoints(waypoints: FirmWaypoints, sendFeedback: (Text) -> Unit) {
		if (waypoints.isRelativeTo != null) {
			val origin = MC.player!!.blockPos
			waypoints.waypoints.replaceAll {
				it.copy(
					x = it.x + origin.x,
					y = it.y + origin.y,
					z = it.z + origin.z,
				)
			}
			waypoints.lastRelativeImport = origin.toImmutable()
			sendFeedback(tr("firmament.command.waypoint.import.ordered.success",
			                "Imported ${waypoints.size} relative waypoints. Make sure you stand in the correct spot while loading the waypoints: ${waypoints.isRelativeTo}."))
		} else {
			sendFeedback(tr("firmament.command.waypoint.import.success",
			                "Imported ${waypoints.size} waypoints."))
		}
		Waypoints.waypoints = waypoints
	}

	fun setOrigin(source: DefaultSource, text: String?) {
		val waypoints = Waypoints.useEditableWaypoints()
		waypoints.isRelativeTo = text ?: waypoints.isRelativeTo ?: ""
		val pos = MC.player!!.blockPos
		waypoints.lastRelativeImport = pos
		source.sendFeedback(tr("firmament.command.waypoint.originset",
		                       "Set the origin of waypoints to ${FirmFormatters.formatPosition(pos)}. Run /firm waypoints export to save the waypoints relative to this position."))
	}

	@Subscribe
	fun onCommands(event: CommandEvent.SubCommand) {
		event.subcommand(Waypoints.WAYPOINTS_SUBCOMMAND) {
			thenLiteral("setorigin") {
				thenExecute {
					setOrigin(source, null)
				}
				thenArgument("hint", RestArgumentType) { text ->
					thenExecute {
						setOrigin(source, this[text])
					}
				}
			}
			thenLiteral("clearorigin") {
				thenExecute {
					val waypoints = Waypoints.useEditableWaypoints()
					waypoints.lastRelativeImport = null
					waypoints.isRelativeTo = null
					source.sendFeedback(tr("firmament.command.waypoint.originunset",
					                       "Unset the origin of the waypoints. Run /firm waypoints export to save the waypoints with absolute coordinates."))
				}
			}
			thenLiteral("export") {
				thenExecute {
					val waypoints = Waypoints.useNonEmptyWaypoints()
					if (waypoints == null) {
						source.sendError(Waypoints.textNothingToExport())
						return@thenExecute
					}
					val exportableWaypoints = createExportableCopy(waypoints)
					val data = TemplateUtil.encodeTemplate(SHARE_PREFIX, exportableWaypoints)
					ClipboardUtils.setTextContent(data)
					source.sendFeedback(tr("firmament.command.waypoint.export",
					                       "Copied ${exportableWaypoints.size} waypoints to clipboard in Firmament format."))
				}
			}
			thenLiteral("import") {
				thenExecute {
					val text = ClipboardUtils.getTextContents()
					if (text.startsWith("[")) {
						source.sendError(tr("firmament.command.waypoint.import.lookslikecw",
						                    "The waypoints in your clipboard look like they might be ColeWeight waypoints. If so, use /firm waypoints importcw or /firm waypoints importrelativecw."))
						return@thenExecute
					}
					val waypoints = TemplateUtil.maybeDecodeTemplate<FirmWaypoints>(SHARE_PREFIX, text)
					if (waypoints == null) {
						source.sendError(tr("firmament.command.waypoint.import.error",
						                    "Could not import Firmament waypoints from your clipboard. Make sure they are Firmament compatible waypoints."))
						return@thenExecute
					}
					loadWaypoints(waypoints, source::sendFeedback)
				}
			}
		}
	}
}