Jump to content

Is there an onBroken event for paintings? [1.16.4]


Godis_apan

Recommended Posts

Hello!

 

I'm currently trying to get PaintingEntities to drop a custom item but don't really know how to implement it. Paintings do not have a loot table json, the item drop is handled in the onBroken method in PaintingEntity, called from HangingEntity. Now there are a lot of conditions in which a HangingEntity calls the onBroken method: when it is attacked, moved, accelerated or not on a valid surface. It seems like a bad method to check for all these scenarios with different Forge events, cancelling them and spawning my own item there instead. Have I missed something or should i hardcorde it in? Thanks for any help!

 

 

Edited by Godis_apan
Link to comment
Share on other sites

Hmm still having problems, two of them. The first one is that since I have added a capability to paintings whether or not to drop my item, the game crashes when I try to look for it. The second problem is that the coordinates don't match from the old painting and the spawned item so i can't mark it for removal.

 

Code here:

@Mod.EventBusSubscriber(modid = VanillaBoom.MOD_ID)
public class PaintingHandler
{
    private static boolean paintingDestroyed;
    private static PaintingEntity paintingEntity = null;

    @SubscribeEvent
    public static void onAttachCapabilities(AttachCapabilitiesEvent<Entity> event)
    {
        if (event.getObject() instanceof PaintingEntity)
        {
            event.addCapability(new ResourceLocation(VanillaBoom.MOD_ID, "painting"), new PaintingCapability());
        }
    }

    @SubscribeEvent
    public static void onEntityLeaveTheWorld(EntityLeaveWorldEvent event)
    {
        if (event.getEntity() instanceof PaintingEntity && !event.getWorld().isRemote) 
        {
            PaintingEntity painting = (PaintingEntity) event.getEntity();
            
            //This crashes since the capability is removed before the event is fired
            paintingDestroyed = painting.getCapability(PaintingCapability.PAINTING_CAPABILITY).orElseThrow(NullPointerException::new).isCustom();
            
            if (paintingDestroyed) 
            {
                paintingEntity = painting;
            }
        }
    }

    @SubscribeEvent
    public static void onEntityJoinTheWorld(EntityJoinWorldEvent event)
    {
        if (event.getEntity() instanceof ItemEntity && paintingDestroyed && !event.getWorld().isRemote) 
        {
            ItemEntity itemEntity = (ItemEntity) event.getEntity();
            
            if (itemEntity.getItem() != null && itemEntity.getItem().getItem() == Items.PAINTING) 
            {
                if (paintingEntity != null) 
                {
                    //These do not match up
                    if (paintingEntity.getPosX() == itemEntity.getPosX() && paintingEntity.getPosY() == itemEntity.getPosY() && paintingEntity.getPosZ() == itemEntity.getPosZ()) 
                    {
                        event.setCanceled(true);
                        paintingEntity.entityDropItem(ModItems.SKULL_AND_ROSES_PAINTING);
                        paintingEntity = null;
                        paintingDestroyed = false;
                    }
                }
            }
        }
    }
}

 

Edited by Godis_apan
Link to comment
Share on other sites

I've tried this now and i still run into an error. When the ItemEntity is spawned when the painting is hit, the paintings capabilities have already been removed. In the HangingEntity's tick() method, this.remove() is called first and then this.onBroken(). This means my code will crash when checking if the painting that was broken was a custom one:

 

    @SubscribeEvent
    public static void onEntityJoinTheWorld(EntityJoinWorldEvent event)
    {
        if (event.getEntity() instanceof ItemEntity && !event.getWorld().isRemote) 
        {
            ItemEntity itemEntity = (ItemEntity) event.getEntity();
            
            if (itemEntity.getItem() != null && itemEntity.getItem().getItem() == Items.PAINTING) 
            {
                double posX = itemEntity.getPosX();
                double posY = itemEntity.getPosY();
                double posZ = itemEntity.getPosZ();

                List<PaintingEntity> list = event.getWorld().getEntitiesWithinAABB(PaintingEntity.class, new AxisAlignedBB(posX-0.5D, posY, posZ-0.5D, posX+0.5D, posY, posZ+0.5D));
                
                for (PaintingEntity painting : list) 
                {
                    //Crash here because the painting's capabilities have already been invalidated 
                    if (painting.getCapability(PaintingCapability.PAINTING_CAPABILITY).orElseThrow(NullPointerException::new).isCustom()) 
                    {
                        painting.entityDropItem(ModItems.SKULL_AND_ROSES_PAINTING);
                        event.setCanceled(true);
                    }
                }
            }
        }
    }

 

Link to comment
Share on other sites

Yes I thought of that at first but decided against it to make my mod work as well as possible with vanilla. However it seems like this way was too much trouble so I guess I have to go with a custom painting entity. Many thanks for the help, you can consider this closed.

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



×
×
  • Create New...

Important Information

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