Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.eternalcode.core.feature.afk;
package com.eternalcode.core.feature.afk.placeholder;

import com.eternalcode.annotations.scan.placeholder.PlaceholderDocs;
import com.eternalcode.core.feature.afk.Afk;
import com.eternalcode.core.feature.afk.AfkService;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.injector.annotations.component.Controller;
import com.eternalcode.core.placeholder.PlaceholderRegistry;
Expand Down Expand Up @@ -28,18 +31,56 @@ class AfkPlaceholderSetup {

@Subscribe(EternalInitializeEvent.class)
void setUpPlaceholders(PlaceholderRegistry placeholderRegistry, AfkService afkService) {
placeholderRegistry.registerPlaceholder(PlaceholderReplacer.of(
placeholderRegistry.registerPlaceholder(this.createAfkPlaceholder(afkService));
placeholderRegistry.registerPlaceholder(this.createAfkFormattedPlaceholder(afkService));
placeholderRegistry.registerPlaceholder(this.createAfkTimePlaceholder(afkService));
placeholderRegistry.registerPlaceholder(this.createAfkPlayerCountPlaceholder(afkService));
}

@PlaceholderDocs(
name = "afk",
description = "Returns true if the player is AFK, false otherwise",
example = "true",
returnType = "boolean",
category = "AFK",
requiresPlayer = true
)
private PlaceholderReplacer createAfkPlaceholder(AfkService afkService) {
return PlaceholderReplacer.of(
"afk",
player -> String.valueOf(afkService.isAfk(player.getUniqueId()))));
placeholderRegistry.registerPlaceholder(PlaceholderReplacer.of(
player -> String.valueOf(afkService.isAfk(player.getUniqueId()))
);
}

@PlaceholderDocs(
name = "afk_formatted",
description = "Returns a formatted AFK status message based on player's language settings",
example = "[AFK]",
returnType = "String",
category = "AFK",
requiresPlayer = true
)
private PlaceholderReplacer createAfkFormattedPlaceholder(AfkService afkService) {
return PlaceholderReplacer.of(
"afk_formatted",
player -> {
Translation messages = this.translationManager.getMessages(player.getUniqueId());
return afkService.isAfk(player.getUniqueId()) ?
messages.afk().afkEnabledPlaceholder() : messages.afk().afkDisabledPlaceholder();
}));
}
);
}

placeholderRegistry.registerPlaceholder(PlaceholderReplacer.of(
@PlaceholderDocs(
name = "afk_time",
description = "Returns the duration the player has been AFK in a formatted string",
example = "5m 30s",
returnType = "String",
category = "AFK",
requiresPlayer = true
)
private PlaceholderReplacer createAfkTimePlaceholder(AfkService afkService) {
return PlaceholderReplacer.of(
"afk_time",
player -> {
Optional<Afk> afkOptional = afkService.getAfk(player.getUniqueId());
Expand All @@ -52,16 +93,28 @@ void setUpPlaceholders(PlaceholderRegistry placeholderRegistry, AfkService afkSe
Instant now = Instant.now();
Duration afkDuration = Duration.between(start, now);
return DurationUtil.format(afkDuration, true);
}));
}
);
}

