Skip to content
This repository has been archived by the owner on Nov 2, 2021. It is now read-only.

API: give custom achievement to player that does not exist in the config yet #990

Open
Silthus opened this issue Mar 25, 2021 · 6 comments
Labels
developer experience Let's reduce the project's technical debt or make things easier for developers! enhancement Also known as new features.

Comments

@Silthus
Copy link

Silthus commented Mar 25, 2021

ℹ️ Basic information

I have a question about the API. I want to create an additional plugin that handles location achievements and allows creating them via commands and with a radius without relying on worldguard regions, signs or other unneeded stuff.

So I want to have a database with all locations and the achievement name. By default they don't look pretty but can be customized using the given key under the custom section in the config. Is that possible?

Help request

  • Is it possible to add new custom achievement types on the fly via the API?
  • How can I give a player a single custom achievement that may not exist yet and has no counter?

Thank you for the help!

The plugin will of course be open source or if you like the idea, be integrated into the plugin itself.

@Silthus Silthus added the general support Help requested by a user. label Mar 25, 2021
@PyvesB
Copy link
Owner

PyvesB commented Mar 25, 2021

Hello @Silthus ! 👋🏻

Thanks for your interest in this project! The overall idea sounds like a good one.

* Is it possible to add new custom achievement types on the fly via the API?

Unfortunately, this is not currently possible. The main blocker to doing this is the fact that achievement categories are currently modelled as enums. For example: https://github.com/PyvesB/advanced-achievements/blob/master/advanced-achievements-api/src/main/java/com/hm/achievement/category/MultipleAchievements.java

This makes achievement types very static. I don't think it would too hard to change this though, it's mostly a matter of turning the enum into a class to which new categories can dynamically be added.

* How can I give a player a single custom achievement that may not exist yet and has no counter?

I'm going to disappoint you as well, achievements are currently only driven by config.yml. However, some of the refactoring that was conducted as part of the 7.0.0 release would allow to do this much more easily, as it would be a matter of adding achievements to AchievementMap.

I'm unsure how you would specify all the parameters (Type, Goal, etc.) and rewards for a dynamic achievement. You mentioned creating achievements via commands in your third-party plugin, I can't imagine it being practical to include all the information for an achievement.

In the meantime, an alternative would be to leverage the Commands or Custom categories, append new achievements to Advanced Achievements' config.yml for one of those categories, and call /aach reload. Admittedly clunky, but it should work fine.

I'm sorry I'm not able to provide a perfect solution, but let me know whether this information helps! 😉

@Silthus
Copy link
Author

Silthus commented Mar 26, 2021

Hi @PyvesB

thank you for the detailed and quick reply. However I think the current API does make it possible what I thought of. Here is a code snipped on how I thought it might work:

AdvancedAchievementsAPI api = ...;

String category = "locations";
String identifier = "loc1";
String name = "Super dupa location";
String message = "You reached the super location";
Achievement achievement = api.getOrCreateAchievement(category, identifier, name, message);
// or use the achievement builder and then register the achievement
Achievement achievement = api.registerAchievement(new AchievementBuilder()....build());
// or get an existing achievement from the plugins category
Achievement achievement = api.getAchievement(category, identifier);

api.addAchievement(achievement, player);

And in the config.yml a new block is created for each achievement created via the API, maybe under a new plugins category?

...

Custom:
  votes:
    10:
      Message: Voted 10 times for the server!
      Name: customs_votes_10
      DisplayName: Server fan
      Type: normal
      Reward:
        Money: 5

Plugins:
  locations:
    loc1:
      Name: loc1
      DisplayName: Super dupa location
      Message: You reached the super location
      # the rest are defaults that are filled in
      Type: normal
      Reward: {}

What do you think? This would make it also possible to create more advanced custom achievements in plugins that do not rely on counters.

@PyvesB
Copy link
Owner

PyvesB commented Mar 27, 2021

// or use the achievement builder and then register the achievement
Achievement achievement = api.registerAchievement(new AchievementBuilder()....build());

This feels like a good design.

As a first step, it would be useful to implement this for existing categories. The API method would insert the right blob of YAML in the existing configuration (i.e. in the right category section & sub-category if any).

Once that's done, you're unblocked and can leverage the existing Commands category. For example, calling:

Achievement loc1 = new AchievementBuilder().category(CommandAchievements.COMMANDS).subcategory("loc1").displayName("Super dupa location").message("You reached the super location").build();
api.registerAchievement(loc1);

Would produce:

Commands:
  loc1:
    Name: loc1
    DisplayName: Super dupa location
    Message: You reached the super location
...

And then your plugin could simply call:

Bukkit.getPluginManager().callEvent(new PlayerAdvancedAchievementEvent(player, loc1));

As a second step, longer term goal, an API method such as api.registerCategory could be implemented so that you can create a clean dedicated category for your plugin. This would require getting rid of the enums I mentioned in my previous comment. :)

@Silthus
Copy link
Author

Silthus commented Mar 27, 2021

That sounds great!

@PyvesB
Copy link
Owner

PyvesB commented Mar 28, 2021

Would you like to help with some of this? The work can be broken down into small pieces that can easily be picked up without needing deep knowledge of the plugin.

In particular, a utility class that maps from an Achievement object to it corresponding YAML string representation will be needed. Basically something very similar to the AdvancementJsonHelper class (and its unit tests here).

@Silthus
Copy link
Author

Silthus commented Mar 29, 2021

I will were I can, but unfortunately I don't have a lot of time at the moment. I will do my best and send a PR once I find the time.

@PyvesB PyvesB added developer experience Let's reduce the project's technical debt or make things easier for developers! enhancement Also known as new features. and removed general support Help requested by a user. labels Apr 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
developer experience Let's reduce the project's technical debt or make things easier for developers! enhancement Also known as new features.
Projects
None yet
Development

No branches or pull requests

2 participants