├── .github └── workflows │ └── gradle.yml ├── .gitignore ├── Bukkit ├── build.gradle.kts └── src │ ├── main │ ├── java │ │ └── net │ │ │ └── frankheijden │ │ │ └── serverutils │ │ │ └── bukkit │ │ │ ├── ServerUtils.java │ │ │ ├── commands │ │ │ ├── BukkitCommandPlugins.java │ │ │ └── BukkitCommandServerUtils.java │ │ │ ├── config │ │ │ └── BukkitMessageKey.java │ │ │ ├── entities │ │ │ ├── BukkitAudience.java │ │ │ ├── BukkitAudienceProvider.java │ │ │ ├── BukkitPlugin.java │ │ │ ├── BukkitPluginDescription.java │ │ │ ├── BukkitResourceProvider.java │ │ │ └── BukkitYamlConfig.java │ │ │ ├── events │ │ │ ├── BukkitPluginDisableEvent.java │ │ │ ├── BukkitPluginEnableEvent.java │ │ │ ├── BukkitPluginEvent.java │ │ │ ├── BukkitPluginLoadEvent.java │ │ │ └── BukkitPluginUnloadEvent.java │ │ │ ├── listeners │ │ │ └── BukkitPlayerListener.java │ │ │ ├── managers │ │ │ ├── BukkitPluginManager.java │ │ │ └── BukkitTaskManager.java │ │ │ ├── reflection │ │ │ ├── RCommandDispatcher.java │ │ │ ├── RCommandMap.java │ │ │ ├── RCommandNode.java │ │ │ ├── RCraftServer.java │ │ │ ├── RCraftingManager.java │ │ │ ├── RDedicatedServer.java │ │ │ ├── RDedicatedServerProperties.java │ │ │ ├── RDedicatedServerSettings.java │ │ │ ├── RIRegistryCustom.java │ │ │ ├── RJavaPlugin.java │ │ │ ├── RJavaPluginLoader.java │ │ │ ├── RJsonList.java │ │ │ ├── RMinecraftKey.java │ │ │ ├── RMinecraftServer.java │ │ │ ├── ROptionSet.java │ │ │ ├── RPlayerList.java │ │ │ ├── RPluginClassLoader.java │ │ │ ├── RPropertyManager.java │ │ │ ├── RRegistryMaterials.java │ │ │ ├── RRegistrySimple.java │ │ │ └── RSimplePluginManager.java │ │ │ └── utils │ │ │ ├── ReloadHandler.java │ │ │ └── VersionReloadHandler.java │ └── resources │ │ ├── bukkit-commands.json │ │ ├── bukkit-config.json │ │ └── bukkit-messages.json │ └── test │ └── java │ └── net │ └── frankheijden │ └── serverutils │ └── bukkit │ └── config │ └── BukkitMessageKeyTest.java ├── Bungee ├── build.gradle.kts └── src │ └── main │ ├── java │ └── net │ │ └── frankheijden │ │ └── serverutils │ │ └── bungee │ │ ├── ServerUtils.java │ │ ├── commands │ │ ├── BungeeCommandPlugins.java │ │ └── BungeeCommandServerUtils.java │ │ ├── entities │ │ ├── BungeeAudience.java │ │ ├── BungeeAudienceProvider.java │ │ ├── BungeePlugin.java │ │ ├── BungeePluginDescription.java │ │ ├── BungeeResourceProvider.java │ │ └── BungeeYamlConfig.java │ │ ├── events │ │ ├── BungeePluginDisableEvent.java │ │ ├── BungeePluginEnableEvent.java │ │ ├── BungeePluginEvent.java │ │ ├── BungeePluginLoadEvent.java │ │ └── BungeePluginUnloadEvent.java │ │ ├── listeners │ │ └── BungeePlayerListener.java │ │ ├── managers │ │ ├── BungeePluginManager.java │ │ └── BungeeTaskManager.java │ │ └── reflection │ │ ├── RPluginClassLoader.java │ │ └── RPluginManager.java │ └── resources │ ├── bungee-commands.json │ ├── bungee-config.json │ └── bungee-messages.json ├── Common ├── build.gradle.kts └── src │ ├── main │ ├── java │ │ └── net │ │ │ └── frankheijden │ │ │ └── serverutils │ │ │ └── common │ │ │ ├── ServerUtilsApp.java │ │ │ ├── commands │ │ │ ├── CommandPlugins.java │ │ │ ├── CommandServerUtils.java │ │ │ ├── ServerUtilsCommand.java │ │ │ ├── arguments │ │ │ │ ├── JarFilesArgument.java │ │ │ │ ├── PluginArgument.java │ │ │ │ └── PluginsArgument.java │ │ │ └── brigadier │ │ │ │ └── BrigadierHandler.java │ │ │ ├── config │ │ │ ├── CommandsResource.java │ │ │ ├── ConfigKey.java │ │ │ ├── ConfigResource.java │ │ │ ├── JsonConfig.java │ │ │ ├── MessageKey.java │ │ │ ├── MessagesResource.java │ │ │ ├── PlaceholderConfigKey.java │ │ │ ├── ServerUtilsConfig.java │ │ │ └── ServerUtilsResource.java │ │ │ ├── entities │ │ │ ├── AbstractTask.java │ │ │ ├── ServerUtilsAudience.java │ │ │ ├── ServerUtilsPlugin.java │ │ │ ├── ServerUtilsPluginDescription.java │ │ │ ├── exceptions │ │ │ │ └── InvalidPluginDescriptionException.java │ │ │ ├── http │ │ │ │ ├── GitHubAsset.java │ │ │ │ ├── GitHubRateLimit.java │ │ │ │ └── GitHubResponse.java │ │ │ └── results │ │ │ │ ├── AbstractResult.java │ │ │ │ ├── CloseablePluginResult.java │ │ │ │ ├── CloseablePluginResults.java │ │ │ │ ├── PluginResult.java │ │ │ │ ├── PluginResults.java │ │ │ │ ├── PluginWatchResult.java │ │ │ │ ├── PluginWatchResults.java │ │ │ │ ├── Result.java │ │ │ │ └── WatchResult.java │ │ │ ├── events │ │ │ ├── PluginDisableEvent.java │ │ │ ├── PluginEnableEvent.java │ │ │ ├── PluginEvent.java │ │ │ ├── PluginLoadEvent.java │ │ │ └── PluginUnloadEvent.java │ │ │ ├── listeners │ │ │ ├── PlayerListener.java │ │ │ └── ServerUtilsListener.java │ │ │ ├── managers │ │ │ ├── AbstractPluginManager.java │ │ │ ├── AbstractTaskManager.java │ │ │ ├── UpdateManager.java │ │ │ └── WatchManager.java │ │ │ ├── providers │ │ │ ├── PluginProvider.java │ │ │ ├── ResourceProvider.java │ │ │ └── ServerUtilsAudienceProvider.java │ │ │ ├── tasks │ │ │ ├── PluginWatcherTask.java │ │ │ └── UpdateCheckerTask.java │ │ │ ├── util │ │ │ └── HashGraph.java │ │ │ └── utils │ │ │ ├── DependencyUtils.java │ │ │ ├── FileUtils.java │ │ │ ├── ForwardFilter.java │ │ │ ├── GitHubUtils.java │ │ │ ├── KeyValueComponentBuilder.java │ │ │ ├── ListComponentBuilder.java │ │ │ ├── MapUtils.java │ │ │ ├── PredicateFilter.java │ │ │ ├── ReflectionUtils.java │ │ │ ├── StringUtils.java │ │ │ └── VersionUtils.java │ └── resources │ │ ├── commands.json │ │ ├── config.json │ │ └── messages.json │ └── test │ └── java │ └── net │ └── frankheijden │ └── serverutils │ └── common │ ├── config │ └── MessageKeyTest.java │ └── utils │ ├── DependencyUtilsTest.java │ ├── ListBuilderTest.java │ └── VersionUtilsTest.java ├── LICENSE ├── README.md ├── Velocity ├── build.gradle.kts └── src │ └── main │ ├── java │ └── net │ │ └── frankheijden │ │ └── serverutils │ │ └── velocity │ │ ├── ServerUtils.java │ │ ├── commands │ │ ├── VelocityCommandPlugins.java │ │ └── VelocityCommandServerUtils.java │ │ ├── entities │ │ ├── VelocityAudience.java │ │ ├── VelocityAudienceProvider.java │ │ ├── VelocityPlugin.java │ │ ├── VelocityPluginDescription.java │ │ ├── VelocityResourceProvider.java │ │ └── VelocityTomlConfig.java │ │ ├── events │ │ ├── VelocityPluginDisableEvent.java │ │ ├── VelocityPluginEnableEvent.java │ │ ├── VelocityPluginEvent.java │ │ ├── VelocityPluginLoadEvent.java │ │ └── VelocityPluginUnloadEvent.java │ │ ├── listeners │ │ └── VelocityPlayerListener.java │ │ ├── managers │ │ ├── VelocityPluginCommandManager.java │ │ ├── VelocityPluginManager.java │ │ └── VelocityTaskManager.java │ │ └── reflection │ │ ├── RJavaPluginLoader.java │ │ ├── RVelocityCommandManager.java │ │ ├── RVelocityConsole.java │ │ ├── RVelocityEventManager.java │ │ ├── RVelocityPluginContainer.java │ │ ├── RVelocityPluginManager.java │ │ └── RVelocityScheduler.java │ └── resources │ ├── velocity-commands.json │ ├── velocity-config.json │ └── velocity-messages.json ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── VersionConstants.kt ├── config └── checkstyle │ ├── checkstyle.xml │ └── suppressions.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: Java CI with Gradle 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | java-version: [ 8 ] 13 | fail-fast: true 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Setup JDK ${{ matrix.java-version }} 17 | uses: actions/setup-java@v2 18 | with: 19 | distribution: adopt 20 | java-version: ${{ matrix.java-version }} 21 | - name: Grant execute permission for gradlew 22 | run: chmod +x gradlew 23 | - name: Build 24 | run: ./gradlew clean build --stacktrace 25 | - name: Upload artififacts 26 | uses: actions/upload-artifact@v2.2.1 27 | with: 28 | name: ServerUtils 29 | path: jars/*.jar 30 | - name: Publish 31 | if: ${{ github.event_name == 'push' }} 32 | env: 33 | FVDH_USERNAME: ${{ secrets.FVDH_USERNAME }} 34 | FVDH_TOKEN: ${{ secrets.FVDH_TOKEN }} 35 | run: ./gradlew publish --stacktrace 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vs/ 3 | .gradle/ 4 | build/ 5 | jars/ 6 | *.class 7 | *.jar -------------------------------------------------------------------------------- /Bukkit/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | 3 | plugins { 4 | id("net.minecrell.plugin-yml.bukkit") version "0.5.0" 5 | } 6 | 7 | group = rootProject.group 8 | val rootDependencyDir = "${rootProject.group}.dependencies" 9 | val dependencyDir = "${group}.bukkit.dependencies" 10 | version = rootProject.version 11 | base { 12 | archivesName.set("${rootProject.name}-Bukkit") 13 | } 14 | 15 | dependencies { 16 | implementation("cloud.commandframework:cloud-paper:${VersionConstants.cloudVersion}") 17 | implementation("net.kyori:adventure-api:${VersionConstants.adventureVersion}") { 18 | exclude("net.kyori", "adventure-text-minimessage") 19 | } 20 | implementation("net.kyori:adventure-platform-bukkit:${VersionConstants.adventurePlatformVersion}") { 21 | exclude("net.kyori", "adventure-api") 22 | exclude("net.kyori", "adventure-text-minimessage") 23 | } 24 | implementation("net.kyori:adventure-text-minimessage:${VersionConstants.adventureMinimessageVersion}") { 25 | exclude("net.kyori", "adventure-api") 26 | } 27 | implementation("org.bstats:bstats-bukkit:${VersionConstants.bstatsVersion}") 28 | implementation(project(":Common")) 29 | compileOnly("com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT") { 30 | exclude("net.kyori", "*") 31 | } 32 | } 33 | 34 | tasks.withType { 35 | relocate("org.bstats", "${dependencyDir}.bstats") 36 | } 37 | 38 | bukkit { 39 | name = "ServerUtils" 40 | main = "net.frankheijden.serverutils.bukkit.ServerUtils" 41 | description = "A server utility" 42 | apiVersion = "1.13" 43 | website = "https://github.com/FrankHeijden/ServerUtils" 44 | softDepend = listOf("ServerUtilsUpdater") 45 | authors = listOf("FrankHeijden") 46 | } 47 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/ServerUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import net.frankheijden.serverutils.bukkit.entities.BukkitPlugin; 8 | import net.frankheijden.serverutils.bukkit.managers.BukkitPluginManager; 9 | import net.frankheijden.serverutils.bukkit.reflection.RCraftServer; 10 | import net.frankheijden.serverutils.common.ServerUtilsApp; 11 | import net.frankheijden.serverutils.common.utils.StringUtils; 12 | import org.bstats.bukkit.Metrics; 13 | import org.bukkit.Bukkit; 14 | import org.bukkit.command.Command; 15 | import org.bukkit.command.PluginCommand; 16 | import org.bukkit.command.defaults.PluginsCommand; 17 | import org.bukkit.plugin.Plugin; 18 | import org.bukkit.plugin.java.JavaPlugin; 19 | 20 | public class ServerUtils extends JavaPlugin { 21 | 22 | private static ServerUtils instance; 23 | 24 | private BukkitPlugin plugin; 25 | 26 | @Override 27 | public void onEnable() { 28 | super.onEnable(); 29 | instance = this; 30 | 31 | this.plugin = new BukkitPlugin(this); 32 | ServerUtilsApp.init(this, plugin); 33 | 34 | new Metrics(this, ServerUtilsApp.BSTATS_METRICS_ID); 35 | plugin.enable(); 36 | } 37 | 38 | public static ServerUtils getInstance() { 39 | return instance; 40 | } 41 | 42 | public BukkitPlugin getPlugin() { 43 | return plugin; 44 | } 45 | 46 | @Override 47 | public void onDisable() { 48 | super.onDisable(); 49 | restoreBukkitPluginCommand(); 50 | RCraftServer.syncCommands(Collections.emptySet()); 51 | plugin.disable(); 52 | } 53 | 54 | public void restoreBukkitPluginCommand() { 55 | RCraftServer.getCommandMap().register("bukkit", new PluginsCommand("plugins")); 56 | } 57 | 58 | /** 59 | * Retrieves the disabled commands from the configuration. 60 | */ 61 | public List getDisabledCommands() { 62 | List commands = new ArrayList<>(); 63 | for (String cmd : plugin.getConfigResource().getConfig().getStringList("disabled-commands")) { 64 | String[] split = cmd.split(":"); 65 | 66 | Command command; 67 | if (split.length > 1) { 68 | String commandString = StringUtils.join(":", split, 1); 69 | PluginCommand pluginCommand = Bukkit.getPluginCommand(commandString); 70 | 71 | Optional pluginOptional = getPlugin().getPluginManager().getPlugin(split[0]); 72 | if (!pluginOptional.isPresent()) { 73 | getLogger().warning("Unknown plugin '" + split[0] + "' in disabled-commands!"); 74 | continue; 75 | } else if (pluginCommand == null) { 76 | getLogger().warning("Unknown command '" + commandString + "' in disabled-commands!"); 77 | continue; 78 | } else if (pluginOptional.get().getName().equalsIgnoreCase(pluginCommand.getPlugin().getName())) { 79 | // No output here, plugin didn't match! 80 | continue; 81 | } 82 | command = pluginCommand; 83 | } else { 84 | command = BukkitPluginManager.getCommand(split[0]); 85 | if (command == null) { 86 | getLogger().warning("Unknown command '" + split[0] + "' in disabled-commands!"); 87 | continue; 88 | } 89 | } 90 | commands.add(command); 91 | } 92 | return commands; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/commands/BukkitCommandPlugins.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.commands; 2 | 3 | import cloud.commandframework.Command; 4 | import cloud.commandframework.CommandManager; 5 | import cloud.commandframework.context.CommandContext; 6 | import net.frankheijden.serverutils.bukkit.entities.BukkitAudience; 7 | import net.frankheijden.serverutils.bukkit.entities.BukkitPlugin; 8 | import net.frankheijden.serverutils.bukkit.entities.BukkitPluginDescription; 9 | import net.frankheijden.serverutils.common.commands.CommandPlugins; 10 | import org.bukkit.plugin.Plugin; 11 | 12 | @SuppressWarnings("LineLength") 13 | public class BukkitCommandPlugins extends CommandPlugins { 14 | 15 | public BukkitCommandPlugins(BukkitPlugin plugin) { 16 | super(plugin); 17 | } 18 | 19 | @Override 20 | protected void register( 21 | CommandManager manager, 22 | Command.Builder builder 23 | ) { 24 | manager.command(builder 25 | .flag(parseFlag("version")) 26 | .handler(this::handlePlugins)); 27 | } 28 | 29 | @Override 30 | protected void handlePlugins(CommandContext context) { 31 | BukkitAudience sender = context.getSender(); 32 | boolean hasVersionFlag = context.flags().contains("version"); 33 | 34 | handlePlugins(sender, plugin.getPluginManager().getPluginsSorted(), hasVersionFlag); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/config/BukkitMessageKey.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.config; 2 | 3 | import java.util.Locale; 4 | import net.frankheijden.serverutils.common.config.PlaceholderConfigKey; 5 | 6 | public enum BukkitMessageKey implements PlaceholderConfigKey { 7 | 8 | RELOADCONFIG_SUCCESS("reloadconfig.success"), 9 | RELOADCONFIG_WARNINGS("reloadconfig.warnings"), 10 | RELOADCONFIG_NOT_EXISTS("reloadconfig.not-exists"), 11 | RELOADCONFIG_NOT_SUPPORTED("reloadconfig.not-supported"), 12 | ENABLEPLUGIN("enableplugin"), 13 | DISABLEPLUGIN("disableplugin"), 14 | ; 15 | 16 | private final String path; 17 | private final boolean hasPlaceholders; 18 | 19 | BukkitMessageKey(String path) { 20 | this(path, true); 21 | } 22 | 23 | BukkitMessageKey(String path, boolean hasPlaceholders) { 24 | this.path = path; 25 | this.hasPlaceholders = hasPlaceholders; 26 | } 27 | 28 | public static BukkitMessageKey fromPath(String path) { 29 | return BukkitMessageKey.valueOf(path.replaceAll("\\.|-", "_").toUpperCase(Locale.ENGLISH)); 30 | } 31 | 32 | @Override 33 | public String getPath() { 34 | return path; 35 | } 36 | 37 | @Override 38 | public boolean hasPlaceholders() { 39 | return hasPlaceholders; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/entities/BukkitAudience.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.entities; 2 | 3 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 4 | import net.kyori.adventure.audience.Audience; 5 | import org.bukkit.command.CommandSender; 6 | import org.bukkit.entity.Player; 7 | 8 | public class BukkitAudience extends ServerUtilsAudience { 9 | 10 | public BukkitAudience(Audience audience, CommandSender source) { 11 | super(audience, source); 12 | } 13 | 14 | @Override 15 | public boolean isPlayer() { 16 | return source instanceof Player; 17 | } 18 | 19 | @Override 20 | public boolean hasPermission(String permission) { 21 | return source.hasPermission(permission); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/entities/BukkitAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.entities; 2 | 3 | import net.frankheijden.serverutils.bukkit.ServerUtils; 4 | import net.frankheijden.serverutils.common.providers.ServerUtilsAudienceProvider; 5 | import net.kyori.adventure.platform.bukkit.BukkitAudiences; 6 | import net.kyori.adventure.text.Component; 7 | import org.bukkit.command.CommandSender; 8 | 9 | public class BukkitAudienceProvider implements ServerUtilsAudienceProvider { 10 | 11 | private final BukkitAudiences audiences; 12 | private final BukkitAudience consoleServerAudience; 13 | 14 | /** 15 | * Constructs a new BukkitAudienceProvider. 16 | */ 17 | public BukkitAudienceProvider(ServerUtils plugin, BukkitAudiences audiences) { 18 | this.audiences = audiences; 19 | this.consoleServerAudience = new BukkitAudience( 20 | audiences.console(), 21 | plugin.getServer().getConsoleSender() 22 | ); 23 | } 24 | 25 | @Override 26 | public BukkitAudience getConsoleServerAudience() { 27 | return this.consoleServerAudience; 28 | } 29 | 30 | @Override 31 | public BukkitAudience get(CommandSender source) { 32 | return new BukkitAudience(audiences.sender(source), source); 33 | } 34 | 35 | @Override 36 | public void broadcast(Component component, String permission) { 37 | audiences.filter(sender -> sender.hasPermission(permission)).sendMessage(component); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/entities/BukkitPluginDescription.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.entities; 2 | 3 | import java.io.File; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription; 7 | import org.bukkit.plugin.PluginDescriptionFile; 8 | 9 | public class BukkitPluginDescription implements ServerUtilsPluginDescription { 10 | 11 | private final PluginDescriptionFile descriptionFile; 12 | private final File file; 13 | private final String author; 14 | private final Set dependencies; 15 | 16 | /** 17 | * Constructs a new BukkitPluginDescription. 18 | */ 19 | public BukkitPluginDescription(PluginDescriptionFile descriptionFile, File file) { 20 | this.descriptionFile = descriptionFile; 21 | this.file = file; 22 | this.author = String.join(", ", this.descriptionFile.getAuthors()); 23 | this.dependencies = new HashSet<>(descriptionFile.getDepend()); 24 | } 25 | 26 | @Override 27 | public String getId() { 28 | return this.descriptionFile.getName(); 29 | } 30 | 31 | @Override 32 | public String getName() { 33 | return this.descriptionFile.getName(); 34 | } 35 | 36 | @Override 37 | public String getVersion() { 38 | return this.descriptionFile.getVersion(); 39 | } 40 | 41 | @Override 42 | public String getAuthor() { 43 | return this.author; 44 | } 45 | 46 | @Override 47 | public File getFile() { 48 | return this.file; 49 | } 50 | 51 | @Override 52 | public Set getDependencies() { 53 | return this.dependencies; 54 | } 55 | 56 | public PluginDescriptionFile getDescriptionFile() { 57 | return descriptionFile; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/entities/BukkitResourceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.entities; 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | import net.frankheijden.serverutils.bukkit.ServerUtils; 6 | import net.frankheijden.serverutils.common.config.ServerUtilsConfig; 7 | import net.frankheijden.serverutils.common.providers.ResourceProvider; 8 | 9 | public class BukkitResourceProvider implements ResourceProvider { 10 | 11 | private final ServerUtils plugin; 12 | 13 | public BukkitResourceProvider(ServerUtils plugin) { 14 | this.plugin = plugin; 15 | } 16 | 17 | @Override 18 | public InputStream getResource(String resource) { 19 | return getRawResource(resource + getResourceExtension()); 20 | } 21 | 22 | @Override 23 | public InputStream getRawResource(String resource) { 24 | return plugin.getResource(resource); 25 | } 26 | 27 | @Override 28 | public ServerUtilsConfig load(InputStream is) { 29 | return new BukkitYamlConfig(is); 30 | } 31 | 32 | @Override 33 | public ServerUtilsConfig load(File file) { 34 | return new BukkitYamlConfig(file); 35 | } 36 | 37 | @Override 38 | public String getResourceExtension() { 39 | return ".yml"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/entities/BukkitYamlConfig.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.entities; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.Collection; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import net.frankheijden.serverutils.common.config.ServerUtilsConfig; 12 | import org.bukkit.configuration.MemorySection; 13 | import org.bukkit.configuration.file.YamlConfiguration; 14 | 15 | public class BukkitYamlConfig implements ServerUtilsConfig { 16 | 17 | private final MemorySection config; 18 | private File file = null; 19 | 20 | public BukkitYamlConfig(File file) { 21 | this.config = YamlConfiguration.loadConfiguration(file); 22 | this.file = file; 23 | } 24 | 25 | public BukkitYamlConfig(InputStream in) { 26 | this.config = YamlConfiguration.loadConfiguration(new InputStreamReader(in)); 27 | } 28 | 29 | public BukkitYamlConfig(MemorySection section) { 30 | this.config = section; 31 | } 32 | 33 | @Override 34 | public Object get(String path) { 35 | Object obj = config.get(path); 36 | if (obj instanceof MemorySection) { 37 | return new BukkitYamlConfig((MemorySection) obj); 38 | } 39 | return obj; 40 | } 41 | 42 | @Override 43 | public List getStringList(String path) { 44 | return config.getStringList(path); 45 | } 46 | 47 | @Override 48 | public Map getMap(String path) { 49 | Object obj = config.get(path); 50 | if (obj instanceof MemorySection) { 51 | return ((MemorySection) obj).getValues(false); 52 | } 53 | return new HashMap<>(); 54 | } 55 | 56 | @Override 57 | public void setUnsafe(String path, Object value) { 58 | config.set(path, value); 59 | } 60 | 61 | @Override 62 | public void remove(String path) { 63 | config.set(path, null); 64 | } 65 | 66 | @Override 67 | public String getString(String path) { 68 | return config.getString(path); 69 | } 70 | 71 | @Override 72 | public boolean getBoolean(String path) { 73 | return config.getBoolean(path); 74 | } 75 | 76 | @Override 77 | public int getInt(String path) { 78 | return config.getInt(path, -1); 79 | } 80 | 81 | @Override 82 | public Collection getKeys() { 83 | return config.getKeys(false); 84 | } 85 | 86 | @Override 87 | public void save() throws IOException { 88 | if (!(config instanceof YamlConfiguration)) throw new IllegalArgumentException("Not a YamlConfiguration!"); 89 | YamlConfiguration yml = (YamlConfiguration) config; 90 | yml.save(file); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/events/BukkitPluginDisableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginDisableEvent; 4 | import org.bukkit.event.HandlerList; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | public class BukkitPluginDisableEvent extends BukkitPluginEvent implements PluginDisableEvent { 8 | 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | public BukkitPluginDisableEvent(Plugin plugin, Stage stage) { 12 | super(plugin, stage); 13 | } 14 | 15 | @Override 16 | public HandlerList getHandlers() { 17 | return handlers; 18 | } 19 | 20 | public static HandlerList getHandlerList() { 21 | return handlers; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/events/BukkitPluginEnableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginEnableEvent; 4 | import org.bukkit.event.HandlerList; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | public class BukkitPluginEnableEvent extends BukkitPluginEvent implements PluginEnableEvent { 8 | 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | public BukkitPluginEnableEvent(Plugin plugin, Stage stage) { 12 | super(plugin, stage); 13 | } 14 | 15 | @Override 16 | public HandlerList getHandlers() { 17 | return handlers; 18 | } 19 | 20 | public static HandlerList getHandlerList() { 21 | return handlers; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/events/BukkitPluginEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginEvent; 4 | import org.bukkit.event.Event; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | public abstract class BukkitPluginEvent extends Event implements PluginEvent { 8 | 9 | private final Plugin plugin; 10 | private final Stage stage; 11 | 12 | protected BukkitPluginEvent(Plugin plugin, Stage stage) { 13 | this.plugin = plugin; 14 | this.stage = stage; 15 | } 16 | 17 | @Override 18 | public Plugin getPlugin() { 19 | return plugin; 20 | } 21 | 22 | @Override 23 | public Stage getStage() { 24 | return stage; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/events/BukkitPluginLoadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginLoadEvent; 4 | import org.bukkit.event.HandlerList; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | public class BukkitPluginLoadEvent extends BukkitPluginEvent implements PluginLoadEvent { 8 | 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | public BukkitPluginLoadEvent(Plugin plugin, Stage stage) { 12 | super(plugin, stage); 13 | } 14 | 15 | @Override 16 | public HandlerList getHandlers() { 17 | return handlers; 18 | } 19 | 20 | public static HandlerList getHandlerList() { 21 | return handlers; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/events/BukkitPluginUnloadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginUnloadEvent; 4 | import org.bukkit.event.HandlerList; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | public class BukkitPluginUnloadEvent extends BukkitPluginEvent implements PluginUnloadEvent { 8 | 9 | private static final HandlerList handlers = new HandlerList(); 10 | 11 | public BukkitPluginUnloadEvent(Plugin plugin, Stage stage) { 12 | super(plugin, stage); 13 | } 14 | 15 | @Override 16 | public HandlerList getHandlers() { 17 | return handlers; 18 | } 19 | 20 | public static HandlerList getHandlerList() { 21 | return handlers; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/listeners/BukkitPlayerListener.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.listeners; 2 | 3 | import net.frankheijden.serverutils.bukkit.entities.BukkitAudience; 4 | import net.frankheijden.serverutils.bukkit.entities.BukkitPlugin; 5 | import net.frankheijden.serverutils.common.listeners.PlayerListener; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.EventPriority; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerJoinEvent; 10 | import org.bukkit.plugin.Plugin; 11 | 12 | public class BukkitPlayerListener 13 | extends PlayerListener 14 | implements Listener { 15 | 16 | public BukkitPlayerListener(BukkitPlugin plugin) { 17 | super(plugin); 18 | } 19 | 20 | /** 21 | * Called when a player joins the server. 22 | * Used for sending an update message to the player, if enabled and has permission. 23 | * @param event The PlayerJoinEvent. 24 | */ 25 | @EventHandler(priority = EventPriority.MONITOR) 26 | public void onPlayerJoin(PlayerJoinEvent event) { 27 | handleUpdate(plugin.getChatProvider().get(event.getPlayer())); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/managers/BukkitTaskManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.managers; 2 | 3 | import net.frankheijden.serverutils.bukkit.ServerUtils; 4 | import net.frankheijden.serverutils.common.managers.AbstractTaskManager; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.scheduler.BukkitTask; 7 | 8 | public class BukkitTaskManager extends AbstractTaskManager { 9 | 10 | public BukkitTaskManager() { 11 | super(BukkitTask::cancel); 12 | } 13 | 14 | @Override 15 | protected BukkitTask runTaskImpl(Runnable runnable) { 16 | return Bukkit.getScheduler().runTask(ServerUtils.getInstance(), runnable); 17 | } 18 | 19 | @Override 20 | public BukkitTask runTaskLater(Runnable runnable, long delay) { 21 | return Bukkit.getScheduler().runTaskLater(ServerUtils.getInstance(), runnable, delay); 22 | } 23 | 24 | @Override 25 | protected BukkitTask runTaskAsynchronouslyImpl(Runnable runnable) { 26 | return Bukkit.getScheduler().runTaskAsynchronously(ServerUtils.getInstance(), runnable); 27 | } 28 | 29 | @Override 30 | public void cancelTask(BukkitTask task) { 31 | task.cancel(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RCommandDispatcher.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import com.mojang.brigadier.CommandDispatcher; 4 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 5 | import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion; 6 | import dev.frankheijden.minecraftreflection.exceptions.MinecraftReflectionException; 7 | import java.lang.reflect.Method; 8 | import java.util.Arrays; 9 | import java.util.Collection; 10 | 11 | public class RCommandDispatcher { 12 | 13 | private static final MinecraftReflection reflection; 14 | private static final Method getCommandDispatcherMethod; 15 | private static final Method getDispatcherMethod; 16 | 17 | static { 18 | if (MinecraftReflectionVersion.MINOR < 13) { 19 | reflection = null; 20 | getCommandDispatcherMethod = null; 21 | getDispatcherMethod = null; 22 | } else { 23 | if (MinecraftReflectionVersion.MINOR >= 17) { 24 | reflection = MinecraftReflection.of("net.minecraft.commands.CommandDispatcher"); 25 | } else { 26 | reflection = MinecraftReflection.of("net.minecraft.server.%s.CommandDispatcher"); 27 | } 28 | 29 | getCommandDispatcherMethod = Arrays.stream(RMinecraftServer.getReflection().getClazz().getDeclaredMethods()) 30 | .filter(m -> m.getReturnType().equals(reflection.getClazz())) 31 | .findAny() 32 | .get(); 33 | getDispatcherMethod = Arrays.stream(getCommandDispatcherMethod.getReturnType().getDeclaredMethods()) 34 | .filter(m -> CommandDispatcher.class.equals(m.getReturnType())) 35 | .findAny() 36 | .get(); 37 | } 38 | } 39 | 40 | public RCommandDispatcher() {} 41 | 42 | /** 43 | * Retrieves the command dispatcher. 44 | */ 45 | public static CommandDispatcher getDispatcher() { 46 | try { 47 | Object minecraftDispatcher = getCommandDispatcherMethod.invoke(RCraftServer.getConsole()); 48 | return (CommandDispatcher) getDispatcherMethod.invoke(minecraftDispatcher); 49 | } catch (ReflectiveOperationException ex) { 50 | throw new MinecraftReflectionException(ex); 51 | } 52 | } 53 | 54 | /** 55 | * Removes commands from the brigadier root node. 56 | */ 57 | public static void removeCommands(Collection commands) { 58 | if (MinecraftReflectionVersion.MINOR < 13) return; 59 | CommandDispatcher dispatcher = getDispatcher(); 60 | for (String command : commands) { 61 | RCommandNode.removeCommand(dispatcher.getRoot(), command); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RCommandMap.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import dev.frankheijden.minecraftreflection.exceptions.MinecraftReflectionException; 5 | import java.util.Map; 6 | import org.bukkit.command.Command; 7 | import org.bukkit.command.SimpleCommandMap; 8 | 9 | public class RCommandMap { 10 | 11 | private static final MinecraftReflection reflection = MinecraftReflection 12 | .of(SimpleCommandMap.class); 13 | 14 | /** 15 | * Gets the known commands from the given command map. 16 | * TODO: figure out which version causes method change. 17 | */ 18 | public static Map getKnownCommands(SimpleCommandMap map) { 19 | try { 20 | return reflection.get(map, "knownCommands"); 21 | } catch (MinecraftReflectionException ignored) { 22 | return reflection.invoke(map, "getKnownCommands"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RCommandNode.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import com.mojang.brigadier.tree.CommandNode; 4 | import dev.frankheijden.minecraftreflection.ClassObject; 5 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 6 | 7 | public class RCommandNode { 8 | 9 | private static final MinecraftReflection reflection; 10 | 11 | static { 12 | reflection = MinecraftReflection.of(CommandNode.class); 13 | } 14 | 15 | public RCommandNode() {} 16 | 17 | public static void removeCommand(Object node, String name) { 18 | reflection.invoke(node, "removeCommand", name); 19 | } 20 | 21 | public static String getName(Object node) { 22 | return reflection.invoke(node, "getName"); 23 | } 24 | 25 | public static void addChild(Object parent, Object child) { 26 | reflection.invoke(parent, "addChild", ClassObject.of(CommandNode.class, child)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RCraftingManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.exceptions.MinecraftReflectionException; 4 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 5 | import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion; 6 | import java.lang.reflect.Method; 7 | import java.util.Arrays; 8 | import java.util.Collection; 9 | import java.util.Map; 10 | import java.util.concurrent.atomic.AtomicBoolean; 11 | import java.util.function.Predicate; 12 | import net.frankheijden.serverutils.common.utils.MapUtils; 13 | import org.bukkit.plugin.Plugin; 14 | 15 | public class RCraftingManager { 16 | 17 | private static final MinecraftReflection reflection; 18 | private static final Method getCraftingManagerMethod; 19 | 20 | static { 21 | if (MinecraftReflectionVersion.MINOR >= 17) { 22 | reflection = MinecraftReflection.of("net.minecraft.world.item.crafting.CraftingManager"); 23 | } else if (MinecraftReflectionVersion.MINOR >= 12) { 24 | reflection = MinecraftReflection.of("net.minecraft.server.%s.CraftingManager"); 25 | } else { 26 | reflection = null; 27 | } 28 | 29 | if (MinecraftReflectionVersion.MINOR > 12) { 30 | getCraftingManagerMethod = Arrays.stream(RMinecraftServer.getReflection().getClazz().getDeclaredMethods()) 31 | .filter(m -> m.getReturnType().equals(reflection.getClazz())) 32 | .findAny() 33 | .get(); 34 | } else { 35 | getCraftingManagerMethod = null; 36 | } 37 | } 38 | 39 | private RCraftingManager() {} 40 | 41 | /** 42 | * Removes all associated recipes of a plugin. 43 | * @param plugin The plugin to remove recipes for. 44 | */ 45 | @SuppressWarnings({"unchecked", "rawtypes"}) 46 | public static void removeRecipesFor(Plugin plugin) { 47 | // Cleaning up recipes before MC 1.12 is not possible, 48 | // as recipes are not associated to plugins. 49 | if (MinecraftReflectionVersion.MINOR == 12) { 50 | RRegistryMaterials.removeKeysFor(reflection.get(null, "recipes"), plugin); 51 | } else if (MinecraftReflectionVersion.MINOR > 12) { 52 | Object server = RMinecraftServer.getReflection().invoke(null, "getServer"); 53 | Object craftingManager; 54 | try { 55 | craftingManager = getCraftingManagerMethod.invoke(server); 56 | } catch (ReflectiveOperationException ex) { 57 | throw new MinecraftReflectionException(ex); 58 | } 59 | 60 | Map recipes; 61 | if (MinecraftReflectionVersion.MINOR >= 17) { 62 | recipes = reflection.get(craftingManager, "c"); 63 | } else { 64 | recipes = reflection.get(craftingManager, "recipes"); 65 | } 66 | 67 | Predicate predicate = RMinecraftKey.matchingPluginPredicate(new AtomicBoolean(false), plugin); 68 | if (MinecraftReflectionVersion.MINOR == 13) { 69 | MapUtils.removeKeys(recipes, predicate); 70 | } else { 71 | Collection list = (Collection) recipes.values(); 72 | list.forEach(map -> MapUtils.removeKeys(map, predicate)); 73 | } 74 | 75 | if (MinecraftReflectionVersion.MINOR >= 18) { 76 | Map byName = reflection.get(craftingManager, "d"); 77 | MapUtils.removeKeys(byName, predicate); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RDedicatedServerProperties.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | 5 | public class RDedicatedServerProperties { 6 | 7 | private static final MinecraftReflection reflection = MinecraftReflection 8 | .of("net.minecraft.server.%s.DedicatedServerProperties"); 9 | 10 | public static MinecraftReflection getReflection() { 11 | return reflection; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RDedicatedServerSettings.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.ClassObject; 4 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 5 | import java.nio.file.Path; 6 | 7 | public class RDedicatedServerSettings { 8 | 9 | private static final MinecraftReflection reflection = MinecraftReflection 10 | .of("net.minecraft.server.%s.DedicatedServerSettings"); 11 | 12 | public static MinecraftReflection getReflection() { 13 | return reflection; 14 | } 15 | 16 | public static Object newInstance(Object options) { 17 | return reflection.newInstance(options); 18 | } 19 | 20 | /** 21 | * Initiates a new instance of DedicatedServerSettings. 22 | */ 23 | public static Object newInstance(Object registry, Object options) { 24 | return reflection.newInstance( 25 | ClassObject.of(RIRegistryCustom.getReflection().getClazz(), registry), 26 | ClassObject.of(options) 27 | ); 28 | } 29 | 30 | public static Path getServerPropertiesPath(Object instance) { 31 | return reflection.get(instance, "path"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RIRegistryCustom.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | 5 | public class RIRegistryCustom { 6 | 7 | private static final MinecraftReflection reflection = MinecraftReflection 8 | .of("net.minecraft.server.%s.IRegistryCustom"); 9 | 10 | public static MinecraftReflection getReflection() { 11 | return reflection; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RJavaPlugin.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import java.io.File; 5 | import org.bukkit.plugin.java.JavaPlugin; 6 | 7 | public class RJavaPlugin { 8 | 9 | private static final MinecraftReflection reflection = MinecraftReflection.of(JavaPlugin.class); 10 | 11 | public static MinecraftReflection getReflection() { 12 | return reflection; 13 | } 14 | 15 | public static ClassLoader getClassLoader(Object instance) { 16 | return reflection.invoke(instance, "getClassLoader"); 17 | } 18 | 19 | public static File getFile(Object instance) { 20 | return reflection.invoke(instance, "getFile"); 21 | } 22 | 23 | /** 24 | * Clears the JavaPlugin from instances and returns the classloader associated with it. 25 | */ 26 | public static void clearJavaPlugin(Object instance) { 27 | reflection.set(instance, "loader", null); 28 | reflection.set(instance, "classLoader", null); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RJavaPluginLoader.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import dev.frankheijden.minecraftreflection.exceptions.MinecraftReflectionException; 5 | import java.util.Collection; 6 | import java.util.Map; 7 | import java.util.concurrent.locks.ReentrantReadWriteLock; 8 | import org.bukkit.plugin.java.JavaPluginLoader; 9 | 10 | public class RJavaPluginLoader { 11 | 12 | private RJavaPluginLoader() {} 13 | 14 | private static final MinecraftReflection reflection = MinecraftReflection.of(JavaPluginLoader.class); 15 | 16 | public static MinecraftReflection getReflection() { 17 | return reflection; 18 | } 19 | 20 | /** 21 | * Removes the given classes from the JavaPluginLoader instance. 22 | * @param instance The instance. 23 | * @param list The list of classpaths. 24 | */ 25 | public static void removeClasses(Object instance, Collection list) { 26 | Map> classes = getFieldIfExists(instance, "classes"); 27 | if (classes != null) { 28 | for (String key : list) { 29 | classes.remove(key); 30 | } 31 | } 32 | 33 | Map classLoadLockCount = getFieldIfExists(instance, "classLoadLockCount"); 34 | if (classLoadLockCount != null) { 35 | for (String key : list) { 36 | classLoadLockCount.remove(key); 37 | } 38 | } 39 | 40 | Map classLoadLock = getFieldIfExists(instance, "classLoadLock"); 41 | if (classLoadLock != null) { 42 | for (String key : list) { 43 | classLoadLock.remove(key); 44 | } 45 | } 46 | } 47 | 48 | private static T getFieldIfExists(Object instance, String field) { 49 | try { 50 | return reflection.get(instance, field); 51 | } catch (MinecraftReflectionException ex) { 52 | if (ex.getCause() instanceof NoSuchFieldException) { 53 | return null; 54 | } else { 55 | throw ex; 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RJsonList.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | 5 | public class RJsonList { 6 | 7 | private static final MinecraftReflection reflection = MinecraftReflection.of("net.minecraft.server.%s.JsonList"); 8 | 9 | public static MinecraftReflection getReflection() { 10 | return reflection; 11 | } 12 | 13 | public static void load(Object jsonList) { 14 | reflection.invoke(jsonList, "load"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RMinecraftKey.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion; 5 | import java.util.Locale; 6 | import java.util.concurrent.atomic.AtomicBoolean; 7 | import java.util.function.Predicate; 8 | import org.bukkit.plugin.Plugin; 9 | 10 | public class RMinecraftKey { 11 | 12 | private static final MinecraftReflection reflection; 13 | 14 | static { 15 | if (MinecraftReflectionVersion.MINOR >= 17) { 16 | reflection = MinecraftReflection.of("net.minecraft.resources.MinecraftKey"); 17 | } else { 18 | reflection = MinecraftReflection.of("net.minecraft.server.%s.MinecraftKey"); 19 | } 20 | } 21 | 22 | private RMinecraftKey() {} 23 | 24 | public static MinecraftReflection getReflection() { 25 | return reflection; 26 | } 27 | 28 | /** 29 | * Retrieves the namespace of the specified MinecraftKey instance. 30 | * @param instance The MinecraftKey instance. 31 | * @return The namespace. 32 | */ 33 | public static String getNameSpace(Object instance) { 34 | if (MinecraftReflectionVersion.MINOR <= 13) { 35 | return reflection.get(instance, "a"); 36 | } else if (MinecraftReflectionVersion.MINOR == 17) { 37 | return reflection.invoke(instance, "getNamespace"); 38 | } else if (MinecraftReflectionVersion.MINOR >= 18) { 39 | return reflection.invoke(instance, "b"); 40 | } 41 | return reflection.get(instance, "namespace"); 42 | } 43 | 44 | public static boolean isFrom(Object instance, Plugin plugin) throws IllegalAccessException { 45 | String namespace = plugin.getName().toLowerCase(Locale.ROOT); 46 | return namespace.equalsIgnoreCase(getNameSpace(instance)); 47 | } 48 | 49 | /** 50 | * Creates a predicate which returns true if a MinecraftKey instance comes from the specified plugin. 51 | * @param errorThrown Requires an atomicboolean to ensure an exception is only thrown once, if any. 52 | * @param plugin The plugin to match the MinecraftKey instance with. 53 | * @return The predicate. 54 | */ 55 | public static Predicate matchingPluginPredicate(AtomicBoolean errorThrown, Plugin plugin) { 56 | return o -> { 57 | try { 58 | return RMinecraftKey.isFrom(o, plugin); 59 | } catch (IllegalAccessException ex) { 60 | if (!errorThrown.get()) { 61 | ex.printStackTrace(); 62 | errorThrown.set(true); 63 | } 64 | } 65 | return false; 66 | }; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RMinecraftServer.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion; 5 | 6 | public class RMinecraftServer { 7 | 8 | private static final MinecraftReflection reflection; 9 | 10 | static { 11 | if (MinecraftReflectionVersion.MINOR >= 17) { 12 | reflection = MinecraftReflection.of("net.minecraft.server.MinecraftServer"); 13 | } else { 14 | reflection = MinecraftReflection.of("net.minecraft.server.%s.MinecraftServer"); 15 | } 16 | } 17 | 18 | private RMinecraftServer() {} 19 | 20 | public static MinecraftReflection getReflection() { 21 | return reflection; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/ROptionSet.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | 5 | public class ROptionSet { 6 | 7 | private static final MinecraftReflection reflection = MinecraftReflection.of("joptsimple.OptionSet"); 8 | 9 | public static MinecraftReflection getReflection() { 10 | return reflection; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RPlayerList.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | 5 | public class RPlayerList { 6 | 7 | private static final MinecraftReflection reflection = MinecraftReflection 8 | .of("net.minecraft.server.%s.PlayerList"); 9 | 10 | public static MinecraftReflection getReflection() { 11 | return reflection; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RPluginClassLoader.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.Map; 5 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 6 | import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion; 7 | import dev.frankheijden.minecraftreflection.Reflection; 8 | import net.frankheijden.serverutils.common.utils.ReflectionUtils; 9 | import org.bukkit.plugin.PluginLoader; 10 | 11 | public class RPluginClassLoader { 12 | 13 | private static final MinecraftReflection reflection = MinecraftReflection 14 | .of("org.bukkit.plugin.java.PluginClassLoader"); 15 | 16 | public static MinecraftReflection getReflection() { 17 | return reflection; 18 | } 19 | 20 | /** 21 | * Clears and closes the provided classloader. 22 | * @param loader The classloader instance. 23 | */ 24 | public static void clearClassLoader(ClassLoader loader) { 25 | if (loader == null) return; 26 | if (reflection.getClazz().isInstance(loader)) { 27 | clearPluginClassLoader(loader); 28 | } 29 | } 30 | 31 | public static PluginLoader getLoader(ClassLoader loader) { 32 | if (loader == null) return null; 33 | return reflection.get(loader, "loader"); 34 | } 35 | 36 | public static ClassLoader getLibraryLoader(ClassLoader loader) { 37 | if (loader == null || MinecraftReflectionVersion.MINOR <= 16) return null; 38 | return reflection.get(loader, "libraryLoader"); 39 | } 40 | 41 | /** 42 | * Clears the plugin fields from the specified PluginClassLoader. 43 | */ 44 | public static void clearPluginClassLoader(Object classLoader) { 45 | if (classLoader == null) return; 46 | 47 | reflection.set(classLoader, "loader", null); 48 | if (MinecraftReflectionVersion.MINOR > 16) { 49 | ReflectionUtils.doPrivilegedWithUnsafe(unsafe -> { 50 | Field libraryLoaderField = Reflection.getField(reflection.getClazz(), "libraryLoader"); 51 | unsafe.putObject(classLoader, unsafe.objectFieldOffset(libraryLoaderField), null); 52 | }); 53 | } 54 | reflection.set(classLoader, "plugin", null); 55 | reflection.set(classLoader, "pluginInit", null); 56 | getClasses(classLoader).clear(); 57 | } 58 | 59 | public static Map> getClasses(Object classLoader) { 60 | return reflection.get(classLoader, "classes"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RPropertyManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | 5 | public class RPropertyManager { 6 | 7 | private static final MinecraftReflection reflection = MinecraftReflection 8 | .of("net.minecraft.server.%s.PropertyManager"); 9 | 10 | public static MinecraftReflection getReflection() { 11 | return reflection; 12 | } 13 | 14 | public static Object newInstance(Object options) { 15 | return ROptionSet.getReflection().newInstance(options); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RRegistryMaterials.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import java.util.Map; 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | import net.frankheijden.serverutils.common.utils.MapUtils; 7 | import org.bukkit.plugin.Plugin; 8 | 9 | public class RRegistryMaterials { 10 | 11 | private static final MinecraftReflection reflection = MinecraftReflection 12 | .of("net.minecraft.server.%s.RegistryMaterials"); 13 | 14 | public static MinecraftReflection getReflection() { 15 | return reflection; 16 | } 17 | 18 | /** 19 | * Removes all registered keys from an instance associated to the specified plugin. 20 | * @param instance The RegistryMaterials instance. 21 | * @param plugin The plugin to remove keys for. 22 | */ 23 | @SuppressWarnings("rawtypes") 24 | public static void removeKeysFor(Object instance, Plugin plugin) { 25 | Map map = reflection.get(instance, "b"); 26 | if (map == null) throw new RuntimeException("Map object was null!"); 27 | 28 | AtomicBoolean errorThrown = new AtomicBoolean(false); 29 | MapUtils.removeValues(map, RMinecraftKey.matchingPluginPredicate(errorThrown, plugin)); 30 | RRegistrySimple.removeKeyFor(instance, plugin); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RRegistrySimple.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import java.util.Map; 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | import net.frankheijden.serverutils.common.utils.MapUtils; 7 | import org.bukkit.plugin.Plugin; 8 | 9 | public class RRegistrySimple { 10 | 11 | private static final MinecraftReflection reflection = MinecraftReflection 12 | .of("net.minecraft.server.%s.RegistrySimple"); 13 | 14 | public static MinecraftReflection getReflection() { 15 | return reflection; 16 | } 17 | 18 | /** 19 | * Removes all registered MinecraftKey's from an instance associated to the specified plugin. 20 | * @param instance The RegistrySimple instance. 21 | * @param plugin The plugin to remove keys for. 22 | */ 23 | @SuppressWarnings("rawtypes") 24 | public static void removeKeyFor(Object instance, Plugin plugin) { 25 | Map map = reflection.get(instance, "c"); 26 | if (map == null) throw new RuntimeException("Map object was null!"); 27 | 28 | AtomicBoolean errorThrown = new AtomicBoolean(false); 29 | MapUtils.removeKeys(map, RMinecraftKey.matchingPluginPredicate(errorThrown, plugin)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/reflection/RSimplePluginManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.reflection; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 4 | import java.util.List; 5 | import java.util.Locale; 6 | import java.util.Map; 7 | import java.util.regex.Pattern; 8 | import org.bukkit.plugin.Plugin; 9 | import org.bukkit.plugin.PluginLoader; 10 | import org.bukkit.plugin.SimplePluginManager; 11 | 12 | public class RSimplePluginManager { 13 | 14 | private static final MinecraftReflection reflection = MinecraftReflection.of(SimplePluginManager.class); 15 | 16 | public static MinecraftReflection getReflection() { 17 | return reflection; 18 | } 19 | 20 | public static Map getFileAssociations(Object manager) throws IllegalAccessException { 21 | return reflection.get(manager, "fileAssociations"); 22 | } 23 | 24 | public static List getPlugins(Object manager) { 25 | return reflection.get(manager, "plugins"); 26 | } 27 | 28 | /** 29 | * Removes the lookup name of the plugin. 30 | * This ensures the plugin cannot be found anymore in Bukkit#getPlugin(String name). 31 | * @param manager The SimplePluginManager instance to remove the lookup name from. 32 | * @param name The name of the plugin to remove. 33 | */ 34 | public static void removeLookupName(Object manager, String name) { 35 | Map lookupNames = reflection.get(manager, "lookupNames"); 36 | if (lookupNames == null) return; 37 | lookupNames.remove(name.replace(' ', '_')); 38 | lookupNames.remove(name.replace(' ', '_').toLowerCase(Locale.ENGLISH)); // Paper 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/utils/ReloadHandler.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.utils; 2 | 3 | public interface ReloadHandler { 4 | 5 | void handle() throws Exception; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Bukkit/src/main/java/net/frankheijden/serverutils/bukkit/utils/VersionReloadHandler.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.utils; 2 | 3 | import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion; 4 | 5 | public class VersionReloadHandler implements ReloadHandler { 6 | 7 | private final int minecraftVersionMaximum; 8 | private final ReloadHandler handler; 9 | 10 | public VersionReloadHandler(int minecraftVersionMaximum, ReloadHandler handler) { 11 | this.minecraftVersionMaximum = minecraftVersionMaximum; 12 | this.handler = handler; 13 | } 14 | 15 | public int getMinecraftVersionMaximum() { 16 | return minecraftVersionMaximum; 17 | } 18 | 19 | @Override 20 | public void handle() throws Exception { 21 | if (MinecraftReflectionVersion.MINOR > minecraftVersionMaximum) { 22 | throw new Exception("ReloadHandler is incompatible with version " + MinecraftReflectionVersion.MINOR 23 | + ". Maximum version this handler supports is " + minecraftVersionMaximum + "."); 24 | } 25 | handler.handle(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Bukkit/src/main/resources/bukkit-commands.json: -------------------------------------------------------------------------------- 1 | { 2 | "commands": { 3 | "serverutils": { 4 | "subcommands": { 5 | "enableplugin": { 6 | "main": "enableplugin", 7 | "aliases": [ 8 | "ep" 9 | ], 10 | "permission": "serverutils.enableplugin", 11 | "description": "Enables the specified plugin(s).", 12 | "display-in-help": true 13 | }, 14 | "disableplugin": { 15 | "main": "disableplugin", 16 | "aliases": [ 17 | "dp" 18 | ], 19 | "permission": "serverutils.disableplugin", 20 | "description": "Disables the specified plugin(s).", 21 | "display-in-help": true, 22 | "flags": { 23 | "force": { 24 | "main": "force", 25 | "aliases": ["f"], 26 | "permission": "serverutils.disableplugin", 27 | "description": "Force disables the specified plugin(s).", 28 | "display-in-help": false 29 | } 30 | } 31 | }, 32 | "reloadconfig": { 33 | "main": "reloadconfig", 34 | "aliases": [ 35 | "rc" 36 | ], 37 | "permission": "serverutils.reloadconfig", 38 | "description": "Reloads particular server configurations." 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Bukkit/src/main/resources/bukkit-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings": { 3 | "disable-plugins-command": false 4 | }, 5 | "disabled-commands": [] 6 | } 7 | -------------------------------------------------------------------------------- /Bukkit/src/main/resources/bukkit-messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "messages": { 3 | "reloadconfig": { 4 | "success": "Successfully reloaded !", 5 | "warnings": "There were warnings while reloading , please check the console!", 6 | "not-exists": "Config does not exist.", 7 | "not-supported": "Config is not supported on your Minecraft version." 8 | }, 9 | "disableplugin": "Successfully disabled !", 10 | "enableplugin": "Successfully enabled !" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Bukkit/src/test/java/net/frankheijden/serverutils/bukkit/config/BukkitMessageKeyTest.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bukkit.config; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.assertj.core.api.Assertions.assertThatCode; 5 | 6 | import java.util.Arrays; 7 | import java.util.stream.Stream; 8 | import org.junit.jupiter.params.ParameterizedTest; 9 | import org.junit.jupiter.params.provider.Arguments; 10 | import org.junit.jupiter.params.provider.MethodSource; 11 | 12 | class BukkitMessageKeyTest { 13 | 14 | @ParameterizedTest(name = "key = {0}") 15 | @MethodSource("bukkitMessageKeyGenerator") 16 | void testMessageKeyConsistency(BukkitMessageKey key) { 17 | assertThatCode(() -> BukkitMessageKey.fromPath(key.getPath())).doesNotThrowAnyException(); 18 | assertThat(BukkitMessageKey.fromPath(key.getPath())).isEqualTo(key); 19 | } 20 | 21 | private static Stream bukkitMessageKeyGenerator() { 22 | return Arrays.stream(BukkitMessageKey.values()) 23 | .map(Arguments::of); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Bungee/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | 3 | plugins { 4 | id("net.minecrell.plugin-yml.bungee") version "0.5.0" 5 | } 6 | 7 | group = rootProject.group 8 | val rootDependencyDir = "${group}.dependencies" 9 | val dependencyDir = "${group}.bungee.dependencies" 10 | version = rootProject.version 11 | base { 12 | archivesName.set("${rootProject.name}-Bungee") 13 | } 14 | 15 | repositories { 16 | maven("https://oss.sonatype.org/content/repositories/snapshots") 17 | } 18 | 19 | dependencies { 20 | implementation("cloud.commandframework:cloud-bungee:${VersionConstants.cloudVersion}") 21 | implementation("net.kyori:adventure-api:${VersionConstants.adventureVersion}") { 22 | exclude("net.kyori", "adventure-text-minimessage") 23 | } 24 | implementation("net.kyori:adventure-platform-bungeecord:${VersionConstants.adventurePlatformVersion}") { 25 | exclude("net.kyori", "adventure-api") 26 | exclude("net.kyori", "adventure-text-minimessage") 27 | } 28 | implementation("net.kyori:adventure-text-minimessage:${VersionConstants.adventureMinimessageVersion}") { 29 | exclude("net.kyori", "adventure-api") 30 | } 31 | implementation("org.bstats:bstats-bungeecord:${VersionConstants.bstatsVersion}") 32 | implementation(project(":Common")) 33 | compileOnly("net.md-5:bungeecord-api:1.19-R0.1-SNAPSHOT") 34 | } 35 | 36 | tasks.withType { 37 | relocate("org.bstats", "${dependencyDir}.bstats") 38 | } 39 | 40 | bungee { 41 | name = "ServerUtils" 42 | main = "net.frankheijden.serverutils.bungee.ServerUtils" 43 | description = "A server utility" 44 | softDepends = setOf("ServerUtilsUpdater") 45 | author = "FrankHeijden" 46 | } 47 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/ServerUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee; 2 | 3 | import net.frankheijden.serverutils.bungee.entities.BungeePlugin; 4 | import net.frankheijden.serverutils.common.ServerUtilsApp; 5 | import net.md_5.bungee.api.plugin.Plugin; 6 | import org.bstats.bungeecord.Metrics; 7 | 8 | public class ServerUtils extends Plugin { 9 | 10 | private static ServerUtils instance; 11 | 12 | private BungeePlugin plugin; 13 | 14 | @Override 15 | public void onEnable() { 16 | super.onEnable(); 17 | instance = this; 18 | 19 | this.plugin = new BungeePlugin(this); 20 | ServerUtilsApp.init(this, plugin); 21 | 22 | new Metrics(this, ServerUtilsApp.BSTATS_METRICS_ID); 23 | plugin.enable(); 24 | } 25 | 26 | @Override 27 | public void onDisable() { 28 | super.onDisable(); 29 | plugin.disable(); 30 | } 31 | 32 | public static ServerUtils getInstance() { 33 | return instance; 34 | } 35 | 36 | public BungeePlugin getPlugin() { 37 | return plugin; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/commands/BungeeCommandPlugins.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.commands; 2 | 3 | import cloud.commandframework.Command; 4 | import cloud.commandframework.CommandManager; 5 | import cloud.commandframework.context.CommandContext; 6 | import net.frankheijden.serverutils.bungee.entities.BungeeAudience; 7 | import net.frankheijden.serverutils.bungee.entities.BungeePlugin; 8 | import net.frankheijden.serverutils.bungee.entities.BungeePluginDescription; 9 | import net.frankheijden.serverutils.common.commands.CommandPlugins; 10 | import net.md_5.bungee.api.plugin.Plugin; 11 | 12 | @SuppressWarnings("LineLength") 13 | public class BungeeCommandPlugins extends CommandPlugins { 14 | 15 | public BungeeCommandPlugins(BungeePlugin plugin) { 16 | super(plugin); 17 | } 18 | 19 | @Override 20 | protected void register( 21 | CommandManager manager, 22 | Command.Builder builder 23 | ) { 24 | manager.command(builder 25 | .flag(parseFlag("version")) 26 | .flag(parseFlag("modules")) 27 | .handler(this::handlePlugins)); 28 | } 29 | 30 | @Override 31 | protected void handlePlugins(CommandContext context) { 32 | BungeeAudience sender = context.getSender(); 33 | boolean hasVersionFlag = context.flags().contains("version"); 34 | boolean hasModulesFlag = context.flags().contains("modules"); 35 | 36 | handlePlugins(sender, plugin.getPluginManager().getPluginsSorted(hasModulesFlag), hasVersionFlag); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/commands/BungeeCommandServerUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.commands; 2 | 3 | import java.util.Arrays; 4 | import java.util.Map; 5 | import java.util.function.Consumer; 6 | import java.util.function.Function; 7 | import net.frankheijden.serverutils.bungee.ServerUtils; 8 | import net.frankheijden.serverutils.bungee.entities.BungeeAudience; 9 | import net.frankheijden.serverutils.bungee.entities.BungeePlugin; 10 | import net.frankheijden.serverutils.bungee.reflection.RPluginManager; 11 | import net.frankheijden.serverutils.common.commands.CommandServerUtils; 12 | import net.frankheijden.serverutils.common.utils.KeyValueComponentBuilder; 13 | import net.frankheijden.serverutils.common.utils.ListComponentBuilder; 14 | import net.kyori.adventure.text.Component; 15 | import net.md_5.bungee.api.plugin.Command; 16 | import net.md_5.bungee.api.plugin.Plugin; 17 | import net.md_5.bungee.api.plugin.PluginDescription; 18 | import net.md_5.bungee.api.plugin.PluginManager; 19 | 20 | public class BungeeCommandServerUtils extends CommandServerUtils { 21 | 22 | public BungeeCommandServerUtils(BungeePlugin plugin) { 23 | super(plugin, Plugin[]::new); 24 | } 25 | 26 | @Override 27 | protected KeyValueComponentBuilder createPluginInfo( 28 | KeyValueComponentBuilder builder, 29 | Function>, Component> listBuilderFunction, 30 | Plugin bungeePlugin 31 | ) { 32 | PluginDescription desc = bungeePlugin.getDescription(); 33 | 34 | return builder 35 | .key("Name").value(desc.getName()) 36 | .key("Version").value(desc.getVersion()) 37 | .key("Author").value(desc.getAuthor()) 38 | .key("Description").value(desc.getDescription()) 39 | .key("Main").value(desc.getMain()) 40 | .key("File").value(desc.getFile().getName()) 41 | .key("Depend").value(listBuilderFunction.apply(b -> b.addAll(desc.getDepends()))) 42 | .key("Soft Depend").value(listBuilderFunction.apply(b -> b.addAll(desc.getSoftDepends()))); 43 | } 44 | 45 | @Override 46 | protected KeyValueComponentBuilder createCommandInfo( 47 | KeyValueComponentBuilder builder, 48 | Function>, Component> listBuilderFunction, 49 | String commandName 50 | ) { 51 | PluginManager proxyPluginManager = ServerUtils.getInstance().getProxy().getPluginManager(); 52 | Map commands; 53 | try { 54 | commands = RPluginManager.getCommands(proxyPluginManager); 55 | } catch (IllegalAccessException ex) { 56 | ex.printStackTrace(); 57 | builder.key("Error").value("Please check the console."); 58 | return builder; 59 | } 60 | 61 | Command cmd = commands.get(commandName); 62 | Plugin plugin = RPluginManager.getPlugin(proxyPluginManager, cmd); 63 | 64 | return builder 65 | .key("Name").value(cmd.getName()) 66 | .key("Plugin").value(plugin == null ? "" : plugin.getDescription().getName()) 67 | .key("Aliases").value(listBuilderFunction.apply(b -> b.addAll(Arrays.asList(cmd.getAliases())))) 68 | .key("Permission").value(cmd.getPermission()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/entities/BungeeAudience.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.entities; 2 | 3 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 4 | import net.kyori.adventure.audience.Audience; 5 | import net.md_5.bungee.api.CommandSender; 6 | import net.md_5.bungee.api.connection.ProxiedPlayer; 7 | 8 | public class BungeeAudience extends ServerUtilsAudience { 9 | 10 | protected BungeeAudience(Audience audience, CommandSender source) { 11 | super(audience, source); 12 | } 13 | 14 | @Override 15 | public boolean isPlayer() { 16 | return source instanceof ProxiedPlayer; 17 | } 18 | 19 | @Override 20 | public boolean hasPermission(String permission) { 21 | return source.hasPermission(permission); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/entities/BungeeAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.entities; 2 | 3 | import net.frankheijden.serverutils.bungee.ServerUtils; 4 | import net.frankheijden.serverutils.common.providers.ServerUtilsAudienceProvider; 5 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences; 6 | import net.kyori.adventure.text.Component; 7 | import net.md_5.bungee.api.CommandSender; 8 | 9 | public class BungeeAudienceProvider implements ServerUtilsAudienceProvider { 10 | 11 | private final BungeeAudiences audiences; 12 | private final BungeeAudience consoleServerAudience; 13 | 14 | /** 15 | * Constructs a new BungeeAudienceProvider. 16 | */ 17 | public BungeeAudienceProvider(ServerUtils plugin, BungeeAudiences audiences) { 18 | this.audiences = audiences; 19 | this.consoleServerAudience = new BungeeAudience( 20 | audiences.console(), 21 | plugin.getProxy().getConsole() 22 | ); 23 | } 24 | 25 | @Override 26 | public BungeeAudience getConsoleServerAudience() { 27 | return consoleServerAudience; 28 | } 29 | 30 | @Override 31 | public BungeeAudience get(CommandSender source) { 32 | return new BungeeAudience(audiences.sender(source), source); 33 | } 34 | 35 | @Override 36 | public void broadcast(Component component, String permission) { 37 | audiences.filter(sender -> sender.hasPermission(permission)).sendMessage(component); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/entities/BungeePlugin.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.entities; 2 | 3 | import cloud.commandframework.bungee.BungeeCommandManager; 4 | import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; 5 | import java.io.File; 6 | import java.util.logging.Logger; 7 | import net.frankheijden.serverutils.bungee.ServerUtils; 8 | import net.frankheijden.serverutils.bungee.commands.BungeeCommandPlugins; 9 | import net.frankheijden.serverutils.bungee.commands.BungeeCommandServerUtils; 10 | import net.frankheijden.serverutils.bungee.listeners.BungeePlayerListener; 11 | import net.frankheijden.serverutils.bungee.managers.BungeePluginManager; 12 | import net.frankheijden.serverutils.bungee.managers.BungeeTaskManager; 13 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 14 | import net.kyori.adventure.platform.bungeecord.BungeeAudiences; 15 | import net.md_5.bungee.api.CommandSender; 16 | import net.md_5.bungee.api.plugin.Plugin; 17 | import net.md_5.bungee.api.scheduler.ScheduledTask; 18 | 19 | public class BungeePlugin extends ServerUtilsPlugin { 20 | 21 | private final ServerUtils plugin; 22 | private final BungeePluginManager pluginManager; 23 | private final BungeeTaskManager taskManager; 24 | private final BungeeResourceProvider resourceProvider; 25 | private final BungeeAudiences audiences; 26 | private final BungeeAudienceProvider chatProvider; 27 | 28 | /** 29 | * Creates a new BungeePlugin instance of ServerUtils. 30 | * @param plugin The ServerUtils plugin. 31 | */ 32 | public BungeePlugin(ServerUtils plugin) { 33 | this.plugin = plugin; 34 | this.pluginManager = new BungeePluginManager(); 35 | this.taskManager = new BungeeTaskManager(); 36 | this.resourceProvider = new BungeeResourceProvider(plugin); 37 | this.audiences = BungeeAudiences.create(plugin); 38 | this.chatProvider = new BungeeAudienceProvider(plugin, audiences); 39 | } 40 | 41 | @Override 42 | protected BungeeCommandManager newCommandManager() { 43 | return new BungeeCommandManager<>( 44 | plugin, 45 | AsynchronousCommandExecutionCoordinator.newBuilder().build(), 46 | chatProvider::get, 47 | BungeeAudience::getSource 48 | ); 49 | } 50 | 51 | @Override 52 | public Platform getPlatform() { 53 | return Platform.BUNGEE; 54 | } 55 | 56 | @Override 57 | public Plugin getPlugin() { 58 | return plugin; 59 | } 60 | 61 | @Override 62 | public BungeePluginManager getPluginManager() { 63 | return pluginManager; 64 | } 65 | 66 | @Override 67 | public BungeeTaskManager getTaskManager() { 68 | return taskManager; 69 | } 70 | 71 | @Override 72 | public BungeeResourceProvider getResourceProvider() { 73 | return resourceProvider; 74 | } 75 | 76 | @Override 77 | public BungeeAudienceProvider getChatProvider() { 78 | return chatProvider; 79 | } 80 | 81 | @Override 82 | public Logger getLogger() { 83 | return plugin.getLogger(); 84 | } 85 | 86 | @Override 87 | public File getDataFolder() { 88 | return plugin.getDataFolder(); 89 | } 90 | 91 | @Override 92 | protected void enablePlugin() { 93 | plugin.getProxy().getPluginManager().registerListener(plugin, new BungeePlayerListener(this)); 94 | } 95 | 96 | @Override 97 | protected void disablePlugin() { 98 | this.audiences.close(); 99 | } 100 | 101 | @Override 102 | protected void reloadPlugin() { 103 | new BungeeCommandPlugins(this).register(commandManager); 104 | new BungeeCommandServerUtils(this).register(commandManager); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/entities/BungeePluginDescription.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.entities; 2 | 3 | import java.io.File; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription; 7 | import net.md_5.bungee.api.plugin.PluginDescription; 8 | 9 | public class BungeePluginDescription implements ServerUtilsPluginDescription { 10 | 11 | private final PluginDescription description; 12 | private final File file; 13 | private final Set dependencies; 14 | 15 | /** 16 | * Constructs a new BungeePluginDescription. 17 | */ 18 | public BungeePluginDescription(PluginDescription description) { 19 | this.description = description; 20 | this.file = description.getFile(); 21 | this.dependencies = new HashSet<>(description.getDepends()); 22 | } 23 | 24 | @Override 25 | public String getId() { 26 | return this.description.getName(); 27 | } 28 | 29 | @Override 30 | public String getName() { 31 | return this.description.getName(); 32 | } 33 | 34 | @Override 35 | public String getVersion() { 36 | return this.description.getVersion(); 37 | } 38 | 39 | @Override 40 | public String getAuthor() { 41 | return this.description.getAuthor(); 42 | } 43 | 44 | @Override 45 | public File getFile() { 46 | return this.file; 47 | } 48 | 49 | @Override 50 | public Set getDependencies() { 51 | return this.dependencies; 52 | } 53 | 54 | public PluginDescription getDescription() { 55 | return description; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/entities/BungeeResourceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.entities; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import net.frankheijden.serverutils.bungee.ServerUtils; 7 | import net.frankheijden.serverutils.common.config.ServerUtilsConfig; 8 | import net.frankheijden.serverutils.common.providers.ResourceProvider; 9 | 10 | public class BungeeResourceProvider implements ResourceProvider { 11 | 12 | private final ServerUtils plugin; 13 | 14 | public BungeeResourceProvider(ServerUtils plugin) { 15 | this.plugin = plugin; 16 | } 17 | 18 | @Override 19 | public InputStream getRawResource(String resource) { 20 | return plugin.getResourceAsStream(resource); 21 | } 22 | 23 | @Override 24 | public ServerUtilsConfig load(InputStream is) { 25 | return new BungeeYamlConfig(is); 26 | } 27 | 28 | @Override 29 | public ServerUtilsConfig load(File file) { 30 | try { 31 | return new BungeeYamlConfig(file); 32 | } catch (IOException ex) { 33 | ex.printStackTrace(); 34 | } 35 | return null; 36 | } 37 | 38 | @Override 39 | public String getResourceExtension() { 40 | return ".yml"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/entities/BungeeYamlConfig.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.entities; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.Collection; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import net.frankheijden.serverutils.common.config.ServerUtilsConfig; 11 | import net.md_5.bungee.config.Configuration; 12 | import net.md_5.bungee.config.ConfigurationProvider; 13 | import net.md_5.bungee.config.YamlConfiguration; 14 | 15 | public class BungeeYamlConfig implements ServerUtilsConfig { 16 | 17 | private static final ConfigurationProvider provider = ConfigurationProvider.getProvider(YamlConfiguration.class); 18 | private final Configuration config; 19 | private File file = null; 20 | 21 | public BungeeYamlConfig(File file) throws IOException { 22 | this.config = provider.load(file); 23 | this.file = file; 24 | } 25 | 26 | public BungeeYamlConfig(InputStream in) { 27 | this.config = provider.load(in); 28 | } 29 | 30 | public BungeeYamlConfig(Configuration config) { 31 | this.config = config; 32 | } 33 | 34 | @Override 35 | public Object get(String path) { 36 | Object obj; 37 | try { 38 | obj = config.get(path); 39 | } catch (ClassCastException ignored) { 40 | return null; 41 | } 42 | 43 | if (obj instanceof Configuration) { 44 | return new BungeeYamlConfig((Configuration) obj); 45 | } 46 | return obj; 47 | } 48 | 49 | @Override 50 | public List getStringList(String path) { 51 | return config.getStringList(path); 52 | } 53 | 54 | @Override 55 | public Map getMap(String path) { 56 | Object obj = config.get(path); 57 | if (obj instanceof Configuration) { 58 | Configuration section = (Configuration) obj; 59 | Collection keys = section.getKeys(); 60 | Map map = new HashMap<>(keys.size()); 61 | for (String key : keys) { 62 | map.put(key, section.get(key)); 63 | } 64 | return map; 65 | } 66 | return new HashMap<>(); 67 | } 68 | 69 | @Override 70 | public void setUnsafe(String path, Object value) { 71 | config.set(path, value); 72 | } 73 | 74 | @Override 75 | public void remove(String path) { 76 | config.set(path, null); 77 | } 78 | 79 | @Override 80 | public String getString(String path) { 81 | return config.getString(path); 82 | } 83 | 84 | @Override 85 | public boolean getBoolean(String path) { 86 | return config.getBoolean(path); 87 | } 88 | 89 | @Override 90 | public int getInt(String path) { 91 | return config.getInt(path, -1); 92 | } 93 | 94 | @Override 95 | public Collection getKeys() { 96 | return config.getKeys(); 97 | } 98 | 99 | @Override 100 | public void save() throws IOException { 101 | provider.save(config, file); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/events/BungeePluginDisableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginDisableEvent; 4 | import net.md_5.bungee.api.plugin.Plugin; 5 | 6 | public class BungeePluginDisableEvent extends BungeePluginEvent implements PluginDisableEvent { 7 | 8 | public BungeePluginDisableEvent(Plugin plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/events/BungeePluginEnableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginEnableEvent; 4 | import net.md_5.bungee.api.plugin.Plugin; 5 | 6 | public class BungeePluginEnableEvent extends BungeePluginEvent implements PluginEnableEvent { 7 | 8 | public BungeePluginEnableEvent(Plugin plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/events/BungeePluginEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginEvent; 4 | import net.md_5.bungee.api.plugin.Event; 5 | import net.md_5.bungee.api.plugin.Plugin; 6 | 7 | public abstract class BungeePluginEvent extends Event implements PluginEvent { 8 | 9 | private final Plugin plugin; 10 | private final Stage stage; 11 | 12 | protected BungeePluginEvent(Plugin plugin, Stage stage) { 13 | this.plugin = plugin; 14 | this.stage = stage; 15 | } 16 | 17 | @Override 18 | public Plugin getPlugin() { 19 | return plugin; 20 | } 21 | 22 | @Override 23 | public Stage getStage() { 24 | return stage; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/events/BungeePluginLoadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginLoadEvent; 4 | import net.md_5.bungee.api.plugin.Plugin; 5 | 6 | public class BungeePluginLoadEvent extends BungeePluginEvent implements PluginLoadEvent { 7 | 8 | public BungeePluginLoadEvent(Plugin plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/events/BungeePluginUnloadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.events; 2 | 3 | import net.frankheijden.serverutils.common.events.PluginUnloadEvent; 4 | import net.md_5.bungee.api.plugin.Plugin; 5 | 6 | public class BungeePluginUnloadEvent extends BungeePluginEvent implements PluginUnloadEvent { 7 | 8 | public BungeePluginUnloadEvent(Plugin plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/listeners/BungeePlayerListener.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.listeners; 2 | 3 | import net.frankheijden.serverutils.bungee.entities.BungeeAudience; 4 | import net.frankheijden.serverutils.bungee.entities.BungeePlugin; 5 | import net.frankheijden.serverutils.common.listeners.PlayerListener; 6 | import net.md_5.bungee.api.event.ServerConnectEvent; 7 | import net.md_5.bungee.api.plugin.Listener; 8 | import net.md_5.bungee.api.plugin.Plugin; 9 | import net.md_5.bungee.event.EventHandler; 10 | 11 | public class BungeePlayerListener extends PlayerListener 12 | implements Listener { 13 | 14 | public BungeePlayerListener(BungeePlugin plugin) { 15 | super(plugin); 16 | } 17 | 18 | @EventHandler 19 | public void onServerConnect(ServerConnectEvent event) { 20 | if (event.getReason() != ServerConnectEvent.Reason.JOIN_PROXY) return; 21 | handleUpdate(plugin.getChatProvider().get(event.getPlayer())); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/managers/BungeeTaskManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.managers; 2 | 3 | import net.frankheijden.serverutils.bungee.ServerUtils; 4 | import net.frankheijden.serverutils.common.managers.AbstractTaskManager; 5 | import net.md_5.bungee.api.ProxyServer; 6 | import net.md_5.bungee.api.scheduler.ScheduledTask; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | public class BungeeTaskManager extends AbstractTaskManager { 10 | 11 | public BungeeTaskManager() { 12 | super(ScheduledTask::cancel); 13 | } 14 | 15 | @Override 16 | protected ScheduledTask runTaskImpl(Runnable runnable) { 17 | return runTaskAsynchronously(runnable); 18 | } 19 | 20 | @Override 21 | public ScheduledTask runTaskLater(Runnable runnable, long delay) { 22 | return ProxyServer.getInstance().getScheduler() 23 | .schedule(ServerUtils.getInstance(), runnable, delay * 50, TimeUnit.MILLISECONDS); 24 | } 25 | 26 | @Override 27 | protected ScheduledTask runTaskAsynchronouslyImpl(Runnable runnable) { 28 | return ProxyServer.getInstance().getScheduler().runAsync(ServerUtils.getInstance(), runnable); 29 | } 30 | 31 | @Override 32 | public void cancelTask(ScheduledTask task) { 33 | task.cancel(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/reflection/RPluginClassLoader.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.reflection; 2 | 3 | import java.util.Set; 4 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 5 | import net.md_5.bungee.api.plugin.Plugin; 6 | 7 | public class RPluginClassLoader { 8 | 9 | private static final MinecraftReflection reflection = MinecraftReflection 10 | .of("net.md_5.bungee.api.plugin.PluginClassloader"); 11 | 12 | private RPluginClassLoader() {} 13 | 14 | /** 15 | * Removes the PluginClassLoader of a specific plugin. 16 | */ 17 | public static Object removePluginClassLoader(Plugin plugin) { 18 | Set allLoaders = reflection.get(null, "allLoaders"); 19 | if (allLoaders == null) return null; 20 | 21 | Object matchingLoader = null; 22 | for (Object loader : allLoaders) { 23 | if (plugin.equals(reflection.get(loader, "plugin"))) { 24 | matchingLoader = loader; 25 | break; 26 | } 27 | } 28 | if (matchingLoader != null) allLoaders.remove(matchingLoader); 29 | return matchingLoader; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Bungee/src/main/java/net/frankheijden/serverutils/bungee/reflection/RPluginManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.bungee.reflection; 2 | 3 | import com.google.common.collect.Multimap; 4 | import dev.frankheijden.minecraftreflection.ClassObject; 5 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 6 | import java.util.Map; 7 | import java.util.Stack; 8 | import net.frankheijden.serverutils.common.utils.MapUtils; 9 | import net.md_5.bungee.api.plugin.Command; 10 | import net.md_5.bungee.api.plugin.Plugin; 11 | import net.md_5.bungee.api.plugin.PluginDescription; 12 | import org.yaml.snakeyaml.Yaml; 13 | 14 | public class RPluginManager { 15 | 16 | private static final MinecraftReflection reflection = MinecraftReflection 17 | .of("net.md_5.bungee.api.plugin.PluginManager"); 18 | 19 | private RPluginManager() {} 20 | 21 | /** 22 | * Clears the plugin from the PluginManager. 23 | * @param instance The instance of the PluginManager. 24 | * @param plugin The plugin to clear. 25 | */ 26 | public static void clearPlugin(Object instance, Plugin plugin) { 27 | String pluginName = plugin.getDescription().getName(); 28 | MapUtils.remove(reflection.get(instance, "plugins"), pluginName); 29 | MapUtils.remove(reflection.get(instance, "toLoad"), pluginName); 30 | } 31 | 32 | public static Yaml getYaml(Object instance) { 33 | return reflection.get(instance, "yaml"); 34 | } 35 | 36 | public static Map getCommands(Object instance) throws IllegalAccessException { 37 | return reflection.get(instance, "commandMap"); 38 | } 39 | 40 | public static Map getToLoad(Object pluginManager) { 41 | return reflection.get(pluginManager, "toLoad"); 42 | } 43 | 44 | public static void setToLoad(Object pluginManager, Map toLoad) { 45 | reflection.set(pluginManager, "toLoad", toLoad); 46 | } 47 | 48 | /** 49 | * Enables a plugin. 50 | */ 51 | public static boolean enablePlugin( 52 | Object pluginManager, 53 | Map pluginStatuses, 54 | Stack dependStack, 55 | PluginDescription plugin 56 | ) { 57 | return reflection.invoke(pluginManager, "enablePlugin", 58 | ClassObject.of(Map.class, pluginStatuses), 59 | ClassObject.of(Stack.class, dependStack), 60 | ClassObject.of(PluginDescription.class, plugin) 61 | ); 62 | } 63 | 64 | /** 65 | * Retrieves the registered plugin of the command. 66 | * @param instance The PluginManager instance. 67 | * @param cmd The command to check the plugin of. 68 | * @return The plugin of the command. 69 | */ 70 | public static Plugin getPlugin(Object instance, Command cmd) { 71 | Multimap plugins = reflection.get(instance, "commandsByPlugin"); 72 | if (plugins == null) return null; 73 | 74 | for (Map.Entry entry : plugins.entries()) { 75 | if (entry.getValue().equals(cmd)) return entry.getKey(); 76 | } 77 | return null; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Bungee/src/main/resources/bungee-commands.json: -------------------------------------------------------------------------------- 1 | { 2 | "commands": { 3 | "plugins": { 4 | "flags": { 5 | "modules": { 6 | "main": "modules", 7 | "aliases": [ 8 | "m" 9 | ], 10 | "permission": "serverutils.plugins.modules", 11 | "description": "Displays the proxy modules.", 12 | "display-in-help": true 13 | } 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Bungee/src/main/resources/bungee-config.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /Bungee/src/main/resources/bungee-messages.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /Common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | 3 | plugins { 4 | id("net.kyori.blossom") version "1.3.0" 5 | } 6 | 7 | group = rootProject.group 8 | version = "${rootProject.version}" 9 | base { 10 | archivesName.set("${rootProject.name}-Common") 11 | } 12 | 13 | repositories { 14 | maven("https://jitpack.io") 15 | } 16 | 17 | dependencies { 18 | compileOnly("net.kyori:adventure-platform-api:${VersionConstants.adventurePlatformVersion}") { 19 | exclude("net.kyori", "adventure-api") 20 | exclude("net.kyori", "adventure-text-minimessage") 21 | } 22 | compileOnly("net.kyori:adventure-text-minimessage:${VersionConstants.adventureMinimessageVersion}") 23 | compileOnly("com.github.FrankHeijden:ServerUtilsUpdater:5f722b10d1") 24 | 25 | testImplementation("net.kyori:adventure-text-serializer-plain:${VersionConstants.adventureVersion}") 26 | } 27 | 28 | tasks { 29 | blossom { 30 | replaceToken("{version}", version, "src/main/java/net/frankheijden/serverutils/common/ServerUtilsApp.java") 31 | } 32 | } 33 | 34 | tasks.withType { 35 | exclude("plugin.yml") 36 | exclude("bungee.yml") 37 | } 38 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/commands/CommandPlugins.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.commands; 2 | 3 | import cloud.commandframework.context.CommandContext; 4 | import java.util.ArrayList; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | import net.frankheijden.serverutils.common.config.MessageKey; 9 | import net.frankheijden.serverutils.common.config.MessagesResource; 10 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 11 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 12 | import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription; 13 | import net.frankheijden.serverutils.common.managers.AbstractPluginManager; 14 | import net.frankheijden.serverutils.common.utils.ListComponentBuilder; 15 | import net.kyori.adventure.text.Component; 16 | import net.kyori.adventure.text.TextComponent; 17 | import net.kyori.adventure.text.minimessage.Template; 18 | 19 | @SuppressWarnings("LineLength") 20 | public abstract class CommandPlugins, P, C extends ServerUtilsAudience, D extends ServerUtilsPluginDescription> 21 | extends ServerUtilsCommand { 22 | 23 | protected CommandPlugins(U plugin) { 24 | super(plugin, "plugins"); 25 | } 26 | 27 | protected abstract void handlePlugins(CommandContext context); 28 | 29 | /** 30 | * Sends a plugin list to the receiver. 31 | * @param sender The receiver of the plugin list. 32 | * @param plugins The plugins to be sent. 33 | * @param pluginFormat The format of the plugins to be sent. 34 | */ 35 | protected void handlePlugins(C sender, List

plugins, boolean hasVersionFlag) { 36 | List

filteredPlugins = new ArrayList<>(plugins.size()); 37 | Set hiddenPlugins = new HashSet<>(plugin.getConfigResource().getConfig().getStringList( 38 | "hide-plugins-from-plugins-command" 39 | )); 40 | AbstractPluginManager pluginManager = plugin.getPluginManager(); 41 | for (P plugin : plugins) { 42 | if (!hiddenPlugins.contains(pluginManager.getPluginId(plugin))) { 43 | filteredPlugins.add(plugin); 44 | } 45 | } 46 | 47 | MessagesResource messages = plugin.getMessagesResource(); 48 | 49 | sender.sendMessage(messages.get(MessageKey.PLUGINS_HEADER).toComponent()); 50 | TextComponent.Builder builder = Component.text(); 51 | builder.append(messages.get(MessageKey.PLUGINS_PREFIX).toComponent( 52 | Template.of("count", String.valueOf(filteredPlugins.size())) 53 | )); 54 | builder.append(ListComponentBuilder.create(filteredPlugins) 55 | .separator(messages.get(MessageKey.PLUGINS_SEPARATOR).toComponent()) 56 | .lastSeparator(messages.get(MessageKey.PLUGINS_LAST_SEPARATOR).toComponent()) 57 | .format(plugin -> { 58 | D description = pluginManager.getLoadedPluginDescription(plugin); 59 | 60 | TextComponent.Builder formatBuilder = Component.text(); 61 | MessageKey formatKey = pluginManager.isPluginEnabled(plugin) 62 | ? MessageKey.PLUGINS_FORMAT 63 | : MessageKey.PLUGINS_FORMAT_DISABLED; 64 | formatBuilder.append(messages.get(formatKey).toComponent( 65 | Template.of("plugin", description.getName()) 66 | )); 67 | if (hasVersionFlag) { 68 | formatBuilder.append(messages.get(MessageKey.PLUGINS_VERSION).toComponent( 69 | Template.of("version", description.getVersion()) 70 | )); 71 | } 72 | 73 | return formatBuilder.build(); 74 | }) 75 | .build()); 76 | sender.sendMessage(builder.build()); 77 | sender.sendMessage(messages.get(MessageKey.PLUGINS_FOOTER).toComponent()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/commands/arguments/PluginArgument.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.commands.arguments; 2 | 3 | import cloud.commandframework.arguments.CommandArgument; 4 | import cloud.commandframework.arguments.parser.ArgumentParseResult; 5 | import cloud.commandframework.arguments.parser.ArgumentParser; 6 | import cloud.commandframework.context.CommandContext; 7 | import cloud.commandframework.exceptions.parsing.NoInputProvidedException; 8 | import io.leangen.geantyref.TypeToken; 9 | import java.util.List; 10 | import java.util.Optional; 11 | import java.util.Queue; 12 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 13 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 14 | 15 | public class PluginArgument, P> extends CommandArgument { 16 | 17 | /** 18 | * Constructs a Plugin argument. 19 | */ 20 | public PluginArgument(boolean required, String name, ServerUtilsPlugin plugin) { 21 | super( 22 | required, 23 | name, 24 | new PluginParser<>(plugin), 25 | "", 26 | new TypeToken

() {}, 27 | null 28 | ); 29 | } 30 | 31 | public static final class PluginParser, P> implements ArgumentParser { 32 | 33 | private final ServerUtilsPlugin plugin; 34 | 35 | public PluginParser(ServerUtilsPlugin plugin) { 36 | this.plugin = plugin; 37 | } 38 | 39 | @Override 40 | public ArgumentParseResult

parse(CommandContext context, Queue inputQueue) { 41 | if (inputQueue.isEmpty()) { 42 | return ArgumentParseResult.failure(new NoInputProvidedException(PluginParser.class, context)); 43 | } 44 | 45 | Optional

pluginOptional = plugin.getPluginManager().getPlugin(inputQueue.peek()); 46 | if (!pluginOptional.isPresent()) { 47 | return ArgumentParseResult.failure(new IllegalArgumentException( 48 | "Plugin '" + inputQueue.peek() + "' does not exist!" 49 | )); 50 | } 51 | 52 | inputQueue.remove(); 53 | return ArgumentParseResult.success(pluginOptional.get()); 54 | } 55 | 56 | @Override 57 | public List suggestions(CommandContext context, String input) { 58 | return plugin.getPluginManager().getPluginNames(); 59 | } 60 | 61 | @Override 62 | public boolean isContextFree() { 63 | return true; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/commands/arguments/PluginsArgument.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.commands.arguments; 2 | 3 | import cloud.commandframework.arguments.CommandArgument; 4 | import cloud.commandframework.arguments.parser.ArgumentParseResult; 5 | import cloud.commandframework.arguments.parser.ArgumentParser; 6 | import cloud.commandframework.context.CommandContext; 7 | import cloud.commandframework.exceptions.parsing.NoInputProvidedException; 8 | import io.leangen.geantyref.TypeToken; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Optional; 12 | import java.util.Queue; 13 | import java.util.Set; 14 | import java.util.function.IntFunction; 15 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 16 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 17 | 18 | public class PluginsArgument, P> extends CommandArgument { 19 | 20 | /** 21 | * Constructs a Plugins argument. 22 | */ 23 | public PluginsArgument( 24 | boolean required, 25 | String name, 26 | PluginsParser parser 27 | ) { 28 | super( 29 | required, 30 | name, 31 | parser, 32 | "", 33 | new TypeToken() {}, 34 | null 35 | ); 36 | } 37 | 38 | public static final class PluginsParser, P> implements ArgumentParser { 39 | 40 | private final ServerUtilsPlugin plugin; 41 | private final IntFunction arrayCreator; 42 | private final String commandConfigPath; 43 | 44 | public PluginsParser(ServerUtilsPlugin plugin, IntFunction arrayCreator) { 45 | this(plugin, arrayCreator, null); 46 | } 47 | 48 | /** 49 | * Constructs a new PluginsParser. 50 | */ 51 | public PluginsParser( 52 | ServerUtilsPlugin plugin, 53 | IntFunction arrayCreator, 54 | String commandConfigPath 55 | ) { 56 | this.plugin = plugin; 57 | this.arrayCreator = arrayCreator; 58 | this.commandConfigPath = commandConfigPath; 59 | } 60 | 61 | @Override 62 | public ArgumentParseResult parse(CommandContext context, Queue inputQueue) { 63 | if (inputQueue.isEmpty()) { 64 | return ArgumentParseResult.failure(new NoInputProvidedException(PluginsParser.class, context)); 65 | } 66 | 67 | Set flags = plugin.getCommandsResource().getAllFlagAliases(commandConfigPath + ".flags.force"); 68 | 69 | int queueSize = inputQueue.size(); 70 | List

plugins = new ArrayList<>(queueSize); 71 | for (int i = 0; i < queueSize; i++) { 72 | if (flags.contains(inputQueue.peek())) continue; 73 | 74 | Optional

pluginOptional = plugin.getPluginManager().getPlugin(inputQueue.peek()); 75 | if (!pluginOptional.isPresent()) { 76 | return ArgumentParseResult.failure(new IllegalArgumentException( 77 | "Plugin '" + inputQueue.peek() + "' does not exist!" 78 | )); 79 | } 80 | 81 | inputQueue.remove(); 82 | plugins.add(pluginOptional.get()); 83 | } 84 | 85 | return ArgumentParseResult.success(plugins.stream().toArray(arrayCreator)); 86 | } 87 | 88 | @Override 89 | public List suggestions(CommandContext context, String input) { 90 | return plugin.getPluginManager().getPluginNames(); 91 | } 92 | 93 | @Override 94 | public boolean isContextFree() { 95 | return true; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/commands/brigadier/BrigadierHandler.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.commands.brigadier; 2 | 3 | import cloud.commandframework.brigadier.CloudBrigadierManager; 4 | import com.mojang.brigadier.arguments.StringArgumentType; 5 | import io.leangen.geantyref.TypeToken; 6 | import net.frankheijden.serverutils.common.commands.arguments.JarFilesArgument; 7 | import net.frankheijden.serverutils.common.commands.arguments.PluginsArgument; 8 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 9 | 10 | public class BrigadierHandler, P> { 11 | 12 | private final CloudBrigadierManager brigadierManager; 13 | 14 | public BrigadierHandler(CloudBrigadierManager brigadierManager) { 15 | this.brigadierManager = brigadierManager; 16 | } 17 | 18 | /** 19 | * Registers types with the cloud brigadier manager. 20 | */ 21 | public void registerTypes() { 22 | brigadierManager.registerMapping( 23 | new TypeToken>() {}, 24 | builder -> builder 25 | .cloudSuggestions() 26 | .toConstant(StringArgumentType.greedyString()) 27 | ); 28 | brigadierManager.registerMapping( 29 | new TypeToken>() {}, 30 | builder -> builder 31 | .cloudSuggestions() 32 | .toConstant(StringArgumentType.greedyString()) 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/config/CommandsResource.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | import java.util.Collections; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 7 | 8 | /** 9 | * The Commands configuration. 10 | */ 11 | public class CommandsResource extends ServerUtilsResource { 12 | 13 | private static final String COMMANDS_RESOURCE = "commands"; 14 | 15 | public CommandsResource(ServerUtilsPlugin plugin) { 16 | super(plugin, COMMANDS_RESOURCE); 17 | } 18 | 19 | /** 20 | * Retrieves all flag aliases for the given flag path. 21 | */ 22 | public Set getAllFlagAliases(String path) { 23 | Object flagObject = getConfig().get(path); 24 | if (flagObject instanceof ServerUtilsConfig) { 25 | ServerUtilsConfig flagConfig = (ServerUtilsConfig) flagObject; 26 | 27 | Set flagAliases = new HashSet<>(); 28 | flagAliases.add("--" + flagConfig.getString("main")); 29 | for (String alias : flagConfig.getStringList("aliases")) { 30 | flagAliases.add("-" + alias); 31 | } 32 | 33 | return flagAliases; 34 | } 35 | 36 | return Collections.emptySet(); 37 | } 38 | 39 | /** 40 | * Retrieves all aliases for the given path. 41 | */ 42 | public Set getAllAliases(String path) { 43 | Object object = getConfig().get(path); 44 | if (object instanceof ServerUtilsConfig) { 45 | ServerUtilsConfig config = (ServerUtilsConfig) object; 46 | 47 | Set aliases = new HashSet<>(); 48 | aliases.add(config.getString("main")); 49 | aliases.addAll(config.getStringList("aliases")); 50 | return aliases; 51 | } 52 | 53 | return Collections.emptySet(); 54 | } 55 | 56 | @Override 57 | public void migrate(int currentConfigVersion) { 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/config/ConfigKey.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | public interface ConfigKey { 4 | 5 | String getPath(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/config/ConfigResource.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 4 | 5 | public class ConfigResource extends ServerUtilsResource { 6 | 7 | private static final String CONFIG_RESOURCE = "config"; 8 | 9 | public ConfigResource(ServerUtilsPlugin plugin) { 10 | super(plugin, CONFIG_RESOURCE); 11 | } 12 | 13 | @Override 14 | public void migrate(int currentConfigVersion) { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/config/MessageKey.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | import java.util.Locale; 4 | 5 | public enum MessageKey implements PlaceholderConfigKey { 6 | 7 | RELOAD("reload", false), 8 | LOADPLUGIN("loadplugin"), 9 | UNLOADPLUGIN("unloadplugin"), 10 | SERVERUTILS_UPDATER("serverutils-updater", false), 11 | RELOADPLUGIN_SUCCESS("reloadplugin.success"), 12 | RELOADPLUGIN_SERVERUTILS("reloadplugin.serverutils"), 13 | GENERIC_PREFIX("generic.prefix", false), 14 | GENERIC_ERROR("generic.error", false), 15 | GENERIC_NOT_EXISTS("generic.not-exists"), 16 | GENERIC_NOT_ENABLED("generic.not-enabled"), 17 | GENERIC_ALREADY_LOADED("generic.already-loaded"), 18 | GENERIC_ALREADY_ENABLED("generic.already-enabled"), 19 | GENERIC_ALREADY_DISABLED("generic.already-disabled"), 20 | GENERIC_INVALID_PLUGIN("generic.invalid-plugin"), 21 | GENERIC_INVALID_DESCRIPTION("generic.invalid-description"), 22 | GENERIC_UNKNOWN_DEPENDENCY("generic.unknown-dependency"), 23 | GENERIC_FILE_DELETED("generic.file-deleted"), 24 | GENERIC_PROTECTED_PLUGIN("generic.protected-plugin"), 25 | DEPENDING_PLUGINS_PREFIX("depending-plugins.prefix"), 26 | DEPENDING_PLUGINS_FORMAT("depending-plugins.format"), 27 | DEPENDING_PLUGINS_SEPARATOR("depending-plugins.separator", false), 28 | DEPENDING_PLUGINS_LAST_SEPARATOR("depending-plugins.last-separator", false), 29 | DEPENDING_PLUGINS_OVERRIDE("depending-plugins.override"), 30 | WATCHPLUGIN_START("watchplugin.start"), 31 | WATCHPLUGIN_CHANGE("watchplugin.change", false), 32 | WATCHPLUGIN_STOPPED("watchplugin.stopped"), 33 | WATCHPLUGIN_FILE_DELETED("watchplugin.file-deleted"), 34 | WATCHPLUGIN_DELETED_FILE_IS_CREATED("watchplugin.deleted-file-is-created"), 35 | WATCHPLUGIN_ALREADY_WATCHING("watchplugin.already-watching"), 36 | WATCHPLUGIN_NOT_WATCHING("watchplugin.not-watching"), 37 | UPDATE_AVAILABLE("update.available"), 38 | UPDATE_DOWNLOADING("update.downloading"), 39 | UPDATE_DOWNLOAD_FAILED("update.download-failed"), 40 | UPDATE_DOWNLOAD_SUCCESS("update.download-success", false), 41 | HELP_HEADER("help.header", false), 42 | HELP_FORMAT("help.format"), 43 | HELP_FOOTER("help.footer", false), 44 | PLUGINS_HEADER("plugins.header", false), 45 | PLUGINS_PREFIX("plugins.prefix"), 46 | PLUGINS_FORMAT("plugins.format"), 47 | PLUGINS_FORMAT_DISABLED("plugins.format-disabled"), 48 | PLUGINS_SEPARATOR("plugins.separator", false), 49 | PLUGINS_LAST_SEPARATOR("plugins.last-separator", false), 50 | PLUGINS_VERSION("plugins.version"), 51 | PLUGINS_FOOTER("plugins.footer", false), 52 | PLUGININFO_HEADER("plugininfo.header", false), 53 | PLUGININFO_FORMAT("plugininfo.format"), 54 | PLUGININFO_LIST_FORMAT("plugininfo.list-format"), 55 | PLUGININFO_LIST_SEPARATOR("plugininfo.list-separator", false), 56 | PLUGININFO_LIST_LAST_SEPARATOR("plugininfo.list-last-separator", false), 57 | PLUGININFO_FOOTER("plugininfo.footer", false), 58 | COMMANDINFO_HEADER("commandinfo.header", false), 59 | COMMANDINFO_FORMAT("commandinfo.format"), 60 | COMMANDINFO_LIST_FORMAT("commandinfo.list-format"), 61 | COMMANDINFO_LIST_SEPARATOR("commandinfo.list-separator", false), 62 | COMMANDINFO_LIST_LAST_SEPARATOR("commandinfo.list-last-separator", false), 63 | COMMANDINFO_FOOTER("commandinfo.footer", false), 64 | COMMANDINFO_NOT_EXISTS("commandinfo.not-exists", false), 65 | ; 66 | 67 | private final String path; 68 | private final boolean hasPlaceholders; 69 | 70 | MessageKey(String path) { 71 | this(path, true); 72 | } 73 | 74 | MessageKey(String path, boolean hasPlaceholders) { 75 | this.path = path; 76 | this.hasPlaceholders = hasPlaceholders; 77 | } 78 | 79 | public static MessageKey fromPath(String path) { 80 | return MessageKey.valueOf(path.replaceAll("\\.|-", "_").toUpperCase(Locale.ENGLISH)); 81 | } 82 | 83 | @Override 84 | public String getPath() { 85 | return path; 86 | } 87 | 88 | @Override 89 | public boolean hasPlaceholders() { 90 | return hasPlaceholders; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/config/MessagesResource.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | import java.util.Collection; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 7 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.minimessage.MiniMessage; 10 | import net.kyori.adventure.text.minimessage.Template; 11 | 12 | public class MessagesResource extends ServerUtilsResource { 13 | 14 | public static final String MESSAGES_RESOURCE = "messages"; 15 | 16 | private final Map messageMap; 17 | private final MiniMessage miniMessage; 18 | 19 | /** 20 | * Constructs a new MessagesResource. 21 | */ 22 | public MessagesResource(ServerUtilsPlugin plugin) { 23 | super(plugin, MESSAGES_RESOURCE); 24 | this.messageMap = new HashMap<>(); 25 | this.miniMessage = MiniMessage.get(); 26 | } 27 | 28 | public Message get(String path) { 29 | return get(MessageKey.fromPath(path)); 30 | } 31 | 32 | public Message get(ConfigKey key) { 33 | return messageMap.get(key); 34 | } 35 | 36 | /** 37 | * Loads message keys and pre-compiles them if possible. 38 | */ 39 | public void load(Collection keys) { 40 | for (PlaceholderConfigKey key : keys) { 41 | this.messageMap.put(key, new Message(key)); 42 | } 43 | } 44 | 45 | public class Message { 46 | 47 | private final PlaceholderConfigKey key; 48 | private final String messageString; 49 | private final Component component; 50 | 51 | /** 52 | * Constructs a new Message. 53 | */ 54 | public Message(PlaceholderConfigKey key) { 55 | this.key = key; 56 | this.messageString = getConfig().getString("messages." + key.getPath()); 57 | this.component = key.hasPlaceholders() ? null : miniMessage.parse(messageString); 58 | } 59 | 60 | /** 61 | * Creates a {@link Component}. 62 | */ 63 | public Component toComponent() { 64 | return this.component == null ? miniMessage.parse(messageString) : this.component; 65 | } 66 | 67 | /** 68 | * Creates a {@link Component}. 69 | */ 70 | public Component toComponent(Template... templates) { 71 | return this.component == null ? miniMessage.parse(messageString, templates) : this.component; 72 | } 73 | 74 | /** 75 | * Creates a {@link Component}. 76 | */ 77 | public Component toComponent(String... placeholders) { 78 | return this.component == null ? miniMessage.parse(messageString, placeholders) : this.component; 79 | } 80 | 81 | public void sendTo(ServerUtilsAudience serverAudience, Template... placeholders) { 82 | serverAudience.sendMessage(toComponent(placeholders)); 83 | } 84 | } 85 | 86 | @Override 87 | public void migrate(int currentConfigVersion) { 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/config/PlaceholderConfigKey.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | public interface PlaceholderConfigKey extends ConfigKey { 4 | 5 | boolean hasPlaceholders(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/config/ServerUtilsResource.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | import java.io.IOException; 4 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 5 | 6 | public abstract class ServerUtilsResource { 7 | 8 | protected final ServerUtilsPlugin plugin; 9 | protected final ServerUtilsConfig config; 10 | protected final JsonConfig defaultConfig; 11 | 12 | protected ServerUtilsResource( 13 | ServerUtilsPlugin plugin, 14 | ServerUtilsConfig config, 15 | JsonConfig defaultConfig 16 | ) { 17 | this.plugin = plugin; 18 | this.config = config; 19 | this.defaultConfig = defaultConfig; 20 | } 21 | 22 | protected ServerUtilsResource(ServerUtilsPlugin plugin, String resourceName) { 23 | this.plugin = plugin; 24 | this.defaultConfig = JsonConfig.load(plugin.getResourceProvider(), plugin.getPlatform(), resourceName); 25 | this.config = ServerUtilsConfig.init( 26 | this.defaultConfig, 27 | plugin.getResourceProvider(), 28 | plugin.getDataFolder().toPath().resolve( 29 | resourceName + plugin.getResourceProvider().getResourceExtension() 30 | ) 31 | ); 32 | this.migrate(); 33 | } 34 | 35 | public ServerUtilsConfig getConfig() { 36 | return config; 37 | } 38 | 39 | public ServerUtilsConfig getDefaultConfig() { 40 | return defaultConfig; 41 | } 42 | 43 | protected void reset(String path) { 44 | config.set(path, JsonConfig.toObjectValue(defaultConfig.getJsonElement(path))); 45 | } 46 | 47 | /** 48 | * Migrates values in the config. 49 | */ 50 | public void migrate() { 51 | migrate(config.getInt("config-version")); 52 | config.set("config-version", defaultConfig.getInt("config-version")); 53 | try { 54 | config.save(); 55 | } catch (IOException ex) { 56 | ex.printStackTrace(); 57 | } 58 | } 59 | 60 | public abstract void migrate(int currentConfigVersion); 61 | } 62 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/AbstractTask.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities; 2 | 3 | public abstract class AbstractTask implements Runnable { 4 | 5 | public abstract void cancel(); 6 | } 7 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/ServerUtilsAudience.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities; 2 | 3 | import net.kyori.adventure.audience.Audience; 4 | import net.kyori.adventure.text.Component; 5 | 6 | public abstract class ServerUtilsAudience { 7 | 8 | protected final Audience audience; 9 | protected final C source; 10 | 11 | protected ServerUtilsAudience(Audience audience, C source) { 12 | this.audience = audience; 13 | this.source = source; 14 | } 15 | 16 | public abstract boolean isPlayer(); 17 | 18 | public abstract boolean hasPermission(String permission); 19 | 20 | public void sendMessage(Component component) { 21 | audience.sendMessage(component); 22 | } 23 | 24 | public C getSource() { 25 | return this.source; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/ServerUtilsPluginDescription.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities; 2 | 3 | import java.io.File; 4 | import java.util.Set; 5 | 6 | public interface ServerUtilsPluginDescription { 7 | 8 | String getId(); 9 | 10 | String getName(); 11 | 12 | String getVersion(); 13 | 14 | String getAuthor(); 15 | 16 | File getFile(); 17 | 18 | Set getDependencies(); 19 | } 20 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/exceptions/InvalidPluginDescriptionException.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.exceptions; 2 | 3 | public class InvalidPluginDescriptionException extends RuntimeException { 4 | 5 | public InvalidPluginDescriptionException() { 6 | super(); 7 | } 8 | 9 | public InvalidPluginDescriptionException(String message) { 10 | super(message); 11 | } 12 | 13 | public InvalidPluginDescriptionException(Throwable cause) { 14 | super(cause); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/http/GitHubAsset.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.http; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | import java.util.Locale; 7 | import java.util.function.Predicate; 8 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 9 | 10 | public class GitHubAsset { 11 | 12 | private final String name; 13 | private final String downloadUrl; 14 | 15 | public GitHubAsset(String name, String downloadUrl) { 16 | this.name = name; 17 | this.downloadUrl = downloadUrl; 18 | } 19 | 20 | /** 21 | * Creates a new GitHubAsset from given release url. 22 | */ 23 | public static GitHubAsset from(JsonObject jsonObject) { 24 | return from(jsonObject, name -> true); 25 | } 26 | 27 | /** 28 | * Creates a new GitHubAsset for given platfrom from given release url. 29 | */ 30 | public static GitHubAsset from(JsonObject jsonObject, ServerUtilsPlugin.Platform platform) { 31 | return from(jsonObject, name -> name.toUpperCase(Locale.ENGLISH).contains(platform.name())); 32 | } 33 | 34 | /** 35 | * Creates a new GitHubAsset from given release url. 36 | */ 37 | public static GitHubAsset from(JsonObject jsonObject, Predicate namePredicate) { 38 | JsonArray assets = jsonObject.getAsJsonArray("assets"); 39 | if (assets != null) { 40 | for (JsonElement asset : assets) { 41 | JsonObject assetJson = asset.getAsJsonObject(); 42 | 43 | String name = assetJson.get("name").getAsString(); 44 | if (namePredicate.test(name)) { 45 | return new GitHubAsset(name, assetJson.get("browser_download_url").getAsString()); 46 | } 47 | } 48 | } 49 | return null; 50 | } 51 | 52 | public String getName() { 53 | return name; 54 | } 55 | 56 | public String getDownloadUrl() { 57 | return downloadUrl; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/http/GitHubRateLimit.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.http; 2 | 3 | import java.net.HttpURLConnection; 4 | 5 | public class GitHubRateLimit { 6 | 7 | private final int limit; 8 | private final int used; 9 | private final int remaining; 10 | private final long reset; 11 | 12 | /** 13 | * Constructs a new GitHubRateLimit object from given params. 14 | */ 15 | public GitHubRateLimit(int limit, int used, int remaining, long reset) { 16 | this.limit = limit; 17 | this.used = used; 18 | this.remaining = remaining; 19 | this.reset = reset; 20 | } 21 | 22 | /** 23 | * Creates a new GitHubRateLimit object from the given opened connection. 24 | */ 25 | public static GitHubRateLimit from(HttpURLConnection connection) { 26 | return new GitHubRateLimit( 27 | connection.getHeaderFieldInt("x-ratelimit-limit", 60), 28 | connection.getHeaderFieldInt("x-ratelimit-used", 0), 29 | connection.getHeaderFieldInt("x-ratelimit-remaining", 60), 30 | connection.getHeaderFieldLong("x-ratelimit-reset", System.currentTimeMillis() / 1000) 31 | ); 32 | } 33 | 34 | public int getLimit() { 35 | return limit; 36 | } 37 | 38 | public int getUsed() { 39 | return used; 40 | } 41 | 42 | public int getRemaining() { 43 | return remaining; 44 | } 45 | 46 | public boolean isRateLimited() { 47 | return remaining == 0; 48 | } 49 | 50 | public long getReset() { 51 | return reset * 1000; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/http/GitHubResponse.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.http; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.net.HttpURLConnection; 6 | 7 | public class GitHubResponse { 8 | 9 | private final HttpURLConnection connection; 10 | private final GitHubRateLimit rateLimit; 11 | 12 | public GitHubResponse(HttpURLConnection connection, GitHubRateLimit rateLimit) { 13 | this.connection = connection; 14 | this.rateLimit = rateLimit; 15 | } 16 | 17 | public static GitHubResponse from(HttpURLConnection connection) { 18 | return new GitHubResponse(connection, GitHubRateLimit.from(connection)); 19 | } 20 | 21 | public HttpURLConnection getConnection() { 22 | return connection; 23 | } 24 | 25 | public GitHubRateLimit getRateLimit() { 26 | return rateLimit; 27 | } 28 | 29 | public InputStream getStream() throws IOException { 30 | int res = connection.getResponseCode(); 31 | return (res >= 200 && res <= 299) ? connection.getInputStream() : connection.getErrorStream(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/AbstractResult.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import net.frankheijden.serverutils.common.config.ConfigKey; 4 | 5 | public interface AbstractResult { 6 | 7 | ConfigKey getKey(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/CloseablePluginResult.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public class CloseablePluginResult extends PluginResult implements Closeable { 9 | 10 | private final List closeables; 11 | 12 | public CloseablePluginResult(String pluginId, Result result) { 13 | super(pluginId, result); 14 | this.closeables = Collections.emptyList(); 15 | } 16 | 17 | public CloseablePluginResult( 18 | String pluginId, 19 | T plugin, 20 | Result result, 21 | List closeables, 22 | String... placeholders 23 | ) { 24 | super(pluginId, plugin, result, placeholders); 25 | this.closeables = closeables; 26 | } 27 | 28 | /** 29 | * Attempts to close the closable, essentially wrapping it with try-catch. 30 | */ 31 | public void tryClose() { 32 | if (closeables == null) return; 33 | try { 34 | close(); 35 | } catch (IOException ex) { 36 | ex.printStackTrace(); 37 | } 38 | } 39 | 40 | /** 41 | * Closes the closable. 42 | */ 43 | @Override 44 | public void close() throws IOException { 45 | for (Closeable closeable : closeables) { 46 | closeable.close(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/CloseablePluginResults.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public class CloseablePluginResults extends PluginResults implements Closeable { 9 | 10 | @Override 11 | public CloseablePluginResults addResult(PluginResult pluginResult) { 12 | if (pluginResult instanceof CloseablePluginResult) { 13 | results.add(pluginResult); 14 | } else { 15 | results.add(new CloseablePluginResult<>( 16 | pluginResult.getPluginId(), 17 | pluginResult.getPlugin(), 18 | pluginResult.getResult(), 19 | Collections.emptyList(), 20 | pluginResult.getPlaceholders() 21 | )); 22 | } 23 | return this; 24 | } 25 | 26 | @Override 27 | public CloseablePluginResults addResult(String pluginId, Result result, String... placeholders) { 28 | super.addResult(pluginId, result, placeholders); 29 | return this; 30 | } 31 | 32 | @Override 33 | public CloseablePluginResults addResult(String pluginId, T plugin, String... placeholders) { 34 | super.addResult(pluginId, plugin, placeholders); 35 | return this; 36 | } 37 | 38 | @Override 39 | protected CloseablePluginResults addResult(String pluginId, T plugin, Result result, String... placeholders) { 40 | return addResult(new CloseablePluginResult<>(pluginId, plugin, result, Collections.emptyList(), placeholders)); 41 | } 42 | 43 | public CloseablePluginResults addResult( 44 | String pluginId, 45 | T plugin, 46 | List closeables, 47 | String... placeholders 48 | ) { 49 | return addResult(new CloseablePluginResult<>(pluginId, plugin, Result.SUCCESS, closeables, placeholders)); 50 | } 51 | 52 | @Override 53 | public CloseablePluginResult first() { 54 | PluginResult pluginResult = super.first(); 55 | if (!(pluginResult instanceof CloseablePluginResult)) { 56 | throw new IllegalArgumentException("Not an instance of CloseablePluginResult: " + pluginResult); 57 | } 58 | return (CloseablePluginResult) pluginResult; 59 | } 60 | 61 | @Override 62 | public CloseablePluginResult last() { 63 | PluginResult pluginResult = super.last(); 64 | if (!(pluginResult instanceof CloseablePluginResult)) { 65 | throw new IllegalArgumentException("Not an instance of CloseablePluginResult: " + pluginResult); 66 | } 67 | return (CloseablePluginResult) pluginResult; 68 | } 69 | 70 | /** 71 | * Attempts to close the {@link CloseablePluginResult}'s enclosed. 72 | */ 73 | public void tryClose() { 74 | try { 75 | close(); 76 | } catch (IOException ex) { 77 | ex.printStackTrace(); 78 | } 79 | } 80 | 81 | @Override 82 | public void close() throws IOException { 83 | for (PluginResult pluginResult : this) { 84 | if (pluginResult instanceof CloseablePluginResult) { 85 | ((CloseablePluginResult) pluginResult).close(); 86 | } 87 | } 88 | System.gc(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/PluginResult.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import net.frankheijden.serverutils.common.ServerUtilsApp; 4 | import net.frankheijden.serverutils.common.config.ConfigKey; 5 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 6 | 7 | public class PluginResult implements AbstractResult { 8 | 9 | private final String pluginId; 10 | private final T plugin; 11 | private final Result result; 12 | private final String[] placeholders; 13 | 14 | public PluginResult(String pluginId, Result result) { 15 | this(pluginId, null, result); 16 | } 17 | 18 | /** 19 | * Constructs a new PluginResult. 20 | */ 21 | public PluginResult(String pluginId, T plugin, Result result, String... placeholders) { 22 | this.pluginId = pluginId; 23 | this.plugin = plugin; 24 | this.result = result; 25 | this.placeholders = new String[placeholders.length + 2]; 26 | this.placeholders[0] = "plugin"; 27 | this.placeholders[1] = pluginId; 28 | System.arraycopy(placeholders, 0, this.placeholders, 2, placeholders.length); 29 | } 30 | 31 | public String getPluginId() { 32 | return pluginId; 33 | } 34 | 35 | public T getPlugin() { 36 | return plugin; 37 | } 38 | 39 | public Result getResult() { 40 | return result; 41 | } 42 | 43 | public String[] getPlaceholders() { 44 | return placeholders; 45 | } 46 | 47 | public boolean isSuccess() { 48 | return plugin != null && result == Result.SUCCESS; 49 | } 50 | 51 | public void sendTo(ServerUtilsAudience sender, ConfigKey successKey) { 52 | ConfigKey key = isSuccess() ? successKey : result.getKey(); 53 | sender.sendMessage(ServerUtilsApp.getPlugin().getMessagesResource().get(key).toComponent(placeholders)); 54 | } 55 | 56 | @Override 57 | public ConfigKey getKey() { 58 | return result.getKey(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/PluginResults.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | import net.frankheijden.serverutils.common.config.ConfigKey; 7 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 8 | 9 | public class PluginResults implements Iterable> { 10 | 11 | protected final List> results; 12 | 13 | public PluginResults() { 14 | this.results = new ArrayList<>(); 15 | } 16 | 17 | public PluginResults addResult(String pluginId, Result result, String... placeholders) { 18 | addResult(pluginId, null, result, placeholders); 19 | return this; 20 | } 21 | 22 | public PluginResults addResult(String pluginId, T plugin, String... placeholders) { 23 | addResult(pluginId, plugin, Result.SUCCESS, placeholders); 24 | return this; 25 | } 26 | 27 | protected PluginResults addResult(String pluginId, T plugin, Result result, String... placeholders) { 28 | addResult(new PluginResult<>(pluginId, plugin, result, placeholders)); 29 | return this; 30 | } 31 | 32 | public PluginResults addResult(PluginResult pluginResult) { 33 | this.results.add(pluginResult); 34 | return this; 35 | } 36 | 37 | public boolean isSuccess() { 38 | return results.stream().allMatch(PluginResult::isSuccess); 39 | } 40 | 41 | public List> getResults() { 42 | return results; 43 | } 44 | 45 | /** 46 | * Creates an array of all plugins. 47 | * @throws IllegalArgumentException Iff a result was not successful (check {@link PluginResults#isSuccess()} first!) 48 | */ 49 | public List getPlugins() { 50 | List plugins = new ArrayList<>(results.size()); 51 | for (PluginResult result : results) { 52 | if (!result.isSuccess()) throw new IllegalArgumentException( 53 | "Result after handling plugin '" + result.getPluginId() + "' was not successful!" 54 | ); 55 | plugins.add(result.getPlugin()); 56 | } 57 | return plugins; 58 | } 59 | 60 | public PluginResult first() { 61 | return results.get(0); 62 | } 63 | 64 | public PluginResult last() { 65 | return results.get(results.size() - 1); 66 | } 67 | 68 | /** 69 | * Sends the result(s) to the given sender. 70 | */ 71 | public void sendTo(ServerUtilsAudience sender, ConfigKey successKey) { 72 | if (!isSuccess()) { 73 | last().sendTo(sender, successKey); 74 | return; 75 | } 76 | 77 | for (PluginResult result : results) { 78 | result.sendTo(sender, successKey); 79 | } 80 | } 81 | 82 | @Override 83 | public Iterator> iterator() { 84 | return results.iterator(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/PluginWatchResult.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import net.frankheijden.serverutils.common.config.ConfigKey; 4 | 5 | public class PluginWatchResult implements AbstractResult { 6 | 7 | private final WatchResult result; 8 | private final String[] placeholders; 9 | 10 | public PluginWatchResult(WatchResult result, String... placeholders) { 11 | this.result = result; 12 | this.placeholders = placeholders; 13 | } 14 | 15 | public WatchResult getResult() { 16 | return result; 17 | } 18 | 19 | public String[] getPlaceholders() { 20 | return placeholders; 21 | } 22 | 23 | @Override 24 | public ConfigKey getKey() { 25 | return result.getKey(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/PluginWatchResults.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | import net.frankheijden.serverutils.common.ServerUtilsApp; 7 | import net.frankheijden.serverutils.common.config.MessagesResource; 8 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 9 | 10 | public class PluginWatchResults implements Iterable { 11 | 12 | private final List watchResults; 13 | 14 | public PluginWatchResults() { 15 | this.watchResults = new ArrayList<>(); 16 | } 17 | 18 | public PluginWatchResults add(WatchResult result, String... placeholders) { 19 | return add(new PluginWatchResult(result, placeholders)); 20 | } 21 | 22 | public PluginWatchResults add(PluginWatchResult watchResult) { 23 | this.watchResults.add(watchResult); 24 | return this; 25 | } 26 | 27 | /** 28 | * Sends the result(s) to the given sender. 29 | */ 30 | public void sendTo(ServerUtilsAudience sender) { 31 | MessagesResource messages = ServerUtilsApp.getPlugin().getMessagesResource(); 32 | 33 | for (PluginWatchResult watchResult : watchResults) { 34 | sender.sendMessage(messages.get(watchResult.getKey()).toComponent(watchResult.getPlaceholders())); 35 | } 36 | } 37 | 38 | @Override 39 | public Iterator iterator() { 40 | return watchResults.iterator(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/Result.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import net.frankheijden.serverutils.common.config.MessageKey; 4 | 5 | /** 6 | * An enum containing possible results. 7 | */ 8 | public enum Result implements AbstractResult { 9 | NOT_EXISTS(MessageKey.GENERIC_NOT_EXISTS), 10 | NOT_ENABLED(MessageKey.GENERIC_NOT_ENABLED), 11 | ALREADY_LOADED(MessageKey.GENERIC_ALREADY_LOADED), 12 | ALREADY_ENABLED(MessageKey.GENERIC_ALREADY_ENABLED), 13 | ALREADY_DISABLED(MessageKey.GENERIC_ALREADY_DISABLED), 14 | FILE_DELETED(MessageKey.GENERIC_FILE_DELETED), 15 | INVALID_DESCRIPTION(MessageKey.GENERIC_INVALID_DESCRIPTION), 16 | INVALID_PLUGIN(MessageKey.GENERIC_INVALID_PLUGIN), 17 | UNKNOWN_DEPENDENCY(MessageKey.GENERIC_UNKNOWN_DEPENDENCY), 18 | ERROR(MessageKey.GENERIC_ERROR), 19 | SUCCESS(null), 20 | ; 21 | 22 | private final MessageKey key; 23 | 24 | Result(MessageKey key) { 25 | this.key = key; 26 | } 27 | 28 | public MessageKey getKey() { 29 | return key; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/entities/results/WatchResult.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.entities.results; 2 | 3 | import net.frankheijden.serverutils.common.ServerUtilsApp; 4 | import net.frankheijden.serverutils.common.config.ConfigKey; 5 | import net.frankheijden.serverutils.common.config.MessageKey; 6 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 7 | import net.kyori.adventure.text.Component; 8 | import net.kyori.adventure.text.minimessage.Template; 9 | 10 | public enum WatchResult implements AbstractResult { 11 | START(MessageKey.WATCHPLUGIN_START), 12 | CHANGE(MessageKey.WATCHPLUGIN_CHANGE), 13 | ALREADY_WATCHING(MessageKey.WATCHPLUGIN_ALREADY_WATCHING), 14 | NOT_WATCHING(MessageKey.WATCHPLUGIN_NOT_WATCHING), 15 | FILE_DELETED(MessageKey.WATCHPLUGIN_FILE_DELETED), 16 | DELETED_FILE_IS_CREATED(MessageKey.WATCHPLUGIN_DELETED_FILE_IS_CREATED), 17 | STOPPED(MessageKey.WATCHPLUGIN_STOPPED), 18 | ; 19 | 20 | private final ConfigKey key; 21 | 22 | WatchResult(ConfigKey key) { 23 | this.key = key; 24 | } 25 | 26 | public void sendTo(ServerUtilsAudience sender, Template... templates) { 27 | Component component = ServerUtilsApp.getPlugin().getMessagesResource().get(key).toComponent(templates); 28 | sender.sendMessage(component); 29 | } 30 | 31 | @Override 32 | public ConfigKey getKey() { 33 | return key; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/events/PluginDisableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.events; 2 | 3 | public interface PluginDisableEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/events/PluginEnableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.events; 2 | 3 | public interface PluginEnableEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/events/PluginEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.events; 2 | 3 | public interface PluginEvent { 4 | 5 | enum Stage { 6 | PRE, 7 | POST 8 | } 9 | 10 | T getPlugin(); 11 | 12 | Stage getStage(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/events/PluginLoadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.events; 2 | 3 | public interface PluginLoadEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/events/PluginUnloadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.events; 2 | 3 | public interface PluginUnloadEvent { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/listeners/PlayerListener.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.listeners; 2 | 3 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 4 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 5 | import net.frankheijden.serverutils.common.tasks.UpdateCheckerTask; 6 | 7 | public abstract class PlayerListener, P, C extends ServerUtilsAudience> 8 | extends ServerUtilsListener { 9 | 10 | protected PlayerListener(U plugin) { 11 | super(plugin); 12 | } 13 | 14 | /** 15 | * Handles the update check on the given ServerCommandSender. 16 | * @param sender The sender which triggered the update. 17 | */ 18 | protected void handleUpdate(C sender) { 19 | if (sender.hasPermission("serverutils.notification.update")) { 20 | UpdateCheckerTask.tryStart(plugin, sender, "login"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/listeners/ServerUtilsListener.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.listeners; 2 | 3 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 4 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 5 | 6 | public abstract class ServerUtilsListener, C extends ServerUtilsAudience> { 7 | 8 | protected final U plugin; 9 | 10 | protected ServerUtilsListener(U plugin) { 11 | this.plugin = plugin; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/managers/UpdateManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.managers; 2 | 3 | import net.frankheijden.serverutils.common.ServerUtilsApp; 4 | 5 | public class UpdateManager { 6 | 7 | private String downloadedVersion = ServerUtilsApp.VERSION; 8 | private long lastUpdateCheck = 0; 9 | 10 | public UpdateManager() {} 11 | 12 | public String getDownloadedVersion() { 13 | return downloadedVersion; 14 | } 15 | 16 | public void setDownloadedVersion(String downloadedVersion) { 17 | this.downloadedVersion = downloadedVersion; 18 | } 19 | 20 | public boolean hasDownloaded() { 21 | return !downloadedVersion.equals(ServerUtilsApp.VERSION); 22 | } 23 | 24 | public boolean canRunUpdateCheck() { 25 | return lastUpdateCheck + 1000 * 60 * 30 <= System.currentTimeMillis(); 26 | } 27 | 28 | public void updateLastUpdateCheck() { 29 | this.lastUpdateCheck = System.currentTimeMillis(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/managers/WatchManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.managers; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.UUID; 8 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 9 | import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin; 10 | import net.frankheijden.serverutils.common.entities.results.PluginWatchResults; 11 | import net.frankheijden.serverutils.common.entities.results.WatchResult; 12 | import net.frankheijden.serverutils.common.tasks.PluginWatcherTask; 13 | 14 | public class WatchManager { 15 | 16 | private final ServerUtilsPlugin plugin; 17 | private final Map watchTasks; 18 | 19 | public WatchManager(ServerUtilsPlugin plugin) { 20 | this.plugin = plugin; 21 | this.watchTasks = new HashMap<>(); 22 | } 23 | 24 | /** 25 | * Starts watching the specified plugin and reloads it when a change is detected. 26 | */ 27 | public PluginWatchResults watchPlugins(ServerUtilsAudience sender, List

plugins) { 28 | List pluginIds = new ArrayList<>(plugins.size()); 29 | for (P watchPlugin : plugins) { 30 | String pluginId = plugin.getPluginManager().getPluginId(watchPlugin); 31 | if (watchTasks.containsKey(pluginId)) { 32 | return new PluginWatchResults().add(WatchResult.ALREADY_WATCHING, "plugin", pluginId); 33 | } 34 | 35 | pluginIds.add(plugin.getPluginManager().getPluginId(watchPlugin)); 36 | } 37 | 38 | UUID key = UUID.randomUUID(); 39 | plugin.getTaskManager().runTaskAsynchronously( 40 | key.toString(), 41 | new PluginWatcherTask<>(plugin, sender, plugins) 42 | ); 43 | 44 | WatchTask watchTask = new WatchTask(key, pluginIds); 45 | for (String pluginId : pluginIds) { 46 | watchTasks.put(pluginId, watchTask); 47 | } 48 | 49 | PluginWatchResults watchResults = new PluginWatchResults(); 50 | for (String pluginId : pluginIds) { 51 | watchResults.add(WatchResult.START, "plugin", pluginId); 52 | } 53 | return watchResults; 54 | } 55 | 56 | /** 57 | * Stops watching plugins for changes. 58 | */ 59 | public PluginWatchResults unwatchPluginsAssociatedWith(String associatedPluginId) { 60 | WatchTask task = watchTasks.get(associatedPluginId); 61 | if (task != null && plugin.getTaskManager().cancelTask(task.key.toString())) { 62 | task.pluginIds.forEach(watchTasks::remove); 63 | 64 | PluginWatchResults watchResults = new PluginWatchResults(); 65 | for (String pluginId : task.pluginIds) { 66 | watchResults.add(WatchResult.STOPPED, "plugin", pluginId); 67 | } 68 | return watchResults; 69 | } 70 | return new PluginWatchResults().add(WatchResult.NOT_WATCHING, "plugin", associatedPluginId); 71 | } 72 | 73 | private static final class WatchTask { 74 | 75 | private final UUID key; 76 | private final List pluginIds; 77 | 78 | private WatchTask(UUID key, List pluginIds) { 79 | this.key = key; 80 | this.pluginIds = pluginIds; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/providers/ResourceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.providers; 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | import net.frankheijden.serverutils.common.config.ServerUtilsConfig; 6 | 7 | public interface ResourceProvider { 8 | 9 | default InputStream getResource(String resource) { 10 | return getRawResource(resource + getResourceExtension()); 11 | } 12 | 13 | InputStream getRawResource(String resource); 14 | 15 | ServerUtilsConfig load(InputStream is); 16 | 17 | ServerUtilsConfig load(File file); 18 | 19 | String getResourceExtension(); 20 | } 21 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/providers/ServerUtilsAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.providers; 2 | 3 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 4 | import net.kyori.adventure.text.Component; 5 | 6 | public interface ServerUtilsAudienceProvider { 7 | 8 | /** 9 | * Retrieves the console ServerAudience. 10 | */ 11 | ServerUtilsAudience getConsoleServerAudience(); 12 | 13 | /** 14 | * Converts the given source (specific to impl) to an ServerAudience. 15 | */ 16 | ServerUtilsAudience get(S source); 17 | 18 | /** 19 | * Broadcasts a message to all with given permission. 20 | */ 21 | void broadcast(Component component, String permission); 22 | } 23 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/util/HashGraph.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.util; 2 | 3 | import java.util.Collections; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | public class HashGraph { 10 | 11 | private final Set nodes; 12 | private final Map> successors; 13 | private final Map> predecessors; 14 | 15 | public HashGraph() { 16 | this(16); 17 | } 18 | 19 | /** 20 | * Constructs a new hash-based graph. 21 | */ 22 | public HashGraph(int initialCapacity) { 23 | this.nodes = new HashSet<>(initialCapacity); 24 | this.successors = new HashMap<>(initialCapacity); 25 | this.predecessors = new HashMap<>(initialCapacity); 26 | } 27 | 28 | public void addNode(T node) { 29 | this.nodes.add(node); 30 | } 31 | 32 | public void putEdge(T from, T to) { 33 | this.successors.computeIfAbsent(from, k -> new HashSet<>()).add(to); 34 | this.predecessors.computeIfAbsent(to, k -> new HashSet<>()).add(from); 35 | } 36 | 37 | public Set nodes() { 38 | return this.nodes; 39 | } 40 | 41 | public Set successors(T node) { 42 | return this.successors.getOrDefault(node, Collections.emptySet()); 43 | } 44 | 45 | public Set predecessors(T node) { 46 | return this.predecessors.getOrDefault(node, Collections.emptySet()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/DependencyUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Deque; 5 | import java.util.HashMap; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Set; 10 | import net.frankheijden.serverutils.common.util.HashGraph; 11 | 12 | public class DependencyUtils { 13 | 14 | private DependencyUtils() {} 15 | 16 | /** 17 | * Determines the topological order of a dependency map. 18 | * Adapted from https://github.com/VelocityPowered/Velocity. 19 | * @throws IllegalStateException Iff circular dependency. 20 | */ 21 | @SuppressWarnings("UnstableApiUsage") 22 | public static List determineOrder(Map> dependencyMap) throws IllegalStateException { 23 | HashGraph dependencyGraph = new HashGraph<>(); 24 | for (T node : dependencyMap.keySet()) { 25 | dependencyGraph.addNode(node); 26 | } 27 | 28 | for (Map.Entry> entry : dependencyMap.entrySet()) { 29 | for (T dependency : entry.getValue()) { 30 | dependencyGraph.putEdge(entry.getKey(), dependency); 31 | } 32 | } 33 | 34 | List orderedList = new ArrayList<>(dependencyMap.size()); 35 | Map marks = new HashMap<>(dependencyMap.size()); 36 | 37 | for (T node : dependencyGraph.nodes()) { 38 | visitNode(dependencyGraph, node, marks, orderedList, new LinkedList<>()); 39 | } 40 | 41 | return orderedList; 42 | } 43 | 44 | @SuppressWarnings("UnstableApiUsage") 45 | private static void visitNode( 46 | HashGraph dependencyGraph, 47 | T node, 48 | Map marks, 49 | List orderedList, 50 | Deque currentIteration 51 | ) throws IllegalStateException { 52 | Mark mark = marks.getOrDefault(node, Mark.NOT_VISITED); 53 | if (mark == Mark.PERMANENT) { 54 | return; 55 | } else if (mark == Mark.TEMPORARY) { 56 | currentIteration.addLast(node); 57 | 58 | StringBuilder sb = new StringBuilder(); 59 | for (T currentNode : currentIteration) { 60 | sb.append(" -> ").append(currentNode); 61 | } 62 | 63 | throw new IllegalStateException("Circular dependency detected: " + sb.substring(4)); 64 | } 65 | 66 | currentIteration.addLast(node); 67 | marks.put(node, Mark.TEMPORARY); 68 | 69 | for (T successorNode : dependencyGraph.successors(node)) { 70 | visitNode(dependencyGraph, successorNode, marks, orderedList, currentIteration); 71 | } 72 | 73 | marks.put(node, Mark.PERMANENT); 74 | currentIteration.removeLast(); 75 | orderedList.add(node); 76 | } 77 | 78 | private enum Mark { 79 | NOT_VISITED, 80 | TEMPORARY, 81 | PERMANENT 82 | } 83 | } 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import com.google.gson.JsonElement; 4 | import com.google.gson.JsonParser; 5 | import java.io.BufferedReader; 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.InputStreamReader; 10 | import java.nio.charset.StandardCharsets; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.security.MessageDigest; 14 | import java.security.NoSuchAlgorithmException; 15 | 16 | public class FileUtils { 17 | 18 | private FileUtils() {} 19 | 20 | /** 21 | * Parses an InputStream into a JsonElement. 22 | */ 23 | public static JsonElement parseJson(InputStream in) throws IOException { 24 | if (in == null) return null; 25 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { 26 | return new JsonParser().parse(reader); 27 | } 28 | } 29 | 30 | /** 31 | * Saves an InputStream to a file. 32 | */ 33 | public static boolean saveResource(InputStream in, File target) throws IOException { 34 | if (target.exists()) return false; 35 | Files.copy(in, target.toPath()); 36 | return true; 37 | } 38 | 39 | /** 40 | * Get the Hash of a file at given path. 41 | * 42 | * @param path The path 43 | * @return The file's hash 44 | */ 45 | public static String getHash(Path path) { 46 | byte[] digest; 47 | try { 48 | digest = MessageDigest.getInstance("MD5").digest(Files.readAllBytes(path)); 49 | } catch (IOException | NoSuchAlgorithmException ex) { 50 | return null; 51 | } 52 | return StringUtils.bytesToHex(digest); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/ForwardFilter.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.util.logging.Level; 4 | import java.util.logging.LogRecord; 5 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 6 | import net.kyori.adventure.text.Component; 7 | import net.kyori.adventure.text.format.NamedTextColor; 8 | 9 | public class ForwardFilter extends PredicateFilter { 10 | 11 | private static final NamedTextColor INFO_COLOR = NamedTextColor.GREEN; 12 | private static final NamedTextColor WARNING_COLOR = NamedTextColor.GOLD; 13 | private static final NamedTextColor SEVERE_COLOR = NamedTextColor.RED; 14 | 15 | private boolean warnings; 16 | 17 | /** 18 | * Creates a filter which forwards all output to the sender. 19 | * @param sender The sender to forward logs to. 20 | */ 21 | public ForwardFilter(ServerUtilsAudience sender) { 22 | this.warnings = false; 23 | 24 | setPredicate(rec -> { 25 | NamedTextColor color = getColor(rec.getLevel()); 26 | if (color != INFO_COLOR) warnings = true; 27 | sender.sendMessage(Component.text(format(rec), color)); 28 | return true; 29 | }); 30 | } 31 | 32 | public boolean hasWarnings() { 33 | return warnings; 34 | } 35 | 36 | private static NamedTextColor getColor(Level level) { 37 | if (Level.SEVERE.equals(level)) { 38 | return SEVERE_COLOR; 39 | } else if (Level.WARNING.equals(level)) { 40 | return WARNING_COLOR; 41 | } 42 | return INFO_COLOR; 43 | } 44 | 45 | private static String format(LogRecord record) { 46 | String msg = record.getMessage(); 47 | 48 | Object[] params = record.getParameters(); 49 | if (params == null) return msg; 50 | for (int i = 0; i < params.length; i++) { 51 | msg = msg.replace("{" + i + "}", String.valueOf(params[i])); 52 | } 53 | return msg; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/GitHubUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import com.google.gson.JsonElement; 4 | import net.frankheijden.serverutils.common.entities.http.GitHubResponse; 5 | import java.io.File; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.net.HttpURLConnection; 10 | import java.net.URL; 11 | import java.nio.channels.Channels; 12 | import java.nio.channels.ReadableByteChannel; 13 | 14 | public class GitHubUtils { 15 | 16 | private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:77.0)" 17 | + " Gecko/20100101" 18 | + " Firefox/77.0"; 19 | 20 | private GitHubUtils() {} 21 | 22 | /** 23 | * Downloads file from a GitHubResponse to a file location. 24 | */ 25 | public static boolean download(GitHubResponse res, File target) throws IOException { 26 | if (res.getRateLimit().isRateLimited()) return false; 27 | try (InputStream is = res.getStream()) { 28 | if (is == null) return false; 29 | try ( 30 | ReadableByteChannel rbc = Channels.newChannel(is); 31 | FileOutputStream fos = new FileOutputStream(target) 32 | ) { 33 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 34 | return true; 35 | } 36 | } 37 | } 38 | 39 | public static JsonElement parseJson(GitHubResponse res) throws IOException { 40 | return FileUtils.parseJson(res.getStream()); 41 | } 42 | 43 | /** 44 | * Opens a stream to a github url and returns the response. 45 | */ 46 | public static GitHubResponse stream(String url) throws IOException { 47 | HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); 48 | conn.setRequestProperty("User-Agent", USER_AGENT); 49 | conn.setConnectTimeout(10000); 50 | return GitHubResponse.from(conn); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/KeyValueComponentBuilder.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import net.frankheijden.serverutils.common.config.MessagesResource; 6 | import net.kyori.adventure.text.Component; 7 | import net.kyori.adventure.text.minimessage.Template; 8 | 9 | public class KeyValueComponentBuilder { 10 | 11 | private final MessagesResource.Message format; 12 | private final List templatesList; 13 | private final String keyPlaceholder; 14 | private final String valuePlaceholder; 15 | 16 | private KeyValueComponentBuilder( 17 | MessagesResource.Message format, 18 | String keyPlaceholder, 19 | String valuePlaceholder 20 | ) { 21 | this.format = format; 22 | this.templatesList = new ArrayList<>(); 23 | this.keyPlaceholder = keyPlaceholder; 24 | this.valuePlaceholder = valuePlaceholder; 25 | } 26 | 27 | /** 28 | * Constructs a new KeyValueComponentBuilder. 29 | */ 30 | public static KeyValueComponentBuilder create( 31 | MessagesResource.Message format, 32 | String keyPlaceholder, 33 | String valuePlaceholder 34 | ) { 35 | return new KeyValueComponentBuilder(format, keyPlaceholder, valuePlaceholder); 36 | } 37 | 38 | public KeyValueComponentBuilder.KeyValuePair key(String key) { 39 | return new KeyValuePair(key); 40 | } 41 | 42 | public KeyValueComponentBuilder.KeyValuePair key(Component key) { 43 | return new KeyValuePair(key); 44 | } 45 | 46 | private KeyValueComponentBuilder add(Template key, Template value) { 47 | this.templatesList.add(new Template[]{ key, value }); 48 | return this; 49 | } 50 | 51 | /** 52 | * Builds the current ListMessageBuilder instance into a Component. 53 | */ 54 | public List build() { 55 | List components = new ArrayList<>(templatesList.size()); 56 | 57 | for (Template[] templates : templatesList) { 58 | components.add(format.toComponent(templates)); 59 | } 60 | 61 | return components; 62 | } 63 | 64 | public class KeyValuePair { 65 | 66 | private final Template key; 67 | 68 | private KeyValuePair(String key) { 69 | this.key = Template.of(keyPlaceholder, key); 70 | } 71 | 72 | private KeyValuePair(Component key) { 73 | this.key = Template.of(keyPlaceholder, key); 74 | } 75 | 76 | public KeyValueComponentBuilder value(String value) { 77 | if (value == null) return KeyValueComponentBuilder.this; 78 | return add(key, Template.of(valuePlaceholder, value)); 79 | } 80 | 81 | public KeyValueComponentBuilder value(Component value) { 82 | if (value == null) return KeyValueComponentBuilder.this; 83 | return add(key, Template.of(valuePlaceholder, value)); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/ListComponentBuilder.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collection; 6 | import java.util.List; 7 | import net.kyori.adventure.text.Component; 8 | import net.kyori.adventure.text.TextComponent; 9 | 10 | public class ListComponentBuilder { 11 | 12 | private final List elements; 13 | private Format format; 14 | private Component separator; 15 | private Component lastSeparator; 16 | private Component emptyValue; 17 | 18 | private ListComponentBuilder() { 19 | this.elements = new ArrayList<>(); 20 | this.emptyValue = Component.empty(); 21 | } 22 | 23 | public static ListComponentBuilder create(Collection list) { 24 | return new ListComponentBuilder().addAll(list); 25 | } 26 | 27 | @SafeVarargs 28 | public static ListComponentBuilder create(T... elements) { 29 | return new ListComponentBuilder().addAll(Arrays.asList(elements)); 30 | } 31 | 32 | public ListComponentBuilder format(Format format) { 33 | this.format = format; 34 | return this; 35 | } 36 | 37 | public ListComponentBuilder separator(Component separator) { 38 | this.separator = separator; 39 | return this; 40 | } 41 | 42 | public ListComponentBuilder lastSeparator(Component lastSeparator) { 43 | this.lastSeparator = lastSeparator; 44 | return this; 45 | } 46 | 47 | public ListComponentBuilder emptyValue(Component emptyValue) { 48 | this.emptyValue = emptyValue; 49 | return this; 50 | } 51 | 52 | public ListComponentBuilder addAll(Collection elements) { 53 | this.elements.addAll(elements); 54 | return this; 55 | } 56 | 57 | /** 58 | * Builds the ListComponent. 59 | */ 60 | public Component build() { 61 | if (elements.isEmpty()) { 62 | return emptyValue; 63 | } else if (elements.size() == 1) { 64 | return format.format(elements.iterator().next()); 65 | } else { 66 | TextComponent.Builder builder = Component.text(); 67 | 68 | int sizeMinusTwo = elements.size() - 2; 69 | for (int i = 0; i < elements.size(); i++) { 70 | builder.append(format.format(elements.get(i))); 71 | if (i == sizeMinusTwo && lastSeparator != null) { 72 | builder.append(lastSeparator); 73 | } else if (i < sizeMinusTwo && separator != null) { 74 | builder.append(separator); 75 | } 76 | } 77 | 78 | return builder.build(); 79 | } 80 | } 81 | 82 | public interface Format { 83 | 84 | Component format(T element); 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/MapUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.util.HashSet; 4 | import java.util.Map; 5 | import java.util.Set; 6 | import java.util.function.Predicate; 7 | 8 | public class MapUtils { 9 | 10 | /** 11 | * Removes keys from a map using a predicate. 12 | * @param map The map. 13 | * @param predicate The predicate used to test removal. 14 | */ 15 | @SuppressWarnings({"unchecked", "rawtypes"}) 16 | public static void removeKeys(Map map, Predicate predicate) { 17 | if (map == null) return; 18 | Set keysToRemove = new HashSet<>(); 19 | map.forEach((k, v) -> { 20 | if (predicate.test(k)) { 21 | keysToRemove.add(k); 22 | } 23 | }); 24 | keysToRemove.forEach(map::remove); 25 | } 26 | 27 | /** 28 | * Removes values from a map using a predicate. 29 | * @param map The map. 30 | * @param predicate The predicate used to test removal. 31 | */ 32 | @SuppressWarnings({"unchecked", "rawtypes"}) 33 | public static void removeValues(Map map, Predicate predicate) { 34 | if (map == null) return; 35 | Set valuesToRemove = new HashSet<>(); 36 | map.forEach((k, v) -> { 37 | if (predicate.test(v)) { 38 | valuesToRemove.add(k); 39 | } 40 | }); 41 | valuesToRemove.forEach(map::remove); 42 | } 43 | 44 | /** 45 | * Removes a key from a map. 46 | * @param map The map instance. 47 | * @param obj The object to remove. 48 | */ 49 | @SuppressWarnings("rawtypes") 50 | public static void remove(Map map, Object obj) { 51 | if (map == null) return; 52 | map.remove(obj); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/PredicateFilter.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.util.function.Predicate; 4 | import java.util.logging.Filter; 5 | import java.util.logging.LogRecord; 6 | import java.util.logging.Logger; 7 | 8 | public class PredicateFilter implements Filter { 9 | 10 | private Predicate predicate; 11 | private Filter filter; 12 | 13 | public void setPredicate(Predicate predicate) { 14 | this.predicate = predicate; 15 | } 16 | 17 | public void start(Logger logger) { 18 | this.filter = logger.getFilter(); 19 | logger.setFilter(this); 20 | } 21 | 22 | public void stop(Logger logger) { 23 | logger.setFilter(filter); 24 | } 25 | 26 | @Override 27 | public boolean isLoggable(LogRecord record) { 28 | return predicate.test(record); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/ReflectionUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import dev.frankheijden.minecraftreflection.Reflection; 4 | import java.lang.invoke.MethodHandle; 5 | import java.lang.invoke.MethodHandles; 6 | import java.security.AccessController; 7 | import java.security.PrivilegedAction; 8 | import java.util.function.Consumer; 9 | import sun.misc.Unsafe; 10 | 11 | public class ReflectionUtils { 12 | 13 | private static MethodHandle theUnsafeFieldMethodHandle; 14 | 15 | static { 16 | try { 17 | theUnsafeFieldMethodHandle = MethodHandles.lookup().unreflectGetter(Reflection.getAccessibleField( 18 | Unsafe.class, 19 | "theUnsafe" 20 | )); 21 | } catch (Throwable th) { 22 | th.printStackTrace(); 23 | } 24 | } 25 | 26 | private ReflectionUtils() {} 27 | 28 | /** 29 | * Performs a privileged action while accessing {@link Unsafe}. 30 | */ 31 | public static void doPrivilegedWithUnsafe(Consumer privilegedAction) { 32 | AccessController.doPrivileged((PrivilegedAction) () -> { 33 | try { 34 | privilegedAction.accept((Unsafe) theUnsafeFieldMethodHandle.invoke()); 35 | } catch (Throwable th) { 36 | th.printStackTrace(); 37 | } 38 | return null; 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | 5 | public class StringUtils { 6 | 7 | /** 8 | * Applies placeholders to a message. 9 | * @param message The message. 10 | * @param replacements The replacements of the message. Expects input to be even and in a key-value like format. 11 | * Example: ["%player%", "Player"] 12 | * @return The message with translated placeholders. 13 | */ 14 | public static String apply(String message, String... replacements) { 15 | if (message == null || message.isEmpty()) return null; 16 | message = message.replace("\\n", "\n"); 17 | for (int i = 0; i < replacements.length; i++, i++) { 18 | message = message.replace(replacements[i], replacements[i + 1]); 19 | } 20 | return message; 21 | } 22 | 23 | /** 24 | * Joins strings from an array starting from begin index (including). 25 | * @param delimiter The delimiter to join the strings on. 26 | * @param strings The string array. 27 | * @param begin Begin index (including) 28 | * @return The joined string. 29 | */ 30 | public static String join(String delimiter, String[] strings, int begin) { 31 | return join(delimiter, strings, begin, strings.length); 32 | } 33 | 34 | /** 35 | * Joins strings from an array from begin index (including) until end index (excluding). 36 | * @param delimiter The delimiter to join the strings on. 37 | * @param strings The string array. 38 | * @param begin Begin index (including) 39 | * @param end End index (excluding) 40 | * @return The joined string. 41 | */ 42 | public static String join(String delimiter, String[] strings, int begin, int end) { 43 | StringBuilder sb = new StringBuilder(); 44 | for (int i = begin; i < end; i++) { 45 | sb.append(delimiter).append(strings[i]); 46 | } 47 | return sb.substring(1); 48 | } 49 | 50 | private static final byte[] HEX_ARRAY = "0123456789abcdef".getBytes(StandardCharsets.US_ASCII); 51 | 52 | /** 53 | * Converts a bytes array to hex. 54 | * via https://stackoverflow.com/a/9855338/11239174 55 | */ 56 | public static String bytesToHex(byte[] bytes) { 57 | byte[] hexChars = new byte[bytes.length * 2]; 58 | for (int j = 0; j < bytes.length; j++) { 59 | int v = bytes[j] & 0xFF; 60 | hexChars[j * 2] = HEX_ARRAY[v >>> 4]; 61 | hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; 62 | } 63 | return new String(hexChars, StandardCharsets.UTF_8); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Common/src/main/java/net/frankheijden/serverutils/common/utils/VersionUtils.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | public class VersionUtils { 6 | 7 | private static final Pattern integerPattern = Pattern.compile("[^0-9]"); 8 | 9 | /** 10 | * Compares two versions in X.X.X format. 11 | * Returns true if version is newer than the old one. 12 | * @param oldVersion The old version. 13 | * @param newVersion The new version. 14 | * @return true iff new version is newer than old version. 15 | */ 16 | public static boolean isNewVersion(String oldVersion, String newVersion) { 17 | if (oldVersion == null || newVersion == null) return false; 18 | String[] oldVersionSplit = oldVersion.split("\\."); 19 | String[] newVersionSplit = newVersion.split("\\."); 20 | 21 | int i = 0; 22 | while (i < oldVersionSplit.length && i < newVersionSplit.length) { 23 | int o = extractInteger(oldVersionSplit[i]); 24 | int n = extractInteger(newVersionSplit[i]); 25 | if (i != oldVersionSplit.length - 1 && i != newVersionSplit.length - 1) { 26 | if (n < o) return false; 27 | } 28 | if (n > o) return true; 29 | i++; 30 | } 31 | return false; 32 | } 33 | 34 | private static Integer extractInteger(String str) { 35 | return Integer.parseInt(integerPattern.matcher(str).replaceAll("")); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Common/src/main/resources/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "config-version": 1, 3 | "settings": { 4 | "check-updates-boot": true, 5 | "check-updates-login": false, 6 | "download-updates-boot": false, 7 | "download-updates-login": false, 8 | "install-updates-boot": false, 9 | "install-updates-login": false 10 | }, 11 | "unload-after-startup": { 12 | "delay-ticks": 20, 13 | "plugins": [] 14 | }, 15 | "hide-plugins-from-plugins-command": [], 16 | "protected-plugins": [] 17 | } 18 | -------------------------------------------------------------------------------- /Common/src/test/java/net/frankheijden/serverutils/common/config/MessageKeyTest.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.config; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.assertj.core.api.Assertions.assertThatCode; 5 | 6 | import java.util.Arrays; 7 | import java.util.stream.Stream; 8 | import org.junit.jupiter.params.ParameterizedTest; 9 | import org.junit.jupiter.params.provider.Arguments; 10 | import org.junit.jupiter.params.provider.MethodSource; 11 | 12 | class MessageKeyTest { 13 | 14 | @ParameterizedTest(name = "key = {0}") 15 | @MethodSource("messageKeyGenerator") 16 | void testMessageKeyConsistency(MessageKey key) { 17 | assertThatCode(() -> MessageKey.fromPath(key.getPath())).doesNotThrowAnyException(); 18 | assertThat(MessageKey.fromPath(key.getPath())).isEqualTo(key); 19 | } 20 | 21 | private static Stream messageKeyGenerator() { 22 | return Arrays.stream(MessageKey.values()) 23 | .map(Arguments::of); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Common/src/test/java/net/frankheijden/serverutils/common/utils/ListBuilderTest.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import static java.util.Arrays.asList; 4 | import static java.util.Collections.singletonList; 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | 7 | import java.util.List; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.TextComponent; 10 | import net.kyori.adventure.text.serializer.ComponentSerializer; 11 | import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; 12 | import org.junit.jupiter.api.Test; 13 | 14 | class ListBuilderTest { 15 | 16 | private static final ComponentSerializer plainTextComponentSerializer 17 | = PlainTextComponentSerializer.plainText(); 18 | private final Component separator = Component.text(", "); 19 | private final Component lastSeparator = Component.text(" and "); 20 | 21 | @Test 22 | void testToStringOneElement() { 23 | Component component = ListComponentBuilder.create(singletonList("Nice")) 24 | .format(Component::text) 25 | .separator(separator) 26 | .lastSeparator(lastSeparator) 27 | .build(); 28 | assertEquals("Nice", plainTextComponentSerializer.serialize(component)); 29 | } 30 | 31 | @Test 32 | void testToStringTwoElements() { 33 | Component component = ListComponentBuilder.create(asList("Nice", "List")) 34 | .format(Component::text) 35 | .separator(separator) 36 | .lastSeparator(lastSeparator) 37 | .build(); 38 | assertEquals("Nice and List", plainTextComponentSerializer.serialize(component)); 39 | } 40 | 41 | @Test 42 | void testToStringMultipleElements() { 43 | Component component = ListComponentBuilder.create(asList("Nice", "List", "You", "Having", "There")) 44 | .format(Component::text) 45 | .separator(separator) 46 | .lastSeparator(lastSeparator) 47 | .build(); 48 | assertEquals("Nice, List, You, Having and There", plainTextComponentSerializer.serialize(component)); 49 | } 50 | 51 | @Test 52 | void testToStringCustomFormat() { 53 | List objects = asList( 54 | new TestObject("pre1", 2), 55 | new TestObject("pre2", 3), 56 | new TestObject("pre3", 4) 57 | ); 58 | 59 | Component component = ListComponentBuilder.create(objects) 60 | .format(obj -> Component.text(obj.prefix + "-" + obj.value)) 61 | .separator(Component.text("; ")) 62 | .lastSeparator(Component.text(" and at last ")) 63 | .build(); 64 | assertEquals("pre1-2; pre2-3 and at last pre3-4", plainTextComponentSerializer.serialize(component)); 65 | } 66 | 67 | private static class TestObject { 68 | private final String prefix; 69 | private final int value; 70 | 71 | public TestObject(String prefix, int value) { 72 | this.prefix = prefix; 73 | this.value = value; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Common/src/test/java/net/frankheijden/serverutils/common/utils/VersionUtilsTest.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.common.utils; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.junit.jupiter.params.provider.Arguments.of; 5 | 6 | import java.util.stream.Stream; 7 | import org.junit.jupiter.params.ParameterizedTest; 8 | import org.junit.jupiter.params.provider.Arguments; 9 | import org.junit.jupiter.params.provider.MethodSource; 10 | 11 | class VersionUtilsTest { 12 | 13 | @ParameterizedTest(name = "old = {0}, new = {1}, expected = {2}") 14 | @MethodSource("versionGenerator") 15 | void isNewVersion(String oldVersion, String newVersion, boolean expected) { 16 | assertThat(VersionUtils.isNewVersion(oldVersion, newVersion)).isEqualTo(expected); 17 | } 18 | 19 | private static Stream versionGenerator() { 20 | return Stream.of( 21 | of("0", "1", true), 22 | of("1", "0", false), 23 | of("9", "10", true), 24 | of("10", "9", false), 25 | of("-1", "5", true), 26 | of("5", "-1", false), 27 | of("10.1", "10.0", false), 28 | of("100.0", "120.0", true), 29 | of("1.0.0", "1.0.1", true), 30 | of("1.0.0", "1.1.0", true), 31 | of("1.0.0", "2.0.0", true), 32 | of("0.0.1", "0.0.1", false), 33 | of("0.0.1", "0.0.0", false), 34 | of("0.1.0", "0.0.1", false), 35 | of("1.0.0", "0.0.1", false), 36 | of("1.1.0", "0.1.1", false), 37 | of("1.0.0.0", "1.0.0.1", true), 38 | of("1.0.1-DEV", "1.0.2", true) 39 | ); 40 | } 41 | } -------------------------------------------------------------------------------- /Velocity/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | 3 | plugins { 4 | id("net.kyori.blossom") version "1.3.0" 5 | } 6 | 7 | group = "${rootProject.group}" 8 | val dependencyDir = "${group}.velocity.dependencies" 9 | version = rootProject.version 10 | base { 11 | archivesName.set("${rootProject.name}-Velocity") 12 | } 13 | 14 | repositories { 15 | maven("https://nexus.velocitypowered.com/repository/maven-public/") 16 | maven("https://libraries.minecraft.net") 17 | } 18 | 19 | dependencies { 20 | implementation("cloud.commandframework:cloud-velocity:${VersionConstants.cloudVersion}") 21 | implementation("org.bstats:bstats-velocity:${VersionConstants.bstatsVersion}") 22 | implementation(project(":Common")) 23 | implementation("net.kyori:adventure-text-minimessage:${VersionConstants.adventureMinimessageVersion}") { 24 | exclude("net.kyori", "adventure-api") 25 | } 26 | compileOnly("com.velocitypowered:velocity-api:3.1.2-SNAPSHOT") 27 | compileOnly("com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT") 28 | compileOnly("com.electronwill.night-config:toml:3.6.3") 29 | annotationProcessor("com.velocitypowered:velocity-api:3.1.2-SNAPSHOT") 30 | } 31 | 32 | tasks { 33 | blossom { 34 | replaceToken("{version}", version, "src/main/java/net/frankheijden/serverutils/velocity/ServerUtils.java") 35 | } 36 | } 37 | 38 | tasks.withType { 39 | relocate("org.bstats", "${dependencyDir}.bstats") 40 | } 41 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/commands/VelocityCommandPlugins.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.commands; 2 | 3 | import cloud.commandframework.Command; 4 | import cloud.commandframework.CommandManager; 5 | import cloud.commandframework.context.CommandContext; 6 | import com.velocitypowered.api.plugin.PluginContainer; 7 | import net.frankheijden.serverutils.common.commands.CommandPlugins; 8 | import net.frankheijden.serverutils.velocity.entities.VelocityAudience; 9 | import net.frankheijden.serverutils.velocity.entities.VelocityPlugin; 10 | import net.frankheijden.serverutils.velocity.entities.VelocityPluginDescription; 11 | 12 | @SuppressWarnings("LineLength") 13 | public class VelocityCommandPlugins extends CommandPlugins { 14 | 15 | public VelocityCommandPlugins(VelocityPlugin plugin) { 16 | super(plugin); 17 | } 18 | 19 | @Override 20 | protected void register( 21 | CommandManager manager, 22 | Command.Builder builder 23 | ) { 24 | manager.command(builder 25 | .flag(parseFlag("version")) 26 | .handler(this::handlePlugins)); 27 | } 28 | 29 | @Override 30 | protected void handlePlugins(CommandContext context) { 31 | VelocityAudience sender = context.getSender(); 32 | boolean hasVersionFlag = context.flags().contains("version"); 33 | 34 | handlePlugins(sender, plugin.getPluginManager().getPluginsSorted(), hasVersionFlag); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/entities/VelocityAudience.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.entities; 2 | 3 | import com.velocitypowered.api.command.CommandSource; 4 | import com.velocitypowered.api.proxy.Player; 5 | import net.frankheijden.serverutils.common.entities.ServerUtilsAudience; 6 | import net.kyori.adventure.audience.Audience; 7 | import net.kyori.adventure.text.Component; 8 | 9 | public class VelocityAudience extends ServerUtilsAudience { 10 | 11 | protected VelocityAudience(Audience audience, CommandSource source) { 12 | super(audience, source); 13 | } 14 | 15 | @Override 16 | public boolean isPlayer() { 17 | return source instanceof Player; 18 | } 19 | 20 | @Override 21 | public boolean hasPermission(String permission) { 22 | return source.hasPermission(permission); 23 | } 24 | 25 | @Override 26 | public void sendMessage(Component component) { 27 | source.sendMessage(component); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/entities/VelocityAudienceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.entities; 2 | 3 | import com.velocitypowered.api.command.CommandSource; 4 | import com.velocitypowered.api.proxy.Player; 5 | import net.frankheijden.serverutils.common.providers.ServerUtilsAudienceProvider; 6 | import net.frankheijden.serverutils.velocity.ServerUtils; 7 | import net.kyori.adventure.text.Component; 8 | 9 | public class VelocityAudienceProvider implements ServerUtilsAudienceProvider { 10 | 11 | private final ServerUtils plugin; 12 | private final VelocityAudience consoleServerAudience; 13 | 14 | /** 15 | * Constructs a new VelocityAudienceProvider. 16 | */ 17 | public VelocityAudienceProvider(ServerUtils plugin) { 18 | this.plugin = plugin; 19 | this.consoleServerAudience = new VelocityAudience( 20 | plugin.getProxy().getConsoleCommandSource(), 21 | plugin.getProxy().getConsoleCommandSource() 22 | ); 23 | } 24 | 25 | @Override 26 | public VelocityAudience getConsoleServerAudience() { 27 | return consoleServerAudience; 28 | } 29 | 30 | @Override 31 | public VelocityAudience get(CommandSource source) { 32 | return new VelocityAudience(source, source); 33 | } 34 | 35 | @Override 36 | public void broadcast(Component component, String permission) { 37 | for (Player player : plugin.getProxy().getAllPlayers()) { 38 | if (player.hasPermission(permission)) { 39 | player.sendMessage(component); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/entities/VelocityPluginDescription.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.entities; 2 | 3 | import com.velocitypowered.api.plugin.PluginDescription; 4 | import com.velocitypowered.api.plugin.meta.PluginDependency; 5 | import java.io.File; 6 | import java.nio.file.Path; 7 | import java.util.Optional; 8 | import java.util.Set; 9 | import java.util.stream.Collectors; 10 | import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription; 11 | import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException; 12 | 13 | public class VelocityPluginDescription implements ServerUtilsPluginDescription { 14 | 15 | private final PluginDescription description; 16 | private final File file; 17 | private final String author; 18 | private final Set dependencies; 19 | 20 | /** 21 | * Constructs a new BungeePluginDescription. 22 | */ 23 | public VelocityPluginDescription(PluginDescription description) { 24 | this.description = description; 25 | 26 | Optional sourceOptional = description.getSource(); 27 | if (!sourceOptional.isPresent()) throw new InvalidPluginDescriptionException("Source path is null"); 28 | 29 | this.file = sourceOptional.get().toFile(); 30 | this.author = String.join(", ", description.getAuthors()); 31 | this.dependencies = description.getDependencies().stream() 32 | .map(PluginDependency::getId) 33 | .collect(Collectors.toSet()); 34 | } 35 | 36 | @Override 37 | public String getId() { 38 | return this.description.getId(); 39 | } 40 | 41 | @Override 42 | public String getName() { 43 | return this.description.getName().orElse(""); 44 | } 45 | 46 | @Override 47 | public String getVersion() { 48 | return this.description.getVersion().orElse(""); 49 | } 50 | 51 | @Override 52 | public String getAuthor() { 53 | return this.author; 54 | } 55 | 56 | @Override 57 | public File getFile() { 58 | return this.file; 59 | } 60 | 61 | @Override 62 | public Set getDependencies() { 63 | return this.dependencies; 64 | } 65 | 66 | public PluginDescription getDescription() { 67 | return description; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/entities/VelocityResourceProvider.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.entities; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.nio.file.StandardCopyOption; 9 | import net.frankheijden.serverutils.common.config.ServerUtilsConfig; 10 | import net.frankheijden.serverutils.common.providers.ResourceProvider; 11 | import net.frankheijden.serverutils.velocity.ServerUtils; 12 | 13 | public class VelocityResourceProvider implements ResourceProvider { 14 | 15 | private final ServerUtils plugin; 16 | 17 | public VelocityResourceProvider(ServerUtils plugin) { 18 | this.plugin = plugin; 19 | } 20 | 21 | @Override 22 | public InputStream getRawResource(String resource) { 23 | return plugin.getClass().getClassLoader().getResourceAsStream(resource); 24 | } 25 | 26 | @Override 27 | public ServerUtilsConfig load(InputStream is) { 28 | try { 29 | Path tmpFile = Files.createTempFile(null, null); 30 | Files.copy(is, tmpFile, StandardCopyOption.REPLACE_EXISTING); 31 | 32 | VelocityTomlConfig config = new VelocityTomlConfig(tmpFile.toFile()); 33 | Files.delete(tmpFile); 34 | 35 | return config; 36 | } catch (IOException ex) { 37 | ex.printStackTrace(); 38 | } 39 | return null; 40 | } 41 | 42 | @Override 43 | public ServerUtilsConfig load(File file) { 44 | return new VelocityTomlConfig(file); 45 | } 46 | 47 | @Override 48 | public String getResourceExtension() { 49 | return ".toml"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/entities/VelocityTomlConfig.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.entities; 2 | 3 | import com.electronwill.nightconfig.core.CommentedConfig; 4 | import com.electronwill.nightconfig.core.file.CommentedFileConfig; 5 | import com.electronwill.nightconfig.toml.TomlFormat; 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | import java.util.Collection; 10 | import java.util.HashMap; 11 | import java.util.HashSet; 12 | import java.util.List; 13 | import java.util.Map; 14 | import net.frankheijden.serverutils.common.config.ServerUtilsConfig; 15 | 16 | public class VelocityTomlConfig implements ServerUtilsConfig { 17 | 18 | private final CommentedConfig config; 19 | private final File file; 20 | 21 | /** 22 | * Creates a new VelocityTomlConfig instance. 23 | */ 24 | public VelocityTomlConfig(File file) { 25 | CommentedFileConfig conf = CommentedFileConfig.of(file, TomlFormat.instance()); 26 | conf.load(); 27 | 28 | this.config = conf; 29 | this.file = file; 30 | } 31 | 32 | public VelocityTomlConfig(CommentedConfig config, File file) { 33 | this.config = config; 34 | this.file = file; 35 | } 36 | 37 | @Override 38 | public Object get(String path) { 39 | Object obj = config.get(path); 40 | if (obj instanceof CommentedConfig) { 41 | return new VelocityTomlConfig((CommentedConfig) obj, file); 42 | } 43 | return obj; 44 | } 45 | 46 | @Override 47 | public List getStringList(String path) { 48 | return config.getOrElse(path, new ArrayList<>()); 49 | } 50 | 51 | @Override 52 | public Map getMap(String path) { 53 | CommentedConfig section = config.get(path); 54 | if (section == null) return new HashMap<>(); 55 | return section.valueMap(); 56 | } 57 | 58 | @Override 59 | public void setUnsafe(String path, Object value) { 60 | config.set(path, value); 61 | } 62 | 63 | @Override 64 | public void remove(String path) { 65 | config.remove(path); 66 | } 67 | 68 | @Override 69 | public String getString(String path) { 70 | return config.get(path); 71 | } 72 | 73 | @Override 74 | public boolean getBoolean(String path) { 75 | return config.get(path); 76 | } 77 | 78 | @Override 79 | public int getInt(String path) { 80 | return config.getOrElse(path, -1); 81 | } 82 | 83 | @Override 84 | public Collection getKeys() { 85 | return new HashSet<>(config.valueMap().keySet()); 86 | } 87 | 88 | @Override 89 | public void save() throws IOException { 90 | if (config instanceof CommentedFileConfig) { 91 | ((CommentedFileConfig) config).save(); 92 | } else { 93 | throw new IOException("Config is not an instance of CommentedFileConfig!"); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/events/VelocityPluginDisableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.events; 2 | 3 | import com.velocitypowered.api.plugin.PluginContainer; 4 | import net.frankheijden.serverutils.common.events.PluginDisableEvent; 5 | 6 | public class VelocityPluginDisableEvent extends VelocityPluginEvent implements PluginDisableEvent { 7 | 8 | public VelocityPluginDisableEvent(PluginContainer plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/events/VelocityPluginEnableEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.events; 2 | 3 | import com.velocitypowered.api.plugin.PluginContainer; 4 | import net.frankheijden.serverutils.common.events.PluginEnableEvent; 5 | 6 | public class VelocityPluginEnableEvent extends VelocityPluginEvent implements PluginEnableEvent { 7 | 8 | public VelocityPluginEnableEvent(PluginContainer plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/events/VelocityPluginEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.events; 2 | 3 | import com.velocitypowered.api.plugin.PluginContainer; 4 | import net.frankheijden.serverutils.common.events.PluginEvent; 5 | 6 | public abstract class VelocityPluginEvent implements PluginEvent { 7 | 8 | private final PluginContainer plugin; 9 | private final Stage stage; 10 | 11 | protected VelocityPluginEvent(PluginContainer plugin, Stage stage) { 12 | this.plugin = plugin; 13 | this.stage = stage; 14 | } 15 | 16 | @Override 17 | public PluginContainer getPlugin() { 18 | return plugin; 19 | } 20 | 21 | @Override 22 | public Stage getStage() { 23 | return stage; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/events/VelocityPluginLoadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.events; 2 | 3 | import com.velocitypowered.api.plugin.PluginContainer; 4 | import net.frankheijden.serverutils.common.events.PluginLoadEvent; 5 | 6 | public class VelocityPluginLoadEvent extends VelocityPluginEvent implements PluginLoadEvent { 7 | 8 | public VelocityPluginLoadEvent(PluginContainer plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/events/VelocityPluginUnloadEvent.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.events; 2 | 3 | import com.velocitypowered.api.plugin.PluginContainer; 4 | import net.frankheijden.serverutils.common.events.PluginUnloadEvent; 5 | 6 | public class VelocityPluginUnloadEvent extends VelocityPluginEvent implements PluginUnloadEvent { 7 | 8 | public VelocityPluginUnloadEvent(PluginContainer plugin, Stage stage) { 9 | super(plugin, stage); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/listeners/VelocityPlayerListener.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.listeners; 2 | 3 | import com.velocitypowered.api.event.Subscribe; 4 | import com.velocitypowered.api.event.player.PlayerChooseInitialServerEvent; 5 | import com.velocitypowered.api.plugin.PluginContainer; 6 | import net.frankheijden.serverutils.common.listeners.PlayerListener; 7 | import net.frankheijden.serverutils.velocity.entities.VelocityAudience; 8 | import net.frankheijden.serverutils.velocity.entities.VelocityPlugin; 9 | 10 | public class VelocityPlayerListener extends PlayerListener { 11 | 12 | public VelocityPlayerListener(VelocityPlugin plugin) { 13 | super(plugin); 14 | } 15 | 16 | @Subscribe 17 | public void onPlayerChooseInitialServer(PlayerChooseInitialServerEvent event) { 18 | handleUpdate(plugin.getChatProvider().get(event.getPlayer())); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/managers/VelocityPluginCommandManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.managers; 2 | 3 | import com.google.common.collect.HashMultimap; 4 | import com.google.common.collect.Multimap; 5 | import com.google.common.collect.Multimaps; 6 | import com.google.gson.Gson; 7 | import com.google.gson.reflect.TypeToken; 8 | import java.io.IOException; 9 | import java.nio.charset.StandardCharsets; 10 | import java.nio.file.Files; 11 | import java.nio.file.Path; 12 | import java.nio.file.StandardOpenOption; 13 | import java.util.Collection; 14 | import java.util.Map; 15 | import java.util.Optional; 16 | 17 | public class VelocityPluginCommandManager { 18 | 19 | private static final Gson gson = new Gson(); 20 | 21 | private final Multimap pluginCommands; 22 | private final Path path; 23 | 24 | public VelocityPluginCommandManager(Path path) { 25 | this.pluginCommands = Multimaps.synchronizedSetMultimap(HashMultimap.create()); 26 | this.path = path; 27 | } 28 | 29 | /** 30 | * Loads and constructs a new {@link VelocityPluginCommandManager} from the given {@link Path}. 31 | */ 32 | public static VelocityPluginCommandManager load(Path path) throws IOException { 33 | VelocityPluginCommandManager manager = new VelocityPluginCommandManager(path); 34 | if (Files.exists(path)) { 35 | Map> rawMap = gson.fromJson( 36 | Files.newBufferedReader(path), 37 | new TypeToken>>(){}.getType() 38 | ); 39 | rawMap.forEach(manager.pluginCommands::putAll); 40 | } 41 | 42 | return manager; 43 | } 44 | 45 | /** 46 | * Attempts to find the plugin id for a given command alias. 47 | */ 48 | public Optional findPluginId(String alias) { 49 | for (Map.Entry entry : pluginCommands.entries()) { 50 | if (alias.equals(entry.getValue())) { 51 | return Optional.of(entry.getKey()); 52 | } 53 | } 54 | return Optional.empty(); 55 | } 56 | 57 | public Multimap getPluginCommands() { 58 | return pluginCommands; 59 | } 60 | 61 | /** 62 | * Saves the map to the {@link Path} it was loaded from. 63 | */ 64 | public void save() throws IOException { 65 | if (Files.notExists(path.getParent())) { 66 | Files.createDirectories(path.getParent()); 67 | } 68 | 69 | Files.write( 70 | path, 71 | gson.toJson(pluginCommands.asMap()).getBytes(StandardCharsets.UTF_8), 72 | StandardOpenOption.CREATE, 73 | StandardOpenOption.TRUNCATE_EXISTING 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/managers/VelocityTaskManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.managers; 2 | 3 | import com.velocitypowered.api.scheduler.ScheduledTask; 4 | import java.time.Duration; 5 | import net.frankheijden.serverutils.common.managers.AbstractTaskManager; 6 | import net.frankheijden.serverutils.velocity.ServerUtils; 7 | 8 | public class VelocityTaskManager extends AbstractTaskManager { 9 | 10 | private final ServerUtils plugin; 11 | 12 | public VelocityTaskManager(ServerUtils plugin) { 13 | super(ScheduledTask::cancel); 14 | this.plugin = plugin; 15 | } 16 | 17 | @Override 18 | protected ScheduledTask runTaskImpl(Runnable runnable) { 19 | return runTaskAsynchronously(runnable); 20 | } 21 | 22 | @Override 23 | public ScheduledTask runTaskLater(Runnable runnable, long delay) { 24 | return plugin.getProxy().getScheduler() 25 | .buildTask(plugin, runnable) 26 | .delay(Duration.ofMillis(delay * 50)) 27 | .schedule(); 28 | } 29 | 30 | @Override 31 | protected ScheduledTask runTaskAsynchronouslyImpl(Runnable runnable) { 32 | return plugin.getProxy().getScheduler() 33 | .buildTask(plugin, runnable) 34 | .schedule(); 35 | } 36 | 37 | @Override 38 | public void cancelTask(ScheduledTask task) { 39 | task.cancel(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/reflection/RJavaPluginLoader.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.reflection; 2 | 3 | import com.google.inject.Module; 4 | import com.velocitypowered.api.plugin.PluginContainer; 5 | import com.velocitypowered.api.plugin.PluginDescription; 6 | import com.velocitypowered.api.proxy.ProxyServer; 7 | import dev.frankheijden.minecraftreflection.ClassObject; 8 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 9 | import java.lang.reflect.Array; 10 | import java.nio.file.Path; 11 | 12 | public class RJavaPluginLoader { 13 | 14 | private static final MinecraftReflection reflection = MinecraftReflection 15 | .of("com.velocitypowered.proxy.plugin.loader.java.JavaPluginLoader"); 16 | 17 | private RJavaPluginLoader() {} 18 | 19 | /** 20 | * Constructs a new instance of a JavaPluginLoader. 21 | */ 22 | public static Object newInstance(ProxyServer proxy, Path baseDirectory) { 23 | return reflection.newInstance( 24 | ClassObject.of(ProxyServer.class, proxy), 25 | ClassObject.of(Path.class, baseDirectory) 26 | ); 27 | } 28 | 29 | /** 30 | * Loads a candidate description from the given source. 31 | */ 32 | public static PluginDescription loadPluginDescription(Object javaPluginLoader, Path source) { 33 | String fieldName = "loadCandidate"; 34 | try { 35 | reflection.getClazz().getDeclaredMethod(fieldName, Path.class); 36 | } catch (NoSuchMethodException ex) { 37 | fieldName = "loadPluginDescription"; 38 | } 39 | 40 | return reflection.invoke(javaPluginLoader, fieldName, ClassObject.of(Path.class, source)); 41 | } 42 | 43 | /** 44 | * Loads the plugin from their candidate PluginDescription. 45 | */ 46 | public static PluginDescription loadPlugin(Object javaPluginLoader, PluginDescription candidate) { 47 | String fieldName = "createPluginFromCandidate"; 48 | try { 49 | reflection.getClazz().getDeclaredMethod(fieldName, PluginDescription.class); 50 | } catch (NoSuchMethodException ex) { 51 | fieldName = "loadPlugin"; 52 | } 53 | 54 | return reflection.invoke(javaPluginLoader, fieldName, ClassObject.of(PluginDescription.class, candidate)); 55 | } 56 | 57 | public static Module createModule(Object javaPluginLoader, PluginContainer container) { 58 | return reflection.invoke(javaPluginLoader, "createModule", ClassObject.of(PluginContainer.class, container)); 59 | } 60 | 61 | /** 62 | * Creates the plugin. 63 | */ 64 | public static void createPlugin(Object javaPluginLoader, PluginContainer container, Module... modules) { 65 | reflection.invoke( 66 | javaPluginLoader, 67 | "createPlugin", 68 | ClassObject.of(PluginContainer.class, container), 69 | ClassObject.of(Array.newInstance(Module.class, 0).getClass(), modules) 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/reflection/RVelocityConsole.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.reflection; 2 | 3 | import com.velocitypowered.api.permission.PermissionFunction; 4 | import com.velocitypowered.api.proxy.ConsoleCommandSource; 5 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 6 | 7 | public class RVelocityConsole { 8 | 9 | private static final MinecraftReflection reflection = MinecraftReflection 10 | .of("com.velocitypowered.proxy.console.VelocityConsole"); 11 | 12 | private RVelocityConsole() {} 13 | 14 | public static void setPermissionFunction(ConsoleCommandSource velocityConsole, PermissionFunction function) { 15 | reflection.set(velocityConsole, "permissionFunction", function); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/reflection/RVelocityEventManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.reflection; 2 | 3 | import com.google.common.collect.Multimap; 4 | import com.velocitypowered.api.event.EventHandler; 5 | import com.velocitypowered.api.event.EventManager; 6 | import com.velocitypowered.api.plugin.PluginContainer; 7 | import dev.frankheijden.minecraftreflection.ClassObject; 8 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 9 | import java.lang.reflect.Array; 10 | import java.util.List; 11 | import java.util.concurrent.CompletableFuture; 12 | import java.util.concurrent.ExecutorService; 13 | import java.util.stream.Collectors; 14 | 15 | public class RVelocityEventManager { 16 | 17 | private static final MinecraftReflection reflection = MinecraftReflection 18 | .of("com.velocitypowered.proxy.event.VelocityEventManager"); 19 | 20 | private RVelocityEventManager() {} 21 | 22 | @SuppressWarnings("rawtypes") 23 | public static Multimap getHandlersByType(EventManager manager) { 24 | return reflection.get(manager, "handlersByType"); 25 | } 26 | 27 | /** 28 | * Retrieves the registrations from a plugin for a specific event. 29 | */ 30 | @SuppressWarnings("unchecked") 31 | public static List getRegistrationsByPlugins( 32 | EventManager manager, 33 | List plugins, 34 | Class eventClass 35 | ) { 36 | return (List) getHandlersByType(manager).get(eventClass).stream() 37 | .filter(r -> plugins.contains(RHandlerRegistration.getPlugin(r).getInstance().orElse(null))) 38 | .sorted(reflection.get(manager, "handlerComparator")) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | /** 43 | * Registers the listener for a given plugin. 44 | */ 45 | public static void registerInternally(EventManager manager, PluginContainer container, Object listener) { 46 | reflection.invoke( 47 | manager, 48 | "registerInternally", 49 | ClassObject.of(PluginContainer.class, container), 50 | ClassObject.of(Object.class, listener) 51 | ); 52 | } 53 | 54 | /** 55 | * Fires an event specifically for one plugin. 56 | */ 57 | public static CompletableFuture fireForPlugins( 58 | EventManager manager, 59 | E event, 60 | List pluginInstances 61 | ) { 62 | List registrations = getRegistrationsByPlugins(manager, pluginInstances, event.getClass()); 63 | CompletableFuture future = new CompletableFuture<>(); 64 | 65 | Object registrationsEmptyArray = Array.newInstance(RHandlerRegistration.reflection.getClazz(), 0); 66 | Class registrationsArrayClass = registrationsEmptyArray.getClass(); 67 | 68 | ExecutorService executor = reflection.invoke(manager, "getAsyncExecutor"); 69 | executor.execute(() -> reflection.invoke( 70 | manager, 71 | "fire", 72 | ClassObject.of(CompletableFuture.class, future), 73 | ClassObject.of(Object.class, event), 74 | ClassObject.of(int.class, 0), 75 | ClassObject.of(boolean.class, true), 76 | ClassObject.of(registrationsArrayClass, registrations.toArray((Object[]) registrationsEmptyArray)) 77 | )); 78 | 79 | return future; 80 | } 81 | 82 | public static class RHandlerRegistration { 83 | 84 | private static final MinecraftReflection reflection = MinecraftReflection 85 | .of("com.velocitypowered.proxy.event.VelocityEventManager$HandlerRegistration"); 86 | 87 | private RHandlerRegistration() {} 88 | 89 | public static PluginContainer getPlugin(Object registration) { 90 | return reflection.get(registration, "plugin"); 91 | } 92 | 93 | public static EventHandler getEventHandler(Object registration) { 94 | return reflection.get(registration, "handler"); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/reflection/RVelocityPluginContainer.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.reflection; 2 | 3 | import com.velocitypowered.api.plugin.PluginContainer; 4 | import com.velocitypowered.api.plugin.PluginDescription; 5 | import dev.frankheijden.minecraftreflection.ClassObject; 6 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 7 | 8 | public class RVelocityPluginContainer { 9 | 10 | private static final MinecraftReflection reflection = MinecraftReflection 11 | .of("com.velocitypowered.proxy.plugin.loader.VelocityPluginContainer"); 12 | 13 | private RVelocityPluginContainer() {} 14 | 15 | public static PluginContainer newInstance(PluginDescription description) { 16 | return reflection.newInstance(ClassObject.of(PluginDescription.class, description)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/reflection/RVelocityPluginManager.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.reflection; 2 | 3 | import com.velocitypowered.api.plugin.PluginContainer; 4 | import com.velocitypowered.api.plugin.PluginManager; 5 | import dev.frankheijden.minecraftreflection.ClassObject; 6 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 7 | import java.util.Map; 8 | 9 | public class RVelocityPluginManager { 10 | 11 | private static final MinecraftReflection reflection = MinecraftReflection 12 | .of("com.velocitypowered.proxy.plugin.VelocityPluginManager"); 13 | 14 | private RVelocityPluginManager() {} 15 | 16 | /** 17 | * Retrieves the plugin map. Key is the id of the plugin. 18 | */ 19 | public static Map getPlugins(PluginManager manager) { 20 | String fieldName = "plugins"; 21 | try { 22 | reflection.getClazz().getField(fieldName); 23 | } catch (NoSuchFieldException ex) { 24 | fieldName = "pluginsById"; 25 | } 26 | 27 | return reflection.get(manager, fieldName); 28 | } 29 | 30 | public static Map getPluginInstances(PluginManager manager) { 31 | return reflection.get(manager, "pluginInstances"); 32 | } 33 | 34 | public static void registerPlugin(PluginManager manager, PluginContainer container) { 35 | reflection.invoke(manager, "registerPlugin", ClassObject.of(PluginContainer.class, container)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Velocity/src/main/java/net/frankheijden/serverutils/velocity/reflection/RVelocityScheduler.java: -------------------------------------------------------------------------------- 1 | package net.frankheijden.serverutils.velocity.reflection; 2 | 3 | import com.google.common.collect.Multimap; 4 | import com.velocitypowered.api.scheduler.ScheduledTask; 5 | import com.velocitypowered.api.scheduler.Scheduler; 6 | import dev.frankheijden.minecraftreflection.MinecraftReflection; 7 | 8 | public class RVelocityScheduler { 9 | 10 | private static final MinecraftReflection reflection = MinecraftReflection 11 | .of("com.velocitypowered.proxy.scheduler.VelocityScheduler"); 12 | 13 | private RVelocityScheduler() {} 14 | 15 | public static Multimap getTasksByPlugin(Scheduler scheduler) { 16 | return reflection.get(scheduler, "tasksByPlugin"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Velocity/src/main/resources/velocity-commands.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /Velocity/src/main/resources/velocity-config.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /Velocity/src/main/resources/velocity-messages.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /buildSrc/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/VersionConstants.kt: -------------------------------------------------------------------------------- 1 | object VersionConstants { 2 | const val cloudVersion = "1.8.0" 3 | const val adventureVersion = "4.11.0" 4 | const val adventurePlatformVersion = "4.1.2" 5 | const val adventureMinimessageVersion = "4.2.0-SNAPSHOT" 6 | const val bstatsVersion = "3.0.0" 7 | } 8 | -------------------------------------------------------------------------------- /config/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.parallel=true 2 | org.gradle.jvmargs='-Dfile.encoding=UTF-8' -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrankHeijden/ServerUtils/dfec660fc751ade57aefb10c012d08b082486eca/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if %ERRORLEVEL% equ 0 goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if %ERRORLEVEL% equ 0 goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "ServerUtils" 2 | include("Common") 3 | include("Bukkit") 4 | include("Bungee") 5 | include("Velocity") 6 | --------------------------------------------------------------------------------