不要在事件方法中重复检查(Bukkit/Spigot)

huangapple go评论70阅读模式
英文:

Don't repeat checks on event methods (Bukkit/Spigot)

问题

我正在审查我一个重要项目的代码库,我注意到有超过150个事件处理程序,它们都运行基本相同的检查:

        if (!(event.getDamager() instanceof Player))
            return;
        if (!(event.getEntity() instanceof Player))
            return;

        Player player = (Player) event.getDamager();

        Player victim = (Player) event.getEntity();

        if(!AntigriefManager.canInjure(player, victim)) return;

        if (!EnchantChecks.mainhand(player, this)) return;

我的问题是,有没有一种很好的方法可以将这部分抽象出来?

是否可能将这些 player 和 victim 的值传递给多个 EntityDamageByEntityEvent 处理程序,而不是在每个处理程序上方重复编写它们?

谢谢!

英文:

I was reviewing my codebase for a major project of mine and i've noticed that there are over 150 event handlers that all run essentially the same check:

        if (!(event.getDamager() instanceof Player))
            return;
        if (!(event.getEntity() instanceof Player))
            return;

        Player player = (Player) event.getDamager();

        Player victim = (Player) event.getEntity();

        if(!AntigriefManager.canInjure(player, victim)) return;

        if (!EnchantChecks.mainhand(player, this)) return;

My question is, can would there be a good way of abstracting this away?

Is it possible to pass those player and victim values to multiple EntityDamageByEntityEvent handlers instead of writing them above each one?

Thanks!

答案1

得分: 1

利用EventHandler,特别是priorityignoreCancelled

你现在的代码是这样的:

@EventHandler
public void onMyEvent(SomeEvent event) {
    //a) 一堆预检代码
    //b) 你想要运行的实际代码,在几个不同的代码块中
}

你将要做的是将这些任务拆分为两个不同的监听器;一个将处理检查,另一个将运行它负责的任何内容。为此,我们的检查将在EventPriority.LOWEST上运行,因为这些在任何其他优先级之前运行。除此之外,如果事件被取消,我们将使用EventHandler#ignoreCancelled来表示我们的代码不应该被运行:

@EventHandler(priority = EventPriority.LOWEST)
public void onMyPrechecks(SomeEvent event) {
    //a) 一堆预检代码,例如:
    if (!AntigriefManager.canInjure(player, victim)) {
        //注意,我们取消事件,而不是从方法中返回
        event.setCancelled(true);
    }
}

//其他地方,可能是另一个类中:
//优先级不应低于LOW
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onMyEvent(SomeEvent event) {
    //b) 你想要运行的实际代码,例如:
    event.getPlayer().sendMessage("运行事件!");
}
英文:

Make use of EventHandler, specifically priority and ignoreCancelled.

Right now you have this:

@EventHandler
public void onMyEvent(SomeEvent event) {
    //a) A bunch of precheck code
    //b) The actual code you want to run, in several different code bodies
}

What you will end up doing is splitting these tasks into two different listeners; one will handle the checks, the other will run whatever it is responsible for. For this, our checks will run on EventPriority.LOWEST, because those are run before any other priority. On top of that, if the event is cancelled, we will use EventHandler#ignoreCancelled to indicate our code should not be run:

@EventHandler(priority = EventPriority.LOWEST)
public void onMyPrechecks(SomeEvent event) {
    //a) A bunch of precheck code, for example:
    if (!AntigriefManager.canInjure(player, victim)) {
        //notice we cancel, instead of returning from a method
        event.setCancelled(true);
    }
}

//Elsewheres, in another class probably:
//priority should never go lower than LOW
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onMyEvent(SomeEvent event) {
    //b) The actual code you want to run, e.g.:
    event.getPlayer().sendMessage("running event!");
}

huangapple
  • 本文由 发表于 2020年9月3日 03:25:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/63712346.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定