aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-08-07 21:34:16 +0200
committerLinnea Gräf <nea@nea.moe>2024-08-07 21:34:16 +0200
commitb4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9 (patch)
tree1f7928e5587b6d4d7ca071949f0a70bf81282c14
parent9b277bd897490d13ee4549a086e8d1b5f4cd0e10 (diff)
downloadfirmament-b4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9.tar.gz
firmament-b4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9.tar.bz2
firmament-b4f9ca21ef801bb3e39c53ae21bb6bf4398c94e9.zip
Add /firm npcs command
-rw-r--r--gradle/libs.versions.toml2
-rw-r--r--src/main/kotlin/moe/nea/firmament/Firmament.kt1
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt7
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt3
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt40
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt22
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt121
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt68
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt15
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt59
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt33
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt12
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt83
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt11
-rw-r--r--src/main/resources/assets/firmament/gui/npc_waypoints.xml42
-rw-r--r--src/main/resources/assets/firmament/textures/gui/waypoint_selected.pngbin0 -> 225 bytes
-rw-r--r--src/main/resources/assets/firmament/textures/gui/waypoint_unselected.pngbin0 -> 217 bytes
21 files changed, 538 insertions, 32 deletions
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 99c6150..80731a7 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -23,7 +23,7 @@ notenoughanimations = "WaI2x21x"
devauth = "1.2.0"
ktor = "2.3.0"
-neurepoparser = "1.4.0"
+neurepoparser = "1.5.0"
hotswap_agent = "1.4.2-SNAPSHOT"
mixinextras = "0.3.5"
jarvis = "1.1.3"
diff --git a/src/main/kotlin/moe/nea/firmament/Firmament.kt b/src/main/kotlin/moe/nea/firmament/Firmament.kt
index e2b904f..a0693f0 100644
--- a/src/main/kotlin/moe/nea/firmament/Firmament.kt
+++ b/src/main/kotlin/moe/nea/firmament/Firmament.kt
@@ -112,6 +112,7 @@ object Firmament {
@JvmStatic
fun onClientInitialize() {
+ FeatureManager.subscribeEvents()
var tick = 0
ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { instance ->
TickEvent.publish(TickEvent(tick++))
diff --git a/src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt
new file mode 100644
index 0000000..4c3083e
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt
@@ -0,0 +1,7 @@
+package moe.nea.firmament.events
+
+import io.github.moulberry.repo.NEURepository
+
+data class ReloadRegistrationEvent(val repo: NEURepository) : FirmamentEvent() {
+ companion object : FirmamentEventBus<ReloadRegistrationEvent>()
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt b/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt
index d127381..c69d7b2 100644
--- a/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt
@@ -87,13 +87,12 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
loadFeature(DebugView)
}
allFeatures.forEach { it.config }
- subscribeEvents()
FeaturesInitializedEvent.publish(FeaturesInitializedEvent(allFeatures.toList()))
hasAutoloaded = true
}
}
- private fun subscribeEvents() {
+ fun subscribeEvents() {
AllSubscriptions.provideSubscriptions {
subscribeSingleEvent(it)
}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt b/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt
new file mode 100644
index 0000000..592b8fa
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt
@@ -0,0 +1,40 @@
+package moe.nea.firmament.features.world
+
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.commands.thenExecute
+import moe.nea.firmament.events.CommandEvent
+import moe.nea.firmament.events.ReloadRegistrationEvent
+import moe.nea.firmament.util.MoulConfigUtils
+import moe.nea.firmament.util.ScreenUtil
+
+object NPCWaypoints {
+
+ var allNpcWaypoints = listOf<NavigableWaypoint>()
+
+ @Subscribe
+ fun onRepoReloadRegistration(event: ReloadRegistrationEvent) {
+ event.repo.registerReloadListener {
+ allNpcWaypoints = it.items.items.values
+ .asSequence()
+ .filter { !it.island.isNullOrBlank() }
+ .map {
+ NavigableWaypoint.NPCWaypoint(it)
+ }
+ .toList()
+ }
+ }
+
+ @Subscribe
+ fun onOpenGui(event: CommandEvent.SubCommand) {
+ event.subcommand("npcs") {
+ thenExecute {
+ ScreenUtil.setScreenLater(MoulConfigUtils.loadScreen(
+ "npc_waypoints",
+ NpcWaypointGui(allNpcWaypoints),
+ null))
+ }
+ }
+ }
+
+
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt b/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt
new file mode 100644
index 0000000..28a517f
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt
@@ -0,0 +1,22 @@
+package moe.nea.firmament.features.world
+
+import io.github.moulberry.repo.data.NEUItem
+import net.minecraft.util.math.BlockPos
+import moe.nea.firmament.util.SkyBlockIsland
+
+abstract class NavigableWaypoint {
+ abstract val name: String
+ abstract val position: BlockPos
+ abstract val island: SkyBlockIsland
+
+ data class NPCWaypoint(
+ val item: NEUItem,
+ ) : NavigableWaypoint() {
+ override val name: String
+ get() = item.displayName
+ override val position: BlockPos
+ get() = BlockPos(item.x, item.y, item.z)
+ override val island: SkyBlockIsland
+ get() = SkyBlockIsland.forMode(item.island)
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt b/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt
new file mode 100644
index 0000000..acdfb86
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt
@@ -0,0 +1,121 @@
+package moe.nea.firmament.features.world
+
+import io.github.moulberry.repo.constants.Islands
+import net.minecraft.text.Text
+import net.minecraft.util.math.BlockPos
+import net.minecraft.util.math.Position
+import net.minecraft.util.math.Vec3i
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.events.SkyblockServerUpdateEvent
+import moe.nea.firmament.events.TickEvent
+import moe.nea.firmament.events.WorldRenderLastEvent
+import moe.nea.firmament.repo.RepoManager
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.SBData
+import moe.nea.firmament.util.SkyBlockIsland
+import moe.nea.firmament.util.WarpUtil
+import moe.nea.firmament.util.render.RenderInWorldContext
+
+object NavigationHelper {
+ var targetWaypoint: NavigableWaypoint? = null
+ set(value) {
+ field = value
+ recalculateRoute()
+ }
+
+ var nextTeleporter: Islands.Teleporter? = null
+ private set
+
+ val Islands.Teleporter.toIsland get() = SkyBlockIsland.forMode(this.getTo())
+ val Islands.Teleporter.fromIsland get() = SkyBlockIsland.forMode(this.getFrom())
+ val Islands.Teleporter.blockPos get() = BlockPos(x.toInt(), y.toInt(), z.toInt())
+
+ @Subscribe
+ fun onWorldSwitch(event: SkyblockServerUpdateEvent) {
+ recalculateRoute()
+ }
+
+ fun recalculateRoute() {
+ val tp = targetWaypoint
+ val currentIsland = SBData.skyblockLocation
+ if (tp == null || currentIsland == null) {
+ nextTeleporter = null
+ return
+ }
+ val route = findRoute(currentIsland, tp.island, mutableSetOf())
+ nextTeleporter = route?.get(0)
+ }
+
+ private fun findRoute(
+ fromIsland: SkyBlockIsland,
+ targetIsland: SkyBlockIsland,
+ visitedIslands: MutableSet<SkyBlockIsland>
+ ): MutableList<Islands.Teleporter>? {
+ var shortestChain: MutableList<Islands.Teleporter>? = null
+ for (it in RepoManager.neuRepo.constants.islands.teleporters) {
+ if (it.toIsland in visitedIslands) continue
+ if (it.fromIsland != fromIsland) continue
+ if (it.toIsland == targetIsland) return mutableListOf(it)
+ visitedIslands.add(fromIsland)
+ val nextRoute = findRoute(it.toIsland, targetIsland, visitedIslands) ?: continue
+ nextRoute.add(0, it)
+ if (shortestChain == null || shortestChain.size > nextRoute.size) {
+ shortestChain = nextRoute
+ }
+ visitedIslands.remove(fromIsland)
+ }
+ return shortestChain
+ }
+
+
+ @Subscribe
+ fun onMovement(event: TickEvent) { // TODO: add a movement tick event maybe?
+ val tp = targetWaypoint ?: return
+ val p = MC.player ?: return
+ if (p.squaredDistanceTo(tp.position.toCenterPos()) < 5 * 5) {
+ targetWaypoint = null
+ }
+ }
+
+ @Subscribe
+ fun drawWaypoint(event: WorldRenderLastEvent) {
+ val tp = targetWaypoint ?: return
+ val nt = nextTeleporter
+ RenderInWorldContext.renderInWorld(event) {
+ if (nt != null) {
+ waypoint(nt.blockPos,
+ Text.literal("Teleporter to " + nt.toIsland.userFriendlyName),
+ Text.literal("(towards " + tp.name + "§f)"))
+ } else if (tp.island == SBData.skyblockLocation) {
+ waypoint(tp.position,
+ Text.literal(tp.name))
+ }
+ }
+ }
+
+ fun tryWarpNear() {
+ val tp = targetWaypoint
+ if (tp == null) {
+ MC.sendChat(Text.literal("Could not find a waypoint to warp you to. Select one first."))
+ return
+ }
+ WarpUtil.teleportToNearestWarp(tp.island, tp.position.asPositionView())
+ }
+
+}
+
+fun Vec3i.asPositionView(): Position {
+ return object : Position {
+ override fun getX(): Double {
+ return this@asPositionView.x.toDouble()
+ }
+
+ override fun getY(): Double {
+ return this@asPositionView.y.toDouble()
+ }
+
+ override fun getZ(): Double {
+ return this@asPositionView.z.toDouble()
+ }
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt b/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt
new file mode 100644
index 0000000..6146e50
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt
@@ -0,0 +1,68 @@
+package moe.nea.firmament.features.world
+
+import io.github.notenoughupdates.moulconfig.observer.ObservableList
+import io.github.notenoughupdates.moulconfig.xml.Bind
+import moe.nea.firmament.features.events.anniversity.AnniversaryFeatures.atOnce
+import moe.nea.firmament.keybindings.SavedKeyBinding
+
+class NpcWaypointGui(
+ val allWaypoints: List<NavigableWaypoint>,
+) {
+
+ data class NavigableWaypointW(val waypoint: NavigableWaypoint) {
+ @Bind
+ fun name() = waypoint.name
+
+ @Bind
+ fun isSelected() = NavigationHelper.targetWaypoint == waypoint
+
+ @Bind
+ fun click() {
+ if (SavedKeyBinding.isShiftDown()) {
+ NavigationHelper.targetWaypoint = waypoint
+ NavigationHelper.tryWarpNear()
+ } else if (isSelected()) {
+ NavigationHelper.targetWaypoint = null
+ } else {
+ NavigationHelper.targetWaypoint = waypoint
+ }
+ }
+ }
+
+ @JvmField
+ @field:Bind
+ var search: String = ""
+ var lastSearch: String? = null
+
+ @Bind("results")
+ fun results(): ObservableList<NavigableWaypointW> {
+ return results
+ }
+
+ @Bind
+ fun tick() {
+ if (search != lastSearch) {
+ updateSearch()
+ lastSearch = search
+ }
+ }
+
+ val results: ObservableList<NavigableWaypointW> = ObservableList(mutableListOf())
+
+ fun updateSearch() {
+ val split = search.split(" +".toRegex())
+ results.atOnce {
+ results.clear()
+ allWaypoints.filter { waypoint ->
+ if (search.isBlank()) {
+ true
+ } else {
+ split.all { waypoint.name.contains(it, ignoreCase = true) }
+ }
+ }.mapTo(results) {
+ NavigableWaypointW(it)
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt
index d1e223e..09025af 100644
--- a/src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt
+++ b/src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt
@@ -18,8 +18,9 @@ import io.github.notenoughupdates.moulconfig.observer.GetSetter
open class FirmButtonComponent(
child: GuiComponent,
val isEnabled: GetSetter<Boolean> = GetSetter.constant(true),
+ val noBackground: Boolean = false,
val action: Runnable,
-) : PanelComponent(child) {
+) : PanelComponent(child, if (noBackground) 0 else 2, DefaultBackgroundRenderer.TRANSPARENT) {
/* TODO: make use of vanillas built in nine slicer */
val hoveredBg =
@@ -44,7 +45,6 @@ open class FirmButtonComponent(
.cornerUv(5 / 200F, 5 / 20F)
.mode(NinePatch.Mode.STRETCHING)
.build()
-
var isClicking = false
override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
if (!isEnabled.get()) return false
@@ -54,12 +54,14 @@ open class FirmButtonComponent(
if (context.isHovered) {
action.run()
}
+ blur()
return true
}
}
if (!context.isHovered) return false
if (mouseEvent !is MouseEvent.Click) return false
if (mouseEvent.mouseState && mouseEvent.mouseButton == 0) {
+ requestFocus()
isClicking = true
return true
}
@@ -73,10 +75,11 @@ open class FirmButtonComponent(
override fun render(context: GuiImmediateContext) {
context.renderContext.pushMatrix()
- context.renderContext.drawNinePatch(
- getBackground(context),
- 0f, 0f, context.width, context.height
- )
+ if (!noBackground)
+ context.renderContext.drawNinePatch(
+ getBackground(context),
+ 0f, 0f, context.width, context.height
+ )
context.renderContext.translate(insets.toFloat(), insets.toFloat(), 0f)
element.render(getChildContext(context))
context.renderContext.popMatrix()
diff --git a/src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt
new file mode 100644
index 0000000..b1792ce
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt
@@ -0,0 +1,59 @@
+package moe.nea.firmament.gui
+
+import io.github.notenoughupdates.moulconfig.gui.GuiComponent
+import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
+import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
+import io.github.notenoughupdates.moulconfig.gui.MouseEvent
+import java.util.function.BiFunction
+import java.util.function.Supplier
+import kotlin.time.Duration
+import moe.nea.firmament.util.TimeMark
+
+class FirmHoverComponent(
+ val child: GuiComponent,
+ val hoverLines: Supplier<List<String>>,
+ val hoverDelay: Duration,
+) : GuiComponent() {
+ override fun getWidth(): Int {
+ return child.width
+ }
+
+ override fun getHeight(): Int {
+ return child.height
+ }
+
+ override fun <T : Any?> foldChildren(
+ initial: T,
+ visitor: BiFunction<GuiComponent, T, T>
+ ): T {
+ return visitor.apply(child, initial)
+ }
+
+ override fun render(context: GuiImmediateContext) {
+ if (context.isHovered && (permaHover || lastMouseMove.passedTime() > hoverDelay)) {
+ context.renderContext.scheduleDrawTooltip(hoverLines.get())
+ permaHover = true
+ } else {
+ permaHover = false
+ }
+ if (!context.isHovered) {
+ lastMouseMove = TimeMark.now()
+ }
+ child.render(context)
+
+ }
+
+ var permaHover = false
+ var lastMouseMove = TimeMark.farPast()
+
+ override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
+ if (mouseEvent is MouseEvent.Move) {
+ lastMouseMove = TimeMark.now()
+ }
+ return child.mouseEvent(mouseEvent, context)
+ }
+
+ override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
+ return child.keyboardEvent(event, context)
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt
new file mode 100644
index 0000000..bba7dee
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt
@@ -0,0 +1,33 @@
+package moe.nea.firmament.gui
+
+import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
+import io.github.notenoughupdates.moulconfig.gui.GuiComponent
+import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
+import java.util.function.Supplier
+
+class ImageComponent(
+ private val width: Int,
+ private val height: Int,
+ val resourceLocation: Supplier<MyResourceLocation>,
+ val u1: Float,
+ val u2: Float,
+ val v1: Float,
+ val v2: Float,
+) : GuiComponent() {
+ override fun getWidth(): Int {
+ return width
+ }
+
+ override fun getHeight(): Int {
+ return height
+ }
+
+ override fun render(context: GuiImmediateContext) {
+ context.renderContext.bindTexture(resourceLocation.get())
+ context.renderContext.drawTexturedRect(
+ 0f, 0f,
+ context.width.toFloat(), context.height.toFloat(),
+ u1, v1, u2, v2
+ )
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt
new file mode 100644
index 0000000..d1879b1
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt
@@ -0,0 +1,18 @@
+package moe.nea.firmament.gui
+
+import io.github.notenoughupdates.moulconfig.gui.GuiComponent
+import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
+
+class TickComponent(val onTick: Runnable) : GuiComponent() {
+ override fun getWidth(): Int {
+ return 0
+ }
+
+ override fun getHeight(): Int {
+ return 0
+ }
+
+ override fun render(context: GuiImmediateContext) {
+ onTick.run()
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt b/src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt
index f07cd29..4056e66 100644
--- a/src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt
+++ b/src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt
@@ -47,8 +47,7 @@ data class SavedKeyBinding(
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SUPER)
} else InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_CONTROL)
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_CONTROL)
- val shift = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SHIFT)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SHIFT)
+ val shift = isShiftDown()
val alt = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_ALT)
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_ALT)
var mods = 0
@@ -57,6 +56,11 @@ data class SavedKeyBinding(
if (alt) mods = mods or GLFW.GLFW_MOD_ALT
return mods
}
+
+ private val h get() = MC.window.handle
+ fun isShiftDown() = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SHIFT)
+ || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SHIFT)
+
}
fun isPressed(atLeast: Boolean = false): Boolean {
@@ -69,8 +73,7 @@ data class SavedKeyBinding(
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SUPER)
} else InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_CONTROL)
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_CONTROL)
- val shift = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SHIFT)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SHIFT)
+ val shift = isShiftDown()
val alt = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_ALT)
|| InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_ALT)
if (atLeast)
diff --git a/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt b/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt
index 179b720..e7a1e9e 100644
--- a/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt
+++ b/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt
@@ -7,7 +7,6 @@
package moe.nea.firmament.repo
-import io.github.moulberry.repo.NEURecipeCache
import io.github.moulberry.repo.NEURepository
import io.github.moulberry.repo.NEURepositoryException
import io.github.moulberry.repo.data.NEUItem
@@ -20,6 +19,7 @@ import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
import moe.nea.firmament.Firmament.logger
+import moe.nea.firmament.events.ReloadRegistrationEvent
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.rei.PetData
import moe.nea.firmament.util.MinecraftDispatcher
@@ -57,6 +57,7 @@ object RepoManager {
registerReloadListener(ItemCache)
registerReloadListener(ExpLadders)
registerReloadListener(ItemNameLookup)
+ ReloadRegistrationEvent.publish(ReloadRegistrationEvent(this))
registerReloadListener {
Firmament.coroutineScope.launch(MinecraftDispatcher) {
if (!trySendClientboundUpdateRecipesPacket()) {
@@ -69,9 +70,10 @@ object RepoManager {
val essenceRecipeProvider = EssenceRecipeProvider()
val recipeCache = BetterRepoRecipeCache(essenceRecipeProvider)
+
init {
- neuRepo.registerReloadListener(essenceRecipeProvider)
- neuRepo.registerReloadListener(recipeCache)
+ neuRepo.registerReloadListener(essenceRecipeProvider)
+ neuRepo.registerReloadListener(recipeCache)
}
fun getAllRecipes() = neuRepo.items.items.values.asSequence().flatMap { it.recipes }
@@ -110,7 +112,9 @@ object RepoManager {
fun reload() {
try {
- ItemCache.ReloadProgressHud.reportProgress("Reloading from Disk", 0, -1) // TODO: replace with a proper boundy bar
+ ItemCache.ReloadProgressHud.reportProgress("Reloading from Disk",
+ 0,
+ -1) // TODO: replace with a proper boundy bar
ItemCache.ReloadProgressHud.isEnabled = true
neuRepo.reload()
} catch (exc: NEURepositoryException) {
diff --git a/src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt b/src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt
index 2884dc5..b99c1fc 100644
--- a/src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt
+++ b/src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt
@@ -18,13 +18,19 @@ import io.github.notenoughupdates.moulconfig.xml.XMLGuiLoader
import io.github.notenoughupdates.moulconfig.xml.XMLUniverse
import io.github.notenoughupdates.moulconfig.xml.XSDGenerator
import java.io.File
+import java.util.function.Supplier
import javax.xml.namespace.QName
import me.shedaniel.math.Color
import org.w3c.dom.Element
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
import net.minecraft.client.gui.screen.Screen
import moe.nea.firmament.gui.BarComponent
import moe.nea.firmament.gui.FirmButtonComponent
+import moe.nea.firmament.gui.FirmHoverComponent
import moe.nea.firmament.gui.FixedComponent
+import moe.nea.firmament.gui.ImageComponent
+import moe.nea.firmament.gui.TickComponent
object MoulConfigUtils {
val firmUrl = "http://firmament.nea.moe/moulconfig"
@@ -69,6 +75,31 @@ object MoulConfigUtils {
return mapOf("progress" to true, "total" to true, "emptyColor" to true, "fillColor" to true)
}
})
+ uni.registerLoader(object : XMLGuiLoader.Basic<FirmHoverComponent> {
+ override fun createInstance(context: XMLContext<*>, element: Element): FirmHoverComponent {
+ return FirmHoverComponent(
+ context.getChildFragment(element),
+ context.getPropertyFromAttribute(element, QName("lines"), List::class.java) as Supplier<List<String>>,
+ context.getPropertyFromAttribute(element, QName("delay"), Duration::class.java, 0.6.seconds),
+ )
+ }
+
+ override fun getName(): QName {
+ return QName(firmUrl, "Hover")
+ }
+
+ override fun getChildCount(): ChildCount {
+ return ChildCount.ONE
+ }
+
+ override fun getAttributeNames(): Map<String, Boolean> {
+ return mapOf(
+ "lines" to true,
+ "delay" to false,
+ )
+ }
+
+ })
uni.registerLoader(object : XMLGuiLoader.Basic<FirmButtonComponent> {
override fun getName(): QName {
return QName(firmUrl, "Button")
@@ -79,6 +110,7 @@ object MoulConfigUtils {
context.getChildFragment(element),
context.getPropertyFromAttribute(element, QName("enabled"), Boolean::class.java)
?: GetSetter.constant(true),
+ context.getPropertyFromAttribute(element, QName("noBackground"), Boolean::class.java, false),
context.getMethodFromAttribute(element, QName("onClick")),
)
}
@@ -88,7 +120,56 @@ object MoulConfigUtils {
}
override fun getAttributeNames(): Map<String, Boolean> {
- return mapOf("onClick" to true, "enabled" to false)
+ return mapOf("onClick" to true, "enabled" to false, "noBackground" to false)
+ }
+ })
+ uni.registerLoader(object : XMLGuiLoader.Basic<ImageComponent> {
+ override fun createInstance(context: XMLContext<*>, element: Element): ImageComponent {
+ return ImageComponent(
+ context.getPropertyFromAttribute(element, QName("width"), Int::class.java)!!.get(),
+ context.getPropertyFromAttribute(element, QName("height"), Int::class.java)!!.get(),
+ context.getPropertyFromAttribute(element, QName("resource"), MyResourceLocation::class.java)!!,
+ context.getPropertyFromAttribute(element, QName("u1"), Float::class.java, 0f),
+ context.getPropertyFromAttribute(element, QName("u2"), Float::class.java, 1f),
+ context.getPropertyFromAttribute(element, QName("v1"), Float::class.java, 0f),
+ context.getPropertyFromAttribute(element, QName("v2"), Float::class.java, 1f),
+ )
+ }
+
+ override fun getName(): QName {
+ return QName(firmUrl, "Image")
+ }
+
+ override fun getChildCount(): ChildCount {
+ return ChildCount.NONE
+ }
+
+ override fun getAttributeNames(): Map<String, Boolean> {
+ return mapOf(
+ "width" to true, "height" to true,
+ "resource" to true,
+ "u1" to false,
+ "u2" to false,
+ "v1" to false,
+ "v2" to false,
+ )
+ }
+ })
+ uni.registerLoader(object : XMLGuiLoader.Basic<TickComponent> {
+ override fun createInstance(context: XMLContext<*>, element: Element): TickComponent {
+ return TickComponent(context.getMethodFromAttribute(element, QName("tick")))
+ }
+
+ override fun getName(): QName {
+ return QName(firmUrl, "Tick")
+ }
+
+ override fun getChildCount(): ChildCount {
+ return ChildCount.NONE
+ }
+
+ override fun getAttributeNames(): Map<String, Boolean> {
+ return mapOf("tick" to true)
}
})
uni.registerLoader(object : XMLGuiLoader.Basic<FixedComponent> {
diff --git a/src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt b/src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt
index 7a20346..ca8bac6 100644
--- a/src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt
+++ b/src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt
@@ -31,8 +31,8 @@ object WarpUtil {
private var lastAttemptedWarp = ""
private var lastWarpAttempt = TimeMark.farPast()
fun findNearestWarp(island: SkyBlockIsland, pos: Position): Islands.Warp? {
- return warps.minByOrNull {
- if (island.locrawMode != it.mode || (DConfig.data?.excludedWarps?.contains(it.warp) == true)) {
+ return warps.asSequence().filter { it.mode == island.locrawMode }.minByOrNull {
+ if (DConfig.data?.excludedWarps?.contains(it.warp) == true) {
return@minByOrNull Double.MAX_VALUE
} else {
return@minByOrNull squaredDist(pos, it)
@@ -48,8 +48,11 @@ object WarpUtil {
}
fun teleportToNearestWarp(island: SkyBlockIsland, pos: Position) {
- val nearestWarp = findNearestWarp(island, pos) ?: return
-
+ val nearestWarp = findNearestWarp(island, pos)
+ if (nearestWarp == null) {
+ MC.sendChat(Text.literal("Could not find an unlocked warp in ${island.userFriendlyName}"))
+ return
+ }
if (island == SBData.skyblockLocation
&& sqrt(squaredDist(pos, nearestWarp)) > 1.1 * sqrt(squaredDist((MC.player ?: return).pos, nearestWarp))
) {
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt b/src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt
index 01a7083..79d6e6f 100644
--- a/src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt
+++ b/src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt
@@ -37,7 +37,8 @@ class FacingThePlayerContext(val worldContext: RenderInWorldContext) {
fun text(
vararg texts: Text,
- verticalAlign: RenderInWorldContext.VerticalAlign = RenderInWorldContext.VerticalAlign.CENTER
+ verticalAlign: RenderInWorldContext.VerticalAlign = RenderInWorldContext.VerticalAlign.CENTER,
+ background: Int = 0x70808080,
) {
assertTrueOr(texts.isNotEmpty()) { return@text }
for ((index, text) in texts.withIndex()) {
@@ -47,14 +48,14 @@ class FacingThePlayerContext(val worldContext: RenderInWorldContext) {
val vertexConsumer: VertexConsumer =
worldContext.vertexConsumers.getBuffer(RenderLayer.getTextBackgroundSeeThrough())
val matrix4f = worldContext.matrixStack.peek().positionMatrix
- vertexConsumer.vertex(matrix4f, -1.0f, -1.0f, 0.0f).color(0x70808080)
+ vertexConsumer.vertex(matrix4f, -1.0f, -1.0f, 0.0f).color(background)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
- vertexConsumer.vertex(matrix4f, -1.0f, MC.font.fontHeight.toFloat(), 0.0f).color(0x70808080)
+ vertexConsumer.vertex(matrix4f, -1.0f, MC.font.fontHeight.toFloat(), 0.0f).color(background)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
vertexConsumer.vertex(matrix4f, width.toFloat(), MC.font.fontHeight.toFloat(), 0.0f)
- .color(0x70808080)
+ .color(background)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
- vertexConsumer.vertex(matrix4f, width.toFloat(), -1.0f, 0.0f).color(0x70808080)
+ vertexConsumer.vertex(matrix4f, width.toFloat(), -1.0f, 0.0f).color(background)
.light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
worldContext.matrixStack.translate(0F, 0F, 0.01F)
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt b/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt
index 3b6e262..0620425 100644
--- a/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt
+++ b/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt
@@ -83,11 +83,12 @@ class RenderInWorldContext private constructor(
}
}
- fun waypoint(position: BlockPos, label: Text) {
+ fun waypoint(position: BlockPos, vararg label: Text) {
text(
position.toCenterPos(),
- label,
- Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}")
+ *label,
+ Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}"),
+ background = 0xAA202020.toInt()
)
}
@@ -123,9 +124,9 @@ class RenderInWorldContext private constructor(
}
}
- fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER) {
+ fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER, background: Int = 0x70808080) {
withFacingThePlayer(position) {
- text(*texts, verticalAlign = verticalAlign)
+ text(*texts, verticalAlign = verticalAlign, background = background)
}
}
diff --git a/src/main/resources/assets/firmament/gui/npc_waypoints.xml b/src/main/resources/assets/firmament/gui/npc_waypoints.xml
new file mode 100644
index 0000000..a71e899
--- /dev/null
+++ b/src/main/resources/assets/firmament/gui/npc_waypoints.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
+
+SPDX-License-Identifier: GPL-3.0-or-later
+-->
+
+<Root xmlns="http://notenoughupdates.org/moulconfig" xmlns:firm="http://firmament.nea.moe/moulconfig">
+ <Center>
+ <Panel background="VANILLA" insets="5">
+ <Column>
+ <Center>
+ <TextField value="@search" width="200"/>
+ </Center>
+ <firm:Tick tick="@tick"/>
+ <Spacer height="5"/>
+ <Panel background="TRANSPARENT" insets="4">
+ <ScrollPanel width="200" height="300">
+ <Array data="@results">
+ <Row>
+ <Text text="@name" width="180"/>
+ <firm:Hover lines="Click to set this waypoint as your destination;Shift-Click to warp to the nearest warp point and set this as your destination">
+ <firm:Button onClick="@click" noBackground="true">
+ <When condition="@isSelected">
+ <firm:Image resource="firmament:textures/gui/waypoint_selected.png"
+ width="16"
+ height="16"/>
+ <firm:Image resource="firmament:textures/gui/waypoint_unselected.png"
+ width="16"
+ height="16"/>
+ </When>
+ </firm:Button>
+ </firm:Hover>
+ </Row>
+ </Array>
+ </ScrollPanel>
+ </Panel>
+ </Column>
+ </Panel>
+ </Center>
+</Root>
diff --git a/src/main/resources/assets/firmament/textures/gui/waypoint_selected.png b/src/main/resources/assets/firmament/textures/gui/waypoint_selected.png
new file mode 100644
index 0000000..80108ad
--- /dev/null
+++ b/src/main/resources/assets/firmament/textures/gui/waypoint_selected.png
Binary files differ
diff --git a/src/main/resources/assets/firmament/textures/gui/waypoint_unselected.png b/src/main/resources/assets/firmament/textures/gui/waypoint_unselected.png
new file mode 100644
index 0000000..3c47e75
--- /dev/null
+++ b/src/main/resources/assets/firmament/textures/gui/waypoint_unselected.png
Binary files differ