Compy's Blog
589 words
3 minutes
[Minecraft] Raycast 구현
2025-02-15

또 정말 오랜만에 돌아옵니다. 요즘 Mojo로 작은 프로젝트하고 있어서 좀 뜸하긴 한데요. 일단 오늘은 간단하게 raycasting을 구현해보려고 합니다.

먼저 Event를 만들어주고, 그 이후에 발생 처리를 해보겠습니다.

이번 구현은 고정된 곳에서 플레이어가 지나가는지 체크를 하는 로직을 좀 구현하고, 딱히 할 대상이 없으니 현재 같은 월드에 있는 모든 엔티티에 대해서 다 처리를 해서 확인을 해보겠습니다.

public class RaycastEvent extends Event {
    private static final HandlerList handlers = new HandlerList();

    private final Player player;
    private final Entity entity;

    private final Location sourceLocation;
    private final Location targetLocation;


    public RaycastEvent(Player player, Entity entity, Location sourceLocation, Location targetLocation){
        this.player = player;
        this.entity = entity;
        this.sourceLocation = sourceLocation;
        this.targetLocation = targetLocation;
    }

    public Player getPlayer() {
        return player;
    }

    public Entity getEntity() {
        return entity;
    }

    public Location getSourceLocation() {
        return sourceLocation;
    }

    public Location getTargetLocation() {
        return targetLocation;
    }

    @Override
    public HandlerList getHandlers() {
        return handlers;
    }
    public static HandlerList getHandlerList(){
        return handlers;
    }
}

뭐 여기까지는 너무 그냥 당연하게 작성한 것이라 넘어가구요!

public class RaycatManager {

    public RaycatManager(){
        register();
    }

    public void register(){
        ProtocolManager manager = ProtocolLibrary.getProtocolManager();

        manager.addPacketListener(new PacketAdapter(BlogPlugin.plugin,
                ListenerPriority.HIGH,
                PacketType.Play.Client.POSITION,
                PacketType.Play.Client.POSITION_LOOK
                ) {



            @Override
            public void onPacketReceiving(PacketEvent event) {
                Player player = event.getPlayer();
                PacketContainer container = event.getPacket();

                double x = container.getDoubles().read(0);
                double y = container.getDoubles().read(1);
                double z = container.getDoubles().read(2);

                tryRaycast(new Location(player.getWorld(), x, y, z), player);
            }
        });
    }


    private void tryRaycast(Location playerLoc, Player player){
        if(playerLoc.getWorld() == null) return;


        Bukkit.getScheduler().runTask(BlogPlugin.plugin, ()->
        {
            playerLoc.getWorld().getEntities().stream().filter(entity ->
                    entity instanceof LivingEntity && !entity.equals(player)
            ).forEach(entity -> raycast(playerLoc, player, entity));
        });
    }
    private void raycast(Location loc, Player player, Entity entity){
        if(loc.getWorld() == null) return;

        Location entityLoc = entity.getLocation();

        double distance = loc.distanceSquared(entityLoc);
        if(distance <= 5*5){ 
            Vector dir = entityLoc.getDirection();
            Vector toPlayer = loc.toVector().subtract(entityLoc.toVector()).normalize();

            double angle = Math.toDegrees(dir.angle(toPlayer));

            if(angle <= 45f){


                if(isBlocked(entityLoc, loc)) return;

                Bukkit.getScheduler().runTask(BlogPlugin.plugin, ()-> {
                    RaycastEvent event = new RaycastEvent(player, entity, entityLoc, player.getLocation());
                    Bukkit.getPluginManager().callEvent(event);
                });
            }
        }


    }

    private boolean isBlocked(Location from, Location to){
        from.setY(from.getY() + 1.5f);
        return from.getWorld().rayTraceBlocks(from, to.toVector().subtract(from.toVector()), to.distance(from)) != null;
    }

}

여기까지 이렇게 raycast를 구현할 수 있어요. 이것도 게임을 공부하다 보면 당연히 보이는 것들이 있을 거구요!
from.setY(from.getY() + 1.5f); 여기는 좀 중요한데… 이게 발가락이 from이 되면서 시야가 너무 낮아지면서 블록이 있는 것으로 알더라구요?! 그래서 이렇게 올려준겁니다.


구현 영상


이제 곧 리버싱, 암호학, 인공지능 이렇게 올라가긴 할겁니당

다들 너무 수고하셨습니다.

[Minecraft] Raycast 구현
https://compy07.github.io/Blog/posts/development/bukkit/packet/raycasting/
Author
뒹굴뒹굴 이정훈 공부방
Published at
2025-02-15