Open Maroon28 opened 3 years ago
Let's consolidate everything into one issue to just keep track of stuff in one place. I've closed #598 and we'll continue here. I think it's worth reiterating the "order of events" challenge to really drive the point home and cover all bases (only one is covered here currently), and also to mention current workarounds for people looking to do something about this here and now.
I hinted at this in the old issue, but there's quite a bit to consider with something like this because of the order of events. For the very specific case of the player join procedure referenced here, I think it makes sense to run commands after the procedure, because that's where the "state" of the player should be stable and unchanging until something else happens (like picking a class or leaving the lobby). For the other events, I'm not sure that after is the right place:
One way to approach this issue is to introduce hooks both before and after each of these procedures and let people choose for themselves. It does muddy the waters a bit, as all flexibility tends to do, so "do we need it?" is probably a good question to have answered before making a giant project out of it all.
For how, we can restort to...
In #598, I alluded to two different workarounds; world/region triggers with external plugins and MobArena's Things framework.
Plugins like WorldGuard have, to my knowledge, some hooks that allow for running commands or "doing stuff" when players enter and leave regions. By placing a region around the lobby, it should be possible to "ghetto detect" the player join event. Similarly, placing a region around the entire arena (lobby, arena floor, spectator area) should make it possible to "ghetto detect" player leave. I don't have any specifics to share, but if anyone does, we could write them down here or maybe add a wiki page about it.
MobArena's own Things framework has Command Things, which can be used to "give" commands to players when they select a class. This is obviously very limited compared to region triggers, but it might be enough for some setups (for now).
Another much more powerful workaround is using a plugin script engine such as Skript or Denizen to import and listen to MobArena's events and run commands based on those. They all fall in the "before" category, as some of them can be cancelled to prevent that event from actually occurring. I haven't toyed with this stuff myself, but a couple of folks have had success with it, so it definitely is possible.
Of course, workarounds are likely not as effective or predictable as...
In #598, I pointed out that I don't see this happening before the Sessions Rework. This is mostly because the Sessions Rework is arguably more important than other session-related features, so taking effort away from that and spending it on stuff that has to be rewritten anyway is a bit of a waste of time. Progress on it is slow and tends to stagnate, which means a lot of other requests will feel a lot more urgent, even though they aren't as important. The more time we spend on seemingly urgent stuff, the longer it will take for the important stuff to get done.
I take my previous statement back. I think we may be able to do this properly before the Sessions Rework. One of the goals of the Sessions Rework is to make things more flexible and more extensible. Hooking into internal events and procedures is very much an extensibility thing (even if it is implemented natively). If we "get it wrong" now, it means we have to suffer the backwards compatibility issues that come with modernizing the code base, but if we "get it right", chances are backwards compatibility becomes a non-issue, and maybe we can even salvage what we do here and reuse it. That's why I think it's important that we don't rush it. I hope that makes sense :)
For the procedure ordering, I do agree that most of these cases should be run before most of the events take place. But we need to take in consideration what we will use these new modules for before deciding. If I had to guess, it'll likely be used to either penalise or reward players. If we're rewarding with a virtual item (money, or points, or w/e for example), sure, it shouldn't matter too much when you run the commands. However, we still need to consider the possibility of rewarding physical items
Take this, for example. What if you want to give a crate key to a player after dying? Running the commands before would be problematic, since the MobArena clears your arena items, and restores back the pre-arena items. Meaning, you'd likely get the key while you're in the arena, then proceed to lose it when the arena gives you back the old items. I think what would make the most sense in this case is to run the commands after the inventory clear and restore steps. This mainly applies to On Leave and On Death
For the On Start, perhaps we can branch it out a bit? To be more specific, we can make it split into On Lobby Start and On Arena Start. The lobby start commands run when the first player joins the lobby and the countdown starts. I personally don't see any good use for this, the only thing I can think of would be some sort of notification that the arena is being queued now. So imo, we can just skip this and do the On Arena Start, which essentially runs after the players are teleported to their arena warps.
As for On End, I'd also suggest we branch this one to Before End and After End, which are self-explanatory. One runs before rolling back the arena, and the other runs after.
I dug around a bit in the recommended workarounds, and I seem to have gotten somewhere with worldguard regions. We should be able to recreate some of these event hooks with some really hacky worldguard flags. First, download and install worldguard and WorldGuardExtraFlags(https://www.spigotmc.org/resources/4823/).
Here's a small guide to replicate some of the events:
On Join: Define a worldguard region around your lobby area (or the entire arena), do /rg flags
while in the region, scroll to page 6, and set your console-command-on-entry
. This will mimic the event just fine, as long as you make sure that they can only enter it once (which is when the arena starts). This is to prevent your players running out of the region, then walking back in and triggering the command.
On Leave: Same as above, just set the console-command-on-exit
flag instead! Make sure you also encompass the entire arena!
On Death: This one is a little tricky, you have to make a sub-region where your fighting happens, and then set the spectator spawn slightly above the sub-region border. Now just set your console-command-on-exit
flag and that should work fine. An issue here would be if you don't have spectator mode on. That means it will run both On Leave and On Death. If you do /ma leave, it will also run both commands, and sadly there isn't much to do about that.
On Start: Simply make a region where your player spawnpoint is, and make sure they can't get to it again, to avoid running and going back in. This again could be a little tricky if your player spawn is in the middle of your fighting ground
On End: This will also sadly blur in with the On Death and On Leave events, and there's not much we can do about that.
The following is a breakdown of the procedures for each of the mentioned events. As evident from the wall of text, there's a lot of stuff going on, but that doesn't mean we can't find a good spot (or spots) for commands to be executed.
The join procedure basically stores the player state, moves them to the lobby, and "resets" everything in various ways.
Some "clearing" happens on player death, but most of the "logistics" can't happen during the death screen and so has to wait for the respawn.
keep-exp: true
, current experience is added as an Experience Thing reward.When a player respawns, they have to be "reset" and either sent to the spectator area or "kicked".
spectate-on-death: false
, the Player leave procedure is executed in the next tick.The leave procedure is basically the inverse of the join procedure, as it uses the same "steps" list, but in reverse. However, it does a lot of "cleanup" from class selection and such as well.
Note that the order of the teleporting and the game mode changing is pretty important, as multi-world inventory plugins tend to "do stuff" on those events.
A lot of stuff happens when the arena starts, and like with the join/leave process, the order does matter quite a bit, even though it might seem a little arbitrary.
When the arena ends, players will have already left or died (players are "kicked" on the final wave, if set), so the cleanup is mostly non-player stuff.
Take this, for example. What if you want to give a crate key to a player after dying? Running the commands before would be problematic, since the MobArena clears your arena items, and restores back the pre-arena items. Meaning, you'd likely get the key while you're in the arena, then proceed to lose it when the arena gives you back the old items. I think what would make the most sense in this case is to run the commands after the inventory clear and restore steps. This mainly applies to On Leave and On Death
This is perhaps not the greatest example, since rewards should be added as actual rewards to hook into the reward granting portion of the leave procedure. This can be done with MobArena's /ma addreward
command, but it would have to happen quite early in the leave/death procedures, because you can only add rewards to players that are "part of" an arena that is also in the "running" state.
I guess it's just two different ways to solve the same problem, which is fine. The more I think about it, the more I think we need to have both before- and after-hooks on most of these events, but where exactly is still unclear. It would be good with concrete examples showing the necessity of each hook, just to have something to work towards.
We've already checked off the player join command location. It should be after the entire procedure ended, I.E step 16. I don't see a need for a before hook, but if we really want to, we can put it as step 5 or 6. Again, this isn't needed at all, and I can't think of any good uses to have a before hook.
PlayerDeath: This one could be executed after step 5, I.E when the player is no longer part of the arena. It can also fit after step 7? Not too sure about this one.
PlayerRespawn: This can have two hooks, maybe? One executes after step 3, the other executes after step 4. Reasoning behind this is if you want to give something to the spectators, you'd use the first hook. But then again if the second hook executes as a new step 5, it might mess with the leave procedure, so perhaps we could only have one hook that happens after step 3, and the rest can be part of the PlayerLeave procedure. As for examples on what items you could give to spectators, probably items to open GUIS that either let you exit the arena, join the next running arena, get a list of arenas etc.
PlayerLeave: This one's a little tricky. I'm not a 100% sure myself, but I'd say somewhere along the lines of step 18? Like, straight after the players are teleported to the join location (or the exit warp), since that's when the player's state is the most stable.
ArenaStart: I think this one can be after step 7. Or maybe even part of step 7. Maybe right after they're teleported to the arena warp? So after step i. We can add another hook that runs after step 16, too.
ArenaEnd: This one can happen after step 7 (again), or step 8/9. If we want to add another hook, then I think it should be after step 12 or 13
So! I was digging around recently and I found another plugin that can help accomplish exactly this sort of stuff. You can basically listen to events from any other plugin, extract any 'local' placeholders from it (using the event directly!), then execute any commands needed for any use cases. So, no more hacky worldguard regions are needed or that much coding experience!
The plugin is ConditionalEvents, and you can use the Custom Events guide to make the mobarena ones. Of course this isn't a final solution and it would still probably be better to have stuff like that natively supported inside MobArena, but I figured I'd update the issue here for any future viewers looking to do something similar! Here's a quick example that I made and tested and it works perfectly fine:
event1:
type: custom
custom_event_data:
event: com.garbagemule.MobArena.events.ArenaPlayerJoinEvent
player_variable: getPlayer()
variables_to_capture:
- '%arena_name%;getArena().getSlug()'
actions:
default:
- 'message: &cThis is a test message! You joined %arena_name%'
- 'playsound: %player%;NOTE_PLING;10;0.1'
edit: Added an example
Feature request
Short description
This is an expansion to issue #598 , with more features to properly flesh out this idea. To keep it simple just send a console command whenever certain events happen. Some basic ones could be: playerJoin, playerLeave, playerDeath, arenaStart, and arenaEnd. This allows us to have more flexibility by integrating some aspects of MobArena with other plugins without needing to use a third-party software, such as skript.
Implementation details
It'll be a simple node for each arena, which allows multiple commands that the plugin can loop through until they're all executed. The commands should be executed as a final step, in order not to mess up with any of MobArena's internal steps. Something like this, for more clarification: