So priority takes an important role, I haven't seen anyone on the pmmp forums talk about priorities, I've only seen threads that include it in their code but no explanation, but some people may not understand what it is, the purpose of this thread is to explain such matters. I've gathered some information to assist all of you guys. When you register events in PMMP, you can assign it a priority. Most people use Priority NORMAL without knowing because that's the default priority until you define it, and that just makes sense, right? Normal's normal. Until you think about other plugins. There are 6 priorities in PMMP (Just like Bukkit/Spigot) Those are: Highest High Normal Low Lowest Monitor They're actually called in this order: Lowest low Normal High Highest Monitor They look sane, right? Except for that obvious bolded "Monitor" one which just sticks out. Not just because it's bold. Really. I'll get to that in a second. The theory behind this system is, every plugin gets a say in what happens, and every plugin must get a chance to know the outcome of an event. So, we pass events to plugins even after they've been canceled. A plugin can actually uncanceled an event after another plugin canceled it. This is where priorities become really important. Let's say a BLOCK_PLACE event is being handled. The lowest priority listener is called to get its say in whether it should be canceled or not. Then the low priority listener is called to see if it wants to override the low, etc. Eventually, it hits monitor, and at this point, nothing should change the outcome of the event. The monitor should be used to see the outcome of an event, without changing any aspect of it. If we have three plugins enabled; one is a basic area protection plugin, one is a fancy plugin using signs, and another is a logging plugin. The protection plugin listens on Priority::LOWEST. It says they can't place blocks in this area and cancels the event. The fancy sign plugin listens on Priority::NORMAL. It says they can place signs here, and un cancels the event. The log plugin listens on Priority::MONITOR. It seems that the event was actually allowed, and logs it. If you want to choose a priority for an event just add this just before it (replace <PRIORITY> with priority name): Code: /** * @priority <PRIORITY> */ Basically, if you want to change the outcome of an event, choose very carefully from LOWEST to HIGHEST. I'd suggest generalized protection plugins on lowest, more specific plugins on normal, and override plugins on high. If you want to act when an event happens, but not change the outcome, use monitor. It's really really important that you use the monitor, or an event might get canceled after you've acted from it, and it's even more important that you don't change the outcome of the event on the monitor or it'll break other plugins. I could explain this better, but I'm hoping you'll get the idea. Any questions or comments?
Actually not. Depending on how you interpret their meanings, some people believe "highest" should execute before "lowest", which is not the case. Unless with the @ignoreCancelled tag set to true. P.S. It is an unofficially planned feature on Poggit to show a list of what events are handled in what plugins at what priority to help developers determine the priority they want to use.
The current event system has some defects. One obvious problem is with event listeners that replace the execution of the event. Let's look at this example. I have a plugin that changes all chat messages into tips (sendTip() instead of sendMessage()). How do I implement it? I have to override PlayerChatEvent, cancel it and call sendTip() in my event listener. Now, what event priority should I use? If one of LOWEST to HIGHEST is used, some event listeners (especially MONITOR listeners) of PlayerChatEvent will see the event as cancelled and fail to work (e.g. not logging chat). If MONITOR is used, this violates the rule that you must not cancel/modify events at MONITOR. In addition, the execution order of multiple MONITOR event listeners is undefined, i.e. if you're unlucky (e.g. if the filesystem sorts the plugins such that the logger plugin is loaded before your plugin is loaded), your MONITOR listener may be executed after other listeners. This order may rely on many factors, such as: plugin loader (PharPluginLoader? FolderPluginLoader? ScriptPluginLoader? ZipPluginLoader?) file system directory order this depends on the file system a lot. See https://unix.stackexchange.com/q/13451/161897 for example. plugin load order (STARTUP? POSTWORLD?) Any suggestions for how to improve this? I thought of something like https://github.com/pmmp/PocketMine-MP/issues/851, but it does not seem to work well with multiple plugins either since they will override each other.
Yeah agree, I'm planning on adding/explaining what Code: @ignoreCancelled tag does. Will also be updating this tutorial with a bit more explanations. I also noticed the same issue with event listeners.
*mindblown* I always thought @ignoreCancelled meant "ignore whether it's cancelled or not", not "ignore cancelled events"
Grammatically: ignore cancelled = ignore cancelled events ignore cancel/cancellation/cancelling = ignore the cancellation of events