Skip to content

Commit

Permalink
Merge pull request #28 from vaperion/dev
Browse files Browse the repository at this point in the history
Merge dev -> master
  • Loading branch information
vaperion authored May 14, 2022
2 parents a1d62a2 + a33322d commit 0fe1fdd
Show file tree
Hide file tree
Showing 105 changed files with 2,141 additions and 1,834 deletions.
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

11 changes: 8 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.idea/
target/
*.iml
### Gradle & IntelliJ ###
.gradle/
/.idea/
build/
out/
run/
*.iml
.idea_modules/
224 changes: 1 addition & 223 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,226 +14,4 @@ YourKit supports open source projects with innovative and intelligent tools for

![YourKit](https://www.yourkit.com/images/yklogo.png)

## Using Blade

Include the jitpack repository using the package manager of your choice:

```xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
```
```groovy
repositories {
maven { url 'https://jitpack.io' }
}
```

And finally, include the dependency:

[![Release](https://jitpack.io/v/vaperion/blade.svg)](https://jitpack.io/#vaperion/blade)

```xml
<dependencies>
<dependency>
<groupId>com.github.vaperion</groupId>
<artifactId>blade</artifactId>
<version>VERSION</version>
<scope>compile</scope>
</dependency>
</dependencies>
```
```groovy
dependencies {
implementation 'com.github.vaperion:blade:VERSION'
}
```

### Creating your first bukkit command

```java
package you.developer.exampleplugin;

import me.vaperion.blade.Blade;
import me.vaperion.blade.annotation.*;
import me.vaperion.blade.argument.BladeProvider;
import me.vaperion.blade.bindings.impl.BukkitBindings;
import me.vaperion.blade.container.impl.BukkitCommandContainer;
import org.bukkit.plugin.java.JavaPlugin;

public class ExamplePlugin extends JavaPlugin {
@Override
public void onEnable() {
Blade.of() // Create a new Blade builder
.bukkitPlugin(this) // Pass your plugin instance to Blade (optional)
.fallbackPrefix("example") // Set the fallback prefix - shows up as `/example:ban`
.containerCreator(BukkitCommandContainer.CREATOR) // Set the container creator
.overrideCommands(true) // Should blade override already registered commands? (optional, defaults to false)
.defaultPermissionMessage("No permission.") // Set the default permission message (optional)
.binding(new BukkitBindings()) // Add the default bindings for Bukkit (Player, OfflinePlayer, etc.) (optional, you may call this multiple times)
.bind(Example.class, new BladeProvider<Example>() {...}) // Bind a provider for the Example type (optional, you may call this multiple times)
.executionTimeWarningThreshold(50) // Set the maximum time (in seconds) commands on the main thread can run for (optional, defaults to 5)
.tabCompleter(new ProtocolLibTabCompleter() [or] new TabCompleter() {...}) // Set a custom tab completer (optional, defaults to DefaultTabCompleter)
.helpGenerator(new NoOpHelpGenerator() [or] new HelpGenerator() {...}) // Set a custom help generator (optional, defaults to BukkitHelpGenerator)
.build() // Finish the builder
.register(ExampleCommand.class) // Register all static commands in the provided class
.register(new ExampleCommand()) // Register all the non-static commands in the provided object
.registerPackage(ExamplePlugin.class, "you.developer.exampleplugin.commands") // Register all commands in the provided package
;
}

@Command(
value = ["test", "testing"], // Command aliases
async = true, // Should the command be called asynchronously (optional, defaults to false)
quoted = true, // Should quotes in the arguments (' and ") be parsed? (optional, defaults to false)
hidden = true, // Should blade hide this command from the help message and tab completion? (optional, defaults to false)
description = "This is an example command.", // Command description that shows up when hovering over the usage and in the help message (optional)
usage = "", // Custom usage message that you want to show instead of the default generated one (optional)
usageAlias = "test", // The command alias that should be used in the usage message (optional, defaults to the first alias in `value`)
extraUsageData = "" // Custom data that shows up after the usage message (optional)
)
@Permission(
value = "example.command.test", // The permission
message = "" // The no permission message (optional, defaults to the one set in the Blade instance)
)
public static void testCommand(@Sender CommandSender sender,
@Flag(value = 'h', description = "Should we say hi?") boolean sayHi,
@Name("message") @Combined String message) {
sender.sendMessage("Your message is: " + message);
if (sayHi) sender.sendMessage("Hi!");
}
}
```

A minimal example:
```java
package you.developer.exampleplugin;

import me.vaperion.blade.Blade;
import me.vaperion.blade.annotation.Command;
import me.vaperion.blade.argument.BladeProvider;
import me.vaperion.blade.bindings.impl.BukkitBindings;
import me.vaperion.blade.container.impl.BukkitCommandContainer;
import org.bukkit.plugin.java.JavaPlugin;

public class ExamplePlugin extends JavaPlugin {
@Override
public void onEnable() {
Blade.of()
.bukkitPlugin(this)
.fallbackPrefix("example")
.containerCreator(BukkitCommandContainer.CREATOR)
.binding(new BukkitBindings())
.build()
.register(ExamplePlugin.class)
;
}

@Command("test")
public static void testCommand(@Sender CommandSender sender) {
sender.sendMessage("Hello, World!");
}
}
```

### Creating your first velocity command

```java
package you.developer.exampleplugin;

import com.google.inject.Inject;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import me.vaperion.blade.Blade;
import me.vaperion.blade.annotation.Command;
import me.vaperion.blade.argument.BladeProvider;
import me.vaperion.blade.bindings.impl.VelocityBindings;
import me.vaperion.blade.container.impl.VelocityCommandContainer;
import net.kyori.adventure.text.Component;

@Plugin(id = "exampleplugin", name = "Example Plugin", version = "0.1.0-SNAPSHOT")
public class ExamplePlugin {

private final ProxyServer server;

@Inject
public ExamplePlugin(ProxyServer server) {
this.server = server;
this.logger = logger;

Blade.of()
.velocityServer(server)
.fallbackPrefix("example")
.containerCreator(VelocityCommandContainer.CREATOR)
.binding(new VelocityBindings())
.build()
.register(ExamplePlugin.class)
;
}

@Command("test")
public static void testCommand(@Sender CommandSource source) {
source.sendMessage(Component.text("Hello, World!"));
}
}
```

### Netty tab completer for v1_7_R4 (1.7.10)

```java
import me.vaperion.blade.service.BladeCommandService;
import me.vaperion.blade.tabcompleter.TabCompleter;
import net.minecraft.server.v1_7_R4.PacketPlayInTabComplete;
import net.minecraft.server.v1_7_R4.PacketPlayOutTabComplete;
import net.minecraft.util.io.netty.channel.ChannelDuplexHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;

public class CustomTabCompleter implements TabCompleter, Listener {

private BladeCommandService commandService;

public CustomTabCompleter(JavaPlugin plugin) {
Bukkit.getServer().getPluginManager().registerEvents(this, plugin);
}

@Override
public void init(@NotNull BladeCommandService bladeCommandService) {
this.commandService = bladeCommandService;
}

@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
((CraftPlayer) player).getHandle().playerConnection.networkManager.m.pipeline()
.addBefore("packet_handler", "blade_completer", new ChannelDuplexHandler() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof PacketPlayInTabComplete) {
String commandLine = ((PacketPlayInTabComplete) msg).c();
if (commandLine.startsWith("/")) {
commandLine = commandLine.substring(1);

List<String> suggestions = commandService.getCommandCompleter().suggest(commandLine, () -> new BukkitSender(player), (cmd) -> hasPermission(player, cmd));
if (suggestions != null) {
ctx.writeAndFlush(new PacketPlayOutTabComplete(suggestions.toArray(new String[0])));
return;
}
}
}

super.channelRead(ctx, msg);
}
});
}
}
```
### The README is currently being rewritten, please check back later!
58 changes: 58 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
plugins {
id 'java-library'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '7.1.2'
id 'io.freefair.lombok' version '6.4.3'
}

allprojects {
repositories {
mavenCentral()
}

group = 'me.vaperion.blade'
version = '3.0.0'

// workaround for gradle issue: https://github.com/gradle/gradle/issues/17236#issuecomment-894385386
tasks.withType(Copy).all {
duplicatesStrategy DuplicatesStrategy.INCLUDE
outputs.upToDateWhen { false }
}
}

subprojects {
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'io.freefair.lombok'
apply plugin: 'maven-publish'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(8)
}
}

tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

afterEvaluate {
shadowJar {
archiveClassifier.set('')
archiveFileName = 'blade-' + project.name + ".jar"
}

publishing {
publications {
maven(MavenPublication) {
artifact shadowJar
}
}
}

tasks.build.dependsOn(shadowJar)

if (project.name != 'core') {
tasks.shadowJar.dependsOn ':core:shadowJar'
}
}
}
17 changes: 17 additions & 0 deletions bukkit/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
id 'java-library'
}

