Commit Graph
100 Commits
Author SHA1 Message Date
Andreas Troelsen 78f5dc0545 Add tiers wave reward section.
This commit introduces a new optional wave rewards section, `tiers`,
which allows server owners to configure rewards that "upgrade" over
time. This makes it possible to create reward configurations where
(some of) the rewards don't stack as the waves progress, but instead
change into different rewards. The most obvious use case is wanting to
grant an armor set for beating a specific wave, but a _better_ set for
beating a later wave, without granting both sets.

Turns out this was a lot easier than I thought it would be. We didn't
even need a rework of anything, and the Things API didn't even need to
adapt in any way. As an added bonus, we managed to get the associated
GitHub issue wrapped up before it turned 8 years old. Neat!

Closes #346
2024-10-06 12:42:09 +02:00
Andreas Troelsen 0527f116e2 Refactor Vault economy integration.
This commit reworks how MobArena interfaces with Vault economy provider
instances. Instead of affixing an Economy _instance_ to the main plugin
at "setup time", we create an instance of the new _Finance_ abstraction
at "(re)load time", and then use this new abstraction at every call site
(really just the MoneyThing) instead of Economy. This accomplishes two
important things:

1. Due to how the Bukkit load order works and how Vault providers are
registered with the plugin, the Finance abstraction gives us a means of
deferring the retrieval of the Economy provider needed to integrate with
the underlying economy plugin (or script). MobArena still uses Finance
as if it was a "complete" object and is completely unaware of what goes
on under the hodd. This is a much more elegant solution compared to the
terrible past proposals of fragmenting MobArena's bootstrapping phase,
especially considering the past proposals were server tick-centric...

2. It creates a simple and maintainable interface between MobArena and
Vault, effectively giving control back to MobArena as to how everything
should mesh together.

The biggest downside to this solution is that we no longer know if an
economy provider is available for when we need it at a convenient time
in the startup process. Instead, we need to react accordingly when an
economy operation is invoked. The implementation takes a somewhat mild
approach by simply _logging_ any issues encountered and defaulting to
"best effort" operations when an economy provider is not available. At
worst, this is a bunch of log spam and potentially a lot of work for
server owners to clean up after (compensating players for rewards and
stuff like that), but MobArena doesn't handle arbitrary exceptions in
its join/leave and start/end procedures very well, so it's probably a
better way to go about it than throwing exceptions.

If the server does not have Vault installed, an UnsupportedFinance is
created. This implementation just logs errors and "fails to work" on
every operation. If Vault is installed, a VaultFinance is created, and
this implementation should only log errors if a Vault economy provider
couldn't be found. We could have opted for a single implementation, but
this approach allows us to potentially support other economy registrars
in the future, so we (probably) won't have to make sweeping changes in
order to swap to something else.

Closes #797
2024-09-15 20:28:10 +02:00
Andreas Troelsen 9679f4b2f7 Remove Vault metric.
We might want to track which economy provider people are using, but
tracking just "uses Vault" is not particularly helpful.
2024-09-15 20:28:10 +02:00
Andreas Troelsen 7694872ebc Allow arena signs to be broken while sneaking.
This commit "fixes" the problem introduced in the "no sign edits" commit
by not invoking the sign actions for interact events where the player is
sneaking. This is not the ideal way to go about it, but since we need to
bump the Spigot API version to access the sign change event that would
fix the underlying issue, this will have to do for now.

Fixes #791
2024-08-20 23:44:57 +02:00
Andreas Troelsen a33f0164b6 Fix arena sign event handler priority.
The previous change to this class introduced a _mutating_ method call,
which would be fine if it wasn't for the fact that the handler listened
on `MONITOR` priority prior to this commit. But no more! We're knocking
it down a notch to better comply with event handler best practices.

While this change doesn't _fix_ #787, it does allow @molor to implement
a hackaround that should keep things in check until we can bump up to a
later API version and use the new sign edit event to fix this particular
issue the right way.
2024-07-23 03:58:46 +02:00
Andreas Troelsen 110076f83e Don't truncate text on arena signs.
Turns out this isn't necessary at all. I think the server used to throw
an exception if there were too many characters on a sign, but it doesn't
seem to be the case anymore (tested on 1.21 and 1.13.2).

This commit simply removes the truncation logic from the sign rendering
procedure, and it fixes issues where text that would otherwise fit on a
sign would be cut off, but more specifically one where color codes would
sort of "push" characters out of the sign despite not being visible.

Fixes #790
2024-08-18 15:07:48 +02:00
Andreas Troelsen c5802faefc Refactor obsidian-bomb explosions.
This commit changes the "source" of the explosions from `obsidian-bomb`
to _something_ that isn't the boss itself. Originally, these explosions
were block explosions, but without a "source" from the damage caused to
other mobs, the `monster-infight` flag was largely ignored. By switching
to "entity explosions" with the boss as the "source", the flag was now
respected, and mobs would no longer take damage from these explosions if
the `monster-infight` flag was set to `false`.

However, the handler for "entity explosions" now started reacting to the
explosions caused by the `obsidian-bomb` ability as if they were normal
entity explosions, e.g. those caused by creepers, and because entities
that explode usually "die" (although without an EntityDeathEvent), the
handler removes the entity from the monster manager, which effectively
"unregisters" the boss, leaving the entity itself just hanging around in
the arena as a normal mob (with a huge health pool).

The "obvious" solution is to change back to "block explosions", and that
could perhaps have worked if the API had consistent interplay between an
"explode event" and the resulting "damage event". It turns out that the
EntityExplodeEvent results in an EntityDamageByEntityEvent, and the same
can be said for BlockExplodeEvent and EntityDamageByBlockEvent, except
the latter will have a `null` block in it, so even if we were to attach
some metadata to the block, we wouldn't be able to retrieve it in the
damage handler. So we're sticking with "entity explosions"...

The hacky solution: We just spawn a new entity and pin the explosion on
it instead of the boss. That way the new entity is removed by the entity
explosion handler (which is a no-op, because the entity isn't an arena
monster) instead of the boss. It technically doesn't matter which entity
we spawn, but by spawning a primed TNT block, we can naturally stick a
source on it, and the damage handler will treat it as if the boss placed
a TNT block and detonated it, which is an apt analogy after all. Just to
make sure we don't forget the dual responsibility, we've added a little
comment in the damage handler.

An alternative solution would have been to spawn any other entity and
stick the boss entity ID on it, then look up the entity by that ID in
the damage handler if the damager had metadata on it. This is just a bit
more streamlined and likely a lot more performant.

