Jump to content

Recommended Posts

Posted

I found some old code for detecting if the block you're looking at is a door:

public boolean isDoor(PlayerInteractEvent event)
{
	BlockDoor door = (BlockDoor)Blocks.wooden_door;
	BlockLocation loc = BlockLocation.get(event.world, event.x, event.y, event.z);

	if((event.action == Action.RIGHT_CLICK_BLOCK) && (loc.getBlock() == door))
		return true;
}

 

Of course this is out dated as BlockLocation is no longer used.  That and Blocks.wooden_door doesn't exist anymore either.  For an updated version of this, does this look about right?

 

public void onDoorInteract(PlayerInteractEvent event)
{
  Minecraft mc = Minecraft.getMinecraft();
  BlockPos blockpos = mc.objectMouseOver.getBlockPos();
  Block block = event.getEntityPlayer().getEntityWorld().getBlockState(blockpos).getBlock();
  
  //call return if block isn't a door
  if((event.action != Action.RIGHT_CLICK_BLOCK) || !(WoodenDoor(block)))
    return;
  
  //Do stuff if it is a door
   
}
                           
public boolean WoodenDoor(Block block)
{
    BlockDoor[] doors = {(BlockDoor) Blocks.ACACIA_DOOR, (BlockDoor) Blocks.BIRCH_DOOR, (BlockDoor) Blocks.DARK_OAK_DOOR,
            (BlockDoor) Blocks.JUNGLE_DOOR, (BlockDoor) Blocks.OAK_DOOR, (BlockDoor) Blocks.SPRUCE_DOOR};

    for(BlockDoor door : doors)
    { if(block == door) return true; }
  
    return false;
}

 

Also, event.action != Action.RIGHT_CLICK_BLOCK doesn't seem to exist since 1.8, either.  Does anyone know how to do this in the current 1.12 environment?

Posted
12 hours ago, fuzzybat23 said:

Also, event.action != Action.RIGHT_CLICK_BLOCK doesn't seem to exist since 1.8, either.  Does anyone know how to do this in the current 1.12 environment?

Why don't you catch the RightClickBlock event directly instead and check if the clicked block is a door?

Don't blame me if i always ask for your help. I just want to learn to be better :)

Posted (edited)

Ok.. I managed to find something about PlayerInteractEvent.RightClickBlock after lots of google digging xD  I did managed to get it to register when I right click, but it doesn't seem to want to correctly check if it's a door or not, now.

 

Edited by fuzzybat23
Posted
    @SubscribeEvent
    public void onDoorInteract(PlayerInteractEvent.RightClickBlock event)
    {
        EntityPlayer player = event.getEntityPlayer();
        BlockPos blockpos = event.getPos().offset(event.getFace());
        Block block = player.getEntityWorld().getBlockState(blockpos).getBlock();

        logger.info("Begin check if it's a door...");
        if( isWoodenDoor(block))
            logger.info("It's a door!");

    }

    public static boolean isWoodenDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR || block == Blocks.DARK_OAK_DOOR || block == Blocks.BIRCH_DOOR ||
                    block == Blocks.JUNGLE_DOOR || block == Blocks.OAK_DOOR || block == Blocks.SPRUCE_DOOR)
                return true;
        return false;
    }

 

Posted
 BlockPos blockpos = event.getPos().offset(event.getFace());

What? I don't understand what are you trying to do there. To get the position of where the player right clicked you have the hitVec variable in the event. So to get the block you should do this

	Block block = event.getWorld().getBlockState(new BlockPos(event.getHitVec().x, event.getHitVec().y, event.getHitVec().z)).getBlock();

Don't blame me if i always ask for your help. I just want to learn to be better :)

Posted
5 minutes ago, JimiIT92 said:

 BlockPos blockpos = event.getPos().offset(event.getFace());

What? I don't understand what are you trying to do there. To get the position of where the player right clicked you have the hitVec variable in the event. So to get the block you should do this


	Block block = event.getWorld().getBlockState(new BlockPos(event.getHitVec().x, event.getHitVec().y, event.getHitVec().z)).getBlock();

getHitVec is the position on the block that the player clicked (in the range 0-1), not the position of the block in the world. 

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

