Jump to content

[1.9.4] Ray casting through a bounding box


OhiraKyou

Recommended Posts

I have a turret that ray casts from its center to its target. I could use some math to push the ray's origin down the barrel's forward vector to prevent it from hitting its own bounding box. However, I do wonder if there is a more elegant solution that allows a cast to simply ignore a bounding box. That would decouple the ray start position from the bounding box.

 

How would you deal or how have you dealt with this?

Link to comment
Share on other sites

When ray tracing in MC we are talking about MovingObjectPosition. MOP can be Block or Entity. The beam (ray) will go until reaches max distance or collides with something - you can simply check if collided box is equal to source (box of "shooter") and if so - pass it.

 

This is (is it?) exacly what arrows do when you shoot them - they check air time and/or if equal to shooter.

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Hmm, looked through the source and it seems MOPs have been removed. Arrows use World.rayTraceBlocks, and dispensers simply use an offset based on facing, which doesn't apply to smoothly rotating turrets.

 

My turret, which fires entity-piercing lasers, also uses rayTraceBlocks. Then, it damages entities whose bounding boxes the ray intersects.

Link to comment
Share on other sites

Ah, that clears up the MOP mystery.

 

Anyway, although the arrow method of checking for a target reference is perfect for use with a moving projectile that just needs to know when to stop, I imagine a laser or other hitscan turret probably can't make much use of that without adding some travel time.

Link to comment
Share on other sites

Yeah, I mentioned that I could do something similar in the OP. It does mostly work. Although, because the turret rotates beyond a single cardinal direction, rather than using facing, I would have to create a separate forward vector between the barrel's origin and the target, using the distance from the center to a corner of the cube to basically create a sphere that encompasses the cube. The surface of that sphere would be the safe ray starting point in any direction.

 

There are a couple of edge cases with this method. The target could have been pushed slightly inside the block. Or, it could be just close enough that it exists between the cube and the safe start sphere. I imagine silverfish and baby mobs could easy manage that. And, if the turret is thinner in one direction than another, the resulting difference between the safe sphere and bounding box could be enough to let in much larger creatures. Sure, it's a relatively minor edge case, but it's also one that wouldn't exist if I could simply shoot from the turret's center instead of from outside of its bounding box.

 

And then there's management concerns. If the turret has more than one bounding box, I'd have to calculate another, virtual box that surrounds them all to get the smallest possible box that lets in the fewest mobs between it and the safe sphere formed from the radius obtained from its center and one of its corners.

 

So, I'm just wondering if there's a more elegant solution that doesn't involve coupling the ray start position and the block's bounding box. If I could trace a ray from the center while ignoring the source block, that would really be the simplest and most ideal solution.

Link to comment
Share on other sites

If you are standing inside the barrel's reach, it can't hit you, so it makes sense to start the ray trace from the end of the barrel rather than the middle of the block, but yes, it becomes trickier if you have 360-degree rotation (and possibly pitch as well) instead of just 4 (or 6) facings.

 

The simplest method may be the one you have already suggested - traversing a vector along the target trajectory until you both a. exit the end of the barrel and b. collide with something. Either that or write your own ray-trace function that ignores the originating block, as I don't believe the vanilla method has any parameter to do so.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • They were already updated, and just to double check I even did a cleanup and fresh update from that same page. I'm quite sure drivers are not the problem here. 
    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.