Fixes #789
2024-07-23 03:49:13 +02:00
Andreas Troelsen a23be39663 Keep track of shuffle-positions teleportees.
Introduces a means of "tracking" both the players and the boss itself
during the `shuffle-positions` ability for the sake of _not_ blocking
the teleport event(s) that could potentially be blocked otherwise.

Note that the change introduced in the PlayerTeleportEvent handler is
not strictly necessary. The final block of code _should_ always yield
the same result, as `shuffle-positions` _should_ be working solely on
positions that are all inside the arena region, but the out-of-bounds
check might be delayed, so we don't know for sure. It's just a safety
precaution, but it really shouldn't be necessary.

Fixes #792
2024-07-23 02:24:42 +02:00
Andreas Troelsen 3badf4c934 Make clashing wave resolution randomized.
This commit changes two things; it allows multiple single waves to have
the same wave number, and it makes the wave selection procedure pick
randomly between multiple valid matches.

Effectively, this means that MobArena now picks randomly when clashing
recurrent waves _also_ clash on priority (rather than deferring the
decision to the arbitrary but deterministic nature of sorted sets), and
it also picks randomly between multiple single waves with the same wave
number (which was not possible before).

This should allow server owners to add variety into their wave setups
while maintaining a great deal of control over the randomness involved.
For instance, it's now possible to have wave 10 be a boss wave, but the
_actual_ boss wave is randomly picked between three different waves all
with wave number 10. Upgrade waves could be randomized as well. As for
randomized recurrent waves, perhaps instead of having potentially four
different mobs in the same wave, a setup could instead have two _pairs_
of mobs that are randomly selected for a different kind of randomness.

Closes #795
2024-07-23 02:24:29 +02:00
Andreas Troelsen 70a46862b0 Add 1.21 to supported game versions.
No breaking changes between 1.20.6 and 1.21, so everything seems to be
working as expected.
2024-07-23 02:22:48 +02:00
Andreas Troelsen 17317fa0ae Handle BlockExplodeEvent explicitly.
This commit cleans up the old fake event show that was implemented when
the BlockExplodeEvent was introduced and caused all sorts of issues back
in the day. It should have been cleaned up years ago, but "if it ain't
broke"... Well, it is now! With this commit, however, we get rid of the
constructor invocation that throws up, but we obviously need to replace
it with something else to take care of the problem it used to fix.

The handler is close to a carbon copy of the EntityExplodeEvent handler,
simply because the code isn't very reusable due to direct method calls
on the event object itself. But because of the refactoring step of the
previous commit, we don't actually have to explicitly repeat the gnarly
"repairable" code that handles the block list, yay... We obviously don't
have an entity to check for (and remove from the monster manager), and
we need to dig a little deeper for the Location object needed for the
region check, but other than that, it's the same thing.

Fixes #796
2024-07-23 02:22:48 +02:00
Andreas Troelsen 8122c535df Move explosion event block handling to private method.
Just a tiny little refactoring that makes reusing this logic a little
easier _without_ obfuscating the commit history for the code itself.
Just git things, really...

We'll want to reuse as much of the original method as possible for the
two explosion events, but because of the direct method calls, we can't
really reuse a good chunk of it. Still, this is better than nothing.
2024-07-23 02:20:42 +02:00
Andreas Troelsen ced55b8a89 Bump version to 0.108.1. 2024-06-24 23:30:08 +02:00
Andreas Troelsen 29c5d7f56d Release 0.108. 2024-01-01 20:15:55 +01:00
Andreas Troelsen e40fc6ef84 Add publish-hangar GitHub Actions workflow.
Introduces a new workflow that runs when a new build has been published
on GitHub Releases. It converts the release notes to Hangar Markdown and
sends it to Hangar along with the jar-file.

Note: The workflow currently relies on the version string being appended
to the filename of the jar-file. Without it, the file reference in the
`curl` request that uploads the build would need to change.

The workflow references a new secret, `HANGAR_TOKEN`, which is just an
API key for the Hangar API. The token was created in the Hangar profile
settings (API Keys), and its only permission is `create_version`.

In order to properly upload a new build to Hangar, we need to construct
a somewhat complex JSON object. This is because the Hangar API allows
for publishing releases on multiple platforms and for multiple versions,
which makes the simple use case for MobArena's single file upload look a
bit overcomplicated. Unlike the CurseForge API, the Hangar API supports
"normal" platform version strings, so we don't need to map anything. It
also supports patch version wildcards, so we can get away with `1.18.x`,
`1.19.x`, etc. for each version supported. The API only uses the API key
for authentication, which means we need to grab a JWT and use that for
the actual upload request. Note that the `pluginDependencies` property
is currently required, but it can be left empty.

The workflow can be invoked directly via the `workflow_dispatch` event,
which might come in handy if something in the pipeline breaks.

The Hangar base URL and project slug are both hardcoded, and things
would probably be cleaner if they were made into variables, but we don't
need this workflow anywhere else, so it's fine for now.
2024-01-01 17:05:41 +01:00
Andreas Troelsen be6fd85a6d Add publish-curseforge GitHub Actions workflow.
Introduces a new workflow that runs when a new build has been published
on GitHub Releases. It converts the release notes to CurseForge HTML and
sends it to CurseForge along with the jar-file.

Note: The workflow currently relies on the version string being appended
to the filename of the jar-file. Without it, the file reference in the
`curl` request that uploads the build would need to change.

The workflow references a new secret, `CURSEFORGE_TOKEN`, which is just
an API key for the CurseForge API. The token was created on CurseForge
under profile settings (My API Tokens).

In order to properly upload a new build to CurseForge, we need a list of
"game version IDs", which isn't completely trivial. The API gives us a
means of looking up _all_ Minecraft game version IDs, but we then have
to manually filter out the ones that don't apply to Bukkit plugins, as
there are duplicate entries for each Minecraft version, and only some of
them work for Bukkit plugins (which turns out to be the ones with game
version type ID 1). The structure of the `metadata` field combined with
how incredibly difficult bash can be to work with has resulted in some
gnarly text processing trying to filter the JSON response and turning it
into a list for use in the `jq` template, but it gets the job done.

The CurseForge base URL and project ID are both hardcoded, and things
would probably be cleaner if they were made into variables, but we don't
need this workflow anywhere else, so it's fine for now.

The workflow can be invoked directly via the `workflow_dispatch` event,
which might come in handy if something in the pipeline breaks.

Lots of inspiration was found in the probably really great GitHub Action
`curseforge-upload` [1]. We could have probably just used that, but it's
nice to have full control of the process. At any rate, thanks to itsmeow
and NotMyFault for publishing their work.

---