I think I figured this one out.  I ended up using this code and tested it and it worked just fine, letting me know if what I clicked on was a door and if it wasn't.  I've even gotten it to distinguish between the different kinds of doors.

    @SubscribeEvent
    public void onBlockInteract(PlayerInteractEvent.RightClickBlock event)
    {
        Minecraft mc = Minecraft.getMinecraft();
        EntityPlayer player = event.getEntityPlayer();
        BlockPos pos = mc.objectMouseOver.getBlockPos();
        Block block = player.getEntityWorld().getBlockState(pos).getBlock();
        IBlockState state = player.getEntityWorld().getBlockState(pos);

        logger.info("Begin check if it's a door...");
        if( isWoodenDoor(block))
            logger.info("It's a door!" + WoodenDoor.whichDoor(block));

    }

    public static boolean isWoodenDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR || block == Blocks.BIRCH_DOOR || block == Blocks.DARK_OAK_DOOR ||
                    block == Blocks.JUNGLE_DOOR || block == Blocks.OAK_DOOR || block == Blocks.SPRUCE_DOOR)
                return true;
        return false;
    }

    public static BlockDoor whichDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR)
            return Blocks.ACACIA_DOOR;
        if(block == Blocks.BIRCH_DOOR)
            return Blocks.BIRCH_DOOR;
        if(block == Blocks.DARK_OAK_DOOR)
            return Blocks.DARK_OAK_DOOR;
        if(block == Blocks.JUNGLE_DOOR)
            return Blocks.JUNGLE_DOOR;
        if(block == Blocks.OAK_DOOR)
            return Blocks.OAK_DOOR;
        if(block == Blocks.SPRUCE_DOOR)
            return Blocks.SPRUCE_DOOR;

        return null;
    }

 

Posted (edited)
1 hour ago, Choonster said:

getHitVec is the position on the block that the player clicked (in the range 0-1), not the position of the block in the world. 

Actually i use that in my mod to detect when a player uses a flint and steel on an unlit torch and it returns almost the coordinates of the torch. I've done a test right now, the torch was at {x=-7, y=84, z=19}, the getHitVec returned me this {x=-6.399999976158142, y=84.39314504887278, z=19.46219003009727}. Is this a recent change or i just something that shouldn't happen?
By the way you can just do this

event.getWorld().getBlockState(event.getPos()).getBlock()


And it will tell you what block the player has right clicked 

Edited by JimiIT92

Don't blame me if i always ask for your help. I just want to learn to be better :)

Posted

I know almost noth9ing about gethitvec, but based on those different xyz values, the torch will of course be on whole numbers.  7, 84 and 19.  The gethitvec is probably returning the exact area within the bounding box that you clicked on, which can't possibly be whole numbers?

Posted

That's wrong.  This is the code directly from PlayerInteractEvent.java

 

        /**
         * @return The hit vector of this click
         */
        public Vec3d getHitVec()
        {
            return hitVec;
        }

Unless I'm wrong, a hit vector is the X Y Z coordinates of a hit, right?

 

Posted

And yes,

event.getWorld().getBlockState(event.getPos()).getBlock()

  does seem to work a little better as far as getting the block being right clicked.  Cleans up my code by five lines at least xD

Posted (edited)

I must have confused getHitVec with the hitX/Y/Z arguments of Block#onBlockActivated, which I'm pretty sure are between 0 and 1.

 

I don't have my IDE in front of me, so I might be mistaken (again).

 

Edit: The hitX/Y/Z arguments of Block#onBlockActivated are between 0 and 1.

Edited by Choonster

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

See, when people say use an instance of BlockDoor, that just confuses the hell out of me -.-  I live in a world of examples.  Unless an example is given, then something like what you said is completely lost to me xD  Anyway, for what i'm working on, the first step was being able to identify the block being interacted with, in this case by right click, as a door.  Not just as a door, but as a wooden door.  Since iron doors fall into the category of BlockDoor, I just can't run a generic test to say "Is it a door?  Yup."  No, it has to be "Is it an Acacia door, a jungle door, a dark oak door, a birch door, an oak door or a spruce door?  Yes."  A few versions ago, pre 1.9 I think, all you had to check was wooden_door, but now wooden_door only pertains to oak doors, where they should have given oak doors their own name in code and kept wooden_doors as a check for all wood type doors.

Posted

Second phase of what I'm doing is determining if an adjacent block contains a door.  In other words, two doors side by side.  Then figure out if those doors are mirror to each other, and when one of the two is right clicked, it will send a door toggle to the other opening it automatically.  Say you're standing in the world facing north and you place a door in front of you.  It's hinges are facing east.  You place a door next to it one block to the west.  It's hinges are facing west.  You have a set of proper double doors now.

Posted

Mmmm, so instead of this:

    public static boolean isWoodenDoor(Block block)
    {
        if(block == Blocks.ACACIA_DOOR || block == Blocks.BIRCH_DOOR || block == Blocks.DARK_OAK_DOOR ||
                    block == Blocks.JUNGLE_DOOR || block == Blocks.OAK_DOOR || block == Blocks.SPRUCE_DOOR)
                return true;
        return false;
    }

 

