Skip to content
This repository was archived by the owner on Apr 17, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/main/java/dev/o7moon/openboatutils/ClientboundPackets.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public enum ClientboundPackets {
REMOVE_BLOCKS_SLIPPERINESS,
CLEAR_SLIPPERINESS,
MODE_SERIES,
EXCLUSIVE_MODE_SERIES;
EXCLUSIVE_MODE_SERIES,
SET_PER_BLOCK;

public static void registerHandlers(){
ClientPlayNetworking.registerGlobalReceiver(OpenBoatUtils.settingsChannel, (client, handler, buf, responseSender) -> {
Expand Down Expand Up @@ -149,6 +150,13 @@ public static void registerHandlers(){
Modes.setMode(Modes.values()[mode]);
}
return;
case 26:
short setting = buf.readShort();
float value = buf.readFloat();
blocks = buf.readString();
blocksArray = blocks.split(",");
OpenBoatUtils.setBlocksSetting(OpenBoatUtils.PerBlockSettingType.values()[setting], Arrays.asList(blocksArray), value);
return;
}
} catch (Exception E) {
OpenBoatUtils.LOG.error("Error when handling clientbound openboatutils packet: ");
Expand Down
25 changes: 24 additions & 1 deletion src/main/java/dev/o7moon/openboatutils/Modes.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.o7moon.openboatutils;

import java.util.ArrayList;

public enum Modes {
BROKEN_SLIME_RALLY,//0
BROKEN_SLIME_RALLY_BLUE,//1
Expand All @@ -16,7 +18,12 @@ public enum Modes {
BA_BLUE_NOFD,//12
PARKOUR_BLUE,//13
BA,//14
BA_BLUE;//15
BA_BLUE,//15
JUMP_BLOCKS,//16
BOOSTER_BLOCKS,//17
DEFAULT_ICE,//18
DEFAULT_BLUE_ICE,//19
;

public static void setMode(Modes mode) {
switch (mode){
Expand Down Expand Up @@ -132,6 +139,22 @@ public static void setMode(Modes mode) {
OpenBoatUtils.setWaterElevation(true);
OpenBoatUtils.breakSlimePlease();
return;
case JUMP_BLOCKS:
OpenBoatUtils.setBlockSetting(OpenBoatUtils.PerBlockSettingType.jumpForce, "minecraft:orange_concrete", 0.36f);// ~1 block
OpenBoatUtils.setBlockSetting(OpenBoatUtils.PerBlockSettingType.jumpForce, "minecraft:black_concrete", 0.0f);// no jump
OpenBoatUtils.setBlockSetting(OpenBoatUtils.PerBlockSettingType.jumpForce, "minecraft:green_concrete", 0.5f);// ~2-3 block
OpenBoatUtils.setBlockSetting(OpenBoatUtils.PerBlockSettingType.jumpForce, "minecraft:yellow_concrete", 0.18f);// ~0.5 blocks
return;
case BOOSTER_BLOCKS:
OpenBoatUtils.setBlockSetting(OpenBoatUtils.PerBlockSettingType.forwardsAccel, "minecraft:magenta_glazed_terracotta", 0.08f);// double accel
OpenBoatUtils.setBlockSetting(OpenBoatUtils.PerBlockSettingType.yawAccel, "minecraft:light_gray_glazed_terracotta", 0.08f);// double yaw accel
return;
case DEFAULT_ICE:
OpenBoatUtils.setAllBlocksSlipperiness(0.98f);
return;
case DEFAULT_BLUE_ICE:
OpenBoatUtils.setAllBlocksSlipperiness(0.985f);
return;
}
}
}
112 changes: 111 additions & 1 deletion src/main/java/dev/o7moon/openboatutils/OpenBoatUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,26 @@
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.LilyPadBlock;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static net.minecraft.server.command.CommandManager.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -68,6 +79,16 @@ public void onInitialize() {
put("minecraft:frosted_ice",0.98f);
}};*/

enum PerBlockSettingType {
jumpForce,
forwardsAccel,
backwardsAccel,
yawAccel,
turnForwardsAccel,
}

public static HashMap<Integer, HashMap<String, Float>> perBlockSettings;

public static HashMap<String, Float> getVanillaSlipperinessMap() {
if (vanillaSlipperinessMap == null) {
vanillaSlipperinessMap = new HashMap<>();
Expand All @@ -80,6 +101,56 @@ public static HashMap<String, Float> getVanillaSlipperinessMap() {
return vanillaSlipperinessMap;
}

public static boolean settingHasPerBlock(PerBlockSettingType setting) {
return perBlockSettings != null && perBlockSettings.containsKey(setting.ordinal());
}

public static float getNearbySetting(BoatEntity instance, PerBlockSettingType setting) {
Box box = instance.getBoundingBox();
Box box2 = new Box(box.minX, box.minY - 0.001, box.minZ, box.maxX, box.minY, box.maxZ);
int i = MathHelper.floor(box2.minX) - 1;
int j = MathHelper.ceil(box2.maxX) + 1;
int k = MathHelper.floor(box2.minY) - 1;
int l = MathHelper.ceil(box2.maxY) + 1;
int m = MathHelper.floor(box2.minZ) - 1;
int n = MathHelper.ceil(box2.maxZ) + 1;
VoxelShape voxelShape = VoxelShapes.cuboid(box2);
float f = 0.0f;
int o = 0;
BlockPos.Mutable mutable = new BlockPos.Mutable();
for (int p = i; p < j; ++p) {
for (int q = m; q < n; ++q) {
int r = (p == i || p == j - 1 ? 1 : 0) + (q == m || q == n - 1 ? 1 : 0);
if (r == 2) continue;
for (int s = k; s < l; ++s) {
if (r > 0 && (s == k || s == l - 1)) continue;
mutable.set(p, s, q);
BlockState blockState = instance.getWorld().getBlockState(mutable);
if (blockState.getBlock() instanceof LilyPadBlock || !VoxelShapes.matchesAnywhere(blockState.getCollisionShape(instance.getWorld(), mutable).offset(p, s, q), voxelShape, BooleanBiFunction.AND)) continue;
f += getPerBlockForBlock(setting, Registries.BLOCK.getId(blockState.getBlock()).toString());
++o;
}
}
}
if (o == 0) return getPerBlockForBlock(setting, "minecraft:air");
return f / (float)o;
}

public static float getPerBlockForBlock(PerBlockSettingType setting, String blockid){
return settingHasPerBlock(setting) && perBlockSettings.get(setting.ordinal()).containsKey(blockid) ? perBlockSettings.get(setting.ordinal()).get(blockid): defaultPerBlock(setting);
}

public static float defaultPerBlock(PerBlockSettingType setting) {
switch (setting) {
case yawAccel -> {return yawAcceleration;}
case jumpForce -> {return jumpForce;}
case forwardsAccel -> {return forwardsAcceleration;}
case backwardsAccel -> {return backwardsAcceleration;}
case turnForwardsAccel -> {return turningForwardsAcceleration;}
};
return 0;// unreachable but java compiler hates me (personally)
}

public static HashMap<String, Float> getSlipperinessMap() {
if (slipperinessMap == null) {
slipperinessMap = new HashMap<>(getVanillaSlipperinessMap());
Expand Down Expand Up @@ -113,7 +184,7 @@ public static void resetSettings(){
put("minecraft:blue_ice",0.989f);
put("minecraft:frosted_ice",0.98f);
}};*/

perBlockSettings = new HashMap();
}

public static void setStepSize(float stepsize){
Expand Down Expand Up @@ -248,4 +319,43 @@ public static void clearSlipperinessMap() {
enabled = true;
slipperinessMap = new HashMap<>();
}

public static float GetJumpForce(BoatEntity boat) {
if (!settingHasPerBlock(PerBlockSettingType.jumpForce)) return jumpForce;
else return getNearbySetting(boat, PerBlockSettingType.jumpForce);
}

public static float GetYawAccel(BoatEntity boat) {
if (!settingHasPerBlock(PerBlockSettingType.yawAccel)) return yawAcceleration;
else return getNearbySetting(boat, PerBlockSettingType.yawAccel);
}

public static float GetForwardAccel(BoatEntity boat) {
if (!settingHasPerBlock(PerBlockSettingType.forwardsAccel)) return forwardsAcceleration;
else return getNearbySetting(boat, PerBlockSettingType.forwardsAccel);
}

public static float GetBackwardAccel(BoatEntity boat) {
if (!settingHasPerBlock(PerBlockSettingType.backwardsAccel)) return backwardsAcceleration;
else return getNearbySetting(boat, PerBlockSettingType.backwardsAccel);
}

public static float GetTurnForwardAccel(BoatEntity boat) {
if (!settingHasPerBlock(PerBlockSettingType.turnForwardsAccel)) return turningForwardsAcceleration;
else return getNearbySetting(boat, PerBlockSettingType.turnForwardsAccel);
}

public static void setBlocksSetting(PerBlockSettingType setting, List<String> blocks, float value) {
enabled = true;
if (!settingHasPerBlock(setting)) perBlockSettings.put(setting.ordinal(), new HashMap());
HashMap<String, Float> map = perBlockSettings.get(setting.ordinal());
for (String block : blocks) {
map.put(block, value);
}
}
public static void setBlockSetting(PerBlockSettingType setting, String block, float value) {
ArrayList<String> blocks = new ArrayList<>();
blocks.add(block);
setBlocksSetting(setting, blocks, value);
}
}
27 changes: 27 additions & 0 deletions src/main/java/dev/o7moon/openboatutils/SingleplayerCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,33 @@ public static void registerCommands(){
return 1;
}))
);

dispatcher.register(
literal("setblocksetting").then(argument("setting", StringArgumentType.string()).then(argument("value", FloatArgumentType.floatArg()).then(argument("blocks", StringArgumentType.greedyString()).executes(ctx -> {
ServerPlayerEntity player = ctx.getSource().getPlayer();
if (player == null) return 0;
OpenBoatUtils.PerBlockSettingType setting;
try {
setting = OpenBoatUtils.PerBlockSettingType.valueOf(StringArgumentType.getString(ctx, "setting"));
} catch (Exception e) {
String valid_settings = "";
for (OpenBoatUtils.PerBlockSettingType s : OpenBoatUtils.PerBlockSettingType.values()) {
valid_settings += s.toString() + " ";
}
ctx.getSource().sendMessage(Text.literal("Invalid setting! Valid settings are: "+valid_settings));
return 0;
}
float value = FloatArgumentType.getFloat(ctx, "value");
String blocks = StringArgumentType.getString(ctx, "blocks");
PacketByteBuf packet = PacketByteBufs.create();
packet.writeShort(ClientboundPackets.SET_PER_BLOCK.ordinal());
packet.writeShort(setting.ordinal());
packet.writeFloat(value);
packet.writeString(blocks);
ServerPlayNetworking.send(player, OpenBoatUtils.settingsChannel, packet);
return 1;
}))))
);
});
}
}
14 changes: 8 additions & 6 deletions src/main/java/dev/o7moon/openboatutils/mixin/BoatMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ void oncePerTick(BoatEntity instance, BoatEntity.Location loc, MinecraftClient m
OpenBoatUtils.coyoteTimer--;
}

