Jump to content

[1.12.1] Canceled PlaceEvent removes block from inventory


Recommended Posts

Posted

Hi all,

I'm using the following code to cancel the PlaceEvent:

@SubscribeEvent
public static void onBlockInteract( PlaceEvent event )
{
	int blockId = Block.getIdFromBlock( event.getPlacedBlock().getBlock() );
	if( blockId == 0 )
	{
		event.setCanceled( true );
	}
}

The following happens:

The block gets placed, it appears for a short time, then disappears and isn't placed at all BUT the placed block is gone from the inventory of the player AND is back after a relog of the player.

 

I want to give the player black the block during his current session, not after a relog.

 

If read the following thread/post maybe I'm encountering the same problem - but I don't know how to solve it.

 

How can I gave the player the not placed item/block back?

 

Kind regards,

Pixtar

Posted

Your handler is only running on the server, not the client, you can tell because the block was never placed, your client just thought it was.

To solve this we might need more context than this. Are you using any @SideOnlys?

Posted

Hi Aarilight,

until now I haven't annotated any class or method with @SideOnly.

 

That sounds like both sides are in need of the mod, client and server?

 

So I need to divide the code into two sections, server and client, like this?

@SubscribeEvent
public static void onBlockInteract( PlaceEvent event )
{
  if( FMLCommonHandler.instance().getSide().isServer() )
  {
      int blockId = Block.getIdFromBlock( event.getPlacedBlock().getBlock() );
      if( blockId == 0 )
      {
          event.setCanceled( true );
      }
  }
  else
  {
      //What to do here?
  }
}

 

Currently I haven't much knowledge about Sides coding.

 

Kind regards,

Pixtar

Posted

You don't need that, you already know your handler is only being called on the server, so it will only reach the top half anyway. Honestly the @SideOnly question was my only idea of what could be wrong, it prevents stuff from being called altogether by removing them from the code on the other side. If you're not using it then it's not your problem. I have no other ideas, so you'll have to wait until someone more knowledgeable responds. Sorry >.>

Posted

Hi Aarilight,

ah okay, no problem, thanks for your help anyway.

 

I think I've detected another problem I need to solve. The canceled event is based on a server side config, which contains a list of blocks which aren't allowed to be place. So I need to follow the hints of this forge documentation and provide the blocks which needs to be blocked via an NetworkInterface to the client. Right?

 

Kind regards,

Pixtar

Posted (edited)

Hi loordgek,

 

thanks for your hint. I've rewritten my code and added the config I'm using to define my blocked block:

@Config(modid = ExampleMod.MODID, name=ExampleMod.MODID+"/"+ExampleMod.MODID, category="config")
public class MyConfig
{
   public static int blockedBlockId = 1;
}

 

public class MyConfigWrapper
{
   public static Block blockedBlock = null;
   MyConfigWrapper()
   {
   	blockedBlock = Block.getBlockById( ExampleMod.config.blockedBlockId );
   }
}

 

public static MyConfig config = null;
public static MyConfigWrapper configWrapper = null;
@Mod.EventHandler
public void preinit( FMLPreInitializationEvent event )
{
  config = new MyConfig( );
  configWrapper = new MyConfigWrapper( );
  //How to share the blocked block for the client?
}

@SubscribeEvent
public static void onBlockInteract( PlaceEvent event )
{
  if( FMLCommonHandler.instance().getSide().isServer() )
  {
      Block destBlock = event.getPlacedBlock().getBlock();
      if( destBlock == configWrapper.blockedBlock )
      {
          event.setCanceled( true );
      }
  }
  else
  {
      //What to do here?
  }
}

At the end these changes are cosmetic I will still have the same problems: The client doesn't know about block which block should be blocked, right?

 

Kind regards,

Pixtar

Edited by Pixtar
Posted
2 minutes ago, Pixtar said:

blockedBlock = Block.getBlockById( config.blockedBlock );

NO NO NO

 

24 minutes ago, loordgek said:

use the RegistryName

 

 

remove

8 minutes ago, Pixtar said:

