friendlyhj/ZenUtils

[Feature Request] expose GUI open event

Closed this issue ยท 8 comments

I want to detect when player "acquire" important items and their functionality.
I found, that if I want to detect complicated stuff like EnderIO Conduits I cannot propertly do this with already existed events:

  1. I cant detect from crafting because player can autocraft it.
  2. I cant detect from placing since player could just use block placers.
  3. I should not detect from PlayerInteractBlockEvent since it would cause false-positive when you accidentally clicked conduit on spawn or just stand too far from block and GUI cancelled.
  4. I cannot detect when player using some weird mechanics that opening GUIs on trigger.

I think, event that expose gui name or something similar would be cool.
I dont know if its possible to expose more information, like if its Inventory GUI and such, but would be good for the future too.

image

Oh, yes, its working.. I cant cancel it through, but i think i could use this. Thank you. I really looked through every event possible several times, but somehow missed it ๐Ÿ˜…

In v1.19.0, you can subscribe all forge events.

#sideonly client
// this a client only event, your script should be client only too.

events.register(function(event as native.net.minecraftforge.client.event.GuiOpenEvent) {
    // your code
});

Yeah, thank you. But i think I need to wait until documentation will be written, since it feels like i do something wrong ๐Ÿ˜…

#sideonly client

events.register(function(event as native.net.minecraftforge.client.event.GuiOpenEvent) {
  val guiClass = typeof(event.getGui());
  if ( guiClass == 'crazypants.enderio.conduits.gui.GuiExternalConnection') event.setCanceled(true);
});
javaw_6y6p9zvCqd.mp4

It is a forge issue. GuiOpenEvent cancellation doesn't work for gui that contains data sync (e.g. item slots). The event only denies the gui from displayed, but it doesn't stop data sync. Server still try to sync the gui contents to client. After you cancel the event, the gui of server and client is different: furance on server side while player invenrory on client side, then the data sync logic produces desync instead. (yea, gui is client only exactly, the thing on server side is called container, to deal with data sync)
So I suggested to PlayerOpenContainer event previously, but it is not cancellable :(

I tried to send packet to notify server to close the gui connection. But it takes time, the gui still displayes in one tick.

So even I expose GuiOpenEvent, there still isn't a good way to deny opening a gui. It's better to find a reliable way to use PlayerInteractBlockEvent. But about your actual problem, I don't think you need to prevent opening gui?

It's better to find a reliable way to use PlayerInteractBlockEvent

Yeah, if i will find nothing better, i will end up with InteractBlock.

I tried to send packet to notify server to close the gui connection. But it takes time, the gui still displayes in one tick.

This solution is actually sounds reliable. Glitchy but players will understand that this happened intentionally. How i could do that with CT?

import mods.zenutils.NetworkHandler;

// in client only script
events.register(function(event as native.net.minecraftforge.client.event.GuiOpenEvent) {
    val guiClass = typeof(event.getGui());
    if ( guiClass == 'net.minecraft.client.gui.inventory.GuiFurnace') {
        NetworkHandler.sendToServer("close_container");
    }
});

// in a plain script
NetworkHandler.registerClient2ServerMessage("close_container", function(server, byteBuf, player) {
    player.native.closeScreen();
});

Oh, wait, PlayerOpenContainerEvent + closeScreen works perfectly

events.register(function(event as crafttweaker.event.PlayerOpenContainerEvent) {
    if (event.container.asString().startsWith("net.minecraft.inventory.ContainerFurnace")) {
        event.player.native.closeScreen();
    }
});