Changes I made before breaking my local repository. Hoping this works.
This commit is contained in:
@@ -1,19 +1,19 @@
|
|||||||
[*]
|
[*]
|
||||||
charset=utf-8
|
charset=utf-8
|
||||||
end_of_line=lf
|
end_of_line=lf
|
||||||
insert_final_newline=false
|
insert_final_newline=false
|
||||||
indent_style=space
|
indent_style=space
|
||||||
indent_size=4
|
indent_size=4
|
||||||
|
|
||||||
[{.babelrc,.stylelintrc,jest.config,.eslintrc,*.bowerrc,*.jsb3,*.jsb2,*.json}]
|
[{.babelrc,.stylelintrc,jest.config,.eslintrc,*.bowerrc,*.jsb3,*.jsb2,*.json}]
|
||||||
indent_style=space
|
indent_style=space
|
||||||
indent_size=2
|
indent_size=2
|
||||||
|
|
||||||
[{*.ddl,*.sql}]
|
[{*.ddl,*.sql}]
|
||||||
indent_style=space
|
indent_style=space
|
||||||
indent_size=2
|
indent_size=2
|
||||||
|
|
||||||
[{*.yml,*.yaml}]
|
[{*.yml,*.yaml}]
|
||||||
indent_style=space
|
indent_style=space
|
||||||
indent_size=2
|
indent_size=2
|
||||||
|
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,4 +6,5 @@ build/
|
|||||||
/debug/
|
/debug/
|
||||||
target/
|
target/
|
||||||
/gradle-output.txt
|
/gradle-output.txt
|
||||||
/*.java
|
/*.java
|
||||||
|
*.dump
|
||||||
32
README.md
32
README.md
@@ -1,16 +1,16 @@
|
|||||||
# Parcels2
|
# Parcels2
|
||||||
|
|
||||||
Plot management and world generator plugin inspired by [PlotMe](https://github.com/WorldCretornica/PlotMe-Core).
|
Plot management and world generator plugin inspired by [PlotMe](https://github.com/WorldCretornica/PlotMe-Core).
|
||||||
|
|
||||||
Newer version of discontinued [Parcels](https://github.com/RedstonerServer/Parcels).
|
Newer version of discontinued [Parcels](https://github.com/RedstonerServer/Parcels).
|
||||||
|
|
||||||
Written in Kotlin.
|
Written in Kotlin.
|
||||||
This project is WIP.
|
This project is WIP.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
1. Add `worldedit-bukkit-7.0.0-beta-01.jar` to `/debug/plugins` directory
|
1. Add `worldedit-bukkit-7.0.0-beta-01.jar` to `/debug/plugins` directory
|
||||||
2. Run `gradle releaseJar`
|
2. Run `gradle releaseJar`
|
||||||
3. Kotlin stdlib classpath is placed in `/debug/lib` directory and artifact can be found in `/debug/plugins` directory
|
3. Kotlin stdlib classpath is placed in `/debug/lib` directory and artifact can be found in `/debug/plugins` directory
|
||||||
|
|||||||
@@ -13,22 +13,22 @@ version = "0.2"
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
java
|
java
|
||||||
kotlin("jvm") version "1.3.0-rc-57"
|
kotlin("jvm") version "1.3.0-rc-146"
|
||||||
id("com.github.johnrengelman.plugin-shadow") version "2.0.3"
|
id("com.github.johnrengelman.plugin-shadow") version "2.0.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
apply<JavaPlugin>()
|
apply<JavaPlugin>()
|
||||||
apply(plugin = "idea")
|
apply(plugin = "idea")
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots")
|
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
||||||
maven("https://hub.spigotmc.org/nexus/content/repositories/sonatype-nexus-snapshots")
|
maven("https://hub.spigotmc.org/nexus/content/repositories/sonatype-nexus-snapshots/")
|
||||||
maven("https://dl.bintray.com/kotlin/exposed")
|
maven("https://dl.bintray.com/kotlin/exposed/")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
maven("https://dl.bintray.com/kotlin/kotlin-dev/")
|
||||||
|
maven("https://dl.bintray.com/kotlin/kotlin-eap/")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlinx/")
|
maven("https://dl.bintray.com/kotlin/kotlinx/")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,11 +146,6 @@ tasks {
|
|||||||
|
|
||||||
val jarUrl = URL("https://yivesmirror.com/files/spigot/spigot-latest.jar")
|
val jarUrl = URL("https://yivesmirror.com/files/spigot/spigot-latest.jar")
|
||||||
val serverJarFile = file("$serverDir/lib/spigot.jar")
|
val serverJarFile = file("$serverDir/lib/spigot.jar")
|
||||||
|
|
||||||
|
|
||||||
doFirst {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,5 +166,8 @@ val ConfigurationContainer.`provided`: Configuration
|
|||||||
val ConfigurationContainer.`kotlinStd`: Configuration
|
val ConfigurationContainer.`kotlinStd`: Configuration
|
||||||
get() = findByName("kotlinStd") ?: create("kotlinStd").let { compileClasspath.extendsFrom(it) }
|
get() = findByName("kotlinStd") ?: create("kotlinStd").let { compileClasspath.extendsFrom(it) }
|
||||||
|
|
||||||
fun Jar.fromFiles(files: Iterable<File>) =
|
fun Jar.fromFiles(files: Iterable<File>) {
|
||||||
|
return
|
||||||
afterEvaluate { from(*files.map { if (it.isDirectory) it else zipTree(it) }.toTypedArray()) }
|
afterEvaluate { from(*files.map { if (it.isDirectory) it else zipTree(it) }.toTypedArray()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,120 +1,120 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.predef.DefaultGroupCommand;
|
import io.dico.dicore.command.predef.DefaultGroupCommand;
|
||||||
import io.dico.dicore.command.predef.HelpCommand;
|
import io.dico.dicore.command.predef.HelpCommand;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ChildCommandAddress extends ModifiableCommandAddress {
|
public class ChildCommandAddress extends ModifiableCommandAddress {
|
||||||
ModifiableCommandAddress parent;
|
ModifiableCommandAddress parent;
|
||||||
final List<String> namesModifiable = new ArrayList<>(4);
|
final List<String> namesModifiable = new ArrayList<>(4);
|
||||||
List<String> names = namesModifiable;
|
List<String> names = namesModifiable;
|
||||||
Command command;
|
Command command;
|
||||||
boolean isCommandTrailing;
|
boolean isCommandTrailing;
|
||||||
|
|
||||||
public ChildCommandAddress() {
|
public ChildCommandAddress() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChildCommandAddress(Command command) {
|
public ChildCommandAddress(Command command) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChildCommandAddress(Command command, String name, String... aliases) {
|
public ChildCommandAddress(Command command, String name, String... aliases) {
|
||||||
this(command);
|
this(command);
|
||||||
addNameAndAliases(name, aliases);
|
addNameAndAliases(name, aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ChildCommandAddress newPlaceHolderCommand(String name, String... aliases) {
|
public static ChildCommandAddress newPlaceHolderCommand(String name, String... aliases) {
|
||||||
ChildCommandAddress rv = new ChildCommandAddress();
|
ChildCommandAddress rv = new ChildCommandAddress();
|
||||||
rv.setupAsPlaceholder(name, aliases);
|
rv.setupAsPlaceholder(name, aliases);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupAsPlaceholder(String name, String... aliases) {
|
public void setupAsPlaceholder(String name, String... aliases) {
|
||||||
if (!hasCommand()) {
|
if (!hasCommand()) {
|
||||||
setCommand(DefaultGroupCommand.getInstance());
|
setCommand(DefaultGroupCommand.getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
addNameAndAliases(name, aliases);
|
addNameAndAliases(name, aliases);
|
||||||
HelpCommand.registerAsChild(this);
|
HelpCommand.registerAsChild(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRoot() {
|
public boolean isRoot() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModifiableCommandAddress getParent() {
|
public ModifiableCommandAddress getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command getCommand() {
|
public Command getCommand() {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCommand(Command command) {
|
public void setCommand(Command command) {
|
||||||
if (hasUserDeclaredCommand()) {
|
if (hasUserDeclaredCommand()) {
|
||||||
throw new IllegalStateException("Command is already set at address \"" + getAddress() + "\"");
|
throw new IllegalStateException("Command is already set at address \"" + getAddress() + "\"");
|
||||||
}
|
}
|
||||||
this.command = command;
|
this.command = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getNames() {
|
public List<String> getNames() {
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addNameAndAliases(String name, String... aliases) {
|
public void addNameAndAliases(String name, String... aliases) {
|
||||||
names.add(name);
|
names.add(name);
|
||||||
names.addAll(Arrays.asList(aliases));
|
names.addAll(Arrays.asList(aliases));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMainKey() {
|
public String getMainKey() {
|
||||||
return namesModifiable.isEmpty() ? null : namesModifiable.get(0);
|
return namesModifiable.isEmpty() ? null : namesModifiable.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAddress() {
|
public String getAddress() {
|
||||||
ICommandAddress address = this;
|
ICommandAddress address = this;
|
||||||
int depth = getDepth();
|
int depth = getDepth();
|
||||||
String[] keys = new String[depth];
|
String[] keys = new String[depth];
|
||||||
for (int i = depth - 1; i >= 0; i--) {
|
for (int i = depth - 1; i >= 0; i--) {
|
||||||
keys[i] = address.getMainKey();
|
keys[i] = address.getMainKey();
|
||||||
address = address.getParent();
|
address = address.getParent();
|
||||||
}
|
}
|
||||||
return String.join(" ", keys);
|
return String.join(" ", keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finalizeNames() {
|
public void finalizeNames() {
|
||||||
if (names == namesModifiable) {
|
if (names == namesModifiable) {
|
||||||
names = Collections.unmodifiableList(namesModifiable);
|
names = Collections.unmodifiableList(namesModifiable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<String> modifiableNamesIterator() {
|
Iterator<String> modifiableNamesIterator() {
|
||||||
return namesModifiable.iterator();
|
return namesModifiable.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setParent(ModifiableCommandAddress parent) {
|
void setParent(ModifiableCommandAddress parent) {
|
||||||
finalizeNames();
|
finalizeNames();
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCommandTrailing() {
|
public boolean isCommandTrailing() {
|
||||||
return isCommandTrailing;
|
return isCommandTrailing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCommandTrailing(boolean trailing) {
|
public void setCommandTrailing(boolean trailing) {
|
||||||
if (hasChildren()) {
|
if (hasChildren()) {
|
||||||
throw new IllegalStateException("Address already has children, this property can't be modified");
|
throw new IllegalStateException("Address already has children, this property can't be modified");
|
||||||
}
|
}
|
||||||
isCommandTrailing = trailing;
|
isCommandTrailing = trailing;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,158 +1,158 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.IContextFilter.Priority;
|
import io.dico.dicore.command.IContextFilter.Priority;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.IArgumentPreProcessor;
|
import io.dico.dicore.command.parameter.IArgumentPreProcessor;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import io.dico.dicore.command.parameter.ParameterList;
|
import io.dico.dicore.command.parameter.ParameterList;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterType;
|
import io.dico.dicore.command.parameter.type.ParameterType;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class Command {
|
public abstract class Command {
|
||||||
private static final String[] EMPTY_DESCRIPTION = new String[0];
|
private static final String[] EMPTY_DESCRIPTION = new String[0];
|
||||||
private final ParameterList parameterList = new ParameterList();
|
private final ParameterList parameterList = new ParameterList();
|
||||||
private final List<IContextFilter> contextFilters = new ArrayList<>(3);
|
private final List<IContextFilter> contextFilters = new ArrayList<>(3);
|
||||||
private String[] description = EMPTY_DESCRIPTION;
|
private String[] description = EMPTY_DESCRIPTION;
|
||||||
private String shortDescription;
|
private String shortDescription;
|
||||||
|
|
||||||
public Command addParameter(Parameter<?, ?> parameter) {
|
public Command addParameter(Parameter<?, ?> parameter) {
|
||||||
parameterList.addParameter(parameter);
|
parameterList.addParameter(parameter);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <TType> Command addParameter(String name, String description, ParameterType<TType, Void> type) {
|
public <TType> Command addParameter(String name, String description, ParameterType<TType, Void> type) {
|
||||||
return addParameter(new Parameter<>(name, description, type, null, false, null));
|
return addParameter(new Parameter<>(name, description, type, null, false, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <TType, TParamInfo> Command addParameter(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
|
public <TType, TParamInfo> Command addParameter(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
|
||||||
return addParameter(new Parameter<>(name, description, type, paramInfo, false, null));
|
return addParameter(new Parameter<>(name, description, type, paramInfo, false, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <TType> Command addFlag(String name, String description, ParameterType<TType, Void> type) {
|
public <TType> Command addFlag(String name, String description, ParameterType<TType, Void> type) {
|
||||||
return addParameter(new Parameter<>('-' + name, description, type, null, true, null));
|
return addParameter(new Parameter<>('-' + name, description, type, null, true, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <TType, TParamInfo> Command addFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
|
public <TType, TParamInfo> Command addFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
|
||||||
return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, null));
|
return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <TType> Command addAuthorizedFlag(String name, String description, ParameterType<TType, Void> type, String permission) {
|
public <TType> Command addAuthorizedFlag(String name, String description, ParameterType<TType, Void> type, String permission) {
|
||||||
return addParameter(new Parameter<>('-' + name, description, type, null, true, permission));
|
return addParameter(new Parameter<>('-' + name, description, type, null, true, permission));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <TType, TParamInfo> Command addAuthorizedFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo, String permission) {
|
public <TType, TParamInfo> Command addAuthorizedFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo, String permission) {
|
||||||
return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, permission));
|
return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, permission));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command requiredParameters(int requiredParameters) {
|
public Command requiredParameters(int requiredParameters) {
|
||||||
parameterList.setRequiredCount(requiredParameters);
|
parameterList.setRequiredCount(requiredParameters);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command repeatFinalParameter() {
|
public Command repeatFinalParameter() {
|
||||||
parameterList.setRepeatFinalParameter(true);
|
parameterList.setRepeatFinalParameter(true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command setDescription(String... description) {
|
public Command setDescription(String... description) {
|
||||||
this.description = Objects.requireNonNull(description);
|
this.description = Objects.requireNonNull(description);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command setShortDescription(String shortDescription) {
|
public Command setShortDescription(String shortDescription) {
|
||||||
this.shortDescription = shortDescription;
|
this.shortDescription = shortDescription;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public Command preprocessArguments(IArgumentPreProcessor processor) {
|
public Command preprocessArguments(IArgumentPreProcessor processor) {
|
||||||
parameterList.setArgumentPreProcessor(processor);
|
parameterList.setArgumentPreProcessor(processor);
|
||||||
return this;
|
return this;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public final ParameterList getParameterList() {
|
public final ParameterList getParameterList() {
|
||||||
return parameterList;
|
return parameterList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String[] getDescription() {
|
public final String[] getDescription() {
|
||||||
return description.length == 0 ? description : description.clone();
|
return description.length == 0 ? description : description.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getShortDescription() {
|
public String getShortDescription() {
|
||||||
return shortDescription;
|
return shortDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ---- CONTEXT FILTERS ----
|
* ---- CONTEXT FILTERS ----
|
||||||
* Filter the contexts. For example, if the sender must be a player but it's the console,
|
* Filter the contexts. For example, if the sender must be a player but it's the console,
|
||||||
* throw a CommandException describing the problem.
|
* throw a CommandException describing the problem.
|
||||||
*/
|
*/
|
||||||
private transient int postParameterFilterCount = 0;
|
private transient int postParameterFilterCount = 0;
|
||||||
|
|
||||||
public Command addContextFilter(IContextFilter contextFilter) {
|
public Command addContextFilter(IContextFilter contextFilter) {
|
||||||
Objects.requireNonNull(contextFilter);
|
Objects.requireNonNull(contextFilter);
|
||||||
if (!contextFilters.contains(contextFilter)) {
|
if (!contextFilters.contains(contextFilter)) {
|
||||||
contextFilters.add(contextFilter);
|
contextFilters.add(contextFilter);
|
||||||
contextFilters.sort(null);
|
contextFilters.sort(null);
|
||||||
|
|
||||||
if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
|
if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
|
||||||
postParameterFilterCount++;
|
postParameterFilterCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IContextFilter> getContextFilters() {
|
public List<IContextFilter> getContextFilters() {
|
||||||
return Collections.unmodifiableList(contextFilters);
|
return Collections.unmodifiableList(contextFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command removeContextFilter(IContextFilter contextFilter) {
|
public Command removeContextFilter(IContextFilter contextFilter) {
|
||||||
boolean ret = contextFilters.remove(contextFilter);
|
boolean ret = contextFilters.remove(contextFilter);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
|
if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
|
||||||
postParameterFilterCount--;
|
postParameterFilterCount--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- CONTROL FLOW IN COMMAND TREES ----
|
// ---- CONTROL FLOW IN COMMAND TREES ----
|
||||||
|
|
||||||
public boolean isVisibleTo(CommandSender sender) {
|
public boolean isVisibleTo(CommandSender sender) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean takePrecedenceOverSubcommand(String subCommand, ArgumentBuffer buffer) {
|
public boolean takePrecedenceOverSubcommand(String subCommand, ArgumentBuffer buffer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- EXECUTION ----
|
// ---- EXECUTION ----
|
||||||
|
|
||||||
public void initializeAndFilterContext(ExecutionContext context) throws CommandException {
|
public void initializeAndFilterContext(ExecutionContext context) throws CommandException {
|
||||||
int i, n;
|
int i, n;
|
||||||
for (i = 0, n = contextFilters.size() - postParameterFilterCount; i < n; i++) {
|
for (i = 0, n = contextFilters.size() - postParameterFilterCount; i < n; i++) {
|
||||||
contextFilters.get(i).filterContext(context);
|
contextFilters.get(i).filterContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.parse(parameterList);
|
context.parse(parameterList);
|
||||||
|
|
||||||
if (!context.isTabComplete()) {
|
if (!context.isTabComplete()) {
|
||||||
for (n = contextFilters.size(); i < n; i++) {
|
for (n = contextFilters.size(); i < n; i++) {
|
||||||
contextFilters.get(i).filterContext(context);
|
contextFilters.get(i).filterContext(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String execute(CommandSender sender, ExecutionContext context) throws CommandException;
|
public abstract String execute(CommandSender sender, ExecutionContext context) throws CommandException;
|
||||||
|
|
||||||
public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
|
public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
|
||||||
return context.getSuggestedCompletions(location);
|
return context.getSuggestedCompletions(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,432 +1,432 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.chat.IChatHandler;
|
import io.dico.dicore.command.chat.IChatHandler;
|
||||||
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
||||||
import io.dico.dicore.command.parameter.type.MapBasedParameterTypeSelector;
|
import io.dico.dicore.command.parameter.type.MapBasedParameterTypeSelector;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterType;
|
import io.dico.dicore.command.parameter.type.ParameterType;
|
||||||
import io.dico.dicore.command.predef.HelpCommand;
|
import io.dico.dicore.command.predef.HelpCommand;
|
||||||
import io.dico.dicore.command.predef.PredefinedCommand;
|
import io.dico.dicore.command.predef.PredefinedCommand;
|
||||||
import io.dico.dicore.command.predef.SyntaxCommand;
|
import io.dico.dicore.command.predef.SyntaxCommand;
|
||||||
import io.dico.dicore.command.registration.reflect.ReflectiveRegistration;
|
import io.dico.dicore.command.registration.reflect.ReflectiveRegistration;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mimic of WorldEdit's CommandGraph
|
* Mimic of WorldEdit's CommandGraph
|
||||||
*/
|
*/
|
||||||
public final class CommandBuilder {
|
public final class CommandBuilder {
|
||||||
private final RootCommandAddress root;
|
private final RootCommandAddress root;
|
||||||
private ModifiableCommandAddress cur;
|
private ModifiableCommandAddress cur;
|
||||||
private IParameterTypeSelector selector;
|
private IParameterTypeSelector selector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a new CommandBuilder with a new command root system
|
* Instantiate a new CommandBuilder with a new command root system
|
||||||
* Commands registered to this command builder might interfere with
|
* Commands registered to this command builder might interfere with
|
||||||
* commands registered to other commands builders or by other plugins.
|
* commands registered to other commands builders or by other plugins.
|
||||||
*/
|
*/
|
||||||
public CommandBuilder() {
|
public CommandBuilder() {
|
||||||
this(new RootCommandAddress());
|
this(new RootCommandAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a new CommandBuilder with a specified root address.
|
* Instantiate a new CommandBuilder with a specified root address.
|
||||||
* If the root address is identical to that of another command builder,
|
* If the root address is identical to that of another command builder,
|
||||||
* they will modify the same tree.
|
* they will modify the same tree.
|
||||||
*
|
*
|
||||||
* @param root the root address
|
* @param root the root address
|
||||||
*/
|
*/
|
||||||
public CommandBuilder(RootCommandAddress root) {
|
public CommandBuilder(RootCommandAddress root) {
|
||||||
this.root = Objects.requireNonNull(root);
|
this.root = Objects.requireNonNull(root);
|
||||||
this.cur = root;
|
this.cur = root;
|
||||||
this.selector = new MapBasedParameterTypeSelector(true);
|
this.selector = new MapBasedParameterTypeSelector(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a sub command at the current address
|
* Add a sub command at the current address
|
||||||
* The current address can be inspected using {@link #getAddress()}
|
* The current address can be inspected using {@link #getAddress()}
|
||||||
*
|
*
|
||||||
* @param name the name of the command
|
* @param name the name of the command
|
||||||
* @param command the command executor
|
* @param command the command executor
|
||||||
* @param aliases any aliases
|
* @param aliases any aliases
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder addSubCommand(String name, Command command, String... aliases) {
|
public CommandBuilder addSubCommand(String name, Command command, String... aliases) {
|
||||||
ChildCommandAddress address = new ChildCommandAddress(command);
|
ChildCommandAddress address = new ChildCommandAddress(command);
|
||||||
address.addNameAndAliases(name, aliases);
|
address.addNameAndAliases(name, aliases);
|
||||||
return addSubCommand(address);
|
return addSubCommand(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a subcommand as an address at the current address
|
* Add a subcommand as an address at the current address
|
||||||
* The result of this call is the same as
|
* The result of this call is the same as
|
||||||
* {@code addSubCommand(address.getMainKey(), address.getCommand(), address.getNames().sublist(1).toArray(new String[0]))}
|
* {@code addSubCommand(address.getMainKey(), address.getCommand(), address.getNames().sublist(1).toArray(new String[0]))}
|
||||||
*
|
*
|
||||||
* @param address the address
|
* @param address the address
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalArgumentException if {@code address.isRoot()}
|
* @throws IllegalArgumentException if {@code address.isRoot()}
|
||||||
*/
|
*/
|
||||||
public CommandBuilder addSubCommand(ICommandAddress address) {
|
public CommandBuilder addSubCommand(ICommandAddress address) {
|
||||||
cur.addChild(address);
|
cur.addChild(address);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search the given class for any (static) methods using command annotations
|
* Search the given class for any (static) methods using command annotations
|
||||||
* The class gets a localized parameter type selector if it defines parameter types.
|
* The class gets a localized parameter type selector if it defines parameter types.
|
||||||
* Any commands found are registered as sub commands to the current address.
|
* Any commands found are registered as sub commands to the current address.
|
||||||
*
|
*
|
||||||
* @param clazz the clazz
|
* @param clazz the clazz
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
|
* @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
|
||||||
* @see #registerCommands(Class, Object)
|
* @see #registerCommands(Class, Object)
|
||||||
*/
|
*/
|
||||||
public CommandBuilder registerCommands(Class<?> clazz) {
|
public CommandBuilder registerCommands(Class<?> clazz) {
|
||||||
return registerCommands(clazz, null);
|
return registerCommands(clazz, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search the given object's class for methods using command annotations.
|
* Search the given object's class for methods using command annotations.
|
||||||
* If the object is null, only static methods are checked. Otherwise, instance methods are also checked.
|
* If the object is null, only static methods are checked. Otherwise, instance methods are also checked.
|
||||||
* The class gets a localized parameter type selector if it defines parameter types.
|
* The class gets a localized parameter type selector if it defines parameter types.
|
||||||
* Any commands found are registered as sub commands to the current address.
|
* Any commands found are registered as sub commands to the current address.
|
||||||
*
|
*
|
||||||
* @param object the object
|
* @param object the object
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
|
* @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
|
||||||
* @see #registerCommands(Class, Object)
|
* @see #registerCommands(Class, Object)
|
||||||
*/
|
*/
|
||||||
public CommandBuilder registerCommands(Object object) {
|
public CommandBuilder registerCommands(Object object) {
|
||||||
return registerCommands(object.getClass(), object);
|
return registerCommands(object.getClass(), object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search the given class for methods using command annotations.
|
* Search the given class for methods using command annotations.
|
||||||
* The class gets a localized parameter type selector if it defines parameter types.
|
* The class gets a localized parameter type selector if it defines parameter types.
|
||||||
* Any commands found are registered as sub commands to the current address.
|
* Any commands found are registered as sub commands to the current address.
|
||||||
* The instance is used to invoke non-static methods.
|
* The instance is used to invoke non-static methods.
|
||||||
*
|
*
|
||||||
* @param clazz the class
|
* @param clazz the class
|
||||||
* @param instance the instance, null if only static methods
|
* @param instance the instance, null if only static methods
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalArgumentException if instance is not null and it's not an instance of the class
|
* @throws IllegalArgumentException if instance is not null and it's not an instance of the class
|
||||||
* @throws IllegalArgumentException if another exception occurs while parsing the methods of this class
|
* @throws IllegalArgumentException if another exception occurs while parsing the methods of this class
|
||||||
*/
|
*/
|
||||||
public CommandBuilder registerCommands(Class<?> clazz, Object instance) {
|
public CommandBuilder registerCommands(Class<?> clazz, Object instance) {
|
||||||
try {
|
try {
|
||||||
ReflectiveRegistration.parseCommandGroup(cur, selector, clazz, instance);
|
ReflectiveRegistration.parseCommandGroup(cur, selector, clazz, instance);
|
||||||
return this;
|
return this;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new IllegalArgumentException(ex);
|
throw new IllegalArgumentException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* register the {@link HelpCommand} as a sub command at the current address
|
* register the {@link HelpCommand} as a sub command at the current address
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder registerHelpCommand() {
|
public CommandBuilder registerHelpCommand() {
|
||||||
HelpCommand.registerAsChild(cur);
|
HelpCommand.registerAsChild(cur);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* register the {@link SyntaxCommand} as a sub command a the current address
|
* register the {@link SyntaxCommand} as a sub command a the current address
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder registerSyntaxCommand() {
|
public CommandBuilder registerSyntaxCommand() {
|
||||||
SyntaxCommand.registerAsChild(cur);
|
SyntaxCommand.registerAsChild(cur);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the predefined commands.
|
* Generate the predefined commands.
|
||||||
* These are presets.
|
* These are presets.
|
||||||
* Examples include {@code help} and {@code syntax}.
|
* Examples include {@code help} and {@code syntax}.
|
||||||
* <p>
|
* <p>
|
||||||
* Predefined commands can be registered through {@link PredefinedCommand#registerPredefinedCommandGenerator(String, Consumer)}
|
* Predefined commands can be registered through {@link PredefinedCommand#registerPredefinedCommandGenerator(String, Consumer)}
|
||||||
*
|
*
|
||||||
* @param commands the commands
|
* @param commands the commands
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder generatePredefinedCommands(String... commands) {
|
public CommandBuilder generatePredefinedCommands(String... commands) {
|
||||||
ReflectiveRegistration.generateCommands(cur, commands);
|
ReflectiveRegistration.generateCommands(cur, commands);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister any childs present at the given keys.
|
* Unregister any childs present at the given keys.
|
||||||
* <p>
|
* <p>
|
||||||
* This method can be used to remove unwanted keys, that might have been added
|
* This method can be used to remove unwanted keys, that might have been added
|
||||||
* outside of your control. For example, because you didn't want all commands
|
* outside of your control. For example, because you didn't want all commands
|
||||||
* registered by {@link #registerCommands(Class, Object)}, or because you didn't
|
* registered by {@link #registerCommands(Class, Object)}, or because you didn't
|
||||||
* want the help command registered by {@link #group(String, String...)}
|
* want the help command registered by {@link #group(String, String...)}
|
||||||
*
|
*
|
||||||
* @param removeAliases true if any aliases of the children present at the keys should be removed
|
* @param removeAliases true if any aliases of the children present at the keys should be removed
|
||||||
* @param keys a varargs array containing the keys
|
* @param keys a varargs array containing the keys
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalArgumentException if keys array is empty
|
* @throws IllegalArgumentException if keys array is empty
|
||||||
*/
|
*/
|
||||||
public CommandBuilder unregisterCommands(boolean removeAliases, String... keys) {
|
public CommandBuilder unregisterCommands(boolean removeAliases, String... keys) {
|
||||||
cur.removeChildren(removeAliases, keys);
|
cur.removeChildren(removeAliases, keys);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jump to the sub-address with the given name as main key.
|
* Jump to the sub-address with the given name as main key.
|
||||||
* If an address with the exact name as main key exists,
|
* If an address with the exact name as main key exists,
|
||||||
* that address becomes the current address.
|
* that address becomes the current address.
|
||||||
* <p>
|
* <p>
|
||||||
* Otherwise, a new addresses is registered with the name and aliases.
|
* Otherwise, a new addresses is registered with the name and aliases.
|
||||||
* New addresses registered by this command have a HelpCommand added by default.
|
* New addresses registered by this command have a HelpCommand added by default.
|
||||||
* <p>
|
* <p>
|
||||||
* After this call, any registered commands are registered as a sub command
|
* After this call, any registered commands are registered as a sub command
|
||||||
* to the new address. To restore the previous state, a call to {@link #parent()}
|
* to the new address. To restore the previous state, a call to {@link #parent()}
|
||||||
* should be made.
|
* should be made.
|
||||||
* <p>
|
* <p>
|
||||||
* If the address is the target of a command, it will provide information about its sub commands
|
* If the address is the target of a command, it will provide information about its sub commands
|
||||||
* using the HelpCommand.
|
* using the HelpCommand.
|
||||||
*
|
*
|
||||||
* @param name the main key
|
* @param name the main key
|
||||||
* @param aliases the aliases
|
* @param aliases the aliases
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder group(String name, String... aliases) {
|
public CommandBuilder group(String name, String... aliases) {
|
||||||
ChildCommandAddress address = cur.getChild(name);
|
ChildCommandAddress address = cur.getChild(name);
|
||||||
if (address == null || !name.equals(address.getMainKey())) {
|
if (address == null || !name.equals(address.getMainKey())) {
|
||||||
address = new ChildCommandAddress();
|
address = new ChildCommandAddress();
|
||||||
address.setupAsPlaceholder(name, aliases);
|
address.setupAsPlaceholder(name, aliases);
|
||||||
cur.addChild(address);
|
cur.addChild(address);
|
||||||
}
|
}
|
||||||
cur = address;
|
cur = address;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link #group(String, String[])} but this will force overwrite any present group,
|
* Similar to {@link #group(String, String[])} but this will force overwrite any present group,
|
||||||
* using the address passed. The address MUST be an instance of {@link ChildCommandAddress}.
|
* using the address passed. The address MUST be an instance of {@link ChildCommandAddress}.
|
||||||
*
|
*
|
||||||
* <p>The address must not have a parent or any keys</p>
|
* <p>The address must not have a parent or any keys</p>
|
||||||
*
|
*
|
||||||
* @param address the address object to use
|
* @param address the address object to use
|
||||||
* @param name the main key
|
* @param name the main key
|
||||||
* @param aliases any aliases
|
* @param aliases any aliases
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalArgumentException if any of the requirements set out above aren't met
|
* @throws IllegalArgumentException if any of the requirements set out above aren't met
|
||||||
*/
|
*/
|
||||||
public CommandBuilder group(ICommandAddress address, String name, String... aliases) {
|
public CommandBuilder group(ICommandAddress address, String name, String... aliases) {
|
||||||
if (address.hasParent() || address.getMainKey() != null || !(address instanceof ChildCommandAddress)) {
|
if (address.hasParent() || address.getMainKey() != null || !(address instanceof ChildCommandAddress)) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
ChildCommandAddress asChild = (ChildCommandAddress) address;
|
ChildCommandAddress asChild = (ChildCommandAddress) address;
|
||||||
asChild.setupAsPlaceholder(name, aliases);
|
asChild.setupAsPlaceholder(name, aliases);
|
||||||
cur.addChild(address);
|
cur.addChild(address);
|
||||||
cur = asChild;
|
cur = asChild;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the description of a group created by {@link #group(String, String...)}
|
* Sets the description of a group created by {@link #group(String, String...)}
|
||||||
* Can be called subsequently to making a call to {@link #group(String, String...)}
|
* Can be called subsequently to making a call to {@link #group(String, String...)}
|
||||||
*
|
*
|
||||||
* @param shortDescription a short description
|
* @param shortDescription a short description
|
||||||
* @param description the lines of a full description.
|
* @param description the lines of a full description.
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalStateException if the current group has no command
|
* @throws IllegalStateException if the current group has no command
|
||||||
*/
|
*/
|
||||||
public CommandBuilder setGroupDescription(String shortDescription, String... description) {
|
public CommandBuilder setGroupDescription(String shortDescription, String... description) {
|
||||||
Command command = cur.getCommand();
|
Command command = cur.getCommand();
|
||||||
if (command == null) throw new IllegalStateException();
|
if (command == null) throw new IllegalStateException();
|
||||||
cur.setCommand(command
|
cur.setCommand(command
|
||||||
.setShortDescription(shortDescription)
|
.setShortDescription(shortDescription)
|
||||||
.setDescription(description));
|
.setDescription(description));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a context filter to the command of the current group
|
* Add a context filter to the command of the current group
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalStateException if the current group has no command
|
* @throws IllegalStateException if the current group has no command
|
||||||
*/
|
*/
|
||||||
public CommandBuilder addContextFilter(IContextFilter contextFilter) {
|
public CommandBuilder addContextFilter(IContextFilter contextFilter) {
|
||||||
Command command = cur.getCommand();
|
Command command = cur.getCommand();
|
||||||
if (command == null) throw new IllegalStateException();
|
if (command == null) throw new IllegalStateException();
|
||||||
cur.setCommand(command
|
cur.setCommand(command
|
||||||
.addContextFilter(contextFilter));
|
.addContextFilter(contextFilter));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a required permission to the command of the current group
|
* Add a required permission to the command of the current group
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalStateException if the current group has no command
|
* @throws IllegalStateException if the current group has no command
|
||||||
*/
|
*/
|
||||||
public CommandBuilder addPermission(String permission) {
|
public CommandBuilder addPermission(String permission) {
|
||||||
return addContextFilter(IContextFilter.permission(permission));
|
return addContextFilter(IContextFilter.permission(permission));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a required permission to the command of the current group, which can be inherited
|
* Add a required permission to the command of the current group, which can be inherited
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalStateException if the current group has no command
|
* @throws IllegalStateException if the current group has no command
|
||||||
*/
|
*/
|
||||||
public CommandBuilder addInheritablePermission(String permission) {
|
public CommandBuilder addInheritablePermission(String permission) {
|
||||||
return addContextFilter(IContextFilter.inheritablePermission(permission));
|
return addContextFilter(IContextFilter.inheritablePermission(permission));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jump up a level in the address
|
* Jump up a level in the address
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalStateException if the address is empty
|
* @throws IllegalStateException if the address is empty
|
||||||
* // has a depth of 0 // is at level 0
|
* // has a depth of 0 // is at level 0
|
||||||
*/
|
*/
|
||||||
public CommandBuilder parent() {
|
public CommandBuilder parent() {
|
||||||
if (cur.hasParent()) {
|
if (cur.hasParent()) {
|
||||||
cur = cur.getParent();
|
cur = cur.getParent();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("No parent exists at this address");
|
throw new IllegalStateException("No parent exists at this address");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jump to the root (empty) address,
|
* Jump to the root (empty) address,
|
||||||
* such that a subsequent call to {@link #parent()}
|
* such that a subsequent call to {@link #parent()}
|
||||||
* will throw a {@link IllegalStateException}
|
* will throw a {@link IllegalStateException}
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder root() {
|
public CommandBuilder root() {
|
||||||
cur = root;
|
cur = root;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current address, as a space-separated string
|
* Get the current address, as a space-separated string
|
||||||
*
|
*
|
||||||
* @return the current address
|
* @return the current address
|
||||||
*/
|
*/
|
||||||
public String getAddress() {
|
public String getAddress() {
|
||||||
return cur.getAddress();
|
return cur.getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the depth of the current address.
|
* Get the depth of the current address.
|
||||||
* This is equivalent to {@code getAddress().split(" ").length}.
|
* This is equivalent to {@code getAddress().split(" ").length}.
|
||||||
* If the address is empty, the depth is 0.
|
* If the address is empty, the depth is 0.
|
||||||
*
|
*
|
||||||
* @return the depth
|
* @return the depth
|
||||||
*/
|
*/
|
||||||
public int getDepth() {
|
public int getDepth() {
|
||||||
return cur.getDepth();
|
return cur.getDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the command at the current group. The command is set
|
* Set the command at the current group. The command is set
|
||||||
* a level higher than it would be if this were a call to {@link #addSubCommand(String, Command, String...)}
|
* a level higher than it would be if this were a call to {@link #addSubCommand(String, Command, String...)}
|
||||||
* <p>
|
* <p>
|
||||||
* If a call to {@link #setGroupDescription(String, String...)} was made at the same address before,
|
* If a call to {@link #setGroupDescription(String, String...)} was made at the same address before,
|
||||||
* the description is copied to the given executor.
|
* the description is copied to the given executor.
|
||||||
*
|
*
|
||||||
* @param command the executor
|
* @param command the executor
|
||||||
* @return this
|
* @return this
|
||||||
* @throws IllegalArgumentException if the command at the address is present and declared by the user,
|
* @throws IllegalArgumentException if the command at the address is present and declared by the user,
|
||||||
* in other words, it's not a {@link PredefinedCommand}
|
* in other words, it's not a {@link PredefinedCommand}
|
||||||
*/
|
*/
|
||||||
public CommandBuilder setCommand(Command command) {
|
public CommandBuilder setCommand(Command command) {
|
||||||
Command current = cur.getCommand();
|
Command current = cur.getCommand();
|
||||||
if (current instanceof HelpCommand && current != HelpCommand.INSTANCE) {
|
if (current instanceof HelpCommand && current != HelpCommand.INSTANCE) {
|
||||||
command.setShortDescription(current.getShortDescription());
|
command.setShortDescription(current.getShortDescription());
|
||||||
command.setDescription(current.getDescription());
|
command.setDescription(current.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
cur.setCommand(command);
|
cur.setCommand(command);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the chat handler at this address. The chat handler
|
* Configure the chat handler at this address. The chat handler
|
||||||
* is used for all children down the tree if they don't explicitly have
|
* is used for all children down the tree if they don't explicitly have
|
||||||
* their own chat handler configured. If this isn't configured,
|
* their own chat handler configured. If this isn't configured,
|
||||||
* {@code ChatHandlers.defaultChat()} is used.
|
* {@code ChatHandlers.defaultChat()} is used.
|
||||||
*
|
*
|
||||||
* @param chatHandler the chat handler
|
* @param chatHandler the chat handler
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder setChatHandler(IChatHandler chatHandler) {
|
public CommandBuilder setChatHandler(IChatHandler chatHandler) {
|
||||||
cur.setChatHandler(chatHandler);
|
cur.setChatHandler(chatHandler);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the parameter type to this builder's selector.
|
* Add the parameter type to this builder's selector.
|
||||||
*
|
*
|
||||||
* @param type the type
|
* @param type the type
|
||||||
* @param <T> the return type of the parameter type
|
* @param <T> the return type of the parameter type
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public <T> CommandBuilder addParameterType(ParameterType<T, Void> type) {
|
public <T> CommandBuilder addParameterType(ParameterType<T, Void> type) {
|
||||||
selector.addType(false, type);
|
selector.addType(false, type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the parameter type to this builder's selector.
|
* Add the parameter type to this builder's selector.
|
||||||
*
|
*
|
||||||
* @param infolessAlias whether to also register the type with an infoless alias.
|
* @param infolessAlias whether to also register the type with an infoless alias.
|
||||||
* this increases the priority assigned to the type if no info object is present.
|
* this increases the priority assigned to the type if no info object is present.
|
||||||
* @param type the type
|
* @param type the type
|
||||||
* @param <T> the return type of the parameter type
|
* @param <T> the return type of the parameter type
|
||||||
* @param <C> the parameter config type (info object)
|
* @param <C> the parameter config type (info object)
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public <T, C> CommandBuilder addParameterType(boolean infolessAlias, ParameterType<T, C> type) {
|
public <T, C> CommandBuilder addParameterType(boolean infolessAlias, ParameterType<T, C> type) {
|
||||||
selector.addType(infolessAlias, type);
|
selector.addType(infolessAlias, type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the dispatcher for the root address.
|
* Get the dispatcher for the root address.
|
||||||
* The dispatcher should be used to finally register all commands,
|
* The dispatcher should be used to finally register all commands,
|
||||||
* after they are all declared.
|
* after they are all declared.
|
||||||
*
|
*
|
||||||
* @return the dispatcher
|
* @return the dispatcher
|
||||||
*/
|
*/
|
||||||
public ICommandDispatcher getDispatcher() {
|
public ICommandDispatcher getDispatcher() {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print debugging information about the current addresses and commands in this builder
|
* Print debugging information about the current addresses and commands in this builder
|
||||||
* A StackTraceElement indicating where this was called from is also included
|
* A StackTraceElement indicating where this was called from is also included
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public CommandBuilder printDebugInformation() {
|
public CommandBuilder printDebugInformation() {
|
||||||
String address = cur == root ? "<root>" : cur.getAddress();
|
String address = cur == root ? "<root>" : cur.getAddress();
|
||||||
StackTraceElement caller = getCallsite();
|
StackTraceElement caller = getCallsite();
|
||||||
|
|
||||||
StringBuilder message = new StringBuilder("### CommandBuilder dump ###");
|
StringBuilder message = new StringBuilder("### CommandBuilder dump ###");
|
||||||
message.append("\nCalled from ").append(caller);
|
message.append("\nCalled from ").append(caller);
|
||||||
message.append("\nPosition: ").append(address);
|
message.append("\nPosition: ").append(address);
|
||||||
cur.appendDebugInformation(message, "", new HashSet<>());
|
cur.appendDebugInformation(message, "", new HashSet<>());
|
||||||
|
|
||||||
System.out.println(message);
|
System.out.println(message);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StackTraceElement getCallsite() {
|
private static StackTraceElement getCallsite() {
|
||||||
// [0] Thread.currentThread()
|
// [0] Thread.currentThread()
|
||||||
// [1] CommandBuilder.getCallsite()
|
// [1] CommandBuilder.getCallsite()
|
||||||
// [2] Calling method
|
// [2] Calling method
|
||||||
// [3] Method calling the calling method
|
// [3] Method calling the calling method
|
||||||
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||||
return trace.length > 3 ? trace[3] : null;
|
return trace.length > 3 ? trace[3] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
public class CommandException extends Exception {
|
public class CommandException extends Exception {
|
||||||
|
|
||||||
public CommandException() {
|
public CommandException() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandException(String message) {
|
public CommandException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandException(String message, Throwable cause) {
|
public CommandException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandException(Throwable cause) {
|
public CommandException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CommandException missingArgument(String parameterName) {
|
public static CommandException missingArgument(String parameterName) {
|
||||||
return new CommandException("Missing argument for " + parameterName);
|
return new CommandException("Missing argument for " + parameterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CommandException invalidArgument(String parameterName, String syntaxHelp) {
|
public static CommandException invalidArgument(String parameterName, String syntaxHelp) {
|
||||||
return new CommandException("Invalid input for " + parameterName + ", should be " + syntaxHelp);
|
return new CommandException("Invalid input for " + parameterName + ", should be " + syntaxHelp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
public enum EMessageType {
|
public enum EMessageType {
|
||||||
GOOD_NEWS,
|
GOOD_NEWS,
|
||||||
BAD_NEWS,
|
BAD_NEWS,
|
||||||
NEUTRAL,
|
NEUTRAL,
|
||||||
INFORMATIVE,
|
INFORMATIVE,
|
||||||
WARNING,
|
WARNING,
|
||||||
INSTRUCTION,
|
INSTRUCTION,
|
||||||
EXCEPTION,
|
EXCEPTION,
|
||||||
RESULT,
|
RESULT,
|
||||||
CUSTOM,
|
CUSTOM,
|
||||||
|
|
||||||
DESCRIPTION,
|
DESCRIPTION,
|
||||||
SYNTAX,
|
SYNTAX,
|
||||||
HIGHLIGHT,
|
HIGHLIGHT,
|
||||||
SUBCOMMAND,
|
SUBCOMMAND,
|
||||||
NUMBER,
|
NUMBER,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override policies for registering to the command map
|
* Override policies for registering to the command map
|
||||||
*/
|
*/
|
||||||
public enum EOverridePolicy {
|
public enum EOverridePolicy {
|
||||||
OVERRIDE_ALL,
|
OVERRIDE_ALL,
|
||||||
MAIN_KEY_ONLY,
|
MAIN_KEY_ONLY,
|
||||||
MAIN_AND_FALLBACK,
|
MAIN_AND_FALLBACK,
|
||||||
FALLBACK_ONLY,
|
FALLBACK_ONLY,
|
||||||
OVERRIDE_NONE
|
OVERRIDE_NONE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,385 +1,385 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.Formatting;
|
import io.dico.dicore.Formatting;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.ContextParser;
|
import io.dico.dicore.command.parameter.ContextParser;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import io.dico.dicore.command.parameter.ParameterList;
|
import io.dico.dicore.command.parameter.ParameterList;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The context of execution.
|
* The context of execution.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is responsible for the control flow of parameter parsing, as well as caching and providing the parsed parameter values.
|
* This class is responsible for the control flow of parameter parsing, as well as caching and providing the parsed parameter values.
|
||||||
* It is also responsible for keeping track of the parameter to complete in the case of a tab completion.
|
* It is also responsible for keeping track of the parameter to complete in the case of a tab completion.
|
||||||
*/
|
*/
|
||||||
public class ExecutionContext {
|
public class ExecutionContext {
|
||||||
// Sender of the command
|
// Sender of the command
|
||||||
private final CommandSender sender;
|
private final CommandSender sender;
|
||||||
// Address while parsing parameters with ContextParser
|
// Address while parsing parameters with ContextParser
|
||||||
private ICommandAddress address;
|
private ICommandAddress address;
|
||||||
// Command to execute
|
// Command to execute
|
||||||
private Command command;
|
private Command command;
|
||||||
// if this flag is set, this execution is only for completion purposes.
|
// if this flag is set, this execution is only for completion purposes.
|
||||||
private boolean tabComplete;
|
private boolean tabComplete;
|
||||||
|
|
||||||
private final ArgumentBuffer buffer;
|
private final ArgumentBuffer buffer;
|
||||||
// private ArgumentBuffer processedBuffer;
|
// private ArgumentBuffer processedBuffer;
|
||||||
|
|
||||||
// caches the buffer's cursor before parsing. This is needed to provide the original input of the player.
|
// caches the buffer's cursor before parsing. This is needed to provide the original input of the player.
|
||||||
private int cursorStart;
|
private int cursorStart;
|
||||||
|
|
||||||
// when the context starts parsing parameters, this flag is set, and any subsequent calls to #parseParameters() throw an IllegalStateException.
|
// when the context starts parsing parameters, this flag is set, and any subsequent calls to #parseParameters() throw an IllegalStateException.
|
||||||
//private boolean attemptedToParse;
|
//private boolean attemptedToParse;
|
||||||
|
|
||||||
|
|
||||||
// The parsed parameter values, mapped by parameter name.
|
// The parsed parameter values, mapped by parameter name.
|
||||||
// This also includes default values. All parameters from the parameter list are present if parsing was successful.
|
// This also includes default values. All parameters from the parameter list are present if parsing was successful.
|
||||||
private Map<String, Object> parameterValueMap = new HashMap<>();
|
private Map<String, Object> parameterValueMap = new HashMap<>();
|
||||||
// this set contains the names of the parameters that were present in the command, and not given a default value.
|
// this set contains the names of the parameters that were present in the command, and not given a default value.
|
||||||
private Set<String> parsedParameters = new HashSet<>();
|
private Set<String> parsedParameters = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
// these fields store information required to provide completions.
|
// these fields store information required to provide completions.
|
||||||
// the parameter to complete is the parameter that threw an exception when it was parsing.
|
// the parameter to complete is the parameter that threw an exception when it was parsing.
|
||||||
// the exception's message was discarded because it is a completion.
|
// the exception's message was discarded because it is a completion.
|
||||||
private Parameter<?, ?> parameterToComplete;
|
private Parameter<?, ?> parameterToComplete;
|
||||||
// this is the cursor that the ArgumentBuffer is reset to when suggested completions are requested.
|
// this is the cursor that the ArgumentBuffer is reset to when suggested completions are requested.
|
||||||
private int parameterToCompleteCursor = -1;
|
private int parameterToCompleteCursor = -1;
|
||||||
|
|
||||||
// if this flag is set, any messages sent through the sendMessage methods are discarded.
|
// if this flag is set, any messages sent through the sendMessage methods are discarded.
|
||||||
private boolean muted;
|
private boolean muted;
|
||||||
|
|
||||||
public ExecutionContext(CommandSender sender, ArgumentBuffer buffer, boolean tabComplete) {
|
public ExecutionContext(CommandSender sender, ArgumentBuffer buffer, boolean tabComplete) {
|
||||||
this.sender = Objects.requireNonNull(sender);
|
this.sender = Objects.requireNonNull(sender);
|
||||||
this.buffer = Objects.requireNonNull(buffer);
|
this.buffer = Objects.requireNonNull(buffer);
|
||||||
this.muted = tabComplete;
|
this.muted = tabComplete;
|
||||||
this.tabComplete = tabComplete;
|
this.tabComplete = tabComplete;
|
||||||
|
|
||||||
// If its tab completing, keep the empty element that might be at the end of the buffer
|
// If its tab completing, keep the empty element that might be at the end of the buffer
|
||||||
// due to a space at the end of the command.
|
// due to a space at the end of the command.
|
||||||
// This allows the parser to correctly identify the parameter to be completed in this case.
|
// This allows the parser to correctly identify the parameter to be completed in this case.
|
||||||
if (!tabComplete) {
|
if (!tabComplete) {
|
||||||
buffer.dropTrailingEmptyElements();
|
buffer.dropTrailingEmptyElements();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an execution context that is ready to parse the parameter values.
|
* Construct an execution context that is ready to parse the parameter values.
|
||||||
*
|
*
|
||||||
* @param sender the sender
|
* @param sender the sender
|
||||||
* @param address the address
|
* @param address the address
|
||||||
* @param command the command
|
* @param command the command
|
||||||
* @param buffer the arguments
|
* @param buffer the arguments
|
||||||
* @param tabComplete true if this execution is a tab-completion
|
* @param tabComplete true if this execution is a tab-completion
|
||||||
*/
|
*/
|
||||||
public ExecutionContext(CommandSender sender, ICommandAddress address, Command command, ArgumentBuffer buffer, boolean tabComplete) {
|
public ExecutionContext(CommandSender sender, ICommandAddress address, Command command, ArgumentBuffer buffer, boolean tabComplete) {
|
||||||
this(sender, buffer, tabComplete);
|
this(sender, buffer, tabComplete);
|
||||||
setAddress(address);
|
setAddress(address);
|
||||||
setCommand(command);
|
setCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sender of the command
|
* Sender of the command
|
||||||
*
|
*
|
||||||
* @return the sender of the command
|
* @return the sender of the command
|
||||||
*/
|
*/
|
||||||
public CommandSender getSender() {
|
public CommandSender getSender() {
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the buffer of arguments
|
* @return the buffer of arguments
|
||||||
*/
|
*/
|
||||||
public ArgumentBuffer getBuffer() {
|
public ArgumentBuffer getBuffer() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command's address
|
* Command's address
|
||||||
*
|
*
|
||||||
* @return the command's address
|
* @return the command's address
|
||||||
*/
|
*/
|
||||||
public ICommandAddress getAddress() {
|
public ICommandAddress getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the address
|
* Set the address
|
||||||
*
|
*
|
||||||
* @param address the new address
|
* @param address the new address
|
||||||
*/
|
*/
|
||||||
public void setAddress(ICommandAddress address) {
|
public void setAddress(ICommandAddress address) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command
|
* The command
|
||||||
*
|
*
|
||||||
* @return the command
|
* @return the command
|
||||||
*/
|
*/
|
||||||
public Command getCommand() {
|
public Command getCommand() {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the command
|
* Set the command
|
||||||
*
|
*
|
||||||
* @param command the new command
|
* @param command the new command
|
||||||
*/
|
*/
|
||||||
public void setCommand(Command command) {
|
public void setCommand(Command command) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this context is for a tab completion.
|
* @return true if this context is for a tab completion.
|
||||||
*/
|
*/
|
||||||
public boolean isTabComplete() {
|
public boolean isTabComplete() {
|
||||||
return tabComplete;
|
return tabComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this context is muted.
|
* @return true if this context is muted.
|
||||||
*/
|
*/
|
||||||
public boolean isMuted() {
|
public boolean isMuted() {
|
||||||
return muted;
|
return muted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse parameters from the given parameter list,
|
* Parse parameters from the given parameter list,
|
||||||
* adding their values to the cache of this context.
|
* adding their values to the cache of this context.
|
||||||
*
|
*
|
||||||
* @param parameterList the parameterList
|
* @param parameterList the parameterList
|
||||||
* @throws CommandException if the arguments are not valid
|
* @throws CommandException if the arguments are not valid
|
||||||
*/
|
*/
|
||||||
public void parse(ParameterList parameterList) throws CommandException {
|
public void parse(ParameterList parameterList) throws CommandException {
|
||||||
cursorStart = buffer.getCursor();
|
cursorStart = buffer.getCursor();
|
||||||
|
|
||||||
ContextParser parser = new ContextParser(this, parameterList, parameterValueMap, parsedParameters);
|
ContextParser parser = new ContextParser(this, parameterList, parameterValueMap, parsedParameters);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
parser.parse();
|
parser.parse();
|
||||||
} finally {
|
} finally {
|
||||||
if (tabComplete) {
|
if (tabComplete) {
|
||||||
parameterToComplete = parser.getCompletionTarget();
|
parameterToComplete = parser.getCompletionTarget();
|
||||||
parameterToCompleteCursor = parser.getCompletionCursor();
|
parameterToCompleteCursor = parser.getCompletionCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command's parameter definition.
|
* The command's parameter definition.
|
||||||
*
|
*
|
||||||
* @return the parameter list
|
* @return the parameter list
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ParameterList getParameterList() {
|
public ParameterList getParameterList() {
|
||||||
return null;//command.getParameterList();
|
return null;//command.getParameterList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the buffer as it was before preprocessing the arguments.
|
* Get the buffer as it was before preprocessing the arguments.
|
||||||
*
|
*
|
||||||
* @return the original buffer
|
* @return the original buffer
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ArgumentBuffer getOriginalBuffer() {
|
public ArgumentBuffer getOriginalBuffer() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The arguments
|
* The arguments
|
||||||
*
|
*
|
||||||
* @return the argument buffer
|
* @return the argument buffer
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ArgumentBuffer getProcessedBuffer() {
|
public ArgumentBuffer getProcessedBuffer() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cursor start, in other words, the buffer's cursor before parameters were parsed.
|
* The cursor start, in other words, the buffer's cursor before parameters were parsed.
|
||||||
*
|
*
|
||||||
* @return the cursor start
|
* @return the cursor start
|
||||||
*/
|
*/
|
||||||
public int getCursorStart() {
|
public int getCursorStart() {
|
||||||
return cursorStart;
|
return cursorStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The original arguments.
|
* The original arguments.
|
||||||
*
|
*
|
||||||
* @return original arguments.
|
* @return original arguments.
|
||||||
*/
|
*/
|
||||||
public String[] getOriginal() {
|
public String[] getOriginal() {
|
||||||
return buffer.getArrayFromIndex(cursorStart);
|
return buffer.getArrayFromIndex(cursorStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path used to access this address.
|
* The path used to access this address.
|
||||||
*
|
*
|
||||||
* @return the path used to access this address.
|
* @return the path used to access this address.
|
||||||
*/
|
*/
|
||||||
public String[] getRoute() {
|
public String[] getRoute() {
|
||||||
return Arrays.copyOf(buffer.toArray(), address.getDepth());
|
return Arrays.copyOf(buffer.toArray(), address.getDepth());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Formatting getFormat(EMessageType type) {
|
public Formatting getFormat(EMessageType type) {
|
||||||
return address.getChatHandler().getChatFormatForType(type);
|
return address.getChatHandler().getChatFormatForType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The full command as cached by the buffer. Might be incomplete depending on how it was dispatched.
|
* The full command as cached by the buffer. Might be incomplete depending on how it was dispatched.
|
||||||
*
|
*
|
||||||
* @return the full command
|
* @return the full command
|
||||||
*/
|
*/
|
||||||
public String getRawInput() {
|
public String getRawInput() {
|
||||||
return buffer.getRawInput();
|
return buffer.getRawInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of the parameter with the given name
|
* Get the value of the parameter with the given name
|
||||||
*
|
*
|
||||||
* @param name the parameter's name
|
* @param name the parameter's name
|
||||||
* @param <T> expected type
|
* @param <T> expected type
|
||||||
* @return the parsed value or the default value
|
* @return the parsed value or the default value
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T get(String name) {
|
public <T> T get(String name) {
|
||||||
if (!parameterValueMap.containsKey(name)) {
|
if (!parameterValueMap.containsKey(name)) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return (T) parameterValueMap.get(name);
|
return (T) parameterValueMap.get(name);
|
||||||
} catch (ClassCastException ex) {
|
} catch (ClassCastException ex) {
|
||||||
throw new IllegalArgumentException("Invalid type parameter requested for parameter " + name, ex);
|
throw new IllegalArgumentException("Invalid type parameter requested for parameter " + name, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of the flag with the given name
|
* Get the value of the flag with the given name
|
||||||
*
|
*
|
||||||
* @param flag the flag's name, without preceding "-"
|
* @param flag the flag's name, without preceding "-"
|
||||||
* @param <T> expected type
|
* @param <T> expected type
|
||||||
* @return the parsed value or the default value
|
* @return the parsed value or the default value
|
||||||
*/
|
*/
|
||||||
public <T> T getFlag(String flag) {
|
public <T> T getFlag(String flag) {
|
||||||
return get("-" + flag);
|
return get("-" + flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public <T> T get(int index) {
|
public <T> T get(int index) {
|
||||||
return null;//get(getParameterList().getIndexedParameterName(index));
|
return null;//get(getParameterList().getIndexedParameterName(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the parameter by the name was provided in the command's arguments.
|
* Checks if the parameter by the name was provided in the command's arguments.
|
||||||
*
|
*
|
||||||
* @param name the parameter name
|
* @param name the parameter name
|
||||||
* @return true if it was provided
|
* @return true if it was provided
|
||||||
*/
|
*/
|
||||||
public boolean isProvided(String name) {
|
public boolean isProvided(String name) {
|
||||||
return parsedParameters.contains(name);
|
return parsedParameters.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the parameter by the index was provided in the command's arguments.
|
* Checks if the parameter by the index was provided in the command's arguments.
|
||||||
*
|
*
|
||||||
* @param index the parameter index
|
* @param index the parameter index
|
||||||
* @return true if it was provided
|
* @return true if it was provided
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isProvided(int index) {
|
public boolean isProvided(int index) {
|
||||||
return false;//isProvided(getParameterList().getIndexedParameterName(index));
|
return false;//isProvided(getParameterList().getIndexedParameterName(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parameter to complete.
|
* The parameter to complete.
|
||||||
* This parameter is requested suggestions
|
* This parameter is requested suggestions
|
||||||
*
|
*
|
||||||
* @return the parameter to complete.
|
* @return the parameter to complete.
|
||||||
*/
|
*/
|
||||||
public Parameter<?, ?> getParameterToComplete() {
|
public Parameter<?, ?> getParameterToComplete() {
|
||||||
return parameterToComplete;
|
return parameterToComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get suggested completions.
|
* Get suggested completions.
|
||||||
*
|
*
|
||||||
* @param location The location as passed to {link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}, or null if requested in another way.
|
* @param location The location as passed to {link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}, or null if requested in another way.
|
||||||
* @return completions.
|
* @return completions.
|
||||||
*/
|
*/
|
||||||
public List<String> getSuggestedCompletions(Location location) {
|
public List<String> getSuggestedCompletions(Location location) {
|
||||||
if (parameterToComplete != null) {
|
if (parameterToComplete != null) {
|
||||||
return parameterToComplete.complete(this, location, buffer.getUnaffectingCopy().setCursor(parameterToCompleteCursor));
|
return parameterToComplete.complete(this, location, buffer.getUnaffectingCopy().setCursor(parameterToCompleteCursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
for (String name : parameterValueMap.keySet()) {
|
for (String name : parameterValueMap.keySet()) {
|
||||||
if (name.startsWith("-") && !parsedParameters.contains(name)) {
|
if (name.startsWith("-") && !parsedParameters.contains(name)) {
|
||||||
result.add(name);
|
result.add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Chat handling
|
Chat handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public void sendMessage(String message) {
|
public void sendMessage(String message) {
|
||||||
sendMessage(true, message);
|
sendMessage(true, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(EMessageType messageType, String message) {
|
public void sendMessage(EMessageType messageType, String message) {
|
||||||
sendMessage(messageType, true, message);
|
sendMessage(messageType, true, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(boolean translateColours, String message) {
|
public void sendMessage(boolean translateColours, String message) {
|
||||||
sendMessage(EMessageType.NEUTRAL, translateColours, message);
|
sendMessage(EMessageType.NEUTRAL, translateColours, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(EMessageType messageType, boolean translateColours, String message) {
|
public void sendMessage(EMessageType messageType, boolean translateColours, String message) {
|
||||||
if (!muted) {
|
if (!muted) {
|
||||||
if (translateColours) {
|
if (translateColours) {
|
||||||
message = Formatting.translateChars('&', message);
|
message = Formatting.translateChars('&', message);
|
||||||
}
|
}
|
||||||
address.getChatHandler().sendMessage(this, messageType, message);
|
address.getChatHandler().sendMessage(this, messageType, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(String messageFormat, Object... args) {
|
public void sendMessage(String messageFormat, Object... args) {
|
||||||
sendMessage(true, messageFormat, args);
|
sendMessage(true, messageFormat, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(EMessageType messageType, String messageFormat, Object... args) {
|
public void sendMessage(EMessageType messageType, String messageFormat, Object... args) {
|
||||||
sendMessage(messageType, true, messageFormat, args);
|
sendMessage(messageType, true, messageFormat, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(boolean translateColours, String messageFormat, Object... args) {
|
public void sendMessage(boolean translateColours, String messageFormat, Object... args) {
|
||||||
sendMessage(EMessageType.NEUTRAL, translateColours, messageFormat, args);
|
sendMessage(EMessageType.NEUTRAL, translateColours, messageFormat, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(EMessageType messageType, boolean translateColours, String messageFormat, Object... args) {
|
public void sendMessage(EMessageType messageType, boolean translateColours, String messageFormat, Object... args) {
|
||||||
sendMessage(messageType, translateColours, String.format(messageFormat, args));
|
sendMessage(messageType, translateColours, String.format(messageFormat, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendHelpMessage(int page) {
|
public void sendHelpMessage(int page) {
|
||||||
if (!muted) {
|
if (!muted) {
|
||||||
address.getChatHandler().sendHelpMessage(sender, this, address, page);
|
address.getChatHandler().sendHelpMessage(sender, this, address, page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendSyntaxMessage() {
|
public void sendSyntaxMessage() {
|
||||||
if (!muted) {
|
if (!muted) {
|
||||||
address.getChatHandler().sendSyntaxMessage(sender, this, address);
|
address.getChatHandler().sendSyntaxMessage(sender, this, address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.parameter.IArgumentPreProcessor;
|
import io.dico.dicore.command.parameter.IArgumentPreProcessor;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterType;
|
import io.dico.dicore.command.parameter.type.ParameterType;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public abstract class ExtendedCommand<T extends ExtendedCommand<T>> extends Command {
|
public abstract class ExtendedCommand<T extends ExtendedCommand<T>> extends Command {
|
||||||
protected boolean modifiable;
|
protected boolean modifiable;
|
||||||
|
|
||||||
public ExtendedCommand() {
|
public ExtendedCommand() {
|
||||||
this(true);
|
this(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtendedCommand(boolean modifiable) {
|
public ExtendedCommand(boolean modifiable) {
|
||||||
this.modifiable = modifiable;
|
this.modifiable = modifiable;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T newModifiableInstance() {
|
protected T newModifiableInstance() {
|
||||||
return (T) this;
|
return (T) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T addParameter(Parameter<?, ?> parameter) {
|
public T addParameter(Parameter<?, ?> parameter) {
|
||||||
return modifiable ? (T) super.addParameter(parameter) : newModifiableInstance().addParameter(parameter);
|
return modifiable ? (T) super.addParameter(parameter) : newModifiableInstance().addParameter(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T addContextFilter(IContextFilter contextFilter) {
|
public T addContextFilter(IContextFilter contextFilter) {
|
||||||
return modifiable ? (T) super.addContextFilter(contextFilter) : newModifiableInstance().addContextFilter(contextFilter);
|
return modifiable ? (T) super.addContextFilter(contextFilter) : newModifiableInstance().addContextFilter(contextFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T removeContextFilter(IContextFilter contextFilter) {
|
public T removeContextFilter(IContextFilter contextFilter) {
|
||||||
return modifiable ? (T) super.removeContextFilter(contextFilter) : newModifiableInstance().removeContextFilter(contextFilter);
|
return modifiable ? (T) super.removeContextFilter(contextFilter) : newModifiableInstance().removeContextFilter(contextFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T requiredParameters(int requiredParameters) {
|
public T requiredParameters(int requiredParameters) {
|
||||||
return modifiable ? (T) super.requiredParameters(requiredParameters) : newModifiableInstance().requiredParameters(requiredParameters);
|
return modifiable ? (T) super.requiredParameters(requiredParameters) : newModifiableInstance().requiredParameters(requiredParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T repeatFinalParameter() {
|
public T repeatFinalParameter() {
|
||||||
return modifiable ? (T) super.repeatFinalParameter() : newModifiableInstance().repeatFinalParameter();
|
return modifiable ? (T) super.repeatFinalParameter() : newModifiableInstance().repeatFinalParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T setDescription(String... description) {
|
public T setDescription(String... description) {
|
||||||
return modifiable ? (T) super.setDescription(description) : newModifiableInstance().setDescription(description);
|
return modifiable ? (T) super.setDescription(description) : newModifiableInstance().setDescription(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T setShortDescription(String shortDescription) {
|
public T setShortDescription(String shortDescription) {
|
||||||
return modifiable ? (T) super.setShortDescription(shortDescription) : newModifiableInstance().setShortDescription(shortDescription);
|
return modifiable ? (T) super.setShortDescription(shortDescription) : newModifiableInstance().setShortDescription(shortDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@Override
|
@Override
|
||||||
public T preprocessArguments(IArgumentPreProcessor processor) {
|
public T preprocessArguments(IArgumentPreProcessor processor) {
|
||||||
return modifiable ? (T) super.preprocessArguments(processor) : newModifiableInstance().preprocessArguments(processor);
|
return modifiable ? (T) super.preprocessArguments(processor) : newModifiableInstance().preprocessArguments(processor);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,205 +1,205 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.chat.IChatHandler;
|
import io.dico.dicore.command.chat.IChatHandler;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.ParameterList;
|
import io.dico.dicore.command.parameter.ParameterList;
|
||||||
import io.dico.dicore.command.predef.PredefinedCommand;
|
import io.dico.dicore.command.predef.PredefinedCommand;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for an address of a command.
|
* Interface for an address of a command.
|
||||||
* <p>
|
* <p>
|
||||||
* The address holds what the name and aliases of a command are.
|
* The address holds what the name and aliases of a command are.
|
||||||
* The address also (optionally) holds a reference to a {@link Command}
|
* The address also (optionally) holds a reference to a {@link Command}
|
||||||
* <p>
|
* <p>
|
||||||
* One instance of {@link Command} can be held by multiple addresses,
|
* One instance of {@link Command} can be held by multiple addresses,
|
||||||
* because the address decides what the command's name and aliases are.
|
* because the address decides what the command's name and aliases are.
|
||||||
* <p>
|
* <p>
|
||||||
* The address holds children by key in a map. This map's keys include aliases for its children.
|
* The address holds children by key in a map. This map's keys include aliases for its children.
|
||||||
* This creates a tree of addresses. If a command is dispatches, the tree is traversed untill a command is found
|
* This creates a tree of addresses. If a command is dispatches, the tree is traversed untill a command is found
|
||||||
* and no children deeper down match the command (there are exceptions to the later as defined by
|
* and no children deeper down match the command (there are exceptions to the later as defined by
|
||||||
* {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
|
* {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
|
||||||
* and {@link Command#isVisibleTo(CommandSender)}
|
* and {@link Command#isVisibleTo(CommandSender)}
|
||||||
*/
|
*/
|
||||||
public interface ICommandAddress {
|
public interface ICommandAddress {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this address has a parent.
|
* @return true if this address has a parent.
|
||||||
*/
|
*/
|
||||||
boolean hasParent();
|
boolean hasParent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the parent of this address
|
* Get the parent of this address
|
||||||
*
|
*
|
||||||
* @return the parent of this address, or null if none exists.
|
* @return the parent of this address, or null if none exists.
|
||||||
*/
|
*/
|
||||||
ICommandAddress getParent();
|
ICommandAddress getParent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this address has a command.
|
* @return true if this address has a command.
|
||||||
*/
|
*/
|
||||||
boolean hasCommand();
|
boolean hasCommand();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this address has a command that is not an instance of {@link PredefinedCommand}
|
* @return true if this address has a command that is not an instance of {@link PredefinedCommand}
|
||||||
*/
|
*/
|
||||||
boolean hasUserDeclaredCommand();
|
boolean hasUserDeclaredCommand();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Get the command of this address, or null if none exists.
|
* @return Get the command of this address, or null if none exists.
|
||||||
*/
|
*/
|
||||||
Command getCommand();
|
Command getCommand();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this address is an instance of {@link RootCommandAddress}
|
* @return true if this address is an instance of {@link RootCommandAddress}
|
||||||
*/
|
*/
|
||||||
boolean isRoot();
|
boolean isRoot();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the root address of the tree which this address resides in.
|
* @return the root address of the tree which this address resides in.
|
||||||
*/
|
*/
|
||||||
ICommandAddress getRoot();
|
ICommandAddress getRoot();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of the names of this address, at the current level.
|
* A list of the names of this address, at the current level.
|
||||||
* The first entry is the main key, the subsequent ones are aliases.
|
* The first entry is the main key, the subsequent ones are aliases.
|
||||||
* <p>
|
* <p>
|
||||||
* Untill an address is assigned a parent, this list is mutable.
|
* Untill an address is assigned a parent, this list is mutable.
|
||||||
* <p>
|
* <p>
|
||||||
* If {@link #isRoot()}, this returns an immutable, empty list.
|
* If {@link #isRoot()}, this returns an immutable, empty list.
|
||||||
*
|
*
|
||||||
* @return the list of names.
|
* @return the list of names.
|
||||||
*/
|
*/
|
||||||
List<String> getNames();
|
List<String> getNames();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of the aliases of this address. That is, {@link #getNames()}
|
* A list of the aliases of this address. That is, {@link #getNames()}
|
||||||
* without the first entry.
|
* without the first entry.
|
||||||
*
|
*
|
||||||
* @return a list of aliases
|
* @return a list of aliases
|
||||||
*/
|
*/
|
||||||
List<String> getAliases();
|
List<String> getAliases();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The first element of {@link #getNames()}
|
* @return The first element of {@link #getNames()}
|
||||||
*/
|
*/
|
||||||
String getMainKey();
|
String getMainKey();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the address of this command.
|
* Get the address of this command.
|
||||||
* That is, the main keys of all commands leading up to this address, and this address itself, separated by a space.
|
* That is, the main keys of all commands leading up to this address, and this address itself, separated by a space.
|
||||||
* In other words, the command without the / that is required to target the command at this address.
|
* In other words, the command without the / that is required to target the command at this address.
|
||||||
*
|
*
|
||||||
* @return the address of this command.
|
* @return the address of this command.
|
||||||
*/
|
*/
|
||||||
String getAddress();
|
String getAddress();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the amount of addresses that separate this address from the root of the tree, + 1.
|
* Get the amount of addresses that separate this address from the root of the tree, + 1.
|
||||||
* The root of the tree has a depth of 0. Each subsequent child has its depth incremented by 1.
|
* The root of the tree has a depth of 0. Each subsequent child has its depth incremented by 1.
|
||||||
*
|
*
|
||||||
* @return The depth of this address
|
* @return The depth of this address
|
||||||
*/
|
*/
|
||||||
int getDepth();
|
int getDepth();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the depth of this address is larger than the argument.
|
* @return true if the depth of this address is larger than the argument.
|
||||||
*/
|
*/
|
||||||
boolean isDepthLargerThan(int depth);
|
boolean isDepthLargerThan(int depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this address has any children.
|
* @return true if this address has any children.
|
||||||
*/
|
*/
|
||||||
boolean hasChildren();
|
boolean hasChildren();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return total number of children, not considering any aliases
|
* @return total number of children, not considering any aliases
|
||||||
*/
|
*/
|
||||||
int getNumberOfRealChildren();
|
int getNumberOfRealChildren();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an unmodifiable view of all main keys of the children of this address.
|
* Get an unmodifiable view of all main keys of the children of this address.
|
||||||
*
|
*
|
||||||
* @return the main keys
|
* @return the main keys
|
||||||
*/
|
*/
|
||||||
Collection<String> getChildrenMainKeys();
|
Collection<String> getChildrenMainKeys();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an unmodifiable view of the children of this address.
|
* Get an unmodifiable view of the children of this address.
|
||||||
* Values might be duplicated for aliases.
|
* Values might be duplicated for aliases.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* To iterate children without duplicates, you can do something like this:
|
* To iterate children without duplicates, you can do something like this:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* for (String key : address.getChildrenMainKeys()) {
|
* for (String key : address.getChildrenMainKeys()) {
|
||||||
* ICommandAddress child = address.getChild(key);
|
* ICommandAddress child = address.getChild(key);
|
||||||
* // do stuff with child
|
* // do stuff with child
|
||||||
* }
|
* }
|
||||||
* }</pre>
|
* }</pre>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @return the children of this address.
|
* @return the children of this address.
|
||||||
*/
|
*/
|
||||||
Map<String, ? extends ICommandAddress> getChildren();
|
Map<String, ? extends ICommandAddress> getChildren();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query for a child at the given key.
|
* Query for a child at the given key.
|
||||||
*
|
*
|
||||||
* @param key the key. The name or alias of a command.
|
* @param key the key. The name or alias of a command.
|
||||||
* @return the child, or null if it's not found
|
* @return the child, or null if it's not found
|
||||||
*/
|
*/
|
||||||
ICommandAddress getChild(String key);
|
ICommandAddress getChild(String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query for a child using the given buffer, with the given context for reference.
|
* Query for a child using the given buffer, with the given context for reference.
|
||||||
* Can be used to override behaviour of the address tree.
|
* Can be used to override behaviour of the address tree.
|
||||||
* <p>
|
* <p>
|
||||||
* The default implementation is as follows:
|
* The default implementation is as follows:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* return buffer.hasNext() ? getChild(buffer.next()) : null;
|
* return buffer.hasNext() ? getChild(buffer.next()) : null;
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* @param context context of a command being executed
|
* @param context context of a command being executed
|
||||||
* @param buffer the buffer. The name or alias of a command.
|
* @param buffer the buffer. The name or alias of a command.
|
||||||
* @return the child, or null if it's not found, altered freely by the implementation
|
* @return the child, or null if it's not found, altered freely by the implementation
|
||||||
*/
|
*/
|
||||||
ICommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
|
ICommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the command dispatcher for this tree
|
* Get the command dispatcher for this tree
|
||||||
*
|
*
|
||||||
* @return the command dispatcher
|
* @return the command dispatcher
|
||||||
*/
|
*/
|
||||||
ICommandDispatcher getDispatcherForTree();
|
ICommandDispatcher getDispatcherForTree();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The desired chathandler for use by commands at this address and any sub-addresses, if they define no explicit chat handler.
|
* @return The desired chathandler for use by commands at this address and any sub-addresses, if they define no explicit chat handler.
|
||||||
*/
|
*/
|
||||||
IChatHandler getChatHandler();
|
IChatHandler getChatHandler();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the command attached to this address should be treated as trailing.
|
* Returns if the command attached to this address should be treated as trailing.
|
||||||
* A trailing command is executed whenever the address is scanned for children.
|
* A trailing command is executed whenever the address is scanned for children.
|
||||||
* Its parameters are parsed and added to the context.
|
* Its parameters are parsed and added to the context.
|
||||||
*
|
*
|
||||||
* @return true if the command attached to this address should be treated as trailing.
|
* @return true if the command attached to this address should be treated as trailing.
|
||||||
*/
|
*/
|
||||||
boolean isCommandTrailing();
|
boolean isCommandTrailing();
|
||||||
|
|
||||||
static ICommandAddress newChild() {
|
static ICommandAddress newChild() {
|
||||||
return new ChildCommandAddress();
|
return new ChildCommandAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
static ICommandAddress newChild(Command command) {
|
static ICommandAddress newChild(Command command) {
|
||||||
return new ChildCommandAddress(command);
|
return new ChildCommandAddress(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ICommandAddress newRoot() {
|
static ICommandAddress newRoot() {
|
||||||
return new RootCommandAddress();
|
return new RootCommandAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,146 +1,146 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.registration.CommandMap;
|
import io.dico.dicore.command.registration.CommandMap;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface ICommandDispatcher {
|
public interface ICommandDispatcher {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a potentially indirect child of the root of this dispatcher
|
* Get a potentially indirect child of the root of this dispatcher
|
||||||
*
|
*
|
||||||
* @param buffer the argument buffer with the subsequent keys to traverse. Any keys beyond the first that isn't found are ignored.
|
* @param buffer the argument buffer with the subsequent keys to traverse. Any keys beyond the first that isn't found are ignored.
|
||||||
* @return the child, or this same instance of no child is found.
|
* @return the child, or this same instance of no child is found.
|
||||||
*/
|
*/
|
||||||
ICommandAddress getDeepChild(ArgumentBuffer buffer);
|
ICommandAddress getDeepChild(ArgumentBuffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link #getDeepChild(ArgumentBuffer)},
|
* Similar to {@link #getDeepChild(ArgumentBuffer)},
|
||||||
* but this method incorporates checks on the command of traversed children:
|
* but this method incorporates checks on the command of traversed children:
|
||||||
* {@link Command#isVisibleTo(CommandSender)}
|
* {@link Command#isVisibleTo(CommandSender)}
|
||||||
* and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
|
* and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
|
||||||
* <p>
|
* <p>
|
||||||
* The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
|
* The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
|
||||||
*
|
*
|
||||||
* @param sender the sender of the command
|
* @param sender the sender of the command
|
||||||
* @param buffer the command itself as a buffer.
|
* @param buffer the command itself as a buffer.
|
||||||
* @return the address that is the target of the command.
|
* @return the address that is the target of the command.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
ICommandAddress getCommandTarget(CommandSender sender, ArgumentBuffer buffer);
|
ICommandAddress getCommandTarget(CommandSender sender, ArgumentBuffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link #getDeepChild(ArgumentBuffer)},
|
* Similar to {@link #getDeepChild(ArgumentBuffer)},
|
||||||
* but this method incorporates checks on the command of traversed children:
|
* but this method incorporates checks on the command of traversed children:
|
||||||
* {@link Command#isVisibleTo(CommandSender)}
|
* {@link Command#isVisibleTo(CommandSender)}
|
||||||
* and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
|
* and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
|
||||||
* <p>
|
* <p>
|
||||||
* The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
|
* The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
|
||||||
*
|
*
|
||||||
* @param context the context of the command. The context must not have its address set.
|
* @param context the context of the command. The context must not have its address set.
|
||||||
* @param buffer the command itself as a buffer.
|
* @param buffer the command itself as a buffer.
|
||||||
* @return the address that is the target of the command.
|
* @return the address that is the target of the command.
|
||||||
*/
|
*/
|
||||||
ICommandAddress getCommandTarget(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
|
ICommandAddress getCommandTarget(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dispatch the command
|
* dispatch the command
|
||||||
*
|
*
|
||||||
* @param sender the sender
|
* @param sender the sender
|
||||||
* @param command the command
|
* @param command the command
|
||||||
* @return true if a command has executed
|
* @return true if a command has executed
|
||||||
*/
|
*/
|
||||||
boolean dispatchCommand(CommandSender sender, String[] command);
|
boolean dispatchCommand(CommandSender sender, String[] command);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dispatch the command
|
* dispatch the command
|
||||||
*
|
*
|
||||||
* @param sender the sender
|
* @param sender the sender
|
||||||
* @param usedLabel the label (word after the /)
|
* @param usedLabel the label (word after the /)
|
||||||
* @param args the arguments
|
* @param args the arguments
|
||||||
* @return true if a command has executed
|
* @return true if a command has executed
|
||||||
*/
|
*/
|
||||||
boolean dispatchCommand(CommandSender sender, String usedLabel, String[] args);
|
boolean dispatchCommand(CommandSender sender, String usedLabel, String[] args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dispatch the command
|
* dispatch the command
|
||||||
*
|
*
|
||||||
* @param sender the sender
|
* @param sender the sender
|
||||||
* @param buffer the command
|
* @param buffer the command
|
||||||
* @return true if a command has executed
|
* @return true if a command has executed
|
||||||
*/
|
*/
|
||||||
boolean dispatchCommand(CommandSender sender, ArgumentBuffer buffer);
|
boolean dispatchCommand(CommandSender sender, ArgumentBuffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* suggest tab completions
|
* suggest tab completions
|
||||||
*
|
*
|
||||||
* @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* args must be sanitized such that it contains no empty elements, particularly at the last index.
|
* args must be sanitized such that it contains no empty elements, particularly at the last index.
|
||||||
* @return tab completions
|
* @return tab completions
|
||||||
*/
|
*/
|
||||||
List<String> getTabCompletions(CommandSender sender, Location location, String[] args);
|
List<String> getTabCompletions(CommandSender sender, Location location, String[] args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* suggest tab completions
|
* suggest tab completions
|
||||||
*
|
*
|
||||||
* @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @param usedLabel the label as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param usedLabel the label as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @return tab completions
|
* @return tab completions
|
||||||
*/
|
*/
|
||||||
List<String> getTabCompletions(CommandSender sender, String usedLabel, Location location, String[] args);
|
List<String> getTabCompletions(CommandSender sender, String usedLabel, Location location, String[] args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* suggest tab completions
|
* suggest tab completions
|
||||||
*
|
*
|
||||||
* @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
* @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
|
||||||
* @param buffer the arguments as a buffer
|
* @param buffer the arguments as a buffer
|
||||||
* @return tab completions
|
* @return tab completions
|
||||||
*/
|
*/
|
||||||
List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer);
|
List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register this dispatcher's commands to the command map
|
* Register this dispatcher's commands to the command map
|
||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException if this dispatcher is not the root of the tree
|
* @throws UnsupportedOperationException if this dispatcher is not the root of the tree
|
||||||
*/
|
*/
|
||||||
default void registerToCommandMap() {
|
default void registerToCommandMap() {
|
||||||
registerToCommandMap(null, CommandMap.getCommandMap(), EOverridePolicy.OVERRIDE_ALL);
|
registerToCommandMap(null, CommandMap.getCommandMap(), EOverridePolicy.OVERRIDE_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register this dispatcher's commands to the command map
|
* Register this dispatcher's commands to the command map
|
||||||
*
|
*
|
||||||
* @param fallbackPrefix the fallback prefix to use, null if none
|
* @param fallbackPrefix the fallback prefix to use, null if none
|
||||||
* @param overridePolicy the override policy
|
* @param overridePolicy the override policy
|
||||||
* @throws UnsupportedOperationException if this dispatcher is not the root of the tree
|
* @throws UnsupportedOperationException if this dispatcher is not the root of the tree
|
||||||
*/
|
*/
|
||||||
default void registerToCommandMap(String fallbackPrefix, EOverridePolicy overridePolicy) {
|
default void registerToCommandMap(String fallbackPrefix, EOverridePolicy overridePolicy) {
|
||||||
registerToCommandMap(fallbackPrefix, CommandMap.getCommandMap(), overridePolicy);
|
registerToCommandMap(fallbackPrefix, CommandMap.getCommandMap(), overridePolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register this dispatcher's commands to the command map
|
* Register this dispatcher's commands to the command map
|
||||||
*
|
*
|
||||||
* @param fallbackPrefix the fallback prefix to use, null if none
|
* @param fallbackPrefix the fallback prefix to use, null if none
|
||||||
* @param map the command map
|
* @param map the command map
|
||||||
* @param overridePolicy the override policy
|
* @param overridePolicy the override policy
|
||||||
* @throws UnsupportedOperationException if this dispatcher is not the root of the tree
|
* @throws UnsupportedOperationException if this dispatcher is not the root of the tree
|
||||||
*/
|
*/
|
||||||
void registerToCommandMap(String fallbackPrefix, Map<String, org.bukkit.command.Command> map, EOverridePolicy overridePolicy);
|
void registerToCommandMap(String fallbackPrefix, Map<String, org.bukkit.command.Command> map, EOverridePolicy overridePolicy);
|
||||||
|
|
||||||
default void unregisterFromCommandMap() {
|
default void unregisterFromCommandMap() {
|
||||||
unregisterFromCommandMap(CommandMap.getCommandMap());
|
unregisterFromCommandMap(CommandMap.getCommandMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterFromCommandMap(Map<String, org.bukkit.command.Command> map);
|
void unregisterFromCommandMap(Map<String, org.bukkit.command.Command> map);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,201 +1,201 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.exceptions.checkedfunctions.CheckedConsumer;
|
import io.dico.dicore.exceptions.checkedfunctions.CheckedConsumer;
|
||||||
import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
|
import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface IContextFilter extends Comparable<IContextFilter> {
|
public interface IContextFilter extends Comparable<IContextFilter> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter the given context by this filter's criteria.
|
* Filter the given context by this filter's criteria.
|
||||||
* If the context does not match the criteria, an exception is thrown describing the problem.
|
* If the context does not match the criteria, an exception is thrown describing the problem.
|
||||||
*
|
*
|
||||||
* @param context the context to match
|
* @param context the context to match
|
||||||
* @throws CommandException if it doesn't match
|
* @throws CommandException if it doesn't match
|
||||||
*/
|
*/
|
||||||
void filterContext(ExecutionContext context) throws CommandException;
|
void filterContext(ExecutionContext context) throws CommandException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter an execution context for a direct or indirect sub command of the command that registered this filter.
|
* Filter an execution context for a direct or indirect sub command of the command that registered this filter.
|
||||||
*
|
*
|
||||||
* @param subContext the context for the execution
|
* @param subContext the context for the execution
|
||||||
* @param path the path traversed from the command that registered this filter to the executed command
|
* @param path the path traversed from the command that registered this filter to the executed command
|
||||||
*/
|
*/
|
||||||
default void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
|
default void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
|
||||||
filterContext(subContext);
|
filterContext(subContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the priority of this context filter.
|
* Get the priority of this context filter.
|
||||||
* The priorities determine the order in which a command's context filters are executed.
|
* The priorities determine the order in which a command's context filters are executed.
|
||||||
*
|
*
|
||||||
* @return the priority
|
* @return the priority
|
||||||
*/
|
*/
|
||||||
Priority getPriority();
|
Priority getPriority();
|
||||||
|
|
||||||
default boolean allowsContext(ExecutionContext context) {
|
default boolean allowsContext(ExecutionContext context) {
|
||||||
try {
|
try {
|
||||||
filterContext(context);
|
filterContext(context);
|
||||||
return true;
|
return true;
|
||||||
} catch (CommandException ex) {
|
} catch (CommandException ex) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to sort filters in execution order. That is, filters are ordered by {@link #getPriority()}
|
* Used to sort filters in execution order. That is, filters are ordered by {@link #getPriority()}
|
||||||
*
|
*
|
||||||
* @param o compared filter
|
* @param o compared filter
|
||||||
* @return comparison value
|
* @return comparison value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
default int compareTo(@NotNull IContextFilter o) {
|
default int compareTo(@NotNull IContextFilter o) {
|
||||||
return getPriority().compareTo(o.getPriority());
|
return getPriority().compareTo(o.getPriority());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
default boolean isInheritable() {
|
default boolean isInheritable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
default IContextFilter inherit(String... components) {
|
default IContextFilter inherit(String... components) {
|
||||||
if (!isInheritable()) {
|
if (!isInheritable()) {
|
||||||
throw new IllegalStateException("This IContextFilter cannot be inherited");
|
throw new IllegalStateException("This IContextFilter cannot be inherited");
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IContextFilter priorities. Executes from top to bottom.
|
* IContextFilter priorities. Executes from top to bottom.
|
||||||
*/
|
*/
|
||||||
enum Priority {
|
enum Priority {
|
||||||
/**
|
/**
|
||||||
* This priority should have checks on the sender type.
|
* This priority should have checks on the sender type.
|
||||||
* Any filters on this priority are tested before permissions are.
|
* Any filters on this priority are tested before permissions are.
|
||||||
* This is the highest priority.
|
* This is the highest priority.
|
||||||
*/
|
*/
|
||||||
VERY_EARLY, // sender type check
|
VERY_EARLY, // sender type check
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This priority is specific to permissions.
|
* This priority is specific to permissions.
|
||||||
*/
|
*/
|
||||||
PERMISSION,
|
PERMISSION,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Early priority. Post permissions, pre parameter-parsing.
|
* Early priority. Post permissions, pre parameter-parsing.
|
||||||
*/
|
*/
|
||||||
EARLY,
|
EARLY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normal priority. Post permissions, pre parameter-parsing.
|
* Normal priority. Post permissions, pre parameter-parsing.
|
||||||
*/
|
*/
|
||||||
NORMAL,
|
NORMAL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Late priority. Post permissions, pre parameter-parsing.
|
* Late priority. Post permissions, pre parameter-parsing.
|
||||||
*/
|
*/
|
||||||
LATE,
|
LATE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Very late priority. Post permissions, pre parameter-parsing.
|
* Very late priority. Post permissions, pre parameter-parsing.
|
||||||
*/
|
*/
|
||||||
VERY_LATE,
|
VERY_LATE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post parameters priority. Post permissions, post parameter-parsing.
|
* Post parameters priority. Post permissions, post parameter-parsing.
|
||||||
* This is the lowest priority.
|
* This is the lowest priority.
|
||||||
*/
|
*/
|
||||||
POST_PARAMETERS;
|
POST_PARAMETERS;
|
||||||
|
|
||||||
private IContextFilter inheritor;
|
private IContextFilter inheritor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the context filter that inherits context filters from the parent of the same priority.
|
* Get the context filter that inherits context filters from the parent of the same priority.
|
||||||
* If this filter is also present at the parent, it will do the same for the parent's parent, and so on.
|
* If this filter is also present at the parent, it will do the same for the parent's parent, and so on.
|
||||||
*
|
*
|
||||||
* @return the inheritor
|
* @return the inheritor
|
||||||
*/
|
*/
|
||||||
public IContextFilter getInheritor() {
|
public IContextFilter getInheritor() {
|
||||||
if (inheritor == null) {
|
if (inheritor == null) {
|
||||||
inheritor = InheritingContextFilter.inheritingPriority(this);
|
inheritor = InheritingContextFilter.inheritingPriority(this);
|
||||||
}
|
}
|
||||||
return inheritor;
|
return inheritor;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that only {@link org.bukkit.entity.Player} type senders can execute the command.
|
* Ensures that only {@link org.bukkit.entity.Player} type senders can execute the command.
|
||||||
*/
|
*/
|
||||||
IContextFilter PLAYER_ONLY = filterSender(Priority.VERY_EARLY, Validate::isPlayer);
|
IContextFilter PLAYER_ONLY = filterSender(Priority.VERY_EARLY, Validate::isPlayer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that only {@link org.bukkit.command.ConsoleCommandSender} type senders can execute the command.
|
* Ensures that only {@link org.bukkit.command.ConsoleCommandSender} type senders can execute the command.
|
||||||
*/
|
*/
|
||||||
IContextFilter CONSOLE_ONLY = filterSender(Priority.VERY_EARLY, Validate::isConsole);
|
IContextFilter CONSOLE_ONLY = filterSender(Priority.VERY_EARLY, Validate::isConsole);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This filter is not working as intended.
|
* This filter is not working as intended.
|
||||||
* <p>
|
* <p>
|
||||||
* There is supposed to be a permission filter that takes a base, and appends the command's address to the base, and checks that permission.
|
* There is supposed to be a permission filter that takes a base, and appends the command's address to the base, and checks that permission.
|
||||||
*/
|
*/
|
||||||
IContextFilter INHERIT_PERMISSIONS = Priority.PERMISSION.getInheritor();
|
IContextFilter INHERIT_PERMISSIONS = Priority.PERMISSION.getInheritor();
|
||||||
|
|
||||||
static IContextFilter fromCheckedRunnable(Priority priority, CheckedRunnable<? extends CommandException> runnable) {
|
static IContextFilter fromCheckedRunnable(Priority priority, CheckedRunnable<? extends CommandException> runnable) {
|
||||||
return new IContextFilter() {
|
return new IContextFilter() {
|
||||||
@Override
|
@Override
|
||||||
public void filterContext(ExecutionContext context) throws CommandException {
|
public void filterContext(ExecutionContext context) throws CommandException {
|
||||||
runnable.checkedRun();
|
runnable.checkedRun();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Priority getPriority() {
|
public Priority getPriority() {
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static IContextFilter filterSender(Priority priority, CheckedConsumer<? super CommandSender, ? extends CommandException> consumer) {
|
static IContextFilter filterSender(Priority priority, CheckedConsumer<? super CommandSender, ? extends CommandException> consumer) {
|
||||||
return new IContextFilter() {
|
return new IContextFilter() {
|
||||||
@Override
|
@Override
|
||||||
public void filterContext(ExecutionContext context) throws CommandException {
|
public void filterContext(ExecutionContext context) throws CommandException {
|
||||||
consumer.checkedAccept(context.getSender());
|
consumer.checkedAccept(context.getSender());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Priority getPriority() {
|
public Priority getPriority() {
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static IContextFilter permission(String permission) {
|
static IContextFilter permission(String permission) {
|
||||||
return new PermissionContextFilter(permission);
|
return new PermissionContextFilter(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IContextFilter permission(String permission, String failMessage) {
|
static IContextFilter permission(String permission, String failMessage) {
|
||||||
return new PermissionContextFilter(permission, failMessage);
|
return new PermissionContextFilter(permission, failMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IContextFilter inheritablePermission(String permission) {
|
static IContextFilter inheritablePermission(String permission) {
|
||||||
return new PermissionContextFilter(permission, true);
|
return new PermissionContextFilter(permission, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce an inheritable permission context filter.
|
* Produce an inheritable permission context filter.
|
||||||
* A permission component is an element in {@code permission.split("\\.")}
|
* A permission component is an element in {@code permission.split("\\.")}
|
||||||
*
|
*
|
||||||
* @param permission The permission that is required for the command that this is directly assigned to
|
* @param permission The permission that is required for the command that this is directly assigned to
|
||||||
* @param componentInsertionIndex the index where any sub-components are inserted. -1 for "at the end".
|
* @param componentInsertionIndex the index where any sub-components are inserted. -1 for "at the end".
|
||||||
* @param failMessage the message to send if the permission is not met
|
* @param failMessage the message to send if the permission is not met
|
||||||
* @return the context filter
|
* @return the context filter
|
||||||
* @throws IllegalArgumentException if componentInsertionIndex is out of range
|
* @throws IllegalArgumentException if componentInsertionIndex is out of range
|
||||||
*/
|
*/
|
||||||
static IContextFilter inheritablePermission(String permission, int componentInsertionIndex, String failMessage) {
|
static IContextFilter inheritablePermission(String permission, int componentInsertionIndex, String failMessage) {
|
||||||
return new PermissionContextFilter(permission, componentInsertionIndex, failMessage);
|
return new PermissionContextFilter(permission, componentInsertionIndex, failMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class InheritingContextFilter implements IContextFilter {
|
public abstract class InheritingContextFilter implements IContextFilter {
|
||||||
private static final String[] emptyStringArray = new String[0];
|
private static final String[] emptyStringArray = new String[0];
|
||||||
|
|
||||||
private static String[] addParent(String[] path, String parent) {
|
private static String[] addParent(String[] path, String parent) {
|
||||||
String[] out = new String[path.length + 1];
|
String[] out = new String[path.length + 1];
|
||||||
System.arraycopy(path, 0, out, 1, path.length);
|
System.arraycopy(path, 0, out, 1, path.length);
|
||||||
out[0] = parent;
|
out[0] = parent;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract boolean isInherited(IContextFilter filter);
|
protected abstract boolean isInherited(IContextFilter filter);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filterContext(ExecutionContext context) throws CommandException {
|
public void filterContext(ExecutionContext context) throws CommandException {
|
||||||
ICommandAddress address = context.getAddress();
|
ICommandAddress address = context.getAddress();
|
||||||
|
|
||||||
String[] traversedPath = emptyStringArray;
|
String[] traversedPath = emptyStringArray;
|
||||||
do {
|
do {
|
||||||
traversedPath = addParent(traversedPath, address.getMainKey());
|
traversedPath = addParent(traversedPath, address.getMainKey());
|
||||||
address = address.getParent();
|
address = address.getParent();
|
||||||
|
|
||||||
if (address != null && address.hasCommand()) {
|
if (address != null && address.hasCommand()) {
|
||||||
boolean doBreak = true;
|
boolean doBreak = true;
|
||||||
|
|
||||||
Command command = address.getCommand();
|
Command command = address.getCommand();
|
||||||
List<IContextFilter> contextFilterList = command.getContextFilters();
|
List<IContextFilter> contextFilterList = command.getContextFilters();
|
||||||
for (IContextFilter filter : contextFilterList) {
|
for (IContextFilter filter : contextFilterList) {
|
||||||
if (isInherited(filter)) {
|
if (isInherited(filter)) {
|
||||||
if (filter == this) {
|
if (filter == this) {
|
||||||
// do the same for next parent
|
// do the same for next parent
|
||||||
// this method is necessary to keep traversedPath information
|
// this method is necessary to keep traversedPath information
|
||||||
doBreak = false;
|
doBreak = false;
|
||||||
} else {
|
} else {
|
||||||
filter.filterSubContext(context, traversedPath);
|
filter.filterSubContext(context, traversedPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doBreak) {
|
if (doBreak) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (address != null);
|
} while (address != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
static InheritingContextFilter inheritingPriority(Priority priority) {
|
static InheritingContextFilter inheritingPriority(Priority priority) {
|
||||||
return new InheritingContextFilter() {
|
return new InheritingContextFilter() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean isInherited(IContextFilter filter) {
|
protected boolean isInherited(IContextFilter filter) {
|
||||||
return filter.getPriority() == priority;
|
return filter.getPriority() == priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Priority getPriority() {
|
public Priority getPriority() {
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.exceptions.checkedfunctions.CheckedBiFunction;
|
import io.dico.dicore.exceptions.checkedfunctions.CheckedBiFunction;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
public class LambdaCommand extends ExtendedCommand<LambdaCommand> {
|
public class LambdaCommand extends ExtendedCommand<LambdaCommand> {
|
||||||
private CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor;
|
private CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor;
|
||||||
private BiFunction<CommandSender, ExecutionContext, List<String>> completer;
|
private BiFunction<CommandSender, ExecutionContext, List<String>> completer;
|
||||||
|
|
||||||
public LambdaCommand executor(CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor) {
|
public LambdaCommand executor(CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor) {
|
||||||
this.executor = Objects.requireNonNull(executor);
|
this.executor = Objects.requireNonNull(executor);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LambdaCommand completer(BiFunction<CommandSender, ExecutionContext, List<String>> completer) {
|
public LambdaCommand completer(BiFunction<CommandSender, ExecutionContext, List<String>> completer) {
|
||||||
this.completer = Objects.requireNonNull(completer);
|
this.completer = Objects.requireNonNull(completer);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
||||||
return executor.checkedApply(sender, context);
|
return executor.checkedApply(sender, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
|
public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
|
||||||
return completer == null ? super.tabComplete(sender, context, location) : completer.apply(sender, context);
|
return completer == null ? super.tabComplete(sender, context, location) : completer.apply(sender, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,312 +1,312 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.chat.ChatHandlers;
|
import io.dico.dicore.command.chat.ChatHandlers;
|
||||||
import io.dico.dicore.command.chat.IChatHandler;
|
import io.dico.dicore.command.chat.IChatHandler;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.ParameterList;
|
import io.dico.dicore.command.parameter.ParameterList;
|
||||||
import io.dico.dicore.command.predef.DefaultGroupCommand;
|
import io.dico.dicore.command.predef.DefaultGroupCommand;
|
||||||
import io.dico.dicore.command.predef.HelpCommand;
|
import io.dico.dicore.command.predef.HelpCommand;
|
||||||
import io.dico.dicore.command.predef.PredefinedCommand;
|
import io.dico.dicore.command.predef.PredefinedCommand;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public abstract class ModifiableCommandAddress implements ICommandAddress {
|
public abstract class ModifiableCommandAddress implements ICommandAddress {
|
||||||
Map<String, ChildCommandAddress> children;
|
Map<String, ChildCommandAddress> children;
|
||||||
Collection<String> childrenMainKeys = Collections.emptyList();
|
Collection<String> childrenMainKeys = Collections.emptyList();
|
||||||
|
|
||||||
// the chat handler as configured by the programmer
|
// the chat handler as configured by the programmer
|
||||||
IChatHandler chatHandler;
|
IChatHandler chatHandler;
|
||||||
// cache for the algorithm that finds the first chat handler going up the tree
|
// cache for the algorithm that finds the first chat handler going up the tree
|
||||||
transient IChatHandler cachedChatHandlerFallback;
|
transient IChatHandler cachedChatHandlerFallback;
|
||||||
|
|
||||||
ModifiableCommandAddress helpChild;
|
ModifiableCommandAddress helpChild;
|
||||||
|
|
||||||
public ModifiableCommandAddress() {
|
public ModifiableCommandAddress() {
|
||||||
this.children = new LinkedHashMap<>(4);
|
this.children = new LinkedHashMap<>(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasParent() {
|
public boolean hasParent() {
|
||||||
return getParent() != null;
|
return getParent() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasCommand() {
|
public boolean hasCommand() {
|
||||||
return getCommand() != null;
|
return getCommand() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasUserDeclaredCommand() {
|
public boolean hasUserDeclaredCommand() {
|
||||||
Command command = getCommand();
|
Command command = getCommand();
|
||||||
return command != null && !(command instanceof PredefinedCommand);
|
return command != null && !(command instanceof PredefinedCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command getCommand() {
|
public Command getCommand() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRoot() {
|
public boolean isRoot() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getNames() {
|
public List<String> getNames() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAliases() {
|
public List<String> getAliases() {
|
||||||
List<String> names = getNames();
|
List<String> names = getNames();
|
||||||
if (names == null) {
|
if (names == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (names.isEmpty()) {
|
if (names.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return names.subList(1, names.size());
|
return names.subList(1, names.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMainKey() {
|
public String getMainKey() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCommand(Command command) {
|
public void setCommand(Command command) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract ModifiableCommandAddress getParent();
|
public abstract ModifiableCommandAddress getParent();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RootCommandAddress getRoot() {
|
public RootCommandAddress getRoot() {
|
||||||
ModifiableCommandAddress out = this;
|
ModifiableCommandAddress out = this;
|
||||||
while (out.hasParent()) {
|
while (out.hasParent()) {
|
||||||
out = out.getParent();
|
out = out.getParent();
|
||||||
}
|
}
|
||||||
return out.isRoot() ? (RootCommandAddress) out : null;
|
return out.isRoot() ? (RootCommandAddress) out : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDepth() {
|
public int getDepth() {
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
ICommandAddress address = this;
|
ICommandAddress address = this;
|
||||||
while (address.hasParent()) {
|
while (address.hasParent()) {
|
||||||
address = address.getParent();
|
address = address.getParent();
|
||||||
depth++;
|
depth++;
|
||||||
}
|
}
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDepthLargerThan(int value) {
|
public boolean isDepthLargerThan(int value) {
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
ICommandAddress address = this;
|
ICommandAddress address = this;
|
||||||
do {
|
do {
|
||||||
if (depth > value) {
|
if (depth > value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
address = address.getParent();
|
address = address.getParent();
|
||||||
depth++;
|
depth++;
|
||||||
} while (address != null);
|
} while (address != null);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasChildren() {
|
public boolean hasChildren() {
|
||||||
return !children.isEmpty();
|
return !children.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getNumberOfRealChildren() {
|
public int getNumberOfRealChildren() {
|
||||||
return childrenMainKeys.size();
|
return childrenMainKeys.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getChildrenMainKeys() {
|
public Collection<String> getChildrenMainKeys() {
|
||||||
return Collections.unmodifiableCollection(childrenMainKeys);
|
return Collections.unmodifiableCollection(childrenMainKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, ? extends ModifiableCommandAddress> getChildren() {
|
public Map<String, ? extends ModifiableCommandAddress> getChildren() {
|
||||||
return Collections.unmodifiableMap(children);
|
return Collections.unmodifiableMap(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChildCommandAddress getChild(String key) {
|
public ChildCommandAddress getChild(String key) {
|
||||||
return children.get(key);
|
return children.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChildCommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
public ChildCommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
||||||
return buffer.hasNext() ? getChild(buffer.next()) : null;
|
return buffer.hasNext() ? getChild(buffer.next()) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addChild(ICommandAddress child) {
|
public void addChild(ICommandAddress child) {
|
||||||
if (!(child instanceof ChildCommandAddress)) {
|
if (!(child instanceof ChildCommandAddress)) {
|
||||||
throw new IllegalArgumentException("Argument must be a ChildCommandAddress");
|
throw new IllegalArgumentException("Argument must be a ChildCommandAddress");
|
||||||
}
|
}
|
||||||
|
|
||||||
ChildCommandAddress mChild = (ChildCommandAddress) child;
|
ChildCommandAddress mChild = (ChildCommandAddress) child;
|
||||||
if (mChild.parent != null) {
|
if (mChild.parent != null) {
|
||||||
throw new IllegalArgumentException("Argument already has a parent");
|
throw new IllegalArgumentException("Argument already has a parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mChild.names.isEmpty()) {
|
if (mChild.names.isEmpty()) {
|
||||||
throw new IllegalArgumentException("Argument must have names");
|
throw new IllegalArgumentException("Argument must have names");
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<String> names = mChild.modifiableNamesIterator();
|
Iterator<String> names = mChild.modifiableNamesIterator();
|
||||||
String mainKey = names.next();
|
String mainKey = names.next();
|
||||||
|
|
||||||
if (!childrenMainKeys.contains(mainKey)) {
|
if (!childrenMainKeys.contains(mainKey)) {
|
||||||
if (!(childrenMainKeys instanceof ArrayList)) {
|
if (!(childrenMainKeys instanceof ArrayList)) {
|
||||||
childrenMainKeys = new ArrayList<>();
|
childrenMainKeys = new ArrayList<>();
|
||||||
}
|
}
|
||||||
childrenMainKeys.add(mainKey);
|
childrenMainKeys.add(mainKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
children.put(mainKey, mChild);
|
children.put(mainKey, mChild);
|
||||||
|
|
||||||
while (names.hasNext()) {
|
while (names.hasNext()) {
|
||||||
String name = names.next();
|
String name = names.next();
|
||||||
if (children.putIfAbsent(name, mChild) != null) {
|
if (children.putIfAbsent(name, mChild) != null) {
|
||||||
names.remove();
|
names.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mChild.setParent(this);
|
mChild.setParent(this);
|
||||||
|
|
||||||
if (mChild.hasCommand() && mChild.getCommand() instanceof HelpCommand) {
|
if (mChild.hasCommand() && mChild.getCommand() instanceof HelpCommand) {
|
||||||
helpChild = mChild;
|
helpChild = mChild;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeChildren(boolean removeAliases, String... keys) {
|
public void removeChildren(boolean removeAliases, String... keys) {
|
||||||
if (keys.length == 0) {
|
if (keys.length == 0) {
|
||||||
throw new IllegalArgumentException("keys is empty");
|
throw new IllegalArgumentException("keys is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
ChildCommandAddress keyTarget = getChild(key);
|
ChildCommandAddress keyTarget = getChild(key);
|
||||||
if (keyTarget == null) {
|
if (keyTarget == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeAliases) {
|
if (removeAliases) {
|
||||||
Iterator<String> iterator = keyTarget.namesModifiable.iterator();
|
Iterator<String> iterator = keyTarget.namesModifiable.iterator();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
String alias = iterator.next();
|
String alias = iterator.next();
|
||||||
ChildCommandAddress aliasTarget = getChild(key);
|
ChildCommandAddress aliasTarget = getChild(key);
|
||||||
if (aliasTarget == keyTarget) {
|
if (aliasTarget == keyTarget) {
|
||||||
if (first) {
|
if (first) {
|
||||||
childrenMainKeys.remove(alias);
|
childrenMainKeys.remove(alias);
|
||||||
}
|
}
|
||||||
children.remove(alias);
|
children.remove(alias);
|
||||||
}
|
}
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (key.equals(keyTarget.getMainKey())) {
|
if (key.equals(keyTarget.getMainKey())) {
|
||||||
childrenMainKeys.remove(key);
|
childrenMainKeys.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
children.remove(key);
|
children.remove(key);
|
||||||
keyTarget.namesModifiable.remove(key);
|
keyTarget.namesModifiable.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasHelpCommand() {
|
public boolean hasHelpCommand() {
|
||||||
return helpChild != null;
|
return helpChild != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModifiableCommandAddress getHelpCommand() {
|
public ModifiableCommandAddress getHelpCommand() {
|
||||||
return helpChild;
|
return helpChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IChatHandler getChatHandler() {
|
public IChatHandler getChatHandler() {
|
||||||
if (cachedChatHandlerFallback == null) {
|
if (cachedChatHandlerFallback == null) {
|
||||||
if (chatHandler != null) {
|
if (chatHandler != null) {
|
||||||
cachedChatHandlerFallback = chatHandler;
|
cachedChatHandlerFallback = chatHandler;
|
||||||
} else if (!hasParent()) {
|
} else if (!hasParent()) {
|
||||||
cachedChatHandlerFallback = ChatHandlers.defaultChat();
|
cachedChatHandlerFallback = ChatHandlers.defaultChat();
|
||||||
} else {
|
} else {
|
||||||
cachedChatHandlerFallback = getParent().getChatHandler();
|
cachedChatHandlerFallback = getParent().getChatHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cachedChatHandlerFallback;
|
return cachedChatHandlerFallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChatHandler(IChatHandler chatHandler) {
|
public void setChatHandler(IChatHandler chatHandler) {
|
||||||
this.chatHandler = chatHandler;
|
this.chatHandler = chatHandler;
|
||||||
resetChatHandlerCache(new HashSet<>());
|
resetChatHandlerCache(new HashSet<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetChatHandlerCache(Set<ModifiableCommandAddress> dejaVu) {
|
void resetChatHandlerCache(Set<ModifiableCommandAddress> dejaVu) {
|
||||||
if (dejaVu.add(this)) {
|
if (dejaVu.add(this)) {
|
||||||
cachedChatHandlerFallback = chatHandler;
|
cachedChatHandlerFallback = chatHandler;
|
||||||
for (ChildCommandAddress address : children.values()) {
|
for (ChildCommandAddress address : children.values()) {
|
||||||
if (address.chatHandler == null) {
|
if (address.chatHandler == null) {
|
||||||
address.resetChatHandlerCache(dejaVu);
|
address.resetChatHandlerCache(dejaVu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ICommandDispatcher getDispatcherForTree() {
|
public ICommandDispatcher getDispatcherForTree() {
|
||||||
return getRoot();
|
return getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCommandTrailing() {
|
public boolean isCommandTrailing() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCommandTrailing(boolean trailing) {
|
public void setCommandTrailing(boolean trailing) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendDebugInformation(StringBuilder target, String linePrefix, Set<ICommandAddress> seen) {
|
void appendDebugInformation(StringBuilder target, String linePrefix, Set<ICommandAddress> seen) {
|
||||||
target.append('\n').append(linePrefix);
|
target.append('\n').append(linePrefix);
|
||||||
if (!seen.add(this)) {
|
if (!seen.add(this)) {
|
||||||
target.append("<duplicate of address '").append(getAddress()).append("'>");
|
target.append("<duplicate of address '").append(getAddress()).append("'>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this instanceof ChildCommandAddress) {
|
if (this instanceof ChildCommandAddress) {
|
||||||
List<String> namesModifiable = ((ChildCommandAddress) this).namesModifiable;
|
List<String> namesModifiable = ((ChildCommandAddress) this).namesModifiable;
|
||||||
if (namesModifiable.isEmpty()) {
|
if (namesModifiable.isEmpty()) {
|
||||||
target.append("<no key>");
|
target.append("<no key>");
|
||||||
} else {
|
} else {
|
||||||
Iterator<String> keys = namesModifiable.iterator();
|
Iterator<String> keys = namesModifiable.iterator();
|
||||||
target.append(keys.next()).append(' ');
|
target.append(keys.next()).append(' ');
|
||||||
if (keys.hasNext()) {
|
if (keys.hasNext()) {
|
||||||
target.append('(').append(keys.next());
|
target.append('(').append(keys.next());
|
||||||
while (keys.hasNext()) {
|
while (keys.hasNext()) {
|
||||||
target.append(" ,").append(keys.next());
|
target.append(" ,").append(keys.next());
|
||||||
}
|
}
|
||||||
target.append(") ");
|
target.append(") ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target.append("<root> ");
|
target.append("<root> ");
|
||||||
}
|
}
|
||||||
|
|
||||||
String commandClass = hasCommand() ? getCommand().getClass().getCanonicalName() : "<no command>";
|
String commandClass = hasCommand() ? getCommand().getClass().getCanonicalName() : "<no command>";
|
||||||
target.append(commandClass);
|
target.append(commandClass);
|
||||||
|
|
||||||
for (ChildCommandAddress child : new HashSet<>(children.values())) {
|
for (ChildCommandAddress child : new HashSet<>(children.values())) {
|
||||||
child.appendDebugInformation(target, linePrefix + " ", seen);
|
child.appendDebugInformation(target, linePrefix + " ", seen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,136 +1,136 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class PermissionContextFilter implements IContextFilter {
|
public class PermissionContextFilter implements IContextFilter {
|
||||||
private String permission;
|
private String permission;
|
||||||
private String[] permissionComponents;
|
private String[] permissionComponents;
|
||||||
private int componentInsertionIndex;
|
private int componentInsertionIndex;
|
||||||
private String failMessage;
|
private String failMessage;
|
||||||
|
|
||||||
public PermissionContextFilter(String permission) {
|
public PermissionContextFilter(String permission) {
|
||||||
this.permission = Objects.requireNonNull(permission);
|
this.permission = Objects.requireNonNull(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PermissionContextFilter(String permission, String failMessage) {
|
public PermissionContextFilter(String permission, String failMessage) {
|
||||||
this(permission);
|
this(permission);
|
||||||
this.failMessage = failMessage;
|
this.failMessage = failMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PermissionContextFilter(String permission, boolean inheritable) {
|
public PermissionContextFilter(String permission, boolean inheritable) {
|
||||||
this(permission, null, inheritable);
|
this(permission, null, inheritable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PermissionContextFilter(String permission, String failMessage, boolean inheritable) {
|
public PermissionContextFilter(String permission, String failMessage, boolean inheritable) {
|
||||||
this(permission, failMessage);
|
this(permission, failMessage);
|
||||||
if (inheritable) {
|
if (inheritable) {
|
||||||
setupInheritability(-1);
|
setupInheritability(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PermissionContextFilter(String permission, int componentInsertionIndex, String failMessage) {
|
public PermissionContextFilter(String permission, int componentInsertionIndex, String failMessage) {
|
||||||
this(permission, failMessage);
|
this(permission, failMessage);
|
||||||
setupInheritability(componentInsertionIndex);
|
setupInheritability(componentInsertionIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupInheritability(int componentInsertionIndex) {
|
private void setupInheritability(int componentInsertionIndex) {
|
||||||
this.permissionComponents = permission.split("\\.");
|
this.permissionComponents = permission.split("\\.");
|
||||||
this.componentInsertionIndex = componentInsertionIndex < 0 ? permissionComponents.length : componentInsertionIndex;
|
this.componentInsertionIndex = componentInsertionIndex < 0 ? permissionComponents.length : componentInsertionIndex;
|
||||||
if (componentInsertionIndex > permissionComponents.length) throw new IllegalArgumentException();
|
if (componentInsertionIndex > permissionComponents.length) throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doFilter(ExecutionContext context, String permission) throws CommandException {
|
private void doFilter(ExecutionContext context, String permission) throws CommandException {
|
||||||
if (failMessage != null) {
|
if (failMessage != null) {
|
||||||
Validate.isAuthorized(context.getSender(), permission, failMessage);
|
Validate.isAuthorized(context.getSender(), permission, failMessage);
|
||||||
} else {
|
} else {
|
||||||
Validate.isAuthorized(context.getSender(), permission);
|
Validate.isAuthorized(context.getSender(), permission);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filterContext(ExecutionContext context) throws CommandException {
|
public void filterContext(ExecutionContext context) throws CommandException {
|
||||||
doFilter(context, permission);
|
doFilter(context, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInheritedPermission(String[] components) {
|
public String getInheritedPermission(String[] components) {
|
||||||
int insertedAmount = components.length;
|
int insertedAmount = components.length;
|
||||||
String[] currentComponents = permissionComponents;
|
String[] currentComponents = permissionComponents;
|
||||||
int currentAmount = currentComponents.length;
|
int currentAmount = currentComponents.length;
|
||||||
String[] targetArray = new String[currentAmount + insertedAmount];
|
String[] targetArray = new String[currentAmount + insertedAmount];
|
||||||
|
|
||||||
int insertionIndex;
|
int insertionIndex;
|
||||||
//int newInsertionIndex;
|
//int newInsertionIndex;
|
||||||
if (componentInsertionIndex == -1) {
|
if (componentInsertionIndex == -1) {
|
||||||
insertionIndex = currentAmount;
|
insertionIndex = currentAmount;
|
||||||
//newInsertionIndex = -1;
|
//newInsertionIndex = -1;
|
||||||
} else {
|
} else {
|
||||||
insertionIndex = componentInsertionIndex;
|
insertionIndex = componentInsertionIndex;
|
||||||
//newInsertionIndex = insertionIndex + insertedAmount;
|
//newInsertionIndex = insertionIndex + insertedAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the current components up to insertionIndex
|
// copy the current components up to insertionIndex
|
||||||
System.arraycopy(currentComponents, 0, targetArray, 0, insertionIndex);
|
System.arraycopy(currentComponents, 0, targetArray, 0, insertionIndex);
|
||||||
// copy the new components into the array at insertionIndex
|
// copy the new components into the array at insertionIndex
|
||||||
System.arraycopy(components, 0, targetArray, insertionIndex, insertedAmount);
|
System.arraycopy(components, 0, targetArray, insertionIndex, insertedAmount);
|
||||||
// copy the current components from insertionIndex + inserted amount
|
// copy the current components from insertionIndex + inserted amount
|
||||||
System.arraycopy(currentComponents, insertionIndex, targetArray, insertionIndex + insertedAmount, currentAmount - insertionIndex);
|
System.arraycopy(currentComponents, insertionIndex, targetArray, insertionIndex + insertedAmount, currentAmount - insertionIndex);
|
||||||
|
|
||||||
return String.join(".", targetArray);
|
return String.join(".", targetArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
|
public void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
|
||||||
if (isInheritable()) {
|
if (isInheritable()) {
|
||||||
doFilter(subContext, getInheritedPermission(path));
|
doFilter(subContext, getInheritedPermission(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Priority getPriority() {
|
public Priority getPriority() {
|
||||||
return Priority.PERMISSION;
|
return Priority.PERMISSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInheritable() {
|
public boolean isInheritable() {
|
||||||
return permissionComponents != null;
|
return permissionComponents != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPermission() {
|
public String getPermission() {
|
||||||
return permission;
|
return permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getComponentInsertionIndex() {
|
public int getComponentInsertionIndex() {
|
||||||
return componentInsertionIndex;
|
return componentInsertionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFailMessage() {
|
public String getFailMessage() {
|
||||||
return failMessage;
|
return failMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
private fun getPermissionsOf(address: ICommandAddress) = getPermissionsOf(address, emptyArray(), mutableListOf())
|
private fun getPermissionsOf(address: ICommandAddress) = getPermissionsOf(address, emptyArray(), mutableListOf())
|
||||||
|
|
||||||
private fun getPermissionsOf(address: ICommandAddress, path: Array<String>, result: MutableList<String>): List<String> {
|
private fun getPermissionsOf(address: ICommandAddress, path: Array<String>, result: MutableList<String>): List<String> {
|
||||||
val command = address.command ?: return result
|
val command = address.command ?: return result
|
||||||
|
|
||||||
var inherited = false
|
var inherited = false
|
||||||
for (filter in command.contextFilters) {
|
for (filter in command.contextFilters) {
|
||||||
when (filter) {
|
when (filter) {
|
||||||
is PermissionContextFilter -> {
|
is PermissionContextFilter -> {
|
||||||
if (path.isEmpty()) result.add(filter.permission)
|
if (path.isEmpty()) result.add(filter.permission)
|
||||||
else if (filter.isInheritable) result.add(filter.getInheritedPermission(path))
|
else if (filter.isInheritable) result.add(filter.getInheritedPermission(path))
|
||||||
}
|
}
|
||||||
is InheritingContextFilter -> {
|
is InheritingContextFilter -> {
|
||||||
if (filter.priority == PERMISSION && address.hasParent() && !inherited) {
|
if (filter.priority == PERMISSION && address.hasParent() && !inherited) {
|
||||||
inherited = true
|
inherited = true
|
||||||
getPermissionsOf(address.parent, arrayOf(address.mainKey, *path), result)
|
getPermissionsOf(address.parent, arrayOf(address.mainKey, *path), result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,275 +1,275 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.registration.BukkitCommand;
|
import io.dico.dicore.command.registration.BukkitCommand;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class RootCommandAddress extends ModifiableCommandAddress implements ICommandDispatcher {
|
public class RootCommandAddress extends ModifiableCommandAddress implements ICommandDispatcher {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static final RootCommandAddress INSTANCE = new RootCommandAddress();
|
public static final RootCommandAddress INSTANCE = new RootCommandAddress();
|
||||||
|
|
||||||
public RootCommandAddress() {
|
public RootCommandAddress() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command getCommand() {
|
public Command getCommand() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRoot() {
|
public boolean isRoot() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getNames() {
|
public List<String> getNames() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModifiableCommandAddress getParent() {
|
public ModifiableCommandAddress getParent() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMainKey() {
|
public String getMainKey() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAddress() {
|
public String getAddress() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerToCommandMap(String fallbackPrefix, Map<String, org.bukkit.command.Command> map, EOverridePolicy overridePolicy) {
|
public void registerToCommandMap(String fallbackPrefix, Map<String, org.bukkit.command.Command> map, EOverridePolicy overridePolicy) {
|
||||||
Objects.requireNonNull(overridePolicy);
|
Objects.requireNonNull(overridePolicy);
|
||||||
//debugChildren(this);
|
//debugChildren(this);
|
||||||
Map<String, ChildCommandAddress> children = this.children;
|
Map<String, ChildCommandAddress> children = this.children;
|
||||||
Map<ChildCommandAddress, BukkitCommand> wrappers = new IdentityHashMap<>();
|
Map<ChildCommandAddress, BukkitCommand> wrappers = new IdentityHashMap<>();
|
||||||
|
|
||||||
for (ChildCommandAddress address : children.values()) {
|
for (ChildCommandAddress address : children.values()) {
|
||||||
if (!wrappers.containsKey(address)) {
|
if (!wrappers.containsKey(address)) {
|
||||||
wrappers.put(address, new BukkitCommand(address));
|
wrappers.put(address, new BukkitCommand(address));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, ChildCommandAddress> entry : children.entrySet()) {
|
for (Map.Entry<String, ChildCommandAddress> entry : children.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
ChildCommandAddress address = entry.getValue();
|
ChildCommandAddress address = entry.getValue();
|
||||||
boolean override = overridePolicy == EOverridePolicy.OVERRIDE_ALL;
|
boolean override = overridePolicy == EOverridePolicy.OVERRIDE_ALL;
|
||||||
if (!override && key.equals(address.getMainKey())) {
|
if (!override && key.equals(address.getMainKey())) {
|
||||||
override = overridePolicy == EOverridePolicy.MAIN_KEY_ONLY || overridePolicy == EOverridePolicy.MAIN_AND_FALLBACK;
|
override = overridePolicy == EOverridePolicy.MAIN_KEY_ONLY || overridePolicy == EOverridePolicy.MAIN_AND_FALLBACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerMember(map, key, wrappers.get(address), override);
|
registerMember(map, key, wrappers.get(address), override);
|
||||||
|
|
||||||
if (fallbackPrefix != null) {
|
if (fallbackPrefix != null) {
|
||||||
key = fallbackPrefix + key;
|
key = fallbackPrefix + key;
|
||||||
override = overridePolicy != EOverridePolicy.OVERRIDE_NONE && overridePolicy != EOverridePolicy.MAIN_KEY_ONLY;
|
override = overridePolicy != EOverridePolicy.OVERRIDE_NONE && overridePolicy != EOverridePolicy.MAIN_KEY_ONLY;
|
||||||
registerMember(map, key, wrappers.get(address), override);
|
registerMember(map, key, wrappers.get(address), override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void debugChildren(ModifiableCommandAddress address) {
|
private static void debugChildren(ModifiableCommandAddress address) {
|
||||||
Collection<String> keys = address.getChildrenMainKeys();
|
Collection<String> keys = address.getChildrenMainKeys();
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
ChildCommandAddress child = address.getChild(key);
|
ChildCommandAddress child = address.getChild(key);
|
||||||
System.out.println(child.getAddress());
|
System.out.println(child.getAddress());
|
||||||
debugChildren(child);
|
debugChildren(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerMember(Map<String, org.bukkit.command.Command> map,
|
private static void registerMember(Map<String, org.bukkit.command.Command> map,
|
||||||
String key, org.bukkit.command.Command value, boolean override) {
|
String key, org.bukkit.command.Command value, boolean override) {
|
||||||
if (override) {
|
if (override) {
|
||||||
map.put(key, value);
|
map.put(key, value);
|
||||||
} else {
|
} else {
|
||||||
map.putIfAbsent(key, value);
|
map.putIfAbsent(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterFromCommandMap(Map<String, org.bukkit.command.Command> map) {
|
public void unregisterFromCommandMap(Map<String, org.bukkit.command.Command> map) {
|
||||||
Set<ICommandAddress> children = new HashSet<>(this.children.values());
|
Set<ICommandAddress> children = new HashSet<>(this.children.values());
|
||||||
Iterator<Map.Entry<String, org.bukkit.command.Command>> iterator = map.entrySet().iterator();
|
Iterator<Map.Entry<String, org.bukkit.command.Command>> iterator = map.entrySet().iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Map.Entry<String, org.bukkit.command.Command> entry = iterator.next();
|
Map.Entry<String, org.bukkit.command.Command> entry = iterator.next();
|
||||||
org.bukkit.command.Command cmd = entry.getValue();
|
org.bukkit.command.Command cmd = entry.getValue();
|
||||||
if (cmd instanceof BukkitCommand && children.contains(((BukkitCommand) cmd).getOrigin())) {
|
if (cmd instanceof BukkitCommand && children.contains(((BukkitCommand) cmd).getOrigin())) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModifiableCommandAddress getDeepChild(ArgumentBuffer buffer) {
|
public ModifiableCommandAddress getDeepChild(ArgumentBuffer buffer) {
|
||||||
ModifiableCommandAddress cur = this;
|
ModifiableCommandAddress cur = this;
|
||||||
ChildCommandAddress child;
|
ChildCommandAddress child;
|
||||||
while (buffer.hasNext()) {
|
while (buffer.hasNext()) {
|
||||||
child = cur.getChild(buffer.next());
|
child = cur.getChild(buffer.next());
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = child;
|
cur = child;
|
||||||
}
|
}
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModifiableCommandAddress getCommandTarget(CommandSender sender, ArgumentBuffer buffer) {
|
public ModifiableCommandAddress getCommandTarget(CommandSender sender, ArgumentBuffer buffer) {
|
||||||
ModifiableCommandAddress cur = this;
|
ModifiableCommandAddress cur = this;
|
||||||
ChildCommandAddress child;
|
ChildCommandAddress child;
|
||||||
while (buffer.hasNext()) {
|
while (buffer.hasNext()) {
|
||||||
child = cur.getChild(buffer.next());
|
child = cur.getChild(buffer.next());
|
||||||
if (child == null
|
if (child == null
|
||||||
|| (child.hasCommand() && !child.getCommand().isVisibleTo(sender))
|
|| (child.hasCommand() && !child.getCommand().isVisibleTo(sender))
|
||||||
|| (cur.hasCommand() && cur.getCommand().takePrecedenceOverSubcommand(buffer.peekPrevious(), buffer.getUnaffectingCopy()))) {
|
|| (cur.hasCommand() && cur.getCommand().takePrecedenceOverSubcommand(buffer.peekPrevious(), buffer.getUnaffectingCopy()))) {
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = child;
|
cur = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModifiableCommandAddress getCommandTarget(ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
public ModifiableCommandAddress getCommandTarget(ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
||||||
CommandSender sender = context.getSender();
|
CommandSender sender = context.getSender();
|
||||||
ModifiableCommandAddress cur = this;
|
ModifiableCommandAddress cur = this;
|
||||||
ChildCommandAddress child;
|
ChildCommandAddress child;
|
||||||
while (buffer.hasNext()) {
|
while (buffer.hasNext()) {
|
||||||
int cursor = buffer.getCursor();
|
int cursor = buffer.getCursor();
|
||||||
|
|
||||||
child = cur.getChild(context, buffer);
|
child = cur.getChild(context, buffer);
|
||||||
|
|
||||||
if (child == null
|
if (child == null
|
||||||
|| (context.isTabComplete() && !buffer.hasNext())
|
|| (context.isTabComplete() && !buffer.hasNext())
|
||||||
|| (child.hasCommand() && !child.getCommand().isVisibleTo(sender))
|
|| (child.hasCommand() && !child.getCommand().isVisibleTo(sender))
|
||||||
|| (cur.hasCommand() && cur.getCommand().takePrecedenceOverSubcommand(buffer.peekPrevious(), buffer.getUnaffectingCopy()))) {
|
|| (cur.hasCommand() && cur.getCommand().takePrecedenceOverSubcommand(buffer.peekPrevious(), buffer.getUnaffectingCopy()))) {
|
||||||
buffer.setCursor(cursor);
|
buffer.setCursor(cursor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = child;
|
cur = child;
|
||||||
|
|
||||||
context.setAddress(child);
|
context.setAddress(child);
|
||||||
if (child.hasCommand() && child.isCommandTrailing()) {
|
if (child.hasCommand() && child.isCommandTrailing()) {
|
||||||
child.getCommand().initializeAndFilterContext(context);
|
child.getCommand().initializeAndFilterContext(context);
|
||||||
child.getCommand().execute(context.getSender(), context);
|
child.getCommand().execute(context.getSender(), context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchCommand(CommandSender sender, String[] command) {
|
public boolean dispatchCommand(CommandSender sender, String[] command) {
|
||||||
return dispatchCommand(sender, new ArgumentBuffer(command));
|
return dispatchCommand(sender, new ArgumentBuffer(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchCommand(CommandSender sender, String usedLabel, String[] args) {
|
public boolean dispatchCommand(CommandSender sender, String usedLabel, String[] args) {
|
||||||
return dispatchCommand(sender, new ArgumentBuffer(usedLabel, args));
|
return dispatchCommand(sender, new ArgumentBuffer(usedLabel, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchCommand(CommandSender sender, ArgumentBuffer buffer) {
|
public boolean dispatchCommand(CommandSender sender, ArgumentBuffer buffer) {
|
||||||
ExecutionContext context = new ExecutionContext(sender, buffer, false);
|
ExecutionContext context = new ExecutionContext(sender, buffer, false);
|
||||||
|
|
||||||
ModifiableCommandAddress targetAddress = null;
|
ModifiableCommandAddress targetAddress = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
targetAddress = getCommandTarget(context, buffer);
|
targetAddress = getCommandTarget(context, buffer);
|
||||||
Command target = targetAddress.getCommand();
|
Command target = targetAddress.getCommand();
|
||||||
|
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
if (targetAddress.hasHelpCommand()) {
|
if (targetAddress.hasHelpCommand()) {
|
||||||
target = targetAddress.getHelpCommand().getCommand();
|
target = targetAddress.getHelpCommand().getCommand();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.setCommand(target);
|
context.setCommand(target);
|
||||||
|
|
||||||
if (!targetAddress.isCommandTrailing()) {
|
if (!targetAddress.isCommandTrailing()) {
|
||||||
target.initializeAndFilterContext(context);
|
target.initializeAndFilterContext(context);
|
||||||
String message = target.execute(sender, context);
|
String message = target.execute(sender, context);
|
||||||
if (message != null && !message.isEmpty()) {
|
if (message != null && !message.isEmpty()) {
|
||||||
context.sendMessage(EMessageType.RESULT, message);
|
context.sendMessage(EMessageType.RESULT, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
if (targetAddress == null) {
|
if (targetAddress == null) {
|
||||||
targetAddress = this;
|
targetAddress = this;
|
||||||
}
|
}
|
||||||
targetAddress.getChatHandler().handleException(sender, context, t);
|
targetAddress.getChatHandler().handleException(sender, context, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getTabCompletions(CommandSender sender, Location location, String[] args) {
|
public List<String> getTabCompletions(CommandSender sender, Location location, String[] args) {
|
||||||
return getTabCompletions(sender, location, new ArgumentBuffer(args));
|
return getTabCompletions(sender, location, new ArgumentBuffer(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getTabCompletions(CommandSender sender, String usedLabel, Location location, String[] args) {
|
public List<String> getTabCompletions(CommandSender sender, String usedLabel, Location location, String[] args) {
|
||||||
return getTabCompletions(sender, location, new ArgumentBuffer(usedLabel, args));
|
return getTabCompletions(sender, location, new ArgumentBuffer(usedLabel, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer) {
|
public List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer) {
|
||||||
ExecutionContext context = new ExecutionContext(sender, buffer, true);
|
ExecutionContext context = new ExecutionContext(sender, buffer, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ICommandAddress target = getCommandTarget(context, buffer);
|
ICommandAddress target = getCommandTarget(context, buffer);
|
||||||
|
|
||||||
List<String> out;
|
List<String> out;
|
||||||
if (target.hasCommand()) {
|
if (target.hasCommand()) {
|
||||||
context.setCommand(target.getCommand());
|
context.setCommand(target.getCommand());
|
||||||
target.getCommand().initializeAndFilterContext(context);
|
target.getCommand().initializeAndFilterContext(context);
|
||||||
out = target.getCommand().tabComplete(sender, context, location);
|
out = target.getCommand().tabComplete(sender, context, location);
|
||||||
} else {
|
} else {
|
||||||
out = Collections.emptyList();
|
out = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
int cursor = buffer.getCursor();
|
int cursor = buffer.getCursor();
|
||||||
String input;
|
String input;
|
||||||
if (cursor >= buffer.size()) {
|
if (cursor >= buffer.size()) {
|
||||||
input = "";
|
input = "";
|
||||||
} else {
|
} else {
|
||||||
input = buffer.get(cursor).toLowerCase();
|
input = buffer.get(cursor).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean wrapped = false;
|
boolean wrapped = false;
|
||||||
for (String child : target.getChildrenMainKeys()) {
|
for (String child : target.getChildrenMainKeys()) {
|
||||||
if (child.toLowerCase().startsWith(input)) {
|
if (child.toLowerCase().startsWith(input)) {
|
||||||
if (!wrapped) {
|
if (!wrapped) {
|
||||||
out = new ArrayList<>(out);
|
out = new ArrayList<>(out);
|
||||||
wrapped = true;
|
wrapped = true;
|
||||||
}
|
}
|
||||||
out.add(child);
|
out.add(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
} catch (CommandException ex) {
|
} catch (CommandException ex) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
package io.dico.dicore.command;
|
package io.dico.dicore.command;
|
||||||
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class Validate {
|
public class Validate {
|
||||||
|
|
||||||
private Validate() {
|
private Validate() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Contract("false, _ -> fail")
|
//@Contract("false, _ -> fail")
|
||||||
public static void isTrue(boolean expression, String failMessage) throws CommandException {
|
public static void isTrue(boolean expression, String failMessage) throws CommandException {
|
||||||
if (!expression) {
|
if (!expression) {
|
||||||
throw new CommandException(failMessage);
|
throw new CommandException(failMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Contract("null, _ -> fail")
|
//@Contract("null, _ -> fail")
|
||||||
public static void notNull(Object obj, String failMessage) throws CommandException {
|
public static void notNull(Object obj, String failMessage) throws CommandException {
|
||||||
Validate.isTrue(obj != null, failMessage);
|
Validate.isTrue(obj != null, failMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void isAuthorized(CommandSender sender, String permission, String failMessage) throws CommandException {
|
public static void isAuthorized(CommandSender sender, String permission, String failMessage) throws CommandException {
|
||||||
Validate.isTrue(sender.hasPermission(permission), failMessage);
|
Validate.isTrue(sender.hasPermission(permission), failMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void isAuthorized(CommandSender sender, String permission) throws CommandException {
|
public static void isAuthorized(CommandSender sender, String permission) throws CommandException {
|
||||||
Validate.isAuthorized(sender, permission, "You do not have permission to use that command");
|
Validate.isAuthorized(sender, permission, "You do not have permission to use that command");
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Contract("null -> fail")
|
//@Contract("null -> fail")
|
||||||
public static void isPlayer(CommandSender sender) throws CommandException {
|
public static void isPlayer(CommandSender sender) throws CommandException {
|
||||||
isTrue(sender instanceof Player, "That command can only be used by players");
|
isTrue(sender instanceof Player, "That command can only be used by players");
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Contract("null -> fail")
|
//@Contract("null -> fail")
|
||||||
public static void isConsole(CommandSender sender) throws CommandException {
|
public static void isConsole(CommandSender sender) throws CommandException {
|
||||||
isTrue(sender instanceof ConsoleCommandSender, "That command can only be used by the console");
|
isTrue(sender instanceof ConsoleCommandSender, "That command can only be used by the console");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T returnIfPresent(Optional<T> maybe, String failMessage) throws CommandException {
|
public static <T> T returnIfPresent(Optional<T> maybe, String failMessage) throws CommandException {
|
||||||
if (!maybe.isPresent()) {
|
if (!maybe.isPresent()) {
|
||||||
throw new CommandException(failMessage);
|
throw new CommandException(failMessage);
|
||||||
}
|
}
|
||||||
return maybe.get();
|
return maybe.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import io.dico.dicore.command.parameter.type.ParameterConfig;
|
import io.dico.dicore.command.parameter.type.ParameterConfig;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
public @interface BigRange {
|
public @interface BigRange {
|
||||||
Class<?> MEMORY_CLASS = Memory.class;
|
Class<?> MEMORY_CLASS = Memory.class;
|
||||||
ParameterConfig<BigRange, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(BigRange.class);
|
ParameterConfig<BigRange, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(BigRange.class);
|
||||||
Memory DEFAULT = new Memory("MIN", "MAX", "0");
|
Memory DEFAULT = new Memory("MIN", "MAX", "0");
|
||||||
|
|
||||||
String min() default "MIN";
|
String min() default "MIN";
|
||||||
|
|
||||||
String max() default "MAX";
|
String max() default "MAX";
|
||||||
|
|
||||||
String defaultValue() default "0";
|
String defaultValue() default "0";
|
||||||
|
|
||||||
class Memory {
|
class Memory {
|
||||||
private final String min;
|
private final String min;
|
||||||
private final String max;
|
private final String max;
|
||||||
private final String defaultValue;
|
private final String defaultValue;
|
||||||
|
|
||||||
public Memory(BigRange range) {
|
public Memory(BigRange range) {
|
||||||
this(range.min(), range.max(), range.defaultValue());
|
this(range.min(), range.max(), range.defaultValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Memory(String min, String max, String defaultValue) {
|
public Memory(String min, String max, String defaultValue) {
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String min() {
|
public String min() {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String max() {
|
public String max() {
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String defaultValue() {
|
public String defaultValue() {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface Cmd {
|
public @interface Cmd {
|
||||||
|
|
||||||
String value();
|
String value();
|
||||||
|
|
||||||
String[] aliases() default {};
|
String[] aliases() default {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to mark methods that register a parameter type to the localized selector for use in reflective commands.
|
* Annotation to mark methods that register a parameter type to the localized selector for use in reflective commands.
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface CmdParamType {
|
public @interface CmdParamType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this flag is set, the type is registered without its annotation type.
|
* If this flag is set, the type is registered without its annotation type.
|
||||||
* As a result, the {@link IParameterTypeSelector} is more likely to select it (faster).
|
* As a result, the {@link IParameterTypeSelector} is more likely to select it (faster).
|
||||||
* This is irrelevant if there is no annotation type or param config.
|
* This is irrelevant if there is no annotation type or param config.
|
||||||
*
|
*
|
||||||
* @return true if this parameter type should be registered without its annotation type too
|
* @return true if this parameter type should be registered without its annotation type too
|
||||||
*/
|
*/
|
||||||
boolean infolessAlias() default false;
|
boolean infolessAlias() default false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
public class CommandAnnotationUtils {
|
public class CommandAnnotationUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the short description from a {@link Desc} annotation.
|
* Get the short description from a {@link Desc} annotation.
|
||||||
* If {@link Desc#shortVersion()} is given, returns that.
|
* If {@link Desc#shortVersion()} is given, returns that.
|
||||||
* Otherwise, returns the first element of {@link Desc#value()}
|
* Otherwise, returns the first element of {@link Desc#value()}
|
||||||
* If neither is available, returns null.
|
* If neither is available, returns null.
|
||||||
*
|
*
|
||||||
* @param desc the annotation
|
* @param desc the annotation
|
||||||
* @return the short description
|
* @return the short description
|
||||||
*/
|
*/
|
||||||
public static String getShortDescription(Desc desc) {
|
public static String getShortDescription(Desc desc) {
|
||||||
String descString;
|
String descString;
|
||||||
if (desc == null) {
|
if (desc == null) {
|
||||||
descString = null;
|
descString = null;
|
||||||
} else if (!desc.shortVersion().isEmpty()) {
|
} else if (!desc.shortVersion().isEmpty()) {
|
||||||
descString = desc.shortVersion();
|
descString = desc.shortVersion();
|
||||||
} else if (desc.value().length > 0) {
|
} else if (desc.value().length > 0) {
|
||||||
descString = desc.value()[0];
|
descString = desc.value()[0];
|
||||||
if (desc.value().length > 1) {
|
if (desc.value().length > 1) {
|
||||||
//System.out.println("[Command Warning] Multiline descriptions not supported here. Keep it short for: " + targetIdentifier);
|
//System.out.println("[Command Warning] Multiline descriptions not supported here. Keep it short for: " + targetIdentifier);
|
||||||
}
|
}
|
||||||
if (descString != null && descString.isEmpty()) {
|
if (descString != null && descString.isEmpty()) {
|
||||||
descString = null;
|
descString = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
descString = null;
|
descString = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return descString;
|
return descString;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Desc {
|
public @interface Desc {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiline description if {@link #shortVersion} is set.
|
* Multiline description if {@link #shortVersion} is set.
|
||||||
* Otherwise, this should be an array with one element (aka, you don't have to add array brackets).
|
* Otherwise, this should be an array with one element (aka, you don't have to add array brackets).
|
||||||
*
|
*
|
||||||
* @return the multiline description.
|
* @return the multiline description.
|
||||||
* @see CommandAnnotationUtils#getShortDescription(Desc)
|
* @see CommandAnnotationUtils#getShortDescription(Desc)
|
||||||
*/
|
*/
|
||||||
String[] value();
|
String[] value();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Short description, use if {@link #value} is multi-line.
|
* Short description, use if {@link #value} is multi-line.
|
||||||
* To get a short description from a {@link Desc}, you should use {@link CommandAnnotationUtils#getShortDescription(Desc)}
|
* To get a short description from a {@link Desc}, you should use {@link CommandAnnotationUtils#getShortDescription(Desc)}
|
||||||
*
|
*
|
||||||
* @return short description
|
* @return short description
|
||||||
* @see CommandAnnotationUtils#getShortDescription(Desc)
|
* @see CommandAnnotationUtils#getShortDescription(Desc)
|
||||||
*/
|
*/
|
||||||
String shortVersion() default "";
|
String shortVersion() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
public @interface Flag {
|
public @interface Flag {
|
||||||
|
|
||||||
String value() default "";
|
String value() default "";
|
||||||
|
|
||||||
String permission() default "";
|
String permission() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface GenerateCommands {
|
public @interface GenerateCommands {
|
||||||
|
|
||||||
String[] value() default {"help"};
|
String[] value() default {"help"};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,68 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation to define sub-groups of the group registered reflectively from all methods in a class.
|
* Annotation to define sub-groups of the group registered reflectively from all methods in a class.
|
||||||
* <p>
|
* <p>
|
||||||
* Commands are selected for grouping by matching their method's names to a regular expression.
|
* Commands are selected for grouping by matching their method's names to a regular expression.
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
public @interface GroupMatchedCommands {
|
public @interface GroupMatchedCommands {
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@interface GroupEntry {
|
@interface GroupEntry {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regular expression to match method names for this group
|
* Regular expression to match method names for this group
|
||||||
* Must be non-empty
|
* Must be non-empty
|
||||||
*
|
*
|
||||||
* @return the regular expression
|
* @return the regular expression
|
||||||
*/
|
*/
|
||||||
String regex();
|
String regex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name or main key of the sub-group or address
|
* The name or main key of the sub-group or address
|
||||||
* Must be non-empty
|
* Must be non-empty
|
||||||
*
|
*
|
||||||
* @return the group name
|
* @return the group name
|
||||||
*/
|
*/
|
||||||
String group();
|
String group();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The aliases for the sub-group
|
* The aliases for the sub-group
|
||||||
*
|
*
|
||||||
* @return the group aliases
|
* @return the group aliases
|
||||||
*/
|
*/
|
||||||
String[] groupAliases() default {};
|
String[] groupAliases() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated (predefined) commands for the sub-group
|
* Generated (predefined) commands for the sub-group
|
||||||
*/
|
*/
|
||||||
String[] generatedCommands() default {};
|
String[] generatedCommands() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Desc
|
* @see Desc
|
||||||
*/
|
*/
|
||||||
String[] description() default {};
|
String[] description() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Desc
|
* @see Desc
|
||||||
*/
|
*/
|
||||||
String shortDescription() default "";
|
String shortDescription() default "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The defined groups.
|
* The defined groups.
|
||||||
* If a method name matches the regex of multiple groups,
|
* If a method name matches the regex of multiple groups,
|
||||||
* groups are prioritized by the order in which they appear in this array.
|
* groups are prioritized by the order in which they appear in this array.
|
||||||
*
|
*
|
||||||
* @return the defined groups
|
* @return the defined groups
|
||||||
*/
|
*/
|
||||||
GroupEntry[] value();
|
GroupEntry[] value();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
public @interface NamedArg {
|
public @interface NamedArg {
|
||||||
|
|
||||||
String value();
|
String value();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public @interface PreprocessArgs {
|
public @interface PreprocessArgs {
|
||||||
|
|
||||||
String tokens() default "\"\"";
|
String tokens() default "\"\"";
|
||||||
|
|
||||||
char escapeChar() default '\\';
|
char escapeChar() default '\\';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +1,67 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.Validate;
|
import io.dico.dicore.command.Validate;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterConfig;
|
import io.dico.dicore.command.parameter.type.ParameterConfig;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.PARAMETER)
|
@Target(ElementType.PARAMETER)
|
||||||
public @interface Range {
|
public @interface Range {
|
||||||
Class<?> MEMORY_CLASS = Memory.class;
|
Class<?> MEMORY_CLASS = Memory.class;
|
||||||
ParameterConfig<Range, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(Range.class);
|
ParameterConfig<Range, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(Range.class);
|
||||||
Memory DEFAULT = new Memory(-Double.MAX_VALUE, Double.MAX_VALUE, 0);
|
Memory DEFAULT = new Memory(-Double.MAX_VALUE, Double.MAX_VALUE, 0);
|
||||||
|
|
||||||
double min() default -Double.MAX_VALUE;
|
double min() default -Double.MAX_VALUE;
|
||||||
|
|
||||||
double max() default Double.MAX_VALUE;
|
double max() default Double.MAX_VALUE;
|
||||||
|
|
||||||
double defaultValue() default 0;
|
double defaultValue() default 0;
|
||||||
|
|
||||||
class Memory {
|
class Memory {
|
||||||
private final double min;
|
private final double min;
|
||||||
private final double max;
|
private final double max;
|
||||||
private final double defaultValue;
|
private final double defaultValue;
|
||||||
|
|
||||||
public Memory(Range range) {
|
public Memory(Range range) {
|
||||||
this(range.min(), range.max(), range.defaultValue());
|
this(range.min(), range.max(), range.defaultValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Memory(double min, double max, double defaultValue) {
|
public Memory(double min, double max, double defaultValue) {
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double min() {
|
public double min() {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double max() {
|
public double max() {
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double defaultValue() {
|
public double defaultValue() {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validate(Number x, String failMessage) throws CommandException {
|
public void validate(Number x, String failMessage) throws CommandException {
|
||||||
Validate.isTrue(valid(x), failMessage);
|
Validate.isTrue(valid(x), failMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean valid(Number x) {
|
public boolean valid(Number x) {
|
||||||
double d = x.doubleValue();
|
double d = x.doubleValue();
|
||||||
return min <= d && d <= max;
|
return min <= d && d <= max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDefault() {
|
public boolean isDefault() {
|
||||||
return this == DEFAULT || (min == DEFAULT.min && max == DEFAULT.max && defaultValue == DEFAULT.defaultValue);
|
return this == DEFAULT || (min == DEFAULT.min && max == DEFAULT.max && defaultValue == DEFAULT.defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface RequireConsole {
|
public @interface RequireConsole {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface RequireParameters {
|
public @interface RequireParameters {
|
||||||
|
|
||||||
int value();
|
int value();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import io.dico.dicore.command.IContextFilter;
|
import io.dico.dicore.command.IContextFilter;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this annotation is not present, inheriting permissions is default.
|
* If this annotation is not present, inheriting permissions is default.
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface RequirePermissions {
|
public @interface RequirePermissions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any permissions that must be present on the sender
|
* Any permissions that must be present on the sender
|
||||||
*
|
*
|
||||||
* @return an array of permission nodes
|
* @return an array of permission nodes
|
||||||
*/
|
*/
|
||||||
String[] value();
|
String[] value();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether permissions should (also) be inherited from the parent.
|
* Whether permissions should (also) be inherited from the parent.
|
||||||
* This uses {@link IContextFilter#INHERIT_PERMISSIONS}
|
* This uses {@link IContextFilter#INHERIT_PERMISSIONS}
|
||||||
* This is true by default.
|
* This is true by default.
|
||||||
*
|
*
|
||||||
* @return true if permissions should be inherited.
|
* @return true if permissions should be inherited.
|
||||||
*/
|
*/
|
||||||
boolean inherit() default true;
|
boolean inherit() default true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package io.dico.dicore.command.annotation;
|
package io.dico.dicore.command.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface RequirePlayer {
|
public @interface RequirePlayer {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,94 +1,94 @@
|
|||||||
package io.dico.dicore.command.chat;
|
package io.dico.dicore.command.chat;
|
||||||
|
|
||||||
import io.dico.dicore.Formatting;
|
import io.dico.dicore.Formatting;
|
||||||
import io.dico.dicore.command.EMessageType;
|
import io.dico.dicore.command.EMessageType;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.chat.help.HelpPages;
|
import io.dico.dicore.command.chat.help.HelpPages;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class AbstractChatHandler implements IChatHandler {
|
public class AbstractChatHandler implements IChatHandler {
|
||||||
private @NotNull HelpPages helpPages;
|
private @NotNull HelpPages helpPages;
|
||||||
|
|
||||||
public AbstractChatHandler(@NotNull HelpPages helpPages) {
|
public AbstractChatHandler(@NotNull HelpPages helpPages) {
|
||||||
this.helpPages = helpPages;
|
this.helpPages = helpPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractChatHandler() {
|
public AbstractChatHandler() {
|
||||||
this(HelpPages.newDefaultHelpPages());
|
this(HelpPages.newDefaultHelpPages());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public HelpPages getHelpPages() {
|
public HelpPages getHelpPages() {
|
||||||
return helpPages;
|
return helpPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHelpPages(@NotNull HelpPages helpPages) {
|
public void setHelpPages(@NotNull HelpPages helpPages) {
|
||||||
this.helpPages = helpPages;
|
this.helpPages = helpPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Formatting getChatFormatForType(EMessageType type) {
|
public Formatting getChatFormatForType(EMessageType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EXCEPTION:
|
case EXCEPTION:
|
||||||
case BAD_NEWS:
|
case BAD_NEWS:
|
||||||
return Formatting.RED;
|
return Formatting.RED;
|
||||||
case INSTRUCTION:
|
case INSTRUCTION:
|
||||||
case NEUTRAL:
|
case NEUTRAL:
|
||||||
return Formatting.GRAY;
|
return Formatting.GRAY;
|
||||||
case CUSTOM:
|
case CUSTOM:
|
||||||
return Formatting.WHITE;
|
return Formatting.WHITE;
|
||||||
case INFORMATIVE:
|
case INFORMATIVE:
|
||||||
return Formatting.AQUA;
|
return Formatting.AQUA;
|
||||||
case RESULT:
|
case RESULT:
|
||||||
default:
|
default:
|
||||||
case GOOD_NEWS:
|
case GOOD_NEWS:
|
||||||
return Formatting.GREEN;
|
return Formatting.GREEN;
|
||||||
case WARNING:
|
case WARNING:
|
||||||
return Formatting.YELLOW;
|
return Formatting.YELLOW;
|
||||||
|
|
||||||
case DESCRIPTION:
|
case DESCRIPTION:
|
||||||
return Formatting.GREEN;
|
return Formatting.GREEN;
|
||||||
case SYNTAX:
|
case SYNTAX:
|
||||||
return Formatting.AQUA;
|
return Formatting.AQUA;
|
||||||
case HIGHLIGHT:
|
case HIGHLIGHT:
|
||||||
return Formatting.RED;
|
return Formatting.RED;
|
||||||
case SUBCOMMAND:
|
case SUBCOMMAND:
|
||||||
return Formatting.GRAY;
|
return Formatting.GRAY;
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
return Formatting.YELLOW;
|
return Formatting.YELLOW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessagePrefixForType(EMessageType type) {
|
public String getMessagePrefixForType(EMessageType type) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String createMessage(EMessageType type, String message) {
|
protected String createMessage(EMessageType type, String message) {
|
||||||
if (message == null || message.isEmpty()) return null;
|
if (message == null || message.isEmpty()) return null;
|
||||||
return getMessagePrefixForType(type) + getChatFormatForType(type) + message;
|
return getMessagePrefixForType(type) + getChatFormatForType(type) + message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createMessage(ExecutionContext context, EMessageType type, String message) {
|
public String createMessage(ExecutionContext context, EMessageType type, String message) {
|
||||||
return createMessage(type, message);
|
return createMessage(type, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createMessage(CommandSender sender, EMessageType type, String message) {
|
public String createMessage(CommandSender sender, EMessageType type, String message) {
|
||||||
return createMessage(type, message);
|
return createMessage(type, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
|
public String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
|
||||||
return helpPages.getHelpPage(sender, context, address, page);
|
return helpPages.getHelpPage(sender, context, address, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
|
public String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
|
||||||
return helpPages.getSyntax(sender, context, address);
|
return helpPages.getSyntax(sender, context, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
package io.dico.dicore.command.chat;
|
package io.dico.dicore.command.chat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static factory methods for {@link IChatHandler}
|
* Static factory methods for {@link IChatHandler}
|
||||||
*/
|
*/
|
||||||
public class ChatHandlers {
|
public class ChatHandlers {
|
||||||
private static final IChatHandler defaultChat;
|
private static final IChatHandler defaultChat;
|
||||||
|
|
||||||
private ChatHandlers() {
|
private ChatHandlers() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IChatHandler defaultChat() {
|
public static IChatHandler defaultChat() {
|
||||||
return defaultChat;
|
return defaultChat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
defaultChat = new AbstractChatHandler();
|
defaultChat = new AbstractChatHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
package io.dico.dicore.command.chat;
|
package io.dico.dicore.command.chat;
|
||||||
|
|
||||||
import io.dico.dicore.Formatting;
|
import io.dico.dicore.Formatting;
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.EMessageType;
|
import io.dico.dicore.command.EMessageType;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
//TODO add methods to send JSON messages
|
//TODO add methods to send JSON messages
|
||||||
public interface IChatHandler {
|
public interface IChatHandler {
|
||||||
|
|
||||||
default void sendMessage(ExecutionContext context, EMessageType type, String message) {
|
default void sendMessage(ExecutionContext context, EMessageType type, String message) {
|
||||||
message = createMessage(context, type, message);
|
message = createMessage(context, type, message);
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
context.getSender().sendMessage(message);
|
context.getSender().sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendMessage(CommandSender sender, EMessageType type, String message) {
|
default void sendMessage(CommandSender sender, EMessageType type, String message) {
|
||||||
message = createMessage(sender, type, message);
|
message = createMessage(sender, type, message);
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
sender.sendMessage(message);
|
sender.sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default void handleCommandException(CommandSender sender, ExecutionContext context, CommandException exception) {
|
default void handleCommandException(CommandSender sender, ExecutionContext context, CommandException exception) {
|
||||||
sendMessage(context, EMessageType.EXCEPTION, exception.getMessage());
|
sendMessage(context, EMessageType.EXCEPTION, exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
default void handleException(CommandSender sender, ExecutionContext context, Throwable exception) {
|
default void handleException(CommandSender sender, ExecutionContext context, Throwable exception) {
|
||||||
if (exception instanceof CommandException) {
|
if (exception instanceof CommandException) {
|
||||||
handleCommandException(sender, context, (CommandException) exception);
|
handleCommandException(sender, context, (CommandException) exception);
|
||||||
} else {
|
} else {
|
||||||
sendMessage(sender, EMessageType.EXCEPTION, "An internal error occurred whilst executing this command");
|
sendMessage(sender, EMessageType.EXCEPTION, "An internal error occurred whilst executing this command");
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
|
default void sendHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
|
||||||
sender.sendMessage(createHelpMessage(sender, context, address, page));
|
sender.sendMessage(createHelpMessage(sender, context, address, page));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void sendSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
|
default void sendSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
|
||||||
sender.sendMessage(createSyntaxMessage(sender, context, address));
|
sender.sendMessage(createSyntaxMessage(sender, context, address));
|
||||||
}
|
}
|
||||||
|
|
||||||
Formatting getChatFormatForType(EMessageType type);
|
Formatting getChatFormatForType(EMessageType type);
|
||||||
|
|
||||||
String getMessagePrefixForType(EMessageType type);
|
String getMessagePrefixForType(EMessageType type);
|
||||||
|
|
||||||
String createMessage(ExecutionContext context, EMessageType type, String message);
|
String createMessage(ExecutionContext context, EMessageType type, String message);
|
||||||
|
|
||||||
String createMessage(CommandSender sender, EMessageType type, String message);
|
String createMessage(CommandSender sender, EMessageType type, String message);
|
||||||
|
|
||||||
String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page);
|
String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page);
|
||||||
|
|
||||||
String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address);
|
String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,92 +1,92 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.chat.help.defaults.*;
|
import io.dico.dicore.command.chat.help.defaults.*;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HelpPages {
|
public class HelpPages {
|
||||||
private @NotNull IPageBuilder pageBuilder;
|
private @NotNull IPageBuilder pageBuilder;
|
||||||
private @NotNull IPageLayout pageLayout;
|
private @NotNull IPageLayout pageLayout;
|
||||||
private int pageLength;
|
private int pageLength;
|
||||||
private @NotNull List<IHelpTopic> helpTopics;
|
private @NotNull List<IHelpTopic> helpTopics;
|
||||||
private @NotNull IHelpTopic syntaxTopic;
|
private @NotNull IHelpTopic syntaxTopic;
|
||||||
|
|
||||||
public HelpPages(@NotNull IPageBuilder pageBuilder, @NotNull IPageLayout pageLayout, int pageLength, @NotNull IHelpTopic syntaxTopic, @NotNull List<IHelpTopic> helpTopics) {
|
public HelpPages(@NotNull IPageBuilder pageBuilder, @NotNull IPageLayout pageLayout, int pageLength, @NotNull IHelpTopic syntaxTopic, @NotNull List<IHelpTopic> helpTopics) {
|
||||||
this.pageBuilder = pageBuilder;
|
this.pageBuilder = pageBuilder;
|
||||||
this.pageLayout = pageLayout;
|
this.pageLayout = pageLayout;
|
||||||
this.pageLength = pageLength;
|
this.pageLength = pageLength;
|
||||||
this.syntaxTopic = syntaxTopic;
|
this.syntaxTopic = syntaxTopic;
|
||||||
this.helpTopics = helpTopics;
|
this.helpTopics = helpTopics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelpPages(IPageBuilder pageBuilder, IPageLayout pageLayout, int pageLength, IHelpTopic syntaxTopic, IHelpTopic... helpTopics) {
|
public HelpPages(IPageBuilder pageBuilder, IPageLayout pageLayout, int pageLength, IHelpTopic syntaxTopic, IHelpTopic... helpTopics) {
|
||||||
this(pageBuilder, pageLayout, pageLength, syntaxTopic, new ArrayList<>(Arrays.asList(helpTopics)));
|
this(pageBuilder, pageLayout, pageLength, syntaxTopic, new ArrayList<>(Arrays.asList(helpTopics)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("RedundantArrayCreation")
|
@SuppressWarnings("RedundantArrayCreation")
|
||||||
public static HelpPages newDefaultHelpPages() {
|
public static HelpPages newDefaultHelpPages() {
|
||||||
IHelpTopic syntaxTopic = new SyntaxHelpTopic();
|
IHelpTopic syntaxTopic = new SyntaxHelpTopic();
|
||||||
return new HelpPages(new DefaultPageBuilder(), new DefaultPageLayout(), 12,
|
return new HelpPages(new DefaultPageBuilder(), new DefaultPageLayout(), 12,
|
||||||
syntaxTopic, new IHelpTopic[]{new DescriptionHelpTopic(), syntaxTopic, new SubcommandsHelpTopic()});
|
syntaxTopic, new IHelpTopic[]{new DescriptionHelpTopic(), syntaxTopic, new SubcommandsHelpTopic()});
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull IPageBuilder getPageBuilder() {
|
public @NotNull IPageBuilder getPageBuilder() {
|
||||||
return pageBuilder;
|
return pageBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPageBuilder(@NotNull IPageBuilder pageBuilder) {
|
public void setPageBuilder(@NotNull IPageBuilder pageBuilder) {
|
||||||
this.pageBuilder = pageBuilder;
|
this.pageBuilder = pageBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull IPageLayout getPageLayout() {
|
public @NotNull IPageLayout getPageLayout() {
|
||||||
return pageLayout;
|
return pageLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPageLayout(@NotNull IPageLayout pageLayout) {
|
public void setPageLayout(@NotNull IPageLayout pageLayout) {
|
||||||
this.pageLayout = pageLayout;
|
this.pageLayout = pageLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPageLength() {
|
public int getPageLength() {
|
||||||
return pageLength;
|
return pageLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPageLength(int pageLength) {
|
public void setPageLength(int pageLength) {
|
||||||
this.pageLength = pageLength;
|
this.pageLength = pageLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull IHelpTopic getSyntaxTopic() {
|
public @NotNull IHelpTopic getSyntaxTopic() {
|
||||||
return syntaxTopic;
|
return syntaxTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSyntaxTopic(@NotNull IHelpTopic syntaxTopic) {
|
public void setSyntaxTopic(@NotNull IHelpTopic syntaxTopic) {
|
||||||
this.syntaxTopic = syntaxTopic;
|
this.syntaxTopic = syntaxTopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<IHelpTopic> getHelpTopics() {
|
public List<IHelpTopic> getHelpTopics() {
|
||||||
return helpTopics;
|
return helpTopics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHelpTopics(@NotNull List<IHelpTopic> helpTopics) {
|
public void setHelpTopics(@NotNull List<IHelpTopic> helpTopics) {
|
||||||
this.helpTopics = helpTopics;
|
this.helpTopics = helpTopics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String getHelpPage(Permissible viewer, ExecutionContext context, ICommandAddress address, int page) {
|
public @NotNull String getHelpPage(Permissible viewer, ExecutionContext context, ICommandAddress address, int page) {
|
||||||
return pageBuilder.getPage(helpTopics, pageLayout, address, viewer, context, page, pageLength);
|
return pageBuilder.getPage(helpTopics, pageLayout, address, viewer, context, page, pageLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String getSyntax(Permissible viewer, ExecutionContext context, ICommandAddress address) {
|
public @NotNull String getSyntax(Permissible viewer, ExecutionContext context, ICommandAddress address) {
|
||||||
List<IHelpComponent> components = syntaxTopic.getComponents(address, viewer, context, false);
|
List<IHelpComponent> components = syntaxTopic.getComponents(address, viewer, context, false);
|
||||||
if (components.isEmpty()) {
|
if (components.isEmpty()) {
|
||||||
return getHelpPage(viewer, context, address, 1);
|
return getHelpPage(viewer, context, address, 1);
|
||||||
}
|
}
|
||||||
return DefaultPageBuilder.combine(components);
|
return DefaultPageBuilder.combine(components);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class HelpTopicModifier implements IHelpTopic {
|
public abstract class HelpTopicModifier implements IHelpTopic {
|
||||||
private final IHelpTopic delegate;
|
private final IHelpTopic delegate;
|
||||||
|
|
||||||
public HelpTopicModifier(IHelpTopic delegate) {
|
public HelpTopicModifier(IHelpTopic delegate) {
|
||||||
this.delegate = Objects.requireNonNull(delegate);
|
this.delegate = Objects.requireNonNull(delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
||||||
return modify(delegate.getComponents(target, viewer, context, true), target, viewer, context);
|
return modify(delegate.getComponents(target, viewer, context, true), target, viewer, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context);
|
protected abstract List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
public interface IHelpComponent {
|
public interface IHelpComponent {
|
||||||
|
|
||||||
int lineCount();
|
int lineCount();
|
||||||
|
|
||||||
void appendTo(StringBuilder sb);
|
void appendTo(StringBuilder sb);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IHelpTopic {
|
public interface IHelpTopic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the components of this help topic
|
* Get the components of this help topic
|
||||||
*
|
*
|
||||||
* @param target The address of the command to provide help about
|
* @param target The address of the command to provide help about
|
||||||
* @param viewer The permissible that the page will be shown to (null -> choose a default set).
|
* @param viewer The permissible that the page will be shown to (null -> choose a default set).
|
||||||
* @param context Context of the command execution
|
* @param context Context of the command execution
|
||||||
* @param isForPage A boolean indicating if the components are to be used in a page (for help)
|
* @param isForPage A boolean indicating if the components are to be used in a page (for help)
|
||||||
* @return a mutable list of components to include in the help pages
|
* @return a mutable list of components to include in the help pages
|
||||||
*/
|
*/
|
||||||
List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage);
|
List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
public interface IPageBorder extends IHelpComponent {
|
public interface IPageBorder extends IHelpComponent {
|
||||||
|
|
||||||
void setPageCount(int pageCount);
|
void setPageCount(int pageCount);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IPageBuilder {
|
public interface IPageBuilder {
|
||||||
|
|
||||||
String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum, int pageLen);
|
String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum, int pageLen);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
public interface IPageLayout {
|
public interface IPageLayout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the page borders for a help page
|
* Get the page borders for a help page
|
||||||
*
|
*
|
||||||
* @param target the address that help is displayed for
|
* @param target the address that help is displayed for
|
||||||
* @param viewer the viewer of the help page, or null if irrelevant
|
* @param viewer the viewer of the help page, or null if irrelevant
|
||||||
* @param context the context of the execution
|
* @param context the context of the execution
|
||||||
* @param pageNum the page number as displayed in the help page (so it's 1-bound and not 0-bound)
|
* @param pageNum the page number as displayed in the help page (so it's 1-bound and not 0-bound)
|
||||||
* @return the page borders.
|
* @return the page borders.
|
||||||
*/
|
*/
|
||||||
PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum);
|
PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,76 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class PageBorders {
|
public class PageBorders {
|
||||||
private final IPageBorder header, footer;
|
private final IPageBorder header, footer;
|
||||||
|
|
||||||
public PageBorders(IPageBorder header, IPageBorder footer) {
|
public PageBorders(IPageBorder header, IPageBorder footer) {
|
||||||
this.header = header;
|
this.header = header;
|
||||||
this.footer = footer;
|
this.footer = footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPageBorder getHeader() {
|
public IPageBorder getHeader() {
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPageBorder getFooter() {
|
public IPageBorder getFooter() {
|
||||||
return footer;
|
return footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IPageBorder simpleBorder(String... lines) {
|
public static IPageBorder simpleBorder(String... lines) {
|
||||||
return new SimplePageBorder(lines);
|
return new SimplePageBorder(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IPageBorder disappearingBorder(int pageNum, String... lines) {
|
public static IPageBorder disappearingBorder(int pageNum, String... lines) {
|
||||||
return disappearingBorder(pageNum, 0, lines);
|
return disappearingBorder(pageNum, 0, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IPageBorder disappearingBorder(int pageNum, int keptLines, String... lines) {
|
public static IPageBorder disappearingBorder(int pageNum, int keptLines, String... lines) {
|
||||||
return new DisappearingPageBorder(pageNum, keptLines, lines);
|
return new DisappearingPageBorder(pageNum, keptLines, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SimplePageBorder extends SimpleHelpComponent implements IPageBorder {
|
static class SimplePageBorder extends SimpleHelpComponent implements IPageBorder {
|
||||||
private final String replacedSequence;
|
private final String replacedSequence;
|
||||||
|
|
||||||
public SimplePageBorder(String replacedSequence, String... lines) {
|
public SimplePageBorder(String replacedSequence, String... lines) {
|
||||||
super(lines);
|
super(lines);
|
||||||
this.replacedSequence = replacedSequence;
|
this.replacedSequence = replacedSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimplePageBorder(String... lines) {
|
public SimplePageBorder(String... lines) {
|
||||||
super(lines);
|
super(lines);
|
||||||
this.replacedSequence = "%pageCount%";
|
this.replacedSequence = "%pageCount%";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPageCount(int pageCount) {
|
public void setPageCount(int pageCount) {
|
||||||
String[] lines = this.lines;
|
String[] lines = this.lines;
|
||||||
for (int i = 0; i < lines.length; i++) {
|
for (int i = 0; i < lines.length; i++) {
|
||||||
lines[i] = lines[i].replace(replacedSequence, Integer.toString(pageCount));
|
lines[i] = lines[i].replace(replacedSequence, Integer.toString(pageCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class DisappearingPageBorder extends SimpleHelpComponent implements IPageBorder {
|
static class DisappearingPageBorder extends SimpleHelpComponent implements IPageBorder {
|
||||||
private final int pageNum;
|
private final int pageNum;
|
||||||
private final int keptLines;
|
private final int keptLines;
|
||||||
|
|
||||||
public DisappearingPageBorder(int pageNum, int keptLines, String... lines) {
|
public DisappearingPageBorder(int pageNum, int keptLines, String... lines) {
|
||||||
super(lines);
|
super(lines);
|
||||||
this.pageNum = pageNum;
|
this.pageNum = pageNum;
|
||||||
this.keptLines = keptLines;
|
this.keptLines = keptLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPageCount(int pageCount) {
|
public void setPageCount(int pageCount) {
|
||||||
if (pageCount == pageNum) {
|
if (pageCount == pageNum) {
|
||||||
String[] lines = this.lines;
|
String[] lines = this.lines;
|
||||||
this.lines = Arrays.copyOfRange(lines, Math.max(0, lines.length - keptLines), lines.length);
|
this.lines = Arrays.copyOfRange(lines, Math.max(0, lines.length - keptLines), lines.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package io.dico.dicore.command.chat.help;
|
package io.dico.dicore.command.chat.help;
|
||||||
|
|
||||||
public class SimpleHelpComponent implements IHelpComponent {
|
public class SimpleHelpComponent implements IHelpComponent {
|
||||||
String[] lines;
|
String[] lines;
|
||||||
|
|
||||||
public SimpleHelpComponent(String... lines) {
|
public SimpleHelpComponent(String... lines) {
|
||||||
this.lines = lines;
|
this.lines = lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lineCount() {
|
public int lineCount() {
|
||||||
return lines.length;
|
return lines.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendTo(StringBuilder sb) {
|
public void appendTo(StringBuilder sb) {
|
||||||
String[] lines = this.lines;
|
String[] lines = this.lines;
|
||||||
int len = lines.length;
|
int len = lines.length;
|
||||||
if (0 < len) {
|
if (0 < len) {
|
||||||
sb.append(lines[0]);
|
sb.append(lines[0]);
|
||||||
}
|
}
|
||||||
for (int i = 1; i < len; i++) {
|
for (int i = 1; i < len; i++) {
|
||||||
sb.append('\n').append(lines[i]);
|
sb.append('\n').append(lines[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +1,115 @@
|
|||||||
package io.dico.dicore.command.chat.help.defaults;
|
package io.dico.dicore.command.chat.help.defaults;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.chat.help.*;
|
import io.dico.dicore.command.chat.help.*;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
public class DefaultPageBuilder implements IPageBuilder {
|
public class DefaultPageBuilder implements IPageBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target,
|
public String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target,
|
||||||
Permissible viewer, ExecutionContext context, int pageNum, int pageLen) {
|
Permissible viewer, ExecutionContext context, int pageNum, int pageLen) {
|
||||||
if (pageLen <= 0 || pageNum < 0) {
|
if (pageLen <= 0 || pageNum < 0) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IHelpComponent> components = new LinkedList<>();
|
List<IHelpComponent> components = new LinkedList<>();
|
||||||
for (IHelpTopic topic : helpTopics) {
|
for (IHelpTopic topic : helpTopics) {
|
||||||
components.addAll(topic.getComponents(target, viewer, context, true));
|
components.addAll(topic.getComponents(target, viewer, context, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
PageBorders pageBorders = null;
|
PageBorders pageBorders = null;
|
||||||
int componentStartIdx = -1;
|
int componentStartIdx = -1;
|
||||||
int componentEndIdx = -1;
|
int componentEndIdx = -1;
|
||||||
int totalPageCount = 0;
|
int totalPageCount = 0;
|
||||||
int curPageLines = 0;
|
int curPageLines = 0;
|
||||||
|
|
||||||
ListIterator<IHelpComponent> iterator = components.listIterator();
|
ListIterator<IHelpComponent> iterator = components.listIterator();
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
if (curPageLines == 0) {
|
if (curPageLines == 0) {
|
||||||
|
|
||||||
if (pageBorders != null) {
|
if (pageBorders != null) {
|
||||||
iterator.add(pageBorders.getFooter());
|
iterator.add(pageBorders.getFooter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageNum == totalPageCount) {
|
if (pageNum == totalPageCount) {
|
||||||
componentStartIdx = iterator.nextIndex();
|
componentStartIdx = iterator.nextIndex();
|
||||||
} else if (pageNum + 1 == totalPageCount) {
|
} else if (pageNum + 1 == totalPageCount) {
|
||||||
componentEndIdx = iterator.nextIndex();
|
componentEndIdx = iterator.nextIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
pageBorders = pageLayout.getPageBorders(target, viewer, context, totalPageCount + 1);
|
pageBorders = pageLayout.getPageBorders(target, viewer, context, totalPageCount + 1);
|
||||||
|
|
||||||
if (pageBorders != null) {
|
if (pageBorders != null) {
|
||||||
iterator.add(pageBorders.getHeader());
|
iterator.add(pageBorders.getHeader());
|
||||||
iterator.previous();
|
iterator.previous();
|
||||||
|
|
||||||
curPageLines += pageBorders.getFooter().lineCount();
|
curPageLines += pageBorders.getFooter().lineCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
totalPageCount++;
|
totalPageCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
IHelpComponent component = iterator.next();
|
IHelpComponent component = iterator.next();
|
||||||
int lineCount = component.lineCount();
|
int lineCount = component.lineCount();
|
||||||
curPageLines += lineCount;
|
curPageLines += lineCount;
|
||||||
|
|
||||||
if (curPageLines >= pageLen) {
|
if (curPageLines >= pageLen) {
|
||||||
curPageLines = 0;
|
curPageLines = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentStartIdx == -1) {
|
if (componentStartIdx == -1) {
|
||||||
// page does not exist
|
// page does not exist
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentEndIdx == -1) {
|
if (componentEndIdx == -1) {
|
||||||
componentEndIdx = components.size();
|
componentEndIdx = components.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
iterator = components.listIterator(componentStartIdx);
|
iterator = components.listIterator(componentStartIdx);
|
||||||
int count = componentEndIdx - componentStartIdx;
|
int count = componentEndIdx - componentStartIdx;
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
|
||||||
while (count-- > 0) {
|
while (count-- > 0) {
|
||||||
IHelpComponent component = iterator.next();
|
IHelpComponent component = iterator.next();
|
||||||
if (component instanceof IPageBorder) {
|
if (component instanceof IPageBorder) {
|
||||||
((IPageBorder) component).setPageCount(totalPageCount);
|
((IPageBorder) component).setPageCount(totalPageCount);
|
||||||
}
|
}
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
}
|
}
|
||||||
component.appendTo(sb);
|
component.appendTo(sb);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String combine(List<IHelpComponent> components) {
|
public static String combine(List<IHelpComponent> components) {
|
||||||
StringBuilder rv = new StringBuilder();
|
StringBuilder rv = new StringBuilder();
|
||||||
|
|
||||||
Iterator<IHelpComponent> iterator = components.iterator();
|
Iterator<IHelpComponent> iterator = components.iterator();
|
||||||
if (iterator.hasNext()) {
|
if (iterator.hasNext()) {
|
||||||
iterator.next().appendTo(rv);
|
iterator.next().appendTo(rv);
|
||||||
}
|
}
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
rv.append('\n');
|
rv.append('\n');
|
||||||
iterator.next().appendTo(rv);
|
iterator.next().appendTo(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv.toString();
|
return rv.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
package io.dico.dicore.command.chat.help.defaults;
|
package io.dico.dicore.command.chat.help.defaults;
|
||||||
|
|
||||||
import io.dico.dicore.command.EMessageType;
|
import io.dico.dicore.command.EMessageType;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.ModifiableCommandAddress;
|
import io.dico.dicore.command.ModifiableCommandAddress;
|
||||||
import io.dico.dicore.Formatting;
|
import io.dico.dicore.Formatting;
|
||||||
import io.dico.dicore.command.chat.IChatHandler;
|
import io.dico.dicore.command.chat.IChatHandler;
|
||||||
import io.dico.dicore.command.chat.help.IPageBorder;
|
import io.dico.dicore.command.chat.help.IPageBorder;
|
||||||
import io.dico.dicore.command.chat.help.IPageLayout;
|
import io.dico.dicore.command.chat.help.IPageLayout;
|
||||||
import io.dico.dicore.command.chat.help.PageBorders;
|
import io.dico.dicore.command.chat.help.PageBorders;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
public class DefaultPageLayout implements IPageLayout {
|
public class DefaultPageLayout implements IPageLayout {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum) {
|
public PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum) {
|
||||||
IChatHandler c = context.getAddress().getChatHandler();
|
IChatHandler c = context.getAddress().getChatHandler();
|
||||||
String prefix = c.getMessagePrefixForType(EMessageType.INFORMATIVE);
|
String prefix = c.getMessagePrefixForType(EMessageType.INFORMATIVE);
|
||||||
Formatting informative = c.getChatFormatForType(EMessageType.INFORMATIVE);
|
Formatting informative = c.getChatFormatForType(EMessageType.INFORMATIVE);
|
||||||
Formatting number = c.getChatFormatForType(EMessageType.NEUTRAL);
|
Formatting number = c.getChatFormatForType(EMessageType.NEUTRAL);
|
||||||
|
|
||||||
String nextPageCommand;
|
String nextPageCommand;
|
||||||
ICommandAddress executor = context.getAddress();
|
ICommandAddress executor = context.getAddress();
|
||||||
if (((ModifiableCommandAddress) executor).hasHelpCommand()) {
|
if (((ModifiableCommandAddress) executor).hasHelpCommand()) {
|
||||||
nextPageCommand = ((ModifiableCommandAddress) executor).getHelpCommand().getAddress() + ' ' + (pageNum + 1);
|
nextPageCommand = ((ModifiableCommandAddress) executor).getHelpCommand().getAddress() + ' ' + (pageNum + 1);
|
||||||
} else {
|
} else {
|
||||||
nextPageCommand = executor.getAddress() + ' ' + (pageNum + 1);
|
nextPageCommand = executor.getAddress() + ' ' + (pageNum + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
String header = prefix + informative + "Help page " + number + pageNum + informative +
|
String header = prefix + informative + "Help page " + number + pageNum + informative +
|
||||||
'/' + number + "%pageCount%" + informative + " for /" + target.getAddress();
|
'/' + number + "%pageCount%" + informative + " for /" + target.getAddress();
|
||||||
String footer = informative + "Type /" + nextPageCommand + " for the next page";
|
String footer = informative + "Type /" + nextPageCommand + " for the next page";
|
||||||
|
|
||||||
IPageBorder headerBorder = PageBorders.simpleBorder("", header);
|
IPageBorder headerBorder = PageBorders.simpleBorder("", header);
|
||||||
IPageBorder footerBorder = PageBorders.disappearingBorder(pageNum, footer);
|
IPageBorder footerBorder = PageBorders.disappearingBorder(pageNum, footer);
|
||||||
return new PageBorders(headerBorder, footerBorder);
|
return new PageBorders(headerBorder, footerBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,45 @@
|
|||||||
package io.dico.dicore.command.chat.help.defaults;
|
package io.dico.dicore.command.chat.help.defaults;
|
||||||
|
|
||||||
import io.dico.dicore.command.Command;
|
import io.dico.dicore.command.Command;
|
||||||
import io.dico.dicore.command.EMessageType;
|
import io.dico.dicore.command.EMessageType;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.Formatting;
|
import io.dico.dicore.Formatting;
|
||||||
import io.dico.dicore.command.chat.help.IHelpComponent;
|
import io.dico.dicore.command.chat.help.IHelpComponent;
|
||||||
import io.dico.dicore.command.chat.help.IHelpTopic;
|
import io.dico.dicore.command.chat.help.IHelpTopic;
|
||||||
import io.dico.dicore.command.chat.help.SimpleHelpComponent;
|
import io.dico.dicore.command.chat.help.SimpleHelpComponent;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DescriptionHelpTopic implements IHelpTopic {
|
public class DescriptionHelpTopic implements IHelpTopic {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
||||||
List<IHelpComponent> out = new ArrayList<>();
|
List<IHelpComponent> out = new ArrayList<>();
|
||||||
Formatting format = context.getFormat(EMessageType.DESCRIPTION);
|
Formatting format = context.getFormat(EMessageType.DESCRIPTION);
|
||||||
|
|
||||||
if (!target.hasCommand()) {
|
if (!target.hasCommand()) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
Command command = target.getCommand();
|
Command command = target.getCommand();
|
||||||
String[] description = command.getDescription();
|
String[] description = command.getDescription();
|
||||||
if (description.length == 0) {
|
if (description.length == 0) {
|
||||||
String shortDescription = command.getShortDescription();
|
String shortDescription = command.getShortDescription();
|
||||||
if (shortDescription == null) {
|
if (shortDescription == null) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
description = new String[]{shortDescription};
|
description = new String[]{shortDescription};
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < description.length; i++) {
|
for (int i = 0; i < description.length; i++) {
|
||||||
description[i] = format + description[i];
|
description[i] = format + description[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
out.add(new SimpleHelpComponent(description));
|
out.add(new SimpleHelpComponent(description));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
package io.dico.dicore.command.chat.help.defaults;
|
package io.dico.dicore.command.chat.help.defaults;
|
||||||
|
|
||||||
import io.dico.dicore.command.EMessageType;
|
import io.dico.dicore.command.EMessageType;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.Formatting;
|
import io.dico.dicore.Formatting;
|
||||||
import io.dico.dicore.command.chat.help.IHelpComponent;
|
import io.dico.dicore.command.chat.help.IHelpComponent;
|
||||||
import io.dico.dicore.command.chat.help.IHelpTopic;
|
import io.dico.dicore.command.chat.help.IHelpTopic;
|
||||||
import io.dico.dicore.command.chat.help.SimpleHelpComponent;
|
import io.dico.dicore.command.chat.help.SimpleHelpComponent;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class SubcommandsHelpTopic implements IHelpTopic {
|
public class SubcommandsHelpTopic implements IHelpTopic {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
||||||
Collection<String> mainKeys = target.getChildrenMainKeys();
|
Collection<String> mainKeys = target.getChildrenMainKeys();
|
||||||
if (mainKeys.isEmpty()) {
|
if (mainKeys.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IHelpComponent> result = new ArrayList<>();
|
List<IHelpComponent> result = new ArrayList<>();
|
||||||
|
|
||||||
mainKeys = new ArrayList<>(target.getChildrenMainKeys());
|
mainKeys = new ArrayList<>(target.getChildrenMainKeys());
|
||||||
((ArrayList<String>) mainKeys).sort(null);
|
((ArrayList<String>) mainKeys).sort(null);
|
||||||
|
|
||||||
CommandSender sender = viewer instanceof CommandSender ? (CommandSender) viewer : context.getSender();
|
CommandSender sender = viewer instanceof CommandSender ? (CommandSender) viewer : context.getSender();
|
||||||
for (String key : mainKeys) {
|
for (String key : mainKeys) {
|
||||||
ICommandAddress child = target.getChild(key);
|
ICommandAddress child = target.getChild(key);
|
||||||
if ((child.hasChildren() || child.hasUserDeclaredCommand()) && child.getCommand().isVisibleTo(sender)) {
|
if ((child.hasChildren() || child.hasUserDeclaredCommand()) && child.getCommand().isVisibleTo(sender)) {
|
||||||
result.add(getComponent(child, viewer, context));
|
result.add(getComponent(child, viewer, context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IHelpComponent getComponent(ICommandAddress child, Permissible viewer, ExecutionContext context) {
|
public IHelpComponent getComponent(ICommandAddress child, Permissible viewer, ExecutionContext context) {
|
||||||
Formatting subcommand = colorOf(context, EMessageType.SUBCOMMAND);
|
Formatting subcommand = colorOf(context, EMessageType.SUBCOMMAND);
|
||||||
Formatting highlight = colorOf(context, EMessageType.HIGHLIGHT);
|
Formatting highlight = colorOf(context, EMessageType.HIGHLIGHT);
|
||||||
|
|
||||||
String address = subcommand + "/" + child.getParent().getAddress() + ' ' + highlight + child.getMainKey();
|
String address = subcommand + "/" + child.getParent().getAddress() + ' ' + highlight + child.getMainKey();
|
||||||
|
|
||||||
String description = child.hasCommand() ? child.getCommand().getShortDescription() : null;
|
String description = child.hasCommand() ? child.getCommand().getShortDescription() : null;
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
Formatting descriptionFormat = colorOf(context, EMessageType.DESCRIPTION);
|
Formatting descriptionFormat = colorOf(context, EMessageType.DESCRIPTION);
|
||||||
return new SimpleHelpComponent(address, descriptionFormat + description);
|
return new SimpleHelpComponent(address, descriptionFormat + description);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SimpleHelpComponent(address);
|
return new SimpleHelpComponent(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Formatting colorOf(ExecutionContext context, EMessageType type) {
|
private static Formatting colorOf(ExecutionContext context, EMessageType type) {
|
||||||
return context.getAddress().getChatHandler().getChatFormatForType(type);
|
return context.getAddress().getChatHandler().getChatFormatForType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,92 +1,92 @@
|
|||||||
package io.dico.dicore.command.chat.help.defaults;
|
package io.dico.dicore.command.chat.help.defaults;
|
||||||
|
|
||||||
import io.dico.dicore.command.Command;
|
import io.dico.dicore.command.Command;
|
||||||
import io.dico.dicore.command.EMessageType;
|
import io.dico.dicore.command.EMessageType;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.Formatting;
|
import io.dico.dicore.Formatting;
|
||||||
import io.dico.dicore.command.chat.help.IHelpComponent;
|
import io.dico.dicore.command.chat.help.IHelpComponent;
|
||||||
import io.dico.dicore.command.chat.help.IHelpTopic;
|
import io.dico.dicore.command.chat.help.IHelpTopic;
|
||||||
import io.dico.dicore.command.chat.help.SimpleHelpComponent;
|
import io.dico.dicore.command.chat.help.SimpleHelpComponent;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import io.dico.dicore.command.parameter.ParameterList;
|
import io.dico.dicore.command.parameter.ParameterList;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SyntaxHelpTopic implements IHelpTopic {
|
public class SyntaxHelpTopic implements IHelpTopic {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
||||||
if (!target.hasCommand()) {
|
if (!target.hasCommand()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.hasChildren()) {
|
if (target.hasChildren()) {
|
||||||
if (!isForPage) {
|
if (!isForPage) {
|
||||||
// HelpPages will send help instead of syntax, which might in turn include syntax as well.
|
// HelpPages will send help instead of syntax, which might in turn include syntax as well.
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target.hasUserDeclaredCommand() && !target.getCommand().getParameterList().hasAnyParameters()) {
|
if (!target.hasUserDeclaredCommand() && !target.getCommand().getParameterList().hasAnyParameters()) {
|
||||||
// no point adding syntax at all
|
// no point adding syntax at all
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder line = new StringBuilder();
|
StringBuilder line = new StringBuilder();
|
||||||
if (isForPage)
|
if (isForPage)
|
||||||
line.append(context.getFormat(EMessageType.SYNTAX))
|
line.append(context.getFormat(EMessageType.SYNTAX))
|
||||||
.append("Syntax: ");
|
.append("Syntax: ");
|
||||||
|
|
||||||
line.append('/')
|
line.append('/')
|
||||||
.append(context.getFormat(EMessageType.INSTRUCTION))
|
.append(context.getFormat(EMessageType.INSTRUCTION))
|
||||||
.append(target.getAddress())
|
.append(target.getAddress())
|
||||||
.append(' ');
|
.append(' ');
|
||||||
|
|
||||||
addShortSyntax(line, target, context);
|
addShortSyntax(line, target, context);
|
||||||
|
|
||||||
return Collections.singletonList(new SimpleHelpComponent(line.toString()));
|
return Collections.singletonList(new SimpleHelpComponent(line.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addShortSyntax(StringBuilder builder, ICommandAddress address, ExecutionContext ctx) {
|
private static void addShortSyntax(StringBuilder builder, ICommandAddress address, ExecutionContext ctx) {
|
||||||
if (address.hasCommand()) {
|
if (address.hasCommand()) {
|
||||||
Formatting syntaxColor = ctx.getFormat(EMessageType.SYNTAX);
|
Formatting syntaxColor = ctx.getFormat(EMessageType.SYNTAX);
|
||||||
Formatting highlight = ctx.getFormat(EMessageType.HIGHLIGHT);
|
Formatting highlight = ctx.getFormat(EMessageType.HIGHLIGHT);
|
||||||
builder.append(syntaxColor);
|
builder.append(syntaxColor);
|
||||||
|
|
||||||
Command command = address.getCommand();
|
Command command = address.getCommand();
|
||||||
ParameterList list = command.getParameterList();
|
ParameterList list = command.getParameterList();
|
||||||
Parameter<?, ?> repeated = list.getRepeatedParameter();
|
Parameter<?, ?> repeated = list.getRepeatedParameter();
|
||||||
|
|
||||||
int requiredCount = list.getRequiredCount();
|
int requiredCount = list.getRequiredCount();
|
||||||
List<Parameter<?, ?>> indexedParameters = list.getIndexedParameters();
|
List<Parameter<?, ?>> indexedParameters = list.getIndexedParameters();
|
||||||
for (int i = 0, n = indexedParameters.size(); i < n; i++) {
|
for (int i = 0, n = indexedParameters.size(); i < n; i++) {
|
||||||
builder.append(i < requiredCount ? " <" : " [");
|
builder.append(i < requiredCount ? " <" : " [");
|
||||||
Parameter<?, ?> param = indexedParameters.get(i);
|
Parameter<?, ?> param = indexedParameters.get(i);
|
||||||
builder.append(param.getName());
|
builder.append(param.getName());
|
||||||
if (param == repeated) {
|
if (param == repeated) {
|
||||||
builder.append(highlight).append("...").append(syntaxColor);
|
builder.append(highlight).append("...").append(syntaxColor);
|
||||||
}
|
}
|
||||||
builder.append(i < requiredCount ? '>' : ']');
|
builder.append(i < requiredCount ? '>' : ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Parameter<?, ?>> parametersByName = list.getParametersByName();
|
Map<String, Parameter<?, ?>> parametersByName = list.getParametersByName();
|
||||||
for (Parameter<?, ?> param : parametersByName.values()) {
|
for (Parameter<?, ?> param : parametersByName.values()) {
|
||||||
if (param.isFlag()) {
|
if (param.isFlag()) {
|
||||||
builder.append(" [").append(param.getName());
|
builder.append(" [").append(param.getName());
|
||||||
if (param.expectsInput()) {
|
if (param.expectsInput()) {
|
||||||
builder.append(" <").append(param.getName()).append(">");
|
builder.append(" <").append(param.getName()).append(">");
|
||||||
}
|
}
|
||||||
builder.append(']');
|
builder.append(']');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
builder.append(' ');
|
builder.append(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
package io.dico.dicore.command.chat.help.insertion;
|
package io.dico.dicore.command.chat.help.insertion;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.chat.help.IHelpComponent;
|
import io.dico.dicore.command.chat.help.IHelpComponent;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public enum EInsertionStage implements IInsertionFunction {
|
public enum EInsertionStage implements IInsertionFunction {
|
||||||
START {
|
START {
|
||||||
@Override
|
@Override
|
||||||
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CENTER {
|
CENTER {
|
||||||
@Override
|
@Override
|
||||||
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
||||||
return current.size() / 2;
|
return current.size() / 2;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
END {
|
END {
|
||||||
@Override
|
@Override
|
||||||
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
||||||
return current.size();
|
return current.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
package io.dico.dicore.command.chat.help.insertion;
|
package io.dico.dicore.command.chat.help.insertion;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.chat.help.HelpTopicModifier;
|
import io.dico.dicore.command.chat.help.HelpTopicModifier;
|
||||||
import io.dico.dicore.command.chat.help.IHelpComponent;
|
import io.dico.dicore.command.chat.help.IHelpComponent;
|
||||||
import io.dico.dicore.command.chat.help.IHelpTopic;
|
import io.dico.dicore.command.chat.help.IHelpTopic;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HelpComponentInserter extends HelpTopicModifier {
|
public class HelpComponentInserter extends HelpTopicModifier {
|
||||||
private List<IInsertion> insertions = new ArrayList<>();
|
private List<IInsertion> insertions = new ArrayList<>();
|
||||||
|
|
||||||
public HelpComponentInserter(IHelpTopic delegate) {
|
public HelpComponentInserter(IHelpTopic delegate) {
|
||||||
super(delegate);
|
super(delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
protected List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
||||||
// int componentCount = components.size();
|
// int componentCount = components.size();
|
||||||
|
|
||||||
for (int i = insertions.size() - 1; i >= 0; i--) {
|
for (int i = insertions.size() - 1; i >= 0; i--) {
|
||||||
IInsertion insertion = insertions.get(i);
|
IInsertion insertion = insertions.get(i);
|
||||||
int idx = insertion.insertionIndex(components, target, viewer, context);
|
int idx = insertion.insertionIndex(components, target, viewer, context);
|
||||||
List<IHelpComponent> inserted = insertion.getComponents(target, viewer, context, true);
|
List<IHelpComponent> inserted = insertion.getComponents(target, viewer, context, true);
|
||||||
components.addAll(idx, inserted);
|
components.addAll(idx, inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelpComponentInserter insert(IInsertionFunction insertionFunction, IHelpTopic helpTopic) {
|
public HelpComponentInserter insert(IInsertionFunction insertionFunction, IHelpTopic helpTopic) {
|
||||||
return insert(Insertions.combine(helpTopic, insertionFunction));
|
return insert(Insertions.combine(helpTopic, insertionFunction));
|
||||||
}
|
}
|
||||||
|
|
||||||
public HelpComponentInserter insert(IInsertion insertion) {
|
public HelpComponentInserter insert(IInsertion insertion) {
|
||||||
insertions.add(insertion);
|
insertions.add(insertion);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package io.dico.dicore.command.chat.help.insertion;
|
package io.dico.dicore.command.chat.help.insertion;
|
||||||
|
|
||||||
import io.dico.dicore.command.chat.help.IHelpTopic;
|
import io.dico.dicore.command.chat.help.IHelpTopic;
|
||||||
|
|
||||||
interface IInsertion extends IHelpTopic, IInsertionFunction {
|
interface IInsertion extends IHelpTopic, IInsertionFunction {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package io.dico.dicore.command.chat.help.insertion;
|
package io.dico.dicore.command.chat.help.insertion;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.chat.help.IHelpComponent;
|
import io.dico.dicore.command.chat.help.IHelpComponent;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IInsertionFunction {
|
public interface IInsertionFunction {
|
||||||
|
|
||||||
int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context);
|
int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
package io.dico.dicore.command.chat.help.insertion;
|
package io.dico.dicore.command.chat.help.insertion;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.chat.help.IHelpComponent;
|
import io.dico.dicore.command.chat.help.IHelpComponent;
|
||||||
import io.dico.dicore.command.chat.help.IHelpTopic;
|
import io.dico.dicore.command.chat.help.IHelpTopic;
|
||||||
import org.bukkit.permissions.Permissible;
|
import org.bukkit.permissions.Permissible;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Insertions {
|
public class Insertions {
|
||||||
|
|
||||||
private Insertions() {
|
private Insertions() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IInsertion combine(IHelpTopic topic, IInsertionFunction function) {
|
public static IInsertion combine(IHelpTopic topic, IInsertionFunction function) {
|
||||||
return new IInsertion() {
|
return new IInsertion() {
|
||||||
@Override
|
@Override
|
||||||
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
|
||||||
return topic.getComponents(target, viewer, context, true);
|
return topic.getComponents(target, viewer, context, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
|
||||||
return function.insertionIndex(current, target, viewer, context);
|
return function.insertionIndex(current, target, viewer, context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,295 +1,295 @@
|
|||||||
package io.dico.dicore.command.parameter;
|
package io.dico.dicore.command.parameter;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer for the arguments.
|
* Buffer for the arguments.
|
||||||
* Easy to traverse for the parser.
|
* Easy to traverse for the parser.
|
||||||
*/
|
*/
|
||||||
public class ArgumentBuffer extends AbstractList<String> implements Iterator<String>, RandomAccess {
|
public class ArgumentBuffer extends AbstractList<String> implements Iterator<String>, RandomAccess {
|
||||||
private String[] array;
|
private String[] array;
|
||||||
private int cursor = 0; // index of the next return value
|
private int cursor = 0; // index of the next return value
|
||||||
private transient ArgumentBuffer unaffectingCopy = null; // see #getUnaffectingCopy()
|
private transient ArgumentBuffer unaffectingCopy = null; // see #getUnaffectingCopy()
|
||||||
|
|
||||||
public ArgumentBuffer(String label, String[] args) {
|
public ArgumentBuffer(String label, String[] args) {
|
||||||
this(combine(label, args));
|
this(combine(label, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] combine(String label, String[] args) {
|
private static String[] combine(String label, String[] args) {
|
||||||
String[] result;
|
String[] result;
|
||||||
//if (args.length > 0 && "".equals(args[args.length - 1])) {
|
//if (args.length > 0 && "".equals(args[args.length - 1])) {
|
||||||
// // drop the last element of args if it is empty
|
// // drop the last element of args if it is empty
|
||||||
// result = args;
|
// result = args;
|
||||||
//} else {
|
//} else {
|
||||||
result = new String[args.length + 1];
|
result = new String[args.length + 1];
|
||||||
//}
|
//}
|
||||||
System.arraycopy(args, 0, result, 1, result.length - 1);
|
System.arraycopy(args, 0, result, 1, result.length - 1);
|
||||||
result[0] = Objects.requireNonNull(label);
|
result[0] = Objects.requireNonNull(label);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new ArgumentBuffer using the given array, without copying it first.
|
* Constructs a new ArgumentBuffer using the given array, without copying it first.
|
||||||
* None of the array its elements should be empty.
|
* None of the array its elements should be empty.
|
||||||
*
|
*
|
||||||
* @param array the array
|
* @param array the array
|
||||||
* @throws NullPointerException if the array or any of its elements are null
|
* @throws NullPointerException if the array or any of its elements are null
|
||||||
*/
|
*/
|
||||||
public ArgumentBuffer(String[] array) {
|
public ArgumentBuffer(String[] array) {
|
||||||
for (String elem : array) {
|
for (String elem : array) {
|
||||||
if (elem == null) throw new NullPointerException("ArgumentBuffer array element");
|
if (elem == null) throw new NullPointerException("ArgumentBuffer array element");
|
||||||
}
|
}
|
||||||
this.array = array;
|
this.array = array;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCursor() {
|
public int getCursor() {
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ArgumentBuffer setCursor(int cursor) {
|
public @NotNull ArgumentBuffer setCursor(int cursor) {
|
||||||
if (cursor <= 0) {
|
if (cursor <= 0) {
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
} else if (size() <= cursor) {
|
} else if (size() <= cursor) {
|
||||||
cursor = size();
|
cursor = size();
|
||||||
}
|
}
|
||||||
this.cursor = cursor;
|
this.cursor = cursor;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return array.length;
|
return array.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String get(int index) {
|
public @NotNull String get(int index) {
|
||||||
return array[index];
|
return array[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int nextIndex() {
|
public int nextIndex() {
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int previousIndex() {
|
public int previousIndex() {
|
||||||
return cursor - 1;
|
return cursor - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int remainingElements() {
|
public int remainingElements() {
|
||||||
return size() - nextIndex() - 1;
|
return size() - nextIndex() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return nextIndex() < size();
|
return nextIndex() < size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPrevious() {
|
public boolean hasPrevious() {
|
||||||
return 0 <= previousIndex();
|
return 0 <= previousIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlike conventional ListIterator implementations, this returns null if there is no next element
|
* Unlike conventional ListIterator implementations, this returns null if there is no next element
|
||||||
*
|
*
|
||||||
* @return the next value, or null
|
* @return the next value, or null
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public @Nullable String next() {
|
public @Nullable String next() {
|
||||||
return hasNext() ? get(cursor++) : null;
|
return hasNext() ? get(cursor++) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String requireNext(String parameterName) throws CommandException {
|
public @NotNull String requireNext(String parameterName) throws CommandException {
|
||||||
String next = next();
|
String next = next();
|
||||||
if (next == null) {
|
if (next == null) {
|
||||||
throw CommandException.missingArgument(parameterName);
|
throw CommandException.missingArgument(parameterName);
|
||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// useful for completion code
|
// useful for completion code
|
||||||
public @NotNull String nextOrEmpty() {
|
public @NotNull String nextOrEmpty() {
|
||||||
return hasNext() ? get(cursor++) : "";
|
return hasNext() ? get(cursor++) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlike conventional ListIterator implementations, this returns null if there is no previous element
|
* Unlike conventional ListIterator implementations, this returns null if there is no previous element
|
||||||
*
|
*
|
||||||
* @return the previous value, or null
|
* @return the previous value, or null
|
||||||
*/
|
*/
|
||||||
public @Nullable String previous() {
|
public @Nullable String previous() {
|
||||||
return hasPrevious() ? get(--cursor) : null;
|
return hasPrevious() ? get(--cursor) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable String peekNext() {
|
public @Nullable String peekNext() {
|
||||||
return hasNext() ? get(cursor) : null;
|
return hasNext() ? get(cursor) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable String peekPrevious() {
|
public @Nullable String peekPrevious() {
|
||||||
return hasPrevious() ? get(cursor - 1) : null;
|
return hasPrevious() ? get(cursor - 1) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ArgumentBuffer advance() {
|
public @NotNull ArgumentBuffer advance() {
|
||||||
return advance(1);
|
return advance(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ArgumentBuffer advance(int amount) {
|
public @NotNull ArgumentBuffer advance(int amount) {
|
||||||
cursor = Math.min(Math.max(0, cursor + amount), size());
|
cursor = Math.min(Math.max(0, cursor + amount), size());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ArgumentBuffer rewind() {
|
public @NotNull ArgumentBuffer rewind() {
|
||||||
return rewind(1);
|
return rewind(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ArgumentBuffer rewind(int amount) {
|
public @NotNull ArgumentBuffer rewind(int amount) {
|
||||||
return advance(-amount);
|
return advance(-amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull String[] getArray() {
|
@NotNull String[] getArray() {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String[] getArrayFromCursor() {
|
public @NotNull String[] getArrayFromCursor() {
|
||||||
return getArrayFromIndex(cursor);
|
return getArrayFromIndex(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String[] getArrayFromIndex(int index) {
|
public @NotNull String[] getArrayFromIndex(int index) {
|
||||||
return Arrays.copyOfRange(array, index, array.length);
|
return Arrays.copyOfRange(array, index, array.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String getRawInput() {
|
public @NotNull String getRawInput() {
|
||||||
return String.join(" ", array);
|
return String.join(" ", array);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull String[] toArray() {
|
public @NotNull String[] toArray() {
|
||||||
return array.clone();
|
return array.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Iterator<String> iterator() {
|
public @NotNull Iterator<String> iterator() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ListIterator<String> listIterator() {
|
public @NotNull ListIterator<String> listIterator() {
|
||||||
return new ListIterator<String>() {
|
return new ListIterator<String>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return ArgumentBuffer.this.hasNext();
|
return ArgumentBuffer.this.hasNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String next() {
|
public String next() {
|
||||||
if (!hasNext()) {
|
if (!hasNext()) {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
return ArgumentBuffer.this.next();
|
return ArgumentBuffer.this.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPrevious() {
|
public boolean hasPrevious() {
|
||||||
return ArgumentBuffer.this.hasPrevious();
|
return ArgumentBuffer.this.hasPrevious();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String previous() {
|
public String previous() {
|
||||||
if (!hasPrevious()) {
|
if (!hasPrevious()) {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
return ArgumentBuffer.this.previous();
|
return ArgumentBuffer.this.previous();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int nextIndex() {
|
public int nextIndex() {
|
||||||
return ArgumentBuffer.this.nextIndex();
|
return ArgumentBuffer.this.nextIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int previousIndex() {
|
public int previousIndex() {
|
||||||
return ArgumentBuffer.this.previousIndex();
|
return ArgumentBuffer.this.previousIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(String s) {
|
public void set(String s) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(String s) {
|
public void add(String s) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dropTrailingEmptyElements() {
|
public void dropTrailingEmptyElements() {
|
||||||
int removeCount = 0;
|
int removeCount = 0;
|
||||||
String[] array = this.array;
|
String[] array = this.array;
|
||||||
for (int i = array.length - 1; i >= 0; i--) {
|
for (int i = array.length - 1; i >= 0; i--) {
|
||||||
if ("".equals(array[i])) {
|
if ("".equals(array[i])) {
|
||||||
removeCount++;
|
removeCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeCount > 0) {
|
if (removeCount > 0) {
|
||||||
String[] newArray = new String[array.length - removeCount];
|
String[] newArray = new String[array.length - removeCount];
|
||||||
System.arraycopy(array, 0, newArray, 0, newArray.length);
|
System.arraycopy(array, 0, newArray, 0, newArray.length);
|
||||||
this.array = newArray;
|
this.array = newArray;
|
||||||
|
|
||||||
if (cursor > newArray.length) {
|
if (cursor > newArray.length) {
|
||||||
cursor = newArray.length;
|
cursor = newArray.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preprocess this argument buffer with the given preprocessor
|
* Preprocess this argument buffer with the given preprocessor
|
||||||
*
|
*
|
||||||
* @param preProcessor preprocessor
|
* @param preProcessor preprocessor
|
||||||
* @return a new ArgumentBuffer with processed contents. Might be this buffer if nothing changed.
|
* @return a new ArgumentBuffer with processed contents. Might be this buffer if nothing changed.
|
||||||
*/
|
*/
|
||||||
public @NotNull ArgumentBuffer preprocessArguments(IArgumentPreProcessor preProcessor) {
|
public @NotNull ArgumentBuffer preprocessArguments(IArgumentPreProcessor preProcessor) {
|
||||||
return preProcessor.process(this, -1);
|
return preProcessor.process(this, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows a piece of code to traverse this buffer without modifying its cursor.
|
* Allows a piece of code to traverse this buffer without modifying its cursor.
|
||||||
* After this method has been called for the first time on this instance, if this method
|
* After this method has been called for the first time on this instance, if this method
|
||||||
* or the {@link #clone()} method are called, the operation carried out on the prior result has finished.
|
* or the {@link #clone()} method are called, the operation carried out on the prior result has finished.
|
||||||
* As such, the same instance might be returned again.
|
* As such, the same instance might be returned again.
|
||||||
*
|
*
|
||||||
* @return A view of this buffer that doesn't affect this buffer's cursor.
|
* @return A view of this buffer that doesn't affect this buffer's cursor.
|
||||||
*/
|
*/
|
||||||
public ArgumentBuffer getUnaffectingCopy() {
|
public ArgumentBuffer getUnaffectingCopy() {
|
||||||
// the copy doesn't alter the cursor of this ArgumentBuffer when moved, but traverses the same array reference.
|
// the copy doesn't alter the cursor of this ArgumentBuffer when moved, but traverses the same array reference.
|
||||||
// there is only ever one copy of an ArgumentBuffer, the cursor of which is updated on every call to this method.
|
// there is only ever one copy of an ArgumentBuffer, the cursor of which is updated on every call to this method.
|
||||||
|
|
||||||
ArgumentBuffer unaffectingCopy = this.unaffectingCopy;
|
ArgumentBuffer unaffectingCopy = this.unaffectingCopy;
|
||||||
if (unaffectingCopy == null) {
|
if (unaffectingCopy == null) {
|
||||||
this.unaffectingCopy = unaffectingCopy = new ArgumentBuffer(array);
|
this.unaffectingCopy = unaffectingCopy = new ArgumentBuffer(array);
|
||||||
}
|
}
|
||||||
unaffectingCopy.cursor = this.cursor;
|
unaffectingCopy.cursor = this.cursor;
|
||||||
return unaffectingCopy;
|
return unaffectingCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||||
public @NotNull ArgumentBuffer clone() {
|
public @NotNull ArgumentBuffer clone() {
|
||||||
ArgumentBuffer result = getUnaffectingCopy();
|
ArgumentBuffer result = getUnaffectingCopy();
|
||||||
this.unaffectingCopy = null;
|
this.unaffectingCopy = null;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("ArgumentBuffer(size = %d, cursor = %d)", size(), getCursor());
|
return String.format("ArgumentBuffer(size = %d, cursor = %d)", size(), getCursor());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,177 +1,177 @@
|
|||||||
package io.dico.dicore.command.parameter;
|
package io.dico.dicore.command.parameter;
|
||||||
|
|
||||||
public class ArgumentMergingPreProcessor implements IArgumentPreProcessor {
|
public class ArgumentMergingPreProcessor implements IArgumentPreProcessor {
|
||||||
private final String tokens;
|
private final String tokens;
|
||||||
private final char escapeChar;
|
private final char escapeChar;
|
||||||
|
|
||||||
public ArgumentMergingPreProcessor(String tokens, char escapeChar) {
|
public ArgumentMergingPreProcessor(String tokens, char escapeChar) {
|
||||||
if ((tokens.length() & 1) != 0 || tokens.isEmpty()) throw new IllegalArgumentException();
|
if ((tokens.length() & 1) != 0 || tokens.isEmpty()) throw new IllegalArgumentException();
|
||||||
this.tokens = tokens;
|
this.tokens = tokens;
|
||||||
this.escapeChar = escapeChar;
|
this.escapeChar = escapeChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArgumentBuffer process(ArgumentBuffer buffer, int count) {
|
public ArgumentBuffer process(ArgumentBuffer buffer, int count) {
|
||||||
Parser parser = new Parser(buffer.getArray().clone(), buffer.getCursor(), count);
|
Parser parser = new Parser(buffer.getArray().clone(), buffer.getCursor(), count);
|
||||||
String[] array = parser.doProcess();
|
String[] array = parser.doProcess();
|
||||||
ArgumentBuffer result = new ArgumentBuffer(array);
|
ArgumentBuffer result = new ArgumentBuffer(array);
|
||||||
parser.updateBuffer(result);
|
parser.updateBuffer(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Parser {
|
private class Parser {
|
||||||
private final String[] args;
|
private final String[] args;
|
||||||
private final int start;
|
private final int start;
|
||||||
private final int count;
|
private final int count;
|
||||||
|
|
||||||
private int foundSectionCount;
|
private int foundSectionCount;
|
||||||
private int currentIndex;
|
private int currentIndex;
|
||||||
private int sectionStart;
|
private int sectionStart;
|
||||||
private char closingToken;
|
private char closingToken;
|
||||||
private int sectionEnd;
|
private int sectionEnd;
|
||||||
private int removeCount;
|
private int removeCount;
|
||||||
|
|
||||||
Parser(String[] args, int start, int count) {
|
Parser(String[] args, int start, int count) {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
this.count = count;
|
this.count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reset() {
|
private void reset() {
|
||||||
foundSectionCount = 0;
|
foundSectionCount = 0;
|
||||||
currentIndex = start;
|
currentIndex = start;
|
||||||
sectionStart = -1;
|
sectionStart = -1;
|
||||||
closingToken = 0;
|
closingToken = 0;
|
||||||
sectionEnd = -1;
|
sectionEnd = -1;
|
||||||
removeCount = 0;
|
removeCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean findNextSectionStart() {
|
private boolean findNextSectionStart() {
|
||||||
if (count >= 0 && foundSectionCount >= count) return false;
|
if (count >= 0 && foundSectionCount >= count) return false;
|
||||||
|
|
||||||
while (currentIndex < args.length) {
|
while (currentIndex < args.length) {
|
||||||
String arg = args[currentIndex];
|
String arg = args[currentIndex];
|
||||||
if (arg == null) {
|
if (arg == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.isEmpty()) {
|
if (arg.isEmpty()) {
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int openingTokenIndex = tokens.indexOf(arg.charAt(0));
|
int openingTokenIndex = tokens.indexOf(arg.charAt(0));
|
||||||
if (openingTokenIndex == -1 || (openingTokenIndex & 1) != 0) {
|
if (openingTokenIndex == -1 || (openingTokenIndex & 1) != 0) {
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// found
|
// found
|
||||||
closingToken = tokens.charAt(openingTokenIndex | 1);
|
closingToken = tokens.charAt(openingTokenIndex | 1);
|
||||||
sectionStart = currentIndex;
|
sectionStart = currentIndex;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean findNextSectionEnd() {
|
private boolean findNextSectionEnd() {
|
||||||
while (currentIndex < args.length) {
|
while (currentIndex < args.length) {
|
||||||
String arg = args[currentIndex];
|
String arg = args[currentIndex];
|
||||||
if (arg == null) {
|
if (arg == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.isEmpty()
|
if (arg.isEmpty()
|
||||||
|| arg.charAt(arg.length() - 1) != closingToken
|
|| arg.charAt(arg.length() - 1) != closingToken
|
||||||
|| (sectionStart == currentIndex && arg.length() == 1)) {
|
|| (sectionStart == currentIndex && arg.length() == 1)) {
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (escapeChar != 0
|
if (escapeChar != 0
|
||||||
&& arg.length() > 1
|
&& arg.length() > 1
|
||||||
&& arg.charAt(arg.length() - 2) == escapeChar) {
|
&& arg.charAt(arg.length() - 2) == escapeChar) {
|
||||||
// escaped
|
// escaped
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// found
|
// found
|
||||||
closingToken = 0;
|
closingToken = 0;
|
||||||
sectionEnd = currentIndex;
|
sectionEnd = currentIndex;
|
||||||
++currentIndex;
|
++currentIndex;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processFoundSection() {
|
private void processFoundSection() {
|
||||||
if (sectionStart == sectionEnd) {
|
if (sectionStart == sectionEnd) {
|
||||||
String arg = args[sectionStart];
|
String arg = args[sectionStart];
|
||||||
args[sectionStart] = arg.substring(1, arg.length() - 1);
|
args[sectionStart] = arg.substring(1, arg.length() - 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
removeCount += sectionEnd - sectionStart;
|
removeCount += sectionEnd - sectionStart;
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(args[sectionStart].substring(1));
|
sb.append(args[sectionStart].substring(1));
|
||||||
|
|
||||||
for (int i = sectionStart + 1; i < sectionEnd; i++) {
|
for (int i = sectionStart + 1; i < sectionEnd; i++) {
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
sb.append(args[i]);
|
sb.append(args[i]);
|
||||||
args[i] = null;
|
args[i] = null;
|
||||||
}
|
}
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
sb.append(args[sectionEnd].substring(0, args[sectionEnd].length() - 1));
|
sb.append(args[sectionEnd].substring(0, args[sectionEnd].length() - 1));
|
||||||
args[sectionEnd] = null;
|
args[sectionEnd] = null;
|
||||||
|
|
||||||
args[sectionStart] = sb.toString();
|
args[sectionStart] = sb.toString();
|
||||||
|
|
||||||
sectionStart = -1;
|
sectionStart = -1;
|
||||||
sectionEnd = -1;
|
sectionEnd = -1;
|
||||||
|
|
||||||
++foundSectionCount;
|
++foundSectionCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] doProcess() {
|
String[] doProcess() {
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
while (findNextSectionStart()) {
|
while (findNextSectionStart()) {
|
||||||
if (findNextSectionEnd()) {
|
if (findNextSectionEnd()) {
|
||||||
processFoundSection();
|
processFoundSection();
|
||||||
} else {
|
} else {
|
||||||
currentIndex = sectionStart + 1;
|
currentIndex = sectionStart + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeCount == 0) {
|
if (removeCount == 0) {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] result = new String[args.length - removeCount];
|
String[] result = new String[args.length - removeCount];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (String arg : args) {
|
for (String arg : args) {
|
||||||
if (arg != null) {
|
if (arg != null) {
|
||||||
result[i++] = arg;
|
result[i++] = arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateBuffer(ArgumentBuffer buffer) {
|
void updateBuffer(ArgumentBuffer buffer) {
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
buffer.setCursor(start);
|
buffer.setCursor(start);
|
||||||
} else {
|
} else {
|
||||||
buffer.setCursor(currentIndex);
|
buffer.setCursor(currentIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,276 +1,276 @@
|
|||||||
package io.dico.dicore.command.parameter;
|
package io.dico.dicore.command.parameter;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ContextParser {
|
public class ContextParser {
|
||||||
private final ExecutionContext m_context;
|
private final ExecutionContext m_context;
|
||||||
private final ArgumentBuffer m_buffer;
|
private final ArgumentBuffer m_buffer;
|
||||||
private final ParameterList m_paramList;
|
private final ParameterList m_paramList;
|
||||||
private final Parameter<?, ?> m_repeatedParam;
|
private final Parameter<?, ?> m_repeatedParam;
|
||||||
private final List<Parameter<?, ?>> m_indexedParams;
|
private final List<Parameter<?, ?>> m_indexedParams;
|
||||||
private final int m_maxIndex;
|
private final int m_maxIndex;
|
||||||
private final int m_maxRequiredIndex;
|
private final int m_maxRequiredIndex;
|
||||||
|
|
||||||
private Map<String, Object> m_valueMap;
|
private Map<String, Object> m_valueMap;
|
||||||
private Set<String> m_parsedKeys;
|
private Set<String> m_parsedKeys;
|
||||||
private int m_completionCursor = -1;
|
private int m_completionCursor = -1;
|
||||||
private Parameter<?, ?> m_completionTarget = null;
|
private Parameter<?, ?> m_completionTarget = null;
|
||||||
|
|
||||||
public ContextParser(ExecutionContext context,
|
public ContextParser(ExecutionContext context,
|
||||||
ParameterList parameterList,
|
ParameterList parameterList,
|
||||||
Map<String, Object> valueMap,
|
Map<String, Object> valueMap,
|
||||||
Set<String> keySet) {
|
Set<String> keySet) {
|
||||||
m_context = context;
|
m_context = context;
|
||||||
m_paramList = parameterList;
|
m_paramList = parameterList;
|
||||||
m_valueMap = valueMap;
|
m_valueMap = valueMap;
|
||||||
m_parsedKeys = keySet;
|
m_parsedKeys = keySet;
|
||||||
|
|
||||||
m_buffer = context.getBuffer();
|
m_buffer = context.getBuffer();
|
||||||
m_repeatedParam = m_paramList.getRepeatedParameter();
|
m_repeatedParam = m_paramList.getRepeatedParameter();
|
||||||
m_indexedParams = m_paramList.getIndexedParameters();
|
m_indexedParams = m_paramList.getIndexedParameters();
|
||||||
m_maxIndex = m_indexedParams.size() - 1;
|
m_maxIndex = m_indexedParams.size() - 1;
|
||||||
m_maxRequiredIndex = m_paramList.getRequiredCount() - 1;
|
m_maxRequiredIndex = m_paramList.getRequiredCount() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExecutionContext getContext() {
|
public ExecutionContext getContext() {
|
||||||
return m_context;
|
return m_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> getValueMap() {
|
public Map<String, Object> getValueMap() {
|
||||||
return m_valueMap;
|
return m_valueMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getParsedKeys() {
|
public Set<String> getParsedKeys() {
|
||||||
return m_parsedKeys;
|
return m_parsedKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parse() throws CommandException {
|
public void parse() throws CommandException {
|
||||||
parseAllParameters();
|
parseAllParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCompletionCursor() {
|
public int getCompletionCursor() {
|
||||||
if (!m_done) {
|
if (!m_done) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
return m_completionCursor;
|
return m_completionCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameter<?, ?> getCompletionTarget() {
|
public Parameter<?, ?> getCompletionTarget() {
|
||||||
if (!m_done) {
|
if (!m_done) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
return m_completionTarget;
|
return m_completionTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ################################
|
// ################################
|
||||||
// # PARSING METHODS #
|
// # PARSING METHODS #
|
||||||
// ################################
|
// ################################
|
||||||
|
|
||||||
private boolean m_repeating = false;
|
private boolean m_repeating = false;
|
||||||
private boolean m_done = false;
|
private boolean m_done = false;
|
||||||
private int m_curParamIndex = -1;
|
private int m_curParamIndex = -1;
|
||||||
private Parameter<?, ?> m_curParam = null;
|
private Parameter<?, ?> m_curParam = null;
|
||||||
private List<Object> m_curRepeatingList = null;
|
private List<Object> m_curRepeatingList = null;
|
||||||
|
|
||||||
private void parseAllParameters() throws CommandException {
|
private void parseAllParameters() throws CommandException {
|
||||||
try {
|
try {
|
||||||
do {
|
do {
|
||||||
prepareStateToParseParam();
|
prepareStateToParseParam();
|
||||||
if (m_done) break;
|
if (m_done) break;
|
||||||
parseCurParam();
|
parseCurParam();
|
||||||
} while (!m_done);
|
} while (!m_done);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
m_curParam = null;
|
m_curParam = null;
|
||||||
m_curRepeatingList = null;
|
m_curRepeatingList = null;
|
||||||
assignDefaultValuesToUncomputedParams();
|
assignDefaultValuesToUncomputedParams();
|
||||||
arrayifyRepeatedParamValue();
|
arrayifyRepeatedParamValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareStateToParseParam() throws CommandException {
|
private void prepareStateToParseParam() throws CommandException {
|
||||||
|
|
||||||
boolean requireInput;
|
boolean requireInput;
|
||||||
if (identifyFlag()) {
|
if (identifyFlag()) {
|
||||||
m_buffer.advance();
|
m_buffer.advance();
|
||||||
prepareRepeatedParameterIfSet();
|
prepareRepeatedParameterIfSet();
|
||||||
requireInput = false;
|
requireInput = false;
|
||||||
|
|
||||||
} else if (m_repeating) {
|
} else if (m_repeating) {
|
||||||
m_curParam = m_repeatedParam;
|
m_curParam = m_repeatedParam;
|
||||||
requireInput = false;
|
requireInput = false;
|
||||||
|
|
||||||
} else if (m_curParamIndex < m_maxIndex) {
|
} else if (m_curParamIndex < m_maxIndex) {
|
||||||
m_curParamIndex++;
|
m_curParamIndex++;
|
||||||
m_curParam = m_indexedParams.get(m_curParamIndex);
|
m_curParam = m_indexedParams.get(m_curParamIndex);
|
||||||
prepareRepeatedParameterIfSet();
|
prepareRepeatedParameterIfSet();
|
||||||
requireInput = m_curParamIndex <= m_maxRequiredIndex;
|
requireInput = m_curParamIndex <= m_maxRequiredIndex;
|
||||||
|
|
||||||
} else if (m_buffer.hasNext()) {
|
} else if (m_buffer.hasNext()) {
|
||||||
throw new CommandException("Too many arguments for /" + m_context.getAddress().getAddress());
|
throw new CommandException("Too many arguments for /" + m_context.getAddress().getAddress());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
m_done = true;
|
m_done = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_buffer.hasNext()) {
|
if (!m_buffer.hasNext()) {
|
||||||
if (requireInput) {
|
if (requireInput) {
|
||||||
reportParameterRequired(m_curParam);
|
reportParameterRequired(m_curParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_repeating) {
|
if (m_repeating) {
|
||||||
m_done = true;
|
m_done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean identifyFlag() {
|
private boolean identifyFlag() {
|
||||||
String potentialFlag = m_buffer.peekNext();
|
String potentialFlag = m_buffer.peekNext();
|
||||||
Parameter<?, ?> target;
|
Parameter<?, ?> target;
|
||||||
if (potentialFlag != null
|
if (potentialFlag != null
|
||||||
&& potentialFlag.startsWith("-")
|
&& potentialFlag.startsWith("-")
|
||||||
&& (target = m_paramList.getParameterByName(potentialFlag)) != null
|
&& (target = m_paramList.getParameterByName(potentialFlag)) != null
|
||||||
&& target.isFlag()
|
&& target.isFlag()
|
||||||
&& !m_valueMap.containsKey(potentialFlag)
|
&& !m_valueMap.containsKey(potentialFlag)
|
||||||
|
|
||||||
// Disabled because it's checked by {@link Parameter#parse(ExecutionContext, ArgumentBuffer)}
|
// Disabled because it's checked by {@link Parameter#parse(ExecutionContext, ArgumentBuffer)}
|
||||||
// && (target.getFlagPermission() == null || m_context.getSender().hasPermission(target.getFlagPermission()))
|
// && (target.getFlagPermission() == null || m_context.getSender().hasPermission(target.getFlagPermission()))
|
||||||
) {
|
) {
|
||||||
m_curParam = target;
|
m_curParam = target;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareRepeatedParameterIfSet() throws CommandException {
|
private void prepareRepeatedParameterIfSet() throws CommandException {
|
||||||
if (m_curParam != null && m_curParam == m_repeatedParam) {
|
if (m_curParam != null && m_curParam == m_repeatedParam) {
|
||||||
|
|
||||||
if (m_curParam.isFlag() && m_curParamIndex < m_maxRequiredIndex) {
|
if (m_curParam.isFlag() && m_curParamIndex < m_maxRequiredIndex) {
|
||||||
Parameter<?, ?> requiredParam = m_indexedParams.get(m_curParamIndex + 1);
|
Parameter<?, ?> requiredParam = m_indexedParams.get(m_curParamIndex + 1);
|
||||||
reportParameterRequired(requiredParam);
|
reportParameterRequired(requiredParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_curRepeatingList = new ArrayList<>();
|
m_curRepeatingList = new ArrayList<>();
|
||||||
assignValue(m_curRepeatingList);
|
assignValue(m_curRepeatingList);
|
||||||
m_repeating = true;
|
m_repeating = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportParameterRequired(Parameter<?, ?> param) throws CommandException {
|
private void reportParameterRequired(Parameter<?, ?> param) throws CommandException {
|
||||||
throw new CommandException("The argument '" + param.getName() + "' is required");
|
throw new CommandException("The argument '" + param.getName() + "' is required");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseCurParam() throws CommandException {
|
private void parseCurParam() throws CommandException {
|
||||||
if (!m_buffer.hasNext() && !m_curParam.isFlag()) {
|
if (!m_buffer.hasNext() && !m_curParam.isFlag()) {
|
||||||
assignDefaultValue();
|
assignDefaultValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cursorStart = m_buffer.getCursor();
|
int cursorStart = m_buffer.getCursor();
|
||||||
|
|
||||||
if (m_context.isTabComplete() && "".equals(m_buffer.peekNext())) {
|
if (m_context.isTabComplete() && "".equals(m_buffer.peekNext())) {
|
||||||
assignAsCompletionTarget(cursorStart);
|
assignAsCompletionTarget(cursorStart);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object parseResult;
|
Object parseResult;
|
||||||
try {
|
try {
|
||||||
parseResult = m_curParam.parse(m_context, m_buffer);
|
parseResult = m_curParam.parse(m_context, m_buffer);
|
||||||
} catch (CommandException e) {
|
} catch (CommandException e) {
|
||||||
assignAsCompletionTarget(cursorStart);
|
assignAsCompletionTarget(cursorStart);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
assignValue(parseResult);
|
assignValue(parseResult);
|
||||||
m_parsedKeys.add(m_curParam.getName());
|
m_parsedKeys.add(m_curParam.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignDefaultValue() throws CommandException {
|
private void assignDefaultValue() throws CommandException {
|
||||||
assignValue(m_curParam.getDefaultValue(m_context, m_buffer));
|
assignValue(m_curParam.getDefaultValue(m_context, m_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignAsCompletionTarget(int cursor) {
|
private void assignAsCompletionTarget(int cursor) {
|
||||||
m_completionCursor = cursor;
|
m_completionCursor = cursor;
|
||||||
m_completionTarget = m_curParam;
|
m_completionTarget = m_curParam;
|
||||||
m_done = true;
|
m_done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignValue(Object value) {
|
private void assignValue(Object value) {
|
||||||
if (m_repeating) {
|
if (m_repeating) {
|
||||||
m_curRepeatingList.add(value);
|
m_curRepeatingList.add(value);
|
||||||
} else {
|
} else {
|
||||||
m_valueMap.put(m_curParam.getName(), value);
|
m_valueMap.put(m_curParam.getName(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignDefaultValuesToUncomputedParams() throws CommandException {
|
private void assignDefaultValuesToUncomputedParams() throws CommandException {
|
||||||
// add default values for unset parameters
|
// add default values for unset parameters
|
||||||
for (Map.Entry<String, Parameter<?, ?>> entry : m_paramList.getParametersByName().entrySet()) {
|
for (Map.Entry<String, Parameter<?, ?>> entry : m_paramList.getParametersByName().entrySet()) {
|
||||||
String name = entry.getKey();
|
String name = entry.getKey();
|
||||||
if (!m_valueMap.containsKey(name)) {
|
if (!m_valueMap.containsKey(name)) {
|
||||||
if (m_repeatedParam == entry.getValue()) {
|
if (m_repeatedParam == entry.getValue()) {
|
||||||
// below value will be turned into an array later
|
// below value will be turned into an array later
|
||||||
m_valueMap.put(name, Collections.emptyList());
|
m_valueMap.put(name, Collections.emptyList());
|
||||||
} else {
|
} else {
|
||||||
m_valueMap.put(name, entry.getValue().getDefaultValue(m_context, m_buffer));
|
m_valueMap.put(name, entry.getValue().getDefaultValue(m_context, m_buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void arrayifyRepeatedParamValue() {
|
private void arrayifyRepeatedParamValue() {
|
||||||
if (m_repeatedParam != null) {
|
if (m_repeatedParam != null) {
|
||||||
m_valueMap.computeIfPresent(m_repeatedParam.getName(), (k, v) -> {
|
m_valueMap.computeIfPresent(m_repeatedParam.getName(), (k, v) -> {
|
||||||
List list = (List) v;
|
List list = (List) v;
|
||||||
Class<?> returnType = m_repeatedParam.getType().getReturnType();
|
Class<?> returnType = m_repeatedParam.getType().getReturnType();
|
||||||
Object array = Array.newInstance(returnType, list.size());
|
Object array = Array.newInstance(returnType, list.size());
|
||||||
ArraySetter setter = ArraySetter.getSetter(returnType);
|
ArraySetter setter = ArraySetter.getSetter(returnType);
|
||||||
for (int i = 0, n = list.size(); i < n; i++) {
|
for (int i = 0, n = list.size(); i < n; i++) {
|
||||||
setter.set(array, i, list.get(i));
|
setter.set(array, i, list.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface ArraySetter {
|
private interface ArraySetter {
|
||||||
void set(Object array, int index, Object value);
|
void set(Object array, int index, Object value);
|
||||||
|
|
||||||
static ArraySetter getSetter(Class<?> clazz) {
|
static ArraySetter getSetter(Class<?> clazz) {
|
||||||
if (!clazz.isPrimitive()) {
|
if (!clazz.isPrimitive()) {
|
||||||
return (array, index, value) -> ((Object[]) array)[index] = value;
|
return (array, index, value) -> ((Object[]) array)[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (clazz.getSimpleName()) {
|
switch (clazz.getSimpleName()) {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return (array, index, value) -> ((boolean[]) array)[index] = (boolean) value;
|
return (array, index, value) -> ((boolean[]) array)[index] = (boolean) value;
|
||||||
case "int":
|
case "int":
|
||||||
return (array, index, value) -> ((int[]) array)[index] = (int) value;
|
return (array, index, value) -> ((int[]) array)[index] = (int) value;
|
||||||
case "double":
|
case "double":
|
||||||
return (array, index, value) -> ((double[]) array)[index] = (double) value;
|
return (array, index, value) -> ((double[]) array)[index] = (double) value;
|
||||||
case "long":
|
case "long":
|
||||||
return (array, index, value) -> ((long[]) array)[index] = (long) value;
|
return (array, index, value) -> ((long[]) array)[index] = (long) value;
|
||||||
case "short":
|
case "short":
|
||||||
return (array, index, value) -> ((short[]) array)[index] = (short) value;
|
return (array, index, value) -> ((short[]) array)[index] = (short) value;
|
||||||
case "byte":
|
case "byte":
|
||||||
return (array, index, value) -> ((byte[]) array)[index] = (byte) value;
|
return (array, index, value) -> ((byte[]) array)[index] = (byte) value;
|
||||||
case "float":
|
case "float":
|
||||||
return (array, index, value) -> ((float[]) array)[index] = (float) value;
|
return (array, index, value) -> ((float[]) array)[index] = (float) value;
|
||||||
case "char":
|
case "char":
|
||||||
return (array, index, value) -> ((char[]) array)[index] = (char) value;
|
return (array, index, value) -> ((char[]) array)[index] = (char) value;
|
||||||
case "void":
|
case "void":
|
||||||
default:
|
default:
|
||||||
throw new InternalError("This should not happen");
|
throw new InternalError("This should not happen");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
package io.dico.dicore.command.parameter;
|
package io.dico.dicore.command.parameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface to process tokens such as quotes
|
* An interface to process tokens such as quotes
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public interface IArgumentPreProcessor {
|
public interface IArgumentPreProcessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preprocess the arguments contained within the given ArgumentBuffer.
|
* Preprocess the arguments contained within the given ArgumentBuffer.
|
||||||
* If no changes are made, this might return the same buffer.
|
* If no changes are made, this might return the same buffer.
|
||||||
* Any arguments preceding {@code buffer.getCursor()} will not be affected.
|
* Any arguments preceding {@code buffer.getCursor()} will not be affected.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If {@code count} is non-negative, it declares a limit on the number of arguments after preprocessing.
|
* If {@code count} is non-negative, it declares a limit on the number of arguments after preprocessing.
|
||||||
* In that case, the buffer's cursor is set to the index of the first argument following processed arguments.
|
* In that case, the buffer's cursor is set to the index of the first argument following processed arguments.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param buffer the argument buffer
|
* @param buffer the argument buffer
|
||||||
* @param count the maximum number of (processed) arguments
|
* @param count the maximum number of (processed) arguments
|
||||||
* @return the arguments after preprocessing
|
* @return the arguments after preprocessing
|
||||||
*/
|
*/
|
||||||
ArgumentBuffer process(ArgumentBuffer buffer, int count);
|
ArgumentBuffer process(ArgumentBuffer buffer, int count);
|
||||||
|
|
||||||
IArgumentPreProcessor NONE = (buffer, count) -> buffer;
|
IArgumentPreProcessor NONE = (buffer, count) -> buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an IArgumentPreProcessor that merges arguments between any two tokens
|
* Get an IArgumentPreProcessor that merges arguments between any two tokens
|
||||||
*
|
*
|
||||||
* @param tokens The tokens that the merged arguments should be enclosed by, in subsequent pairs.
|
* @param tokens The tokens that the merged arguments should be enclosed by, in subsequent pairs.
|
||||||
* Example: []{}""
|
* Example: []{}""
|
||||||
* This would mean the following would be merged: [ hello this is a merged argument]
|
* This would mean the following would be merged: [ hello this is a merged argument]
|
||||||
* @param escapeChar the char that can be used to escape the given tokens
|
* @param escapeChar the char that can be used to escape the given tokens
|
||||||
* @return The IArgumentPreProcessor
|
* @return The IArgumentPreProcessor
|
||||||
*/
|
*/
|
||||||
static IArgumentPreProcessor mergeOnTokens(String tokens, char escapeChar) {
|
static IArgumentPreProcessor mergeOnTokens(String tokens, char escapeChar) {
|
||||||
return new ArgumentMergingPreProcessor(tokens, escapeChar);
|
return new ArgumentMergingPreProcessor(tokens, escapeChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,148 +1,148 @@
|
|||||||
package io.dico.dicore.command.parameter;
|
package io.dico.dicore.command.parameter;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IParameter definition for a command
|
* IParameter definition for a command
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
public class ParameterList {
|
public class ParameterList {
|
||||||
//private ParameterList parent;
|
//private ParameterList parent;
|
||||||
private List<Parameter<?, ?>> indexedParameters;
|
private List<Parameter<?, ?>> indexedParameters;
|
||||||
private Map<String, Parameter<?, ?>> byName;
|
private Map<String, Parameter<?, ?>> byName;
|
||||||
//private IArgumentPreProcessor argumentPreProcessor = IArgumentPreProcessor.NONE;
|
//private IArgumentPreProcessor argumentPreProcessor = IArgumentPreProcessor.NONE;
|
||||||
private int requiredCount = -1;
|
private int requiredCount = -1;
|
||||||
private boolean repeatFinalParameter;
|
private boolean repeatFinalParameter;
|
||||||
|
|
||||||
// if the final parameter is repeated and the command is implemented through reflection,
|
// if the final parameter is repeated and the command is implemented through reflection,
|
||||||
// the repeated parameter is simply the last parameter of the method, rather than the last
|
// the repeated parameter is simply the last parameter of the method, rather than the last
|
||||||
// indexed parameter. This might be a flag. As such, this field exists to ensure the correct
|
// indexed parameter. This might be a flag. As such, this field exists to ensure the correct
|
||||||
// parameter is taken for repeating
|
// parameter is taken for repeating
|
||||||
private boolean finalParameterMayBeFlag;
|
private boolean finalParameterMayBeFlag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public ParameterList(ParameterList parent) {
|
public ParameterList(ParameterList parent) {
|
||||||
this();
|
this();
|
||||||
if (parent.repeatFinalParameter) {
|
if (parent.repeatFinalParameter) {
|
||||||
throw new IllegalArgumentException("Parent may not have repeating parameters");
|
throw new IllegalArgumentException("Parent may not have repeating parameters");
|
||||||
}
|
}
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public ParameterList() {
|
public ParameterList() {
|
||||||
this.indexedParameters = new ArrayList<>();
|
this.indexedParameters = new ArrayList<>();
|
||||||
this.byName = new LinkedHashMap<>();
|
this.byName = new LinkedHashMap<>();
|
||||||
this.repeatFinalParameter = false;
|
this.repeatFinalParameter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public IArgumentPreProcessor getArgumentPreProcessor() {
|
public IArgumentPreProcessor getArgumentPreProcessor() {
|
||||||
return argumentPreProcessor;
|
return argumentPreProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterList setArgumentPreProcessor(IArgumentPreProcessor argumentPreProcessor) {
|
public ParameterList setArgumentPreProcessor(IArgumentPreProcessor argumentPreProcessor) {
|
||||||
this.argumentPreProcessor = argumentPreProcessor == null ? IArgumentPreProcessor.NONE : argumentPreProcessor;
|
this.argumentPreProcessor = argumentPreProcessor == null ? IArgumentPreProcessor.NONE : argumentPreProcessor;
|
||||||
return this;
|
return this;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public boolean repeatFinalParameter() {
|
public boolean repeatFinalParameter() {
|
||||||
return repeatFinalParameter;
|
return repeatFinalParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterList setRepeatFinalParameter(boolean repeatFinalParameter) {
|
public ParameterList setRepeatFinalParameter(boolean repeatFinalParameter) {
|
||||||
this.repeatFinalParameter = repeatFinalParameter;
|
this.repeatFinalParameter = repeatFinalParameter;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean finalParameterMayBeFlag() {
|
public boolean finalParameterMayBeFlag() {
|
||||||
return finalParameterMayBeFlag;
|
return finalParameterMayBeFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterList setFinalParameterMayBeFlag(boolean finalParameterMayBeFlag) {
|
public ParameterList setFinalParameterMayBeFlag(boolean finalParameterMayBeFlag) {
|
||||||
this.finalParameterMayBeFlag = finalParameterMayBeFlag;
|
this.finalParameterMayBeFlag = finalParameterMayBeFlag;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRequiredCount() {
|
public int getRequiredCount() {
|
||||||
return requiredCount == -1 ? indexedParameters.size() : requiredCount;
|
return requiredCount == -1 ? indexedParameters.size() : requiredCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterList setRequiredCount(int requiredCount) {
|
public ParameterList setRequiredCount(int requiredCount) {
|
||||||
this.requiredCount = requiredCount;
|
this.requiredCount = requiredCount;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAnyParameters() {
|
public boolean hasAnyParameters() {
|
||||||
return !byName.isEmpty();
|
return !byName.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIndexedParameterCount() {
|
public int getIndexedParameterCount() {
|
||||||
return indexedParameters.size();
|
return indexedParameters.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Parameter<?, ?>> getIndexedParameters() {
|
public List<Parameter<?, ?>> getIndexedParameters() {
|
||||||
return Collections.unmodifiableList(indexedParameters);
|
return Collections.unmodifiableList(indexedParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameter<?, ?> getParameterByName(String name) {
|
public Parameter<?, ?> getParameterByName(String name) {
|
||||||
return byName.get(name);
|
return byName.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getIndexedParameterName(int index) {
|
public String getIndexedParameterName(int index) {
|
||||||
return indexedParameters.get(index).getName();
|
return indexedParameters.get(index).getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Parameter<?, ?>> getParametersByName() {
|
public Map<String, Parameter<?, ?>> getParametersByName() {
|
||||||
return Collections.unmodifiableMap(byName);
|
return Collections.unmodifiableMap(byName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the given parameter to the end of this parameter list
|
* Add the given parameter to the end of this parameter list
|
||||||
* Can be a flag
|
* Can be a flag
|
||||||
*
|
*
|
||||||
* @param parameter the parameter
|
* @param parameter the parameter
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public ParameterList addParameter(Parameter<?, ?> parameter) {
|
public ParameterList addParameter(Parameter<?, ?> parameter) {
|
||||||
return addParameter(-1, parameter);
|
return addParameter(-1, parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the given parameter to this parameter list
|
* Add the given parameter to this parameter list
|
||||||
* If the parameter is a flag, the index is ignored
|
* If the parameter is a flag, the index is ignored
|
||||||
*
|
*
|
||||||
* @param index parameter index number, -1 if end
|
* @param index parameter index number, -1 if end
|
||||||
* @param parameter the parameter
|
* @param parameter the parameter
|
||||||
* @return this
|
* @return this
|
||||||
* @throws NullPointerException if parameter is null
|
* @throws NullPointerException if parameter is null
|
||||||
*/
|
*/
|
||||||
public ParameterList addParameter(int index, Parameter<?, ?> parameter) {
|
public ParameterList addParameter(int index, Parameter<?, ?> parameter) {
|
||||||
//System.out.println("Added parameter " + parameter.getName() + ", flag: " + parameter.isFlag());
|
//System.out.println("Added parameter " + parameter.getName() + ", flag: " + parameter.isFlag());
|
||||||
byName.put(parameter.getName(), parameter);
|
byName.put(parameter.getName(), parameter);
|
||||||
if (!parameter.isFlag()) {
|
if (!parameter.isFlag()) {
|
||||||
indexedParameters.add(index == -1 ? indexedParameters.size() : index, parameter);
|
indexedParameters.add(index == -1 ? indexedParameters.size() : index, parameter);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameter<?, ?> getRepeatedParameter() {
|
public Parameter<?, ?> getRepeatedParameter() {
|
||||||
if (!repeatFinalParameter) {
|
if (!repeatFinalParameter) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (finalParameterMayBeFlag) {
|
if (finalParameterMayBeFlag) {
|
||||||
Iterator<Parameter<?, ?>> iterator = byName.values().iterator();
|
Iterator<Parameter<?, ?>> iterator = byName.values().iterator();
|
||||||
Parameter<?, ?> result = null;
|
Parameter<?, ?> result = null;
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
result = iterator.next();
|
result = iterator.next();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexedParameters.isEmpty()) {
|
if (indexedParameters.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexedParameters.get(indexedParameters.size() - 1);
|
return indexedParameters.get(indexedParameters.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,46 @@
|
|||||||
package io.dico.dicore.command.parameter.type;
|
package io.dico.dicore.command.parameter.type;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class EnumParameterType<E extends Enum> extends SimpleParameterType<E, Void> {
|
public class EnumParameterType<E extends Enum> extends SimpleParameterType<E, Void> {
|
||||||
private final E[] universe;
|
private final E[] universe;
|
||||||
|
|
||||||
public EnumParameterType(Class<E> returnType) {
|
public EnumParameterType(Class<E> returnType) {
|
||||||
super(returnType);
|
super(returnType);
|
||||||
universe = returnType.getEnumConstants();
|
universe = returnType.getEnumConstants();
|
||||||
if (universe == null) {
|
if (universe == null) {
|
||||||
throw new IllegalArgumentException("returnType must be an enum");
|
throw new IllegalArgumentException("returnType must be an enum");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected E parse(Parameter<E, Void> parameter, CommandSender sender, String input) throws CommandException {
|
protected E parse(Parameter<E, Void> parameter, CommandSender sender, String input) throws CommandException {
|
||||||
for (E constant : universe) {
|
for (E constant : universe) {
|
||||||
if (constant.name().equalsIgnoreCase(input)) {
|
if (constant.name().equalsIgnoreCase(input)) {
|
||||||
return constant;
|
return constant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw CommandException.invalidArgument(parameter.getName(), "the enum value does not exist");
|
throw CommandException.invalidArgument(parameter.getName(), "the enum value does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> complete(Parameter<E, Void> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
|
public List<String> complete(Parameter<E, Void> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
|
||||||
String input = buffer.next().toUpperCase();
|
String input = buffer.next().toUpperCase();
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
for (E constant : universe) {
|
for (E constant : universe) {
|
||||||
if (constant.name().toUpperCase().startsWith(input.toUpperCase())) {
|
if (constant.name().toUpperCase().startsWith(input.toUpperCase())) {
|
||||||
result.add(constant.name().toLowerCase());
|
result.add(constant.name().toLowerCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
package io.dico.dicore.command.parameter.type;
|
package io.dico.dicore.command.parameter.type;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for an object that stores parameter types by {@link ParameterKey} and finds appropriate types for {@link ParameterKey parameterKeys}
|
* An interface for an object that stores parameter types by {@link ParameterKey} and finds appropriate types for {@link ParameterKey parameterKeys}
|
||||||
*/
|
*/
|
||||||
public interface IParameterTypeSelector {
|
public interface IParameterTypeSelector {
|
||||||
|
|
||||||
<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key);
|
<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key);
|
||||||
|
|
||||||
//<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(ParameterKey key);
|
//<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(ParameterKey key);
|
||||||
|
|
||||||
<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key);
|
<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key);
|
||||||
|
|
||||||
|
|
||||||
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType) {
|
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType) {
|
||||||
return selectExact(returnType, null);
|
return selectExact(returnType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType, Class<? extends Annotation> annotationClass) {
|
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType, Class<? extends Annotation> annotationClass) {
|
||||||
return selectExact(new ParameterKey(returnType, annotationClass));
|
return selectExact(new ParameterKey(returnType, annotationClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType) {
|
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType) {
|
||||||
return selectExactOrSubclass(returnType, null);
|
return selectExactOrSubclass(returnType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType, Class<? extends Annotation> annotationClass) {
|
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType, Class<? extends Annotation> annotationClass) {
|
||||||
return selectExactOrSubclass(new ParameterKey(returnType, annotationClass));
|
return selectExactOrSubclass(new ParameterKey(returnType, annotationClass));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType) {
|
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType) {
|
||||||
return selectAny(returnType, null);
|
return selectAny(returnType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType, Class<? extends Annotation> annotationClass) {
|
default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType, Class<? extends Annotation> annotationClass) {
|
||||||
return selectAny(new ParameterKey(returnType, annotationClass));
|
return selectAny(new ParameterKey(returnType, annotationClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addType(boolean infolessAlias, ParameterType<?, ?> type);
|
void addType(boolean infolessAlias, ParameterType<?, ?> type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,114 +1,114 @@
|
|||||||
package io.dico.dicore.command.parameter.type;
|
package io.dico.dicore.command.parameter.type;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map based implementation of {@link IParameterTypeSelector}
|
* Map based implementation of {@link IParameterTypeSelector}
|
||||||
*/
|
*/
|
||||||
public class MapBasedParameterTypeSelector implements IParameterTypeSelector {
|
public class MapBasedParameterTypeSelector implements IParameterTypeSelector {
|
||||||
static final MapBasedParameterTypeSelector defaultSelector = new MapBasedParameterTypeSelector(false);
|
static final MapBasedParameterTypeSelector defaultSelector = new MapBasedParameterTypeSelector(false);
|
||||||
private final Map<ParameterKey, ParameterType<?, ?>> parameterTypeMap;
|
private final Map<ParameterKey, ParameterType<?, ?>> parameterTypeMap;
|
||||||
private final boolean useDefault;
|
private final boolean useDefault;
|
||||||
|
|
||||||
public MapBasedParameterTypeSelector(boolean useDefault) {
|
public MapBasedParameterTypeSelector(boolean useDefault) {
|
||||||
this.parameterTypeMap = new HashMap<>();
|
this.parameterTypeMap = new HashMap<>();
|
||||||
this.useDefault = useDefault;
|
this.useDefault = useDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key) {
|
public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key) {
|
||||||
ParameterType<?, ?> out = parameterTypeMap.get(key);
|
ParameterType<?, ?> out = parameterTypeMap.get(key);
|
||||||
if (useDefault && out == null) {
|
if (useDefault && out == null) {
|
||||||
out = defaultSelector.selectExact(key);
|
out = defaultSelector.selectExact(key);
|
||||||
}
|
}
|
||||||
if (out == null && key.getReturnType().isEnum()) {
|
if (out == null && key.getReturnType().isEnum()) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
out = new EnumParameterType(key.getReturnType());
|
out = new EnumParameterType(key.getReturnType());
|
||||||
addType(false, out);
|
addType(false, out);
|
||||||
}
|
}
|
||||||
return cast(out);
|
return cast(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key) {
|
public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key) {
|
||||||
ParameterType<TReturn, TParamInfo> exact = selectExact(key);
|
ParameterType<TReturn, TParamInfo> exact = selectExact(key);
|
||||||
if (exact != null) {
|
if (exact != null) {
|
||||||
return exact;
|
return exact;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.getAnnotationClass() != null) {
|
if (key.getAnnotationClass() != null) {
|
||||||
exact = selectExact(new ParameterKey(key.getReturnType()));
|
exact = selectExact(new ParameterKey(key.getReturnType()));
|
||||||
if (exact != null) {
|
if (exact != null) {
|
||||||
return exact;
|
return exact;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> returnType = key.getReturnType();
|
Class<?> returnType = key.getReturnType();
|
||||||
Class<? extends Annotation> annotationClass = key.getAnnotationClass();
|
Class<? extends Annotation> annotationClass = key.getAnnotationClass();
|
||||||
|
|
||||||
ParameterType<?, ?> out = selectByReturnType(parameterTypeMap, returnType, annotationClass, false);
|
ParameterType<?, ?> out = selectByReturnType(parameterTypeMap, returnType, annotationClass, false);
|
||||||
if (out == null && useDefault) {
|
if (out == null && useDefault) {
|
||||||
out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, false);
|
out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, false);
|
||||||
}
|
}
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
out = selectByReturnType(parameterTypeMap, returnType, annotationClass, true);
|
out = selectByReturnType(parameterTypeMap, returnType, annotationClass, true);
|
||||||
}
|
}
|
||||||
if (out == null && useDefault) {
|
if (out == null && useDefault) {
|
||||||
out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, true);
|
out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, true);
|
||||||
}
|
}
|
||||||
return cast(out);
|
return cast(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ParameterType<?, ?> selectByReturnType(Map<ParameterKey, ParameterType<?, ?>> map, Class<?> returnType,
|
private static ParameterType<?, ?> selectByReturnType(Map<ParameterKey, ParameterType<?, ?>> map, Class<?> returnType,
|
||||||
Class<? extends Annotation> annotationClass, boolean allowSubclass) {
|
Class<? extends Annotation> annotationClass, boolean allowSubclass) {
|
||||||
ParameterType<?, ?> out = null;
|
ParameterType<?, ?> out = null;
|
||||||
if (allowSubclass) {
|
if (allowSubclass) {
|
||||||
for (ParameterType<?, ?> type : map.values()) {
|
for (ParameterType<?, ?> type : map.values()) {
|
||||||
if (returnType.isAssignableFrom(type.getReturnType())) {
|
if (returnType.isAssignableFrom(type.getReturnType())) {
|
||||||
if (annotationClass == type.getAnnotationClass()) {
|
if (annotationClass == type.getAnnotationClass()) {
|
||||||
out = type;
|
out = type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
out = type;
|
out = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (ParameterType<?, ?> type : map.values()) {
|
for (ParameterType<?, ?> type : map.values()) {
|
||||||
if (returnType == type.getReturnType()) {
|
if (returnType == type.getReturnType()) {
|
||||||
if (annotationClass == type.getAnnotationClass()) {
|
if (annotationClass == type.getAnnotationClass()) {
|
||||||
out = type;
|
out = type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
out = type;
|
out = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> T cast(Object o) {
|
private static <T> T cast(Object o) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (T) o;
|
return (T) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addType(boolean infolessAlias, ParameterType<?, ?> type) {
|
public void addType(boolean infolessAlias, ParameterType<?, ?> type) {
|
||||||
parameterTypeMap.put(type.getTypeKey(), type);
|
parameterTypeMap.put(type.getTypeKey(), type);
|
||||||
|
|
||||||
if (infolessAlias) {
|
if (infolessAlias) {
|
||||||
parameterTypeMap.putIfAbsent(type.getInfolessTypeKey(), type);
|
parameterTypeMap.putIfAbsent(type.getInfolessTypeKey(), type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// registers default parameter types
|
// registers default parameter types
|
||||||
ParameterTypes.clinit();
|
ParameterTypes.clinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,80 +1,80 @@
|
|||||||
package io.dico.dicore.command.parameter.type;
|
package io.dico.dicore.command.parameter.type;
|
||||||
|
|
||||||
import io.dico.dicore.Reflection;
|
import io.dico.dicore.Reflection;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class serves the purpose of having annotated parameter configurations (such as ranges for number parameters).
|
* This class serves the purpose of having annotated parameter configurations (such as ranges for number parameters).
|
||||||
* Such configurations must be possible to obtain without using annotations, and as such, there should be a class conveying the information
|
* Such configurations must be possible to obtain without using annotations, and as such, there should be a class conveying the information
|
||||||
* that is separate from the annotation itself. This class acts as a bridge from the annotation to said class conveying the information.
|
* that is separate from the annotation itself. This class acts as a bridge from the annotation to said class conveying the information.
|
||||||
*
|
*
|
||||||
* @param <TAnnotation> the annotation type for parameters
|
* @param <TAnnotation> the annotation type for parameters
|
||||||
* @param <TParamInfo> the object type that holds the information required in memory
|
* @param <TParamInfo> the object type that holds the information required in memory
|
||||||
*/
|
*/
|
||||||
public abstract class ParameterConfig<TAnnotation extends Annotation, TParamInfo> implements Comparable<ParameterConfig<?, ?>> {
|
public abstract class ParameterConfig<TAnnotation extends Annotation, TParamInfo> implements Comparable<ParameterConfig<?, ?>> {
|
||||||
private final Class<TAnnotation> annotationClass;
|
private final Class<TAnnotation> annotationClass;
|
||||||
// protected final TParamInfo defaultValue;
|
// protected final TParamInfo defaultValue;
|
||||||
|
|
||||||
public ParameterConfig(Class<TAnnotation> annotationClass/*, TParamInfo defaultValue*/) {
|
public ParameterConfig(Class<TAnnotation> annotationClass/*, TParamInfo defaultValue*/) {
|
||||||
this.annotationClass = annotationClass;
|
this.annotationClass = annotationClass;
|
||||||
//this.defaultValue = defaultValue;
|
//this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Class<TAnnotation> getAnnotationClass() {
|
public final Class<TAnnotation> getAnnotationClass() {
|
||||||
return annotationClass;
|
return annotationClass;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
public TParamInfo getDefaultValue() {
|
public TParamInfo getDefaultValue() {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
protected abstract TParamInfo toParameterInfo(TAnnotation annotation);
|
protected abstract TParamInfo toParameterInfo(TAnnotation annotation);
|
||||||
|
|
||||||
public TParamInfo getParameterInfo(Annotation annotation) {
|
public TParamInfo getParameterInfo(Annotation annotation) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return toParameterInfo((TAnnotation) annotation);
|
return toParameterInfo((TAnnotation) annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo>
|
public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo>
|
||||||
includeMemoryClass(Class<TAnnotation> annotationClass, Class<TParamInfo> memoryClass) {
|
includeMemoryClass(Class<TAnnotation> annotationClass, Class<TParamInfo> memoryClass) {
|
||||||
Constructor<TParamInfo> constructor;
|
Constructor<TParamInfo> constructor;
|
||||||
//TParamInfo defaultValue;
|
//TParamInfo defaultValue;
|
||||||
try {
|
try {
|
||||||
constructor = memoryClass.getConstructor(annotationClass);
|
constructor = memoryClass.getConstructor(annotationClass);
|
||||||
//defaultValue = Reflection.getStaticFieldValue(annotationClass, "DEFAULT");
|
//defaultValue = Reflection.getStaticFieldValue(annotationClass, "DEFAULT");
|
||||||
} catch (NoSuchMethodException | IllegalArgumentException ex) {
|
} catch (NoSuchMethodException | IllegalArgumentException ex) {
|
||||||
throw new IllegalArgumentException(ex);
|
throw new IllegalArgumentException(ex);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if (defaultValue == null) try {
|
if (defaultValue == null) try {
|
||||||
defaultValue = memoryClass.newInstance();
|
defaultValue = memoryClass.newInstance();
|
||||||
} catch (IllegalAccessException | InstantiationException ex) {
|
} catch (IllegalAccessException | InstantiationException ex) {
|
||||||
throw new IllegalArgumentException("Failed to get a default value for the param info", ex);
|
throw new IllegalArgumentException("Failed to get a default value for the param info", ex);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
return new ParameterConfig<TAnnotation, TParamInfo>(annotationClass/*, defaultValue*/) {
|
return new ParameterConfig<TAnnotation, TParamInfo>(annotationClass/*, defaultValue*/) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TParamInfo toParameterInfo(TAnnotation annotation) {
|
public TParamInfo toParameterInfo(TAnnotation annotation) {
|
||||||
try {
|
try {
|
||||||
return constructor.newInstance(annotation);
|
return constructor.newInstance(annotation);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo> getMemoryClassFromField(Class<TAnnotation> annotationClass) {
|
public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo> getMemoryClassFromField(Class<TAnnotation> annotationClass) {
|
||||||
return ParameterConfig.includeMemoryClass(annotationClass, Reflection.getStaticFieldValue(annotationClass, "MEMORY_CLASS"));
|
return ParameterConfig.includeMemoryClass(annotationClass, Reflection.getStaticFieldValue(annotationClass, "MEMORY_CLASS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(ParameterConfig<?, ?> o) {
|
public int compareTo(ParameterConfig<?, ?> o) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,149 +1,149 @@
|
|||||||
package io.dico.dicore.command.parameter.type;
|
package io.dico.dicore.command.parameter.type;
|
||||||
|
|
||||||
import io.dico.dicore.Reflection;
|
import io.dico.dicore.Reflection;
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.annotation.Range;
|
import io.dico.dicore.command.annotation.Range;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parameter type.
|
* A parameter type.
|
||||||
* Takes care of parsing, default values as well as completions.
|
* Takes care of parsing, default values as well as completions.
|
||||||
*
|
*
|
||||||
* @param <TReturn> type of the parameter
|
* @param <TReturn> type of the parameter
|
||||||
* @param <TParamInfo> the info object type for the parameter (Example: {@link Range.Memory}
|
* @param <TParamInfo> the info object type for the parameter (Example: {@link Range.Memory}
|
||||||
*/
|
*/
|
||||||
public abstract class ParameterType<TReturn, TParamInfo> {
|
public abstract class ParameterType<TReturn, TParamInfo> {
|
||||||
private final Class<TReturn> returnType;
|
private final Class<TReturn> returnType;
|
||||||
private final ParameterConfig<?, TParamInfo> parameterConfig;
|
private final ParameterConfig<?, TParamInfo> parameterConfig;
|
||||||
protected final ParameterType<TReturn, TParamInfo> otherType; // flag or non-flag, depending on current
|
protected final ParameterType<TReturn, TParamInfo> otherType; // flag or non-flag, depending on current
|
||||||
|
|
||||||
public ParameterType(Class<TReturn> returnType) {
|
public ParameterType(Class<TReturn> returnType) {
|
||||||
this(returnType, null);
|
this(returnType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
|
public ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
|
||||||
this.returnType = Objects.requireNonNull(returnType);
|
this.returnType = Objects.requireNonNull(returnType);
|
||||||
this.parameterConfig = paramConfig;
|
this.parameterConfig = paramConfig;
|
||||||
|
|
||||||
ParameterType<TReturn, TParamInfo> otherType = flagTypeParameter();
|
ParameterType<TReturn, TParamInfo> otherType = flagTypeParameter();
|
||||||
this.otherType = otherType == null ? this : otherType;
|
this.otherType = otherType == null ? this : otherType;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> parameterConfig, ParameterType<TReturn, TParamInfo> otherType) {
|
protected ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> parameterConfig, ParameterType<TReturn, TParamInfo> otherType) {
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
this.parameterConfig = parameterConfig;
|
this.parameterConfig = parameterConfig;
|
||||||
this.otherType = otherType;
|
this.otherType = otherType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExpectedAmountOfConsumedArguments() {
|
public int getExpectedAmountOfConsumedArguments() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canBeFlag() {
|
public boolean canBeFlag() {
|
||||||
return this == otherType;
|
return this == otherType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFlagExplicitly() {
|
public boolean isFlagExplicitly() {
|
||||||
return this instanceof FlagParameterType;
|
return this instanceof FlagParameterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The return type
|
* @return The return type
|
||||||
*/
|
*/
|
||||||
public final Class<TReturn> getReturnType() {
|
public final Class<TReturn> getReturnType() {
|
||||||
return returnType;
|
return returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Class<?> getAnnotationClass() {
|
public final Class<?> getAnnotationClass() {
|
||||||
return parameterConfig == null ? null : parameterConfig.getAnnotationClass();
|
return parameterConfig == null ? null : parameterConfig.getAnnotationClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ParameterConfig<?, TParamInfo> getParameterConfig() {
|
public final ParameterConfig<?, TParamInfo> getParameterConfig() {
|
||||||
return parameterConfig;
|
return parameterConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterKey getTypeKey() {
|
public ParameterKey getTypeKey() {
|
||||||
return new ParameterKey(returnType, parameterConfig != null ? parameterConfig.getAnnotationClass() : null);
|
return new ParameterKey(returnType, parameterConfig != null ? parameterConfig.getAnnotationClass() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterKey getInfolessTypeKey() {
|
public ParameterKey getInfolessTypeKey() {
|
||||||
return new ParameterKey(returnType, null);
|
return new ParameterKey(returnType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FlagParameterType<TReturn, TParamInfo> flagTypeParameter() {
|
protected FlagParameterType<TReturn, TParamInfo> flagTypeParameter() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterType<TReturn, TParamInfo> asFlagParameter() {
|
public ParameterType<TReturn, TParamInfo> asFlagParameter() {
|
||||||
return canBeFlag() ? this : otherType;
|
return canBeFlag() ? this : otherType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParameterType<TReturn, TParamInfo> asNormalParameter() {
|
public ParameterType<TReturn, TParamInfo> asNormalParameter() {
|
||||||
return isFlagExplicitly() ? otherType : this;
|
return isFlagExplicitly() ? otherType : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException;
|
public abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException;
|
||||||
|
|
||||||
public TReturn parseForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
public TReturn parseForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
||||||
return parse(parameter, context.getSender(), buffer);
|
return parse(parameter, context.getSender(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TReturn getDefaultValue(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
|
public TReturn getDefaultValue(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TReturn getDefaultValueForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
public TReturn getDefaultValueForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
||||||
return getDefaultValue(parameter, context.getSender(), buffer);
|
return getDefaultValue(parameter, context.getSender(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> complete(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
|
public List<String> complete(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> completeForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, Location location, ArgumentBuffer buffer) {
|
public List<String> completeForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, Location location, ArgumentBuffer buffer) {
|
||||||
return complete(parameter, context.getSender(), location, buffer);
|
return complete(parameter, context.getSender(), location, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static abstract class FlagParameterType<TResult, TParamInfo> extends ParameterType<TResult, TParamInfo> {
|
protected static abstract class FlagParameterType<TResult, TParamInfo> extends ParameterType<TResult, TParamInfo> {
|
||||||
|
|
||||||
protected FlagParameterType(ParameterType<TResult, TParamInfo> otherType) {
|
protected FlagParameterType(ParameterType<TResult, TParamInfo> otherType) {
|
||||||
super(otherType.returnType, otherType.parameterConfig, otherType);
|
super(otherType.returnType, otherType.parameterConfig, otherType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getExpectedAmountOfConsumedArguments() {
|
public int getExpectedAmountOfConsumedArguments() {
|
||||||
return otherType.getExpectedAmountOfConsumedArguments();
|
return otherType.getExpectedAmountOfConsumedArguments();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeFlag() {
|
public boolean canBeFlag() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final FlagParameterType<TResult, TParamInfo> flagTypeParameter() {
|
protected final FlagParameterType<TResult, TParamInfo> flagTypeParameter() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParameterType<TResult, TParamInfo> asFlagParameter() {
|
public ParameterType<TResult, TParamInfo> asFlagParameter() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParameterType<TResult, TParamInfo> asNormalParameter() {
|
public ParameterType<TResult, TParamInfo> asNormalParameter() {
|
||||||
return otherType;
|
return otherType;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
package io.dico.dicore.command.parameter.type;
|
package io.dico.dicore.command.parameter.type;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstraction for parameter types that only parse a single argument
|
* An abstraction for parameter types that only parse a single argument
|
||||||
*
|
*
|
||||||
* @param <TReturn> the parameter type
|
* @param <TReturn> the parameter type
|
||||||
* @param <TParamInfo> parameter info object type
|
* @param <TParamInfo> parameter info object type
|
||||||
*/
|
*/
|
||||||
public abstract class SimpleParameterType<TReturn, TParamInfo> extends ParameterType<TReturn, TParamInfo> {
|
public abstract class SimpleParameterType<TReturn, TParamInfo> extends ParameterType<TReturn, TParamInfo> {
|
||||||
|
|
||||||
public SimpleParameterType(Class<TReturn> returnType) {
|
public SimpleParameterType(Class<TReturn> returnType) {
|
||||||
super(returnType);
|
super(returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
|
public SimpleParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
|
||||||
super(returnType, paramConfig);
|
super(returnType, paramConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, String input) throws CommandException;
|
protected abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, String input) throws CommandException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
|
public TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
|
||||||
return parse(parameter, sender, buffer.requireNext(parameter.getName()));
|
return parse(parameter, sender, buffer.requireNext(parameter.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +1,56 @@
|
|||||||
package io.dico.dicore.command.predef;
|
package io.dico.dicore.command.predef;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
import io.dico.dicore.command.IContextFilter;
|
import io.dico.dicore.command.IContextFilter;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
public class DefaultGroupCommand extends PredefinedCommand<DefaultGroupCommand> {
|
public class DefaultGroupCommand extends PredefinedCommand<DefaultGroupCommand> {
|
||||||
private static final DefaultGroupCommand instance;
|
private static final DefaultGroupCommand instance;
|
||||||
private static final IContextFilter noArgumentFilter;
|
private static final IContextFilter noArgumentFilter;
|
||||||
|
|
||||||
public static DefaultGroupCommand getInstance() {
|
public static DefaultGroupCommand getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefaultGroupCommand(boolean modifiable) {
|
private DefaultGroupCommand(boolean modifiable) {
|
||||||
addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
|
addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
|
||||||
addContextFilter(noArgumentFilter);
|
addContextFilter(noArgumentFilter);
|
||||||
this.modifiable = modifiable;
|
this.modifiable = modifiable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DefaultGroupCommand() {
|
public DefaultGroupCommand() {
|
||||||
this(true);
|
this(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DefaultGroupCommand newModifiableInstance() {
|
protected DefaultGroupCommand newModifiableInstance() {
|
||||||
return new DefaultGroupCommand(true);
|
return new DefaultGroupCommand(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
||||||
context.getAddress().getChatHandler().sendHelpMessage(sender, context, context.getAddress(), 1);
|
context.getAddress().getChatHandler().sendHelpMessage(sender, context, context.getAddress(), 1);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
noArgumentFilter = new IContextFilter() {
|
noArgumentFilter = new IContextFilter() {
|
||||||
@Override
|
@Override
|
||||||
public void filterContext(ExecutionContext context) throws CommandException {
|
public void filterContext(ExecutionContext context) throws CommandException {
|
||||||
if (context.getBuffer().hasNext()) {
|
if (context.getBuffer().hasNext()) {
|
||||||
throw new CommandException("No such command: /" + context.getAddress().getAddress()
|
throw new CommandException("No such command: /" + context.getAddress().getAddress()
|
||||||
+ " " + context.getBuffer().next());
|
+ " " + context.getBuffer().next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Priority getPriority() {
|
public Priority getPriority() {
|
||||||
return Priority.EARLY;
|
return Priority.EARLY;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
instance = new DefaultGroupCommand(false);
|
instance = new DefaultGroupCommand(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,76 @@
|
|||||||
package io.dico.dicore.command.predef;
|
package io.dico.dicore.command.predef;
|
||||||
|
|
||||||
import io.dico.dicore.command.*;
|
import io.dico.dicore.command.*;
|
||||||
import io.dico.dicore.command.annotation.Range;
|
import io.dico.dicore.command.annotation.Range;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import io.dico.dicore.command.parameter.type.NumberParameterType;
|
import io.dico.dicore.command.parameter.type.NumberParameterType;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The help command
|
* The help command
|
||||||
*/
|
*/
|
||||||
public class HelpCommand extends PredefinedCommand<HelpCommand> {
|
public class HelpCommand extends PredefinedCommand<HelpCommand> {
|
||||||
private static final Parameter<Integer, Range.Memory> pageParameter;
|
private static final Parameter<Integer, Range.Memory> pageParameter;
|
||||||
public static final HelpCommand INSTANCE;
|
public static final HelpCommand INSTANCE;
|
||||||
|
|
||||||
private HelpCommand(boolean modifiable) {
|
private HelpCommand(boolean modifiable) {
|
||||||
super(modifiable);
|
super(modifiable);
|
||||||
getParameterList().addParameter(pageParameter);
|
getParameterList().addParameter(pageParameter);
|
||||||
getParameterList().setRequiredCount(0);
|
getParameterList().setRequiredCount(0);
|
||||||
setDescription("Shows this help page");
|
setDescription("Shows this help page");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HelpCommand newModifiableInstance() {
|
protected HelpCommand newModifiableInstance() {
|
||||||
return new HelpCommand(true);
|
return new HelpCommand(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
||||||
ICommandAddress target = context.getAddress();
|
ICommandAddress target = context.getAddress();
|
||||||
if (context.getAddress().getCommand() == this) {
|
if (context.getAddress().getCommand() == this) {
|
||||||
target = target.getParent();
|
target = target.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
context.getAddress().getChatHandler().sendHelpMessage(sender, context, target, context.<Integer>get("page") - 1);
|
context.getAddress().getChatHandler().sendHelpMessage(sender, context, target, context.<Integer>get("page") - 1);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerAsChild(ICommandAddress address) {
|
public static void registerAsChild(ICommandAddress address) {
|
||||||
registerAsChild(address, "help");
|
registerAsChild(address, "help");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
|
public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
|
||||||
((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
|
((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
pageParameter = new Parameter<>("page", "the page number",
|
pageParameter = new Parameter<>("page", "the page number",
|
||||||
new NumberParameterType<Integer>(Integer.TYPE) {
|
new NumberParameterType<Integer>(Integer.TYPE) {
|
||||||
@Override
|
@Override
|
||||||
protected Integer parse(String input) throws NumberFormatException {
|
protected Integer parse(String input) throws NumberFormatException {
|
||||||
return Integer.parseInt(input);
|
return Integer.parseInt(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Integer select(Number number) {
|
protected Integer select(Number number) {
|
||||||
return number.intValue();
|
return number.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer parseForContext(Parameter<Integer, Range.Memory> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
public Integer parseForContext(Parameter<Integer, Range.Memory> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
|
||||||
if (context.getAddress().getCommand() == null || context.getAddress().getCommand().getClass() != HelpCommand.class) {
|
if (context.getAddress().getCommand() == null || context.getAddress().getCommand().getClass() != HelpCommand.class) {
|
||||||
// An address was executed with its help command as target
|
// An address was executed with its help command as target
|
||||||
buffer.next();
|
buffer.next();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return parse(parameter, context.getSender(), buffer);
|
return parse(parameter, context.getSender(), buffer);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Range.Memory(1, Integer.MAX_VALUE, 1));
|
new Range.Memory(1, Integer.MAX_VALUE, 1));
|
||||||
|
|
||||||
INSTANCE = new HelpCommand(false);
|
INSTANCE = new HelpCommand(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
package io.dico.dicore.command.predef;
|
package io.dico.dicore.command.predef;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandBuilder;
|
import io.dico.dicore.command.CommandBuilder;
|
||||||
import io.dico.dicore.command.ExtendedCommand;
|
import io.dico.dicore.command.ExtendedCommand;
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marker class for commands that are generated. These commands can be replaced using methods in {@link CommandBuilder}
|
* Marker class for commands that are generated. These commands can be replaced using methods in {@link CommandBuilder}
|
||||||
*/
|
*/
|
||||||
public abstract class PredefinedCommand<T extends PredefinedCommand<T>> extends ExtendedCommand<T> {
|
public abstract class PredefinedCommand<T extends PredefinedCommand<T>> extends ExtendedCommand<T> {
|
||||||
static final Map<String, Consumer<ICommandAddress>> predefinedCommandGenerators = new HashMap<>();
|
static final Map<String, Consumer<ICommandAddress>> predefinedCommandGenerators = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a predefined command
|
* Get a predefined command
|
||||||
*
|
*
|
||||||
* @param name the name
|
* @param name the name
|
||||||
* @return the subscriber
|
* @return the subscriber
|
||||||
*/
|
*/
|
||||||
public static Consumer<ICommandAddress> getPredefinedCommandGenerator(String name) {
|
public static Consumer<ICommandAddress> getPredefinedCommandGenerator(String name) {
|
||||||
return predefinedCommandGenerators.get(name);
|
return predefinedCommandGenerators.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a predefined command
|
* Register a predefined command
|
||||||
*
|
*
|
||||||
* @param name the name
|
* @param name the name
|
||||||
* @param consumer the generator which adds the child to the address
|
* @param consumer the generator which adds the child to the address
|
||||||
* @return true if and only if the subscriber was registered (false if the name exists)
|
* @return true if and only if the subscriber was registered (false if the name exists)
|
||||||
*/
|
*/
|
||||||
public static boolean registerPredefinedCommandGenerator(String name, Consumer<ICommandAddress> consumer) {
|
public static boolean registerPredefinedCommandGenerator(String name, Consumer<ICommandAddress> consumer) {
|
||||||
return predefinedCommandGenerators.putIfAbsent(name, consumer) == null;
|
return predefinedCommandGenerators.putIfAbsent(name, consumer) == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
registerPredefinedCommandGenerator("help", HelpCommand::registerAsChild);
|
registerPredefinedCommandGenerator("help", HelpCommand::registerAsChild);
|
||||||
//noinspection StaticInitializerReferencesSubClass
|
//noinspection StaticInitializerReferencesSubClass
|
||||||
registerPredefinedCommandGenerator("syntax", SyntaxCommand::registerAsChild);
|
registerPredefinedCommandGenerator("syntax", SyntaxCommand::registerAsChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PredefinedCommand() {
|
public PredefinedCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PredefinedCommand(boolean modifiable) {
|
public PredefinedCommand(boolean modifiable) {
|
||||||
super(modifiable);
|
super(modifiable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
package io.dico.dicore.command.predef;
|
package io.dico.dicore.command.predef;
|
||||||
|
|
||||||
import io.dico.dicore.command.*;
|
import io.dico.dicore.command.*;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The syntax command
|
* The syntax command
|
||||||
*/
|
*/
|
||||||
public class SyntaxCommand extends PredefinedCommand<SyntaxCommand> {
|
public class SyntaxCommand extends PredefinedCommand<SyntaxCommand> {
|
||||||
public static final SyntaxCommand INSTANCE = new SyntaxCommand(false);
|
public static final SyntaxCommand INSTANCE = new SyntaxCommand(false);
|
||||||
|
|
||||||
private SyntaxCommand(boolean modifiable) {
|
private SyntaxCommand(boolean modifiable) {
|
||||||
super(modifiable);
|
super(modifiable);
|
||||||
setDescription("Describes how to use the command");
|
setDescription("Describes how to use the command");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SyntaxCommand newModifiableInstance() {
|
protected SyntaxCommand newModifiableInstance() {
|
||||||
return new SyntaxCommand(true);
|
return new SyntaxCommand(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
||||||
context.getAddress().getChatHandler().sendSyntaxMessage(sender, context, context.getAddress().getParent());
|
context.getAddress().getChatHandler().sendSyntaxMessage(sender, context, context.getAddress().getParent());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerAsChild(ICommandAddress address) {
|
public static void registerAsChild(ICommandAddress address) {
|
||||||
registerAsChild(address, "syntax");
|
registerAsChild(address, "syntax");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
|
public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
|
||||||
((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
|
((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,122 +1,122 @@
|
|||||||
package io.dico.dicore.command.registration;
|
package io.dico.dicore.command.registration;
|
||||||
|
|
||||||
import io.dico.dicore.command.ICommandAddress;
|
import io.dico.dicore.command.ICommandAddress;
|
||||||
import io.dico.dicore.command.ICommandDispatcher;
|
import io.dico.dicore.command.ICommandDispatcher;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class extends the bukkit's command class.
|
* This class extends the bukkit's command class.
|
||||||
* Instances are injected into the command map.
|
* Instances are injected into the command map.
|
||||||
*/
|
*/
|
||||||
public class BukkitCommand extends Command {
|
public class BukkitCommand extends Command {
|
||||||
private ICommandDispatcher dispatcher;
|
private ICommandDispatcher dispatcher;
|
||||||
private ICommandAddress origin;
|
private ICommandAddress origin;
|
||||||
|
|
||||||
public BukkitCommand(ICommandAddress address) {
|
public BukkitCommand(ICommandAddress address) {
|
||||||
super(validateTree(address).getNames().get(0), "", "", address.getNames().subList(1, address.getNames().size()));
|
super(validateTree(address).getNames().get(0), "", "", address.getNames().subList(1, address.getNames().size()));
|
||||||
this.dispatcher = address.getDispatcherForTree();
|
this.dispatcher = address.getDispatcherForTree();
|
||||||
this.origin = address;
|
this.origin = address;
|
||||||
|
|
||||||
setTimingsIfNecessary(this);
|
setTimingsIfNecessary(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICommandAddress validateTree(ICommandAddress tree) {
|
private static ICommandAddress validateTree(ICommandAddress tree) {
|
||||||
if (!tree.hasParent()) {
|
if (!tree.hasParent()) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
if (tree.getNames().isEmpty()) {
|
if (tree.getNames().isEmpty()) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommandAddress getOrigin() {
|
public ICommandAddress getOrigin() {
|
||||||
return origin;
|
return origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender sender, String label, String[] args) {
|
public boolean execute(CommandSender sender, String label, String[] args) {
|
||||||
if (!dispatcher.dispatchCommand(sender, label, args)) {
|
if (!dispatcher.dispatchCommand(sender, label, args)) {
|
||||||
//System.out.println("failed to dispatch command");
|
//System.out.println("failed to dispatch command");
|
||||||
// target command not found, send a message in the future TODO
|
// target command not found, send a message in the future TODO
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
|
public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
|
||||||
return this.tabComplete(sender, alias, args, null);
|
return this.tabComplete(sender, alias, args, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Override
|
//@Override
|
||||||
public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
|
public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
|
||||||
return dispatcher.getTabCompletions(sender, alias, location, args);
|
return dispatcher.getTabCompletions(sender, alias, location, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
BukkitCommand that = (BukkitCommand) o;
|
BukkitCommand that = (BukkitCommand) o;
|
||||||
|
|
||||||
return getName().equals(that.getName()) && dispatcher == that.dispatcher;
|
return getName().equals(that.getName()) && dispatcher == that.dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return dispatcher.hashCode() | getName().hashCode();
|
return dispatcher.hashCode() | getName().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setTimingsIfNecessary(Command object) {
|
private static void setTimingsIfNecessary(Command object) {
|
||||||
// with paper spigot, the timings are not set by super constructor but by CommandMap.register(), which is not invoked for this system
|
// with paper spigot, the timings are not set by super constructor but by CommandMap.register(), which is not invoked for this system
|
||||||
// I use reflection so that the project does not require paper spigot to build
|
// I use reflection so that the project does not require paper spigot to build
|
||||||
try {
|
try {
|
||||||
// public field
|
// public field
|
||||||
Field field = Command.class.getDeclaredField("timings");
|
Field field = Command.class.getDeclaredField("timings");
|
||||||
if (field.get(object) != null) return;
|
if (field.get(object) != null) return;
|
||||||
Class<?> clazz = Class.forName("co.aikar.timings.TimingsManager");
|
Class<?> clazz = Class.forName("co.aikar.timings.TimingsManager");
|
||||||
// public method
|
// public method
|
||||||
Method method = clazz.getDeclaredMethod("getCommandTiming", String.class, Command.class);
|
Method method = clazz.getDeclaredMethod("getCommandTiming", String.class, Command.class);
|
||||||
Object timings = method.invoke(null, "", object);
|
Object timings = method.invoke(null, "", object);
|
||||||
field.set(object, timings);
|
field.set(object, timings);
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public static void registerToMap(ICommandAddress tree, Map<String, Command> map) {
|
public static void registerToMap(ICommandAddress tree, Map<String, Command> map) {
|
||||||
BukkitCommand command = new BukkitCommand(tree);
|
BukkitCommand command = new BukkitCommand(tree);
|
||||||
Iterator<String> iterator = tree.getNames().iterator();
|
Iterator<String> iterator = tree.getNames().iterator();
|
||||||
map.put(iterator.next(), command);
|
map.put(iterator.next(), command);
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
map.putIfAbsent(iterator.next(), command);
|
map.putIfAbsent(iterator.next(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unregisterFromMap(ICommandAddress tree, Map<String, Command> map) {
|
public static void unregisterFromMap(ICommandAddress tree, Map<String, Command> map) {
|
||||||
map.values().remove(new BukkitCommand(tree));
|
map.values().remove(new BukkitCommand(tree));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void registerChildrenToMap(ICommandAddress tree, Map<String, Command> map) {
|
public static void registerChildrenToMap(ICommandAddress tree, Map<String, Command> map) {
|
||||||
for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
|
for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
|
||||||
ICommandAddress child = entry.getValue();
|
ICommandAddress child = entry.getValue();
|
||||||
registerToMap(child, map);
|
registerToMap(child, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unregisterChildenFromMap(ICommandAddress tree, Map<String, Command> map) {
|
public static void unregisterChildenFromMap(ICommandAddress tree, Map<String, Command> map) {
|
||||||
for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
|
for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
|
||||||
ICommandAddress child = entry.getValue();
|
ICommandAddress child = entry.getValue();
|
||||||
unregisterFromMap(child, map);
|
unregisterFromMap(child, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
package io.dico.dicore.command.registration;
|
package io.dico.dicore.command.registration;
|
||||||
|
|
||||||
import io.dico.dicore.Reflection;
|
import io.dico.dicore.Reflection;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.SimpleCommandMap;
|
import org.bukkit.command.SimpleCommandMap;
|
||||||
import org.bukkit.plugin.SimplePluginManager;
|
import org.bukkit.plugin.SimplePluginManager;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to bukkit's {@code Map<String, org.bukkit.command.Command>} command map.
|
* Provides access to bukkit's {@code Map<String, org.bukkit.command.Command>} command map.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public class CommandMap {
|
public class CommandMap {
|
||||||
private static final Map<String, Command> commandMap = findCommandMap();
|
private static final Map<String, Command> commandMap = findCommandMap();
|
||||||
|
|
||||||
private CommandMap() {
|
private CommandMap() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, Command> getCommandMap() {
|
public static Map<String, Command> getCommandMap() {
|
||||||
return Objects.requireNonNull(commandMap);
|
return Objects.requireNonNull(commandMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAvailable() {
|
public static boolean isAvailable() {
|
||||||
return commandMap != null;
|
return commandMap != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Command get(String key) {
|
public static Command get(String key) {
|
||||||
return commandMap.get(key);
|
return commandMap.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void put(String key, Command command) {
|
public static void put(String key, Command command) {
|
||||||
commandMap.put(key, command);
|
commandMap.put(key, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Collection<String> replace(Command command, Command replacement) {
|
public static Collection<String> replace(Command command, Command replacement) {
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
for (Map.Entry<String, Command> entry : commandMap.entrySet()) {
|
for (Map.Entry<String, Command> entry : commandMap.entrySet()) {
|
||||||
if (entry.getValue() == command) {
|
if (entry.getValue() == command) {
|
||||||
entry.setValue(replacement);
|
entry.setValue(replacement);
|
||||||
result.add(entry.getKey());
|
result.add(entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, Command> findCommandMap() {
|
private static Map<String, Command> findCommandMap() {
|
||||||
try {
|
try {
|
||||||
return Reflection.getFieldValue(SimpleCommandMap.class, "knownCommands",
|
return Reflection.getFieldValue(SimpleCommandMap.class, "knownCommands",
|
||||||
Reflection.getFieldValue(SimplePluginManager.class, "commandMap", Bukkit.getPluginManager()));
|
Reflection.getFieldValue(SimplePluginManager.class, "commandMap", Bukkit.getPluginManager()));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
package io.dico.dicore.command.registration.reflect;
|
package io.dico.dicore.command.registration.reflect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown if an error occurs while 'parsing' a reflection command method
|
* Thrown if an error occurs while 'parsing' a reflection command method
|
||||||
* Other errors can be thrown too in there that may not be directly relevant to a parsing error.
|
* Other errors can be thrown too in there that may not be directly relevant to a parsing error.
|
||||||
*/
|
*/
|
||||||
public class CommandParseException extends Exception {
|
public class CommandParseException extends Exception {
|
||||||
|
|
||||||
public CommandParseException() {
|
public CommandParseException() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandParseException(String message) {
|
public CommandParseException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandParseException(String message, Throwable cause) {
|
public CommandParseException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandParseException(Throwable cause) {
|
public CommandParseException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
public CommandParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
super(message, cause, enableSuppression, writableStackTrace);
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
package io.dico.dicore.command.registration.reflect;
|
package io.dico.dicore.command.registration.reflect;
|
||||||
|
|
||||||
import io.dico.dicore.command.ExecutionContext;
|
import io.dico.dicore.command.ExecutionContext;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public interface ICommandInterceptor {
|
public interface ICommandInterceptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the receiver of the command, if applicable.
|
* Get the receiver of the command, if applicable.
|
||||||
* A command has a receiver if its first parameter implements {@link ICommandReceiver}
|
* A command has a receiver if its first parameter implements {@link ICommandReceiver}
|
||||||
* and its instance object implements this interface.
|
* and its instance object implements this interface.
|
||||||
*
|
*
|
||||||
* @param context the context of execution
|
* @param context the context of execution
|
||||||
* @param target the method of the command
|
* @param target the method of the command
|
||||||
* @param cmdName the name of the command
|
* @param cmdName the name of the command
|
||||||
* @return the receiver
|
* @return the receiver
|
||||||
*/
|
*/
|
||||||
default ICommandReceiver getReceiver(ExecutionContext context, Method target, String cmdName) {
|
default ICommandReceiver getReceiver(ExecutionContext context, Method target, String cmdName) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If applicable, get the coroutine context to use in suspend functions (Kotlin only).
|
* If applicable, get the coroutine context to use in suspend functions (Kotlin only).
|
||||||
* The return type is object to avoid depending on the kotlin runtime.
|
* The return type is object to avoid depending on the kotlin runtime.
|
||||||
*
|
*
|
||||||
* @param context the context of execution
|
* @param context the context of execution
|
||||||
* @param target the method of the command
|
* @param target the method of the command
|
||||||
* @param cmdName the name of the command
|
* @param cmdName the name of the command
|
||||||
* @return the coroutine context
|
* @return the coroutine context
|
||||||
*/
|
*/
|
||||||
default Object getCoroutineContext(ExecutionContext context, Method target, String cmdName) {
|
default Object getCoroutineContext(ExecutionContext context, Method target, String cmdName) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
package io.dico.dicore.command.registration.reflect;
|
package io.dico.dicore.command.registration.reflect;
|
||||||
|
|
||||||
public interface ICommandReceiver {
|
public interface ICommandReceiver {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,187 +1,187 @@
|
|||||||
package io.dico.dicore.command.registration.reflect;
|
package io.dico.dicore.command.registration.reflect;
|
||||||
|
|
||||||
import io.dico.dicore.command.*;
|
import io.dico.dicore.command.*;
|
||||||
import io.dico.dicore.command.annotation.Cmd;
|
import io.dico.dicore.command.annotation.Cmd;
|
||||||
import io.dico.dicore.command.annotation.GenerateCommands;
|
import io.dico.dicore.command.annotation.GenerateCommands;
|
||||||
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
public final class ReflectiveCommand extends Command {
|
public final class ReflectiveCommand extends Command {
|
||||||
private static final int continuationMask = 1 << 3;
|
private static final int continuationMask = 1 << 3;
|
||||||
private final Cmd cmdAnnotation;
|
private final Cmd cmdAnnotation;
|
||||||
private final Method method;
|
private final Method method;
|
||||||
private final Object instance;
|
private final Object instance;
|
||||||
private String[] parameterOrder;
|
private String[] parameterOrder;
|
||||||
|
|
||||||
// hasContinuation | hasContext | hasSender | hasReceiver
|
// hasContinuation | hasContext | hasSender | hasReceiver
|
||||||
private final int flags;
|
private final int flags;
|
||||||
|
|
||||||
ReflectiveCommand(IParameterTypeSelector selector, Method method, Object instance) throws CommandParseException {
|
ReflectiveCommand(IParameterTypeSelector selector, Method method, Object instance) throws CommandParseException {
|
||||||
if (!method.isAnnotationPresent(Cmd.class)) {
|
if (!method.isAnnotationPresent(Cmd.class)) {
|
||||||
throw new CommandParseException("No @Cmd present for the method " + method.toGenericString());
|
throw new CommandParseException("No @Cmd present for the method " + method.toGenericString());
|
||||||
}
|
}
|
||||||
cmdAnnotation = method.getAnnotation(Cmd.class);
|
cmdAnnotation = method.getAnnotation(Cmd.class);
|
||||||
|
|
||||||
java.lang.reflect.Parameter[] parameters = method.getParameters();
|
java.lang.reflect.Parameter[] parameters = method.getParameters();
|
||||||
|
|
||||||
if (!method.isAccessible()) try {
|
if (!method.isAccessible()) try {
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new CommandParseException("Failed to make method accessible");
|
throw new CommandParseException("Failed to make method accessible");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Modifier.isStatic(method.getModifiers())) {
|
if (!Modifier.isStatic(method.getModifiers())) {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
try {
|
try {
|
||||||
instance = method.getDeclaringClass().newInstance();
|
instance = method.getDeclaringClass().newInstance();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new CommandParseException("No instance given for instance method, and failed to create new instance", ex);
|
throw new CommandParseException("No instance given for instance method, and failed to create new instance", ex);
|
||||||
}
|
}
|
||||||
} else if (!method.getDeclaringClass().isInstance(instance)) {
|
} else if (!method.getDeclaringClass().isInstance(instance)) {
|
||||||
throw new CommandParseException("Given instance is not an instance of the method's declaring class");
|
throw new CommandParseException("Given instance is not an instance of the method's declaring class");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.flags = ReflectiveRegistration.parseCommandAttributes(selector, method, this, parameters);
|
this.flags = ReflectiveRegistration.parseCommandAttributes(selector, method, this, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Method getMethod() {
|
public Method getMethod() {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getInstance() {
|
public Object getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCmdName() { return cmdAnnotation.value(); }
|
public String getCmdName() { return cmdAnnotation.value(); }
|
||||||
|
|
||||||
void setParameterOrder(String[] parameterOrder) {
|
void setParameterOrder(String[] parameterOrder) {
|
||||||
this.parameterOrder = parameterOrder;
|
this.parameterOrder = parameterOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICommandAddress getAddress() {
|
ICommandAddress getAddress() {
|
||||||
ChildCommandAddress result = new ChildCommandAddress();
|
ChildCommandAddress result = new ChildCommandAddress();
|
||||||
result.setCommand(this);
|
result.setCommand(this);
|
||||||
|
|
||||||
Cmd cmd = cmdAnnotation;
|
Cmd cmd = cmdAnnotation;
|
||||||
result.getNames().add(cmd.value());
|
result.getNames().add(cmd.value());
|
||||||
for (String alias : cmd.aliases()) {
|
for (String alias : cmd.aliases()) {
|
||||||
result.getNames().add(alias);
|
result.getNames().add(alias);
|
||||||
}
|
}
|
||||||
result.finalizeNames();
|
result.finalizeNames();
|
||||||
|
|
||||||
GenerateCommands generateCommands = method.getAnnotation(GenerateCommands.class);
|
GenerateCommands generateCommands = method.getAnnotation(GenerateCommands.class);
|
||||||
if (generateCommands != null) {
|
if (generateCommands != null) {
|
||||||
ReflectiveRegistration.generateCommands(result, generateCommands.value());
|
ReflectiveRegistration.generateCommands(result, generateCommands.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
|
||||||
String[] parameterOrder = this.parameterOrder;
|
String[] parameterOrder = this.parameterOrder;
|
||||||
int extraArgumentCount = Integer.bitCount(flags);
|
int extraArgumentCount = Integer.bitCount(flags);
|
||||||
int parameterStartIndex = Integer.bitCount(flags & ~continuationMask);
|
int parameterStartIndex = Integer.bitCount(flags & ~continuationMask);
|
||||||
|
|
||||||
Object[] args = new Object[parameterOrder.length + extraArgumentCount];
|
Object[] args = new Object[parameterOrder.length + extraArgumentCount];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
int mask = 1;
|
int mask = 1;
|
||||||
if ((flags & mask) != 0) {
|
if ((flags & mask) != 0) {
|
||||||
// Has receiver
|
// Has receiver
|
||||||
try {
|
try {
|
||||||
args[i++] = ((ICommandInterceptor) instance).getReceiver(context, method, getCmdName());
|
args[i++] = ((ICommandInterceptor) instance).getReceiver(context, method, getCmdName());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
return null; // unreachable
|
return null; // unreachable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
if ((flags & mask) != 0) {
|
if ((flags & mask) != 0) {
|
||||||
// Has sender
|
// Has sender
|
||||||
args[i++] = sender;
|
args[i++] = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
if ((flags & mask) != 0) {
|
if ((flags & mask) != 0) {
|
||||||
// Has context
|
// Has context
|
||||||
args[i++] = context;
|
args[i++] = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
if ((flags & mask) != 0) {
|
if ((flags & mask) != 0) {
|
||||||
// Has continuation
|
// Has continuation
|
||||||
|
|
||||||
extraArgumentCount--;
|
extraArgumentCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int n = args.length; i < n; i++) {
|
for (int n = args.length; i < n; i++) {
|
||||||
args[i] = context.get(parameterOrder[i - extraArgumentCount]);
|
args[i] = context.get(parameterOrder[i - extraArgumentCount]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & mask) != 0) {
|
if ((flags & mask) != 0) {
|
||||||
// Since it has continuation, call as coroutine
|
// Since it has continuation, call as coroutine
|
||||||
return callAsCoroutine(context, args);
|
return callAsCoroutine(context, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return callSynchronously(args);
|
return callSynchronously(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuspendFunction() {
|
private boolean isSuspendFunction() {
|
||||||
try {
|
try {
|
||||||
return KotlinReflectiveRegistrationKt.isSuspendFunction(method);
|
return KotlinReflectiveRegistrationKt.isSuspendFunction(method);
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String callSynchronously(Object[] args) throws CommandException {
|
public String callSynchronously(Object[] args) throws CommandException {
|
||||||
try {
|
try {
|
||||||
return getResult(method.invoke(instance, args), null);
|
return getResult(method.invoke(instance, args), null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return getResult(null, ex);
|
return getResult(null, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getResult(Object returned, Exception ex) throws CommandException {
|
public static String getResult(Object returned, Exception ex) throws CommandException {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
handleException(ex);
|
handleException(ex);
|
||||||
return null; // unreachable
|
return null; // unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returned instanceof String) {
|
if (returned instanceof String) {
|
||||||
return (String) returned;
|
return (String) returned;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void handleException(Exception ex) throws CommandException {
|
public static void handleException(Exception ex) throws CommandException {
|
||||||
if (ex instanceof InvocationTargetException) {
|
if (ex instanceof InvocationTargetException) {
|
||||||
if (ex.getCause() instanceof CommandException) {
|
if (ex.getCause() instanceof CommandException) {
|
||||||
throw (CommandException) ex.getCause();
|
throw (CommandException) ex.getCause();
|
||||||
}
|
}
|
||||||
|
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
throw new CommandException("An internal error occurred while executing this command.", ex);
|
throw new CommandException("An internal error occurred while executing this command.", ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof CommandException) {
|
if (ex instanceof CommandException) {
|
||||||
throw (CommandException) ex;
|
throw (CommandException) ex;
|
||||||
}
|
}
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
throw new CommandException("An internal error occurred while executing this command.", ex);
|
throw new CommandException("An internal error occurred while executing this command.", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String callAsCoroutine(ExecutionContext context, Object[] args) {
|
private String callAsCoroutine(ExecutionContext context, Object[] args) {
|
||||||
return KotlinReflectiveRegistrationKt.callAsCoroutine(this, (ICommandInterceptor) instance, context, args);
|
return KotlinReflectiveRegistrationKt.callAsCoroutine(this, (ICommandInterceptor) instance, context, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,415 +1,415 @@
|
|||||||
package io.dico.dicore.command.registration.reflect;
|
package io.dico.dicore.command.registration.reflect;
|
||||||
|
|
||||||
import io.dico.dicore.command.*;
|
import io.dico.dicore.command.*;
|
||||||
import io.dico.dicore.command.annotation.*;
|
import io.dico.dicore.command.annotation.*;
|
||||||
import io.dico.dicore.command.annotation.GroupMatchedCommands.GroupEntry;
|
import io.dico.dicore.command.annotation.GroupMatchedCommands.GroupEntry;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import io.dico.dicore.command.parameter.ParameterList;
|
import io.dico.dicore.command.parameter.ParameterList;
|
||||||
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
|
||||||
import io.dico.dicore.command.parameter.type.MapBasedParameterTypeSelector;
|
import io.dico.dicore.command.parameter.type.MapBasedParameterTypeSelector;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterType;
|
import io.dico.dicore.command.parameter.type.ParameterType;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterTypes;
|
import io.dico.dicore.command.parameter.type.ParameterTypes;
|
||||||
import io.dico.dicore.command.predef.PredefinedCommand;
|
import io.dico.dicore.command.predef.PredefinedCommand;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.ConsoleCommandSender;
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.PatternSyntaxException;
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes care of turning a reflection {@link Method} into a command and more.
|
* Takes care of turning a reflection {@link Method} into a command and more.
|
||||||
*/
|
*/
|
||||||
public class ReflectiveRegistration {
|
public class ReflectiveRegistration {
|
||||||
/**
|
/**
|
||||||
* This object provides names of the parameters.
|
* This object provides names of the parameters.
|
||||||
* Oddly, the AnnotationParanamer extensions require a 'fallback' paranamer to function properly without
|
* Oddly, the AnnotationParanamer extensions require a 'fallback' paranamer to function properly without
|
||||||
* requiring ALL parameters to have that flag. This is weird because it should just use the AdaptiveParanamer on an upper level to
|
* requiring ALL parameters to have that flag. This is weird because it should just use the AdaptiveParanamer on an upper level to
|
||||||
* determine the name of each individual flag. Oddly this isn't how it works, so the fallback works the same way as the AdaptiveParanamer does.
|
* determine the name of each individual flag. Oddly this isn't how it works, so the fallback works the same way as the AdaptiveParanamer does.
|
||||||
* It's just linked instead of using an array for that part. Then we can use an AdaptiveParanamer for the latest fallback, to get bytecode names
|
* It's just linked instead of using an array for that part. Then we can use an AdaptiveParanamer for the latest fallback, to get bytecode names
|
||||||
* or, finally, to get the Jvm-provided parameter names.
|
* or, finally, to get the Jvm-provided parameter names.
|
||||||
*/
|
*/
|
||||||
//private static final Paranamer paranamer = new CachingParanamer(new BytecodeReadingParanamer());
|
//private static final Paranamer paranamer = new CachingParanamer(new BytecodeReadingParanamer());
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
private static String[] lookupParameterNames(Method method, java.lang.reflect.Parameter[] parameters, int start) {
|
private static String[] lookupParameterNames(Method method, java.lang.reflect.Parameter[] parameters, int start) {
|
||||||
int n = parameters.length;
|
int n = parameters.length;
|
||||||
String[] out = new String[n - start];
|
String[] out = new String[n - start];
|
||||||
|
|
||||||
//String[] bytecode;
|
//String[] bytecode;
|
||||||
//try {
|
//try {
|
||||||
// bytecode = paranamer.lookupParameterNames(method, false);
|
// bytecode = paranamer.lookupParameterNames(method, false);
|
||||||
//} catch (Exception ex) {
|
//} catch (Exception ex) {
|
||||||
// bytecode = new String[0];
|
// bytecode = new String[0];
|
||||||
// System.err.println("ReflectiveRegistration.lookupParameterNames failed to read bytecode");
|
// System.err.println("ReflectiveRegistration.lookupParameterNames failed to read bytecode");
|
||||||
// //ex.printStackTrace();
|
// //ex.printStackTrace();
|
||||||
//}
|
//}
|
||||||
//int bn = bytecode.length;
|
//int bn = bytecode.length;
|
||||||
|
|
||||||
for (int i = start; i < n; i++) {
|
for (int i = start; i < n; i++) {
|
||||||
java.lang.reflect.Parameter parameter = parameters[i];
|
java.lang.reflect.Parameter parameter = parameters[i];
|
||||||
Flag flag = parameter.getAnnotation(Flag.class);
|
Flag flag = parameter.getAnnotation(Flag.class);
|
||||||
NamedArg namedArg = parameter.getAnnotation(NamedArg.class);
|
NamedArg namedArg = parameter.getAnnotation(NamedArg.class);
|
||||||
|
|
||||||
boolean isFlag = flag != null;
|
boolean isFlag = flag != null;
|
||||||
String name;
|
String name;
|
||||||
if (namedArg != null && !(name = namedArg.value()).isEmpty()) {
|
if (namedArg != null && !(name = namedArg.value()).isEmpty()) {
|
||||||
} else if (isFlag && !(name = flag.value()).isEmpty()) {
|
} else if (isFlag && !(name = flag.value()).isEmpty()) {
|
||||||
//} else if (i < bn && (name = bytecode[i]) != null && !name.isEmpty()) {
|
//} else if (i < bn && (name = bytecode[i]) != null && !name.isEmpty()) {
|
||||||
} else {
|
} else {
|
||||||
name = parameter.getName();
|
name = parameter.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFlag) {
|
if (isFlag) {
|
||||||
name = '-' + name;
|
name = '-' + name;
|
||||||
} else {
|
} else {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
while (name.startsWith("-", idx)) {
|
while (name.startsWith("-", idx)) {
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
name = name.substring(idx);
|
name = name.substring(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
out[i - start] = name;
|
out[i - start] = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parseCommandGroup(ICommandAddress address, Class<?> clazz, Object instance) throws CommandParseException {
|
public static void parseCommandGroup(ICommandAddress address, Class<?> clazz, Object instance) throws CommandParseException {
|
||||||
parseCommandGroup(address, ParameterTypes.getSelector(), clazz, instance);
|
parseCommandGroup(address, ParameterTypes.getSelector(), clazz, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parseCommandGroup(ICommandAddress address, IParameterTypeSelector selector, Class<?> clazz, Object instance) throws CommandParseException {
|
public static void parseCommandGroup(ICommandAddress address, IParameterTypeSelector selector, Class<?> clazz, Object instance) throws CommandParseException {
|
||||||
boolean requireStatic = instance == null;
|
boolean requireStatic = instance == null;
|
||||||
if (!requireStatic && !clazz.isInstance(instance)) {
|
if (!requireStatic && !clazz.isInstance(instance)) {
|
||||||
throw new CommandParseException();
|
throw new CommandParseException();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Method> methods = new LinkedList<>(Arrays.asList(clazz.getDeclaredMethods()));
|
List<Method> methods = new LinkedList<>(Arrays.asList(clazz.getDeclaredMethods()));
|
||||||
|
|
||||||
Iterator<Method> it = methods.iterator();
|
Iterator<Method> it = methods.iterator();
|
||||||
for (Method method; it.hasNext(); ) {
|
for (Method method; it.hasNext(); ) {
|
||||||
method = it.next();
|
method = it.next();
|
||||||
|
|
||||||
if (requireStatic && !Modifier.isStatic(method.getModifiers())) {
|
if (requireStatic && !Modifier.isStatic(method.getModifiers())) {
|
||||||
it.remove();
|
it.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method.isAnnotationPresent(CmdParamType.class)) {
|
if (method.isAnnotationPresent(CmdParamType.class)) {
|
||||||
it.remove();
|
it.remove();
|
||||||
|
|
||||||
if (method.getReturnType() != ParameterType.class || method.getParameterCount() != 0) {
|
if (method.getReturnType() != ParameterType.class || method.getParameterCount() != 0) {
|
||||||
throw new CommandParseException("Invalid CmdParamType method: must return ParameterType and take no arguments");
|
throw new CommandParseException("Invalid CmdParamType method: must return ParameterType and take no arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
ParameterType<?, ?> type;
|
ParameterType<?, ?> type;
|
||||||
try {
|
try {
|
||||||
Object inst = Modifier.isStatic(method.getModifiers()) ? null : instance;
|
Object inst = Modifier.isStatic(method.getModifiers()) ? null : instance;
|
||||||
type = (ParameterType<?, ?>) method.invoke(inst);
|
type = (ParameterType<?, ?>) method.invoke(inst);
|
||||||
Objects.requireNonNull(type, "ParameterType returned is null");
|
Objects.requireNonNull(type, "ParameterType returned is null");
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new CommandParseException("Error occurred whilst getting ParameterType from CmdParamType method '" + method.toGenericString() + "'", ex);
|
throw new CommandParseException("Error occurred whilst getting ParameterType from CmdParamType method '" + method.toGenericString() + "'", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selector == ParameterTypes.getSelector()) {
|
if (selector == ParameterTypes.getSelector()) {
|
||||||
selector = new MapBasedParameterTypeSelector(true);
|
selector = new MapBasedParameterTypeSelector(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
selector.addType(method.getAnnotation(CmdParamType.class).infolessAlias(), type);
|
selector.addType(method.getAnnotation(CmdParamType.class).infolessAlias(), type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupMatcherCache groupMatcherCache = new GroupMatcherCache(clazz, address);
|
GroupMatcherCache groupMatcherCache = new GroupMatcherCache(clazz, address);
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
if (method.isAnnotationPresent(Cmd.class)) {
|
if (method.isAnnotationPresent(Cmd.class)) {
|
||||||
ICommandAddress parsed = parseCommandMethod(selector, method, instance);
|
ICommandAddress parsed = parseCommandMethod(selector, method, instance);
|
||||||
groupMatcherCache.getGroupFor(method).addChild(parsed);
|
groupMatcherCache.getGroupFor(method).addChild(parsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class GroupMatcherCache {
|
private static final class GroupMatcherCache {
|
||||||
private ModifiableCommandAddress groupRootAddress;
|
private ModifiableCommandAddress groupRootAddress;
|
||||||
private GroupEntry[] matchEntries;
|
private GroupEntry[] matchEntries;
|
||||||
private Pattern[] patterns;
|
private Pattern[] patterns;
|
||||||
private ModifiableCommandAddress[] addresses;
|
private ModifiableCommandAddress[] addresses;
|
||||||
|
|
||||||
GroupMatcherCache(Class<?> clazz, ICommandAddress groupRootAddress) throws CommandParseException {
|
GroupMatcherCache(Class<?> clazz, ICommandAddress groupRootAddress) throws CommandParseException {
|
||||||
this.groupRootAddress = (ModifiableCommandAddress) groupRootAddress;
|
this.groupRootAddress = (ModifiableCommandAddress) groupRootAddress;
|
||||||
|
|
||||||
GroupMatchedCommands groupMatchedCommands = clazz.getAnnotation(GroupMatchedCommands.class);
|
GroupMatchedCommands groupMatchedCommands = clazz.getAnnotation(GroupMatchedCommands.class);
|
||||||
GroupEntry[] matchEntries = groupMatchedCommands == null ? new GroupEntry[0] : groupMatchedCommands.value();
|
GroupEntry[] matchEntries = groupMatchedCommands == null ? new GroupEntry[0] : groupMatchedCommands.value();
|
||||||
|
|
||||||
Pattern[] patterns = new Pattern[matchEntries.length];
|
Pattern[] patterns = new Pattern[matchEntries.length];
|
||||||
for (int i = 0; i < matchEntries.length; i++) {
|
for (int i = 0; i < matchEntries.length; i++) {
|
||||||
GroupEntry matchEntry = matchEntries[i];
|
GroupEntry matchEntry = matchEntries[i];
|
||||||
if (matchEntry.group().isEmpty() || matchEntry.regex().isEmpty()) {
|
if (matchEntry.group().isEmpty() || matchEntry.regex().isEmpty()) {
|
||||||
throw new CommandParseException("Empty group or regex in GroupMatchedCommands entry");
|
throw new CommandParseException("Empty group or regex in GroupMatchedCommands entry");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
patterns[i] = Pattern.compile(matchEntry.regex());
|
patterns[i] = Pattern.compile(matchEntry.regex());
|
||||||
} catch (PatternSyntaxException ex) {
|
} catch (PatternSyntaxException ex) {
|
||||||
throw new CommandParseException(ex);
|
throw new CommandParseException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.matchEntries = matchEntries;
|
this.matchEntries = matchEntries;
|
||||||
this.patterns = patterns;
|
this.patterns = patterns;
|
||||||
this.addresses = new ModifiableCommandAddress[this.matchEntries.length];
|
this.addresses = new ModifiableCommandAddress[this.matchEntries.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
ModifiableCommandAddress getGroupFor(Method method) {
|
ModifiableCommandAddress getGroupFor(Method method) {
|
||||||
String name = method.getName();
|
String name = method.getName();
|
||||||
|
|
||||||
GroupEntry[] matchEntries = this.matchEntries;
|
GroupEntry[] matchEntries = this.matchEntries;
|
||||||
Pattern[] patterns = this.patterns;
|
Pattern[] patterns = this.patterns;
|
||||||
ModifiableCommandAddress[] addresses = this.addresses;
|
ModifiableCommandAddress[] addresses = this.addresses;
|
||||||
|
|
||||||
for (int i = 0; i < matchEntries.length; i++) {
|
for (int i = 0; i < matchEntries.length; i++) {
|
||||||
GroupEntry matchEntry = matchEntries[i];
|
GroupEntry matchEntry = matchEntries[i];
|
||||||
if (patterns[i].matcher(name).matches()) {
|
if (patterns[i].matcher(name).matches()) {
|
||||||
if (addresses[i] == null) {
|
if (addresses[i] == null) {
|
||||||
ChildCommandAddress placeholder = new ChildCommandAddress();
|
ChildCommandAddress placeholder = new ChildCommandAddress();
|
||||||
placeholder.setupAsPlaceholder(matchEntry.group(), matchEntry.groupAliases());
|
placeholder.setupAsPlaceholder(matchEntry.group(), matchEntry.groupAliases());
|
||||||
addresses[i] = placeholder;
|
addresses[i] = placeholder;
|
||||||
groupRootAddress.addChild(placeholder);
|
groupRootAddress.addChild(placeholder);
|
||||||
generateCommands(placeholder, matchEntry.generatedCommands());
|
generateCommands(placeholder, matchEntry.generatedCommands());
|
||||||
setDescription(placeholder, matchEntry.description(), matchEntry.shortDescription());
|
setDescription(placeholder, matchEntry.description(), matchEntry.shortDescription());
|
||||||
}
|
}
|
||||||
return addresses[i];
|
return addresses[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return groupRootAddress;
|
return groupRootAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICommandAddress parseCommandMethod(IParameterTypeSelector selector, Method method, Object instance) throws CommandParseException {
|
public static ICommandAddress parseCommandMethod(IParameterTypeSelector selector, Method method, Object instance) throws CommandParseException {
|
||||||
return new ReflectiveCommand(selector, method, instance).getAddress();
|
return new ReflectiveCommand(selector, method, instance).getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command, java.lang.reflect.Parameter[] parameters) throws CommandParseException {
|
static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command, java.lang.reflect.Parameter[] parameters) throws CommandParseException {
|
||||||
ParameterList list = command.getParameterList();
|
ParameterList list = command.getParameterList();
|
||||||
|
|
||||||
boolean hasReceiverParameter = false;
|
boolean hasReceiverParameter = false;
|
||||||
boolean hasSenderParameter = false;
|
boolean hasSenderParameter = false;
|
||||||
boolean hasContextParameter = false;
|
boolean hasContextParameter = false;
|
||||||
boolean hasContinuationParameter = false;
|
boolean hasContinuationParameter = false;
|
||||||
|
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int end = parameters.length;
|
int end = parameters.length;
|
||||||
|
|
||||||
Class<?> senderParameterType = null;
|
Class<?> senderParameterType = null;
|
||||||
|
|
||||||
if (parameters.length > start
|
if (parameters.length > start
|
||||||
&& command.getInstance() instanceof ICommandInterceptor
|
&& command.getInstance() instanceof ICommandInterceptor
|
||||||
&& ICommandReceiver.class.isAssignableFrom(parameters[start].getType())) {
|
&& ICommandReceiver.class.isAssignableFrom(parameters[start].getType())) {
|
||||||
hasReceiverParameter = true;
|
hasReceiverParameter = true;
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.length > start && CommandSender.class.isAssignableFrom(senderParameterType = parameters[start].getType())) {
|
if (parameters.length > start && CommandSender.class.isAssignableFrom(senderParameterType = parameters[start].getType())) {
|
||||||
hasSenderParameter = true;
|
hasSenderParameter = true;
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.length > start && parameters[start].getType() == ExecutionContext.class) {
|
if (parameters.length > start && parameters[start].getType() == ExecutionContext.class) {
|
||||||
hasContextParameter = true;
|
hasContextParameter = true;
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.length > start && parameters[end - 1].getType().getName().equals("kotlin.coroutines.Continuation")) {
|
if (parameters.length > start && parameters[end - 1].getType().getName().equals("kotlin.coroutines.Continuation")) {
|
||||||
hasContinuationParameter = true;
|
hasContinuationParameter = true;
|
||||||
end--;
|
end--;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] parameterNames = lookupParameterNames(method, parameters, start);
|
String[] parameterNames = lookupParameterNames(method, parameters, start);
|
||||||
for (int i = start, n = end; i < n; i++) {
|
for (int i = start, n = end; i < n; i++) {
|
||||||
Parameter<?, ?> parameter = parseParameter(selector, method, parameters[i], parameterNames[i - start]);
|
Parameter<?, ?> parameter = parseParameter(selector, method, parameters[i], parameterNames[i - start]);
|
||||||
list.addParameter(parameter);
|
list.addParameter(parameter);
|
||||||
}
|
}
|
||||||
command.setParameterOrder(hasContinuationParameter ? Arrays.copyOfRange(parameterNames, 0, parameterNames.length - 1) : parameterNames);
|
command.setParameterOrder(hasContinuationParameter ? Arrays.copyOfRange(parameterNames, 0, parameterNames.length - 1) : parameterNames);
|
||||||
|
|
||||||
RequirePermissions cmdPermissions = method.getAnnotation(RequirePermissions.class);
|
RequirePermissions cmdPermissions = method.getAnnotation(RequirePermissions.class);
|
||||||
if (cmdPermissions != null) {
|
if (cmdPermissions != null) {
|
||||||
for (String permission : cmdPermissions.value()) {
|
for (String permission : cmdPermissions.value()) {
|
||||||
command.addContextFilter(IContextFilter.permission(permission));
|
command.addContextFilter(IContextFilter.permission(permission));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdPermissions.inherit()) {
|
if (cmdPermissions.inherit()) {
|
||||||
command.addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
|
command.addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
command.addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
|
command.addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequireParameters reqPar = method.getAnnotation(RequireParameters.class);
|
RequireParameters reqPar = method.getAnnotation(RequireParameters.class);
|
||||||
if (reqPar != null) {
|
if (reqPar != null) {
|
||||||
list.setRequiredCount(reqPar.value() < 0 ? Integer.MAX_VALUE : reqPar.value());
|
list.setRequiredCount(reqPar.value() < 0 ? Integer.MAX_VALUE : reqPar.value());
|
||||||
} else {
|
} else {
|
||||||
list.setRequiredCount(list.getIndexedParameters().size());
|
list.setRequiredCount(list.getIndexedParameters().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PreprocessArgs preprocessArgs = method.getAnnotation(PreprocessArgs.class);
|
PreprocessArgs preprocessArgs = method.getAnnotation(PreprocessArgs.class);
|
||||||
if (preprocessArgs != null) {
|
if (preprocessArgs != null) {
|
||||||
IArgumentPreProcessor preProcessor = IArgumentPreProcessor.mergeOnTokens(preprocessArgs.tokens(), preprocessArgs.escapeChar());
|
IArgumentPreProcessor preProcessor = IArgumentPreProcessor.mergeOnTokens(preprocessArgs.tokens(), preprocessArgs.escapeChar());
|
||||||
list.setArgumentPreProcessor(preProcessor);
|
list.setArgumentPreProcessor(preProcessor);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
Desc desc = method.getAnnotation(Desc.class);
|
Desc desc = method.getAnnotation(Desc.class);
|
||||||
if (desc != null) {
|
if (desc != null) {
|
||||||
String[] array = desc.value();
|
String[] array = desc.value();
|
||||||
if (array.length == 0) {
|
if (array.length == 0) {
|
||||||
command.setDescription(desc.shortVersion());
|
command.setDescription(desc.shortVersion());
|
||||||
} else {
|
} else {
|
||||||
command.setDescription(array);
|
command.setDescription(array);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
command.setDescription();
|
command.setDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSenderParameter && Player.class.isAssignableFrom(senderParameterType)) {
|
if (hasSenderParameter && Player.class.isAssignableFrom(senderParameterType)) {
|
||||||
command.addContextFilter(IContextFilter.PLAYER_ONLY);
|
command.addContextFilter(IContextFilter.PLAYER_ONLY);
|
||||||
} else if (hasSenderParameter && ConsoleCommandSender.class.isAssignableFrom(senderParameterType)) {
|
} else if (hasSenderParameter && ConsoleCommandSender.class.isAssignableFrom(senderParameterType)) {
|
||||||
command.addContextFilter(IContextFilter.CONSOLE_ONLY);
|
command.addContextFilter(IContextFilter.CONSOLE_ONLY);
|
||||||
} else if (method.isAnnotationPresent(RequirePlayer.class)) {
|
} else if (method.isAnnotationPresent(RequirePlayer.class)) {
|
||||||
command.addContextFilter(IContextFilter.PLAYER_ONLY);
|
command.addContextFilter(IContextFilter.PLAYER_ONLY);
|
||||||
} else if (method.isAnnotationPresent(RequireConsole.class)) {
|
} else if (method.isAnnotationPresent(RequireConsole.class)) {
|
||||||
command.addContextFilter(IContextFilter.CONSOLE_ONLY);
|
command.addContextFilter(IContextFilter.CONSOLE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.setRepeatFinalParameter(parameters.length > start && parameters[parameters.length - 1].isVarArgs());
|
list.setRepeatFinalParameter(parameters.length > start && parameters[parameters.length - 1].isVarArgs());
|
||||||
list.setFinalParameterMayBeFlag(true);
|
list.setFinalParameterMayBeFlag(true);
|
||||||
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (hasContinuationParameter) flags |= 1;
|
if (hasContinuationParameter) flags |= 1;
|
||||||
flags <<= 1;
|
flags <<= 1;
|
||||||
if (hasContextParameter) flags |= 1;
|
if (hasContextParameter) flags |= 1;
|
||||||
flags <<= 1;
|
flags <<= 1;
|
||||||
if (hasSenderParameter) flags |= 1;
|
if (hasSenderParameter) flags |= 1;
|
||||||
flags <<= 1;
|
flags <<= 1;
|
||||||
if (hasReceiverParameter) flags |= 1;
|
if (hasReceiverParameter) flags |= 1;
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command) throws CommandParseException {
|
public static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command) throws CommandParseException {
|
||||||
return parseCommandAttributes(selector, method, command, method.getParameters());
|
return parseCommandAttributes(selector, method, command, method.getParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Parameter<?, ?> parseParameter(IParameterTypeSelector selector, Method method, java.lang.reflect.Parameter parameter, String name) throws CommandParseException {
|
public static Parameter<?, ?> parseParameter(IParameterTypeSelector selector, Method method, java.lang.reflect.Parameter parameter, String name) throws CommandParseException {
|
||||||
Class<?> type = parameter.getType();
|
Class<?> type = parameter.getType();
|
||||||
if (parameter.isVarArgs()) {
|
if (parameter.isVarArgs()) {
|
||||||
type = type.getComponentType();
|
type = type.getComponentType();
|
||||||
}
|
}
|
||||||
|
|
||||||
Annotation[] annotations = parameter.getAnnotations();
|
Annotation[] annotations = parameter.getAnnotations();
|
||||||
Flag flag = null;
|
Flag flag = null;
|
||||||
Annotation typeAnnotation = null;
|
Annotation typeAnnotation = null;
|
||||||
Desc desc = null;
|
Desc desc = null;
|
||||||
|
|
||||||
for (Annotation annotation : annotations) {
|
for (Annotation annotation : annotations) {
|
||||||
//noinspection StatementWithEmptyBody
|
//noinspection StatementWithEmptyBody
|
||||||
if (annotation instanceof NamedArg) {
|
if (annotation instanceof NamedArg) {
|
||||||
// do nothing
|
// do nothing
|
||||||
} else if (annotation instanceof Flag) {
|
} else if (annotation instanceof Flag) {
|
||||||
if (flag != null) {
|
if (flag != null) {
|
||||||
throw new CommandParseException("Multiple flags for the same parameter");
|
throw new CommandParseException("Multiple flags for the same parameter");
|
||||||
}
|
}
|
||||||
flag = (Flag) annotation;
|
flag = (Flag) annotation;
|
||||||
} else if (annotation instanceof Desc) {
|
} else if (annotation instanceof Desc) {
|
||||||
if (desc != null) {
|
if (desc != null) {
|
||||||
throw new CommandParseException("Multiple descriptions for the same parameter");
|
throw new CommandParseException("Multiple descriptions for the same parameter");
|
||||||
}
|
}
|
||||||
desc = (Desc) annotation;
|
desc = (Desc) annotation;
|
||||||
} else {
|
} else {
|
||||||
if (typeAnnotation != null) {
|
if (typeAnnotation != null) {
|
||||||
throw new CommandParseException("Multiple parameter type annotations for the same parameter");
|
throw new CommandParseException("Multiple parameter type annotations for the same parameter");
|
||||||
}
|
}
|
||||||
typeAnnotation = annotation;
|
typeAnnotation = annotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag == null && name.startsWith("-")) {
|
if (flag == null && name.startsWith("-")) {
|
||||||
throw new CommandParseException("Non-flag parameter's name starts with -");
|
throw new CommandParseException("Non-flag parameter's name starts with -");
|
||||||
} else if (flag != null && !name.startsWith("-")) {
|
} else if (flag != null && !name.startsWith("-")) {
|
||||||
throw new CommandParseException("Flag parameter's name doesn't start with -");
|
throw new CommandParseException("Flag parameter's name doesn't start with -");
|
||||||
}
|
}
|
||||||
|
|
||||||
ParameterType<Object, Object> parameterType = selector.selectAny(type, typeAnnotation == null ? null : typeAnnotation.getClass());
|
ParameterType<Object, Object> parameterType = selector.selectAny(type, typeAnnotation == null ? null : typeAnnotation.getClass());
|
||||||
if (parameterType == null) {
|
if (parameterType == null) {
|
||||||
throw new CommandParseException("IParameter type not found for parameter " + name + " in method " + method.toString());
|
throw new CommandParseException("IParameter type not found for parameter " + name + " in method " + method.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Object parameterInfo;
|
Object parameterInfo;
|
||||||
if (typeAnnotation == null) {
|
if (typeAnnotation == null) {
|
||||||
parameterInfo = null;
|
parameterInfo = null;
|
||||||
} else try {
|
} else try {
|
||||||
parameterInfo = parameterType.getParameterConfig() == null ? null : parameterType.getParameterConfig().getParameterInfo(typeAnnotation);
|
parameterInfo = parameterType.getParameterConfig() == null ? null : parameterType.getParameterConfig().getParameterInfo(typeAnnotation);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new CommandParseException("Invalid parameter config", ex);
|
throw new CommandParseException("Invalid parameter config", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
String descString = desc == null ? null : CommandAnnotationUtils.getShortDescription(desc);
|
String descString = desc == null ? null : CommandAnnotationUtils.getShortDescription(desc);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
String flagPermission = flag == null || flag.permission().isEmpty() ? null : flag.permission();
|
String flagPermission = flag == null || flag.permission().isEmpty() ? null : flag.permission();
|
||||||
return new Parameter<>(name, descString, parameterType, parameterInfo, type.isPrimitive(), name.startsWith("-"), flagPermission);
|
return new Parameter<>(name, descString, parameterType, parameterInfo, type.isPrimitive(), name.startsWith("-"), flagPermission);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new CommandParseException("Invalid parameter", ex);
|
throw new CommandParseException("Invalid parameter", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void generateCommands(ICommandAddress address, String[] input) {
|
public static void generateCommands(ICommandAddress address, String[] input) {
|
||||||
for (String value : input) {
|
for (String value : input) {
|
||||||
Consumer<ICommandAddress> consumer = PredefinedCommand.getPredefinedCommandGenerator(value);
|
Consumer<ICommandAddress> consumer = PredefinedCommand.getPredefinedCommandGenerator(value);
|
||||||
if (consumer == null) {
|
if (consumer == null) {
|
||||||
System.out.println("[Command Warning] generated command '" + value + "' could not be found");
|
System.out.println("[Command Warning] generated command '" + value + "' could not be found");
|
||||||
} else {
|
} else {
|
||||||
consumer.accept(address);
|
consumer.accept(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Desired format
|
Desired format
|
||||||
|
|
||||||
@Cmd({"tp", "tpto"})
|
@Cmd({"tp", "tpto"})
|
||||||
@RequirePermissions("teleport.self")
|
@RequirePermissions("teleport.self")
|
||||||
public (static) String|void onCommand(Player sender, Player target, @Flag("force", permission = "teleport.self.force") boolean force) {
|
public (static) String|void onCommand(Player sender, Player target, @Flag("force", permission = "teleport.self.force") boolean force) {
|
||||||
Validate.isTrue(force || !hasTpToggledOff(target), "Target has teleportation disabled. Use -force to ignore");
|
Validate.isTrue(force || !hasTpToggledOff(target), "Target has teleportation disabled. Use -force to ignore");
|
||||||
sender.teleport(target);
|
sender.teleport(target);
|
||||||
//return
|
//return
|
||||||
}
|
}
|
||||||
|
|
||||||
parser needs to:
|
parser needs to:
|
||||||
- see the @Cmd and create a CommandTree for it
|
- see the @Cmd and create a CommandTree for it
|
||||||
- see that it must be a Player executing the command
|
- see that it must be a Player executing the command
|
||||||
- add an indexed IParameter for a Player type
|
- add an indexed IParameter for a Player type
|
||||||
- add a flag parameter named force, that consumes no arguments.
|
- add a flag parameter named force, that consumes no arguments.
|
||||||
- see that setting the force flag requires a permission
|
- see that setting the force flag requires a permission
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private static void setDescription(ICommandAddress address, String[] array, String shortVersion) {
|
private static void setDescription(ICommandAddress address, String[] array, String shortVersion) {
|
||||||
if (!address.hasCommand()) {
|
if (!address.hasCommand()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array.length == 0) {
|
if (array.length == 0) {
|
||||||
address.getCommand().setDescription(shortVersion);
|
address.getCommand().setDescription(shortVersion);
|
||||||
} else {
|
} else {
|
||||||
address.getCommand().setDescription(array);
|
address.getCommand().setDescription(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,66 @@
|
|||||||
package io.dico.dicore.command.registration.reflect
|
package io.dico.dicore.command.registration.reflect
|
||||||
|
|
||||||
import io.dico.dicore.command.*
|
import io.dico.dicore.command.*
|
||||||
import kotlinx.coroutines.CoroutineStart.UNDISPATCHED
|
import kotlinx.coroutines.CoroutineStart.UNDISPATCHED
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.util.concurrent.CancellationException
|
import java.util.concurrent.CancellationException
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.coroutines.intrinsics.intercepted
|
import kotlin.coroutines.intrinsics.intercepted
|
||||||
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
|
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
|
||||||
import kotlin.reflect.jvm.kotlinFunction
|
import kotlin.reflect.jvm.kotlinFunction
|
||||||
|
|
||||||
fun isSuspendFunction(method: Method): Boolean {
|
fun isSuspendFunction(method: Method): Boolean {
|
||||||
val func = method.kotlinFunction ?: return false
|
val func = method.kotlinFunction ?: return false
|
||||||
return func.isSuspend
|
return func.isSuspend
|
||||||
}
|
}
|
||||||
|
|
||||||
fun callAsCoroutine(
|
fun callAsCoroutine(
|
||||||
command: ReflectiveCommand,
|
command: ReflectiveCommand,
|
||||||
factory: ICommandInterceptor,
|
factory: ICommandInterceptor,
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
args: Array<Any?>
|
args: Array<Any?>
|
||||||
): String? {
|
): String? {
|
||||||
val coroutineContext = factory.getCoroutineContext(context, command.method, command.cmdName) as CoroutineContext
|
val coroutineContext = factory.getCoroutineContext(context, command.method, command.cmdName) as CoroutineContext
|
||||||
|
|
||||||
// UNDISPATCHED causes the handler to run until the first suspension point on the current thread,
|
// UNDISPATCHED causes the handler to run until the first suspension point on the current thread,
|
||||||
// meaning command handlers that don't have suspension points will run completely synchronously.
|
// meaning command handlers that don't have suspension points will run completely synchronously.
|
||||||
// Tasks that take time to compute should suspend the coroutine and resume on another thread.
|
// Tasks that take time to compute should suspend the coroutine and resume on another thread.
|
||||||
val job = GlobalScope.async(context = coroutineContext, start = UNDISPATCHED) {
|
val job = GlobalScope.async(context = coroutineContext, start = UNDISPATCHED) {
|
||||||
suspendCoroutineUninterceptedOrReturn<Any?> { cont ->
|
suspendCoroutineUninterceptedOrReturn<Any?> { cont ->
|
||||||
command.method.invoke(command.instance, *args, cont.intercepted())
|
command.method.invoke(command.instance, *args, cont.intercepted())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (job.isCompleted) {
|
if (job.isCompleted) {
|
||||||
return job.getResult()
|
return job.getResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
job.invokeOnCompletion {
|
job.invokeOnCompletion {
|
||||||
val chatHandler = context.address.chatHandler
|
val chatHandler = context.address.chatHandler
|
||||||
try {
|
try {
|
||||||
val result = job.getResult()
|
val result = job.getResult()
|
||||||
chatHandler.sendMessage(context.sender, EMessageType.RESULT, result)
|
chatHandler.sendMessage(context.sender, EMessageType.RESULT, result)
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
chatHandler.handleException(context.sender, context, ex)
|
chatHandler.handleException(context.sender, context, ex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(CommandException::class)
|
@Throws(CommandException::class)
|
||||||
private fun Deferred<Any?>.getResult(): String? {
|
private fun Deferred<Any?>.getResult(): String? {
|
||||||
getCompletionExceptionOrNull()?.let { ex ->
|
getCompletionExceptionOrNull()?.let { ex ->
|
||||||
if (ex is CancellationException) {
|
if (ex is CancellationException) {
|
||||||
System.err.println("An asynchronously dispatched command was cancelled unexpectedly")
|
System.err.println("An asynchronously dispatched command was cancelled unexpectedly")
|
||||||
ex.printStackTrace()
|
ex.printStackTrace()
|
||||||
throw CommandException("The command was cancelled unexpectedly (see console)")
|
throw CommandException("The command was cancelled unexpectedly (see console)")
|
||||||
}
|
}
|
||||||
if (ex is Exception) return ReflectiveCommand.getResult(null, ex)
|
if (ex is Exception) return ReflectiveCommand.getResult(null, ex)
|
||||||
throw ex
|
throw ex
|
||||||
}
|
}
|
||||||
return ReflectiveCommand.getResult(getCompleted(), null)
|
return ReflectiveCommand.getResult(getCompleted(), null)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +1,73 @@
|
|||||||
package io.dico.dicore.command.example;
|
package io.dico.dicore.command.example;
|
||||||
|
|
||||||
import io.dico.dicore.command.CommandBuilder;
|
import io.dico.dicore.command.CommandBuilder;
|
||||||
import io.dico.dicore.command.CommandException;
|
import io.dico.dicore.command.CommandException;
|
||||||
import io.dico.dicore.command.Validate;
|
import io.dico.dicore.command.Validate;
|
||||||
import io.dico.dicore.command.annotation.Cmd;
|
import io.dico.dicore.command.annotation.Cmd;
|
||||||
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
import io.dico.dicore.command.parameter.ArgumentBuffer;
|
||||||
import io.dico.dicore.command.parameter.Parameter;
|
import io.dico.dicore.command.parameter.Parameter;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterConfig;
|
import io.dico.dicore.command.parameter.type.ParameterConfig;
|
||||||
import io.dico.dicore.command.parameter.type.ParameterType;
|
import io.dico.dicore.command.parameter.type.ParameterType;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
public class ParameterInfoObjectExample {
|
public class ParameterInfoObjectExample {
|
||||||
|
|
||||||
private @interface ParentPermission {
|
private @interface ParentPermission {
|
||||||
String value();
|
String value();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MyInfoObject {
|
static class MyInfoObject {
|
||||||
public static final ParameterConfig<ParentPermission, MyInfoObject> config = new ParameterConfig<ParentPermission, MyInfoObject>() {
|
public static final ParameterConfig<ParentPermission, MyInfoObject> config = new ParameterConfig<ParentPermission, MyInfoObject>() {
|
||||||
@Override
|
@Override
|
||||||
protected MyInfoObject toParameterInfo(ParentPermission annotation) {
|
protected MyInfoObject toParameterInfo(ParentPermission annotation) {
|
||||||
return new MyInfoObject(annotation.value());
|
return new MyInfoObject(annotation.value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private String permissionParent;
|
private String permissionParent;
|
||||||
|
|
||||||
MyInfoObject(String permissionParent) {
|
MyInfoObject(String permissionParent) {
|
||||||
this.permissionParent = permissionParent;
|
this.permissionParent = permissionParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPermissionParent() {
|
public String getPermissionParent() {
|
||||||
return permissionParent;
|
return permissionParent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MyParameterType extends ParameterType<String, MyInfoObject> {
|
static class MyParameterType extends ParameterType<String, MyInfoObject> {
|
||||||
|
|
||||||
public MyParameterType() {
|
public MyParameterType() {
|
||||||
super(String.class, MyInfoObject.config);
|
super(String.class, MyInfoObject.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String parse(Parameter<String, MyInfoObject> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
|
public String parse(Parameter<String, MyInfoObject> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
|
||||||
String value = buffer.next();
|
String value = buffer.next();
|
||||||
|
|
||||||
MyInfoObject mio = parameter.getParamInfo();
|
MyInfoObject mio = parameter.getParamInfo();
|
||||||
if (mio != null) {
|
if (mio != null) {
|
||||||
String permission = mio.permissionParent + "." + value;
|
String permission = mio.permissionParent + "." + value;
|
||||||
Validate.isAuthorized(sender, permission);
|
Validate.isAuthorized(sender, permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MyCommands {
|
static class MyCommands {
|
||||||
|
|
||||||
@Cmd("test")
|
@Cmd("test")
|
||||||
Object cmdTest(@ParentPermission("test.permission") String value) {
|
Object cmdTest(@ParentPermission("test.permission") String value) {
|
||||||
return "You have permission to use the argument '" + value + "'!";
|
return "You have permission to use the argument '" + value + "'!";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void main(String[] args) {
|
static void main(String[] args) {
|
||||||
new CommandBuilder()
|
new CommandBuilder()
|
||||||
.addParameterType(false, new MyParameterType())
|
.addParameterType(false, new MyParameterType())
|
||||||
.registerCommands(new MyCommands());
|
.registerCommands(new MyCommands());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,182 +1,182 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
public interface BitModifier {
|
public interface BitModifier {
|
||||||
|
|
||||||
long mask();
|
long mask();
|
||||||
|
|
||||||
long get(long x);
|
long get(long x);
|
||||||
|
|
||||||
long set(long x, long value);
|
long set(long x, long value);
|
||||||
|
|
||||||
default int lowerBound() {
|
default int lowerBound() {
|
||||||
return Long.numberOfTrailingZeros(mask());
|
return Long.numberOfTrailingZeros(mask());
|
||||||
}
|
}
|
||||||
|
|
||||||
default int upperBound() {
|
default int upperBound() {
|
||||||
return 64 - Long.numberOfLeadingZeros(mask());
|
return 64 - Long.numberOfLeadingZeros(mask());
|
||||||
}
|
}
|
||||||
|
|
||||||
default int bitCount() {
|
default int bitCount() {
|
||||||
return Long.bitCount(mask());
|
return Long.bitCount(mask());
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean getBoolean(long x) {
|
default boolean getBoolean(long x) {
|
||||||
return get(x) == 1;
|
return get(x) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
default long setBoolean(long x, boolean value) {
|
default long setBoolean(long x, boolean value) {
|
||||||
return set(x, value ? 1 : 0);
|
return set(x, value ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
default int getInt(long x) {
|
default int getInt(long x) {
|
||||||
return (int) (get(x) & 0xFFFFFFFFL);
|
return (int) (get(x) & 0xFFFFFFFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
default long setInt(long x, int value) {
|
default long setInt(long x, int value) {
|
||||||
return set(x, value & 0xFFFFFFFFL);
|
return set(x, value & 0xFFFFFFFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
default short getShort(long x) {
|
default short getShort(long x) {
|
||||||
return (short) (get(x) & 0xFFFFL);
|
return (short) (get(x) & 0xFFFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
default long setShort(long x, int value) {
|
default long setShort(long x, int value) {
|
||||||
return set(x, value & 0xFFFFL);
|
return set(x, value & 0xFFFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
default byte getByte(long x) {
|
default byte getByte(long x) {
|
||||||
return (byte) (get(x) & 0xFFL);
|
return (byte) (get(x) & 0xFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
default long setByte(long x, int value) {
|
default long setByte(long x, int value) {
|
||||||
return set(x, value & 0xFFL);
|
return set(x, value & 0xFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
final class OfSingle implements BitModifier {
|
final class OfSingle implements BitModifier {
|
||||||
private final long mask;
|
private final long mask;
|
||||||
|
|
||||||
public OfSingle(int bit) {
|
public OfSingle(int bit) {
|
||||||
if (bit < 0 || bit >= 64) {
|
if (bit < 0 || bit >= 64) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
this.mask = 1L << bit;
|
this.mask = 1L << bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int bitCount() {
|
public int bitCount() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long mask() {
|
public long mask() {
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBoolean(long x) {
|
public boolean getBoolean(long x) {
|
||||||
return (x & mask) != 0;
|
return (x & mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long setBoolean(long x, boolean value) {
|
public long setBoolean(long x, boolean value) {
|
||||||
return value ? (x | mask) : (x & ~mask);
|
return value ? (x | mask) : (x & ~mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long get(long x) {
|
public long get(long x) {
|
||||||
return getBoolean(x) ? 1 : 0;
|
return getBoolean(x) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long set(long x, long value) {
|
public long set(long x, long value) {
|
||||||
if (value < 0 || value > 1) {
|
if (value < 0 || value > 1) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
return setBoolean(x, value == 1);
|
return setBoolean(x, value == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class OfMultiple implements BitModifier {
|
final class OfMultiple implements BitModifier {
|
||||||
private final int lowerBound;
|
private final int lowerBound;
|
||||||
private final int bitCount;
|
private final int bitCount;
|
||||||
private final long mask;
|
private final long mask;
|
||||||
|
|
||||||
public OfMultiple(int lowerBound, int bitCount) {
|
public OfMultiple(int lowerBound, int bitCount) {
|
||||||
int upperBound = lowerBound + bitCount;
|
int upperBound = lowerBound + bitCount;
|
||||||
if (lowerBound < 0 || lowerBound >= 64 || upperBound < 1 || upperBound > 64 || upperBound < lowerBound) {
|
if (lowerBound < 0 || lowerBound >= 64 || upperBound < 1 || upperBound > 64 || upperBound < lowerBound) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
this.lowerBound = lowerBound;
|
this.lowerBound = lowerBound;
|
||||||
this.bitCount = bitCount;
|
this.bitCount = bitCount;
|
||||||
this.mask = (Long.MIN_VALUE >> (bitCount - 1)) >>> (64 - bitCount - lowerBound);
|
this.mask = (Long.MIN_VALUE >> (bitCount - 1)) >>> (64 - bitCount - lowerBound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lowerBound() {
|
public int lowerBound() {
|
||||||
return lowerBound;
|
return lowerBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int bitCount() {
|
public int bitCount() {
|
||||||
return bitCount;
|
return bitCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int upperBound() {
|
public int upperBound() {
|
||||||
return lowerBound + bitCount;
|
return lowerBound + bitCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long mask() {
|
public long mask() {
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long get(long x) {
|
public long get(long x) {
|
||||||
return (x & mask) >>> lowerBound;
|
return (x & mask) >>> lowerBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long set(long x, long value) {
|
public long set(long x, long value) {
|
||||||
return (x & ~mask) | ((value << lowerBound) & mask);
|
return (x & ~mask) | ((value << lowerBound) & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
int currentIndex;
|
int currentIndex;
|
||||||
|
|
||||||
public int getCurrentIndex() {
|
public int getCurrentIndex() {
|
||||||
return currentIndex;
|
return currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRemaining() {
|
public int getRemaining() {
|
||||||
return 64 - currentIndex;
|
return 64 - currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OfSingle single() {
|
public OfSingle single() {
|
||||||
checkAvailable(1);
|
checkAvailable(1);
|
||||||
return new OfSingle(currentIndex++);
|
return new OfSingle(currentIndex++);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitModifier size(int size) {
|
public BitModifier size(int size) {
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
return single();
|
return single();
|
||||||
}
|
}
|
||||||
checkAvailable(size);
|
checkAvailable(size);
|
||||||
BitModifier result = new OfMultiple(currentIndex, size);
|
BitModifier result = new OfMultiple(currentIndex, size);
|
||||||
currentIndex += size;
|
currentIndex += size;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitModifier remaining() {
|
public BitModifier remaining() {
|
||||||
return size(getRemaining());
|
return size(getRemaining());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAvailable(int size) {
|
private void checkAvailable(int size) {
|
||||||
if (size <= 0 || currentIndex + size > 64) {
|
if (size <= 0 || currentIndex + size > 64) {
|
||||||
throw new IllegalStateException("Exceeding bit count of a long");
|
throw new IllegalStateException("Exceeding bit count of a long");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,295 +1,295 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017 ProjectOreville
|
* Copyright (c) 2017 ProjectOreville
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Author(s):
|
* Author(s):
|
||||||
* Dico Karssiens
|
* Dico Karssiens
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public final class Formatting implements CharSequence {
|
public final class Formatting implements CharSequence {
|
||||||
public static final char FORMAT_CHAR = '\u00a7';
|
public static final char FORMAT_CHAR = '\u00a7';
|
||||||
private static final String CACHED_CHARS = "0123456789abcdefklmnor";
|
private static final String CACHED_CHARS = "0123456789abcdefklmnor";
|
||||||
private static final Formatting[] singleCharInstances = new Formatting[CACHED_CHARS.length()];
|
private static final Formatting[] singleCharInstances = new Formatting[CACHED_CHARS.length()];
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static final Formatting
|
public static final Formatting
|
||||||
BLACK = from('0'),
|
BLACK = from('0'),
|
||||||
DARK_BLUE = from('1'),
|
DARK_BLUE = from('1'),
|
||||||
DARL_GREEN = from('2'),
|
DARL_GREEN = from('2'),
|
||||||
CYAN = from('3'),
|
CYAN = from('3'),
|
||||||
DARK_RED = from('4'),
|
DARK_RED = from('4'),
|
||||||
PURPLE = from('5'),
|
PURPLE = from('5'),
|
||||||
ORANGE = from('6'),
|
ORANGE = from('6'),
|
||||||
GRAY = from('7'),
|
GRAY = from('7'),
|
||||||
DARK_GRAY = from('8'),
|
DARK_GRAY = from('8'),
|
||||||
BLUE = from('9'),
|
BLUE = from('9'),
|
||||||
GREEN = from('a'),
|
GREEN = from('a'),
|
||||||
AQUA = from('b'),
|
AQUA = from('b'),
|
||||||
RED = from('c'),
|
RED = from('c'),
|
||||||
PINK = from('d'),
|
PINK = from('d'),
|
||||||
YELLOW = from('e'),
|
YELLOW = from('e'),
|
||||||
WHITE = from('f'),
|
WHITE = from('f'),
|
||||||
BOLD = from('l'),
|
BOLD = from('l'),
|
||||||
STRIKETHROUGH = from('m'),
|
STRIKETHROUGH = from('m'),
|
||||||
UNDERLINE = from('n'),
|
UNDERLINE = from('n'),
|
||||||
ITALIC = from('o'),
|
ITALIC = from('o'),
|
||||||
MAGIC = from('k'),
|
MAGIC = from('k'),
|
||||||
RESET = from('r'),
|
RESET = from('r'),
|
||||||
EMPTY = from('\0');
|
EMPTY = from('\0');
|
||||||
|
|
||||||
public static String stripAll(String value) {
|
public static String stripAll(String value) {
|
||||||
return stripAll(FORMAT_CHAR, value);
|
return stripAll(FORMAT_CHAR, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String stripAll(char alternateChar, String value) {
|
public static String stripAll(char alternateChar, String value) {
|
||||||
int index = value.indexOf(alternateChar);
|
int index = value.indexOf(alternateChar);
|
||||||
int max;
|
int max;
|
||||||
if (index == -1 || index == (max = value.length() - 1)) {
|
if (index == -1 || index == (max = value.length() - 1)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
int from = 0;
|
int from = 0;
|
||||||
do {
|
do {
|
||||||
if (isRecognizedChar(value.charAt(index + 1))) {
|
if (isRecognizedChar(value.charAt(index + 1))) {
|
||||||
result.append(value, from, index);
|
result.append(value, from, index);
|
||||||
from = index + 2;
|
from = index + 2;
|
||||||
} else {
|
} else {
|
||||||
result.append(value, from, from = index + 2);
|
result.append(value, from, from = index + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
index = value.indexOf(alternateChar, index + 1);
|
index = value.indexOf(alternateChar, index + 1);
|
||||||
} while (index != -1 && index != max && from <= max);
|
} while (index != -1 && index != max && from <= max);
|
||||||
|
|
||||||
if (from <= max) {
|
if (from <= max) {
|
||||||
result.append(value, from, value.length());
|
result.append(value, from, value.length());
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String stripFirst(String value) {
|
public static String stripFirst(String value) {
|
||||||
return stripFirst(FORMAT_CHAR, value);
|
return stripFirst(FORMAT_CHAR, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String stripFirst(char alternateChar, String value) {
|
public static String stripFirst(char alternateChar, String value) {
|
||||||
int index = value.indexOf(alternateChar);
|
int index = value.indexOf(alternateChar);
|
||||||
int max;
|
int max;
|
||||||
if (index == -1 || index == (max = value.length() - 1)) {
|
if (index == -1 || index == (max = value.length() - 1)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder result = new StringBuilder(value.length());
|
StringBuilder result = new StringBuilder(value.length());
|
||||||
int from = 0;
|
int from = 0;
|
||||||
if (isRecognizedChar(value.charAt(index + 1))) {
|
if (isRecognizedChar(value.charAt(index + 1))) {
|
||||||
result.append(value, from, index);
|
result.append(value, from, index);
|
||||||
from = index + 2;
|
from = index + 2;
|
||||||
} else {
|
} else {
|
||||||
result.append(value, from, from = index + 2);
|
result.append(value, from, from = index + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from < max) {
|
if (from < max) {
|
||||||
result.append(value, from, value.length());
|
result.append(value, from, value.length());
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Formatting from(char c) {
|
public static Formatting from(char c) {
|
||||||
if (isRecognizedChar(c)) {
|
if (isRecognizedChar(c)) {
|
||||||
c = Character.toLowerCase(c);
|
c = Character.toLowerCase(c);
|
||||||
int index = CACHED_CHARS.indexOf(c);
|
int index = CACHED_CHARS.indexOf(c);
|
||||||
if (index == -1) return EMPTY;
|
if (index == -1) return EMPTY;
|
||||||
|
|
||||||
Formatting res = singleCharInstances[index];
|
Formatting res = singleCharInstances[index];
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
singleCharInstances[index] = res = new Formatting(c);
|
singleCharInstances[index] = res = new Formatting(c);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Formatting from(String chars) {
|
public static Formatting from(String chars) {
|
||||||
return chars.length() == 1 ? from(chars.charAt(0)) : getFormats(chars, '\0');
|
return chars.length() == 1 ? from(chars.charAt(0)) : getFormats(chars, '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Formatting getFormats(String input) {
|
public static Formatting getFormats(String input) {
|
||||||
return getFormats(input, FORMAT_CHAR);
|
return getFormats(input, FORMAT_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Formatting getFormats(String input, char formatChar) {
|
public static Formatting getFormats(String input, char formatChar) {
|
||||||
return getFormats(input, 0, input.length(), formatChar);
|
return getFormats(input, 0, input.length(), formatChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Formatting getFormats(String input, int start, int end, char formatChar) {
|
public static Formatting getFormats(String input, int start, int end, char formatChar) {
|
||||||
if ((start < 0) || (start > end) || (end > input.length())) {
|
if ((start < 0) || (start > end) || (end > input.length())) {
|
||||||
throw new IndexOutOfBoundsException("start " + start + ", end " + end + ", input.length() " + input.length());
|
throw new IndexOutOfBoundsException("start " + start + ", end " + end + ", input.length() " + input.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean needsFormatChar = formatChar != '\0';
|
boolean needsFormatChar = formatChar != '\0';
|
||||||
char[] formats = new char[6];
|
char[] formats = new char[6];
|
||||||
// just make sure it's not the same as formatChar
|
// just make sure it's not the same as formatChar
|
||||||
char previous = (char) (formatChar + 1);
|
char previous = (char) (formatChar + 1);
|
||||||
|
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
|
|
||||||
if (previous == formatChar || !needsFormatChar) {
|
if (previous == formatChar || !needsFormatChar) {
|
||||||
if (isColourChar(c) || isResetChar(c)) {
|
if (isColourChar(c) || isResetChar(c)) {
|
||||||
formats = new char[6];
|
formats = new char[6];
|
||||||
formats[0] = Character.toLowerCase(c);
|
formats[0] = Character.toLowerCase(c);
|
||||||
} else if (isFormatChar(c)) {
|
} else if (isFormatChar(c)) {
|
||||||
char format = Character.toLowerCase(c);
|
char format = Character.toLowerCase(c);
|
||||||
for (int j = 0; j < 6; j++) {
|
for (int j = 0; j < 6; j++) {
|
||||||
if (formats[j] == '\0') {
|
if (formats[j] == '\0') {
|
||||||
formats[j] = format;
|
formats[j] = format;
|
||||||
break;
|
break;
|
||||||
} else if (formats[j] == format) {
|
} else if (formats[j] == format) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previous = c;
|
previous = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return formats[1] == '\0' ? from(formats[0]) : new Formatting(formats);
|
return formats[1] == '\0' ? from(formats[0]) : new Formatting(formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String translate(String input) {
|
public static String translate(String input) {
|
||||||
return translateChars('&', input);
|
return translateChars('&', input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String translateChars(char alternateChar, String input) {
|
public static String translateChars(char alternateChar, String input) {
|
||||||
return translateFormat(alternateChar, FORMAT_CHAR, input);
|
return translateFormat(alternateChar, FORMAT_CHAR, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String revert(String input) {
|
public static String revert(String input) {
|
||||||
return revertChars('&', input);
|
return revertChars('&', input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String revertChars(char alternateChar, String input) {
|
public static String revertChars(char alternateChar, String input) {
|
||||||
return translateFormat(FORMAT_CHAR, alternateChar, input);
|
return translateFormat(FORMAT_CHAR, alternateChar, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String translateFormat(char fromChar, char toChar, String input) {
|
public static String translateFormat(char fromChar, char toChar, String input) {
|
||||||
if (input == null) {
|
if (input == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int n = input.length();
|
int n = input.length();
|
||||||
if (n < 2) {
|
if (n < 2) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
char[] result = null;
|
char[] result = null;
|
||||||
char previous = input.charAt(0);
|
char previous = input.charAt(0);
|
||||||
for (int i = 1; i < n; i++) {
|
for (int i = 1; i < n; i++) {
|
||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
if (previous == fromChar && isRecognizedChar(c)) {
|
if (previous == fromChar && isRecognizedChar(c)) {
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = input.toCharArray();
|
result = input.toCharArray();
|
||||||
}
|
}
|
||||||
result[i - 1] = toChar;
|
result[i - 1] = toChar;
|
||||||
}
|
}
|
||||||
previous = c;
|
previous = c;
|
||||||
}
|
}
|
||||||
return result == null ? input : String.valueOf(result);
|
return result == null ? input : String.valueOf(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void translate(StringBuilder input) {
|
public static void translate(StringBuilder input) {
|
||||||
translateChars('&', input);
|
translateChars('&', input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void translateChars(char alternateChar, StringBuilder input) {
|
public static void translateChars(char alternateChar, StringBuilder input) {
|
||||||
translateFormat(alternateChar, FORMAT_CHAR, input);
|
translateFormat(alternateChar, FORMAT_CHAR, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void revert(StringBuilder input) {
|
public static void revert(StringBuilder input) {
|
||||||
revertChars('&', input);
|
revertChars('&', input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void revertChars(char alternateChar, StringBuilder input) {
|
public static void revertChars(char alternateChar, StringBuilder input) {
|
||||||
translateFormat(FORMAT_CHAR, alternateChar, input);
|
translateFormat(FORMAT_CHAR, alternateChar, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void translateFormat(char fromChar, char toChar, StringBuilder input) {
|
public static void translateFormat(char fromChar, char toChar, StringBuilder input) {
|
||||||
if (input == null) {
|
if (input == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int n = input.length();
|
int n = input.length();
|
||||||
if (n < 2) {
|
if (n < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char previous = input.charAt(0);
|
char previous = input.charAt(0);
|
||||||
for (int i = 1; i < n; i++) {
|
for (int i = 1; i < n; i++) {
|
||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
if (previous == fromChar && isRecognizedChar(c)) {
|
if (previous == fromChar && isRecognizedChar(c)) {
|
||||||
input.setCharAt(i -1, toChar);
|
input.setCharAt(i -1, toChar);
|
||||||
}
|
}
|
||||||
previous = c;
|
previous = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isRecognizedChar(char c) {
|
private static boolean isRecognizedChar(char c) {
|
||||||
return isColourChar(c) || isFormatChar(c) || isResetChar(c);
|
return isColourChar(c) || isFormatChar(c) || isResetChar(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isColourChar(char c) {
|
private static boolean isColourChar(char c) {
|
||||||
return "0123456789abcdefABCDEF".indexOf(c) >= 0;
|
return "0123456789abcdefABCDEF".indexOf(c) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isResetChar(char c) {
|
private static boolean isResetChar(char c) {
|
||||||
return c == 'r' || c == 'R';
|
return c == 'r' || c == 'R';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isFormatChar(char c) {
|
private static boolean isFormatChar(char c) {
|
||||||
return "klmnoKLMNO".indexOf(c) >= 0;
|
return "klmnoKLMNO".indexOf(c) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String format;
|
private final String format;
|
||||||
|
|
||||||
private Formatting(char[] formats) {
|
private Formatting(char[] formats) {
|
||||||
StringBuilder format = new StringBuilder(12);
|
StringBuilder format = new StringBuilder(12);
|
||||||
for (char c : formats) {
|
for (char c : formats) {
|
||||||
if (c != '\0') {
|
if (c != '\0') {
|
||||||
format.append(FORMAT_CHAR).append(c);
|
format.append(FORMAT_CHAR).append(c);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.format = format.toString();
|
this.format = format.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Formatting(char c) {
|
private Formatting(char c) {
|
||||||
this.format = (c != '\0') ? String.valueOf(new char[]{FORMAT_CHAR, c}) : "";
|
this.format = (c != '\0') ? String.valueOf(new char[]{FORMAT_CHAR, c}) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int length() {
|
public int length() {
|
||||||
return format.length();
|
return format.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char charAt(int index) {
|
public char charAt(int index) {
|
||||||
return format.charAt(index);
|
return format.charAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String subSequence(int start, int end) {
|
public String subSequence(int start, int end) {
|
||||||
return format.substring(start, end);
|
return format.substring(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString(char formatChar) {
|
public String toString(char formatChar) {
|
||||||
return format.replace(FORMAT_CHAR, formatChar);
|
return format.replace(FORMAT_CHAR, formatChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,173 +1,173 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A chainable object
|
* A chainable object
|
||||||
* <p>
|
* <p>
|
||||||
* It is not possible to declare another upper bound for type parameter Subtype.
|
* It is not possible to declare another upper bound for type parameter Subtype.
|
||||||
* However, it is required that it also extends the type parameter Element.
|
* However, it is required that it also extends the type parameter Element.
|
||||||
*
|
*
|
||||||
* @param <Subtype> the interface that is chainable
|
* @param <Subtype> the interface that is chainable
|
||||||
* @param <Element> the element of the chain, this is a supertype of the subtype
|
* @param <Element> the element of the chain, this is a supertype of the subtype
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public interface InterfaceChain<Element, Subtype extends InterfaceChain<Element, Subtype>> {
|
public interface InterfaceChain<Element, Subtype extends InterfaceChain<Element, Subtype>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the empty InterfaceChain instance.
|
* returns the empty InterfaceChain instance.
|
||||||
*
|
*
|
||||||
* @return the empty InterfaceChain instance
|
* @return the empty InterfaceChain instance
|
||||||
*/
|
*/
|
||||||
Subtype getEmptyInstance();
|
Subtype getEmptyInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns a InterfaceChain with the last added element detached.
|
* returns a InterfaceChain with the last added element detached.
|
||||||
* <p>
|
* <p>
|
||||||
* if this InterfaceChain is the empty instance, the empty instance is returned.
|
* if this InterfaceChain is the empty instance, the empty instance is returned.
|
||||||
*
|
*
|
||||||
* @return a InterfaceChain with the last added element detached
|
* @return a InterfaceChain with the last added element detached
|
||||||
* @implNote for the purpose of lambdas, the default implementation also returns the empty instance.
|
* @implNote for the purpose of lambdas, the default implementation also returns the empty instance.
|
||||||
*/
|
*/
|
||||||
default Subtype withoutLastNode() {
|
default Subtype withoutLastNode() {
|
||||||
return getEmptyInstance();
|
return getEmptyInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the element that was inserted as the last element
|
* returns the element that was inserted as the last element
|
||||||
* <p>
|
* <p>
|
||||||
* For instance, calling this method on the result of calling {@link InterfaceChain#withElement(Object)}
|
* For instance, calling this method on the result of calling {@link InterfaceChain#withElement(Object)}
|
||||||
* would return the given element.
|
* would return the given element.
|
||||||
*
|
*
|
||||||
* @return the element that was inserted as the last element
|
* @return the element that was inserted as the last element
|
||||||
* @implNote for the purpose of lambdas, the default implementation returns this object,
|
* @implNote for the purpose of lambdas, the default implementation returns this object,
|
||||||
* which is required to implement the Element type parameter.
|
* which is required to implement the Element type parameter.
|
||||||
*/
|
*/
|
||||||
default Element getDelegateOfLastNode() {
|
default Element getDelegateOfLastNode() {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (Element) this;
|
return (Element) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The number of elements chained from this InterfaceChain.
|
* @return The number of elements chained from this InterfaceChain.
|
||||||
* @implNote for the purpose of lambdas, the default implementation returns 1.
|
* @implNote for the purpose of lambdas, the default implementation returns 1.
|
||||||
*/
|
*/
|
||||||
default int getElementCount() {
|
default int getElementCount() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a new InterfaceChain that includes the given Element.
|
* Get a new InterfaceChain that includes the given Element.
|
||||||
* <p>
|
* <p>
|
||||||
* The default implementation of the Subtype should look like this:
|
* The default implementation of the Subtype should look like this:
|
||||||
* <pre> {@code
|
* <pre> {@code
|
||||||
* if (element == null) {
|
* if (element == null) {
|
||||||
* return this;
|
* return this;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* int count = getElementCount() + 1;
|
* int count = getElementCount() + 1;
|
||||||
* return new Subtype() {
|
* return new Subtype() {
|
||||||
* \@Override
|
* \@Override
|
||||||
* public void exampleElementMethod() {
|
* public void exampleElementMethod() {
|
||||||
* try {
|
* try {
|
||||||
* Subtype.this.exampleElementMethod();
|
* Subtype.this.exampleElementMethod();
|
||||||
* } finally {
|
* } finally {
|
||||||
* element.exampleElementMethod();
|
* element.exampleElementMethod();
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* \@Override
|
* \@Override
|
||||||
* public Subtype withoutLastNode() {
|
* public Subtype withoutLastNode() {
|
||||||
* return Subtype.this;
|
* return Subtype.this;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* \@Override
|
* \@Override
|
||||||
* public Element getDelegateOfLastNode() {
|
* public Element getDelegateOfLastNode() {
|
||||||
* return element;
|
* return element;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* \@Override
|
* \@Override
|
||||||
* public int getElementCount() {
|
* public int getElementCount() {
|
||||||
* return count;
|
* return count;
|
||||||
* }
|
* }
|
||||||
* };
|
* };
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param element A new element to insert at the end of this InterfaceChain.
|
* @param element A new element to insert at the end of this InterfaceChain.
|
||||||
* @return a new InterfaceChain that includes the given Element.
|
* @return a new InterfaceChain that includes the given Element.
|
||||||
*/
|
*/
|
||||||
Subtype withElement(Element element);
|
Subtype withElement(Element element);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append each of the elements to this InterfaceChain
|
* Append each of the elements to this InterfaceChain
|
||||||
*
|
*
|
||||||
* @param elements the elements to append
|
* @param elements the elements to append
|
||||||
* @return a new InterfaceChain with the elements appended
|
* @return a new InterfaceChain with the elements appended
|
||||||
*/
|
*/
|
||||||
default Subtype withElements(Element... elements) {
|
default Subtype withElements(Element... elements) {
|
||||||
Subtype result = (Subtype) this;
|
Subtype result = (Subtype) this;
|
||||||
for (Element element : elements) {
|
for (Element element : elements) {
|
||||||
result = result.withElement(element);
|
result = result.withElement(element);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Example Subtypes implementation
|
Example Subtypes implementation
|
||||||
|
|
||||||
public class Subtypes {
|
public class Subtypes {
|
||||||
|
|
||||||
private Subtypes() {
|
private Subtypes() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Subtype empty = new Subtype() {
|
private static final Subtype empty = new Subtype() {
|
||||||
@Override
|
@Override
|
||||||
public void exampleElementMethod() {
|
public void exampleElementMethod() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Subtype withElement(Element other) {
|
public Subtype withElement(Element other) {
|
||||||
return Subtypes.singleton(other);
|
return Subtypes.singleton(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getElementCount() {
|
public int getElementCount() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Element getDelegateOfLastNode() {
|
public Element getDelegateOfLastNode() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Subtype empty() {
|
public static Subtype empty() {
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Subtype singleton(Element element) {
|
public static Subtype singleton(Element element) {
|
||||||
if (element instanceof Subtype) {
|
if (element instanceof Subtype) {
|
||||||
return (Subtype) element;
|
return (Subtype) element;
|
||||||
}
|
}
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
return new Subtype() {
|
return new Subtype() {
|
||||||
@Override
|
@Override
|
||||||
public void exampleElementMethod() {
|
public void exampleElementMethod() {
|
||||||
element.exampleElementMethod();
|
element.exampleElementMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Element getDelegateOfLastNode() {
|
public Element getDelegateOfLastNode() {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,120 +1,120 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.PlayerInventory;
|
import org.bukkit.inventory.PlayerInventory;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class InventoryEventUtil {
|
public class InventoryEventUtil {
|
||||||
|
|
||||||
private InventoryEventUtil() {
|
private InventoryEventUtil() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack getNewItem(InventoryClickEvent event) {
|
public static ItemStack getNewItem(InventoryClickEvent event) {
|
||||||
Inventory clicked = event.getInventory();
|
Inventory clicked = event.getInventory();
|
||||||
switch (event.getAction()) {
|
switch (event.getAction()) {
|
||||||
case SWAP_WITH_CURSOR:
|
case SWAP_WITH_CURSOR:
|
||||||
case PLACE_ALL:
|
case PLACE_ALL:
|
||||||
return event.getCursor();
|
return event.getCursor();
|
||||||
case PICKUP_ALL:
|
case PICKUP_ALL:
|
||||||
case HOTBAR_MOVE_AND_READD:
|
case HOTBAR_MOVE_AND_READD:
|
||||||
case MOVE_TO_OTHER_INVENTORY:
|
case MOVE_TO_OTHER_INVENTORY:
|
||||||
case DROP_ALL_SLOT:
|
case DROP_ALL_SLOT:
|
||||||
case COLLECT_TO_CURSOR:
|
case COLLECT_TO_CURSOR:
|
||||||
return null;
|
return null;
|
||||||
case PICKUP_HALF:
|
case PICKUP_HALF:
|
||||||
case PICKUP_SOME:
|
case PICKUP_SOME:
|
||||||
ItemStack item = clicked.getItem(event.getSlot()).clone();
|
ItemStack item = clicked.getItem(event.getSlot()).clone();
|
||||||
item.setAmount(item.getAmount() / 2);
|
item.setAmount(item.getAmount() / 2);
|
||||||
return item;
|
return item;
|
||||||
case PICKUP_ONE:
|
case PICKUP_ONE:
|
||||||
case DROP_ONE_SLOT:
|
case DROP_ONE_SLOT:
|
||||||
item = clicked.getItem(event.getSlot()).clone();
|
item = clicked.getItem(event.getSlot()).clone();
|
||||||
item.setAmount(Math.max(0, item.getAmount() - 1));
|
item.setAmount(Math.max(0, item.getAmount() - 1));
|
||||||
return item;
|
return item;
|
||||||
case PLACE_ONE:
|
case PLACE_ONE:
|
||||||
item = event.getView().getCursor().clone();
|
item = event.getView().getCursor().clone();
|
||||||
item.setAmount(1);
|
item.setAmount(1);
|
||||||
return item;
|
return item;
|
||||||
case PLACE_SOME:
|
case PLACE_SOME:
|
||||||
item = event.getView().getCursor().clone();
|
item = event.getView().getCursor().clone();
|
||||||
item.setAmount(item.getAmount() / 2);
|
item.setAmount(item.getAmount() / 2);
|
||||||
return item;
|
return item;
|
||||||
case HOTBAR_SWAP:
|
case HOTBAR_SWAP:
|
||||||
return event.getView().getBottomInventory().getItem(event.getHotbarButton());
|
return event.getView().getBottomInventory().getItem(event.getHotbarButton());
|
||||||
default:
|
default:
|
||||||
return clicked.getItem(event.getSlot());
|
return clicked.getItem(event.getSlot());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Map<Integer, ItemStack> deduceChangesIfItemAdded(Inventory inventory, ItemStack added, boolean computeNewItem) {
|
public static Map<Integer, ItemStack> deduceChangesIfItemAdded(Inventory inventory, ItemStack added, boolean computeNewItem) {
|
||||||
int addedAmount = added.getAmount();
|
int addedAmount = added.getAmount();
|
||||||
Map<Integer, ItemStack> rv = Collections.emptyMap();
|
Map<Integer, ItemStack> rv = Collections.emptyMap();
|
||||||
|
|
||||||
for (int n = inventory.getSize(), i = 0; i < n; i++) {
|
for (int n = inventory.getSize(), i = 0; i < n; i++) {
|
||||||
if (addedAmount <= 0) break;
|
if (addedAmount <= 0) break;
|
||||||
|
|
||||||
ItemStack current = inventory.getItem(i);
|
ItemStack current = inventory.getItem(i);
|
||||||
if (current == null || current.getType() == Material.AIR || current.isSimilar(added)) {
|
if (current == null || current.getType() == Material.AIR || current.isSimilar(added)) {
|
||||||
int count = current == null ? 0 : current.getAmount();
|
int count = current == null ? 0 : current.getAmount();
|
||||||
int max = (current == null ? added : current).getType().getMaxStackSize();
|
int max = (current == null ? added : current).getType().getMaxStackSize();
|
||||||
if (count < max) {
|
if (count < max) {
|
||||||
int diff = max - count;
|
int diff = max - count;
|
||||||
if (diff > addedAmount) {
|
if (diff > addedAmount) {
|
||||||
diff = addedAmount;
|
diff = addedAmount;
|
||||||
}
|
}
|
||||||
addedAmount -= diff;
|
addedAmount -= diff;
|
||||||
|
|
||||||
if (rv.isEmpty()) rv = new LinkedHashMap<>();
|
if (rv.isEmpty()) rv = new LinkedHashMap<>();
|
||||||
|
|
||||||
if (computeNewItem) {
|
if (computeNewItem) {
|
||||||
current = (current == null ? added : current).clone();
|
current = (current == null ? added : current).clone();
|
||||||
current.setAmount(count + diff);
|
current.setAmount(count + diff);
|
||||||
rv.put(i, current);
|
rv.put(i, current);
|
||||||
} else {
|
} else {
|
||||||
rv.put(i, null);
|
rv.put(i, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static ItemStack getNewHeldItemIfPickedUp(PlayerInventory inventory, ItemStack added) {
|
public static ItemStack getNewHeldItemIfPickedUp(PlayerInventory inventory, ItemStack added) {
|
||||||
int heldItemSlot = inventory.getHeldItemSlot();
|
int heldItemSlot = inventory.getHeldItemSlot();
|
||||||
ItemStack heldItem = inventory.getItem(heldItemSlot);
|
ItemStack heldItem = inventory.getItem(heldItemSlot);
|
||||||
|
|
||||||
if (SpigotUtil.isItemPresent(heldItem) && !added.isSimilar(heldItem)) {
|
if (SpigotUtil.isItemPresent(heldItem) && !added.isSimilar(heldItem)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int amt = added.getAmount();
|
int amt = added.getAmount();
|
||||||
for (int i = 0; i < heldItemSlot; i++) {
|
for (int i = 0; i < heldItemSlot; i++) {
|
||||||
ItemStack item = inventory.getItem(i);
|
ItemStack item = inventory.getItem(i);
|
||||||
if (!SpigotUtil.isItemPresent(item)) {
|
if (!SpigotUtil.isItemPresent(item)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (item.isSimilar(item)) {
|
if (item.isSimilar(item)) {
|
||||||
amt -= Math.max(0, item.getMaxStackSize() - item.getAmount());
|
amt -= Math.max(0, item.getMaxStackSize() - item.getAmount());
|
||||||
if (amt <= 0) {
|
if (amt <= 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
added = added.clone();
|
added = added.clone();
|
||||||
added.setAmount(amt + Math.max(0, heldItem == null ? 0 : heldItem.getAmount()));
|
added.setAmount(amt + Math.max(0, heldItem == null ? 0 : heldItem.getAmount()));
|
||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,116 +1,116 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public interface Logging {
|
public interface Logging {
|
||||||
|
|
||||||
void info(Object o);
|
void info(Object o);
|
||||||
|
|
||||||
void warn(Object o);
|
void warn(Object o);
|
||||||
|
|
||||||
void error(Object o);
|
void error(Object o);
|
||||||
|
|
||||||
void debug(Object o);
|
void debug(Object o);
|
||||||
|
|
||||||
void setDebugging(boolean debugging);
|
void setDebugging(boolean debugging);
|
||||||
|
|
||||||
boolean isDebugging();
|
boolean isDebugging();
|
||||||
|
|
||||||
class RootLogging implements Logging {
|
class RootLogging implements Logging {
|
||||||
private final String prefix;
|
private final String prefix;
|
||||||
private final Logger root;
|
private final Logger root;
|
||||||
private boolean debugging;
|
private boolean debugging;
|
||||||
|
|
||||||
public RootLogging(String prefix, Logger root, boolean debugging) {
|
public RootLogging(String prefix, Logger root, boolean debugging) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
this.debugging = debugging;
|
this.debugging = debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(Object o) {
|
public void info(Object o) {
|
||||||
root.info(prefix(o));
|
root.info(prefix(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(Object o) {
|
public void warn(Object o) {
|
||||||
root.warning(prefix(o));
|
root.warning(prefix(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Object o) {
|
public void error(Object o) {
|
||||||
root.severe(prefix(o));
|
root.severe(prefix(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(Object o) {
|
public void debug(Object o) {
|
||||||
if (debugging) {
|
if (debugging) {
|
||||||
root.info(String.format("[DEBUG] %s", prefix(o)));
|
root.info(String.format("[DEBUG] %s", prefix(o)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDebugging() {
|
public boolean isDebugging() {
|
||||||
return debugging;
|
return debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDebugging(boolean debugging) {
|
public void setDebugging(boolean debugging) {
|
||||||
this.debugging = debugging;
|
this.debugging = debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String prefix(Object o) {
|
private String prefix(Object o) {
|
||||||
return String.format("[%s] %s", prefix, String.valueOf(o));
|
return String.format("[%s] %s", prefix, String.valueOf(o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SubLogging implements Logging {
|
class SubLogging implements Logging {
|
||||||
protected String prefix;
|
protected String prefix;
|
||||||
private final Logging superLogger;
|
private final Logging superLogger;
|
||||||
private boolean debugging;
|
private boolean debugging;
|
||||||
|
|
||||||
public SubLogging(String prefix, Logging superLogger, boolean debugging) {
|
public SubLogging(String prefix, Logging superLogger, boolean debugging) {
|
||||||
this.superLogger = superLogger;
|
this.superLogger = superLogger;
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
this.debugging = debugging;
|
this.debugging = debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void info(Object o) {
|
public void info(Object o) {
|
||||||
superLogger.info(prefix(o));
|
superLogger.info(prefix(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warn(Object o) {
|
public void warn(Object o) {
|
||||||
superLogger.warn(prefix(o));
|
superLogger.warn(prefix(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(Object o) {
|
public void error(Object o) {
|
||||||
superLogger.error(prefix(o));
|
superLogger.error(prefix(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void debug(Object o) {
|
public void debug(Object o) {
|
||||||
if (debugging) {
|
if (debugging) {
|
||||||
superLogger.info(String.format("[DEBUG] %s", prefix(o)));
|
superLogger.info(String.format("[DEBUG] %s", prefix(o)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDebugging() {
|
public boolean isDebugging() {
|
||||||
return debugging;
|
return debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDebugging(boolean debugging) {
|
public void setDebugging(boolean debugging) {
|
||||||
this.debugging = debugging;
|
this.debugging = debugging;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String prefix(Object o) {
|
private String prefix(Object o) {
|
||||||
return String.format("[%s] %s", prefix, String.valueOf(o));
|
return String.format("[%s] %s", prefix, String.valueOf(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,59 +1,59 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SetBasedWhitelist implements Whitelist {
|
public class SetBasedWhitelist implements Whitelist {
|
||||||
private final Set set;
|
private final Set set;
|
||||||
private final boolean blacklist;
|
private final boolean blacklist;
|
||||||
|
|
||||||
public SetBasedWhitelist(Object[] array, boolean blacklist) {
|
public SetBasedWhitelist(Object[] array, boolean blacklist) {
|
||||||
this(Arrays.asList(array), blacklist);
|
this(Arrays.asList(array), blacklist);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SetBasedWhitelist(ConfigurationSection section, Function<String, ?> parser) {
|
public SetBasedWhitelist(ConfigurationSection section, Function<String, ?> parser) {
|
||||||
this(section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toList()),
|
this(section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toList()),
|
||||||
section.getBoolean("blacklist", false));
|
section.getBoolean("blacklist", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public SetBasedWhitelist(Collection collection, boolean blacklist) {
|
public SetBasedWhitelist(Collection collection, boolean blacklist) {
|
||||||
Set set;
|
Set set;
|
||||||
if (collection.isEmpty()) {
|
if (collection.isEmpty()) {
|
||||||
set = Collections.emptySet();
|
set = Collections.emptySet();
|
||||||
} else if (collection.iterator().next() instanceof Enum) {
|
} else if (collection.iterator().next() instanceof Enum) {
|
||||||
set = EnumSet.copyOf(collection);
|
set = EnumSet.copyOf(collection);
|
||||||
} else if (collection instanceof Set) {
|
} else if (collection instanceof Set) {
|
||||||
set = (Set) collection;
|
set = (Set) collection;
|
||||||
} else {
|
} else {
|
||||||
set = new HashSet<>(collection);
|
set = new HashSet<>(collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set = set;
|
this.set = set;
|
||||||
this.blacklist = blacklist;
|
this.blacklist = blacklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWhitelisted(Object o) {
|
public boolean isWhitelisted(Object o) {
|
||||||
return blacklist != set.contains(o);
|
return blacklist != set.contains(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return (blacklist ? "Blacklist" : "Whitelist") + "{"
|
return (blacklist ? "Blacklist" : "Whitelist") + "{"
|
||||||
+ String.join(", ", (CharSequence[]) set.stream().map(String::valueOf).toArray(String[]::new)) + "}";
|
+ String.join(", ", (CharSequence[]) set.stream().map(String::valueOf).toArray(String[]::new)) + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set getSet() {
|
public Set getSet() {
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBlacklist() {
|
public boolean isBlacklist() {
|
||||||
return blacklist;
|
return blacklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,408 +1,408 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.material.Attachable;
|
import org.bukkit.material.Attachable;
|
||||||
import org.bukkit.material.MaterialData;
|
import org.bukkit.material.MaterialData;
|
||||||
import org.bukkit.projectiles.ProjectileSource;
|
import org.bukkit.projectiles.ProjectileSource;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class SpigotUtil {
|
public class SpigotUtil {
|
||||||
|
|
||||||
private SpigotUtil() {
|
private SpigotUtil() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static World matchWorld(String input) {
|
public static World matchWorld(String input) {
|
||||||
try {
|
try {
|
||||||
UUID uid = UUID.fromString(input);
|
UUID uid = UUID.fromString(input);
|
||||||
World world = Bukkit.getWorld(uid);
|
World world = Bukkit.getWorld(uid);
|
||||||
if (world != null) {
|
if (world != null) {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException ignored) {
|
} catch (IllegalArgumentException ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
World result = Bukkit.getWorld(input);
|
World result = Bukkit.getWorld(input);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
input = input.toLowerCase().replace("_", "").replaceAll("[-_]", "");
|
input = input.toLowerCase().replace("_", "").replaceAll("[-_]", "");
|
||||||
for (World world : Bukkit.getWorlds()) {
|
for (World world : Bukkit.getWorlds()) {
|
||||||
if (world.getName().toLowerCase().equals(input)) {
|
if (world.getName().toLowerCase().equals(input)) {
|
||||||
result = world;
|
result = world;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Block getSupportingBlock(Block block) {
|
public static Block getSupportingBlock(Block block) {
|
||||||
MaterialData data = block.getState().getData();
|
MaterialData data = block.getState().getData();
|
||||||
if (data instanceof Attachable) {
|
if (data instanceof Attachable) {
|
||||||
BlockFace attachedOn = ((Attachable) data).getAttachedFace();
|
BlockFace attachedOn = ((Attachable) data).getAttachedFace();
|
||||||
return block.getRelative(attachedOn);
|
return block.getRelative(attachedOn);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isItemPresent(ItemStack stack) {
|
public static boolean isItemPresent(ItemStack stack) {
|
||||||
return stack != null && stack.getType() != Material.AIR && stack.getAmount() > 0;
|
return stack != null && stack.getType() != Material.AIR && stack.getAmount() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean removeItems(Inventory from, ItemStack item, int amount) {
|
public static boolean removeItems(Inventory from, ItemStack item, int amount) {
|
||||||
for (Map.Entry<Integer, ? extends ItemStack> entry : from.all(item.getType()).entrySet()) {
|
for (Map.Entry<Integer, ? extends ItemStack> entry : from.all(item.getType()).entrySet()) {
|
||||||
ItemStack stack = entry.getValue();
|
ItemStack stack = entry.getValue();
|
||||||
if (item.isSimilar(stack)) {
|
if (item.isSimilar(stack)) {
|
||||||
amount -= stack.getAmount();
|
amount -= stack.getAmount();
|
||||||
int stackAmount = -Math.min(0, amount);
|
int stackAmount = -Math.min(0, amount);
|
||||||
if (stackAmount == 0) {
|
if (stackAmount == 0) {
|
||||||
from.setItem(entry.getKey(), null);
|
from.setItem(entry.getKey(), null);
|
||||||
} else {
|
} else {
|
||||||
stack.setAmount(stackAmount);
|
stack.setAmount(stackAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return amount <= 0;
|
return amount <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlockFace yawToFace(float yaw) {
|
public static BlockFace yawToFace(float yaw) {
|
||||||
if ((yaw %= 360) < 0)
|
if ((yaw %= 360) < 0)
|
||||||
yaw += 360;
|
yaw += 360;
|
||||||
if (45 <= yaw && yaw < 135)
|
if (45 <= yaw && yaw < 135)
|
||||||
return BlockFace.WEST;
|
return BlockFace.WEST;
|
||||||
if (135 <= yaw && yaw < 225)
|
if (135 <= yaw && yaw < 225)
|
||||||
return BlockFace.NORTH;
|
return BlockFace.NORTH;
|
||||||
if (225 <= yaw && yaw < 315)
|
if (225 <= yaw && yaw < 315)
|
||||||
return BlockFace.EAST;
|
return BlockFace.EAST;
|
||||||
return BlockFace.SOUTH;
|
return BlockFace.SOUTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addItems(InventoryHolder entity, ItemStack... items) {
|
public static void addItems(InventoryHolder entity, ItemStack... items) {
|
||||||
Location dropLocation;
|
Location dropLocation;
|
||||||
if (entity instanceof Entity) {
|
if (entity instanceof Entity) {
|
||||||
dropLocation = ((Entity) entity).getLocation();
|
dropLocation = ((Entity) entity).getLocation();
|
||||||
} else if (entity instanceof BlockState) {
|
} else if (entity instanceof BlockState) {
|
||||||
dropLocation = ((BlockState) entity).getLocation().add(0.5, 1, 0.5);
|
dropLocation = ((BlockState) entity).getLocation().add(0.5, 1, 0.5);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Can't find location of this InventoryHolder: " + entity);
|
throw new IllegalArgumentException("Can't find location of this InventoryHolder: " + entity);
|
||||||
}
|
}
|
||||||
World world = dropLocation.getWorld();
|
World world = dropLocation.getWorld();
|
||||||
for (ItemStack toDrop : entity.getInventory().addItem(items).values()) {
|
for (ItemStack toDrop : entity.getInventory().addItem(items).values()) {
|
||||||
world.dropItemNaturally(dropLocation, toDrop);
|
world.dropItemNaturally(dropLocation, toDrop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String asJsonString(Object object) {
|
public static String asJsonString(Object object) {
|
||||||
return asJsonString(null, object, 0);
|
return asJsonString(null, object, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String asJsonString(String key, Object object, int indentation) {
|
public static String asJsonString(String key, Object object, int indentation) {
|
||||||
String indent = new String(new char[indentation * 2]).replace('\0', ' ');
|
String indent = new String(new char[indentation * 2]).replace('\0', ' ');
|
||||||
StringBuilder builder = new StringBuilder(indent);
|
StringBuilder builder = new StringBuilder(indent);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
builder.append(key).append(": ");
|
builder.append(key).append(": ");
|
||||||
}
|
}
|
||||||
if (object instanceof ConfigurationSerializable) {
|
if (object instanceof ConfigurationSerializable) {
|
||||||
object = ((ConfigurationSerializable) object).serialize();
|
object = ((ConfigurationSerializable) object).serialize();
|
||||||
}
|
}
|
||||||
if (object instanceof Map) {
|
if (object instanceof Map) {
|
||||||
builder.append("{\n");
|
builder.append("{\n");
|
||||||
Map<?, ?> map = (Map) object;
|
Map<?, ?> map = (Map) object;
|
||||||
for (Map.Entry entry : map.entrySet()) {
|
for (Map.Entry entry : map.entrySet()) {
|
||||||
builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1));
|
builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1));
|
||||||
}
|
}
|
||||||
builder.append(indent).append("}");
|
builder.append(indent).append("}");
|
||||||
} else if (object instanceof List) {
|
} else if (object instanceof List) {
|
||||||
builder.append("[\n");
|
builder.append("[\n");
|
||||||
List list = (List) object;
|
List list = (List) object;
|
||||||
for (Object entry : list) {
|
for (Object entry : list) {
|
||||||
builder.append(asJsonString(null, entry, indentation + 1));
|
builder.append(asJsonString(null, entry, indentation + 1));
|
||||||
}
|
}
|
||||||
builder.append(indent).append("]");
|
builder.append(indent).append("]");
|
||||||
} else {
|
} else {
|
||||||
builder.append(String.valueOf(object));
|
builder.append(String.valueOf(object));
|
||||||
}
|
}
|
||||||
return builder.append(",\n").toString();
|
return builder.append(",\n").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String asJsonString(String key, Object object, int indentation, BiConsumer<List<?>, StringBuilder> listHeader) {
|
public static String asJsonString(String key, Object object, int indentation, BiConsumer<List<?>, StringBuilder> listHeader) {
|
||||||
String indent = new String(new char[indentation * 2]).replace('\0', ' ');
|
String indent = new String(new char[indentation * 2]).replace('\0', ' ');
|
||||||
StringBuilder builder = new StringBuilder(indent);
|
StringBuilder builder = new StringBuilder(indent);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
builder.append(key).append(": ");
|
builder.append(key).append(": ");
|
||||||
}
|
}
|
||||||
if (object instanceof ConfigurationSerializable) {
|
if (object instanceof ConfigurationSerializable) {
|
||||||
object = ((ConfigurationSerializable) object).serialize();
|
object = ((ConfigurationSerializable) object).serialize();
|
||||||
}
|
}
|
||||||
if (object instanceof Map) {
|
if (object instanceof Map) {
|
||||||
builder.append("{\n");
|
builder.append("{\n");
|
||||||
Map<?, ?> map = (Map) object;
|
Map<?, ?> map = (Map) object;
|
||||||
for (Map.Entry entry : map.entrySet()) {
|
for (Map.Entry entry : map.entrySet()) {
|
||||||
builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1, listHeader));
|
builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1, listHeader));
|
||||||
}
|
}
|
||||||
builder.append(indent).append("}");
|
builder.append(indent).append("}");
|
||||||
} else if (object instanceof List) {
|
} else if (object instanceof List) {
|
||||||
builder.append("[");
|
builder.append("[");
|
||||||
List list = (List) object;
|
List list = (List) object;
|
||||||
listHeader.accept(list, builder);
|
listHeader.accept(list, builder);
|
||||||
builder.append("\n");
|
builder.append("\n");
|
||||||
for (Object entry : list) {
|
for (Object entry : list) {
|
||||||
builder.append(asJsonString(null, entry, indentation + 1, listHeader));
|
builder.append(asJsonString(null, entry, indentation + 1, listHeader));
|
||||||
}
|
}
|
||||||
builder.append(indent).append("]");
|
builder.append(indent).append("]");
|
||||||
} else {
|
} else {
|
||||||
builder.append(String.valueOf(object));
|
builder.append(String.valueOf(object));
|
||||||
}
|
}
|
||||||
return builder.append(",\n").toString();
|
return builder.append(",\n").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlockFace estimateDirectionTo(Location from, Location to) {
|
public static BlockFace estimateDirectionTo(Location from, Location to) {
|
||||||
double dx = from.getX() - to.getX();
|
double dx = from.getX() - to.getX();
|
||||||
double dz = from.getZ() - to.getZ();
|
double dz = from.getZ() - to.getZ();
|
||||||
|
|
||||||
boolean xGreater = Math.abs(dx) - Math.abs(dz) > 0;
|
boolean xGreater = Math.abs(dx) - Math.abs(dz) > 0;
|
||||||
double f = xGreater ? 2 / Math.abs(dx) : 2 / Math.abs(dz);
|
double f = xGreater ? 2 / Math.abs(dx) : 2 / Math.abs(dz);
|
||||||
dx *= f;
|
dx *= f;
|
||||||
dz *= f;
|
dz *= f;
|
||||||
|
|
||||||
double other = Math.abs(xGreater ? dz : dx);
|
double other = Math.abs(xGreater ? dz : dx);
|
||||||
|
|
||||||
if (other <= .5) {
|
if (other <= .5) {
|
||||||
return xGreater ? (dx < 0 ? BlockFace.WEST : BlockFace.EAST) : (dz < 0 ? BlockFace.NORTH : BlockFace.SOUTH);
|
return xGreater ? (dx < 0 ? BlockFace.WEST : BlockFace.EAST) : (dz < 0 ? BlockFace.NORTH : BlockFace.SOUTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other < 1.5) {
|
if (other < 1.5) {
|
||||||
if (xGreater) {
|
if (xGreater) {
|
||||||
return dx < 0 ? (dz < 0 ? BlockFace.WEST_NORTH_WEST : BlockFace.WEST_SOUTH_WEST) : (dz < 0 ? BlockFace.EAST_NORTH_EAST : BlockFace.EAST_SOUTH_EAST);
|
return dx < 0 ? (dz < 0 ? BlockFace.WEST_NORTH_WEST : BlockFace.WEST_SOUTH_WEST) : (dz < 0 ? BlockFace.EAST_NORTH_EAST : BlockFace.EAST_SOUTH_EAST);
|
||||||
}
|
}
|
||||||
return dx < 0 ? (dz < 0 ? BlockFace.NORTH_NORTH_WEST : BlockFace.SOUTH_SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_NORTH_EAST : BlockFace.SOUTH_SOUTH_EAST);
|
return dx < 0 ? (dz < 0 ? BlockFace.NORTH_NORTH_WEST : BlockFace.SOUTH_SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_NORTH_EAST : BlockFace.SOUTH_SOUTH_EAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dx < 0 ? (dz < 0 ? BlockFace.NORTH_WEST : BlockFace.SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_EAST : BlockFace.SOUTH_EAST);
|
return dx < 0 ? (dz < 0 ? BlockFace.NORTH_WEST : BlockFace.SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_EAST : BlockFace.SOUTH_EAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Entity findEntityFromDamager(Entity damager, EntityType searched) {
|
public static Entity findEntityFromDamager(Entity damager, EntityType searched) {
|
||||||
if (damager.getType() == searched) {
|
if (damager.getType() == searched) {
|
||||||
return damager;
|
return damager;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (damager instanceof Projectile) {
|
if (damager instanceof Projectile) {
|
||||||
ProjectileSource shooter = ((Projectile) damager).getShooter();
|
ProjectileSource shooter = ((Projectile) damager).getShooter();
|
||||||
if (shooter instanceof Entity && ((Entity) shooter).getType() == searched) {
|
if (shooter instanceof Entity && ((Entity) shooter).getType() == searched) {
|
||||||
return (Entity) shooter;
|
return (Entity) shooter;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (damager.getType() == EntityType.PRIMED_TNT) {
|
if (damager.getType() == EntityType.PRIMED_TNT) {
|
||||||
Entity source = ((TNTPrimed) damager).getSource();
|
Entity source = ((TNTPrimed) damager).getSource();
|
||||||
if (source.getType() == searched) {
|
if (source.getType() == searched) {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int xpForNextLevel(int currentLevel) {
|
public static int xpForNextLevel(int currentLevel) {
|
||||||
if (currentLevel >= 30) {
|
if (currentLevel >= 30) {
|
||||||
return 112 + (currentLevel - 30) * 9;
|
return 112 + (currentLevel - 30) * 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentLevel >= 15) {
|
if (currentLevel >= 15) {
|
||||||
return 37 + (currentLevel - 15) * 5;
|
return 37 + (currentLevel - 15) * 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 7 + currentLevel * 2;
|
return 7 + currentLevel * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int removeExp(Player entity, int xp) {
|
public static int removeExp(Player entity, int xp) {
|
||||||
int total = entity.getTotalExperience();
|
int total = entity.getTotalExperience();
|
||||||
if (xp > total) {
|
if (xp > total) {
|
||||||
xp = total;
|
xp = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
int level = entity.getLevel();
|
int level = entity.getLevel();
|
||||||
if (level < 0) {
|
if (level < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int removed = 0;
|
int removed = 0;
|
||||||
int xpForNextLevel = xpForNextLevel(level);
|
int xpForNextLevel = xpForNextLevel(level);
|
||||||
int current = (int) entity.getExp() * xpForNextLevel;
|
int current = (int) entity.getExp() * xpForNextLevel;
|
||||||
|
|
||||||
if (xp > current) {
|
if (xp > current) {
|
||||||
xp -= current;
|
xp -= current;
|
||||||
total -= current;
|
total -= current;
|
||||||
removed += current;
|
removed += current;
|
||||||
|
|
||||||
if (level == 0) {
|
if (level == 0) {
|
||||||
entity.setExp(0F);
|
entity.setExp(0F);
|
||||||
entity.setTotalExperience(total);
|
entity.setTotalExperience(total);
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
current -= xp;
|
current -= xp;
|
||||||
total -= xp;
|
total -= xp;
|
||||||
removed += xp;
|
removed += xp;
|
||||||
|
|
||||||
entity.setExp((float) current / xpForNextLevel);
|
entity.setExp((float) current / xpForNextLevel);
|
||||||
entity.setTotalExperience(total);
|
entity.setTotalExperience(total);
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
xpForNextLevel = xpForNextLevel(--level);
|
xpForNextLevel = xpForNextLevel(--level);
|
||||||
if (xpForNextLevel >= xp) {
|
if (xpForNextLevel >= xp) {
|
||||||
total -= xp;
|
total -= xp;
|
||||||
removed += xp;
|
removed += xp;
|
||||||
|
|
||||||
entity.setExp(1F / xpForNextLevel * (xpForNextLevel - xp));
|
entity.setExp(1F / xpForNextLevel * (xpForNextLevel - xp));
|
||||||
entity.setTotalExperience(total);
|
entity.setTotalExperience(total);
|
||||||
entity.setLevel(level);
|
entity.setLevel(level);
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
xp -= xpForNextLevel;
|
xp -= xpForNextLevel;
|
||||||
total -= xpForNextLevel;
|
total -= xpForNextLevel;
|
||||||
removed += xpForNextLevel;
|
removed += xpForNextLevel;
|
||||||
} while (level > 0);
|
} while (level > 0);
|
||||||
|
|
||||||
entity.setExp(0F);
|
entity.setExp(0F);
|
||||||
entity.setTotalExperience(0);
|
entity.setTotalExperience(0);
|
||||||
entity.setLevel(0);
|
entity.setLevel(0);
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getTotalExp(Player entity) {
|
public static int getTotalExp(Player entity) {
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
int level = Math.min(entity.getLevel(), 20000);
|
int level = Math.min(entity.getLevel(), 20000);
|
||||||
for (int i = 0; i < level; i++) {
|
for (int i = 0; i < level; i++) {
|
||||||
rv += xpForNextLevel(i);
|
rv += xpForNextLevel(i);
|
||||||
}
|
}
|
||||||
rv += Math.min(1F, Math.max(0F, entity.getExp())) * xpForNextLevel(level);
|
rv += Math.min(1F, Math.max(0F, entity.getExp())) * xpForNextLevel(level);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double getTotalExpLevels(Player entity) {
|
public static double getTotalExpLevels(Player entity) {
|
||||||
int xp = entity.getTotalExperience();
|
int xp = entity.getTotalExperience();
|
||||||
|
|
||||||
int level = 0;
|
int level = 0;
|
||||||
while (xp > 0 && level < 20000) {
|
while (xp > 0 && level < 20000) {
|
||||||
int needed = xpForNextLevel(level);
|
int needed = xpForNextLevel(level);
|
||||||
if (needed > xp) {
|
if (needed > xp) {
|
||||||
return level + ((double) xp / needed);
|
return level + ((double) xp / needed);
|
||||||
}
|
}
|
||||||
xp -= needed;
|
xp -= needed;
|
||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getNearbyPlayerCount(Player origin, double range, Predicate<Player> predicate) {
|
public static int getNearbyPlayerCount(Player origin, double range, Predicate<Player> predicate) {
|
||||||
List<Entity> entities = origin.getNearbyEntities(range, range, range);
|
List<Entity> entities = origin.getNearbyEntities(range, range, range);
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
|
if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
|
||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getNearbyPlayers(Player origin, double range, Collection<Player> collection, Predicate<Player> predicate) {
|
public static void getNearbyPlayers(Player origin, double range, Collection<Player> collection, Predicate<Player> predicate) {
|
||||||
List<Entity> entities = origin.getNearbyEntities(range, range, range);
|
List<Entity> entities = origin.getNearbyEntities(range, range, range);
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
|
if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
|
||||||
collection.add((Player) entity);
|
collection.add((Player) entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forEachNearbyPlayer(Player origin, double range, Consumer<Player> action) {
|
public static void forEachNearbyPlayer(Player origin, double range, Consumer<Player> action) {
|
||||||
List<Entity> entities = origin.getNearbyEntities(range, range, range);
|
List<Entity> entities = origin.getNearbyEntities(range, range, range);
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
if (entity.getType() == EntityType.PLAYER) {
|
if (entity.getType() == EntityType.PLAYER) {
|
||||||
action.accept((Player) entity);
|
action.accept((Player) entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double distanceSquared(Location first, Location second) {
|
public static double distanceSquared(Location first, Location second) {
|
||||||
double dx = first.getX() - second.getX();
|
double dx = first.getX() - second.getX();
|
||||||
double dy = first.getY() - second.getY();
|
double dy = first.getY() - second.getY();
|
||||||
double dz = first.getZ() - second.getZ();
|
double dz = first.getZ() - second.getZ();
|
||||||
|
|
||||||
return dx * dx + dy * dy + dz * dz;
|
return dx * dx + dy * dy + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <T extends Entity> Iterator<T> findNearbyEntities(Entity origin, boolean includeSelf, Predicate<Entity> predicate, double horizontalRange, double verticalRange) {
|
public static <T extends Entity> Iterator<T> findNearbyEntities(Entity origin, boolean includeSelf, Predicate<Entity> predicate, double horizontalRange, double verticalRange) {
|
||||||
Objects.requireNonNull(origin);
|
Objects.requireNonNull(origin);
|
||||||
return new Iterator<T>() {
|
return new Iterator<T>() {
|
||||||
Entity next;
|
Entity next;
|
||||||
List<Entity> nearby;
|
List<Entity> nearby;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
{
|
{
|
||||||
if (includeSelf) {
|
if (includeSelf) {
|
||||||
next = origin;
|
next = origin;
|
||||||
} else {
|
} else {
|
||||||
next = findNext();
|
next = findNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity findNext() {
|
Entity findNext() {
|
||||||
if (nearby == null) {
|
if (nearby == null) {
|
||||||
nearby = origin.getNearbyEntities(horizontalRange, verticalRange, horizontalRange);
|
nearby = origin.getNearbyEntities(horizontalRange, verticalRange, horizontalRange);
|
||||||
size = nearby.size();
|
size = nearby.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (index < size) {
|
while (index < size) {
|
||||||
Entity e = nearby.get(index++);
|
Entity e = nearby.get(index++);
|
||||||
if (predicate.test(e)) {
|
if (predicate.test(e)) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return next != null;
|
return next != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T next() {
|
public T next() {
|
||||||
if (next == null) {
|
if (next == null) {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
Entity result = next;
|
Entity result = next;
|
||||||
next = findNext();
|
next = findNext();
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (T) result;
|
return (T) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,473 +1,473 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
public class StringUtil {
|
public class StringUtil {
|
||||||
|
|
||||||
public static String capitalize(String input) {
|
public static String capitalize(String input) {
|
||||||
if (input.length() > 0) {
|
if (input.length() > 0) {
|
||||||
char first = input.charAt(0);
|
char first = input.charAt(0);
|
||||||
if (first != (first = Character.toUpperCase(first))) {
|
if (first != (first = Character.toUpperCase(first))) {
|
||||||
char[] result = input.toCharArray();
|
char[] result = input.toCharArray();
|
||||||
result[0] = first;
|
result[0] = first;
|
||||||
return String.valueOf(result);
|
return String.valueOf(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Capitalizes the first character of the string or the first character of each word
|
* Capitalizes the first character of the string or the first character of each word
|
||||||
*
|
*
|
||||||
* @param input the string to capitalize
|
* @param input the string to capitalize
|
||||||
* @param spaceChar the character separating each word. If @code '\0' is passed, only the first character of
|
* @param spaceChar the character separating each word. If @code '\0' is passed, only the first character of
|
||||||
* the input is capitalized.
|
* the input is capitalized.
|
||||||
* @return the capitalized string
|
* @return the capitalized string
|
||||||
*/
|
*/
|
||||||
public static String capitalize(String input, char spaceChar) {
|
public static String capitalize(String input, char spaceChar) {
|
||||||
if (spaceChar == '\0') {
|
if (spaceChar == '\0') {
|
||||||
return capitalize(input);
|
return capitalize(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] result = null;
|
char[] result = null;
|
||||||
boolean capitalize = true;
|
boolean capitalize = true;
|
||||||
for (int n = input.length(), i = 0; i < n; i++) {
|
for (int n = input.length(), i = 0; i < n; i++) {
|
||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
if (capitalize && c != (c = Character.toUpperCase(c))) {
|
if (capitalize && c != (c = Character.toUpperCase(c))) {
|
||||||
if (result == null) result = input.toCharArray();
|
if (result == null) result = input.toCharArray();
|
||||||
result[i] = c;
|
result[i] = c;
|
||||||
}
|
}
|
||||||
capitalize = c == spaceChar;
|
capitalize = c == spaceChar;
|
||||||
}
|
}
|
||||||
return result != null ? String.valueOf(result) : input;
|
return result != null ? String.valueOf(result) : input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String capitalize(String input, char spaceChar, char newSpaceChar) {
|
public static String capitalize(String input, char spaceChar, char newSpaceChar) {
|
||||||
if (newSpaceChar == '\0') {
|
if (newSpaceChar == '\0') {
|
||||||
return capitalize(input, spaceChar);
|
return capitalize(input, spaceChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] result = null;
|
char[] result = null;
|
||||||
boolean capitalize = true;
|
boolean capitalize = true;
|
||||||
for (int n = input.length(), i = 0; i < n; i++) {
|
for (int n = input.length(), i = 0; i < n; i++) {
|
||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
if (capitalize && c != (c = Character.toUpperCase(c))) {
|
if (capitalize && c != (c = Character.toUpperCase(c))) {
|
||||||
if (result == null) result = input.toCharArray();
|
if (result == null) result = input.toCharArray();
|
||||||
result[i] = c;
|
result[i] = c;
|
||||||
}
|
}
|
||||||
if (capitalize = c == spaceChar) {
|
if (capitalize = c == spaceChar) {
|
||||||
if (result == null) result = input.toCharArray();
|
if (result == null) result = input.toCharArray();
|
||||||
result[i] = newSpaceChar;
|
result[i] = newSpaceChar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result != null ? String.valueOf(result) : input;
|
return result != null ? String.valueOf(result) : input;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a lowercase version of the input with _ replaced with a space.
|
* Returns a lowercase version of the input with _ replaced with a space.
|
||||||
* Mainly used for making names of enum constants readable.
|
* Mainly used for making names of enum constants readable.
|
||||||
*
|
*
|
||||||
* @param input
|
* @param input
|
||||||
* @return a humanified version of @code input
|
* @return a humanified version of @code input
|
||||||
*/
|
*/
|
||||||
public static String humanify(String input) {
|
public static String humanify(String input) {
|
||||||
return input == null ? null : input.toLowerCase().replace('_', ' ');
|
return input == null ? null : input.toLowerCase().replace('_', ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enumerate the given items, separating them by ", " and finally by " and "
|
* Enumerate the given items, separating them by ", " and finally by " and "
|
||||||
*
|
*
|
||||||
* @param words the items to enumerate (it's not really enumerating....)
|
* @param words the items to enumerate (it's not really enumerating....)
|
||||||
* @return the enumerated string
|
* @return the enumerated string
|
||||||
*/
|
*/
|
||||||
public static String enumerate(String... words) {
|
public static String enumerate(String... words) {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
int size = words.length;
|
int size = words.length;
|
||||||
int secondLastIndex = size - 2;
|
int secondLastIndex = size - 2;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
String word = words[i];
|
String word = words[i];
|
||||||
if (word.isEmpty())
|
if (word.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
result.append(word);
|
result.append(word);
|
||||||
if (i < secondLastIndex)
|
if (i < secondLastIndex)
|
||||||
result.append(", ");
|
result.append(", ");
|
||||||
else if (i == secondLastIndex)
|
else if (i == secondLastIndex)
|
||||||
result.append(" and ");
|
result.append(" and ");
|
||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String enumerate(String list, String regex) {
|
public static String enumerate(String list, String regex) {
|
||||||
return enumerate(list.split(regex));
|
return enumerate(list.split(regex));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a formatted string of the length in millis, containing days, hours and minutes.
|
* Return a formatted string of the length in millis, containing days, hours and minutes.
|
||||||
*
|
*
|
||||||
* @param length The delay in milliseconds
|
* @param length The delay in milliseconds
|
||||||
* @return the formatted string
|
* @return the formatted string
|
||||||
*/
|
*/
|
||||||
public static String getTimeLength(long length) {
|
public static String getTimeLength(long length) {
|
||||||
int minute = 60000; // in millis
|
int minute = 60000; // in millis
|
||||||
int hour = 60 * minute;
|
int hour = 60 * minute;
|
||||||
int day = 24 * hour;
|
int day = 24 * hour;
|
||||||
|
|
||||||
int minutes = (int) ((length / minute) % 60);
|
int minutes = (int) ((length / minute) % 60);
|
||||||
int hours = (int) ((length / hour) % 24);
|
int hours = (int) ((length / hour) % 24);
|
||||||
int days = (int) (length / day); //returns floor
|
int days = (int) (length / day); //returns floor
|
||||||
|
|
||||||
String result = ""; // It will be splitted at "|"
|
String result = ""; // It will be splitted at "|"
|
||||||
if (days != 0)
|
if (days != 0)
|
||||||
result += days + " days|";
|
result += days + " days|";
|
||||||
if (hours != 0)
|
if (hours != 0)
|
||||||
result += hours + " hours|";
|
result += hours + " hours|";
|
||||||
if (minutes != 0)
|
if (minutes != 0)
|
||||||
result += minutes + " minutes|";
|
result += minutes + " minutes|";
|
||||||
return enumerate(result.split("\\|"));
|
return enumerate(result.split("\\|"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a formatted String to represent the given time length, in the given units
|
* Return a formatted String to represent the given time length, in the given units
|
||||||
*
|
*
|
||||||
* @param sourceAmount Amount of delay
|
* @param sourceAmount Amount of delay
|
||||||
* @param sourceUnit Unit of delay
|
* @param sourceUnit Unit of delay
|
||||||
* @param ifEmpty the String to return if the
|
* @param ifEmpty the String to return if the
|
||||||
* @param displayedUnits units displayed
|
* @param displayedUnits units displayed
|
||||||
* @return the formatted string
|
* @return the formatted string
|
||||||
* @throws IllegalArgumentException if there are no displayed units
|
* @throws IllegalArgumentException if there are no displayed units
|
||||||
*/
|
*/
|
||||||
public static String getTimeLength(long sourceAmount, TimeUnit sourceUnit, String ifEmpty, TimeUnit... displayedUnits) {
|
public static String getTimeLength(long sourceAmount, TimeUnit sourceUnit, String ifEmpty, TimeUnit... displayedUnits) {
|
||||||
if (displayedUnits.length == 0) {
|
if (displayedUnits.length == 0) {
|
||||||
throw new IllegalArgumentException("No displayed units");
|
throw new IllegalArgumentException("No displayed units");
|
||||||
}
|
}
|
||||||
Arrays.sort(displayedUnits, Collections.reverseOrder(TimeUnit::compareTo)); // sort by opposite of enum declaration order (largest -> smallest)
|
Arrays.sort(displayedUnits, Collections.reverseOrder(TimeUnit::compareTo)); // sort by opposite of enum declaration order (largest -> smallest)
|
||||||
List<String> segments = new ArrayList<>(displayedUnits.length);
|
List<String> segments = new ArrayList<>(displayedUnits.length);
|
||||||
for (TimeUnit unit : displayedUnits) {
|
for (TimeUnit unit : displayedUnits) {
|
||||||
long displayedAmount = unit.convert(sourceAmount, sourceUnit);
|
long displayedAmount = unit.convert(sourceAmount, sourceUnit);
|
||||||
sourceAmount -= sourceUnit.convert(displayedAmount, unit);
|
sourceAmount -= sourceUnit.convert(displayedAmount, unit);
|
||||||
if (displayedAmount > 0) {
|
if (displayedAmount > 0) {
|
||||||
String unitWord = unit.name().toLowerCase(); // plural
|
String unitWord = unit.name().toLowerCase(); // plural
|
||||||
if (displayedAmount == 1) {
|
if (displayedAmount == 1) {
|
||||||
unitWord = unitWord.substring(0, unitWord.length() - 1); // remove s at the end
|
unitWord = unitWord.substring(0, unitWord.length() - 1); // remove s at the end
|
||||||
}
|
}
|
||||||
segments.add(displayedAmount + " " + unitWord);
|
segments.add(displayedAmount + " " + unitWord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return segments.isEmpty() ? ifEmpty : enumerate(segments.toArray(new String[segments.size()]));
|
return segments.isEmpty() ? ifEmpty : enumerate(segments.toArray(new String[segments.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the delay represented by a ban-like delay representation, in milliseconds
|
* Returns the delay represented by a ban-like delay representation, in milliseconds
|
||||||
* Example: "5d2h5m3s" for 5 days, 2 hours, 5 minutes and 3 seconds.
|
* Example: "5d2h5m3s" for 5 days, 2 hours, 5 minutes and 3 seconds.
|
||||||
* <p>
|
* <p>
|
||||||
* Supported characters are s, m, h, d, w.
|
* Supported characters are s, m, h, d, w.
|
||||||
* Negative numbers are supported.
|
* Negative numbers are supported.
|
||||||
*
|
*
|
||||||
* @param input The input string
|
* @param input The input string
|
||||||
* @return The delay in milliseconds
|
* @return The delay in milliseconds
|
||||||
* @throws IllegalArgumentException if the input string isn't properly formatted, or any non-digit character isn't recognized (capitals are not recognized).
|
* @throws IllegalArgumentException if the input string isn't properly formatted, or any non-digit character isn't recognized (capitals are not recognized).
|
||||||
*/
|
*/
|
||||||
public static long getTimeLength(String input) { //if -1: error
|
public static long getTimeLength(String input) { //if -1: error
|
||||||
long count = 0;
|
long count = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < input.length()) {
|
while (i < input.length()) {
|
||||||
int num = 0;
|
int num = 0;
|
||||||
char unit = '\0';
|
char unit = '\0';
|
||||||
boolean negate;
|
boolean negate;
|
||||||
if (negate = input.charAt(i) == '-') {
|
if (negate = input.charAt(i) == '-') {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
char c = input.charAt(i);
|
char c = input.charAt(i);
|
||||||
int digit = c - '0';
|
int digit = c - '0';
|
||||||
if (0 <= digit && digit < 10) {
|
if (0 <= digit && digit < 10) {
|
||||||
num = 10 * num + digit;
|
num = 10 * num + digit;
|
||||||
} else {
|
} else {
|
||||||
unit = c;
|
unit = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (i < input.length());
|
} while (i < input.length());
|
||||||
|
|
||||||
long unitTime = getUnitTime(unit);
|
long unitTime = getUnitTime(unit);
|
||||||
if (unitTime == -1)
|
if (unitTime == -1)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (negate) {
|
if (negate) {
|
||||||
unitTime = -unitTime;
|
unitTime = -unitTime;
|
||||||
}
|
}
|
||||||
count += (num * unitTime);
|
count += (num * unitTime);
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time represented by the given unit character in milliseconds.
|
* Returns the time represented by the given unit character in milliseconds.
|
||||||
* <p>
|
* <p>
|
||||||
* 's' -> 1000
|
* 's' -> 1000
|
||||||
* 'm' -> 1000 * 60
|
* 'm' -> 1000 * 60
|
||||||
* 'h' -> 1000 * 60 * 60
|
* 'h' -> 1000 * 60 * 60
|
||||||
* 'd' -> 1000 * 60 * 60 * 24
|
* 'd' -> 1000 * 60 * 60 * 24
|
||||||
* 'w' -> 1000 * 60 * 60 * 24 * 7
|
* 'w' -> 1000 * 60 * 60 * 24 * 7
|
||||||
* anything else -> -1
|
* anything else -> -1
|
||||||
*
|
*
|
||||||
* @param unit The unit character, as shown above
|
* @param unit The unit character, as shown above
|
||||||
* @return the millisecond delay represented by the unit
|
* @return the millisecond delay represented by the unit
|
||||||
*/
|
*/
|
||||||
public static long getUnitTime(char unit) { //if -1: no value found
|
public static long getUnitTime(char unit) { //if -1: no value found
|
||||||
switch (Character.toLowerCase(unit)) {
|
switch (Character.toLowerCase(unit)) {
|
||||||
case 's':
|
case 's':
|
||||||
return 1000;
|
return 1000;
|
||||||
case 'm':
|
case 'm':
|
||||||
return 1000 * 60;
|
return 1000 * 60;
|
||||||
case 'h':
|
case 'h':
|
||||||
return 1000 * 60 * 60;
|
return 1000 * 60 * 60;
|
||||||
case 'd':
|
case 'd':
|
||||||
return 1000 * 60 * 60 * 24;
|
return 1000 * 60 * 60 * 24;
|
||||||
case 'w':
|
case 'w':
|
||||||
return 1000 * 60 * 60 * 24 * 7;
|
return 1000 * 60 * 60 * 24 * 7;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes a binary representation of the value.
|
* Computes a binary representation of the value.
|
||||||
* The returned representation always displays 64 bits.
|
* The returned representation always displays 64 bits.
|
||||||
* Every 8 bits, the digits are seperated by an _
|
* Every 8 bits, the digits are seperated by an _
|
||||||
* The representation is prefixed by 0b.
|
* The representation is prefixed by 0b.
|
||||||
* <p>
|
* <p>
|
||||||
* Example: 0b00000000_11111111_00000001_11110000_00001111_11001100_00001111_10111010
|
* Example: 0b00000000_11111111_00000001_11110000_00001111_11001100_00001111_10111010
|
||||||
*
|
*
|
||||||
* @param entry the value to represent in binary
|
* @param entry the value to represent in binary
|
||||||
* @return A binary representation of the long value
|
* @return A binary representation of the long value
|
||||||
*/
|
*/
|
||||||
public static String toBinaryString(long entry) {
|
public static String toBinaryString(long entry) {
|
||||||
String binary = Long.toBinaryString(entry);
|
String binary = Long.toBinaryString(entry);
|
||||||
String binary64 = String.valueOf(new char[64 - binary.length()]).replace('\0', '0') + binary;
|
String binary64 = String.valueOf(new char[64 - binary.length()]).replace('\0', '0') + binary;
|
||||||
String withUnderscores = String.join("_", IntStream.range(0, 8).mapToObj(x -> binary64.substring(x * 8, x * 8 + 8)).toArray(String[]::new));
|
String withUnderscores = String.join("_", IntStream.range(0, 8).mapToObj(x -> binary64.substring(x * 8, x * 8 + 8)).toArray(String[]::new));
|
||||||
return "0b" + withUnderscores;
|
return "0b" + withUnderscores;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turns a generic java classname into a name formatted properly to be an enum constant.
|
* Turns a generic java classname into a name formatted properly to be an enum constant.
|
||||||
*
|
*
|
||||||
* @param name The string value I'd describe as a generic java classname (so we have CapitalCase)
|
* @param name The string value I'd describe as a generic java classname (so we have CapitalCase)
|
||||||
* @return An enum constant version of it (ENUM_FORMAT: CAPITAL_CASE)
|
* @return An enum constant version of it (ENUM_FORMAT: CAPITAL_CASE)
|
||||||
*/
|
*/
|
||||||
public static String toEnumFormat(String name) {
|
public static String toEnumFormat(String name) {
|
||||||
StringBuilder result = new StringBuilder(name.length() + 2);
|
StringBuilder result = new StringBuilder(name.length() + 2);
|
||||||
|
|
||||||
boolean capital = true;
|
boolean capital = true;
|
||||||
for (int i = 0, n = name.length(); i < n; i++) {
|
for (int i = 0, n = name.length(); i < n; i++) {
|
||||||
char c = name.charAt(i);
|
char c = name.charAt(i);
|
||||||
if (capital) {
|
if (capital) {
|
||||||
capital = Character.isUpperCase(c);
|
capital = Character.isUpperCase(c);
|
||||||
} else if (Character.isUpperCase(c)) {
|
} else if (Character.isUpperCase(c)) {
|
||||||
capital = true;
|
capital = true;
|
||||||
result.append('_');
|
result.append('_');
|
||||||
}
|
}
|
||||||
result.append(capital ? c : Character.toUpperCase(c));
|
result.append(capital ? c : Character.toUpperCase(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces any occurrence of toReplace with another string.
|
* Replaces any occurrence of toReplace with another string.
|
||||||
* Any colours that occured before the occurence of toReplace, are copied to the end of the replacement.
|
* Any colours that occured before the occurence of toReplace, are copied to the end of the replacement.
|
||||||
*
|
*
|
||||||
* @param target The String to query
|
* @param target The String to query
|
||||||
* @param toReplace The sequence to replace
|
* @param toReplace The sequence to replace
|
||||||
* @param with the replacing sequence
|
* @param with the replacing sequence
|
||||||
* @return the result
|
* @return the result
|
||||||
*/
|
*/
|
||||||
public static String replaceKeepColours(String target, String toReplace, String with) {
|
public static String replaceKeepColours(String target, String toReplace, String with) {
|
||||||
int index = -toReplace.length();
|
int index = -toReplace.length();
|
||||||
while ((index = target.indexOf(toReplace, index + toReplace.length())) != -1) {
|
while ((index = target.indexOf(toReplace, index + toReplace.length())) != -1) {
|
||||||
String start = target.substring(0, index);
|
String start = target.substring(0, index);
|
||||||
Formatting coloursBefore = Formatting.getFormats(start);
|
Formatting coloursBefore = Formatting.getFormats(start);
|
||||||
String after;
|
String after;
|
||||||
try {
|
try {
|
||||||
after = target.substring(index + toReplace.length());
|
after = target.substring(index + toReplace.length());
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (IndexOutOfBoundsException e) {
|
||||||
after = "";
|
after = "";
|
||||||
}
|
}
|
||||||
target = start + with + coloursBefore + after;
|
target = start + with + coloursBefore + after;
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String replParam(String target, String param, Object repl) {
|
public static String replParam(String target, String param, Object repl) {
|
||||||
return replParam(target, param, repl, false);
|
return replParam(target, param, repl, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String replParams(String target, String[] params, Object[] repls) {
|
public static String replParams(String target, String[] params, Object[] repls) {
|
||||||
return replParams(target, params, repls, false, false);
|
return replParams(target, params, repls, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParams(String[] target, String[] params, Object[] repls) {
|
public static boolean replParams(String[] target, String[] params, Object[] repls) {
|
||||||
return replParams(target, 0, target.length, params, repls);
|
return replParams(target, 0, target.length, params, repls);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls) {
|
public static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls) {
|
||||||
return replParams(target, from, to, params, repls, false);
|
return replParams(target, from, to, params, repls, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParams(List<String> target, String[] params, Object[] repls) {
|
public static boolean replParams(List<String> target, String[] params, Object[] repls) {
|
||||||
return replParams(target, 0, target.size(), params, repls);
|
return replParams(target, 0, target.size(), params, repls);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls) {
|
public static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls) {
|
||||||
return replParams(target, from, to, params, repls, false);
|
return replParams(target, from, to, params, repls, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String replParamAndTranslate(String target, String param, Object repl) {
|
public static String replParamAndTranslate(String target, String param, Object repl) {
|
||||||
return replParam(target, param, repl, true);
|
return replParam(target, param, repl, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String replParamsAndTranslate(String target, String[] params, Object[] repls) {
|
public static String replParamsAndTranslate(String target, String[] params, Object[] repls) {
|
||||||
return replParams(target, params, repls, false, true);
|
return replParams(target, params, repls, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParamsAndTranslate(String[] target, String[] params, Object[] repls) {
|
public static boolean replParamsAndTranslate(String[] target, String[] params, Object[] repls) {
|
||||||
return replParamsAndTranslate(target, 0, target.length, params, repls);
|
return replParamsAndTranslate(target, 0, target.length, params, repls);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParamsAndTranslate(String[] target, int from, int to, String[] params, Object[] repls) {
|
public static boolean replParamsAndTranslate(String[] target, int from, int to, String[] params, Object[] repls) {
|
||||||
return replParams(target, from, to, params, repls, true);
|
return replParams(target, from, to, params, repls, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParamsAndTranslate(List<String> target, String[] params, Object[] repls) {
|
public static boolean replParamsAndTranslate(List<String> target, String[] params, Object[] repls) {
|
||||||
return replParamsAndTranslate(target, 0, target.size(), params, repls);
|
return replParamsAndTranslate(target, 0, target.size(), params, repls);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean replParamsAndTranslate(List<String> target, int from, int to, String[] params, Object[] repls) {
|
public static boolean replParamsAndTranslate(List<String> target, int from, int to, String[] params, Object[] repls) {
|
||||||
return replParams(target, from, to, params, repls, true);
|
return replParams(target, from, to, params, repls, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String replParam(String target, String param, Object replacementObj, boolean translate) {
|
private static String replParam(String target, String param, Object replacementObj, boolean translate) {
|
||||||
int idx = target.indexOf(param, 0);
|
int idx = target.indexOf(param, 0);
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
return translate ? Formatting.translate(target) : target;
|
return translate ? Formatting.translate(target) : target;
|
||||||
}
|
}
|
||||||
|
|
||||||
String rep = replacementObj.toString();
|
String rep = replacementObj.toString();
|
||||||
StringBuilder builder = new StringBuilder(target);
|
StringBuilder builder = new StringBuilder(target);
|
||||||
do {
|
do {
|
||||||
builder.replace(idx, idx + param.length(), rep);
|
builder.replace(idx, idx + param.length(), rep);
|
||||||
idx = builder.indexOf(param, idx + rep.length());
|
idx = builder.indexOf(param, idx + rep.length());
|
||||||
} while (idx != -1);
|
} while (idx != -1);
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
Formatting.translate(builder);
|
Formatting.translate(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("StringEquality")
|
@SuppressWarnings("StringEquality")
|
||||||
private static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls, boolean translate) {
|
private static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls, boolean translate) {
|
||||||
if (from < 0 || to < from || to > target.length) {
|
if (from < 0 || to < from || to > target.length) {
|
||||||
throw new IllegalArgumentException("Invalid from-to for array size " + target.length + ": " + from + "-" + to);
|
throw new IllegalArgumentException("Invalid from-to for array size " + target.length + ": " + from + "-" + to);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean change = false;
|
boolean change = false;
|
||||||
for (int i = from; i < to; i++) {
|
for (int i = from; i < to; i++) {
|
||||||
String val = target[i];
|
String val = target[i];
|
||||||
if (val != (val = replParams(val, params, repls, true, translate))) {
|
if (val != (val = replParams(val, params, repls, true, translate))) {
|
||||||
target[i] = val;
|
target[i] = val;
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("StringEquality")
|
@SuppressWarnings("StringEquality")
|
||||||
private static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls, boolean translate) {
|
private static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls, boolean translate) {
|
||||||
if (from < 0 || to < from || to > target.size()) {
|
if (from < 0 || to < from || to > target.size()) {
|
||||||
throw new IllegalArgumentException("Invalid from-to for list size " + target.size() + ": " + from + "-" + to);
|
throw new IllegalArgumentException("Invalid from-to for list size " + target.size() + ": " + from + "-" + to);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean change = false;
|
boolean change = false;
|
||||||
if (target instanceof RandomAccess) {
|
if (target instanceof RandomAccess) {
|
||||||
for (int i = from; i < to; i++) {
|
for (int i = from; i < to; i++) {
|
||||||
String val = target.get(i);
|
String val = target.get(i);
|
||||||
if (val != (val = replParams(val, params, repls, true, translate))) {
|
if (val != (val = replParams(val, params, repls, true, translate))) {
|
||||||
target.set(i, val);
|
target.set(i, val);
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ListIterator<String> itr = target.listIterator(from);
|
ListIterator<String> itr = target.listIterator(from);
|
||||||
for (int n = to - from, i = 0; i < n && itr.hasNext(); i++) {
|
for (int n = to - from, i = 0; i < n && itr.hasNext(); i++) {
|
||||||
String val = itr.next();
|
String val = itr.next();
|
||||||
if (val != (val = replParams(val, params, repls, true, translate))) {
|
if (val != (val = replParams(val, params, repls, true, translate))) {
|
||||||
itr.set(val);
|
itr.set(val);
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String replParams(String target, String[] params, Object[] repls, boolean updateRepls, boolean translate) {
|
private static String replParams(String target, String[] params, Object[] repls, boolean updateRepls, boolean translate) {
|
||||||
int n = params.length;
|
int n = params.length;
|
||||||
if (n != repls.length) {
|
if (n != repls.length) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
String param = null;
|
String param = null;
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
param = params[i];
|
param = params[i];
|
||||||
if (param == null) {
|
if (param == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
idx = target.indexOf(param, 0);
|
idx = target.indexOf(param, 0);
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
return translate ? Formatting.translate(target) : target;
|
return translate ? Formatting.translate(target) : target;
|
||||||
}
|
}
|
||||||
|
|
||||||
String repl = repls[i].toString();
|
String repl = repls[i].toString();
|
||||||
if (updateRepls) {
|
if (updateRepls) {
|
||||||
repls[i] = repl;
|
repls[i] = repl;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder(target);
|
StringBuilder builder = new StringBuilder(target);
|
||||||
do {
|
do {
|
||||||
builder.replace(idx, idx + param.length(), repl);
|
builder.replace(idx, idx + param.length(), repl);
|
||||||
idx = builder.indexOf(param, idx + repl.length());
|
idx = builder.indexOf(param, idx + repl.length());
|
||||||
} while (idx != -1);
|
} while (idx != -1);
|
||||||
|
|
||||||
for (i++; i < n; i++) {
|
for (i++; i < n; i++) {
|
||||||
param = params[i];
|
param = params[i];
|
||||||
if (param == null || (idx = builder.indexOf(param, 0)) == -1) {
|
if (param == null || (idx = builder.indexOf(param, 0)) == -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
repl = repls[i].toString();
|
repl = repls[i].toString();
|
||||||
if (updateRepls) {
|
if (updateRepls) {
|
||||||
repls[i] = repl;
|
repls[i] = repl;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
builder.replace(idx, idx + param.length(), repl);
|
builder.replace(idx, idx + param.length(), repl);
|
||||||
idx = builder.indexOf(param, idx + repl.length());
|
idx = builder.indexOf(param, idx + repl.length());
|
||||||
} while (idx != -1);
|
} while (idx != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
Formatting.translate(builder);
|
Formatting.translate(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,91 +1,91 @@
|
|||||||
package io.dico.dicore;
|
package io.dico.dicore;
|
||||||
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Whitelist extends Predicate {
|
public interface Whitelist extends Predicate {
|
||||||
|
|
||||||
Whitelist EVERYTHING = item -> true;
|
Whitelist EVERYTHING = item -> true;
|
||||||
Whitelist NOTHING = item -> false;
|
Whitelist NOTHING = item -> false;
|
||||||
Whitelist NOT_NULL = Objects::nonNull;
|
Whitelist NOT_NULL = Objects::nonNull;
|
||||||
|
|
||||||
static <T> Predicate<T> everythingAsPredicate() {
|
static <T> Predicate<T> everythingAsPredicate() {
|
||||||
return (Predicate<T>) EVERYTHING;
|
return (Predicate<T>) EVERYTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> Predicate<T> nothingAsPredicate() {
|
static <T> Predicate<T> nothingAsPredicate() {
|
||||||
return (Predicate<T>) NOTHING;
|
return (Predicate<T>) NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> Predicate<T> notNullAsPredicate() {
|
static <T> Predicate<T> notNullAsPredicate() {
|
||||||
return (Predicate<T>) NOT_NULL;
|
return (Predicate<T>) NOT_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Whitelist only(Object item) {
|
static Whitelist only(Object item) {
|
||||||
return item::equals;
|
return item::equals;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Whitelist not(Object item) {
|
static Whitelist not(Object item) {
|
||||||
return o -> !item.equals(o);
|
return o -> !item.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Whitelist only(Object item1, Object item2) {
|
static Whitelist only(Object item1, Object item2) {
|
||||||
return item -> item1.equals(item) || item2.equals(item);
|
return item -> item1.equals(item) || item2.equals(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Whitelist not(Object item1, Object item2) {
|
static Whitelist not(Object item1, Object item2) {
|
||||||
return item -> !(item1.equals(item) || item2.equals(item));
|
return item -> !(item1.equals(item) || item2.equals(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Whitelist only(Object[] objects) {
|
static Whitelist only(Object[] objects) {
|
||||||
return new SetBasedWhitelist(objects, false);
|
return new SetBasedWhitelist(objects, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Whitelist not(Object[] objects) {
|
static Whitelist not(Object[] objects) {
|
||||||
return new SetBasedWhitelist(objects, true);
|
return new SetBasedWhitelist(objects, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Whitelist fromConfig(ConfigurationSection section, Function<String, ?> parser) {
|
static Whitelist fromConfig(ConfigurationSection section, Function<String, ?> parser) {
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
return NOTHING;
|
return NOTHING;
|
||||||
}
|
}
|
||||||
boolean blacklist = section.getBoolean("blacklist", false);
|
boolean blacklist = section.getBoolean("blacklist", false);
|
||||||
Set list = section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toSet());
|
Set list = section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||||
switch (list.size()) {
|
switch (list.size()) {
|
||||||
case 0:
|
case 0:
|
||||||
return blacklist ? EVERYTHING : NOTHING;
|
return blacklist ? EVERYTHING : NOTHING;
|
||||||
case 1: {
|
case 1: {
|
||||||
Iterator iterator = list.iterator();
|
Iterator iterator = list.iterator();
|
||||||
return blacklist ? not(iterator.next()) : only(iterator.next());
|
return blacklist ? not(iterator.next()) : only(iterator.next());
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
Iterator iterator = list.iterator();
|
Iterator iterator = list.iterator();
|
||||||
return blacklist ? not(iterator.next(), iterator.next()) : only(iterator.next(), iterator.next());
|
return blacklist ? not(iterator.next(), iterator.next()) : only(iterator.next(), iterator.next());
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
Object item = list.iterator().next();
|
Object item = list.iterator().next();
|
||||||
if (item instanceof Enum) {
|
if (item instanceof Enum) {
|
||||||
list = EnumSet.copyOf(list);
|
list = EnumSet.copyOf(list);
|
||||||
}
|
}
|
||||||
return new SetBasedWhitelist(list, blacklist);
|
return new SetBasedWhitelist(list, blacklist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyIntoConfig(ConfigurationSection target, Function<Object, String> mapper, boolean blacklist, Object... objects) {
|
static void copyIntoConfig(ConfigurationSection target, Function<Object, String> mapper, boolean blacklist, Object... objects) {
|
||||||
target.set("blacklist", blacklist);
|
target.set("blacklist", blacklist);
|
||||||
target.set("listed", Arrays.stream(objects).map(mapper).unordered().distinct().collect(Collectors.toList()));
|
target.set("listed", Arrays.stream(objects).map(mapper).unordered().distinct().collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default boolean test(Object o) {
|
default boolean test(Object o) {
|
||||||
return isWhitelisted(o);
|
return isWhitelisted(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isWhitelisted(Object o);
|
boolean isWhitelisted(Object o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,46 +1,46 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
import io.dico.dicore.InterfaceChain;
|
import io.dico.dicore.InterfaceChain;
|
||||||
|
|
||||||
public interface ChainedListener<T> extends InterfaceChain<SimpleListener<T>, ChainedListener<T>>, SimpleListener<T> {
|
public interface ChainedListener<T> extends InterfaceChain<SimpleListener<T>, ChainedListener<T>>, SimpleListener<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default ChainedListener<T> getEmptyInstance() {
|
default ChainedListener<T> getEmptyInstance() {
|
||||||
return ChainedListeners.empty();
|
return ChainedListeners.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default ChainedListener<T> withElement(SimpleListener<T> element) {
|
default ChainedListener<T> withElement(SimpleListener<T> element) {
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = getElementCount() + 1;
|
int count = getElementCount() + 1;
|
||||||
return new ChainedListener<T>() {
|
return new ChainedListener<T>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(T event) {
|
public void accept(T event) {
|
||||||
try {
|
try {
|
||||||
ChainedListener.this.accept(event);
|
ChainedListener.this.accept(event);
|
||||||
} finally {
|
} finally {
|
||||||
element.accept(event);
|
element.accept(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChainedListener<T> withoutLastNode() {
|
public ChainedListener<T> withoutLastNode() {
|
||||||
return ChainedListener.this;
|
return ChainedListener.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SimpleListener<T> getDelegateOfLastNode() {
|
public SimpleListener<T> getDelegateOfLastNode() {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getElementCount() {
|
public int getElementCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,55 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
import io.dico.dicore.InterfaceChain;
|
import io.dico.dicore.InterfaceChain;
|
||||||
|
|
||||||
public interface ChainedListenerHandle extends InterfaceChain<ListenerHandle, ChainedListenerHandle>, ListenerHandle {
|
public interface ChainedListenerHandle extends InterfaceChain<ListenerHandle, ChainedListenerHandle>, ListenerHandle {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default ChainedListenerHandle getEmptyInstance() {
|
default ChainedListenerHandle getEmptyInstance() {
|
||||||
return ChainedListenerHandles.empty();
|
return ChainedListenerHandles.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default ChainedListenerHandle withElement(ListenerHandle element) {
|
default ChainedListenerHandle withElement(ListenerHandle element) {
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = getElementCount() + 1;
|
int count = getElementCount() + 1;
|
||||||
return new ChainedListenerHandle() {
|
return new ChainedListenerHandle() {
|
||||||
@Override
|
@Override
|
||||||
public void register() {
|
public void register() {
|
||||||
try {
|
try {
|
||||||
ChainedListenerHandle.this.register();
|
ChainedListenerHandle.this.register();
|
||||||
} finally {
|
} finally {
|
||||||
element.register();
|
element.register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregister() {
|
public void unregister() {
|
||||||
try {
|
try {
|
||||||
ChainedListenerHandle.this.unregister();
|
ChainedListenerHandle.this.unregister();
|
||||||
} finally {
|
} finally {
|
||||||
element.unregister();
|
element.unregister();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChainedListenerHandle withoutLastNode() {
|
public ChainedListenerHandle withoutLastNode() {
|
||||||
return ChainedListenerHandle.this;
|
return ChainedListenerHandle.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenerHandle getDelegateOfLastNode() {
|
public ListenerHandle getDelegateOfLastNode() {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getElementCount() {
|
public int getElementCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +1,63 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
public class ChainedListenerHandles {
|
public class ChainedListenerHandles {
|
||||||
|
|
||||||
private ChainedListenerHandles() {
|
private ChainedListenerHandles() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ChainedListenerHandle empty = new ChainedListenerHandle() {
|
private static final ChainedListenerHandle empty = new ChainedListenerHandle() {
|
||||||
@Override
|
@Override
|
||||||
public void register() {
|
public void register() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregister() {
|
public void unregister() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChainedListenerHandle withElement(ListenerHandle other) {
|
public ChainedListenerHandle withElement(ListenerHandle other) {
|
||||||
return ChainedListenerHandles.singleton(other);
|
return ChainedListenerHandles.singleton(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getElementCount() {
|
public int getElementCount() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenerHandle getDelegateOfLastNode() {
|
public ListenerHandle getDelegateOfLastNode() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ChainedListenerHandle empty() {
|
public static ChainedListenerHandle empty() {
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ChainedListenerHandle singleton(ListenerHandle element) {
|
public static ChainedListenerHandle singleton(ListenerHandle element) {
|
||||||
if (element instanceof ChainedListenerHandle) {
|
if (element instanceof ChainedListenerHandle) {
|
||||||
return (ChainedListenerHandle) element;
|
return (ChainedListenerHandle) element;
|
||||||
}
|
}
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
return new ChainedListenerHandle() {
|
return new ChainedListenerHandle() {
|
||||||
@Override
|
@Override
|
||||||
public void register() {
|
public void register() {
|
||||||
element.register();
|
element.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregister() {
|
public void unregister() {
|
||||||
element.unregister();
|
element.unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenerHandle getDelegateOfLastNode() {
|
public ListenerHandle getDelegateOfLastNode() {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +1,56 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ChainedListeners {
|
public class ChainedListeners {
|
||||||
|
|
||||||
private static final ChainedListener<?> empty = new ChainedListener<Object>() {
|
private static final ChainedListener<?> empty = new ChainedListener<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(Object event) {
|
public void accept(Object event) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChainedListener<Object> withElement(SimpleListener other) {
|
public ChainedListener<Object> withElement(SimpleListener other) {
|
||||||
return ChainedListeners.singleton(other);
|
return ChainedListeners.singleton(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getElementCount() {
|
public int getElementCount() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SimpleListener<Object> getDelegateOfLastNode() {
|
public SimpleListener<Object> getDelegateOfLastNode() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private ChainedListeners() {
|
private ChainedListeners() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ChainedListener<T> empty() {
|
public static <T> ChainedListener<T> empty() {
|
||||||
return (ChainedListener<T>) empty;
|
return (ChainedListener<T>) empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ChainedListener<T> singleton(SimpleListener<T> element) {
|
public static <T> ChainedListener<T> singleton(SimpleListener<T> element) {
|
||||||
if (element instanceof ChainedListener) {
|
if (element instanceof ChainedListener) {
|
||||||
return (ChainedListener<T>) element;
|
return (ChainedListener<T>) element;
|
||||||
}
|
}
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
return new ChainedListener<T>() {
|
return new ChainedListener<T>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(T event) {
|
public void accept(T event) {
|
||||||
element.accept(event);
|
element.accept(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SimpleListener getDelegateOfLastNode() {
|
public SimpleListener getDelegateOfLastNode() {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,91 +1,91 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
import org.bukkit.event.Cancellable;
|
import org.bukkit.event.Cancellable;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public final class HandlerList<T> {
|
public final class HandlerList<T> {
|
||||||
private final List<Listener<T>> source = new ArrayList<>();
|
private final List<Listener<T>> source = new ArrayList<>();
|
||||||
private Listener<T>[] listeners = newArray(0);
|
private Listener<T>[] listeners = newArray(0);
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
source.sort(Comparator.comparingInt(l -> l.getPriority().ordinal()));
|
source.sort(Comparator.comparingInt(l -> l.getPriority().ordinal()));
|
||||||
listeners = source.toArray(newArray(source.size()));
|
listeners = source.toArray(newArray(source.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static <T> Listener<T>[] newArray(int length) {
|
private static <T> Listener<T>[] newArray(int length) {
|
||||||
return new Listener[length];
|
return new Listener[length];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(Listener<T> listener) {
|
public void register(Listener<T> listener) {
|
||||||
if (!source.contains(listener) && source.add(listener)) {
|
if (!source.contains(listener) && source.add(listener)) {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenerHandle getListenerHandle(Listener<T> listener) {
|
public ListenerHandle getListenerHandle(Listener<T> listener) {
|
||||||
return new ListenerHandle() {
|
return new ListenerHandle() {
|
||||||
@Override
|
@Override
|
||||||
public void register() {
|
public void register() {
|
||||||
HandlerList.this.register(listener);
|
HandlerList.this.register(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregister() {
|
public void unregister() {
|
||||||
HandlerList.this.unregister(listener);
|
HandlerList.this.unregister(listener);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(EventPriority priority, Consumer<T> listener) {
|
public void register(EventPriority priority, Consumer<T> listener) {
|
||||||
register(new Listener<T>() {
|
register(new Listener<T>() {
|
||||||
@Override
|
@Override
|
||||||
public EventPriority getPriority() {
|
public EventPriority getPriority() {
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(T event) {
|
public void accept(T event) {
|
||||||
listener.accept(event);
|
listener.accept(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Listener<T>> getRegistrations() {
|
public List<Listener<T>> getRegistrations() {
|
||||||
return Collections.unmodifiableList(source);
|
return Collections.unmodifiableList(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregister(Listener<T> listener) {
|
public void unregister(Listener<T> listener) {
|
||||||
if (source.remove(listener)) {
|
if (source.remove(listener)) {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void callEvent(T event) {
|
public void callEvent(T event) {
|
||||||
if (event instanceof Cancellable) {
|
if (event instanceof Cancellable) {
|
||||||
Cancellable c = (Cancellable) event;
|
Cancellable c = (Cancellable) event;
|
||||||
boolean cancelled = c.isCancelled();
|
boolean cancelled = c.isCancelled();
|
||||||
for (Listener<T> listener : listeners) {
|
for (Listener<T> listener : listeners) {
|
||||||
if (listener.listensToCancelledState(cancelled)) {
|
if (listener.listensToCancelledState(cancelled)) {
|
||||||
//EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
|
//EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
|
||||||
listener.accept(event);
|
listener.accept(event);
|
||||||
cancelled = c.isCancelled();
|
cancelled = c.isCancelled();
|
||||||
} /*else {
|
} /*else {
|
||||||
EnchantsPlugin.getInstance().debug("Listener does not listen to cancelled state of " + cancelled + ": " + listener.getClass().getSimpleName());
|
EnchantsPlugin.getInstance().debug("Listener does not listen to cancelled state of " + cancelled + ": " + listener.getClass().getSimpleName());
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Listener<T> listener : listeners) {
|
for (Listener<T> listener : listeners) {
|
||||||
//EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
|
//EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
|
||||||
listener.accept(event);
|
listener.accept(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
|
|
||||||
public interface Listener<T> {
|
public interface Listener<T> {
|
||||||
|
|
||||||
default EventPriority getPriority() {
|
default EventPriority getPriority() {
|
||||||
return EventPriority.NORMAL;
|
return EventPriority.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean listensToCancelledState(boolean cancelled) {
|
default boolean listensToCancelledState(boolean cancelled) {
|
||||||
return !cancelled;
|
return !cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void accept(T event);
|
void accept(T event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
public interface ListenerHandle {
|
public interface ListenerHandle {
|
||||||
|
|
||||||
void register();
|
void register();
|
||||||
|
|
||||||
void unregister();
|
void unregister();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package io.dico.dicore.event;
|
package io.dico.dicore.event;
|
||||||
|
|
||||||
public interface SimpleListener<T> {
|
public interface SimpleListener<T> {
|
||||||
|
|
||||||
void accept(T event);
|
void accept(T event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user