Add temporary waypoints and /firm sendcoords
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
@@ -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())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user