placeholderRegistry.registerPlaceholder(PlaceholderReplacer.of(
@PlaceholderDocs(
name = "afk_playercount",
description = "Returns the total number of AFK players on the server",
example = "3",
returnType = "int",
category = "AFK",
requiresPlayer = false
)
private PlaceholderReplacer createAfkPlayerCountPlaceholder(AfkService afkService) {
return PlaceholderReplacer.of(
"afk_playercount",
player -> {
ignoredPlayer -> {
long afkPlayerCount = this.server.getOnlinePlayers()
.stream()
.filter(onlinePlayer -> afkService.isAfk(onlinePlayer.getUniqueId()))
.count();
return String.valueOf(afkPlayerCount);
}));
}
);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.eternalcode.core.feature.home;

import com.eternalcode.annotations.scan.placeholder.PlaceholderDocs;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.injector.annotations.component.Controller;
import com.eternalcode.core.placeholder.PlaceholderRegistry;
Expand Down Expand Up @@ -28,46 +29,92 @@ class HomePlaceholderSetup {
@Subscribe(EternalInitializeEvent.class)
void setUp(PlaceholderRegistry placeholderRegistry) {
Stream.of(
PlaceholderReplacer.of("homes_owned", (text, targetPlayer) -> this.ownedHomes(targetPlayer)),
PlaceholderReplacer.of("homes_count", (text, targetPlayer) -> this.homesCount(targetPlayer)),
PlaceholderReplacer.of("homes_limit", (text, targetPlayer) -> this.homesLimit(targetPlayer)),
PlaceholderReplacer.of("homes_left", (text, targetPlayer) -> this.homesLeft(targetPlayer))
).forEach(placeholder -> placeholderRegistry.registerPlaceholder(placeholder));
this.createHomesOwnedPlaceholder(),
this.createHomesCountPlaceholder(),
this.createHomesLimitPlaceholder(),
this.createHomesLeftPlaceholder()
).forEach(placeholderRegistry::registerPlaceholder);
}

private String homesLeft(Player targetPlayer) {
int homesLimit = this.homeService.getHomeLimit(targetPlayer);
int amountOfHomes = this.homeService.getAmountOfHomes(targetPlayer.getUniqueId());
@PlaceholderDocs(
name = "homes_owned",
description = "Returns a comma-separated list of all homes owned by the player. If the player has no homes, returns a localized message.",
example = "home1, home2, domek",
returnType = "String",
category = "Home",
requiresPlayer = true
)
private PlaceholderReplacer createHomesOwnedPlaceholder() {
return PlaceholderReplacer.of(
"homes_owned",
(text, targetPlayer) -> {
Collection<Home> homes = this.homeService.getHomes(targetPlayer.getUniqueId());
Translation translation = this.translationManager.getMessages(targetPlayer.getUniqueId());

return homesLeft(homesLimit, amountOfHomes);
}

static String homesLeft(int homesLimit, int amountOfHomes) {
if (homesLimit < -1 || amountOfHomes > homesLimit) {
return "0";
}
if (homes.isEmpty()) {
return translation.home().noHomesOwnedPlaceholder();
}

int result = homesLimit - amountOfHomes;

return String.valueOf(result);
return homes.stream()
.map(Home::getName)
.collect(Collectors.joining(", "));
}
);
}

private String ownedHomes(Player targetPlayer) {
Collection<Home> homes = this.homeService.getHomes(targetPlayer.getUniqueId());
Translation translation = this.translationManager.getMessages(targetPlayer.getUniqueId());

if (homes.isEmpty()) {
return translation.home().noHomesOwnedPlaceholder();
}

return homes.stream().map(Home::getName).collect(Collectors.joining(", "));
@PlaceholderDocs(
name = "homes_count",
description = "Returns the number of homes the player currently owns.",
example = "3",
returnType = "int",
category = "Home",
requiresPlayer = true
)
private PlaceholderReplacer createHomesCountPlaceholder() {
return PlaceholderReplacer.of(
"homes_count",
(text, targetPlayer) ->
String.valueOf(this.homeService.getAmountOfHomes(targetPlayer.getUniqueId()))
);
}

private String homesCount(Player targetPlayer) {
return String.valueOf(this.homeService.getAmountOfHomes(targetPlayer.getUniqueId()));
@PlaceholderDocs(
name = "homes_limit",
description = "Returns the maximum number of homes the player can have.",
example = "5",
returnType = "int",
category = "Home",
requiresPlayer = true
)
private PlaceholderReplacer createHomesLimitPlaceholder() {
return PlaceholderReplacer.of(
"homes_limit",
(text, targetPlayer) ->
String.valueOf(this.homeService.getHomeLimit(targetPlayer))
);
}

private String homesLimit(Player targetPlayer) {
return String.valueOf(this.homeService.getHomeLimit(targetPlayer));
@PlaceholderDocs(
name = "homes_left",
description = "Returns how many more homes the player can create before reaching the limit.",
example = "2",
returnType = "int",
category = "Home",
requiresPlayer = true
)
private PlaceholderReplacer createHomesLeftPlaceholder() {
return PlaceholderReplacer.of(
"homes_left",
(text, targetPlayer) -> {
int homesLimit = this.homeService.getHomeLimit(targetPlayer);
int amountOfHomes = this.homeService.getAmountOfHomes(targetPlayer.getUniqueId());

if (homesLimit < -1 || amountOfHomes > homesLimit) {
return "0";
}

return String.valueOf(homesLimit - amountOfHomes);
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.eternalcode.annotations.scan.reflect.PackageUtil;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class EternalScanner {
Expand All @@ -16,10 +17,13 @@ public EternalScanner(ClassLoader classLoader, Package packageToScan) {
this.packageToScan = packageToScan;
}

public <RESULT, RESOLVER extends EternalScanResolver<RESULT>> List<RESULT> scan(RESOLVER resolver) {
public <RESULT, RESOLVER extends EternalScanResolver<RESULT>> List<RESULT> scan(RESOLVER resolver, Comparator<RESULT> sort) {
PackageStack packageStack = PackageUtil.createPackageStack(this.packageToScan, this.classLoader);

return this.scan(packageStack, resolver);
return this.scan(packageStack, resolver).stream()
.sorted(sort)
.distinct()
.toList();
}

private <RESULT, RESOLVER extends EternalScanResolver<RESULT>> List<RESULT> scan(PackageStack packageStack, RESOLVER resolver) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.eternalcode.annotations.scan.placeholder;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD })
public @interface PlaceholderDocs {

/**
* The name of the placeholder (without % symbols)
* Example: "afk" for %afk%
*/
String name();

/**
* Description of what the placeholder does
*/
String description();

/**
* Example output of the placeholder
*/
String example();

/**
* Return type of the placeholder
*/
String returnType();

/**
* Category for grouping placeholders
*/
String category() default "General";

/**
* Whether the placeholder requires a player context
*/
boolean requiresPlayer();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.eternalcode.annotations.scan.placeholder;

public record PlaceholderResult(
String name,
String description,
String example,
String returnType,
String category,
boolean requiresPlayer
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.eternalcode.annotations.scan.placeholder;

import com.eternalcode.annotations.scan.EternalScanRecord;
import com.eternalcode.annotations.scan.SingleAnnotationScanResolver;

public class PlaceholderScanResolver extends SingleAnnotationScanResolver<PlaceholderDocs, PlaceholderResult> {

public PlaceholderScanResolver() {
super(PlaceholderDocs.class);
}

@Override
public PlaceholderResult resolve(EternalScanRecord record, PlaceholderDocs annotation) {
String prefixedName = "%eternalcore_" + annotation.name() + "%";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
String prefixedName = "%eternalcore_" + annotation.name() + "%";
String prefix = "%eternalcore_" + annotation.name() + "%";

return new PlaceholderResult(
prefixedName,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
prefixedName,
prefix,

annotation.description(),
annotation.example(),
annotation.returnType(),
annotation.category(),
annotation.requiresPlayer()
);
}
}
8 changes: 8 additions & 0 deletions eternalcore-docs-generate/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,17 @@ dependencies {
runtimeOnly("org.panda-lang:panda-utilities:${Versions.PANDA_UTILITIES}")
runtimeOnly("commons-io:commons-io:${Versions.APACHE_COMMONS}")
runtimeOnly("dev.triumphteam:triumph-gui:${Versions.TRIUMPH_GUI}")
runtimeOnly("eu.okaeri:okaeri-configs-yaml-snakeyaml:${Versions.OKAERI_CONFIGS}")
runtimeOnly("eu.okaeri:okaeri-configs-serdes-commons:${Versions.OKAERI_CONFIGS}")
runtimeOnly("org.bstats:bstats-bukkit:${Versions.BSTATS}")
runtimeOnly("com.github.ben-manes.caffeine:caffeine:${Versions.CAFFEINE}")
runtimeOnly("com.eternalcode:multification-core:${Versions.MULTIFICATION}")
runtimeOnly("com.eternalcode:eternalcode-commons-bukkit:${Versions.ETERNALCODE_COMMONS}")
runtimeOnly("com.eternalcode:eternalcode-commons-adventure:${Versions.ETERNALCODE_COMMONS}")
runtimeOnly("com.eternalcode:eternalcode-commons-folia:${Versions.ETERNALCODE_COMMONS}")
runtimeOnly("com.eternalcode:eternalcode-commons-updater:${Versions.ETERNALCODE_COMMONS}")
runtimeOnly("com.github.cryptomorin:XSeries:${Versions.XSERIES}")
runtimeOnly("us.dynmap:dynmap-api:${Versions.DYNMAP_API}")
runtimeOnly("us.dynmap:DynmapCoreAPI:${Versions.DYNMAP_API}")
runtimeOnly("fr.skytasul:glowingentities:${Versions.GLOWING_ENTITIES}")
}
Loading