if (OpenBoatUtils.coyoteTimer >= 0 && OpenBoatUtils.jumpForce > 0f && minecraft.options.jumpKey.isPressed()) {
float jumpForce = OpenBoatUtils.GetJumpForce((BoatEntity)(Object)this);

if (OpenBoatUtils.coyoteTimer >= 0 && jumpForce > 0f && minecraft.options.jumpKey.isPressed()) {
Vec3d velocity = instance.getVelocity();
instance.setVelocity(velocity.x, OpenBoatUtils.jumpForce, velocity.z);
instance.setVelocity(velocity.x, jumpForce, velocity.z);
OpenBoatUtils.coyoteTimer = -1;// cant jump again until grounded
}
}
Expand Down Expand Up @@ -143,26 +145,26 @@ private void redirectYawVelocityIncrement(BoatEntity boat, float yawVelocity) {
float original_delta = yawVelocity - this.yawVelocity;
// sign isn't needed here because the vanilla acceleration is exactly 1,
// but I suppose this helps if mojang ever decides to change that value for some reason
this.yawVelocity += MathHelper.sign(original_delta) * OpenBoatUtils.yawAcceleration;
this.yawVelocity += MathHelper.sign(original_delta) * OpenBoatUtils.GetYawAccel((BoatEntity)(Object)this);
}