[1] https://github.com/itsmeow/curseforge-upload
2024-01-01 16:46:38 +01:00
Andreas Troelsen b881943656 Add hangar format to release note script.
Hangar uses Markdown, so this is a very easy release note "conversion"
just like GitHub Releases.
2023-12-31 15:14:25 +01:00
Andreas Troelsen 8e5d2f0d23 Make InventoryThingParser package-private.
We don't need the parser exposed outside of the `things` package, and
none of the other thing parsers are public anyway. Coincidentally, this
fixes a warning about exposing InventoryThing outside of its visibility
scope, so yay.
2024-01-01 18:34:20 +01:00
Andreas Troelsen 3b7b638b00 Make LexeMatcher package-private.
We don't need it outside of the `formula` package.

This fixes warnings about exposing Lexeme outside of its visibility
scope, so yay.
2024-01-01 18:26:44 +01:00
Andreas Troelsen eb51a31720 Remove unused ThingManager constructor.
This fixes a warning about exposing ItemStackThingParser outside of its
visibility scope, but really it's just a good little cleanup step, since
the constructor in question is never used for anything. We might want to
eventually expose the ItemStackThingParser and use it in more places in
the code base, but in that case, and in that case it would probably make
sense to re-introduce the constructor, but I'm calling YAGNI on this in
order to nuke a warning.
2024-01-01 18:23:54 +01:00
Andreas Troelsen 82f00c5535 Fix "unary operator" warnings in FormulaManagerIT.
Okay, the reason the code included the unary plus was to more directly
represent the resulting expression, but I'm guessing the compiler isn't
going to respect that intent even if it could somehow understand it, so
it will probably remove the symbols and just parse it all the same.

Unlike with the unary plus, the unary minus can be "fixed" by wrapping
it in parentheses. The end result is of course the exact same, but the
intent is perhaps a bit clearer this way. We want to try to coerce the
compiler into creating an expression with "add a negative value", just
for the sake of "correctness" at the runtime evaluation level, but even
if that isn't what will actually happen, the explicit code is still a
bit easier to read. While unary plus is easy to disregard, "fixing" an
unnecessary unary minus would mean having to change the binary operator
before it, which muddies the intent of the expression.
2024-01-01 17:49:21 +01:00
Andreas Troelsen d8fdbb80c0 Simplify formula operation interfaces.
This commit releases the BinaryOperation and UnaryOperation interfaces
of the `formula` package from their `java.util.function` supertypes and
redeclares the previously inherited functions directly in the operation
interfaces, but also reifies them by explicitly using primitive doubles
instead of generics and wrapper classes. Doing so does not change the
functionality or any other code at all, but it makes the interfaces much
"stronger", since they no longer need to consider `null` values, which
they didn't actually take into account anyway. This fixes a warning in
Visual Studio Code (not sure how to get the same warning in IntelliJ)
about the operator registrations in the default formula environment
factory method being unsafe.
2024-01-01 19:39:59 +01:00
Andreas Troelsen e5ffe169a1 Create release drafts from "Release ..." commits.
This commit adds a second job to the build workflow that runs after the
build job has completed. The job creates a GitHub Releases _draft_ that
needs to be manually published in order to be publicly available.

The job runs if, and only if, the following conditions are met:

- The build job has completed _successfully_, i.e. if the Gradle `build`
  task fails, the draft job doesn't run.

- The `push` event that triggered the workflow happened on the `master`
  branch, i.e. releases will never be created from temporary branches.

- The commit message of the most recent commit in the `push` event that
  triggered the workflow starts with `"Release "`, i.e. there must be a
  commit that explicitly tries to "release" a build.

- The version string does _not_ end with `-SNAPSHOT`, i.e. development
  builds will not be released.

All of these conditions act as safeguards, so we don't end up releasing
something we don't want to release, but they also prevent bloating the
Releases page with a bunch of useless drafts.

The job uses the `version` output variable from the build job that was
introduced in a recent commit to extract release notes using the script
that was also introduced recently, as well as for the name of the _tag_
to create when the release is published.

Note that the `GITHUB_TOKEN` environment variable is required to be set
when we want to use the GitHub CLI in a workflow [1]. The job also has
an explicit `contents: write` permission, which is required for creating
releases from GitHub Actions.
2023-12-31 04:43:53 +01:00
Andreas Troelsen 798ae0f578 Output version string in build workflow.
This commit makes the build workflow output the version string as found
in the `version` property in `build.gradle.kts`. The version string will
be necessary further down the pipeline when we need to extract release
notes and create tags.

There are many ways to extract the version string:

- Use `grep` to grab it from `build.gradle.kts` directly. This is pretty
  brittle, since we don't really know for sure if the structure of the
  file will change in the future.

- Create a Gradle task in `build.gradle.kts` that prints the version
  string. This is probably the most direct approach we could take, but
  such a hyper-specific task feels like a code smell. It also requires
  running Gradle again, which is a bit slow.

- Use the built-in `properties` task in Gradle to print the `version`
  property and `grep` it. We avoid changing `build.gradle.kts`, which is
  a plus, but we still have to actually run Gradle.

- Parse the filename of the resulting jar-file in `build/libs/`, since
  it now contains the version string. This is also brittle, because we
  don't know if we're gonna continue to append the version string to the
  jar-file, and depending so much on it being there is a little scary.

- Extract `plugin.yml` from the resulting jar-file and `grep` it. This
  is perhaps a little crude, but it is much faster than running Gradle,
  and as a bonus, we get a bit closer to "what's inside the jar-file",
  which should give us a bit more confidence that any given release is
  actually the version it claims to be.

It may seem like a small thing to invest so much text on, but from an
automation standpoint, it is much easier to be confident in automations
with predictable and robust mechanisms for deriving input variables.
2023-12-31 04:16:08 +01:00
Andreas Troelsen 84776990b9 Add release note extraction script.
Introduces a crude Python script that can extract release notes from the
changelog for a given version and convert it to one of three different
output formats:

- `github` for GitHub Releases. This is just the Markdown itself, but
  with the very first line (the version) removed, because the version is
also the title of the release itself.

- `spigot` for Spigot Resources. This is the BBCode format used on the
  forums and in the resource descriptions.

- `curse` for CurseForge File Uploads. Curse uses a so-called "WYSIWYG"
  format that's really just HTML underneath.

The formats for Spigot and CurseForge are straightforward to convert to
as long as we only use simple text formatting, bullet lists, and links,
but that is really all the changelog should consist of anyway.

While this script already makes the release process quite a bit easier
on its own, the end goal is to _automate_ releases as much as possible,
and to do that, we need to be able to extract release notes, and we need
to be able to do it from GitHub Actions, which is quite a bit simpler if
we don't use third-party libraries.

