Add /firm npcs command
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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++))
|
||||
|
||||
@@ -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>()
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
59
src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt
Normal file
59
src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
33
src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt
Normal file
33
src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt
Normal file
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
18
src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt
Normal file
18
src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt
Normal file
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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))
|
||||
) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
42
src/main/resources/assets/firmament/gui/npc_waypoints.xml
Normal file
42
src/main/resources/assets/firmament/gui/npc_waypoints.xml
Normal file
@@ -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>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 225 B |
Binary file not shown.
|
After Width: | Height: | Size: 217 B |
Reference in New Issue
Block a user