// a whole lotta modifyconstants because mojang put the acceleration values in literals
@ModifyConstant(method = "updatePaddles", constant = @Constant(floatValue = 0.04f, ordinal = 0))
private float forwardsAccel(float original) {
if (!OpenBoatUtils.enabled) return original;
return OpenBoatUtils.forwardsAcceleration;
return OpenBoatUtils.GetForwardAccel((BoatEntity)(Object)this);
}

@ModifyConstant(method = "updatePaddles", constant = @Constant(floatValue = 0.005f, ordinal = 0))
private float turnAccel(float original) {
if (!OpenBoatUtils.enabled) return original;
return OpenBoatUtils.turningForwardsAcceleration;
return OpenBoatUtils.GetTurnForwardAccel((BoatEntity)(Object)this);
}

@ModifyConstant(method = "updatePaddles", constant = @Constant(floatValue = 0.005f, ordinal = 1))
private float backwardsAccel(float original) {
if (!OpenBoatUtils.enabled) return original;
return OpenBoatUtils.backwardsAcceleration;
return OpenBoatUtils.GetBackwardAccel((BoatEntity)(Object)this);
}

@Redirect(method = "updatePaddles", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/vehicle/BoatEntity;pressingForward:Z", opcode = Opcodes.GETFIELD, ordinal = 0))
Expand Down