Publishing releases on GitHub is almost trivial, while CurseForge is
pretty easy, and Hangar should be very doable as well. Spigot, on the
other hand, is stuck in the dark ages, so we must continue to upload
files manually there.
2023-12-31 03:25:14 +01:00
Andreas Troelsen 590f877756 Build on push to branches, not tags.
According to the documentation, by not specifying anything in the `push`
event, GitHub Actions will run the workflow for both branches and tags,
but by specifying `branches` alone, it will _only_ run the workflow for
branches and _not_ tags [1].

We want to build on pushes to _all_ branches so we can give folks a jar
to try out for feature requests and bug fixes. We don't want to build on
tags, however, because they don't provide any value in the current build
pipeline. If the version was derived from Git tags, it could make sense
to build on tags, but that's not where we are.

As for the `**` glob pattern instead of just `*`, the documentation says
that the latter does not match forward slashes [2], and while our naming
convention for branches doesn't use slashes right now, there's no reason
that they shouldn't be viable later down the road.

---

[1] https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onpushbranchestagsbranches-ignoretags-ignore
[2] https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
2023-12-31 02:25:41 +01:00
Andreas Troelsen 932b9de8f2 Minor tweaks to build workflow.
Removes trailing whitespace and simplifies some step names.
2023-12-31 02:24:53 +01:00
Andreas Troelsen 614d95683e Update upload-artifact to v4.
Apparently there are numerous performance and behavioral improvements.
2023-12-30 23:49:03 +01:00
Andreas Troelsen 4c855e6705 Include version in artifact filename.
Removes the "archive version" override for the `shadowJar` task in the
build file, resulting in a jar-file that contains the current version
number in the filename. It's mostly a convenience tradeoff; either we
can see the version directly in the filename and avoid assumptions, or
we can easily overwrite an existing jar-file with a new one.

Also updates the upload step of the build workflow to a glob pattern so
we grab the file regardless of the version.
2023-12-30 23:36:07 +01:00
Andreas Troelsen 7942c33e67 Add monster-teleporting to resource file.
This should have been part of commit 511d16f, but apparently I forgot to
stage the file.

Whoops.
2023-12-17 21:20:25 +01:00
Andreas Troelsen f57f10ecd5 Convert to Gradle.
This commit converts the project from Maven to Gradle by removing the
old Maven-related files such as `pom.xml` and the Maven Wrapper, and
replacing them with their Gradle counterparts (more or less).

Comparing the artifacts from Maven and Gradle indicates no significant
differences in the resulting jar-files, and a quick test of the plugin
shows that things are still working as expected.

Bits of `build.gradle.kts` may need a bit of a tune-up later down the
road, e.g. the test sources "hack" put in place. It may be cleaner to
omit this hack and just suck up having to repeat dependencies, but in
that case, it might be better to embrace the "libs" file instead of
having to repeat dependencies in full.

Note that this commit changes the caching mechanism used in the GitHub
Actions build workflow, opting for the one built into `setup-java`.
2023-12-09 21:08:09 +01:00
Andreas Troelsen 511d16f45a Add per-arena setting monster-teleporting.
This setting allows server owners to allow arena monsters to teleport
around _while inside the region_. They still can't teleport out of the
region.

Taken at face value, this should just be the default behavior. However,
due to arena regions being boxes, any non-box shaped arena will need a
region that covers more than the physical arena structure, which means
mobs like Endermen will be able to teleport into possibly unreachable
areas of the physical structure. So we have to make do with a setting.

