This commit is a full sweep across the WaveParser. It introduces the ConfigError exception to the WaveParser and throws it whenever something isn't right. There's quite a lot of stuff going on, but in overall:
- Errors are thrown rather than null values being returned
- Defaults are picked in lieu of explicit values when they "make sense"
- Most list-type values can now be either the default comma-separated string or a string list
Common nodes:
- Spawnpoints can now be a string list
Default waves:
- Missing or empty monsters map throws an error
- Missing wave growth defaults to medium
- Invalid wave growth throws an error
Special waves:
- Missing or empty monsters map throws an error
Swarm waves:
- Missing or empty monster node throws an error
- Missing swarm amount defaults to low
- Invalid swarm amount throws an error
Supply waves:
- Missing or empty monsters map throws an error
- Missing or empty drops node throws an error
- Invalid drop throws an error
- Drops can now be a string list
Upgrade waves:
- Missing or empty upgrades map throws an error
Boss waves:
- Missing or empty monster node throws an error
- Missing or empty boss health defaults to medium
- Invalid boss health throws an error
- Invalid ability throws an error
- Invalid drop throws an error
- Abilities and drops can now be string lists
This commit changes how the ThingParser is used throughout the code base. Instead of blindly filtering out null values, we're now throwing a new InvalidThingInputString exception. This exception is caught in an outer scope that has more context. The exception is then unwrapped and rethrown as a ConfigError with the additional context. In the outermost scope of (re)loading the config-file, the ConfigError is caught and printed, and then (re)loading stops gracefully.
We still need a proper way to handle loads/reloads consistently to get rid of the default command usage message, but this is a good step towards better usability in the face of user errors.
Fixes#478
This commit adds a new per-arena setting, join-interrupt-timer, which, when set to a positive number, will introduce a delay to the join and spec commands. During this delay, if the player takes damage or moves more than one block's distance, the command will be interrupted.
Closes#482
This commit adds a new per-arena config-file setting, next-wave-delay. When a new wave is about to spawn, a positive next-wave-delay value will cause the spawning of the wave to be delayed by that amount of seconds, similar to how first-wave-delay delays the spawning of the first wave.
By moving all of the actual spawning logic into a new method and simply referencing that as a Runnable, we can avoid having to set weird boolean flags and re-scheduling the MASpawnThread itself.
Closes#449
The autogenerated arenas are backed up in a file that isn't valid in 1.13. It's also buggy, inducing a false sense of safety. Instead of trying to hack it together for 1.13, let's remove it and see if we can't live without it.
This semi-reverts part of the change in e484583b7e.
We're now specifically denying the use of items if there are any. This doesn't cancel the interact event, but just prevents stuff like potion consumption.
The block fade event is called when a block fades from one state to another, such as when snow melts and becomes air, or ice melts and becomes water. Cancelling it solves the issue of snow and ice melting in arenas.
Fixes#249.
Originally, the right click ban was introduced to prevent issues with people blowing themselves and each other up in the lobby. The right click ban only solves this issue sometimes, so it isn't really very effective.
By removing the right click ban, it becomes possible to activate redstone stuff like buttons and levers in the lobby.
Fixes#431.
The flag is almost always set to true, and when it isn't, it's either because people don't know that they have to set it, or because they only give one upgrade per class and thus don't feel the effect of it.
This is not the proper way to solve this issue, but the refactoring needed to move the responsibility of class chest search somewhere else is a bit too much for a bug hunt.
This introduces state in the ScoreboardManager for keeping track of the scoreboards that players have before the arena session starts, if any. Upon leaving, the scoreboards are restored.
Ideally, this change should be re-implemented as a Step of the join/leave process, but that would require opening up Arena or ScoreboardManager in ways that would probably be best handled in a rewrite of the scoreboards, so we'll leave it in ScoreboardManager for now.
Fixes#366
A new section in global-settings called pet-items is used to define pet item transformation items. By default, bones are transformed into wolves, but the item type can now be changed to support using actual bones in classes.
This refactors the pet spawning into its own class to reduce some of the massive responsibility of ArenaImpl.
This closes#467
In this commit, the ItemParser's behavior changes from one that requires or encourages numeric IDs for everything to one that discourages it by logging a warning that suggests using a string instead of a numeric value.
While this doesn't actually make things that much better for updating to Minecraft 1.13, the "ID nagging" hopefully increases awareness about the upcoming breaking changes.
Fixes#382
This follows from the removal of the set class command being removed and the cascading removal of the methods in ArenaMasterImpl that referenced the parseString methods in ItemParser.
Similar to a88556771f.
This specific change may stir the pot a bit, since some people may rely on the set command. However, class chests solve a lot of the problems that the initial command set out to tackle, and we can probably do better in a rewrite of the command if it's missed anyway.
The removed commands render a few methods in ArenaMaster obsolete.
These commands solve a very, very specific problem that it's safe to assume nobody has. It's safe to assume that most config editing happens in the actual config-file, and changing class permissions is probably one of the last things people would expect to find a command for.
Removing these commands renders some methods in ArenaMaster and ArenaClass obsolete.
Instead of the obscure error thrown from ArenaClass when the SHIELD enum value on Material isn't found, MobArena throws its own, more human-friendly error.
Fixes#469
When the arena ends, the MonsterManager is cleared, which means that all references to health bars are lost. Before this, we remove all players from any boss bars to make sure that the boss bars don't stick to players upon dying.
Fixes#473
This changes the upgrade waves from the local Upgrade interface to the Thing interface. This means that all Things can now be used in upgrade waves, including commands, money, potion effects, and permissions.
Unfortunately, the weapons upgrade/replace functionality has been gutted as a result of the Things API not supporting it. We could add it back in later down the road, but for now let's just see if it causes anyone any inconvenience.
Closes#468
This replaces the Map<String, Boolean> approach in ArenaClass with a List<Thing> approach. This greatly simplifies how per-class permissions are handled.
This commit introduces the PermissionThing and associated parser. The parser determines the value (grant/revoke) of the permission by looking at the first character of the input string - if it is a minus (-) or caret (^), the value is false (revoke), otherwise it is true (grant). To distinguish permissions from other things, the parser requires a prefix of "perm:".
This removes the map of attachments in ArenaImpl and makes the permissions "replacement" happen via the Bukkit API's PermissionAttachmentInfo. Bukkit already keeps track of which attachments we've added to a player, so removing them is just a matter of looping through and finding those. This reduces the coupling between the Arena interface and UpgradeWave (which is the only interface that used the methods removed from the Arena interface).
The goal with these specific metrics is to figure out if some of the arena settings can be removed. If everyone uses the same values for these settings, there is no point in having the added complexity in the code.
Three different types of health bars are implemented behind a basic Strategy Pattern. A new per-arena setting, boss-health-bar, can be used to configure which one of the three types (if any) of health bar should be used for bosses in the given arena:
- `boss-bar` creates a boss bar at the top of the screen as if the players were fighting an ender dragon or a wither.
- `title` uses the Chapters/Titles API in Bukkit to display the health of the boss as a "subtitle" whenever it takes damage.
- `name` sets the entitiy's health along with an optional custom name above the entity's head.
The announcements file loading method is renamed to indicate that it's also meant for re-loading, and the access modifier is changed from private to package-private to allow ArenaMasterImpl to call it.
Closes#462
This commit introduces the PotionEffectThing and associated parser. The parser simply delegates to the existing PotionEffectParser utility class the same way the ItemStackThing parser does it. To distinguish potion effects from other things, the parser requires a prefix of "effect:".
As with the initial Thing API commit, this commit also adds an overload to the existing parser class to avoid spamming the console with meaningless warnings.
Boss waves already support potion effects, but with this commit, the potions node moves up as a common node, so all waves that spawn monsters (all but upgrade waves) can now spawn those monsters with a list of potion effects applied to them. It's not possible to give certain potion effects to specific monster types. All monsters get all the effects listed in the node.
Because we aren't actually giving potions but potion effects, the node is renamed from "potions" to "effects". However, to preserve backwards compatibility, both names are supported in this commit.
Closes#453
The ability to execute commands by hitting signs is already implemented by other plugins, but by creating built-in support for such signs, it's possible to leverage information about the plugin and its current state. This implementation allows for displaying live information about player counts, waves, etc. on the signs in addition to tying actions to them.
Customizable templates defined in the new signs.yml config-file can be bound to signs during the in-game sign creation, and users can define state-specific templates that change based on whether an arena is completely idle, has players in the lobby, or is running and in full swing.
Sign data is stored in data/signs.data as a YAML-formatted file that shouldn't be modified directly, effectively separating configuration (templates in signs.yml) and data (coordinates and parameters in signs.data).
Closes#385
This commit makes it possible for mounted players to dismount. Upon dismounting, the horse AI is set to false to prevent it from moving around. Players attempting to mount an available horse will be thrown off unless they actually own the horse. The owners are free to remount when they want.
Metrics will greatly help the development process in terms of finding out which server versions people are running, as well as which features they are using. For now, we check to see how widespread Vault is, and how many arenas and classes people have.
Advanced bar charts are, at the time of this commit, not supported in the bStats dashboard. When they are supported again, we can look into usage statistics for specific settings and features.
Changes the "Vault was not found" message in Vault setup to INFO instead of WARNING, because this configuration isn't actually necessarily a warning sign. Parsing a money thing with no economy is, however. MoneyThingParser logs at ERROR level if Vault or an economy plugin isn't found, but a money thing is parsed.
This also swaps out the dependency on mockito-all with mockito-core, which is actually maintained. The purpose of updating is to allow for new Mockito features, such as mocking final methods, which happens due to the test resource org.mockito.plugins.MockMaker.
It turns out that the method reference on MobArena#getEconomy() in ThingManager is a tight enough dependency on Vault's Economy interface that it results in a NoClassDefFoundError if Vault isn't present.
By resorting to a more "naive" approach of resolving the Economy instance from the main plugin class on every parse call in MoneyThingParser, the NoClassDefFoundError is avoided along with the load/enable ordering issue that was fixed with the lazy-fetching in commit 2fcb20b2ae.
This reverts 2fcb20b2ae and partly 4c34a183c7.
Fixes#463
If the arena has already started, there is no reason why a leaver should have a refund. It's also a douchey move because your buddies in the arena will have a harder time after you leave them for dead.
This moves the refunding of the entry fee to after the join/leave process for the player has been rolled back, i.e. after the inventory is restored. Before this change, the refund would happen before restoring the player's inventory, which resulted in the refund getting overwritten.
This was mainly left in for debugging purposes, but it creates a bit too much spam that isn't really informative or helpful in any way, since the exception reveals the failed step anyway.
This commit swaps out the naive call to takeFee with a more robust approach that actually checks the result. If it fails, the player doesn't join.
It also refactors takeFee so that it will refund any already taken parts of the entry fee if one of the parts fails.
The eager loading results in nothing but nulls because ThingManager (and, by proxy, MoneyThingParser) is instantiated on load, while the Economy provider from Vault is fetched on enable.
The bug was introduced with 4c34a183c7.
This fixes#451
MobArena has been on version 0.9x for so long that it just never was an issue that the version string was unquoted until now. Because SnakeYAML parses the string as a number, 0.100 becomes 0.1, which means the version string gets parsed into a 0 and a 1, which is less than 0 and 99 (previous version).
This should fix that problem for good.
This commit adds two new announcements for use in boss waves:
- wave-boss-killed to announce who killed the boss
- wave-boss-reward-earned to notify the killer of the boss reward, if any
Fixes#428
Historically, we've seen plugins try to "auto-correct" the falling-through-the-world bug in Minecraft when chunks load too slowly. The plugins often solve this by force-warping until the player is stable, and blocking those teleport events are going to cause heavy "not allowed" spam.
Note that this commit makes breaking changes to the Arena interface and completely changes the responsibility of the InventoryManager.
The join/leave process is replaced with an implementation of the Command Pattern, where every step of the process (e.g. teleport to lobby, change gamemode to survival, reset health, etc.) is realized as an implementation of the new Step interface, which has "run" and "undo" operations. The "run" operation takes a snapshot of a specific part of the player's state and then resets it. The "undo" operation restores the snapshot.
Step groupings are arranged in two factory classes, PlayerJoinArena and PlayerSpecArena, which realize, respectively, the join and spectate processes. Each instance of ArenaImpl instantiates groupings for its own context, and a grouping is invoked as one unit when a player joins or spectates an arena, and rolled back when a player leaves.
As a result of a more stringent process, some things are now a little different than before:
- Setting spectate-on-death to true effectively results in /ma leave followed by /ma spec. This makes the player/arena state a little more predictable and well-defined.
- Using exit warps will result in the player leaving to their entry point and then being teleported to the exit warp. This means the exit warp doesn't have any effect on the rest of the restoration process, as it effectively happens "post leave".
This finally fixes#423.
This makes commands case insensitive, e.g. /ma join. Note that arenas with the same name but different casing are considered the same arena, and one of them will be ignored during config-file parsing.
It turns out that the Inventory#removeItem(ItemStack) method doesn't actually work for items held in the offhand. This commit changes the behavior so it simply decrements the ItemStack amount for the item held during the block place. Note that going from 1 to 0 will result in an air stack, which will just disappear from the inventory.
Fixes#429
Replaces the hideous StringBuilder code with a normal String, and the BufferedReader with a basic Java NIO readAllLines(), which also takes care of the eye sore that is the finally clause with a nested try-catch.
This means that MoneyThingParser now needs to pass along an Economy instance instead of a MobArena instance, which makes the dependency a little more focused and reasonable.
Also adds MoneyThingParser tests.
Originally, the permissions checking was implemented with a dependency on various permissions plugins, but since the introduction of SuperPerms, it hasn't been needed, and this residue is safe to remove.
Removes the dynamic registration of permissions for classes and arenas.
This means that it is no longer enough to just check whether a Player.hasPermission("mobarena.classes.Knight"), but we also need to check if the Player.isPermissionSet("mobarena.classes.Knight"), which it won't be by default.
To make the stringly typed parts of this dynamic permissions checking more focused, ArenaClass and Arena now both have hasPermission(Player) methods, so the actual permissions checking happens on the objects themselves, rather than from the caller of these methods.
The /back command in Essentials - and similar commands from other plugins that allow you to warp back to your location of death - makes it possible to re-enter the arena after dying.
This commit builds upon the "leaving players" of commit 02f75d0e7f and introduces a more general notion of players being "moved". The arena is "moving" a player if the player is being teleported somewhere by MobArena (to any arena warp), and in this case, all teleports of a player are permitted. This takes care of the cases where MobArena "might be doing it". The rest of the cases are due to commands, plugins, ender pearls, etc., and they are a little easier to deal with separately. The new logic is more straightforward and should prevent most exploits and permit most legit warp cases.
This (hopefully) fixes#313.
Swaps out the hard dependecy on ItemStack for class armor, such that the ThingManager - and thus every ThingParser registered within - has a chance at providing "armor" for a class.
To distinguish armor from items, ArenaMasterImpl prepends "armor:" or slot-specific prefixes to these values before passing them to the ThingManager. This makes it possible to distinguish between items and armor on the thing parser end if applicable - it doesn't make sense for money and command parsers, but they will just end up skipping these values.
The ItemStackThingParser is given a bit of an overhaul. It now depends internally on ItemStack parsers, which can be registered via the ThingManager. This allows custom plugins to hook into the ItemStack-specific part of the ItemStackThingParser to avoid having to duplicate code. Plugins that just want to provide ItemStacks can use this parser approach, and plugins that want to provide more abstract Things can use the Thing parser approach.
Swaps out the hard dependecy on ItemStack for class items (not armor), such that the ThingManager - and thus every ThingParser registered within - has a chance at providing "items" for a class.
Armor is not handled in this commit, because it appears to be quite a bit of extra work, and the "equippable" nature of armor needs to be handled differently than regular inventory items.
The getLogo() method on ArenaClass is removed, because it is no longer used (internally at least). It is residue from the old Spout support.
Turns out that a player who disconnects while in the arena is actually still online if you ask the Player object. The setScoreboard() javadoc specifically says it throws an IllegalStateException in that case, so we can just catch and swallow it.
It's unclear what the state of the player's scoreboard is when they rejoin the server, but a borken scoreboard is better than a rogue exception.
This commit removes certain items from the in-arena inventories of players who choose the "My Items" class:
- Ender chests allow players to smuggle stuff out of arenas
- Ender pearls can be used to warp to unintended spots, and to build ender chests
- Shulker boxes can carry any items - including ender chests
- Shulker shells can be used to build shulker boxes
At the end of the day, ender chests are the bad seed. The rest are just to prevent ender chests from making appearances.
Apparently, the /give command will drop an item "as" the target player, resulting in the player picking up the item if there is room in their inventory. This triggers a PlayerDropItemEvent, which MobArena catches and tries to cancel if the target player is in an arena. Furthermore, if the player is a spectator outside of the arena region, MobArena will force the player to leave the arena. This triggers the reward granting logic, so using the /give command as a reward has the potential of causing an infinite loop.
This commit introduces the idea of "leaving players", i.e. players in the process of leaving the arena. In the event of a dropped item from a player who is currently leaving an arena, the PlayerDropItemEvent is ignored, because it is assumed to be from the /give command. Note that this doesn't actually prevent normal PlayerDropItemEvents from causing a forced leave, since the player won't be in the process of leaving at that specific point.
This commit changes the naive behavior of the ConfigUtils methods addIfEmpty() and addMissingRemoveObsolete(). Instead of an almost guaranteed config-file write on every invocation of either method, writes only happen if the loaded configuration changes. The excessive writes result in long config reload times, and this change fixes that, effectively fixing the second part of #435.
To further the performance boost, the resource reads are cached in a map - this turns out to not be an issue for server plugin reloads, as a new ClassLoader instance is used to load the new set of plugins.
This means that the cleanup code will only run if there are players in the lobby, arena, or spectator area. This fixes the first part of #435 where the cleanup code is taking too long for large/many arenas.
Originally, the force end command was meant as a way to circumvent any condition keeping players from leaving the arena and cleaning it up. In retrospect, the main reason for using force end is to "get people out of there", but since there's plenty of stuff that can go wrong when a player leaves, this isn't really that helpful, as exceptions will just cause the command to break at the same point anyway.
Use ItemStack display name in ItemStackThing (if available).
This means that named items will appear in the rewards list with their name rather than the ItemStack type. This is useful for "tokens" type items.
Note that named items are still not supported by the built-in item parser, so this commit only affects ItemStackThings created by custom parsers (for now).
With CommandThing and its parser, it is now possible to use commands anywhere a thing can be used. Commands are invoked as the console/server, and they support a single variable, the name of the recipient player.
Commands are give-only, meaning they will fail to be "taken" from players, and they cannot be "held" either. The idea of commands as things basically only makes sense in the context of rewards.
While it doesn't really make sense to have class prices be a Thing (or maybe it does?), this does get rid of the dirty "ItemStacks wit ID -29" hack for economy money, which will eventually break, when the upstream int-based ID API breaks.
With this commit, the Things API is introduced to the code base, but it is not yet used. It introduces the building blocks for an extensible architecture that supports custom parsers and custom "things". This should allow other developers simple, yet powerful hooks into the way MobArena handles class "equipment" and rewards. The basic skeleton includes parsers for ItemStacks and economy money, so it should be interchangeable with the current inner workings of the plugin.
The commit also adds an overload to the ItemParser that allows for a the method to fail silently. This is necessary to avoid false negatives in the log in case the ItemStackThingParser fails but a different parser succeeds.
Since the announce() methods always required an Arena argument, and since the Messenger instance used was always acquired from an Arena instance, there really was no reason for the methods to exist on Messenger.
- Messenger no longer has a static nature and must be instantiated to be used. The prefix is provided in the constructor.
- MobArena instantiates a global Messenger in onEnable() with a prefix string from global-settings. This instance is used by anything that isn't arena-specific, as well as for arenas with no prefix.
- ArenaImpl instantiates a local Messenger in its constructor if, and only if, its arena-specific prefix setting is non-empty. Otherwise it uses the plugin's global instance.
This removes the logging capabilities from Messenger and replaces all references to them with proper logging via Bukkit's PluginLogger that all plugins have.
The blockList() call returns the actual List<Block> object in the explode event, which means it'll be shared between the the fake event and the original event. As a result, the call to blockList().clear() will clear the shared list, and the following call to blockList().addAll(fake.blockList()) results in trying to add the empty list to itself.
This commit makes sure to copy the original event's block list before sending it to the fake event.
Okay, "Fixes" would be lying, and that's terrible, but here's something to help you shrug it off: The timer module is a bit of a mess, and since there isn't actually anything "dangerous" about this, let's just calm our tits and focus on other stuff.
Before, these redundant calls didn't really do anything. Now they mess everything up, because setContents() doesn't set inventory contents only, but the entire inventory instead, because that's so super useful. Well done, boys!
#notsalty
Because it is clearly impossible to change JavaDocs to correctly describe what a method does, the method setContents() has now been changed to a useless, over-aggressive, inventory-wiping piece of junk that must be invoked before anything else. This commit ensures that armor contents are set after the setContents() method is called, overwriting the nulls that the setContents() method creates.
This changes the format from:
<effect>:<duration>:<amplifier>
to a (pressumably) more user-friendly format of:
<effect>:<amplifier>:<duration>
The reason for this swap is that the duration is more likely to be
wanted left at default than the amplifier. From previous user input
on the matter, it sounds like users generally want the bosses to have
"permanent" or "infinite duration" effects, and this change makes it
a little easier on them, not having to specify a duration.
With this feature you can add potions to the bosses when they spawn,
adding the ability to add strength to the boss for the first 30 seconds
making it harder for the first few seconds and once the effect wears
goes away the boss becomes easier. The syntax is in the same style as
potion items, except it uses either the potion effect enum name or the
potion effect id.
POTION_EFFECT:duration in seconds:amplifer
SLOW:360:4;INVISIBILITY:36000:0
If no duration is given, the plugin will default to sixty seconds. If
the amplifer was not provided, the plugin will default to zero. The
potion effect amplifcation starts at 0 being level 1.
Some of the config-file resets were fixed in a previous commit:
4330885d46
The resets fixed previously were ones where snakeyaml would throw a fit
due to tabs. Because an exception is thrown, the call to saveConfig()
is never reached, which means the config-file is never reset.
However, errors resulting from other illegal characters were not caught
because the built-in reloadConfig() method catches, prints and then
simply does nothing about any exceptions thrown, which means the actual
YamlConfiguration would be empty. Saving this empty file would result
in a reset, because MobArena, during initialization, sees missing bits
and pieces and tries to insert them. Thus, the resets were not an issue
with MobArena's attempt to keep the config-file tidy, but the reckless
handling of errors in the built-in config methods in JavaPlugin.
This commit completely overrides the methods in JavaPlugin that would
result in these resets, and the MobArena plugin class stores its own
reference to the config file and an associated FileConfiguration. When
the reloadConfig() and saveConfig() methods are called, the checked
exceptions are caught and rethrown as unchecked exceptions, causing the
plugin to crash when it needs to do so.
This commit creates a fail-fast exception-throwing guard inside the
method for handling config-reloading in the main plugin class.
If a config-file contains a tab, an exception will be thrown when
the plugin loads (as it did before), which means the plugin will not
load correctly. However, upon reloading with the reload command, an
exception is thrown before the current settings are overwritten.
This fixes a long-standing issue with config-files resetting upon
reload with invalid syntax. Verification is needed, as this commit
has only been tested on OS X where tabs and carriage returns are
injected via vim.
Due to the start-delay-timer holding a reference to the
auto-start-timer as its internal callback, the start-delay-timer
should be stopped, when both timers should be stopped.
The StartDelayTimer wraps the AutoStartTimer and provides a means of
"locking" the lobby until a configurable time has passed. During this
time, it is possible for other players to join the lobby and ready up,
but the arena will not start until the StartDelayTimer has run out,
after which the AutoStartTimer is started (if applicable).
New per-arena setting: start-delay-timer: [seconds]
New announcement: arena-start-delay
This framework consists of interfaces and classes for managing various
kinds of timers. The Timer interface models a timer with configurable
tick intervals. The TimerCallback interface provides a means of adding
logic to the following timer events: onStart, onStop, onFinish and
onTick.
Timer implementations include a CountdownTimer (kitchen timer), and a
StopwatchTimer, which should both be self-explanatory.
The purpose of this framework is to add a means of creating a very
generalized approach to timers, in hopes of abstracting away some of
the Bukkit scheduling for easy maintenance and increased portability.
Future work:
- Port auto-start-timer
- Port boss abilities
- Port spawner
- Create 'delay-timer' as per DBO ticket request.
- Create various types of cooldowns, delays, etc.
When the WaveManager is queried for the next wave to be spawned via
the next() method, it now returns a copy of the wave instead of the
wave itself. This is because waves (boss waves in particular) have
state, and this state is transferred to the next occurrence of the
given wave. This caused recurrent boss waves to inconsistently share
state, which resulted in the BossAbilityThread bailing early after
the first occurrence of the boss wave it belonged to. By copying
the initial wave state in the WaveManager, the issue is fixed.
Fixes: http://dev.bukkit.org/bukkit-plugins/mobarena/tickets/1220/
This is necessary to ensure a robust /ma spec command. If no spectator
warp is set, the command will throw an NPE - it is much more safe and
sane to require the warp.
The items-node in the classes section now supports list values instead
of strictly string-values. This should make it easier to see exactly
which items a class has, and it should alleviate some of the problems
associated with apostrophes and such. The string-valued setup is still
supported to preserve some backwards compatibility.
The armor-node remains untouched, but it will probably be updated to
the same system later.
The notion of a "selected arena" disappears with this commit. All
commands that previously did not require an arena name in the case
of multiple arenas now do, i.e. it is no longer possible to "set"
an arena to be the target of commands. This should not be an issue,
however, since Setup Mode replaces all the commands that previously
were the main reason for the notion of a selected arena.
The /ma setup <arena> command is the first step in the process of
making the setup procedure more intuitive. The command consists of
the actual command handling, as well as a multi-role inner class,
and together they constitute Setup Mode.
- Toolbox; a set of tools are provided to the user, and a handler
for the interact event will react to the usage of these tools,
providing the primary, interactive element of Setup Mode. The
tools are used to set regions, warps and points.
- Text input; by typing 'exp', the user can expand a given region
in the typical directions (up, down, out), and by typing 'show',
the user can request red wool blocks to be displayed in place of
region frames, warps and points.
Whilst in Setup Mode, the user cannot type any commands, because
the input is intercepted due to the Conversations API - this is
by design, and may prevent some inconsistencies.
The next step in the process will be to fully remove the commands
that Setup Mode renders obsolete. The commands include, but are
not limited to:
- set(lobby)region
- expand(lobby)region
- setwarp
- addspawn
- delspawn
- addchest
- delchest