Use something like this?

    public static boolean isWoodenDoor(IBlockState state)
    {
        if(state.getBlock() instanceof BlockDoor && state.getMaterial() == Material.WOOD)
                return true;
        return false;
    }

 

Posted

Also, does this look about right as far as looping through the enumfacing?  Passing in the right click event to generate the new target block, using offset(facing) to offset targetblock from block.

    public void checkForDoors(PlayerInteractEvent.RightClickBlock event, Block block)
    {
        for(EnumFacing facing : EnumFacing.HORIZONTALS)
        {
            Block targetblock = event.getWorld().getBlockState(event.getPos().offset(facing)).getBlock();
            if(targetblock == block)
                //Do stuff if block that is offset to original block is same as original block
        }
    }

 

Posted

You said that the hinge is on the top half of the door, and the hinge side is used to determine if the doors face each other, right?  I found this in an older mod, but I'm not sure what the updated code would look like.  I know that this is definitely outdated, though, but from what I can tell it did exactly that.  Determined if it was the upper or lower part of the door being interacted with and set a door variable to the top portion.

    Block blockBottom = block.getRelative(BlockFace.DOWN);
    Block blockTop = block.getRelative(BlockFace.UP);
    Block blockNearBottom = blockBottom.getRelative(BlockFace.NORTH);
    Block blockNearTop = blockTop.getRelative(BlockFace.NORTH);
    Door door = (Door)block.getState().getData();
    Door doorTop = (Door)block.getState().getData();
    Door doorBottom = (Door)block.getState().getData();
    Door doorNearBottom = (Door)block.getState().getData();
    Door doorNearTop = (Door)block.getState().getData();
    if (door.isTopHalf()) {
      blockTop = block;
      doorTop = door;
      doorBottom = (Door)blockBottom.getState().getData();
    } else {
      blockBottom = block;
      doorBottom = door;
      doorTop = (Door)blockTop.getState().getData();
    }

I don't think getRelative exists anymore, and Door isn't a type anymore, it's now BlockDoor.

Posted

That code looks like it's from a Bukkit plugin (or a plugin for a similar system) rather than an old Forge mod.

 

You need to use IBlockState#getValue to get the values of the various properties stored in the BlockDoor class from the state. This will tell you the door's facing and hinge position 

 

diesieben07 explained which properties you need and which block to get their values from earlier in the thread.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

I was rooting around through BlockDoor.java looking for something unrelated and I saw a few snippets that sparked inspiration.  Ran and tested this and it seems to work just fine :D

public static boolean isDoubleDoor(World world, BlockPos pos, EnumFacing offsetPos)
    {
        String RIGHT = "RIGHT";
        String LEFT = "LEFT";
        boolean flag = false;
        IBlockState targetState = world.getBlockState(pos);
        Block targetBlock = targetState.getBlock();

        IBlockState offsetState = world.getBlockState(pos.offset(offsetPos));
        Block offsetBlock = offsetState.getBlock();

        //Get correct blockState, including hinge, for targeted door.

        if(targetState.getValue(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.LOWER)
            if(targetState.getBlock() == targetBlock)
                targetState = world.getBlockState(pos.up());
        BlockDoor.EnumHingePosition targetHinge = targetState.getValue(BlockDoor.HINGE);

        //get correct blockState, including hinge, for offset door.
        
        if(offsetState.getValue(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.LOWER)
            if(offsetState.getBlock() == offsetBlock)
                offsetState = world.getBlockState(pos.offset(offsetPos).up());
        BlockDoor.EnumHingePosition offsetHinge = offsetState.getValue(BlockDoor.HINGE);

        logger.info("(targetHinge)(name)" + targetHinge.name() + "=? (offsetHinge)(name)" + offsetHinge.name() );

        if(((targetHinge.name() == RIGHT) && (offsetHinge.name() == LEFT)) || ((targetHinge.name() == LEFT) && (offsetHinge.name() == RIGHT)))
            flag = true;

        return flag;
    }

 

First checks if it's the lower half of the door and if so, resets the blockState to the upper half.  Then it grabs the side of the door the hinge is on and checks if hinges on the two doors are on the opposite outer sides.

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

    • It is 1.12.2 - I have no idea if there is a 1.12 pack
    • Okay, but does the modpack works with 1.12 or just with 1.12.2, because I need the Forge client specifically for Minecraft 1.12, not 1.12.2
    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
  • Topics

×
×
  • Create New...

Important Information

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