Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.
Merged

Dev #12

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
3e11654
Refactor CoreScheduler and ScheduledTask to remove Bukkit dependencie…
mzcydev Jul 22, 2025
bc0c950
Fix logging format in ConsoleHeader to remove unnecessary spaces
mzcydev Jul 22, 2025
b1f4cfa
Add event handler registration methods with execution limits and time…
mzcydev Jul 22, 2025
8f58b81
Remove plugin reference from CoreScheduler instantiation for improved…
mzcydev Jul 22, 2025
526aab8
Add chat pagination management classes for improved user experience
mzcydev Jul 22, 2025
1635d04
Implement database management system with support for multiple databa…
mzcydev Jul 22, 2025
46c2383
Bump version to 3.0-SNAPSHOT in build.gradle
mzcydev Jul 22, 2025
4da0a20
Add UI components and layout management for enhanced user interface
mzcydev Jul 22, 2025
cffbed7
Bump version to 3.0.1-SNAPSHOT in build.gradle
mzcydev Jul 22, 2025
af283de
Add DataStore and DataStoreRegistry classes for managing key-value pa…
mzcydev Jul 22, 2025
0647d46
Add performance monitoring components including LagGuard, Performance…
mzcydev Jul 22, 2025
14d6c60
Add debug logging framework with DebugContext, DebugFlagStore, DebugM…
mzcydev Jul 22, 2025
64e0cd1
Add messaging framework with MessageBus, MessageChannel, MessageEnvel…
mzcydev Jul 22, 2025
31610ca
Add AdvancedTaskScheduler and TaskBuilder for enhanced task schedulin…
mzcydev Jul 22, 2025
199738b
Update version to 2.2 in build.gradle
mzcydev Jul 22, 2025
4a5c6ec
Add backup and file management utilities with BackupHandler, Director…
mzcydev Jul 22, 2025
65178d0
Add backup and file management utilities with BackupHandler, Director…
mzcydev Jul 22, 2025
5b3b832
Update version to 2.3 in build.gradle
mzcydev Jul 22, 2025
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
23 changes: 22 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

group = 'gg.nextforge'
version = '2.0'
version = '2.3'

repositories {
mavenCentral()
Expand All @@ -28,6 +28,15 @@ sourceSets {
}
}

repositories {
maven {
url = 'https://repo.extendedclip.com/releases/'
}
maven {
url 'https://jitpack.io'
}
}

