diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/autoflight/AutopilotLogicComputer.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/autoflight/AutopilotLogicComputer.kt index fd0e2e8..79d42ba 100644 --- a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/autoflight/AutopilotLogicComputer.kt +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/autoflight/AutopilotLogicComputer.kt @@ -39,8 +39,19 @@ class AutopilotLogicComputer(computers: ComputerView) : Computer(computers) { } } - fun computePitch(active: Boolean): ControlInput? { - TODO() + fun computePitch(active: Boolean): ControlInput { + return when (verticalMode.type) { + VerticalMode.Type.SelectedPitch -> + ControlInput( + verticalMode.pitchOrAltitude, + ControlInput.Priority.NORMAL, + Text.translatable("mode.flightassistant.vertical.selected_pitch", "%.1f".format(verticalMode.pitchOrAltitude)), + active = active, + identifier = ID + ) + VerticalMode.Type.SelectedAltitude -> TODO() + VerticalMode.Type.WaypointAltitude -> TODO() + } } fun computeHeading(active: Boolean): ControlInput? { diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/GroundProximityComputer.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/GroundProximityComputer.kt index 97a8575..dfba8a4 100644 --- a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/GroundProximityComputer.kt +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/GroundProximityComputer.kt @@ -133,7 +133,7 @@ class GroundProximityComputer(computers: ComputerView) : Computer(computers), Pi return ControlInput( computers.data.pitch.coerceAtMost(0.0f), ControlInput.Priority.HIGH, - Text.translatable("mode.flightassistant.pitch.terrain_protection") + Text.translatable("mode.flightassistant.vertical.terrain_protection") ) } @@ -149,7 +149,7 @@ class GroundProximityComputer(computers: ComputerView) : Computer(computers), Pi return ControlInput( 90.0f, ControlInput.Priority.HIGH, - Text.translatable("mode.flightassistant.pitch.terrain_escape"), + Text.translatable("mode.flightassistant.vertical.terrain_escape"), 1.0f / minImpactTime, active = groundImpactStatus == Status.RECOVER || obstacleImpactStatus == Status.RECOVER ) diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/StallComputer.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/StallComputer.kt index 5304d26..563075f 100644 --- a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/StallComputer.kt +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/StallComputer.kt @@ -53,7 +53,7 @@ class StallComputer(computers: ComputerView) : Computer(computers), PitchLimiter return ControlInput( maximumSafePitch, ControlInput.Priority.HIGHEST, - Text.translatable("mode.flightassistant.pitch.stall_protection"), + Text.translatable("mode.flightassistant.vertical.stall_protection"), 1.5f, FAConfig.safety.stallLimitPitch ) diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/VoidProximityComputer.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/VoidProximityComputer.kt index 3555409..015cdc8 100644 --- a/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/VoidProximityComputer.kt +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/safety/VoidProximityComputer.kt @@ -45,7 +45,7 @@ class VoidProximityComputer(computers: ComputerView) : Computer(computers), Pitc (-90.0f + (computers.data.world.bottomY - (computers.data.altitude + computers.data.velocity.y * 20)) / 64.0f * 105.0f).toFloat() .coerceIn(-35.0f..computers.thrust.getOptimumClimbPitch()), ControlInput.Priority.HIGH, - Text.translatable("mode.flightassistant.pitch.void_protection") + Text.translatable("mode.flightassistant.vertical.void_protection") ) } @@ -54,7 +54,7 @@ class VoidProximityComputer(computers: ComputerView) : Computer(computers), Pitc override fun getPitchInput(): ControlInput? { if (FAConfig.safety.voidAutoPitch && status <= Status.APPROACHING_DAMAGE_ALTITUDE) { - return ControlInput(computers.thrust.getOptimumClimbPitch(), ControlInput.Priority.HIGH, Text.translatable("mode.flightassistant.pitch.void_escape"), + return ControlInput(computers.thrust.getOptimumClimbPitch(), ControlInput.Priority.HIGH, Text.translatable("mode.flightassistant.vertical.void_escape"), active = status == Status.REACHED_DAMAGE_ALTITUDE && computers.thrust.current >= ThrustComputer.TOGA_THRESHOLD && !computers.thrust.noThrustSource) } diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/screen/AutoFlightScreen.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/AutoFlightScreen.kt index 535e393..1015ce8 100644 --- a/src/main/kotlin/ru/octol1ttle/flightassistant/screen/AutoFlightScreen.kt +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/AutoFlightScreen.kt @@ -7,12 +7,16 @@ import net.minecraft.util.Formatting import ru.octol1ttle.flightassistant.api.computer.ComputerView import ru.octol1ttle.flightassistant.impl.computer.ComputerHost import ru.octol1ttle.flightassistant.screen.widgets.ColoredButtonWidget +import ru.octol1ttle.flightassistant.screen.widgets.autoflight.DelayedApplyChanges import ru.octol1ttle.flightassistant.screen.widgets.autoflight.ThrustModeWidget +import ru.octol1ttle.flightassistant.screen.widgets.autoflight.VerticalModeWidget class AutoFlightScreen : FABaseScreen(Text.translatable("menu.flightassistant.autoflight")) { private lateinit var flightDirectors: ColoredButtonWidget private lateinit var autoThrust: ColoredButtonWidget private lateinit var autopilot: ColoredButtonWidget + private var thrustMode: ThrustModeWidget? = null + private var verticalMode: VerticalModeWidget? = null override fun init() { super.init() @@ -23,20 +27,24 @@ class AutoFlightScreen : FABaseScreen(Text.translatable("menu.flightassistant.au computers.automations.setFlightDirectors(!computers.automations.flightDirectors) }.position(this.centerX - 100, this.centerY + 50).width(200).build()) autoThrust = this.addDrawableChild(ColoredButtonWidget.builder(Text.translatable("menu.flightassistant.autoflight.auto_thrust")) { + thrustMode?.applyChanges() computers.automations.setAutoThrust(!computers.automations.autoThrust, true) }.position(this.centerX - 100, this.centerY + 80).width(95).build()) autopilot = this.addDrawableChild(ColoredButtonWidget.builder(Text.translatable("menu.flightassistant.autoflight.autopilot")) { computers.automations.setAutoPilot(!computers.automations.autopilot, true) }.position(this.centerX + 5, this.centerY + 80).width(95).build()) - this.addDrawableChild(ThrustModeWidget(computers, 0, this.height / 3, this.width / 3)) + thrustMode?.applyChanges() + thrustMode = this.addDrawableChild(ThrustModeWidget(computers, 5, this.height / 3, this.width / 3 - 3)) + verticalMode?.applyChanges() + verticalMode = this.addDrawableChild(VerticalModeWidget(computers, 3 + this.width / 3 + 3, this.height / 3, this.width / 3 - 3)) } override fun close() { super.close() for (child: Element in children()) { - if (child is AutoCloseable) { - child.close() + if (child is DelayedApplyChanges) { + child.applyChanges() } } } diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/DelayedApplyChanges.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/DelayedApplyChanges.kt new file mode 100644 index 0000000..551b87c --- /dev/null +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/DelayedApplyChanges.kt @@ -0,0 +1,5 @@ +package ru.octol1ttle.flightassistant.screen.widgets.autoflight + +interface DelayedApplyChanges { + fun applyChanges() +} diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/ThrustModeWidget.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/ThrustModeWidget.kt index dad33d4..dfffb7a 100644 --- a/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/ThrustModeWidget.kt +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/ThrustModeWidget.kt @@ -13,8 +13,7 @@ import ru.octol1ttle.flightassistant.api.util.extensions.clearAndAdd import ru.octol1ttle.flightassistant.impl.computer.autoflight.AutopilotLogicComputer import ru.octol1ttle.flightassistant.screen.widgets.AbstractParentWidget -// TODO: fix dimensions -class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val width: Int) : AbstractParentWidget(), AutoCloseable { +class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val width: Int) : AbstractParentWidget(), DelayedApplyChanges { private val title: TextWidget = TextWidget( x, y, width, 20, Text.translatable("menu.flightassistant.autoflight.thrust"), mc.textRenderer ) @@ -27,7 +26,7 @@ class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val buttons[AutopilotLogicComputer.ThrustMode.Type.WaypointThrust] = ButtonWidget.builder( Text.translatable("menu.flightassistant.autoflight.thrust.waypoint_thrust") ) { newType = AutopilotLogicComputer.ThrustMode.Type.WaypointThrust } - .dimensions(x, y + 20, width / 3 - 5, 15).build() + .dimensions(x + (width * (2 / TOTAL_MODES)).toInt() + 1, y + 20, width / 3 - 1, 15).build() } private fun initSelectedSpeed() { @@ -36,7 +35,7 @@ class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val buttons[type] = ButtonWidget.builder( Text.translatable("menu.flightassistant.autoflight.thrust.selected_speed") ) { newType = type } - .dimensions(x, y + 20, (width - 15) / 3, 15).build() + .dimensions(x + 1, y + 20, width / 3 - 1, 15).build() val targetSpeedWidget = TextFieldWidget( mc.textRenderer, x + width / 4, y + 40, width / 2, 15, textFields[type]?.singleOrNull(), Text.empty() ) @@ -54,10 +53,10 @@ class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val buttons[type] = ButtonWidget.builder( Text.translatable("menu.flightassistant.autoflight.thrust.vertical_target") ) { newType = type } - .dimensions(x + (width - 15) / 3, y + 20, (width - 15) / 3, 15).build() + .dimensions(x + (width * (1 / TOTAL_MODES)).toInt() + 1, y + 20, width / 3 - 1, 15).build() val climbThrustWidget = TextFieldWidget( - mc.textRenderer, x, y + 40, (width - 10) / 2, 15, textFields[type]?.firstOrNull(), Text.empty() + mc.textRenderer, x + 2, y + 40, width / 2 - 4, 15, textFields[type]?.firstOrNull(), Text.empty() ) climbThrustWidget.setPlaceholder(Text.translatable("menu.flightassistant.autoflight.thrust.vertical_target.climb_thrust")) climbThrustWidget.setTextPredicate { @@ -66,7 +65,7 @@ class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val } val descendThrustWidget = TextFieldWidget( - mc.textRenderer, x + width / 2, y + 40, (width - 10) / 2, 15, textFields[type]?.firstOrNull(), Text.empty() + mc.textRenderer, x + width / 2 + 3, y + 40, width / 2 - 4, 15, textFields[type]?.firstOrNull(), Text.empty() ) descendThrustWidget.setPlaceholder(Text.translatable("menu.flightassistant.autoflight.thrust.vertical_target.descend_thrust")) descendThrustWidget.setTextPredicate { @@ -81,13 +80,13 @@ class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val val list = ArrayList() list.add(title) list.addAll(buttons.values) - textFields[computers.autopilot.thrustMode.type]?.let { + textFields[newType]?.let { list.addAll(it) } return list } - override fun close() { + override fun applyChanges() { computers.autopilot.thrustMode.type = newType when (val type: AutopilotLogicComputer.ThrustMode.Type = computers.autopilot.thrustMode.type) { AutopilotLogicComputer.ThrustMode.Type.SelectedSpeed -> computers.autopilot.thrustMode.speed = textFields[type]!!.single().text.toFloatOrNull() ?: 0.0f @@ -101,7 +100,7 @@ class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val override fun render(context: DrawContext?, mouseX: Int, mouseY: Int, delta: Float) { for (button in buttons) { - button.value.active = computers.autopilot.thrustMode.type != button.key + button.value.active = newType != button.key } super.render(context, mouseX, mouseY, delta) @@ -110,5 +109,6 @@ class ThrustModeWidget(val computers: ComputerView, val x: Int, val y: Int, val companion object { private val buttons: EnumMap = EnumMap(AutopilotLogicComputer.ThrustMode.Type::class.java) private val textFields: EnumMap> = EnumMap(AutopilotLogicComputer.ThrustMode.Type::class.java) + const val TOTAL_MODES: Float = 3.0f } } diff --git a/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/VerticalModeWidget.kt b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/VerticalModeWidget.kt new file mode 100644 index 0000000..17cb473 --- /dev/null +++ b/src/main/kotlin/ru/octol1ttle/flightassistant/screen/widgets/autoflight/VerticalModeWidget.kt @@ -0,0 +1,100 @@ +package ru.octol1ttle.flightassistant.screen.widgets.autoflight + +import java.util.EnumMap +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.gui.Element +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.gui.widget.TextFieldWidget +import net.minecraft.client.gui.widget.TextWidget +import net.minecraft.text.Text +import ru.octol1ttle.flightassistant.FlightAssistant.mc +import ru.octol1ttle.flightassistant.api.computer.ComputerView +import ru.octol1ttle.flightassistant.api.util.extensions.clearAndAdd +import ru.octol1ttle.flightassistant.impl.computer.autoflight.AutopilotLogicComputer +import ru.octol1ttle.flightassistant.screen.widgets.AbstractParentWidget + +class VerticalModeWidget(val computers: ComputerView, val x: Int, val y: Int, val width: Int) : AbstractParentWidget(), DelayedApplyChanges { + private val title: TextWidget = TextWidget( + x, y, width, 20, Text.translatable("menu.flightassistant.autoflight.vertical"), mc.textRenderer + ) + private var newType: AutopilotLogicComputer.VerticalMode.Type = computers.autopilot.verticalMode.type + + init { + initSelectedPitch() + initSelectedAltitude() + + buttons[AutopilotLogicComputer.VerticalMode.Type.WaypointAltitude] = ButtonWidget.builder( + Text.translatable("menu.flightassistant.autoflight.vertical.waypoint_altitude") + ) { newType = AutopilotLogicComputer.VerticalMode.Type.WaypointAltitude } + .dimensions(x + (width * (2 / TOTAL_MODES)).toInt() + 1, y + 20, width / 3 - 1, 15).build() + } + + private fun initSelectedPitch() { + val type = AutopilotLogicComputer.VerticalMode.Type.SelectedPitch + + buttons[type] = ButtonWidget.builder( + Text.translatable("menu.flightassistant.autoflight.vertical.selected_pitch") + ) { newType = type } + .dimensions(x + 1, y + 20, width / 3 - 1, 15).build() + val selectedPitchWidget = TextFieldWidget( + mc.textRenderer, x + width / 4, y + 40, width / 2, 15, textFields[type]?.singleOrNull(), Text.empty() + ) + selectedPitchWidget.setPlaceholder(Text.translatable("menu.flightassistant.autoflight.vertical.selected_pitch.target")) + selectedPitchWidget.setTextPredicate { + val i: Float? = it.toFloatOrNull() + it.isEmpty() || i != null && i in -90.0f..90.0f + } + textFields.computeIfAbsent(type) { ArrayList() }.clearAndAdd(selectedPitchWidget) + } + + private fun initSelectedAltitude() { + val type = AutopilotLogicComputer.VerticalMode.Type.SelectedAltitude + + buttons[type] = ButtonWidget.builder( + Text.translatable("menu.flightassistant.autoflight.vertical.selected_altitude") + ) { newType = type } + .dimensions(x + (width * (1 / TOTAL_MODES)).toInt() + 1, y + 20, width / 3 - 1, 15).build() + + val selectedAltitudeWidget = TextFieldWidget( + mc.textRenderer, x + width / 4, y + 40, width / 2, 15, textFields[type]?.singleOrNull(), Text.empty() + ) + selectedAltitudeWidget.setPlaceholder(Text.translatable("menu.flightassistant.autoflight.vertical.selected_altitude.target")) + selectedAltitudeWidget.setTextPredicate { + it.isEmpty() || it.toIntOrNull() != null + } + textFields.computeIfAbsent(type) { ArrayList() }.clearAndAdd(selectedAltitudeWidget) + } + + override fun children(): MutableList { + val list = ArrayList() + list.add(title) + list.addAll(buttons.values) + textFields[newType]?.let { + list.addAll(it) + } + return list + } + + override fun applyChanges() { + computers.autopilot.verticalMode.type = newType + when (val type: AutopilotLogicComputer.VerticalMode.Type = computers.autopilot.verticalMode.type) { + AutopilotLogicComputer.VerticalMode.Type.SelectedPitch, AutopilotLogicComputer.VerticalMode.Type.SelectedAltitude + -> computers.autopilot.verticalMode.pitchOrAltitude = textFields[type]!!.single().text.toFloatOrNull() ?: 0.0f + else -> Unit + } + } + + override fun render(context: DrawContext?, mouseX: Int, mouseY: Int, delta: Float) { + for (button in buttons) { + button.value.active = newType != button.key + } + + super.render(context, mouseX, mouseY, delta) + } + + companion object { + private val buttons: EnumMap = EnumMap(AutopilotLogicComputer.VerticalMode.Type::class.java) + private val textFields: EnumMap> = EnumMap(AutopilotLogicComputer.VerticalMode.Type::class.java) + const val TOTAL_MODES: Float = 3.0f + } +} diff --git a/src/main/resources/assets/flightassistant/lang/en_us.yml b/src/main/resources/assets/flightassistant/lang/en_us.yml index b2ecedb..69aeefe 100644 --- a/src/main/resources/assets/flightassistant/lang/en_us.yml +++ b/src/main/resources/assets/flightassistant/lang/en_us.yml @@ -240,6 +240,15 @@ menu.flightassistant: climb_thrust: Climb thrust descend_thrust: Descend thrust waypoint_thrust: F/PLAN + vertical: + .: Vertical + selected_pitch: + .: PITCH + target: Target pitch + selected_altitude: + .: ALT + target: Target altitude + waypoint_altitude: F/PLAN mode.flightassistant: thrust: @@ -252,13 +261,13 @@ mode.flightassistant: selected_speed: SPD %s climb: THR CLB descend: THR DES - pitch: + vertical: void_protection: VOID PROT void_escape: VOID ESC stall_protection: STALL PROT terrain_protection: TERR PROT terrain_escape: TERR ESC - altitude: ALT %s + selected_pitch: PITCH %s heading: selected: HDG %s diff --git a/src/main/resources/assets/flightassistant/lang/ru_ru.yml b/src/main/resources/assets/flightassistant/lang/ru_ru.yml index 4addada..85abfd0 100644 --- a/src/main/resources/assets/flightassistant/lang/ru_ru.yml +++ b/src/main/resources/assets/flightassistant/lang/ru_ru.yml @@ -244,6 +244,15 @@ menu.flightassistant: climb_thrust: Тяга набора descend_thrust: Тяга снижения waypoint_thrust: ПЛАН/П + vertical: + .: Вертикаль + selected_pitch: + .: УГОЛ + target: Целевой угол + selected_altitude: + .: ВЫС + target: Целевая выс. + waypoint_altitude: ПЛАН/П mode.flightassistant: thrust: @@ -256,13 +265,13 @@ mode.flightassistant: selected_speed: СКОР %s climb: ТЯГА НАБОР descend: ТЯГА СНИЖ - pitch: + vertical: void_protection: ПУСТ ЗАЩ void_escape: ПУСТ ВЫХОД stall_protection: СВАЛ ЗАЩ terrain_protection: ЗЕМЛ ЗАЩ terrain_escape: ЗЕМЛ ИЗБЕЖ - altitude: ВЫС %s + selected_pitch: УГОЛ %s heading: selected: КУРС %s