if( FMLCommonHandler.instance().getSide().isServer()

 

Posted
    public EnumActionResult onItemUse(EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ)
    {
        if (!worldIn.isRemote) return net.minecraftforge.common.ForgeHooks.onPlaceItemIntoWorld(this, playerIn, worldIn, pos, side, hitX, hitY, hitZ, hand);
        EnumActionResult enumactionresult = this.getItem().onItemUse(playerIn, worldIn, pos, hand, side, hitX, hitY, hitZ);

        if (enumactionresult == EnumActionResult.SUCCESS)
        {
            playerIn.addStat(StatList.getObjectUseStats(this.item));
        }

        return enumactionresult;
    }

this is the point in the itemStack where it gets called from,and the problem you have

 

why is the hook only called from the server side and not both ??

Posted

Hi loordgek,

so how to cast from an Integer to an object Block dynamically without using switch case to determine the static Block?

 

I've removed the SideOnly barrier.

 

At the end I'm here to figure out exactly that question:

Quote

why is the hook only called from the server side and not both ??

 

Maybe PlaceEvent is only hooked on the server side and I need to use RightClickBlock?

 

Kind regards,

Pixtar

Posted
3 minutes ago, Pixtar said:

so how to cast from an Integer to an object Block dynamically without using switch case to determine the static Block?

you dont

save the RegistryName to the config

 

Block.getRegistryName();

 

15 minutes ago, Pixtar said:

Maybe PlaceEvent is only hooked on the server side and I need to use RightClickBlock?

yes works tested it,  read the javadoc on it

Posted (edited)

Hi loordgek,

 

if I'm storing e.g. Dirt via RegistryName it stores nothing in the annotated config except the variable name:

public static ResourceLocation blockedBlock = Blocks.DIRT.getRegistryName();

Result

blockedBlock {
}

 

Let's talk about which versions we are using, currently I'm working with forge-1.12.1-14.22.0.2467-mdk

 

Could it be a sync bug in forge? I'm asking, because I've contact to another mod developer and he's saying he's having the same issue. :-/

 

Kind regards,

Pixtar

Edited by Pixtar
Posted (edited)

Hi loordgek,

 

well that worked for me:

public static String blockedBlock = Blocks.DIRT.getRegistryName().toString();

Results in:

S:blockedBlock=minecraft:dirt

 

Like I mentioned before about the cast .. how to cast it backwards? Currently I would do the comparison like the following, because I don't know how to cast from String to Block backwards:

if ( event.getPlacedBlock().getBlock().getRegistryName().toString().equals( config.blockedBlock ) )

The only way I found myself is this one ?!

if ( event.getPlacedBlock().getBlock() == Block.REGISTRY.getObject(new ResourceLocation( ExampleMod.config.blockedBlock ) ) )

 

Kind regards,

Pixtar

Edited by Pixtar
Posted (edited)
1 hour ago, Pixtar said:

because Blocks.PODZOL isn't defined.

Of course it's not. For the same reason Blocks.PINK_WOOL isn't defined: it's a metadata state variant of the dirt block. You need to also read/supply a metadata value or IBlockState definition.

Edited by Draco18s

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.

Posted

Hi Draco18s,

thanks for the advice of the metadata state. I will keep that in mind.


Anyway - the entire thread is heading the wrong track. My initial problem of the sync client / server is still available.

5 hours ago, Pixtar said:

The block gets placed, it appears for a short time, then disappears and isn't placed at all BUT the placed block is gone from the inventory of the player AND is back after a relog of the player.

Pixtar

Posted
6 hours ago, Aarilight said:

Your handler is only running on the server, not the client, you can tell because the block was never placed, your client just thought it was.

 

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.

Posted (edited)

Hi Draco18s,

so I've cleaned my gradle, created a complete clean server, removed all mods at the client side, compiled the BlockPlaceEventTest loordgek posted, inserted it at the server and the client side and tried it again.

I encounter still the same problem - the inventory of the client won't be updated, ONLY if the user collects a block of the same denied type the belt receives an update and the blocks are back.

 

Yep - I understand the circumstance that the client thinks the block is/was placed.

 

Main question: At which place do I need to modify what to inform the client that the block wasn't placed successfully if the code of loordgek isn't doing that?

Side question: How does the client notice. that the blocks weren't placed after collecting a new block of the same denied type?

Pixtar

Edited by Pixtar
Posted
1 hour ago, Pixtar said:

Hi Draco18s,

compiled the BlockPlaceEventTest loordgek posted, inserted it at the server and the client side and tried it again.

You put the code from a test into your code? He posted that test to demonstrate how BlockPlaceEvent works. This code won't do anything for you as is.

 

6 hours ago, Pixtar said:

Maybe PlaceEvent is only hooked on the server side and I need to use RightClickBlock?

In the handler which started this entire problem, did you try using RightClickBlock instead of PlaceEvent?

 

I went ahead and just tested in game, and yes, PlaceEvent only seems to occur on the server. RightClickBlock can be cancelled based on the ItemStack in your hand, though. Here is working code that only cancels Podzol:

 

	@SubscribeEvent
	public static void onBlockPlace(RightClickBlock event) {
		ItemStack block = event.getEntityPlayer().getHeldItemMainhand();
		if (ItemStack.areItemStacksEqual(block, new ItemStack(Blocks.DIRT, block.getCount(), 2))) {
			event.setCanceled(true);
		}
	}

 

To cancel based on a list of blocked blocks, the easiest way would be to store them as ItemStacks, since that supports holding both the block type and the metadata, and just loop through the list in this event handler. To check equality, make sure the count of the stack you're checking is the same as the held stack count. WILDCARD_VALUE does not work for count. If one of them matches, cancel the event.

Posted

Hi Aarilight,

7 hours ago, Aarilight said:

You put the code from a test into your code? He posted that test to demonstrate how BlockPlaceEvent works. This code won't do anything for you as is.

well, that might be, that he posted that code only for a demo - nevertheless the code is doing the same like mine; canceling the event.

 

7 hours ago, Aarilight said:

In the handler which started this entire problem, did you try using RightClickBlock instead of PlaceEvent?

Yep - I tried that one too. Thank you for your time to create and test your posted snippet.

 

I'm sorry to say that, but for my version of forge (1.12.1-14.22.0.2452) it does nothing else than the other codes - furthermore it doesn't only block Podzol it blocks the entire dirt group. Block gets placed, forge tidies up the block, it disappears and it's gone from the inventory.

 

Have a nice day,

Pixtar

Posted (edited)

Hi Aarilight, Draco18s and loordgek,

 

it working now with the source of Aarilight. Thank you all for your patience with me. ^^

 

Kind regards,

Pixtar

Edited by Pixtar
Posted

Hi all again,

 

it's driving me insane. xD

It's only working flawless if both ; client and server are having the same config file. >:(

 

Now I changed the config file at the server from dirt to stone and I'm running into the same problem - again.

Block isn't placed, Block is temporary gone from the hotbar slot. I can throw/drop [Q] the "empty" slot and it drops the gone stone block.

SOO the client knows about the not placed block, but it doesn't refresh the hotbar slot.

 

How can I refresh/update the hotbar slot?

 

Kind regards,

Pixtar

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

    • 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?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

×
×
  • Create New...

Important Information

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