Skip to content

Commit

Permalink
Add Smart Centering (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeF53 committed Jul 13, 2023
1 parent a5a9aa9 commit 2d26d53
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 22 deletions.
94 changes: 72 additions & 22 deletions src/main/java/net/cardinalboats/TurnPriming.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.cardinalboats.config.ModConfig;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.block.AirBlock;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.option.KeyBinding;
Expand All @@ -12,8 +13,17 @@
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import static net.minecraft.util.math.Direction.NORTH;
import static net.minecraft.util.math.Direction.SOUTH;
import static net.minecraft.util.math.Direction.EAST;
import static net.minecraft.util.math.Direction.WEST;

public class TurnPriming {
public static final KeyBinding lQueueKey = new KeyBinding(
Expand All @@ -29,10 +39,18 @@ public class TurnPriming {
"category.cardinalboats.key_category_title"
);

public static final KeyBinding smartCenterKey = new KeyBinding(
"key.cardinalboats.smartCenter",
InputUtil.Type.KEYSYM,
InputUtil.GLFW_KEY_BACKSLASH,
"category.cardinalboats.key_category_title"
);

// Run by fabric initializer
public static void init() {
KeyBindingHelper.registerKeyBinding(lQueueKey);
KeyBindingHelper.registerKeyBinding(rQueueKey);
KeyBindingHelper.registerKeyBinding(smartCenterKey);

ClientTickEvents.END_CLIENT_TICK.register(TurnPriming::tick);
}
Expand All @@ -56,20 +74,22 @@ public static void tick(MinecraftClient minecraft) {
lTurnPrimed = false;
}

if (ModConfig.getInstance().alwaysSmartCenter && boat.getYaw() % 90 == 0) { smartCenter(boat); }
while (smartCenterKey.wasPressed()) { smartCenter(boat); }

if (lTurnPrimed && shouldTurn(boat, minecraft.world, true)) {
Util.rotateBoat(boat, Util.roundYRot(boat.getYaw() - 90, 90), ModConfig.getInstance().maintainVelocityOnTurns);
lTurnPrimed = false;
Util.ClientChatLog(player, Text.translatable("info.cardinalboats.left_turn_complete").getString());
if (ModConfig.getInstance().smartCenterPrimedTurn) smartCenter(boat);
} else if (rTurnPrimed && shouldTurn(boat, minecraft.world, false)) {
Util.rotateBoat(boat, Util.roundYRot(boat.getYaw() + 90, 90), ModConfig.getInstance().maintainVelocityOnTurns);
rTurnPrimed = false;
Util.ClientChatLog(player, Text.translatable("info.cardinalboats.right_turn_complete").getString());
if (ModConfig.getInstance().smartCenterPrimedTurn) smartCenter(boat);
}
} else {
while (lQueueKey.wasPressed()) {
}
while (rQueueKey.wasPressed()) {
}
while (lQueueKey.wasPressed() || rQueueKey.wasPressed() || smartCenterKey.wasPressed()) {}
}
} else {
// if we aren't in the boat anymore, we don't care
Expand All @@ -80,30 +100,27 @@ public static void tick(MinecraftClient minecraft) {
rTurnPrimed = false;

// not in a boat, don't care about any presses these buttons get right now
while (lQueueKey.wasPressed()) {
}
while (rQueueKey.wasPressed()) {
}
while (lQueueKey.wasPressed() || rQueueKey.wasPressed() || smartCenterKey.wasPressed()) {}
}
}

private static final Map<Direction, int[][]> toScanMapLeft = new HashMap<>() {{
put(Direction.SOUTH, new int[][]{{ 3, 0}, { 3,-1}, { 3,-2}});
put(Direction.NORTH, new int[][]{{-3, 0}, {-3, 1}, {-3, 2}});
put(Direction.EAST, new int[][]{{ 0,-3}, {-1,-3}, {-2,-3}});
put(Direction.WEST, new int[][]{{ 0, 3}, { 1, 3}, { 2, 3}});
put(SOUTH, new int[][]{{ 3, 0}, { 3,-1}, { 3,-2}});
put(NORTH, new int[][]{{-3, 0}, {-3, 1}, {-3, 2}});
put(EAST, new int[][]{{ 0,-3}, {-1,-3}, {-2,-3}});
put(WEST, new int[][]{{ 0, 3}, { 1, 3}, { 2, 3}});
}};
private static final Map<Direction, int[][]> toScanMapRight = new HashMap<>() {{
put(Direction.SOUTH, new int[][]{{-3, 0}, {-3,-1}, {-3,-2}});
put(Direction.NORTH, new int[][]{{ 3, 0}, { 3, 1}, { 3, 2}});
put(Direction.EAST, new int[][]{{ 0, 3}, {-1, 3}, {-2, 3}});
put(Direction.WEST, new int[][]{{ 0,-3}, { 1,-3}, { 2,-3}});
put(SOUTH, new int[][]{{-3, 0}, {-3,-1}, {-3,-2}});
put(NORTH, new int[][]{{ 3, 0}, { 3, 1}, { 3, 2}});
put(EAST, new int[][]{{ 0, 3}, {-1, 3}, {-2, 3}});
put(WEST, new int[][]{{ 0,-3}, { 1,-3}, { 2,-3}});
}};
private static final Map<Direction, int[][]> snapBlockMap = new HashMap<>() {{
put(Direction.SOUTH, new int[][]{{ 0, 0}, { 0,-1}, { 0,-2}});
put(Direction.NORTH, new int[][]{{ 0, 0}, { 0, 1}, { 0, 2}});
put(Direction.EAST, new int[][]{{ 0, 0}, {-1, 0}, {-2, 0}});
put(Direction.WEST, new int[][]{{ 0, 0}, { 1, 0}, { 2, 0}});
put(SOUTH, new int[][]{{ 0, 0}, { 0,-1}, { 0,-2}});
put(NORTH, new int[][]{{ 0, 0}, { 0, 1}, { 0, 2}});
put(EAST, new int[][]{{ 0, 0}, {-1, 0}, {-2, 0}});
put(WEST, new int[][]{{ 0, 0}, { 1, 0}, { 2, 0}});
}};

public static boolean shouldTurn(BoatEntity boat, ClientWorld level, boolean left) {
Expand All @@ -122,7 +139,6 @@ public static boolean shouldTurn(BoatEntity boat, ClientWorld level, boolean lef
} else {
map = toScanMapRight.get(direction);
}

for (int i = 0; i < map.length; i++) {
BlockPos testBlockPos = new BlockPos(rootX + map[i][0], rootY, rootZ + map[i][1]);
if (Util.isIce(level.getBlockState(testBlockPos))) {
Expand All @@ -134,4 +150,38 @@ public static boolean shouldTurn(BoatEntity boat, ClientWorld level, boolean lef

return false;
}
}

public static void smartCenter(BoatEntity boat) {
World world = boat.getWorld();
Direction direction = boat.getHorizontalFacing();
int rootX = boat.getBlockX();
int rootY = boat.getBlockY();
int rootZ = boat.getBlockZ();

int scanAhead = ModConfig.getInstance().smartCenterLookAhead;
if (direction == NORTH || direction == SOUTH) {
int startZ = direction == NORTH ? -scanAhead : -1;
int endZ = direction == NORTH ? 1 : scanAhead;
double nudgeX = calculateNudge(world, startZ, endZ, z -> new BlockPos(rootX - 1, rootY, rootZ + z), z -> new BlockPos(rootX + 1, rootY, rootZ + z));
boat.setPosition(rootX + 0.5 + nudgeX, boat.getY(), boat.getZ());
} else {
int startX = direction == WEST ? -scanAhead : -1;
int endX = direction == WEST ? 1 : scanAhead;
double nudgeZ = calculateNudge(world, startX, endX, x -> new BlockPos(rootX + x, rootY, rootZ - 1), x -> new BlockPos(rootX + x, rootY, rootZ + 1));
boat.setPosition(boat.getX(), boat.getY(), rootZ + 0.5 + nudgeZ);
}
}

private static double calculateNudge(World world, int start, int end, Function<Integer, BlockPos> leftBlockPosFunc, Function<Integer, BlockPos> rightBlockPosFunc) {
int nudge = 0;
for (int i = start; i <= end; i++) {
BlockPos leftBlockPos = leftBlockPosFunc.apply(i);
BlockPos rightBlockPos = rightBlockPosFunc.apply(i);
if (!(world.getBlockState(leftBlockPos).getBlock() instanceof AirBlock))
nudge += 1;
if (!(world.getBlockState(rightBlockPos).getBlock() instanceof AirBlock))
nudge -= 1;
}
return MathHelper.clamp(nudge, -0.2, 0.2);
}
}
10 changes: 10 additions & 0 deletions src/main/java/net/cardinalboats/config/ModConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ public class ModConfig implements ConfigData {
@ConfigEntry.Gui.Tooltip
public boolean moveWhileChatting = true;

@ConfigEntry.Gui.Tooltip
public boolean alwaysSmartCenter = false;

@ConfigEntry.Gui.Tooltip
@ConfigEntry.BoundedDiscrete(min = 1, max = 10)
public int smartCenterLookAhead = 5;

@ConfigEntry.Gui.Tooltip
public boolean smartCenterPrimedTurn = true;

public static void init() {
AutoConfig.register(ModConfig.class, Toml4jConfigSerializer::new);
}
Expand Down
10 changes: 10 additions & 0 deletions src/main/resources/assets/cardinalboats/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

"key.cardinalboats.snapManual" : "Re-Snap",
"key.cardinalboats.snap180" : "Instant Reverse",
"key.cardinalboats.smartCenter" : "Smart Center",

"key.cardinalboats.prime_left": "Prime Left Turn",
"key.cardinalboats.prime_right": "Prime Right Turn",
Expand All @@ -26,6 +27,15 @@
"text.autoconfig.CardinalBoat.option.eightWaySnapKey.boolean.true" : "§bEight-Way",
"text.autoconfig.CardinalBoat.option.eightWaySnapKey.boolean.false" : "§6Four-Way",

"text.autoconfig.CardinalBoat.option.alwaysSmartCenter" : "Always Smart Center",
"text.autoconfig.CardinalBoat.option.alwaysSmartCenter.@Tooltip" : "Runs smart center all the time when boat is perfectly cardinally aligned",

"text.autoconfig.CardinalBoat.option.smartCenterLookAhead" : "Smart Center Lookahead",
"text.autoconfig.CardinalBoat.option.smartCenterLookAhead.@Tooltip" : "Number of blocks ahead of you that smart center scans for walls.",

"text.autoconfig.CardinalBoat.option.smartCenterPrimedTurn" : "Smart Center on Primed Turns",
"text.autoconfig.CardinalBoat.option.smartCenterPrimedTurn.@Tooltip" : "Boat will automatically smart center itself after taking a primed turn",

"text.autoconfig.CardinalBoat.option.moveWhileChatting" : "Keep Moving While Chatting",
"text.autoconfig.CardinalBoat.option.moveWhileChatting.@Tooltip" : "Allows you to chat while driving a boat.\nIf you open the chat while moving forward, it keeps moving forward for you.\n§mDon't text and drive.",

Expand Down

0 comments on commit 2d26d53

Please sign in to comment.