Jump to content

[1.7.10] Detect if player is in a cave


mrbandler

Recommended Posts

Hey Guys,

 

I'm fairly new to modding minecraft with forge.

 

I want to check if the player is in a cave or not...

I figured this would be possible to check because there are lots of minecraft cave map mods and such.

 

Only problem, I have no idea where to start  :-[

 

Help is greatly appreciated, thanks in advance!  :)

Link to comment
Share on other sites

The typical way to go about it is to check if the player can see the sky or not.

 

The problem with that is how do you differentiate being under a tree or in a house vs. in a cave? So you have to decide how would you even define a 'cave'? Should it be mostly stone blocks? What about dirt? Sandstone? Mineshafts?

 

Once you decide that, you can get fancier and check surrounding blocks, but that will slow your algorithm down exponentially with the search radius. To make it faster, you could only check the first non-air block above the player and see if it's in your whitelist of acceptable 'cave' blocks, but then you still get false positives if a player makes a house of stone, for example.

 

Anyway, there isn't any surefire way that I know of to say with 100% certainty a player is in a cave, so you have to figure out what is an acceptable level of error for your purposes.

Link to comment
Share on other sites

If you don't mind missing caves high in hillsides, you could look at the player's Y coordinate to see if it is <62. Overworld and subterranean y and no sky and not wet is probably a cave (or mine, or stronghold, or the player's underground lair).

 

Also decide what you want to do about dimensions besides the overworld.

 

What are you trying to accomplish? Depending on your objective, you might also look at light-level to rule-out houses, deep bases, and well-civilized caves.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

Well, the goal is to have a item that plays music at its position, when the player has the item in his inventory it will play the music on the position of the player, so far so good all of that is already implemented.

 

Now to the advanced stuff, I want to let the player specify a group of music (a playlist) and bind it to certain things in the game.

This bindings being:

  - Day

  - Night

  - Cave

  - Combat

  - etc.

 

Day & night was easy and is already implemented.

Link to comment
Share on other sites

  - Combat

You have a few ways to handle this one.

You could use the LivingEntityHurt event (I think), and check if it's the player being hurt or hurting something. If there's an event for the swinging of an item, you could check if it's a sword that a player is holding, and play the music then.

Link to comment
Share on other sites

Doesn't Minecraft already play spooky sounds when you go into a cave? How does it determine that?

The ambient sounds emerge from dark air with no sky. You can hear them even if there's stone between you and the darkness.

 

Yes, it would be worth looking at the test for ambient sound.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

  • 1 month later...

Thanks for all the answers so far!

 

@jeffryfisher How would I check for wetness and light-level on blocks?

 

I already got that far to check for the players Y position and if the first non air block above the player is exposed to the sun or if there even is one.

 

Can anybody tell me how deep and high the minecraft world is?

 

Thanks again for your help.

Link to comment
Share on other sites

Check if their sunlight is below a certain threshold (I would say about 10). However, being inside would trigger it. You may have to do other checks, such as Y-level (if you can, base it off sea level) and checking their surroundings (you would only need to do this once per second at most).

Link to comment
Share on other sites

The survival overworld has Y-coords 0..255, with bedrock filling the lowermost few and sea-level at 63.

 

I think there's a world method "isWet", but what I meant was not swimming in an ocean. Just being in air should suffice.

 

There are several light levels (including the luminosity of each block type), but now I'm not sure that would help you. You want a trigger in lit caves also, right? I think you want to find the method "canSeeTheSky" (or something like that).

 

BTW, One can never see sky in the End and Nether, so you might want to trap those first (and maybe make different sounds for them).

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

isWet is a boolean based on whether or not the entity was recently (or still is) swimming, that's it.  It's not even close to what you'd have to do to check for caves.

 

As for sky_light, that absolutely helps, and more so than canSeeTheSky.  canSeeTheSky checks only the vertical column of blocks at the current location.  sky_light can reach up to 15 blocks underneath an overhang.  Sky_light is also tracked independently of block_light, so lit caves will still register as caves.

 

The problem is figuring out whether or not the material blocking out the light is made of stone, as opposed to wood, dirt, water, or other block type.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

  • 2 months later...

In 1.10 the method is called "getLightFor(EnumSkyBlock, BlockPos)" (that's the environemtn I have open at the moment). I can't recall the 1.7.10 name off the top of my head ("getSavedLightValue?"), but it's named pretty similarly and takes an

EnumSkyBlock

parameter (which has two values:

BLOCK

meaning torches, etc. and

SKY

meaning the sun).

 

It doesn't check day/night (that's "getSkylightSubtracted").  But yeah, any "cave" location is going to have 0 sunlight.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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.