Closes #762
2023-11-13 16:29:51 +01:00
Andreas Troelsen 457bf2ffff Clean up PvP activation logic.
The idea behind the previous implementation worked, but it was a tad bit
confusing. This commit refactors the activation logic by simply removing
it entirely. The "activation" part of the logic is now derived from the
wave number (if 0, it means we haven't _really_ started yet), instead of
relying on the spawn thread to toggle the flag on and off. This kind of
dependency inversion (spawn thread -> listener, listener -> "phase") is
a pretty decent (albeit super tiny) step towards cleaning up the whole
session system, so I call that a victory in and of itself!
2023-11-13 16:19:01 +01:00
Andreas Troelsen a662157cbf Reformat ArenaListener fields.
What a mess, sheesh...
2023-11-13 15:37:51 +01:00
Andreas Troelsen 9e083a91de Report Spigot health error to admins.
Using the new `mobarena.admin.errors` permission, this commit provides
server owners with a way to make the infamous Spigot health error much
more visible by sending the error message to any "admins" online when
the error occurs.

Closes #764
2023-11-13 14:39:05 +01:00
Andreas Troelsen 12314f476c Add mobarena.admin.errors permission.
Introduces a new permission for "admins" that can be used to increase
visibility of errors caught by the plugin. Server owners may not want
_all_ online players to see these types of messages, so the permission
gives error handlers a way to filter the list of online players before
sending the error message.
2023-11-13 14:37:34 +01:00
Andreas Troelsen feb257213c Add support for saved items.
Introduces the concept of a _saved item_; an in-game item that has been
captured in a YAML file via Bukkit's item serialization mechanism. These
items can be referenced in the config-file in all places that any other
normal item can be used, assuming the ThingManager is in charge of the
parsing. This should help bridge the gap between class chests and the
config-file by allowing any Bukkit serializable item stack to be stored
and referenced as if MobArena's item syntax directly supported it.

Three new setup commands are introduced to help manage the items, such
that they can be created, deleted, and loaded (for "editing" purposes).
The commands are somewhat rough around the edges and may need a little
bit of polish going forward.

Together with the new inventory referencing Things, this functionality
should help provide most of the flexibility people have been missing
from the item syntax for about a decade... Hell, it's about time.

Closes #212
2023-11-13 14:33:31 +01:00
Andreas Troelsen d7336526e1 Add InventoryThing collection.
Adds three new Thing types that can be used to reference items in chests
(or any block-based InventoryHolder):

- InventoryIndexThing looks up an item by index/slot in an inventory.
- InventoryGroupThing groups all non-null/non-air items in an inventory
  into a ThingGroup.
- InventoryRangeThing groups all non-null/non-air items in a given range
  of an inventory into a ThingGroup.

The new Thing types aim to bridge a gap between the class chests and the
rest of the Thing-based parts of the config-file. The goal is two-fold:
allow for more in-game configuration so access to the config-file isn't
_quite_ as crucial, and propagate the item-wise feature completeness of
class chests to other parts of the plugin.

While class chests are low configuration and a bit "all or nothing", the
inventory Thing types require manually punching in the coords for chests
and possibly indices/ranges for items. This means that the initial setup
could be a bit unwieldy, and highly volatile wave setups are definitely
not a good fit. If the wave setup is mostly pre-defined, it is fairly
easy to tweak upgrade waves and rewards in the same way class chests are
tweaked.

As for item-wise feature completeness, the inventory Thing types share
the same "if Bukkit can copy it, it will work" rule of thumb as class
chests do, which means items with metadata such as custom names, lore,
or even NBTs, should just work. This could remove the need to employ
other plugins.

By no means can this solution be considered "optimal", but it it _does_
enable some long-requested features.

Closes #456
2023-11-13 14:32:35 +01:00
Andreas Troelsen 1a7109a1d4 Add Hangar link to README.
We'll get around to the Gradle plugin and auto-publishing at some point,
but for now, let's at least just link to the project page.
2023-11-13 12:21:40 +01:00
Andreas Troelsen af513b03b0 Prevent unauthorized sign edits.
Since Minecraft 1.20, players can edit signs by right-clicking on them,
and that poses a problem for the sign-centric portions of the plugin,
such as class selection signs and the various types of arena signs.

This commit refactors the PlayerInteractEvent handler in ArenaListener
in order to break open the possibility of handling non-lobby players as
well. We're a little more strict with lobby players, and we still want
to handle class sign clicks and iron block clicks here. For players who
aren't in the lobby, we're really just blocking the event according to
the regular protection rules (block is inside region, protect is on, and
arena is not in edit mode).

It also blanket cancels events in the HandlesSignClicks event handler,
because there is no meaningful way to edit an arena sign, since their
contents come from the template file and not from what is written on
them by the sign renderer.

Ideally, we'd refactor some of this event handler logic, because it's a
lot easier to take care of the individual responsibilities in separate
event handlers.

Fixes #765
2023-11-04 00:20:39 +01:00
Andreas Troelsen 6579c4bf0e Call update() when reparing signs.
It boggles the mind that this tiny little class has worked as intended
since 2011 (!!), and all of a sudden, signs no longer retain their text
in the repair procedure...

By calling the somewhat arbitrary `update()` method on the sign after
setting the contents, the sign appears to correctly update again.

Fixes #772
2023-10-23 18:55:08 +02:00
Andreas Troelsen a79678430d Add -Xlint:all to compiler args.
Nice little flag to get all those juicy warnings out into the build
output for better visibility.
2023-10-23 18:35:54 +02:00
Andreas Troelsen 61550161a7 Remove unused class.
I had no idea this class existed, but it seems like it's actually never
been used for anything, since the commit that introduced it didn't even
use it either.
2023-10-23 00:30:55 +02:00
Andreas Troelsen bbe7ed491d Bulk up the test suite for FormulaManager.
Introduces a couple of tests for the FormulaManager test suite in order
to cover all the methods the class exposes. This means it is no longer
necessary to suppress the "unused" warnings.
2023-10-23 00:30:55 +02:00
Andreas Troelsen 15a79bdd7e Remove discrepancy in auto-ready behavior.
It's not clear why this variation in the auto-ready logic exists, and
the commit history doesn't seem to have any clues either. Perhaps the
actual readying up logic was incompatible with auto-ready at some point,
but at this point in time it doesn't seem like this is necessary at all,
and it appears to be causing a bug with the MobArenaStats extension.

By simply calling the player ready procedure regardless of the status of
the auto start timer, MobArena fires the arena player ready event that
MobArenaStats depends on for some of its pre-session bookkeeping. It
could be argued that MobArenaStats should be more robust, but we would
much rather fix the root problem than slack on the otherwise fairly
sound strictness of the MobArenaStats data model.

Fixes #746
2023-05-07 11:52:31 +02:00
Andreas Troelsen 4f78936716 Use boss entity as source for obsidian bomb.
Makes the boss entity the source of the obsidian bomb explosion, which
then makes the damage event listener handle the explosion damage as if
the boss is the damager, which means the `monster-infight` flag should
be respected.

Fixes #759
2023-05-07 11:29:36 +02:00
Andreas Troelsen 2eb1761e76 Use exploding sheep as source for explosion.
Makes the sheep entity the source of the explosion that's created when
it triggers close to a player. This, in turn, makes the damage event
listener handle the explosion damage as if the sheep is the damager,
which means it will respect the `monster-infight` flag.

Fixes #758
2023-05-07 11:28:13 +02:00
Andreas Troelsen 9871bb85d8 Bump version to 0.107.1. 2023-05-07 11:21:21 +02:00
Andreas Troelsen 00605b54f9 Release 0.107. 2022-07-30 20:24:03 +02:00
Andreas Troelsen ec644df05b Adapt to the new SPELL spawn reason.
This new spawn reason was introduced somewhere between 1.18 and 1.18.1,
and unfortunately it is a breaking change, so we have to employ it for
MobArena to properly allow and register vexes (again...), but we also
have to maintain a variation of the old logic so we don't break support
for older server versions.

Fixes #719
2022-07-26 13:20:54 +02:00
Andreas Troelsen 2c0d3e292c Update SpigotAPI to 1.19.
This time around we're trying to keep the API version bumped for the
sake of not leaving the people who actually keep their servers updated
behind. It does present some potential backwards compatibility issues
when we do employ new API, but we'll just have to be mindful of _how_ we
go about doing so...
2022-07-26 13:10:06 +02:00
Andreas Troelsen d963d90cb9 Update VaultAPI to 1.7.1. 2022-07-26 12:23:53 +02:00
Andreas Troelsen b76b0e6719 Add workflow_dispatch trigger to build workflow.
This should allow us to just initiate a build if the artifact of the
latest build expires.
2022-06-25 17:21:16 +02:00
Andreas Troelsen 6cec72ebfb Add some whitespace to build workflow.
Let's clean this up a little bit.
2022-06-25 17:19:49 +02:00
Andreas Troelsen 8c5ae13bef Rename build workflow.
The previous name was really just a way to try to "prettify" the whole
thing, but the badge in the README is a little wonky compared to other
projects, so we're just gonna go with "build" for now for consistency.
2022-06-25 17:18:02 +02:00
Andreas Troelsen 36908cbe85 Remove class pets on player death.
When a player with pets dies in the arena, we want their pets to be
removed. One could probably argue that the pets _should_ be able to
stick around, but the original intent was for them to be removed
alongside their owner.

Fixes #721
2022-06-25 17:16:09 +02:00
Andreas Troelsen c88f20c46f Add per-arena setting auto-ignite-fuse.
This new setting allows changing the fuse time for auto-ignited TNT,
which is normally a hardcoded 80 ticks in Minecraft. Note the somewhat
weak safeguarding without any sort of error message - with great power
comes great responsibility...

Closes #715
2022-02-13 00:33:18 +01:00
Andreas Troelsen b9b4d0d204 Replace metadata "planter" logic with TNT primed source.
Now that MobArena sets the TNTPrimed source on auto-ignited TNT, the
"planter" logic becomes _somewhat_ obsolete. This is due to the fact
that manually ignited TNT blocks produce a TNTPrimed entity with the
source property set to the player that ignited the block.

Because the "planter" logic in the BlockIgniteEvent handler didn't
actually work, this change shouldn't actually do anything in that
regard. That is, a TNT block ignited by a player would still have that
player as its source regardless of who the planter was, because the
procedure that would have otherwise set the planter of the TNTPrimed
entity never ran.
2022-02-12 23:53:04 +01:00
Andreas Troelsen 4470b60aaf Remove unused code block.
Turns out igniting TNT _doesn't_ fire a BlockIgniteEvent but rather an
ExplosionPrimeEvent, which means this code has never actually been of
any use. This code block was likely dead on arrival and has been dead
for almost 9 years. Wonderful...

The proper handling here would be to listen for the PlayerInteractEvent
and detect flint and steel interactions with TNT blocks. This is super
cumbersome, however, because the event handler would have to listen on
the MONITOR priority to ensure that nothing changes down the line. What
we are _actually_ need to do is remove the TNT block from the arena's
block set when it is ignited, but since this hasn't worked for almost a
decade, we're not really in a hurry to fix it now. It just makes for a
slightly slower (but negligible) cleanup procedure most of the time.
2022-02-12 23:30:21 +01:00
Andreas Troelsen d3e5d44cb2 Set source property on TNTPrimed entities.
This property makes TNT explosions look more "real" to other plugins who
may be consuming events from MobArena's sessions. It also gives way to a
potential rework of the "planter" logic that currently makes use of the
Bukkit Metadata API.

Closes #718
2022-02-12 22:42:39 +01:00
Andreas Troelsen d4dcc8dc90 Don't nag players with mobarena.admin.teleport.
Changes the behavior of the ArenaListener's teleport event handler such
that it _ignores_ teleport attempts instead of _rejecting_ them when the
player in question has the `mobarena.admin.teleport` permission. Because
the global listener's event handler only ever checks the permission if
at least one per-arena listener has _rejected_ the teleport attempt, and
none of them have explicitly _allowed_ it, the change means that it will
never check the permission, because its internal `allow` flag will never
change to `false`. Thus, the check can be safely removed from the global
listener's logic.

When the response is to ignore instead of reject, the message that would
have otherwise been sent to the player is skipped. This fixes #702.

It is perhaps tempting to move the permission check up into the section
of sanity checks in the global listener, but this is very specifically
avoided to allow MobArena to _uncancel_ teleport events that have been
cancelled by other plugins, but that MobArena might need to go through.
Please see afcc526a71 for more info.
2022-02-12 19:06:40 +01:00
Andreas Troelsen 77b2525707 Cancel damage to players by pets.
This is technically not necessary when pets are simple entities like
wolves and zombies, because these types of pets will never target and
thus attack other players in the arena. However, projectile entities
such as Blazes and Ghasts may hit players in the line of fire, and so
any such damage should be cancelled.

Fixes #712
2022-02-12 17:55:58 +01:00
Andreas Troelsen 9164b125bd Allow flaming arrows to ignite TNT.
It turns out that, according to the Spigot API, flaming arrows actually
_change_ TNT blocks to air before/instead of igniting them. While this
is a little counter-intuitive, the fix seems to revolve around allowing
the change to happen if the changed block is TNT and the "changer" is an
arrow.

Allowing the change event to happen means "foreign" primed TNT entities
will spawn, which makes it necessary to clean them up during the session
cleanup phase in ArenaImpl.

Fixes #696
2021-12-05 17:30:24 +01:00
Andreas Troelsen c80f0375ee Copy cancel state to fake EntityExplodeEvent.
It's not clear if this change actually solves the underlying issue,
because it has not been tested in a controlled environment. However,
considering the EntityExplodeEvent constructor, which doesn't take a
cancel state value, and the `HIGHEST` priority setting of MobArena's
event handler, the issue is realistic, and this change very likely
solves the issue.

Fixes #704
2021-12-05 16:18:54 +01:00
Andreas Troelsen 2c12112fd0 Update JUnit to 4.13.2. 2021-10-13 23:25:13 +02:00
Andreas Troelsen fe9d160edd Update Mockito to 3.12.4. 2021-10-13 23:25:13 +02:00
Andreas Troelsen 4348a0497e Use arena slugs in arena sign update handler.
The arena signs predate the use of arena slugs everywhere, so something
slipped through the cracks in this regard. Incidentally, the handler for
arena updates is one of the few classes in the signs package that has no
unit tests, probably due to it being "obvious implementation". Not so
obvious after all, it seems, so now we have a basic test for it.

Fixes #705
2021-10-13 23:25:13 +02:00
Andreas Troelsen c143cc81c9 Add per-arena setting auto-leave-on-end.
Introduces a new arena setting to force spectators to leave the arena
when the current session ends. If set to `true`, it "overrides" the
behavior of `spectate-on-death: true` when players respawn, such that
they only become spectators if there is an active arena session.

The respawn behavior technically means that it is possible for a player
to begin spectating "the next session" if a new session begins between
them dying and clicking Respawn on the death screen. Ideally, we would
want the player to auto-leave, because the session _they_ participated
in ended, but we don't have a concept of "previous sessions", so this
quirky behavior will have to do.

Closes #682
2021-08-08 00:56:41 +02:00
Andreas Troelsen 52226fa1c9 Make Thing extend ThingPicker.
By turning things into their own thing pickers, we can avoid creating a
bunch of SingleThingPicker wrappers, which are now redundant. Because
the semantics of using things and thing pickers are quite different, it
does perhaps make it necessary to be a bit more careful about picking
the right type.
2021-08-07 16:08:23 +02:00
Andreas Troelsen 7b9a9505b9 Reformat code in things package.
This is mostly just line breaks at the top and bottom of classes and
interfaces, but also marks some fields `final`.
2021-08-07 12:29:44 +02:00
Andreas Troelsen cad2eef8ba Optimize imports in things package.
We're good with on-demand imports for the static Hamcrest and Mockito
functions in test code, because the arrange and assert steps of unit
tests all make use of them, so it's known where they come from.
2021-08-07 12:20:45 +02:00
Andreas Troelsen 9fec49cc58 Make ThingGroupPicker aware of result set size.
This commit makes the ThingGroupPicker return different values depending
on the size of the picked result set. If the set is empty, the picker
returns null, emulating a NothingPicker. If the set is a singleton, the
element itself is returned, emulating the SingleThingPicker. Finally, if
the set contains more than one element, a ThingGroup containing those
elements is returned.
2021-08-07 01:36:37 +02:00
Andreas Troelsen 823be96b4e Guard against nothing in ThingGroupPicker.
This commit filters the result list of a ThingGroupPicker by a non-null
predicate to avoid null values in the resulting ThingGroup instance.

Since null values represent `nothing`, and we don't usually announce it
when players earn a `nothing` reward, it makes sense that they wouldn't
bubble up and somehow "manifest" in groups of things either.

Fixes #691
2021-08-07 01:36:35 +02:00
Andreas Troelsen 286071871f Add support for angry bees.
This commit introduces a new type variant, `angry-bee`, which is a bee
whose anger level is maximized upon spawning, much in the same vein as
its angry wolf cousin.

Note that bees are not available prior to Minecraft 1.15, so a sentinel
`null` name is used in the registration to prevent warnings from being
logged on server versions that don't have a concept of bees.

Closes #584
2021-07-30 18:21:41 +02:00
Andreas Troelsen c1716709f3 Add changelog bullet about targeting 1.17.
Because this bullet covers both the commit with the version bump and the
following compatibility commits, it didn't really fit properly into any
one of those commits, so now it gets its own!
2021-07-30 18:21:41 +02:00
Andreas Troelsen 15698d3eee Use block data to check if blocks are signs.
Instead of relying on the evolving Material enum values, we can use the
new BlockData API as advised by some of the folks "in the know". It is
unclear how much of a performance impact the the "block data gathering"
and `instanceof` checks incur, but this is a pretty secluded place in
the code base, so probably nothing to worry about.

An alternative solution could have been to check if the _name_ of the
Material equals "SIGN" or "WALL_SIGN", or ends with "_SIGN". That should
cover all cases in a sorta kinda safe manner, but it isn't as resilient
as the BlockData/BlockState hierarchies.

We could also employ the new Materials utility class and enumerate all
sign types by name and just check for membership of the resulting set,
but this creates another brittle crash point.
2021-07-30 18:21:41 +02:00
Andreas Troelsen b4cd509eff Use "legacy-aware" utility class for Material types.
Introduces the Materials utility class, which works much like the static
MACreature registration process, but for certain material types. Instead
of storing everything in a stringly typed map, certain Material values
are stored as constants.

Right now it's just the `OAK_SIGN`/`SIGN` pair for the autogeneration in
MAUtils, and chances are we can throw it out at some point in the near
future, but at least now there's room for more materials, should the
need arise.
2021-07-30 18:21:41 +02:00
Andreas Troelsen b49920fc38 Make fallback default wave consistent with default config.
Changes the fallback default wave in the wave parser to be consistent
with the default wave of the default config-file. Not a huge deal, but
it does feel a bit more neat.
2021-07-30 18:21:41 +02:00
Andreas Troelsen 36237ebe2d Replace pig zombies in the special wave of the default config.
Replaces the `zombie-pigmen` entry in the `spec1` wave of the default
configuration with `slimes-big`. This is due to the pig zombie rework
into piglins, which makes the custom name a little flaky. If we ever
decide to ditch the custom names somehow, this will probably make such a
transition a little easier.

While `slimes-big` is also a custom name, so are `powered-creepers` and
`angry-wolves`, but at least they are "API stable" in comparison, which
is really what this change is about.
2021-07-30 18:21:41 +02:00
Andreas Troelsen 4de0ce258b Tidy up code style in MACreature.
It's K&R style braces in all modern portions of the code base, and
IntelliJ keeps complaining about final values, so let's just make it
happy.

The `plural` field should go away at some point, but for now it's fine
to just null it out, since the legacy `register()` method is only ever
used by the deprecated-for-removal constructors, both of which actually
set it to something non-null.
2021-07-30 18:21:41 +02:00
Andreas Troelsen 72f4d16e6f Deprecate old MACreature constructors for removal.
The new constructor and registration method pair is what other plugins
should be using. They provide a slightly cleaner interface, and we don't
need so many different ways to do the same thing.
2021-07-30 18:21:41 +02:00
Andreas Troelsen 490df61375 Refactor MACreature registrations.
This commit changes the way MACreature initializes its internal map of
available monster types. Specifically, it replaces all static references
to EntityType enum values with a series of registration helper methods
that try to resolve EntityType enum values from a given set of strings,
stopping on the first match. If nothing matches, no registration, but a
warning is logged unless a specific sentinel `null` value is passed as
an argument, in which case the key is just silently skipped (not in use
as of this commit, but it will be necessary for modern types like bees
from 1.15+).

While this is arguably a huge step back in terms of type safety, it does
make the code base more resilient to API version bumps, and it allows
compiling against modern API versions and still run on older (1.13-1.16)
servers. It _does_ mean that changes to the EntityType enum (such as
PIG_ZOMBIE to ZOMBIFIED_PIGLIN) must be discovered manually, which makes
maintenance a little more difficult. The warning in the server log does
make it fairly easy to fire up an early build of a new server version
and check if everything initializes correctly.
2021-07-30 18:21:41 +02:00
Andreas Troelsen 95b65371f1 Switch to Spigot API and bump version to 1.17.
Spigot has decided to discontinue distribution of the Bukkit artifacts,
which means Bukkit "doesn't exist" after Minecraft 1.15. This commit
takes the plunge on that change and moves to the Spigot API rather than
the Bukkit API. Goodbye, Bukkit. Hello, Spigot.

The version is also bumped to 1.17 to give way to new features and bug
fixes otherwise blocked by staying on 1.13. Unfortunately, this brings
with it a swath of potential issues with version compatibility going
forward, because backwards compatibility in the API sometimes takes a
back seat, such as with the Material and EntityType enums. This commit
specifically changes some references that break compatibility with older
server versions, but compatibility with those is reinstated later.

Finally, the Spigot repository is changed to match the consensus about
which path on the Spigot Nexus instance to use. This seems to be what
everyone else is doing, so `bandwagon.jumpOn()`.
2021-07-30 18:21:39 +02:00
Andreas Troelsen f1cfd4136e Update Mockito version.
This makes the test setup compatible with Java 16.
2021-07-07 00:39:59 +02:00
Andreas Troelsen b99713f1ec Add reload events.
This commit introduces two reload events, MobArenaPreReloadEvent and
MobArenaReloadEvent. Both events are fired when MobArena reloads, the
former right before the reload, and the latter right after.

The reason for two events is to allow plugins to reload either entirely
or partially along with MobArena, if it makes sense for them to do so,
_when_ it makes sense for them to do so. Some plugins need to reload and
re-register themselves with MobArena before the config-file itself is
loaded (e.g. ThingParsers), while others either require MobArena to be
fully loaded or are more decoupled and thus don't depend on anything in
MobArena's innards to function. The "pre" event is for the former, while
the other event is for the latter.

As for naming, the choice of "Pre" and no prefix was made for the sake
of consistency with the event names in the Bukkit API, which has just
one example of such a pair (PlayerPreLoginEvent and PlayerLoginEvent).
Some event naming conventions (e.g. in the .NET world) seem to favor
present and past tense (reloading, reloaded), but this would be wildly
inconsistent with the rest of the event names, so it might be better to
just stay consistent. Names may change before an actual release, but for
now, this is what we're rolling with.

Closes #677
2021-07-07 00:14:29 +02:00
Andreas Troelsen 903752d23a Add support for registering subcommands by instance.
This commit introduces a new `register()` method on the CommandHandler
class to allow registering pre-instantiated subcommands. This means that
subcommands are no longer restricted in terms of instantiation, so they
can have their dependencies injected at creation, rather than having to
resort to Singleton anti-pattern means.

Also refactors the existing internal MobArena command registration to
use the new method to "drink our own champagne" and to reuse the code.

Fixes #675
2021-07-01 22:59:05 +02:00
Andreas Troelsen 614da20df8 Make /ma playerlist pattern less greedy.
This commit changes the pattern of the player list command to one that
isn't quite as greedy. This change is enough to fix issue #676 and thus
allow MobArenaStats to take control of its own command.

The command framework could definitely do with a bit of a rework away
from pattern matching towards aliases, which would prevent similar
issues from cropping up down the line. For now, this is good enough.

Fixes #676
2021-07-01 22:57:21 +02:00
Andreas Troelsen 2c2c36b880 Bump version to 0.106.1. 2021-05-10 09:08:19 +02:00
Andreas Troelsen 498cef9ec7 Release 0.106. 2021-05-10 09:07:50 +02:00
Andreas Troelsen 30c059f51b Include bStats, Github Actions in changelog.
These should have been included in their respective commits, but they
didn't seem particularly interesting for end users at the time. Might as
well include them, though.
2021-05-09 13:43:55 +02:00
Andreas Troelsen b08c74afbd Replace Travis CI with Github Actions.
This commit introduces a Github Actions workflow in the form of the file
`.github/workflows/build.yml`, replacing Travis CI and its `.travis.yml`
file.

The new workflow does a little bit more than Travis CI: it uploads an
artifact after a successful build. Due to a known issue with Github's
package UI, the MobArena.jar file is dynamically zipped on download, so
we get MobArena.jar.zip containing just MobArena.jar. It's redundant,
but there doesn't seem to be a simple way around it at the time of this
commit, so we'll leave it be.

For now, the workflow runs on every push to every branch. I'm probably
going to regret that, but we'll leave that as it is for now as well.
2021-04-15 17:24:56 +02:00
Andreas Troelsen c7e740040c Update bStats Metrics to 2.2.1.
The previously nested classes are now standalone, so imports and super
class definitions of the custom various charts are updated as well.
2021-04-11 13:11:47 +02:00
Andreas Troelsen 9081ec8055 Add support for custom formulas.
This commit re-frames the formula concept used by the wave growth, swarm
amount, and boss health wave configuration properties. It fundamentally
changes how these values are calculated, from a static, compile-time set
of enum values and hardcoded expressions, to a powerful math expression
feature that supports constants, variables, operators, and functions.

In part to remain backwards compatible with existing MobArena setups,
and in part for a better user experience, the old enum-based expressions
are relocated into a new file, `formulas.yml`, as _macros_. The file is
written to the plugin folder if missing, and it contains a formula for
each of the legacy values for each of the enums. Additionally, it has a
global section with some predefined macros for inspiration's sake. The
goal of this file is to allow people to define new formulas and reuse
them in their wave configurations instead of having to duplicate the
same formulas again and again.

Parts of the system are extensible. It is possible for other plugins to
register additional constants, variables, operators, and functions.

Closes #460
Closes #461
2021-04-07 22:13:03 +02:00
Andreas Troelsen 0da90f3963 Rework arena sign data store.
This commit constitutes a major rewrite of how arena signs are stored
and loaded. It fixes an issue where an unloaded or missing world would
cause MobArena to throw errors if there were any arena signs recorded in
said world.

The solution is to load signs of a given world when it is available,
rather than loading all signs at once indiscriminately. At startup,
signs for all _currently available_ worlds are loaded. This fixes the
errors. When a world loads and a WorldLoadEvent is fired, signs in that
world are loaded. This ensures that all valid signs in existing worlds
will _eventually_ load. To keep things tidy, a WorldUnloadEvent will
unload all signs for the unloaded world.

Bukkit's own YAML deserialization implementation doesn't re-throw all
deserialization errors, which means we can't actually catch the problem
of missing worlds without doing an awkward "scan" of the deserialized
objects. This prompted a rewrite of the serialization and data storage
into a custom CSV-like format which is both simpler and also provides a
lot more control over the process. Instead of relying on world _names_,
the new format uses world _UUIDs_. While the rest of the plugin won't
necessarily adapt well to a world being renamed, the signs data store
should be resilient enough to handle it.

Most of the actual sign rendering code and almost all of the template
code is intact, but quite a lot of other classes have been rewritten or
replaced. Some of the rewrites weren't strictly necessary, but because
the components were already fairly small, rewrites were much faster and
a lot less awkward than attempting to adapt existing code.

Fixes #645
2021-03-25 10:20:49 +01:00
Andreas Troelsen cf296704b0 Clean up .gitignore.
This file has an interesting history with content that goes all the way
back to MobArena's dark days of both Ant and Eclipse. This commit cleans
up the file a bit, removing a lot of unnecessary bits and pieces, and
making it a little more tightly bound to the current project setup.
2020-11-08 19:27:22 +01:00
Andreas Troelsen 9bc23c61a0 Bump version to 0.105.1. 2020-11-08 18:34:37 +01:00
Andreas Troelsen 3bef4948a6 Fix date of 0.105 release in changelog.md.
Time flies, oh my!
2020-11-08 18:33:18 +01:00
Andreas Troelsen 5f62b8013b Release 0.105. 2020-11-08 17:35:31 +01:00
Andreas Troelsen 532a2ce0da Add Maven Wrapper.
This should make it a lot easier to get started with the project and to
build a custom artifact from source.
2020-11-04 01:21:50 +01:00
Andreas Troelsen 07f0ce5d08 Add changelog entry for water bottle fix on 1.8.
This is a bit awkward to deal with, because the actual fix exists only
on the 1.8 branch, but we release from the main branch, so we want the
changelog entry to come from there.
2020-11-04 01:12:27 +01:00