Examples
Complete Working Example
Here's a complete example of a feature-rich neuron:
public class ServerInfoNeuron extends BukkitNeuron {
private final Plugin plugin;
private final AtomicLong lastUpdate = new AtomicLong(0);
public ServerInfoNeuron(Plugin plugin) {
super(plugin, Namespace.of("server", "srv"));
this.plugin = plugin;
registerAllPlaceholders();
}
private void registerAllPlaceholders() {
// Static placeholders
register("name", () -> Bukkit.getServerName());
register("version", () -> Bukkit.getVersion());
register("bukkit_version", () -> Bukkit.getBukkitVersion());
// Dynamic placeholders with caching
register("online", () -> Bukkit.getOnlinePlayers().size(),
options -> {
options.cache(true);
options.cacheTTL(5, TimeUnit.SECONDS);
});
register("max_players", () -> Bukkit.getMaxPlayers());
// Contextual placeholders
register("player_world", context -> {
Player player = context.user().requirePlayer();
World world = player.getWorld();
return world != null ? world.getName() : "unknown";
});
register("tps", context -> {
// Simulate TPS calculation
return String.format("%.2f", 20.0);
}, options -> {
options.cache(true);
options.cacheTTL(10, TimeUnit.SECONDS);
});
// Placeholder with arguments - using method reference for cleaner code
register("world_info", this::getWorldInfo);
}
private Object getWorldInfo(Context<BukkitUser> context) {
String[] args = context.arguments();
if (args.length == 0) {
return "Specify: players, entities, or chunks";
}
Player player = context.user().requirePlayer();
World world = player.getWorld();
if (world == null) return "No world";
return switch (args[0].toLowerCase()) {
case "players" -> world.getPlayers().size();
case "entities" -> world.getEntities().size();
case "chunks" -> world.getLoadedChunks().length;
default -> "Invalid option: " + args[0];
};
}
}
This neuron provides placeholders like:
${server.name},${srv.name}- Server name${server.online}- Online player count (cached)${server.player_world}- Current player's world${server.world_info:players}- Players in current world
Option Usage Examples
Performance Optimization Scenarios
public class OptimizedNeuron extends BukkitNeuron {
public OptimizedNeuron(Plugin plugin) {
super(plugin, Namespace.of("optimized"));
// Heavy calculation - run async with refresh
register("server_load", () -> {
// Simulate heavy CPU calculation
return String.format("%.1f%%", calculateCPUUsage());
}, options -> {
options.async(true); // Don't block main thread
options.refresh(true); // Keep value updated
options.delay(15, TimeUnit.SECONDS); // Update every 15s
});
// Database lookup - cache per user
register("user_data", context -> {
return queryUserDatabase(context.user().getUniqueId());
}, options -> {
options.cache(true); // Cache expensive DB query
options.cacheTTL(2, TimeUnit.MINUTES); // Refresh every 2 min
});
// API call with arguments - cache with TTL
register("external_data", context -> {
String endpoint = context.arguments().length > 0
? context.arguments()[0]
: "default";
return callExternalAPI(endpoint, context.user());
}, options -> {
options.cache(true); // Cache API responses
options.cacheTTL(1, TimeUnit.MINUTES); // Short TTL for API data
});
// Relationship calculation - expensive relational operation
registerRelational("player_similarity", context -> {
// Complex algorithm comparing two players
return calculateSimilarityScore(
context.user().getUniqueId(),
context.other().getUniqueId()
);
}, options -> {
options.cache(true); // Cache relationship calculations
options.cacheTTL(30, TimeUnit.MINUTES); // Long TTL for relationships
});
}
}
Choosing the Right Options
When to use async(true) (Static only):
- Database operations
- File I/O operations
- Network requests
- Heavy computations
- Any operation that might block for >50ms
When to use cache(true):
- Database lookups
- API calls
- Complex calculations
- File reads
- Any operation repeated frequently with same inputs
Cache TTL Guidelines:
- Short TTL (1-5 minutes): Frequently changing data, API responses
- Medium TTL (5-30 minutes): User stats, rankings, moderately dynamic data
- Long TTL (30+ minutes): Relationships, permissions, rarely changing data
Refresh Guidelines (Static only):
- High frequency (1-10 seconds): Server stats, online counts
- Medium frequency (30-60 seconds): Resource usage, queue lengths
- Low frequency (5+ minutes): Configuration values, external service status
This gives you fine-grained control over performance and ensures your placeholders scale well with your server's needs!