Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
6f9bd9f
Update for 26.1.1
Greymagic27 Apr 4, 2026
5018660
Update workflow to Java 25
Greymagic27 Apr 4, 2026
849fff1
Minor updates
Greymagic27 Apr 4, 2026
c600300
Bump paper version
Greymagic27 Apr 5, 2026
d62a50e
Merge branch 'master' into 26.1.1
Greymagic27 Apr 11, 2026
2f2c9cd
Bump paper
Greymagic27 Apr 11, 2026
d6b3530
Change how plugin is named
Greymagic27 Apr 11, 2026
fa3520b
Update for 26.1.2
Greymagic27 Apr 11, 2026
5ae4033
Mass format
Greymagic27 Apr 11, 2026
11d9a06
Convert to Adventure rather than ChatColor
Greymagic27 Apr 11, 2026
f9be528
Prefix is now in grey as well
Greymagic27 Apr 11, 2026
948c602
Spacing fix
Greymagic27 Apr 11, 2026
c384344
Remove message as it's clear when this is granted anyway
Greymagic27 Apr 11, 2026
1e606b0
Remove message as it's clear when this is granted anyway
Greymagic27 Apr 11, 2026
6431aaf
Undo last 2 commits
Greymagic27 Apr 11, 2026
7849ac9
Minor spacing changes
Greymagic27 Apr 11, 2026
034f7de
Cleaning up colors further - can now specify firework color in config
Greymagic27 Apr 11, 2026
83d4007
Code cleanup
Greymagic27 Apr 11, 2026
729fa23
Fix gui elements having color codes written in
Greymagic27 Apr 11, 2026
1d4603c
Remove all instances of ChatColor
Greymagic27 Apr 12, 2026
527e4b9
Update readme
Greymagic27 Apr 12, 2026
a1ccbe5
Format
Greymagic27 Apr 12, 2026
586c3ee
Update ConfigModule to use Component for PluginHeader
Greymagic27 Apr 12, 2026
a47f7ff
Add legacy stringbuilder
Greymagic27 Apr 12, 2026
b943ed6
Readme update
Greymagic27 Apr 12, 2026
4e35953
Readme update
Greymagic27 Apr 12, 2026
e02b87f
Possibly resolve #159
Greymagic27 Apr 12, 2026
b90d0ea
Possibly resolve #157
Greymagic27 Apr 12, 2026
436c69e
Fix compile error
Greymagic27 Apr 13, 2026
d225338
Readme update - Changes to support this are still in the works
Greymagic27 Apr 13, 2026
f8a766e
Potential fix for pull request finding 'Potential input resource leak'
Greymagic27 Apr 13, 2026
f59195b
Github CQ suggestion
Greymagic27 Apr 13, 2026
13120e4
Merge branch '26.1.2' of https://github.com/mrfdev/advanced-achieveme…
Greymagic27 Apr 13, 2026
7034fa4
Hardcode more colours into strings
Greymagic27 Apr 13, 2026
b3a9fa8
Combine lines
Greymagic27 Apr 13, 2026
74e404d
Revert readme
Greymagic27 Apr 13, 2026
9955607
Fix commands appearing as raw strings
Greymagic27 Apr 13, 2026
01e3ea3
Fixes #159
Greymagic27 Apr 13, 2026
ba1a1ef
Closes #165
Greymagic27 Apr 13, 2026
a88f288
Inline variable
Greymagic27 Apr 13, 2026
3cb885c
Expand test suite
Greymagic27 Apr 13, 2026
897ff19
Inline method to remove class
Greymagic27 Apr 13, 2026
5553748
Code cleanup
Greymagic27 Apr 13, 2026
6a510db
Fix #162
Greymagic27 Apr 15, 2026
04d841a
Update paper version
Greymagic27 Apr 15, 2026
33e2203
Dependency update
Greymagic27 Apr 15, 2026
f2d6f2b
Disable tests to continue working. Adventure update broke a lot of these
Greymagic27 Apr 15, 2026
56bacfc
Revert adventure update
Greymagic27 Apr 15, 2026
ab5b8d1
Code refactor
Greymagic27 Apr 16, 2026
91c485d
Fix #166
Greymagic27 Apr 16, 2026
05bd31a
Update config links
Greymagic27 Apr 16, 2026
e7aebff
Embed method
Greymagic27 Apr 16, 2026
7bd2f0a
Embed method
Greymagic27 Apr 16, 2026
ca0cfaa
Fix #161
Greymagic27 Apr 18, 2026
1a9bb11
Capitals
Greymagic27 Apr 18, 2026
17ba000
Merge branch 'master' into 26.1.2
Greymagic27 Apr 18, 2026
040a15f
Make 'HINT' light grey again
Greymagic27 Apr 18, 2026
13da9a2
Merge branch '26.1.2' of https://github.com/mrfdev/advanced-achieveme…
Greymagic27 Apr 18, 2026
ff583d8
Fix #174
Greymagic27 Apr 18, 2026
38757d5
Fix #173, #171, #157
Greymagic27 Apr 18, 2026
b282ce5
Merge branch 'master' into 26.1.2
Greymagic27 Apr 18, 2026
0c570d3
Fix tests
Greymagic27 Apr 20, 2026
ee85c70
Fix #172
Greymagic27 Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
- name: Set up JDK 21
- name: Set up JDK 25
uses: actions/setup-java@v5.2.0
with:
java-version: '21'
java-version: '25'
distribution: 'microsoft'
cache: maven
- name: Build with Maven
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
Found a problem or need some help? The following steps may help:

