From 465032a36220669cbd641a3efd4d52ff62d83366 Mon Sep 17 00:00:00 2001 From: btwonion Date: Mon, 5 Aug 2024 19:01:26 +0200 Subject: [PATCH] add options to specify where the boat should be boosted --- .github/workflows/readme-modrinth-sync.yml | 2 +- README.md | 13 ++- build.gradle.kts | 2 +- changelog.md | 3 +- src/main/java/dev/nyon/bbm/asm/BoatMixin.java | 73 +++++++++++- .../kotlin/dev/nyon/bbm/BetterBoatMovement.kt | 2 +- src/main/kotlin/dev/nyon/bbm/config/Config.kt | 54 ++++++--- .../dev/nyon/bbm/config/ConfigScreen.kt | 105 +++++++++++------- src/main/resources/assets/bbm/lang/en_us.json | 28 +++-- 9 files changed, 202 insertions(+), 80 deletions(-) diff --git a/.github/workflows/readme-modrinth-sync.yml b/.github/workflows/readme-modrinth-sync.yml index a87aed1..d4cf665 100644 --- a/.github/workflows/readme-modrinth-sync.yml +++ b/.github/workflows/readme-modrinth-sync.yml @@ -5,7 +5,7 @@ on: paths: - "README.md" branches: - - main + - master workflow_dispatch: jobs: diff --git a/README.md b/README.md index 34e3729..0904178 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,15 @@ ```json5 { - "version": 1, // just ignore that, only for migrations + "version": 3, // just ignore that, only for migrations "config": { - "stepHeight": 0.3, // the height the boat should travel upwards - "playerEjectTicks": 200.0, // defines the ticks that should pass before ejecting a player, when the player lost control over the boat - "boostUnderwater": true, // toggles, whether a boat, which is underwater should be boosted upwards with half of the step height - "onlyForPlayers": true // toggles, whether the boosts configured below should only work if the boat carries a player. + "stepHeight": 0.35, // The amount of blocks you are going to be boosted when triggering a boost + "playerEjectTicks": 200.0, // The ticks the game waits before kicking you out of a boat after the player lost control + "boostUnderwater": true, // Toggles, whether a boat, which is underwater should be boosted upwards + "boostOnBlocks": false, // Toggles, whether a boat, which is on a block should be boosted upwards when running against an elevation + "boostOnIce": true, // Toggles, whether a boat, which is on an ice block should be boosted upwards when running against an elevation + "boostOnWater": true, // Toggles, whether a boat, which is on water should be boosted upwards when floating against an elevation + "onlyForPlayers": true // Toggles, whether a boat should only be boosted when carrying a player } } ``` diff --git a/build.gradle.kts b/build.gradle.kts index d5550c1..d9a837a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ plugins { } val beta: Int? = null // Pattern is '1.0.0-beta1-1.20.6-pre.2' -val featureVersion = "2.0.0${if (beta != null) "-beta$beta" else ""}" +val featureVersion = "2.1.0${if (beta != null) "-beta$beta" else ""}" val mcVersion = property("mcVersion")!!.toString() val mcVersionRange = property("mcVersionRange")!!.toString() version = "$featureVersion-$mcVersion" diff --git a/changelog.md b/changelog.md index 9b1299c..df832d7 100644 --- a/changelog.md +++ b/changelog.md @@ -1 +1,2 @@ -- simplify movement logic \ No newline at end of file +- add options to specify where the player wants to get boosted +- use yacl 3.5 for config screen creation \ No newline at end of file diff --git a/src/main/java/dev/nyon/bbm/asm/BoatMixin.java b/src/main/java/dev/nyon/bbm/asm/BoatMixin.java index 67ce332..455a4bd 100644 --- a/src/main/java/dev/nyon/bbm/asm/BoatMixin.java +++ b/src/main/java/dev/nyon/bbm/asm/BoatMixin.java @@ -3,11 +3,16 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import dev.nyon.bbm.config.Config; import dev.nyon.bbm.config.ConfigKt; +import net.minecraft.core.BlockPos; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.Boat; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -16,6 +21,9 @@ import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.ModifyConstant; +import java.util.ArrayList; +import java.util.List; + @Mixin(Boat.class) abstract class BoatMixin extends Entity { @Shadow @@ -28,6 +36,39 @@ public BoatMixin( super(entityType, level); } + @Unique + private List getCarryingBlocks() { + List states = new ArrayList<>(); + + AABB aABB = this.getBoundingBox(); + AABB aABB2 = new AABB(aABB.minX, aABB.minY - 0.001, aABB.minZ, aABB.maxX, aABB.minY, aABB.maxZ); + int i = Mth.floor(aABB2.minX) - 1; + int j = Mth.ceil(aABB2.maxX) + 1; + int k = Mth.floor(aABB2.minY) - 1; + int l = Mth.ceil(aABB2.maxY) + 1; + int m = Mth.floor(aABB2.minZ) - 1; + int n = Mth.ceil(aABB2.maxZ) + 1; + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + + for (int p = i; p < j; p++) { + for (int q = m; q < n; q++) { + int r = (p != i && p != j - 1 ? 0 : 1) + (q != m && q != n - 1 ? 0 : 1); + if (r != 2) { + for (int s = k; s < l; s++) { + if (r <= 0 || s != k && s != l - 1) { + mutableBlockPos.set(p, s, q); + BlockState blockState = this.level() + .getBlockState(mutableBlockPos); + states.add(blockState); + } + } + } + } + } + + return states; + } + @SuppressWarnings("DataFlowIssue") @ModifyExpressionValue( method = "floatBoat", @@ -39,9 +80,33 @@ public BoatMixin( ) private Vec3 changeMovement(Vec3 original) { if (failsPlayerCondition()) return original; - if (!horizontalCollision) return original; - if (status == Boat.Status.UNDER_WATER && !ConfigKt.getActiveConfig() - .getBoostUnderwater()) return original; + + switch (status) { + case ON_LAND -> { + if (!ConfigKt.getActiveConfig() + .getBoostOnBlocks() && !ConfigKt.getActiveConfig() + .getBoostOnIce()) return original; + if (ConfigKt.getActiveConfig() + .getBoostOnIce()) { + List carryingBlocks = getCarryingBlocks(); + if (carryingBlocks.stream() + .noneMatch(state -> state.is(BlockTags.ICE))) return original; + } + if (!horizontalCollision) return original; + } + case IN_WATER -> { + if (!ConfigKt.getActiveConfig() + .getBoostOnWater()) return original; + if (!horizontalCollision) return original; + } + case UNDER_WATER, UNDER_FLOWING_WATER -> { + if (!ConfigKt.getActiveConfig() + .getBoostUnderwater()) return original; + } + case IN_AIR -> { + return original; + } + } return new Vec3( original.x, @@ -71,6 +136,6 @@ private boolean failsPlayerCondition() { if (!config.getOnlyForPlayers()) return false; return getPassengers().stream() - .anyMatch(entity -> entity instanceof Player); + .noneMatch(entity -> entity instanceof Player); } } diff --git a/src/main/kotlin/dev/nyon/bbm/BetterBoatMovement.kt b/src/main/kotlin/dev/nyon/bbm/BetterBoatMovement.kt index 4a4f4cb..fa2cafa 100644 --- a/src/main/kotlin/dev/nyon/bbm/BetterBoatMovement.kt +++ b/src/main/kotlin/dev/nyon/bbm/BetterBoatMovement.kt @@ -53,7 +53,7 @@ object BetterBoatMovement : ModInitializer { private fun instantiateConfig() { config( FabricLoader.getInstance().configDir.resolve("better-boat-movement.json"), - 2, + 3, Config() ) { element, version -> migrate(element, version) } internalConfig = loadConfig() diff --git a/src/main/kotlin/dev/nyon/bbm/config/Config.kt b/src/main/kotlin/dev/nyon/bbm/config/Config.kt index ce77334..206f34c 100644 --- a/src/main/kotlin/dev/nyon/bbm/config/Config.kt +++ b/src/main/kotlin/dev/nyon/bbm/config/Config.kt @@ -4,20 +4,24 @@ import dev.nyon.bbm.extensions.resourceLocation import dev.nyon.bbm.serverConfig import kotlinx.serialization.Serializable import kotlinx.serialization.Transient -import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.* import net.fabricmc.api.EnvType import net.fabricmc.loader.api.FabricLoader import net.minecraft.client.Minecraft import net.minecraft.network.FriendlyByteBuf -/*? if <1.20.5 {*/ + +/*? if <1.20.6 {*/ /*import net.fabricmc.fabric.api.networking.v1.FabricPacket import net.fabricmc.fabric.api.networking.v1.PacketType @Serializable data class Config( - var stepHeight: Float = 0.3f, + var stepHeight: Float = 0.35f, var playerEjectTicks: Float = 20f * 10f, var boostUnderwater: Boolean = true, + var boostOnBlocks: Boolean = true, + var boostOnIce: Boolean = true, + var boostOnWater: Boolean = true, var onlyForPlayers: Boolean = true ) : FabricPacket { companion object { @@ -25,15 +29,26 @@ data class Config( val packetType: PacketType = PacketType.create( resourceLocation("better-boat-movement:sync")!! ) { buffer -> - Config(buffer.readFloat(), buffer.readFloat(), buffer.readBoolean(), buffer.readBoolean()) + Config( + buffer.readFloat(), + buffer.readFloat(), + buffer.readBoolean(), + buffer.readBoolean(), + buffer.readBoolean(), + buffer.readBoolean(), + buffer.readBoolean() + ) } } - override fun write(buffer: FriendlyByteBuf) { - buffer.writeFloat(stepHeight) - buffer.writeFloat(playerEjectTicks) - buffer.writeBoolean(boostUnderwater) - buffer.writeBoolean(onlyForPlayers) + override fun write(buf: FriendlyByteBuf) { + buf.writeFloat(stepHeight) + buf.writeFloat(playerEjectTicks) + buf.writeBoolean(boostUnderwater) + buf.writeBoolean(boostOnBlocks) + buf.writeBoolean(boostOnIce) + buf.writeBoolean(boostOnWater) + buf.writeBoolean(onlyForPlayers) } override fun getType(): PacketType<*> { @@ -46,9 +61,12 @@ import net.minecraft.network.protocol.common.custom.CustomPacketPayload @Serializable data class Config( - var stepHeight: Float = 0.2f, + var stepHeight: Float = 0.35f, var playerEjectTicks: Float = 20f * 10f, var boostUnderwater: Boolean = true, + var boostOnBlocks: Boolean = true, + var boostOnIce: Boolean = true, + var boostOnWater: Boolean = true, var onlyForPlayers: Boolean = true ) : CustomPacketPayload { companion object { @@ -64,6 +82,9 @@ data class Config( buf.readFloat(), buf.readFloat(), buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), + buf.readBoolean(), buf.readBoolean() ) } @@ -75,6 +96,9 @@ data class Config( buf.writeFloat(config.stepHeight) buf.writeFloat(config.playerEjectTicks) buf.writeBoolean(config.boostUnderwater) + buf.writeBoolean(config.boostOnBlocks) + buf.writeBoolean(config.boostOnIce) + buf.writeBoolean(config.boostOnWater) buf.writeBoolean(config.onlyForPlayers) } } @@ -94,11 +118,15 @@ fun getActiveConfig(): Config? { return serverConfig } - -@Suppress("UNUSED_PARAMETER") fun migrate(tree: JsonElement, version: Int?): Config? { + val jsonObject = tree.jsonObject return when (version) { - 1 -> Config() + 1 -> null + 2 -> Config( + playerEjectTicks = jsonObject["playerEjectTicks"]?.jsonPrimitive?.floatOrNull ?: return null, + boostUnderwater = jsonObject["boostUnderwater"]?.jsonPrimitive?.booleanOrNull ?: return null, + onlyForPlayers = jsonObject["onlyForPlayers"]?.jsonPrimitive?.booleanOrNull ?: return null + ) else -> null } } \ No newline at end of file diff --git a/src/main/kotlin/dev/nyon/bbm/config/ConfigScreen.kt b/src/main/kotlin/dev/nyon/bbm/config/ConfigScreen.kt index 1f93583..89509f7 100644 --- a/src/main/kotlin/dev/nyon/bbm/config/ConfigScreen.kt +++ b/src/main/kotlin/dev/nyon/bbm/config/ConfigScreen.kt @@ -1,46 +1,67 @@ package dev.nyon.bbm.config -import dev.isxander.yacl3.api.ConfigCategory -import dev.isxander.yacl3.api.Option -import dev.isxander.yacl3.api.OptionDescription -import dev.isxander.yacl3.api.YetAnotherConfigLib -import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder -import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder +import dev.isxander.yacl3.dsl.* import dev.nyon.konfig.config.saveConfig import net.minecraft.client.gui.screens.Screen -import net.minecraft.network.chat.Component - -fun generateYaclScreen(parent: Screen?): Screen { - val builder = YetAnotherConfigLib.createBuilder() - - builder.title(Component.translatable("menu.bbm.config.title")) - builder.appendCategory() - - builder.save { saveConfig(config) } - val yacl = builder.build() - return yacl.generateScreen(parent) -} - -private fun YetAnotherConfigLib.Builder.appendCategory() = category( - ConfigCategory.createBuilder().name(Component.translatable("menu.bbm.config.category.title")).option( - Option.createBuilder().name(Component.translatable("menu.bbm.config.category.ground_step_height.title")) - .description(OptionDescription.of(Component.translatable("menu.bbm.config.category.ground_step_height.description"))) - .binding(config.stepHeight, { config.stepHeight }, { config.stepHeight = it }) - .controller(FloatFieldControllerBuilder::create).build() - ).option( - Option.createBuilder().name(Component.translatable("menu.bbm.config.category.player_eject_ticks.title")) - .description(OptionDescription.of(Component.translatable("menu.bbm.config.category.player_eject_ticks.description"))) - .binding(config.playerEjectTicks, { config.playerEjectTicks }, { config.playerEjectTicks = it }) - .controller(FloatFieldControllerBuilder::create).build() - ).option( - Option.createBuilder().name(Component.translatable("menu.bbm.config.category.boost_underwater.title")) - .description(OptionDescription.of(Component.translatable("menu.bbm.config.category.boost_underwater.description"))) - .binding(config.boostUnderwater, { config.boostUnderwater }, { config.boostUnderwater = it }) - .controller(TickBoxControllerBuilder::create).build() - ).option( - Option.createBuilder().name(Component.translatable("menu.bbm.config.category.only_for_players.title")) - .description(OptionDescription.of(Component.translatable("menu.bbm.config.category.only_for_players.description"))) - .binding(config.onlyForPlayers, { config.onlyForPlayers }, { config.onlyForPlayers = it }) - .controller(TickBoxControllerBuilder::create).build() - ).build() -) + +fun generateYaclScreen(parent: Screen?): Screen = YetAnotherConfigLib("bbm") { + val general by categories.registering { + val stepHeight by rootOptions.registering { + binding(1f, { config.stepHeight }, { config.stepHeight = it}) + controller = numberField(0f) + descriptionBuilder { + addDefaultText(1) + } + } + + val playerEjectTicks by rootOptions.registering { + binding(0.2f, { config.playerEjectTicks }, { config.playerEjectTicks = it}) + controller = numberField(0f, 10000f) + descriptionBuilder { + addDefaultText(1) + } + } + + val boostUnderwater by rootOptions.registering { + binding(true, { config.boostUnderwater }, { config.boostUnderwater = it }) + controller = tickBox() + descriptionBuilder { + addDefaultText(1) + } + } + + val boostOnBlocks by rootOptions.registering { + binding(true, { config.boostOnBlocks }, { config.boostOnBlocks = it }) + controller = tickBox() + descriptionBuilder { + addDefaultText(1) + } + } + + val boostOnIce by rootOptions.registering { + binding(true, { config.boostOnIce }, { config.boostOnIce = it }) + controller = tickBox() + descriptionBuilder { + addDefaultText(1) + } + } + + val boostOnWater by rootOptions.registering { + binding(true, { config.boostOnWater }, { config.boostOnWater = it }) + controller = tickBox() + descriptionBuilder { + addDefaultText(1) + } + } + + val onlyForPlayers by rootOptions.registering { + binding(true, { config.onlyForPlayers }, { config.onlyForPlayers = it }) + controller = tickBox() + descriptionBuilder { + addDefaultText(1) + } + } + } + + save { saveConfig(config) } +}.generateScreen(parent) \ No newline at end of file diff --git a/src/main/resources/assets/bbm/lang/en_us.json b/src/main/resources/assets/bbm/lang/en_us.json index 674808f..7705603 100644 --- a/src/main/resources/assets/bbm/lang/en_us.json +++ b/src/main/resources/assets/bbm/lang/en_us.json @@ -1,14 +1,18 @@ { - "menu.bbm.config.title": "Better Boat Movement", - "menu.bbm.config.category.title": "General", - "menu.bbm.config.category.ground_step_height.title": "Step height", - "menu.bbm.config.category.ground_step_height.description": "Defines the height on which the boat starts moving the block up.", - "menu.bbm.config.category.player_eject_ticks.title": "Player eject ticks", - "menu.bbm.config.category.player_eject_ticks.description": "Defines the ticks that should pass before ejecting a player, when the player lost control over the boat.", - "menu.bbm.config.category.boost_underwater.title": "Boost underwater", - "menu.bbm.config.category.boost_underwater.description": "Toggles, whether a boat, which is underwater should be boosted upwards with half of the step height.", - "menu.bbm.config.category.wall_hit_cooldown_ticks.title": "Wall hit cooldown ticks", - "menu.bbm.config.category.wall_hit_cooldown_ticks.description": "Defines the ticks that should pass before moving the boat up a block.", - "menu.bbm.config.category.only_for_players.title": "Only for players", - "menu.bbm.config.category.only_for_players.description": "Toggles, whether the boosts configured below should only work if the boat carries a player." + "yacl3.config.bbm.title": "Better Boat Movement", + "yacl3.config.bbm.category.general": "General", + "yacl3.config.bbm.category.general.root.option.stepHeight": "Step height", + "yacl3.config.bbm.category.general.root.option.stepHeight.description": "The amount of blocks you are going to be boosted when triggering a boost.", + "yacl3.config.bbm.category.general.root.option.playerEjectTicks": "Player eject ticks", + "yacl3.config.bbm.category.general.root.option.playerEjectTicks.description": "The ticks the game waits before kicking you out of a boat after the player lost control.", + "yacl3.config.bbm.category.general.root.option.boostUnderwater": "Boost underwater", + "yacl3.config.bbm.category.general.root.option.boostUnderwater.description": "Toggles, whether a boat, which is underwater should be boosted upwards.", + "yacl3.config.bbm.category.general.root.option.boostOnBlocks": "Boost on blocks", + "yacl3.config.bbm.category.general.root.option.boostOnBlocks.description": "Toggles, whether a boat, which is on a block should be boosted upwards when running against an elevation.", + "yacl3.config.bbm.category.general.root.option.boostOnIce": "Boost on ice", + "yacl3.config.bbm.category.general.root.option.boostOnIce.description": "Toggles, whether a boat, which is on an ice block should be boosted upwards when running against an elevation.", + "yacl3.config.bbm.category.general.root.option.boostOnWater": "Boost on water", + "yacl3.config.bbm.category.general.root.option.boostOnWater.description": "Toggles, whether a boat, which is on water should be boosted upwards when floating against an elevation.", + "yacl3.config.bbm.category.general.root.option.onlyForPlayers": "Only for players", + "yacl3.config.bbm.category.general.root.option.onlyForPlayers.description": "Toggles, whether a boat should only be boosted when carrying a player." }