repositories {
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
maven { url 'https://repo.dmulloy2.net/repository/public/' }
}

dependencies {
implementation project(":core")

compileOnly 'org.jetbrains:annotations:23.0.0'

compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package me.vaperion.blade.bukkit;

import lombok.RequiredArgsConstructor;
import me.vaperion.blade.Blade;
import me.vaperion.blade.Blade.Builder.Binder;
import me.vaperion.blade.bukkit.argument.OfflinePlayerArgument;
import me.vaperion.blade.bukkit.argument.PlayerArgument;
import me.vaperion.blade.bukkit.container.BukkitContainer;
import me.vaperion.blade.bukkit.platform.BukkitHelpGenerator;
import me.vaperion.blade.bukkit.platform.ProtocolLibTabCompleter;
import me.vaperion.blade.container.ContainerCreator;
import me.vaperion.blade.platform.BladeConfiguration;
import me.vaperion.blade.platform.BladePlatform;
import me.vaperion.blade.platform.TabCompleter;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;

import java.util.Locale;

@RequiredArgsConstructor
public final class BladeBukkitPlatform implements BladePlatform {

private final JavaPlugin plugin;

@Override
public @NotNull Object getPluginInstance() {
return plugin;
}

@Override
public @NotNull ContainerCreator<?> getContainerCreator() {
return BukkitContainer.CREATOR;
}

@Override
public void configureBlade(Blade.@NotNull Builder builder, @NotNull BladeConfiguration configuration) {
configuration.setPluginInstance(plugin);
configuration.setFallbackPrefix(plugin.getName().toLowerCase(Locale.ROOT));
configuration.setHelpGenerator(new BukkitHelpGenerator());
configuration.setTabCompleter(Bukkit.getPluginManager().isPluginEnabled("ProtocolLib") ? new ProtocolLibTabCompleter(plugin) : new TabCompleter.Default());

Binder binder = new Binder(builder, true);
binder.bind(Player.class, new PlayerArgument());
binder.bind(OfflinePlayer.class, new OfflinePlayerArgument());
}
}
Loading

0 comments on commit 0fe1fdd

Please sign in to comment.