private void startListening() {
        Events.merge(Player.class)
                .bindEvent(PlayerDeathEvent.class, PlayerDeathEvent::getEntity)
                .bindEvent(PlayerQuitEvent.class, PlayerEvent::getPlayer)
                .bindEvent(PlayerChangedWorldEvent.class, PlayerEvent::getPlayer)
                .bindEvent(PlayerTeleportEvent.class, PlayerEvent::getPlayer)
                .filter(p -> p.equals(this.player))
                .filter(p -> isValid())
                .handler(p -> invalidate())
                .bindWith(this);

        Events.subscribe(InventoryDragEvent.class)
                .filter(e -> e.getInventory().getHolder() != null)
                .filter(e -> e.getInventory().getHolder().equals(this.player))
                .handler(e -> {
                    e.setCancelled(true);
                    if (!isValid()) {
                        close();
                    }
                }).bindWith(this);

        Events.subscribe(InventoryClickEvent.class)
                .filter(e -> e.getInventory().getHolder() != null)
                .filter(e -> e.getInventory().getHolder().equals(this.player))
                .handler(e -> {
                    e.setCancelled(true);

                    if (!isValid()) {
                        close();
                        return;
                    }

                    if (!e.getInventory().equals(this.inventory)) {
                        return;
                    }

                    int slotId = e.getRawSlot();

                    // check if the click was in the top inventory
                    if (slotId != e.getSlot()) {
                        return;
                    }

                    SimpleSlot slot = this.slots.get(slotId);
                    if (slot != null) {
                        slot.handle(e);
                    }
                })
                .bindWith(this);

        Events.subscribe(InventoryOpenEvent.class)
                .filter(e -> e.getPlayer().equals(this.player))
                .filter(e -> !e.getInventory().equals(this.inventory))
                .filter(e -> isValid())
                .handler(e -> invalidate())
                .bindWith(this);

        Events.subscribe(InventoryCloseEvent.class)
                .filter(e -> e.getPlayer().equals(this.player))
                .filter(e -> isValid())
                .handler(e -> {
                    invalidate();

                    if (!e.getInventory().equals(this.inventory)) {
                        return;
                    }

                    // Check for a fallback GUI
                    Function<Player, Gui> fallback = this.fallbackGui;
                    if (fallback == null) {
                        return;
                    }

                    // Open at a delay
                    Schedulers.sync().runLater(() -> {
                        if (!this.player.isOnline()) {
                            return;
                        }
                        Gui fallbackGui = fallback.apply(this.player);
                        if (fallbackGui == null) {
                            throw new IllegalStateException("Fallback function " + fallback + " returned null");
                        }
                        if (fallbackGui.valid) {
                            throw new IllegalStateException("Fallback function " + fallback + " produced a GUI " + fallbackGui + " which is already open");
                        }
                        fallbackGui.open();

                    }, 1L);
                })
                .bindWith(this);
    }
Registers the event handlers for this GUI
helper/src/main/java/me/lucko/helper/menu/Gui.java