1. Upgrade to the latest version of the plugin (
available [here](https://www.spigotmc.org/resources/advancedachievements.121486/history)) and a recent Paper build for
available [here](https://www.spigotmc.org/resources/advancedachievements.121486/history)) and a recent Paper build
for
your Minecraft version (see [here](https://docs.papermc.io/paper/getting-started)).
2. Check your server's logs (including when plugins are loaded!), there may be warnings/errors/stack straces to help you
out with your issue.
Expand Down
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

Custom fork for Minecraft server 1MoreBlock.com

Recent changes include java 21+, 1.21.11, and legacy color code fixes.
Recent changes include Java 25, 26.1.2, and removing deprecated ChatColor methods in favour of Adventure Components.

**Advanced Achievements enables unique and challenging achievements on Minecraft servers. Collect as many as you can,
earn rewards, climb the rankings and receive RP books! The plugin supports SQLite, MySQL, H2 and PostgreSQL, manages an
Expand All @@ -26,23 +26,22 @@ releases page here on GitHub by the way, but here it is.)
<br/>
</p>

## :star: Support and feedback
## Support and feedback

Thought of a cool idea? Found a problem or need some help? Simply open an [**issue
**](https://github.com/mrfdev/advanced-achievements/issues)!
Thought of a cool idea? Found a problem or need some help? Simply open an [**issue**](https://github.com/mrfdev/advanced-achievements/issues)!

Find the project useful, fun or interesting? **Star** the repository by clicking on the icon on the top right of this
page!

## :computer: Code contributions
## 🖥️ Code contributions

Want to make Advanced Achievements better, faster, stronger? Contributions are welcome, open a **pull request** and
share your code! Simply **fork** the repository by clicking on the icon on the top right of this page to get started.

## :balance_scale: License
## ⚖️ License

GNU General Public License v3.0

## Special credits
## 📜 Special credits

Pierre-Yves Bigourdan, [@PyvesB](https://github.com/PyvesB/)
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

import java.util.List;
import java.util.function.Consumer;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;

public record Reward(List<String> listTexts, List<String> chatTexts, Consumer<Player> rewarder) {


public record Reward(List<String> listTexts, List<Component> chatTexts, Consumer<Player> rewarder) {
}
7 changes: 5 additions & 2 deletions advanced-achievements-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
<artifactId>petmaster</artifactId>
<scope>provided</scope>
</dependency>
<!--suppress VulnerableLibrariesLocal -->
<dependency>
<groupId>com.github.Zrips</groupId>
<artifactId>CMI-API</artifactId>
Expand Down Expand Up @@ -163,7 +162,7 @@
<executions>
<execution>
<configuration>
<finalName>advanced-achievements-plugin-${project.version}</finalName>
<finalName>advanced-achievements-${project.version}</finalName>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<outputFile>${project.build.directory}/${project.build.finalName}.jar</outputFile>
Expand Down Expand Up @@ -197,6 +196,10 @@
<shadedPattern>com.hm.fasterxml.jackson</shadedPattern>
</relocation>
</relocations>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
</transformers>
</configuration>
<phase>package</phase>
<goals>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@
import org.bukkit.plugin.java.JavaPlugin;

@Singleton
@Component(modules = {
CleanableModule.class,
CommandModule.class,
ConfigModule.class,
DatabaseModule.class,
ReloadableModule.class,
ServerVersionModule.class
})
@Component(modules = {CleanableModule.class, CommandModule.class, ConfigModule.class, DatabaseModule.class, ReloadableModule.class, ServerVersionModule.class})
interface AdvancedAchievementsComponent {

PluginLoader pluginLoader();
Expand Down Expand Up @@ -64,30 +57,27 @@ public void onEnable() {
long startTime = System.currentTimeMillis();
// DaggerAdvancedAchievementsComponent is generated by Dagger. Add target/generated-sources/annotations to your
// build path if the IDE complains here. In any case this will not actually prevent you from compiling.
AdvancedAchievementsComponent advancedAchievementsComponent = DaggerAdvancedAchievementsComponent.builder()
.advancedAchievements(this).logger(getLogger()).build();
AdvancedAchievementsComponent advancedAchievementsComponent = DaggerAdvancedAchievementsComponent.builder().advancedAchievements(this).logger(getLogger()).build();

pluginLoader = advancedAchievementsComponent.pluginLoader();
advancedAchievementsAPI = advancedAchievementsComponent.advancedAchievementsBukkitAPI();

try {
pluginLoader.loadAdvancedAchievements();
} catch (PluginLoadError e) {
getLogger().log(Level.SEVERE,
"A non recoverable error was encountered while loading the plugin, disabling it:", e);
getLogger().log(Level.SEVERE, "A non recoverable error was encountered while loading the plugin, disabling it:", e);
Bukkit.getPluginManager().disablePlugin(this);
return;
}

getLogger().info(
"Plugin has finished loading and is ready to run! Took " + (System.currentTimeMillis() - startTime) + "ms.");
getLogger().info("Plugin has finished loading and is ready to run! Took " + (System.currentTimeMillis() - startTime) + "ms.");
}

@Override
public void onDisable() {
pluginLoader.disableAdvancedAchievements();
}

@SuppressWarnings("unused")
public AdvancedAchievementsAPI getAdvancedAchievementsAPI() {
return advancedAchievementsAPI;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.hm.achievement.command.executable;

import com.hm.achievement.config.PluginHeader;
import com.hm.achievement.lifecycle.Reloadable;
import org.bukkit.ChatColor;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jspecify.annotations.NonNull;

/**
* Abstract class in charge of factoring out common functionality for commands.
Expand All @@ -14,11 +16,11 @@ public abstract class AbstractCommand implements Reloadable {

final YamlConfiguration mainConfig;
final YamlConfiguration langConfig;
final StringBuilder pluginHeader;
final PluginHeader pluginHeader;

private String langNoPermissions;

AbstractCommand(YamlConfiguration mainConfig, YamlConfiguration langConfig, StringBuilder pluginHeader) {
AbstractCommand(YamlConfiguration mainConfig, YamlConfiguration langConfig, PluginHeader pluginHeader) {
this.mainConfig = mainConfig;
this.langConfig = langConfig;
this.pluginHeader = pluginHeader;
Expand Down Expand Up @@ -53,7 +55,12 @@ public void execute(CommandSender sender, String[] args) {
*/
abstract void onExecute(CommandSender sender, String[] args);

String translateColorCodes(String translate) {
return ChatColor.translateAlternateColorCodes('&', translate);
protected Component replace(@NonNull Component component, String placeholder, String value) {
return component.replaceText(b -> b.matchLiteral(placeholder).replacement(value));
}

protected Component replace(@NonNull Component component, String @NonNull [] placeholders, String[] values) {
for (int i = 0; i < placeholders.length; i++) component = replace(component, placeholders[i], values[i]);
return component;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.hm.achievement.command.executable;

import com.hm.achievement.command.external.CommandUtils;
import com.hm.achievement.config.PluginHeader;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
Expand All @@ -18,7 +19,7 @@ public abstract class AbstractParsableCommand extends AbstractCommand {
private String langPlayerOffline;
private String langEntityNotPlayer;

AbstractParsableCommand(YamlConfiguration mainConfig, YamlConfiguration langConfig, StringBuilder pluginHeader) {
AbstractParsableCommand(YamlConfiguration mainConfig, YamlConfiguration langConfig, PluginHeader pluginHeader) {
super(mainConfig, langConfig, pluginHeader);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.hm.achievement.command.executable;

import com.hm.achievement.command.pagination.CommandPagination;
import com.hm.achievement.config.PluginHeader;
import com.hm.achievement.db.AbstractDatabaseManager;
import com.hm.achievement.utils.ColorHelper;
import com.hm.achievement.utils.SoundPlayer;
import com.hm.achievement.utils.StringHelper;
import java.util.ArrayList;
Expand All @@ -11,13 +13,15 @@
import java.util.Objects;
import java.util.UUID;
import java.util.logging.Logger;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.apache.commons.lang3.math.NumberUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Particle;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.jspecify.annotations.NonNull;

/**
* Abstract class in charge of factoring out common functionality for /aach top, week and month commands.
Expand All @@ -39,21 +43,20 @@ public abstract class AbstractRankingCommand extends AbstractCommand {
private final AbstractDatabaseManager databaseManager;
private final SoundPlayer soundPlayer;

private ChatColor configColor;
private NamedTextColor configColor;
private int configTopList;
private boolean configAdditionalEffects;
private boolean configSound;
private String configSoundRanking;
private String langPeriodAchievement;
private String langPlayerRank;
private String langNotRanked;
private Component langPeriodAchievement;
private Component langPlayerRank;
private Component langNotRanked;
// Used for caching.
private Map<String, Integer> cachedSortedRankings;
private List<Integer> cachedAchievementCounts;
private long lastCacheUpdate = 0L;

AbstractRankingCommand(YamlConfiguration mainConfig, YamlConfiguration langConfig, StringBuilder pluginHeader,
Logger logger, String languageKey, AbstractDatabaseManager databaseManager, SoundPlayer soundPlayer) {
AbstractRankingCommand(YamlConfiguration mainConfig, YamlConfiguration langConfig, PluginHeader pluginHeader, Logger logger, String languageKey, AbstractDatabaseManager databaseManager, SoundPlayer soundPlayer) {
super(mainConfig, langConfig, pluginHeader);
this.logger = logger;
this.languageKey = languageKey;
Expand All @@ -64,16 +67,15 @@ public abstract class AbstractRankingCommand extends AbstractCommand {
@Override
public void extractConfigurationParameters() {
super.extractConfigurationParameters();

configColor = ChatColor.getByChar(Objects.requireNonNull(mainConfig.getString("Color")));
configColor = ColorHelper.configColor(mainConfig);
configTopList = mainConfig.getInt("TopList");
configAdditionalEffects = mainConfig.getBoolean("AdditionalEffects");
configSound = mainConfig.getBoolean("Sound");
configSoundRanking = Objects.requireNonNull(mainConfig.getString("SoundRanking")).toUpperCase();

langPeriodAchievement = pluginHeader + langConfig.getString(languageKey);
langPlayerRank = pluginHeader + langConfig.getString("player-rank") + " " + configColor;
langNotRanked = pluginHeader + langConfig.getString("not-ranked");
langPeriodAchievement = Component.text().append(pluginHeader.get()).append(Component.text(Objects.requireNonNull(langConfig.getString(languageKey)))).build();
langPlayerRank = Component.text().append(pluginHeader.get()).append(Component.text(Objects.requireNonNull(langConfig.getString("player-rank")))).append(Component.text(" ").color(configColor)).build();
langNotRanked = Component.text().append(pluginHeader.get()).append(Component.text(Objects.requireNonNull(langConfig.getString("not-ranked")))).build();
}

@Override
Expand All @@ -87,7 +89,7 @@ public void onExecute(CommandSender sender, String[] args) {

sender.sendMessage(langPeriodAchievement);

List<String> rankingMessages = getRankingMessages(sender);
List<Component> rankingMessages = getRankingMessages(sender);

// If config has top set at less than one page, don't use pagination.
if (configTopList < PER_PAGE) {
Expand All @@ -110,43 +112,36 @@ public void onExecute(CommandSender sender, String[] args) {
if (playerRank <= configTopList) {
launchEffects((Player) sender);
}
sender.sendMessage(
langPlayerRank + playerRank + ChatColor.GRAY + "/" + configColor + cachedSortedRankings.size());
sender.sendMessage(langPlayerRank.append(Component.text(playerRank)).color(NamedTextColor.GRAY).append(Component.text("/").append(Component.text(cachedSortedRankings.size()))).color(NamedTextColor.GRAY));
}
}
}

private int getPage(String[] args) {
private int getPage(String @NonNull [] args) {
return args.length > 1 && NumberUtils.isDigits(args[1]) ? Integer.parseInt(args[1]) : 1;
}

private List<String> getRankingMessages(CommandSender sender) {
List<String> rankingMessages = new ArrayList<>();
private @NonNull List<Component> getRankingMessages(CommandSender sender) {
List<Component> rankingMessages = new ArrayList<>();
int currentRank = 1;
for (Entry<String, Integer> ranking : cachedSortedRankings.entrySet()) {
String playerName = Bukkit.getOfflinePlayer(UUID.fromString(ranking.getKey())).getName();
if (playerName != null) {
// Color the name of the player if he is in the top list.
ChatColor color = playerName.equals(sender.getName()) ? configColor : ChatColor.GRAY;
rankingMessages.add(color + " " + getRankingSymbol(currentRank) + " " + playerName + " - "
+ ranking.getValue());
} else {
logger.warning("Ranking command: could not find player's name using a database UUID.");
}

// Colour the name of the player if he is in the top list.
NamedTextColor color = playerName.equals(sender.getName()) ? configColor : NamedTextColor.GRAY;
rankingMessages.add(Component.text(" " + getRankingSymbol(currentRank) + " " + playerName + " - " + ranking.getValue()).color(color));
} else logger.warning("Ranking command: could not find player's name using a database UUID.");
++currentRank;
if (currentRank > configTopList) {
break;
}
if (currentRank > configTopList) break;
}
return rankingMessages;
}

/**
* Returns a UTF-8 circled number based on the player's rank.
*
* @param rank
* @return an UTF-8 string corresponding to the rank
* @param rank rank
* @return a UTF-8 string corresponding to the rank
*/
private String getRankingSymbol(int rank) {
int decimalRankSymbol;
Expand All @@ -172,15 +167,10 @@ private String getRankingSymbol(int rank) {
/**
* Launches sound and particle effects if player is in a top list.
*
* @param player
* @param player player
*/
private void launchEffects(Player player) {
if (configAdditionalEffects) {
player.spawnParticle(Particle.PORTAL, player.getLocation(), 100, 0, 1, 0, 0.5f);
}

if (configSound) {
soundPlayer.play(player, configSoundRanking, "ENTITY_FIREWORK_ROCKET_BLAST");
}
if (configAdditionalEffects) player.spawnParticle(Particle.PORTAL, player.getLocation(), 100, 0, 1, 0, 0.5f);
if (configSound) soundPlayer.play(player, configSoundRanking, "ENTITY_FIREWORK_ROCKET_BLAST");
}
}
Loading
Loading