Add temporary waypoints and /firm sendcoords

This commit is contained in:
Linnea Gräf
2023-11-12 14:45:05 +01:00
parent 897ab0f06b
commit 2c9c388683
9 changed files with 151 additions and 6 deletions

View File

@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package moe.nea.firmament.mixins.accessor;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.GameRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(GameRenderer.class)
public interface AccessorGameRenderer {
@Invoker("getFov")
double getFov_firmament(Camera camera, float tickDelta, boolean changingFov);
}

View File

@@ -36,8 +36,9 @@ fun firmamentCommand() = literal("firmament") {
} }
thenArgument("property", string()) { property -> thenArgument("property", string()) { property ->
suggestsList { suggestsList {
(AllConfigsGui.allConfigs.find { it.name == this[config] }?:return@suggestsList listOf()) (AllConfigsGui.allConfigs.find { it.name == this[config] } ?: return@suggestsList listOf())
.allOptions.entries.asSequence().filter { it.value.handler is BooleanHandler }.map { it.key } .allOptions.entries.asSequence().filter { it.value.handler is BooleanHandler }
.map { it.key }
.asIterable() .asIterable()
} }
thenExecute { thenExecute {
@@ -89,6 +90,12 @@ fun firmamentCommand() = literal("firmament") {
InventoryButtons.openEditor() InventoryButtons.openEditor()
} }
} }
thenLiteral("sendcoords") {
thenExecute {
val p = MC.player ?: return@thenExecute
MC.sendServerChat("x: ${p.blockX}, y: ${p.blockY}, z: ${p.blockZ}")
}
}
thenLiteral("storage") { thenLiteral("storage") {
thenExecute { thenExecute {
ScreenUtil.setScreenLater(StorageOverlayScreen()) ScreenUtil.setScreenLater(StorageOverlayScreen())

View File

@@ -6,8 +6,8 @@
package moe.nea.firmament.events package moe.nea.firmament.events
import moe.nea.firmament.util.unformattedString
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.util.unformattedString
/** /**
* Behaves like [AllowChatEvent], but is triggered even when cancelled by other mods. Intended for data collection. * Behaves like [AllowChatEvent], but is triggered even when cancelled by other mods. Intended for data collection.
@@ -16,6 +16,13 @@ import net.minecraft.text.Text
data class ProcessChatEvent(val text: Text, val wasExternallyCancelled: Boolean) : FirmamentEvent.Cancellable() { data class ProcessChatEvent(val text: Text, val wasExternallyCancelled: Boolean) : FirmamentEvent.Cancellable() {
val unformattedString = text.unformattedString val unformattedString = text.unformattedString
val nameHeuristic: String? = run {
val firstColon = unformattedString.indexOf(':')
if (firstColon < 0) return@run null
val firstSpace = unformattedString.lastIndexOf(' ', firstColon)
unformattedString.substring(firstSpace + 1 until firstColon).takeIf { it.isNotEmpty() }
}
init { init {
if (wasExternallyCancelled) if (wasExternallyCancelled)
cancelled = true cancelled = true

View File

@@ -27,6 +27,7 @@ import moe.nea.firmament.features.inventory.buttons.InventoryButtons
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlay import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlay
import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures
import moe.nea.firmament.features.world.FairySouls import moe.nea.firmament.features.world.FairySouls
import moe.nea.firmament.features.world.Waypoints
import moe.nea.firmament.util.data.DataHolder import moe.nea.firmament.util.data.DataHolder
object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "features", ::Config) { object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "features", ::Config) {
@@ -56,6 +57,7 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
loadFeature(StorageOverlay) loadFeature(StorageOverlay)
loadFeature(CraftingOverlay) loadFeature(CraftingOverlay)
loadFeature(PowerUserTools) loadFeature(PowerUserTools)
loadFeature(Waypoints)
loadFeature(ChatLinks) loadFeature(ChatLinks)
loadFeature(InventoryButtons) loadFeature(InventoryButtons)
loadFeature(CompatibliltyFeatures) loadFeature(CompatibliltyFeatures)

View File

@@ -0,0 +1,72 @@
/*
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package moe.nea.firmament.features.world
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.seconds
import net.minecraft.text.Text
import net.minecraft.util.math.BlockPos
import moe.nea.firmament.events.ProcessChatEvent
import moe.nea.firmament.events.WorldReadyEvent
import moe.nea.firmament.events.WorldRenderLastEvent
import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.TimeMark
import moe.nea.firmament.util.render.RenderInWorldContext
object Waypoints : FirmamentFeature {
override val identifier: String
get() = "waypoints"
object TConfig : ManagedConfig(identifier) {
val tempWaypointDuration by duration("temp-waypoint-duration", 0.seconds, 1.hours) { 30.seconds }
}
data class TemporaryWaypoint(
val pos: BlockPos,
val postedAt: TimeMark,
)
override val config get() = TConfig
val temporaryWaypointList = mutableMapOf<String, TemporaryWaypoint>()
val temporaryWaypointMatcher = "x: (-?[0-9]+),? y: (-?[0-9]+),? z: (-?[0-9]+)".toPattern()
override fun onLoad() {
WorldRenderLastEvent.subscribe {
temporaryWaypointList.entries.removeIf { it.value.postedAt.passedTime() > TConfig.tempWaypointDuration }
if (temporaryWaypointList.isNotEmpty())
RenderInWorldContext.renderInWorld(it) {
color(1f, 1f, 0f, 1f)
temporaryWaypointList.forEach { (player, waypoint) ->
block(waypoint.pos)
}
color(1f, 1f, 1f, 1f)
temporaryWaypointList.forEach { (player, waypoint) ->
waypoint(waypoint.pos, Text.translatable("firmament.waypoint.temporary", player))
}
}
}
WorldReadyEvent.subscribe {
temporaryWaypointList.clear()
}
ProcessChatEvent.subscribe {
val matcher = temporaryWaypointMatcher.matcher(it.unformattedString)
if (it.nameHeuristic != null && TConfig.tempWaypointDuration > 0.seconds && matcher.find()) {
temporaryWaypointList.put(
it.nameHeuristic, TemporaryWaypoint(
BlockPos(
matcher.group(1).toInt(),
matcher.group(2).toInt(),
matcher.group(3).toInt(),
),
TimeMark.now()
)
)
}
}
}
}

View File

@@ -28,6 +28,12 @@ object FirmFormatters {
return formatCurrency(long) + (if (digits.isEmpty()) "" else ".$digits") return formatCurrency(long) + (if (digits.isEmpty()) "" else ".$digits")
} }
fun formatDistance(distance: Double): String {
if (distance < 10)
return "%.1fm".format(distance)
return "%dm".format(distance.toInt())
}
fun formatTimespan(duration: Duration): String { fun formatTimespan(duration: Duration): String {
return duration.toString() return duration.toString()
} }

View File

@@ -51,6 +51,10 @@ object MC {
) )
} }
fun sendServerChat(text: String) {
player?.networkHandler?.sendChatMessage(text)
}
fun sendCommand(command: String) { fun sendCommand(command: String) {
player?.networkHandler?.sendCommand(command) player?.networkHandler?.sendCommand(command)
} }

View File

@@ -8,8 +8,10 @@ package moe.nea.firmament.util.render
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import java.lang.Math.pow import java.lang.Math.pow
import java.lang.Math.toRadians
import org.joml.Matrix4f import org.joml.Matrix4f
import org.joml.Vector3f import org.joml.Vector3f
import kotlin.math.tan
import net.minecraft.client.font.TextRenderer import net.minecraft.client.font.TextRenderer
import net.minecraft.client.gl.VertexBuffer import net.minecraft.client.gl.VertexBuffer
import net.minecraft.client.render.BufferBuilder import net.minecraft.client.render.BufferBuilder
@@ -28,6 +30,8 @@ import net.minecraft.text.Text
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d import net.minecraft.util.math.Vec3d
import moe.nea.firmament.events.WorldRenderLastEvent import moe.nea.firmament.events.WorldRenderLastEvent
import moe.nea.firmament.mixins.accessor.AccessorGameRenderer
import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.assertTrueOr import moe.nea.firmament.util.assertTrueOr
@@ -35,9 +39,12 @@ class RenderInWorldContext private constructor(
private val tesselator: Tessellator, private val tesselator: Tessellator,
private val matrixStack: MatrixStack, private val matrixStack: MatrixStack,
private val camera: Camera, private val camera: Camera,
private val tickDelta: Float,
private val vertexConsumers: VertexConsumerProvider.Immediate, private val vertexConsumers: VertexConsumerProvider.Immediate,
) { ) {
private val buffer = tesselator.buffer private val buffer = tesselator.buffer
val effectiveFov = (MC.instance.gameRenderer as AccessorGameRenderer).getFov_firmament(camera, tickDelta, true)
val effectiveFovScaleFactor = 1 / tan(toRadians(effectiveFov) / 2)
fun color(red: Float, green: Float, blue: Float, alpha: Float) { fun color(red: Float, green: Float, blue: Float, alpha: Float) {
RenderSystem.setShaderColor(red, green, blue, alpha) RenderSystem.setShaderColor(red, green, blue, alpha)
@@ -65,15 +72,24 @@ class RenderInWorldContext private constructor(
} }
fun waypoint(position: BlockPos, label: Text) { fun waypoint(position: BlockPos, label: Text) {
text(position.toCenterPos(), label, Text.literal("§e${MC.player?.pos?.distanceTo(position.toCenterPos())}m")) text(
position.toCenterPos(),
label,
Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}")
)
} }
fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER) { fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER) {
assertTrueOr(texts.isNotEmpty()) { return@text } assertTrueOr(texts.isNotEmpty()) { return@text }
matrixStack.push() matrixStack.push()
matrixStack.translate(position.x, position.y, position.z) matrixStack.translate(position.x, position.y, position.z)
val actualCameraDistance = position.distanceTo(camera.pos)
val distanceToMoveTowardsCamera = if (actualCameraDistance < 10) 0.0 else -(actualCameraDistance - 10.0)
val vec = position.subtract(camera.pos).multiply(distanceToMoveTowardsCamera / actualCameraDistance)
matrixStack.translate(vec.x, vec.y, vec.z)
matrixStack.multiply(camera.rotation) matrixStack.multiply(camera.rotation)
matrixStack.scale(-0.025F, -0.025F, -1F) matrixStack.scale(-0.025F, -0.025F, -1F)
for ((index, text) in texts.withIndex()) { for ((index, text) in texts.withIndex()) {
matrixStack.push() matrixStack.push()
val width = MC.font.getWidth(text) val width = MC.font.getWidth(text)
@@ -145,7 +161,16 @@ class RenderInWorldContext private constructor(
} }
companion object { companion object {
private fun doLine(matrix: Entry, buf: BufferBuilder, i: Number, j: Number, k: Number, x: Number, y: Number, z: Number) { private fun doLine(
matrix: Entry,
buf: BufferBuilder,
i: Number,
j: Number,
k: Number,
x: Number,
y: Number,
z: Number
) {
val normal = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) val normal = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
.sub(i.toFloat(), j.toFloat(), k.toFloat()) .sub(i.toFloat(), j.toFloat(), k.toFloat())
.mul(-1F) .mul(-1F)
@@ -226,6 +251,7 @@ class RenderInWorldContext private constructor(
RenderSystem.renderThreadTesselator(), RenderSystem.renderThreadTesselator(),
event.matrices, event.matrices,
event.camera, event.camera,
event.tickDelta,
event.vertexConsumers event.vertexConsumers
) )

View File

@@ -64,7 +64,10 @@
"firmament.inventory-buttons.save-preset": "Save Preset", "firmament.inventory-buttons.save-preset": "Save Preset",
"firmament.inventory-buttons.load-preset": "Load Preset", "firmament.inventory-buttons.load-preset": "Load Preset",
"firmament.inventory-buttons.import-failed": "One of your buttons could only be imported partially", "firmament.inventory-buttons.import-failed": "One of your buttons could only be imported partially",
"firmament.config.inventory-buttons": "One of your buttons could only be imported partially", "firmament.config.inventory-buttons": "Inventory buttons",
"firmament.waypoint.temporary": "Temporary Waypoint: %s",
"firmament.config.waypoints": "Waypoints",
"firmament.config.waypoints.temp-waypoint-duration": "Temporary Waypoint Duration",
"firmament.recipe.forge.time": "Forging Time: %s", "firmament.recipe.forge.time": "Forging Time: %s",
"firmament.pv.skills": "Skills", "firmament.pv.skills": "Skills",
"firmament.pv.skills.farming": "Farming", "firmament.pv.skills.farming": "Farming",