Skip to content

Commit

Permalink
Use AABB methods for raycasting
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexProgrammerDE committed Nov 5, 2024
1 parent 299e12f commit cb36950
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 325 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
*/
package com.soulfiremc.server.data;

import com.soulfiremc.server.protocol.bot.movement.AABB;
import com.soulfiremc.server.util.SFHelpers;
import com.soulfiremc.server.util.mcstructs.AABB;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.cloudburstmc.math.vector.Vector3i;
Expand All @@ -27,7 +27,7 @@
import java.util.List;

@SuppressWarnings("unused")
public record BlockShapeGroup(int id, List<BlockShape> blockShapes, double highestY) {
public record BlockShapeGroup(int id, List<AABB> blockShapes, double highestY) {
public static final Int2ObjectMap<BlockShapeGroup> FROM_ID = new Int2ObjectOpenHashMap<>();
public static final BlockShapeGroup EMPTY;

Expand All @@ -39,14 +39,14 @@ public record BlockShapeGroup(int id, List<BlockShape> blockShapes, double highe
var parts = line.split("\\|");

var id = Integer.parseInt(parts[0]);
var blockShapes = new ArrayList<BlockShape>();
var blockShapes = new ArrayList<AABB>();

if (parts.length > 1) {
for (var i = 1; i < parts.length; i++) {
var part = parts[i];
var subParts = part.split(",");
var shape =
new BlockShape(
new AABB(
Double.parseDouble(subParts[0]),
Double.parseDouble(subParts[1]),
Double.parseDouble(subParts[2]),
Expand All @@ -62,7 +62,7 @@ public record BlockShapeGroup(int id, List<BlockShape> blockShapes, double highe
new BlockShapeGroup(
id,
blockShapes,
blockShapes.stream().mapToDouble(BlockShape::maxY).max().orElse(0)));
blockShapes.stream().mapToDouble(a -> a.maxY).max().orElse(0)));
});

EMPTY = getById(0);
Expand All @@ -77,7 +77,7 @@ public List<AABB> getCollisionBoxes(Vector3i block, BlockType blockType) {
for (var shape : blockShapes) {
var shapeBB =
new AABB(
shape.minX(), shape.minY(), shape.minZ(), shape.maxX(), shape.maxY(), shape.maxZ());
shape.minX, shape.minY, shape.minZ, shape.maxX, shape.maxY, shape.maxZ);

// Apply random offset if needed
shapeBB = shapeBB.move(OffsetHelper.getOffsetForBlock(blockType, block));
Expand All @@ -96,7 +96,7 @@ public boolean isFullBlock() {
return false;
}

return blockShapes.getFirst().isFullBlock();
return blockShapes.getFirst().fullBlock();
}

public boolean hasNoCollisions() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
package com.soulfiremc.server.data;

import com.soulfiremc.server.protocol.bot.movement.AABB;
import com.soulfiremc.server.util.mcstructs.AABB;
import net.kyori.adventure.key.Key;
import org.cloudburstmc.math.vector.Vector3i;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,10 @@ public void tick(BotConnection connection) {
var level = dataManager.currentLevel();
if (!didLook) {
didLook = true;
var previousYRot = clientEntity.yRot();
var previousXRot = clientEntity.xRot();
clientEntity.lookAt(
RotationOrigin.EYES,
blockBreakSideHint.getMiddleOfFace(blockPosition));
if (previousXRot != clientEntity.xRot() || previousYRot != clientEntity.yRot()) {
clientEntity.sendRot();
}
clientEntity.sendPositionChanges();
}

if (!putInHand) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@
*/
package com.soulfiremc.server.protocol.bot;

import com.soulfiremc.server.data.BlockState;
import com.soulfiremc.server.data.AttributeType;
import com.soulfiremc.server.pathfinding.SFVec3i;
import com.soulfiremc.server.pathfinding.graph.BlockFace;
import com.soulfiremc.server.protocol.BotConnection;
import com.soulfiremc.server.protocol.bot.movement.AABB;
import com.soulfiremc.server.util.mcstructs.AABB;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f;
import lombok.extern.slf4j.Slf4j;
import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.mcprotocollib.protocol.data.game.entity.RotationOrigin;
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
Expand All @@ -37,13 +36,11 @@
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;

import java.util.ArrayList;
import java.util.Optional;

/**
* Manages mostly block and interaction related stuff that requires to keep track of sequence
* numbers.
*/
@Slf4j
@Data
@RequiredArgsConstructor
public class BotActionManager {
Expand All @@ -53,38 +50,6 @@ public class BotActionManager {
private final BotConnection connection;
private int sequenceNumber = 0;

private static Optional<Vector3f> rayCastToBlock(
BlockState blockState, Vector3d eyePosition, Vector3d headRotation, Vector3i targetBlock) {
var intersections = new ArrayList<Vector3f>();

for (var shape : blockState.getCollisionBoxes(targetBlock)) {
shape
.getIntersection(eyePosition, headRotation)
.map(Vector3d::toFloat)
.ifPresent(intersections::add);
}

if (intersections.isEmpty()) {
return Optional.empty();
}

Vector3f closestIntersection = null;
var closestDistance = Double.MAX_VALUE;

for (var intersection : intersections) {
double distance =
intersection.distance(eyePosition.getX(), eyePosition.getY(), eyePosition.getZ());

if (distance < closestDistance) {
closestIntersection = intersection;
closestDistance = distance;
}
}

assert closestIntersection != null;
return Optional.of(closestIntersection);
}

public void incrementSequenceNumber() {
sequenceNumber++;
}
Expand All @@ -107,36 +72,37 @@ public void placeBlock(Hand hand, Vector3i againstBlock, BlockFace againstFace)

var againstPlacePosition = againstFace.getMiddleOfFace(SFVec3i.fromInt(againstBlock));

var previousYRot = clientEntity.yRot();
var previousXRot = clientEntity.xRot();
clientEntity.lookAt(RotationOrigin.EYES, againstPlacePosition);
if (previousXRot != clientEntity.xRot() || previousYRot != clientEntity.yRot()) {
clientEntity.sendRot();
}

var rayCast =
rayCastToBlock(
level.getBlockState(againstBlock),
eyePosition,
clientEntity.rotationVector(),
againstBlock);
if (rayCast.isEmpty()) {
clientEntity.sendPositionChanges();

var viewDirection = clientEntity.getViewVector();
var blockInteractionRange = clientEntity.attributeValue(AttributeType.BLOCK_INTERACTION_RANGE);
var endPos = eyePosition.add(
viewDirection.getX() * blockInteractionRange,
viewDirection.getY() * blockInteractionRange,
viewDirection.getZ() * blockInteractionRange
);
var againstState = level.getBlockState(againstBlock);
var hitResult = AABB.clip(againstState.getCollisionBoxes(againstBlock), eyePosition, endPos, againstBlock);
if (hitResult == null) {
log.warn("Failed to place block at {} against {}", againstBlock, againstFace);
return;
}

var rayCastPosition = rayCast.get().sub(againstBlock.toFloat());
var insideBlock = !level.getCollisionBoxes(new AABB(eyePosition, eyePosition)).isEmpty();

var blockPlacePosition = hitResult.getVector3i();
var blockPlaceLocation = hitResult.location();
connection.sendPacket(
new ServerboundUseItemOnPacket(
againstBlock,
hitResult.getVector3i(),
againstFace.toDirection(),
hand,
rayCastPosition.getX(),
rayCastPosition.getY(),
rayCastPosition.getZ(),
(float) (blockPlaceLocation.getX() - (double) blockPlacePosition.getX()),
(float) (blockPlaceLocation.getY() - (double) blockPlacePosition.getY()),
(float) (blockPlaceLocation.getZ() - (double) blockPlacePosition.getZ()),
insideBlock,
false, // TODO: Implement check for hitting world border
false,
sequenceNumber));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
import com.soulfiremc.server.data.EntityType;
import com.soulfiremc.server.protocol.BotConnection;
import com.soulfiremc.server.protocol.SFProtocolConstants;
import com.soulfiremc.server.protocol.bot.movement.AABB;
import com.soulfiremc.server.protocol.bot.state.entity.Entity;
import com.soulfiremc.server.util.mcstructs.AABB;
import com.soulfiremc.server.util.structs.Segment;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import com.soulfiremc.server.settings.lib.SettingsSource;
import com.soulfiremc.server.util.EntityMovement;
import com.soulfiremc.server.util.SFHelpers;
import com.soulfiremc.server.util.VectorHelper;
import com.soulfiremc.server.util.structs.TickTimer;
import com.soulfiremc.server.viaversion.SFVersionConstants;
import io.netty.buffer.Unpooled;
Expand Down Expand Up @@ -70,7 +69,6 @@
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PositionElement;
import org.geysermc.mcprotocollib.protocol.data.game.level.notify.LimitedCraftingValue;
import org.geysermc.mcprotocollib.protocol.data.game.level.notify.RainStrengthValue;
import org.geysermc.mcprotocollib.protocol.data.game.level.notify.RespawnScreenValue;
Expand Down Expand Up @@ -340,7 +338,7 @@ public void onPosition(ClientboundPlayerPositionPacket packet) {
}

@EventHandler
public void onROtation(ClientboundPlayerRotationPacket packet) {
public void onRotation(ClientboundPlayerRotationPacket packet) {
clientEntity.setRotation(
packet.getYRot(),
packet.getXRot()
Expand Down
Loading

0 comments on commit cb36950

Please sign in to comment.