Java中用于插件MC的无限循环java /事件

时间:2018-01-04 19:26:18

标签: java minecraft bukkit

我的MC插件有问题,我需要一个等待条件满足的无限循环。但它创建了一个无限循环,但变量已经改变。这是代码:

boolean bState;
public boolean GetState(){
    return bState;
}
public void SetState(boolean bState) {
    this.bState = bState;
}

@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) throws InterruptedException {
    Player player = event.getPlayer();
    if (event.getAction().equals(Action.RIGHT_CLICK_BLOCK) && event.getClickedBlock().getType() == Material.CHEST && event.getItem().getType() == Material.DIAMOND_SWORD)  {
        Chest chest = (Chest) event.getClickedBlock().getState();
        event.setCancelled(true);
        Inventory inv = chest.getInventory();
        inv.getContents();
        Inventory sinv = Bukkit.createInventory(player, chest.getInventory().getSize());
        sinv.setContents(inv.getContents());
        SetState(false);
        player.openInventory(sinv);
        while(GetState() == false){
            getLogger().info("Ok");
        }
        //Some other things to do
    }
}

@EventHandler
public void onPlayerCloseInv(InventoryCloseEvent event) {
    Player player = (Player) event.getPlayer();
    SetState(true);
}

我确信100%在onPlayerInteract之后触发了事件onPlayerCloseInv。谁能帮我 ? 谢谢:D

编辑: 我的新代码onPlayerCloseInv没有启动任何人有想法吗?

1 个答案:

答案 0 :(得分:2)

使用bukkit,你只有一个主线程的原则。

因为这个线程一次只能做一件事,所以你不能使用自旋锁来等待条件,因为自旋锁基本上会让线程忙。

将关闭代码移至setState

虽然这是最简单的方法,但使用遗嘱,您将失去对本地变量的跟踪。

public void SetState(boolean bState) {
    if(this.bState == false && bState == true) {
        //Some other things to do
        getLogger().info('Inventory closed');
    }
    this.bState = bState;
}

使用本地runnable为负状态

虽然这种方法会受到新lamba实例的惩罚以及稍微混淆的堆栈跟踪,但是使用它可以访问所有本地(隐含的)最终变量。

Runnable closeTask = null;
public void SetState(boolean bState) {
    if(this.bState == false && bState == true ) {
        if(closeTask != null) {
            closeTask.run();
            closeTask = null;
        }
    }
    this.bState = bState;
}

@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) throws InterruptedException {
    Player player = event.getPlayer();
    if (event.getAction().equals(Action.RIGHT_CLICK_BLOCK) && event.getClickedBlock().getType() == Material.CHEST && event.getItem().getType() == Material.DIAMOND_SWORD)  {
        ...
        player.openInventory(sinv);
        closeTask = () => {
            //Some other things to do
             getLogger().info('Inventory closed');
        };

    }
}