#efficient way to check if there are any blocks or any entities in a radius?

63 messages · Page 1 of 1 (latest)

little ocean
#
    .tick(ctx => {
        let entity = ctx.entity
        let x = entity.x
        let y = entity.y
        let z = entity.z
    })
tepid sparrowBOT
#

Once your ticket has been resolved, please close it with </ticket close:1054771505520717835> command!

little ocean
#

I just need to constantly check if there are any blocks or entities in a radius from this entity

#

since I want the entity later to explode if there is anything near

dense stratus
#

level.getEntitiesOfClass(class, aabb) gets you an iterable List<T extends class> of entities inside the AABB
You can import net.minecraft.world.phys.AABB and instantiate it with 2 BlockPos' of opposite corners of whatever cube size you want
I recommend importing let $LivingEntity = Java.loadClass('net.minecraft.world.entity.LivingEntity') and then just passing $LivingEntity as the class, unless you want higher control

Blocks can get a bit messy...
For this, I recommend using BlockPos::betweenClosed(x1,y1,z1,x2,y2,z2) which is optimized for large searching large areas, by using MutableBlockPos. But there's some large caveats to keep in mind. The resulting BlockPos' instances can only be used within the iteration loop, unless you specifically convert the BlockPos using .toImmutable() as the referenced blockpos will switch through each following position within the search radius
Also: the x1,y1,z1,x2,y2,z2 have to be passed based on size. x1 must be less than x2, y1 must be less than y2 and z1 must be less than z2

little ocean
#

oh my

dense stratus
#

also; I heavily recommend only searching every so often. Searching once every second for entities is near imperceptible for most players, and is an instant 20x better performance
Searching blocks (which will be the bigger performance loss) once every 5s is an instant 100x performance

little ocean
#

hmm

#

actually now when I think about it

#

could I not just idk increase the entity hitbox aswell

#

not sure if I can live edit it tho

#

it might also increase the model size tho

#

hmm

fiery coral
#

iirc larger hitbox doesn't really make it performant than doing AABB

#

The game still needs to do the physics anyway, and perhaps on a gametick basis

#

Btw, AABB is built in kubejs so you can directly use AABB.of and not need to do Java.loadclass for it

little ocean
#

hmm

little ocean
#
    .tick(entity => {
        let level = entity.level
        console.log(entity.age)
        if (entity.age > 20 && entity.age % 20 == 0) {
            let fuze = entity.getSyncedData("Fuze")
            let RADIUS = entity.getSyncedData("FuzeValue") || 10
            console.log(fuze, RADIUS)
            if (fuze === "proximity_fuze") {
                let x = entity.x
                let y = entity.y
                let z = entity.z

                let foundBlock = false

                outerLoop:
                for (let dx = -RADIUS; dx <= RADIUS; dx++) {
                    for (let dy = -RADIUS; dy <= RADIUS; dy++) {
                        for (let dz = -RADIUS; dz <= RADIUS; dz++) {
                            let block = level.getBlock(x + dx, y + dy, z + dz)
                            if (block.id !== "minecraft:air") {
                                foundBlock = true
                                break outerLoop
                            }
                        }
                    }
                }

                if (foundBlock) {
                    entity.remove("discarded")

I currently have this, which is extremely laggy.

#

idk how to use the provided ideas

dense stratus
#

you are checking if any block block except air exists in radius.... that should break the loop in like 6 attempts max...
Try this and see if performance is better

.tick(entity => {
    let level = entity.level
    console.log(entity.age)
    if(entity.age > 20 && entity.age % 20 == 0){
        let fuze = entity.getSyncedData('Fuze')
        let RADIUS = entity.getSyncedData('FuzeValue') || 10
        console.log(fuze, RADIUS)
        if(fuze === "proximity_fuze"){
            let center = entity.blockPosition()
            let lessercorner = center.north(RADIUS).west(RADIUS).below(RADIUS)
            let greatercorner = center.south(RADIUS).east(RADIUS).above(RADIUS)
            let targets = $BlockPos.betweenClosedStream(lessercorner, greatercorner)
                .filter(bpos => {
                    level.getBlock(bpos).id !== "minecraft:air"
                })
                .toArray()
            if(targets.length > 0)
                entity.remove("discarded")
        }
    }
#

(north/west/below are negative directions, south/east/above being positive. shouldn't matter for the betweenClosedStream(BlockPos, BlockPos) overload, but still...)

little ocean
#

hmm

#

problem

#

the proximity fuze has max of 32 blocks for whatever reason

#

which

#

is a lot

#

maybe if I can minimize the amount of blocks to check

#

maybe just a hollow shell or something

#

I have no idea how create big cannons did it

#

is that even open sourced

fiery coral
#

Does the bomb move? or is it affected by gravity?

little ocean
#

it moves

#

it's a projectile with a model

#

I thought about increasing the projectile hitbox

#

but idk bout performance

fiery coral
#

Well, an idea is to separate blockpos to check into several groups and only check a group in 1 tick. Just like I did it in the previous "block degradation" thread

#

Or you can try the raycast way

little ocean
#

I thought about that

#

can I just use clip?

fiery coral
#

I think you can

#

you'll just need to check if the hitresult type is MISS

little ocean
#

should I cast them in random directions

#

or should they be fixed

#

like

#

idk

dense stratus
#

should be fine with 6 (all cuboid directions) or even just 5 and skip "behind"
The 4 cardinal can also have a lesser range as they're less likely to trigger

little ocean
#

hmm

#

I prob need more rays than that tbh

#

I would probably do diagonal too

#

25 rays seems like a lot idk

little ocean
#
        let result = level.clip(new $ClipContext(
            ORIGIN,
            TO,
            $ClipContext.Block.COLLIDER,
            $ClipContext.Fluid.NONE,
            entity
        ))

        if (result) { // how do I check again
            hitSomething = true
            break
        }

I forgot how to check

#
const $HitResult$Type = Java.loadClass("net.minecraft.world.phys.HitResult$Type")
#

something with this

#

forgot

#
        if (result.type == HitResult$Type.MISS) { // how do I check again
            hitSomething = true
            break
        }
#

this maybe

#

well

#

with a !

#

I guess

fiery coral
#

if(!result.type.equals($HitResult$Type.MISS))

little ocean
#

okay that works well

#

no lag either it seems

#

thanks