dependencies {
paperweight.paperDevBundle("1.19.1-R0.1-SNAPSHOT")

Expand All @@ -37,6 +46,18 @@ dependencies {
implementation "org.mozilla:rhino:1.7.14"
implementation "com.google.code.gson:gson:2.10.1"
implementation "org.bstats:bstats-bukkit:3.0.2"

implementation 'org.redisson:redisson:3.50.0'
implementation 'com.mysql:mysql-connector-j:9.3.0'
implementation 'org.xerial:sqlite-jdbc:3.50.3.0'
implementation 'com.h2database:h2:2.3.232'
implementation 'org.mongodb:mongodb-driver-sync:5.5.1'

implementation 'org.reflections:reflections:0.10.2'

compileOnly 'me.clip:placeholderapi:2.11.6'
compileOnly "com.github.MilkBowl:VaultAPI:1.7"
compileOnly 'net.luckperms:api:5.4'
}

subprojects {
Expand Down
52 changes: 52 additions & 0 deletions src/main/java/gg/nextforge/bridge/BridgeBootstrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package gg.nextforge.bridge;

import gg.nextforge.bridge.annotations.Bridge;
import org.reflections.Reflections;

import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Automatically discovers and registers all PluginBridges annotated with @Bridge.
*/
public class BridgeBootstrapper {

private static final Logger LOGGER = Logger.getLogger("BridgeBootstrapper");

private final BridgeManager bridgeManager;

public BridgeBootstrapper(BridgeManager bridgeManager) {
this.bridgeManager = bridgeManager;
}

/**
* Scans and registers all bridges annotated with @Bridge.
*/
public void loadBridges(String basePackage) {
Reflections reflections = new Reflections(basePackage);
Set<Class<?>> bridgeClasses = reflections.getTypesAnnotatedWith(Bridge.class);

for (Class<?> clazz : bridgeClasses) {
if (!PluginBridge.class.isAssignableFrom(clazz)) {
LOGGER.warning("Invalid @Bridge class (not a PluginBridge): " + clazz.getName());
continue;
}

try {
PluginBridge instance = (PluginBridge) clazz.getDeclaredConstructor().newInstance();
Bridge annotation = clazz.getAnnotation(Bridge.class);

if (annotation.enabled()) {
bridgeManager.register(instance);
LOGGER.info("Registered bridge: " + clazz.getSimpleName());
} else {
LOGGER.info("Bridge disabled (annotation): " + clazz.getSimpleName());
}

} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Failed to initialize bridge: " + clazz.getName(), e);
}
}
}
}
69 changes: 69 additions & 0 deletions src/main/java/gg/nextforge/bridge/BridgeManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package gg.nextforge.bridge;

import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;

import java.util.*;
import java.util.logging.Logger;

/**
* Central manager for all plugin bridges.
*/
public class BridgeManager {

private static final Logger LOGGER = Logger.getLogger("BridgeManager");

private final Map<Class<? extends PluginBridge>, PluginBridge> bridges = new HashMap<>();

/**
* Registers and tries to initialize the bridge.
*/
public void register(PluginBridge bridge) {
String pluginName = bridge.getPluginName();

Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
if (plugin != null && plugin.isEnabled()) {
try {
bridge.onEnable(plugin);
bridge.setStatus(BridgeStatus.ENABLED);
LOGGER.info("Bridge enabled: " + pluginName);
} catch (Exception e) {
bridge.setStatus(BridgeStatus.FAILED);
LOGGER.warning("Failed to enable bridge for " + pluginName + ": " + e.getMessage());
}
} else {
bridge.setStatus(BridgeStatus.MISSING);
LOGGER.info("Bridge missing: " + pluginName);
}

bridges.put(bridge.getClass(), bridge);
}

/**
* Returns true if a bridge is available and enabled.
*/
public boolean isAvailable(String pluginName) {
return bridges.values().stream()
.anyMatch(b -> b.getPluginName().equalsIgnoreCase(pluginName) && b.isEnabled());
}

/**
* Gets the bridge by class if registered.
*/
@SuppressWarnings("unchecked")
public <T extends PluginBridge> Optional<T> get(Class<T> type) {
return Optional.ofNullable((T) bridges.get(type));
}

/**
* Calls onDisable on all loaded bridges.
*/
public void shutdown() {
for (PluginBridge bridge : bridges.values()) {
if (bridge.isEnabled()) {
bridge.onDisable();
}
}
bridges.clear();
}
}
27 changes: 27 additions & 0 deletions src/main/java/gg/nextforge/bridge/BridgeStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package gg.nextforge.bridge;

/**
* Represents the current status of a plugin bridge.
*/
public enum BridgeStatus {

/** Plugin not found or not supported */
MISSING,

/** Plugin found but initialization failed */
FAILED,

/** Plugin found and bridge initialized successfully */
ENABLED,

/** Bridge not yet initialized */
UNINITIALIZED;

public boolean isReady() {
return this == ENABLED;
}

public boolean isMissingOrFailed() {
return this == MISSING || this == FAILED;
}
}
45 changes: 45 additions & 0 deletions src/main/java/gg/nextforge/bridge/PluginBridge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package gg.nextforge.bridge;

import gg.nextforge.bridge.BridgeStatus;
import org.bukkit.plugin.Plugin;

/**
* Base class for defining plugin bridges.
* Handles lifecycle and dependency check.
*/
public abstract class PluginBridge {

private BridgeStatus status = BridgeStatus.UNINITIALIZED;

/**
* Name of the external plugin this bridge supports.
*/
public abstract String getPluginName();

/**
* Called if the plugin is available and the bridge is loaded.
* @param plugin the detected plugin instance
*/
public abstract void onEnable(Plugin plugin);

/**
* Called when the bridge should shut down or disconnect.
*/
public void onDisable() {}

public final void setStatus(BridgeStatus status) {
this.status = status;
}

public final BridgeStatus getStatus() {
return status;
}

public final boolean isEnabled() {
return status == BridgeStatus.ENABLED;
}

public final boolean isFailed() {
return status == BridgeStatus.FAILED;
}
}
24 changes: 24 additions & 0 deletions src/main/java/gg/nextforge/bridge/annotations/Bridge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package gg.nextforge.bridge.annotations;

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

/**
* Marks a PluginBridge for automatic discovery and registration.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bridge {

/**
* Whether to enable this bridge by default.
*/
boolean enabled() default true;

/**
* Optional description of the bridge.
*/
String description() default "";
}
55 changes: 55 additions & 0 deletions src/main/java/gg/nextforge/bridge/impl/LuckPermsBridge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package gg.nextforge.bridge;

import gg.nextforge.bridge.annotations.Bridge;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import net.luckperms.api.model.user.User;
import net.luckperms.api.node.Node;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

/**
* Integration bridge for LuckPerms.
*/
@Bridge(description = "Integration with LuckPerms")
public class LuckPermsBridge extends PluginBridge {

private LuckPerms api;

@Override
public String getPluginName() {
return "LuckPerms";
}

@Override
public void onEnable(Plugin plugin) {
this.api = LuckPermsProvider.get();
}

public LuckPerms getApi() {
return api;
}

public boolean hasPermission(Player player, String permissionNode) {
User user = api.getUserManager().getUser(player.getUniqueId());
if (user == null) return false;

return user.getCachedData().getPermissionData().checkPermission(permissionNode).asBoolean();
}

public void addPermission(Player player, String permissionNode) {
User user = api.getUserManager().getUser(player.getUniqueId());
if (user != null) {
user.data().add(Node.builder(permissionNode).build());
api.getUserManager().saveUser(user);
}
}

public void removePermission(Player player, String permissionNode) {
User user = api.getUserManager().getUser(player.getUniqueId());
if (user != null) {
user.data().remove(Node.builder(permissionNode).build());
api.getUserManager().saveUser(user);
}
}
}
33 changes: 33 additions & 0 deletions src/main/java/gg/nextforge/bridge/impl/PlaceholderAPIBridge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package gg.nextforge.bridge.impl;

import gg.nextforge.bridge.PluginBridge;
import gg.nextforge.bridge.annotations.Bridge;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

/**
* Integration bridge for PlaceholderAPI.
*/
@Bridge(description = "Integration with PlaceholderAPI")
public class PlaceholderAPIBridge extends PluginBridge {

@Override
public String getPluginName() {
return "PlaceholderAPI";
}

@Override
public void onEnable(Plugin plugin) {
// Optional setup if needed
}

public String setPlaceholder(Player player, String placeholder) {
return PlaceholderAPI.setPlaceholders(player, placeholder);
}

public String setPlaceholder(OfflinePlayer offlinePlayer, String placeholder) {
return PlaceholderAPI.setPlaceholders(offlinePlayer, placeholder);
}
}
Loading
Loading