diff options
author | Dico Karssiens <dico.karssiens@gmail.com> | 2018-07-29 01:03:31 +0100 |
---|---|---|
committer | Dico Karssiens <dico.karssiens@gmail.com> | 2018-07-29 01:03:31 +0100 |
commit | d425a1e977cb03a7b9162e3dcb775cabeff52814 (patch) | |
tree | f0bcc94a0912c8a79fbcb7c30c389542402311b6 | |
parent | 547ffcb0ba8407838e0ec9241406206b38885ad2 (diff) |
Tweaks and fixes
19 files changed, 507 insertions, 206 deletions
diff --git a/build.gradle.kts b/build.gradle.kts index d358fcc..a1a6e4f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,25 +1,23 @@ -@file:Suppress("UNUSED_VARIABLE") +@file:Suppress("RemoveRedundantBackticks", "IMPLICIT_CAST_TO_ANY", "UNUSED_VARIABLE") import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import org.jetbrains.kotlin.gradle.dsl.Coroutines.ENABLE -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.io.PrintWriter -val firstImport = false -val stdout = PrintWriter(File("$rootDir/gradle-output.txt")) - -buildscript { - dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.51") - } -} +val stdout = PrintWriter("gradle-output.txt") group = "io.dico" version = "0.1" -inline fun <reified T : Plugin<out Project>> Project.apply() = - (this as PluginAware).apply<T>() +plugins { + java + kotlin("jvm") version "1.2.51" + id("com.github.johnrengelman.plugin-shadow") version "2.0.3" +} + +kotlin.experimental.coroutines = ENABLE allprojects { apply<JavaPlugin>() @@ -28,76 +26,72 @@ allprojects { mavenCentral() maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots") maven("https://hub.spigotmc.org/nexus/content/repositories/sonatype-nexus-snapshots") + maven("https://dl.bintray.com/kotlin/exposed") } + dependencies { val spigotVersion = "1.13-R0.1-SNAPSHOT" - compile("org.bukkit:bukkit:$spigotVersion") { isTransitive = false } - compile("org.spigotmc:spigot-api:$spigotVersion") { isTransitive = false } + c.provided("org.bukkit:bukkit:$spigotVersion") { isTransitive = false } + c.provided("org.spigotmc:spigot-api:$spigotVersion") { isTransitive = false } - compile("net.sf.trove4j:trove4j:3.0.3") + c.provided("net.sf.trove4j:trove4j:3.0.3") testCompile("junit:junit:4.12") } + + afterEvaluate { + tasks.filter { it is Jar }.forEach { it.group = "artifacts" } + } } project(":dicore3:dicore3-command") { apply<KotlinPlatformJvmPlugin>() - kotlin.experimental.coroutines = ENABLE dependencies { - // why the fuck does it need reflect explicitly? - compile("org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4") - compile(kotlin("reflect", version = "1.2.50")) - compile(kotlin("stdlib-jdk8", version = "1.2.51")) + c.kotlinStd(kotlin("stdlib-jdk8")) + c.kotlinStd(kotlin("reflect")) + c.kotlinStd(kotlinx("coroutines-core:0.23.4")) + compile(project(":dicore3:dicore3-core")) compile("com.thoughtworks.paranamer:paranamer:2.8") + c.provided("com.google.guava:guava:25.1-jre") } } -plugins { - kotlin("jvm") version "1.2.51" - id("com.github.johnrengelman.plugin-shadow") version "2.0.3" -} - -kotlin.experimental.coroutines = ENABLE - -repositories { - maven("https://dl.bintray.com/kotlin/exposed") -} - dependencies { compile(project(":dicore3:dicore3-core")) compile(project(":dicore3:dicore3-command")) - compile(kotlin("stdlib-jdk8")) - compile("org.jetbrains.exposed:exposed:0.10.3") - compile("org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4") + c.kotlinStd(kotlin("stdlib-jdk8")) + c.kotlinStd(kotlinx("coroutines-core:0.23.4")) + c.kotlinStd("org.jetbrains.exposed:exposed:0.10.3") + compile("com.zaxxer:HikariCP:3.2.0") - compile("com.h2database:h2:1.4.197") val jacksonVersion = "2.9.6" compile("com.fasterxml.jackson.core:jackson-core:$jacksonVersion") compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") - compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion") compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion") - //compile("org.yaml:snakeyaml:1.19") - - compile("org.slf4j:slf4j-api:1.7.25") - compile("ch.qos.logback:logback-classic:1.2.3") + compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion") { isTransitive = false } } tasks { + removeIf { it is ShadowJar } + + val compileKotlin by getting(KotlinCompile::class) { + kotlinOptions { + javaParameters = true + } + } + val serverDir = "$rootDir/debug" val jar by getting(Jar::class) + val kotlinStdlibJar by creating(Jar::class) { destinationDir = file("$serverDir/lib") archiveName = "kotlin-stdlib.jar" - packageDependencies("kotlin-stdlib-jdk8") - } - - val debugEnvironment by creating(Exec::class) { - + fromFiles(c.kotlinStd) } val releaseJar by creating(ShadowJar::class) { @@ -105,103 +99,46 @@ tasks { baseName = "parcels2-release" with(jar) + fromFiles(c.compile) - packageArtifacts( - "jackson-core", - "jackson-databind", - "jackson-module-kotlin", - "jackson-annotations", - "jackson-dataformat-yaml", - "snakeyaml", - - "slf4j-api", - "logback-core", - "logback-classic", - - //"h2", - "HikariCP", - "kotlinx-coroutines-core", - "kotlinx-coroutines-core-common", - "atomicfu-common", - "exposed", - - "dicore3-core", - "dicore3-command", - "paranamer", - - "trove4j", - "joda-time", - - "annotations", - "kotlin-stdlib-common", - "kotlin-stdlib", - "kotlin-stdlib-jdk7", - "kotlin-stdlib-jdk8", - "kotlin-reflect" - ) - - relocate("org.yaml.snakeyaml", "io.dico.parcels2.util.snakeyaml") - - manifest.attributes["Class-Path"] = "lib/kotlin-stdlib.jar" - dependsOn(kotlinStdlibJar) - } + /* + Shadow Jar is retarded so it also relocates packages not included in the releaseJar (such as the bukkit api) -} + relocate("", "io.dico.parcels2.lib.") { + exclude("*yml") + exclude("*xml") + exclude("META-INF/*") + exclude("io/dico/*") + } + */*/*/ -allprojects { - tasks.filter { it is Jar }.forEach { it.group = "artifacts" } + // jackson-dataformat-yaml requires an older version of snakeyaml (1.19 or earlier) + // snakeyaml made a breaking change in 1.20 and didn't really warn anyone afaik + // it was like me changing the command library because I know I'm the only one using it + // spigot ships a later version in the root, so we must relocate ours + relocate("org.yaml.snakeyaml.", "io.dico.parcels2.lib.org.yaml.snakeyaml.") + + manifest.attributes["Class-Path"] = "../lib/kotlin-stdlib.jar" + dependsOn(kotlinStdlibJar) + } } stdout.flush() stdout.close() -fun Jar.packageDependencies(vararg names: String) { - if (!firstImport) { - from(*project.configurations.compile.resolvedConfiguration.firstLevelModuleDependencies - .filter { it.moduleName in names } - .flatMap { it.allModuleArtifacts } - .map { it.file } - .map(::zipTree) - .toTypedArray() - ) - } -} +inline fun <reified T : Plugin<out Project>> Project.apply() = + (this as PluginAware).apply<T>() -fun Jar.packageDependency(name: String, configure: ModuleDependency.() -> Unit) { - if (!firstImport) { - val configuration = project.configurations.compile.copyRecursive() +fun kotlinx(module: String, version: String? = null): Any = + "org.jetbrains.kotlinx:kotlinx-$module${version?.let { ":$version" } ?: ""}" - configuration.dependencies.removeIf { - if (it is ModuleDependency && it.name == name) { - it.configure() - false - } else true - } +val Project.c get() = configurations - from(*configuration.resolvedConfiguration.resolvedArtifacts - .map { it.file } - .map(::zipTree) - .toTypedArray()) - } -} +val ConfigurationContainer.`provided`: Configuration + get() = findByName("provided") ?: create("provided").let { compileClasspath.extendsFrom(it) } -@Suppress("IMPLICIT_CAST_TO_ANY") -fun Jar.packageArtifacts(vararg names: String) { - if (!firstImport) { - from(*project.configurations.compile.resolvedConfiguration.firstLevelModuleDependencies - .flatMap { dep -> dep.allModuleArtifacts.map { dep to it } } - .filter { pair -> - val (dep, art) = pair - val id = art.moduleVersion.id - (id.name in names).also { - val artName = art.moduleVersion.id.let {"${it.group}:${it.name}:${it.version}"} - val depName = dep.let { "${it.moduleGroup}:${it.moduleName}:${it.moduleVersion}" } - val name = "$artName \n from $depName" - stdout.println("${if (it) "Including" else "Not including"} artifact $name") - } - } - .map { pair -> pair.second.file } - .map { if (it.isDirectory()) it else zipTree(it) } - .toTypedArray()) - } -} +val ConfigurationContainer.`kotlinStd`: Configuration + get() = findByName("kotlinStd") ?: create("kotlinStd").let { compileClasspath.extendsFrom(it) } + +fun Jar.fromFiles(files: Iterable<File>) = + afterEvaluate { from(*files.map { if (it.isDirectory) it else zipTree(it) }.toTypedArray()) } diff --git a/dicore3/command/build.gradle.kts b/dicore3/command/build.gradle.kts index b4e64bd..6bc75ec 100644 --- a/dicore3/command/build.gradle.kts +++ b/dicore3/command/build.gradle.kts @@ -1,6 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.Coroutines -import org.jetbrains.kotlin.js.translate.context.Namer.kotlin group = "io.dico.dicore3" -//name = "dicore3-command" version = "1.2.5-mc-1.13" diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/Command.java b/dicore3/command/src/main/java/io/dico/dicore/command/Command.java index 0ba04b1..b66b5f5 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/Command.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/Command.java @@ -27,27 +27,27 @@ public abstract class Command { } public <TType> Command addParameter(String name, String description, ParameterType<TType, Void> type) { - return addParameter(Parameter.newParameter(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) { - return addParameter(Parameter.newParameter(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) { - return addParameter(Parameter.newParameter('-' + 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) { - return addParameter(Parameter.newParameter('-' + 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) { - return addParameter(Parameter.newParameter('-' + 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) { - return addParameter(Parameter.newParameter('-' + name, description, type, paramInfo, true, permission)); + return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, permission)); } public Command requiredParameters(int requiredParameters) { diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java b/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java index 59eebf9..0ffc960 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java @@ -153,14 +153,7 @@ public final class CommandBuilder { * @return this */ public CommandBuilder generatePredefinedCommands(String... commands) { - for (String value : commands) { - Consumer<ICommandAddress> subscriber = PredefinedCommand.getPredefinedCommandGenerator(value); - if (subscriber == null) { - System.out.println("[Command Warning] generated command '" + value + "' could not be found"); - } else { - subscriber.accept(cur); - } - } + ReflectiveRegistration.generateCommands(cur, commands); return this; } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/Parameter.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/Parameter.java index ca66068..9ce1119 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/Parameter.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/Parameter.java @@ -21,6 +21,8 @@ public class Parameter<TResult, TParamInfo> { private final String description; private final ParameterType<TResult, TParamInfo> parameterType; private final TParamInfo paramInfo; + private final boolean isPrimitive; + private final boolean flag; private final String flagPermission; @@ -29,6 +31,10 @@ public class Parameter<TResult, TParamInfo> { } public Parameter(String name, String description, ParameterType<TResult, TParamInfo> parameterType, TParamInfo paramInfo, boolean flag, String flagPermission) { + this(name, description, parameterType, paramInfo, false, flag, flagPermission); + } + + public Parameter(String name, String description, ParameterType<TResult, TParamInfo> parameterType, TParamInfo paramInfo, boolean isPrimitive, boolean flag, String flagPermission) { this.name = Objects.requireNonNull(name); this.description = description == null ? "" : description; this.parameterType = flag ? parameterType.asFlagParameter() : parameterType; @@ -38,6 +44,7 @@ public class Parameter<TResult, TParamInfo> { } */ this.paramInfo = paramInfo; + this.isPrimitive = isPrimitive; this.flag = flag; this.flagPermission = flagPermission; @@ -49,17 +56,7 @@ public class Parameter<TResult, TParamInfo> { } } - public static <TResult> Parameter<TResult, ?> newParameter(String name, String description, ParameterType<TResult, ?> type) { - return new Parameter<>(name, description, type, null); - } - public static <TResult, TParamInfo> Parameter<TResult, TParamInfo> newParameter(String name, String description, ParameterType<TResult, TParamInfo> type, TParamInfo info) { - return new Parameter<>(name, description, type, info); - } - - public static <TResult, TParamInfo> Parameter<TResult, TParamInfo> newParameter(String name, String description, ParameterType<TResult, TParamInfo> parameterType, TParamInfo paramInfo, boolean flag, String flagPermission) { - return new Parameter<>(name, description, parameterType, paramInfo, flag, flagPermission); - } public TResult parse(ExecutionContext context, ArgumentBuffer buffer) throws CommandException { if (getFlagPermission() != null) { @@ -96,6 +93,10 @@ public class Parameter<TResult, TParamInfo> { return paramInfo; } + public boolean isPrimitive() { + return isPrimitive; + } + public boolean isFlag() { return flag; } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/NumberParameterType.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/NumberParameterType.java index ed53cb0..4aac122 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/NumberParameterType.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/NumberParameterType.java @@ -49,7 +49,8 @@ public abstract class NumberParameterType<T extends Number> extends ParameterTyp @Override public T getDefaultValue(Parameter<T, Range.Memory> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException { Range.Memory memory = (Range.Memory) parameter.getParamInfo(); - return select(memory != null ? memory.defaultValue() : 0); + if (memory != null) return select(memory.defaultValue()); + return !parameter.isPrimitive() ? null : select(0); } } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterKey.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterKey.java index 67f86d4..ee265e6 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterKey.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterKey.java @@ -1,5 +1,9 @@ package io.dico.dicore.command.parameter.type; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Maps; + import java.lang.annotation.Annotation; import java.util.Objects; @@ -7,16 +11,28 @@ import java.util.Objects; * More appropriate name: ParameterTypeKey */ public class ParameterKey { + private final Class<?> returnType; private final Class<? extends Annotation> annotationClass; + // just a marker, not used in equals or hashCode(). + // returnType is never primitive + private boolean isPrimitive; + public ParameterKey(Class<?> returnType) { this(returnType, null); } public ParameterKey(Class<?> returnType, Class<? extends Annotation> annotationClass) { + boolean isPrimitive = returnType.isPrimitive(); + + if (isPrimitive) { + returnType = primitivesToWrappers.get(returnType); + } + this.returnType = Objects.requireNonNull(returnType); this.annotationClass = annotationClass; + this.isPrimitive = isPrimitive; } public Class<?> getReturnType() { @@ -43,4 +59,45 @@ public class ParameterKey { return result; } + private static Class<?> getPrimitiveWrapperClass(Class<?> primitiveClass) { + if (!primitiveClass.isPrimitive()) return null; + switch (primitiveClass.getName()) { + case "boolean": + return Boolean.class; + case "char": + return Character.class; + case "byte": + return Byte.class; + case "short": + return Short.class; + case "int": + return Integer.class; + case "float": + return Float.class; + case "long": + return Long.class; + case "double": + return Double.class; + case "void": + return Void.class; + default: + throw new InternalError(); + } + } + + private static final BiMap<Class<?>, Class<?>> primitivesToWrappers; + static { + HashBiMap<Class<?>, Class<?>> tmp = HashBiMap.create(); + tmp.put(Boolean.TYPE, Boolean.class); + tmp.put(Character.TYPE, Character.class); + tmp.put(Byte.TYPE, Byte.class); + tmp.put(Short.TYPE, Short.class); + tmp.put(Integer.TYPE, Integer.class); + tmp.put(Float.TYPE, Float.class); + tmp.put(Long.TYPE, Long.class); + tmp.put(Double.TYPE, Double.class); + tmp.put(Void.TYPE, Void.class); + primitivesToWrappers = Maps.unmodifiableBiMap(tmp); + } + } diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterTypes.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterTypes.java index 98b7b77..678bbc6 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterTypes.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterTypes.java @@ -42,9 +42,6 @@ public class ParameterTypes { public static final NumberParameterType<Float> FLOAT; public static final ParameterType<Player, Void> PLAYER; public static final ParameterType<OfflinePlayer, Void> OFFLINE_PLAYER; - //public static final ParameterType<Boolean, Void> PRESENCE; - //public static final NumberParameterType<BigDecimal> BIG_DECIMAL; - //public static final NumberParameterType<BigInteger> BIG_INTEGER; private ParameterTypes() { @@ -59,7 +56,7 @@ public class ParameterTypes { @Override public String getDefaultValue(Parameter<String, Void> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException { - return ""; + return null; } }); @@ -81,7 +78,7 @@ public class ParameterTypes { @Override public Boolean getDefaultValue(Parameter<Boolean, Void> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException { - return false; + return !parameter.isPrimitive() ? null : false; } @Override diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommandExtended.java b/dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommandExtended.java new file mode 100644 index 0000000..49f5e72 --- /dev/null +++ b/dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommandExtended.java @@ -0,0 +1,7 @@ +package io.dico.dicore.command.predef; + +public class HelpCommandExtended { + + // TODO + +} diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java index 0003c1f..669f440 100644 --- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java +++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java @@ -332,7 +332,7 @@ public class ReflectiveRegistration { ParameterType<Object, Object> parameterType = selector.selectAny(type, typeAnnotation == null ? null : typeAnnotation.getClass()); if (parameterType == null) { - throw new CommandParseException("IParameter type not found for parameter " + name + " in method " + method.toGenericString()); + throw new CommandParseException("IParameter type not found for parameter " + name + " in method " + method.toString()); } Object parameterInfo; @@ -348,7 +348,8 @@ public class ReflectiveRegistration { try { //noinspection unchecked - return Parameter.newParameter(name, descString, parameterType, parameterInfo, name.startsWith("-"), flag == null ? null : flag.permission()); + String flagPermission = flag == null ? null : flag.permission(); + return new Parameter<>(name, descString, parameterType, parameterInfo, type.isPrimitive(), name.startsWith("-"), flagPermission); } catch (Exception ex) { throw new CommandParseException("Invalid parameter", ex); } diff --git a/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt b/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt index bc48a26..9d23ee6 100644 --- a/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt +++ b/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt @@ -66,4 +66,11 @@ private fun Deferred<Any?>.getResult(): String? { throw ex } return ReflectiveCommand.getResult(getCompleted(), null) +} + +fun getNonPrimitiveClass(clazz: Class<*>): Class<*>? { + return if (clazz.isPrimitive) + clazz.kotlin.javaObjectType + else + null }
\ No newline at end of file diff --git a/dicore3/core/build.gradle.kts b/dicore3/core/build.gradle.kts index 3fa41d2..76a7382 100644 --- a/dicore3/core/build.gradle.kts +++ b/dicore3/core/build.gradle.kts @@ -2,15 +2,3 @@ group = "io.dico.dicore3" version = "1.2.5" -plugins { - java -} - -repositories() { - mavenCentral() -} - -dependencies { - compile(files("../../res/spigot-1.13-pre7.jar")) - -}
\ No newline at end of file diff --git a/old-build.gradle.kts b/old-build.gradle.kts new file mode 100644 index 0000000..fa79c4d --- /dev/null +++ b/old-build.gradle.kts @@ -0,0 +1,206 @@ +@file:Suppress("UNUSED_VARIABLE") + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.jetbrains.kotlin.gradle.dsl.Coroutines.ENABLE +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformJvmPlugin +import java.io.PrintWriter + +val firstImport = false +val stdout = PrintWriter(File("$rootDir/gradle-output.txt")) + +buildscript { + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.51") + } +} + +group = "io.dico" +version = "0.1" + +inline fun <reified T : Plugin<out Project>> Project.apply() = + (this as PluginAware).apply<T>() + +allprojects { + apply<JavaPlugin>() + + repositories { + mavenCentral() + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots") + maven("https://hub.spigotmc.org/nexus/content/repositories/sonatype-nexus-snapshots") + } + dependencies { + val spigotVersion = "1.13-R0.1-SNAPSHOT" + compile("org.bukkit:bukkit:$spigotVersion") { isTransitive = false } + compile("org.spigotmc:spigot-api:$spigotVersion") { isTransitive = false } + + compile("net.sf.trove4j:trove4j:3.0.3") + testCompile("junit:junit:4.12") + } +} + +project(":dicore3:dicore3-command") { + apply<KotlinPlatformJvmPlugin>() + + kotlin.experimental.coroutines = ENABLE + + dependencies { + compile("org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4") + compile(kotlin("reflect", version = "1.2.50")) + compile(kotlin("stdlib-jdk8", version = "1.2.51")) + compile(project(":dicore3:dicore3-core")) + compile("com.thoughtworks.paranamer:paranamer:2.8") + } +} + + +plugins { + kotlin("jvm") version "1.2.51" + id("com.github.johnrengelman.plugin-shadow") version "2.0.3" +} + +kotlin.experimental.coroutines = ENABLE + +repositories { + maven("https://dl.bintray.com/kotlin/exposed") +} + +dependencies { + compile(project(":dicore3:dicore3-core")) + compile(project(":dicore3:dicore3-command")) + compile(kotlin("stdlib-jdk8")) + + compile("org.jetbrains.exposed:exposed:0.10.3") + compile("org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4") + compile("com.zaxxer:HikariCP:3.2.0") + compile("com.h2database:h2:1.4.197") + + val jacksonVersion = "2.9.6" + compile("com.fasterxml.jackson.core:jackson-core:$jacksonVersion") + compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") + compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion") + compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion") + //compile("org.yaml:snakeyaml:1.19") + + compile("org.slf4j:slf4j-api:1.7.25") + compile("ch.qos.logback:logback-classic:1.2.3") +} + +tasks { + val serverDir = "$rootDir/debug" + val jar by getting(Jar::class) + val kotlinStdlibJar by creating(Jar::class) { + destinationDir = file("$serverDir/lib") + archiveName = "kotlin-stdlib.jar" + packageDependencies("kotlin-stdlib-jdk8") + } + + val debugEnvironment by creating(Exec::class) { + + } + + val releaseJar by creating(ShadowJar::class) { + destinationDir = file("$serverDir/plugins") + baseName = "parcels2-release" + + with(jar) + + packageArtifacts( + "jackson-core", + "jackson-databind", + "jackson-module-kotlin", + "jackson-annotations", + "jackson-dataformat-yaml", + "snakeyaml", + + "slf4j-api", + "logback-core", + "logback-classic", + + //"h2", + "HikariCP", + "kotlinx-coroutines-core", + "kotlinx-coroutines-core-common", + "atomicfu-common", + "exposed", + + "dicore3-core", + "dicore3-command", + "paranamer", + + "trove4j", + "joda-time", + + "annotations", + "kotlin-stdlib-common", + "kotlin-stdlib", + "kotlin-stdlib-jdk7", + "kotlin-stdlib-jdk8", + "kotlin-reflect" + ) + + relocate("org.yaml.snakeyaml", "io.dico.parcels2.util.snakeyaml") + + manifest.attributes["Class-Path"] = "lib/kotlin-stdlib.jar" + dependsOn(kotlinStdlibJar) + } + +} + +allprojects { + tasks.filter { it is Jar }.forEach { it.group = "artifacts" } +} + +stdout.flush() +stdout.close() + +fun Jar.packageDependencies(vararg names: String) { + if (!firstImport) { + from(*project.configurations.compile.resolvedConfiguration.firstLevelModuleDependencies + .filter { it.moduleName in names } + .flatMap { it.allModuleArtifacts } + .map { it.file } + .map(::zipTree) + .toTypedArray() + ) + } +} + +fun Jar.packageDependency(name: String, configure: ModuleDependency.() -> Unit) { + if (!firstImport) { + val configuration = project.configurations.compile.copyRecursive() + + configuration.dependencies.removeIf { + if (it is ModuleDependency && it.name == name) { + it.configure() + false + } else true + } + + from(*configuration.resolvedConfiguration.resolvedArtifacts + .map { it.file } + .map(::zipTree) + .toTypedArray()) + } +} + +@Suppress("IMPLICIT_CAST_TO_ANY") +fun Jar.packageArtifacts(vararg names: String) { + if (!firstImport) { + from(*project.configurations.compile.resolvedConfiguration.firstLevelModuleDependencies + .flatMap { dep -> dep.allModuleArtifacts.map { dep to it } } + .filter { pair -> + val (dep, art) = pair + val id = art.moduleVersion.id + (id.name in names).also { + val artName = art.moduleVersion.id.let {"${it.group}:${it.name}:${it.version}"} + val depName = dep.let { "${it.moduleGroup}:${it.moduleName}:${it.moduleVersion}" } + val name = "$artName \n from $depName" + stdout.println("${if (it) "Including" else "Not including"} artifact $name") + } + } + .map { pair -> pair.second.file } + .map { if (it.isDirectory()) it else zipTree(it) } + .toTypedArray()) + } +} diff --git a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt index a2e8155..d4287af 100644 --- a/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt +++ b/src/main/kotlin/io/dico/parcels2/ParcelWorld.kt @@ -15,6 +15,7 @@ import org.bukkit.block.Block import org.bukkit.entity.Entity import org.bukkit.entity.Player import java.util.* +import kotlin.coroutines.experimental.buildIterator import kotlin.coroutines.experimental.buildSequence import kotlin.reflect.jvm.javaMethod import kotlin.reflect.jvm.kotlinFunction @@ -117,7 +118,9 @@ class ParcelWorld constructor(val name: String, val options: WorldOptions, val generator: ParcelGenerator, val storage: Storage) : ParcelProvider by generator, ParcelContainer { - val world: World by lazy { Bukkit.getWorld(name) ?: throw NullPointerException("World $name does not appear to be loaded") } + val world: World by lazy { + Bukkit.getWorld(name) ?: throw NullPointerException("World $name does not appear to be loaded") + } val container: ParcelContainer = DefaultParcelContainer(this, storage) override fun parcelByID(x: Int, z: Int): Parcel? { @@ -189,12 +192,24 @@ class DefaultParcelContainer(private val world: ParcelWorld, } override fun parcelByID(x: Int, z: Int): Parcel? { - return parcels.getOrNull(x)?.getOrNull(z) + return parcels.getOrNull(x + world.options.axisLimit)?.getOrNull(z + world.options.axisLimit) } override fun nextEmptyParcel(): Parcel? { - return parcels[0][0] - TODO() + return walkInCircle().find { it.owner == null } + } + + private fun walkInCircle(): Iterable<Parcel> = Iterable { + buildIterator { + val center = world.options.axisLimit + for (radius in 0..center) { + var x = center - radius; var z = center - radius + repeat(radius * 2) { yield(parcels[x++][z]) } + repeat(radius * 2) { yield(parcels[x][z++]) } + repeat(radius * 2) { yield(parcels[x--][z]) } + repeat(radius * 2) { yield(parcels[x][z--]) } + } + } } fun allParcels(): Sequence<Parcel> = buildSequence { diff --git a/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt b/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt index 15fbde6..6bd214b 100644 --- a/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt +++ b/src/main/kotlin/io/dico/parcels2/WorldGenerator.kt @@ -194,7 +194,7 @@ class DefaultParcelGenerator(val worlds: Worlds, val name: String, private val o val signBlock = world.getBlockAt(b.x - 2, o.floorHeight + 1, b.z - 1) val skullBlock = world.getBlockAt(b.x - 1, o.floorHeight + 2, b.z - 1) - val owner = parcel.data?.owner + val owner = parcel.owner if (owner == null) { wallBlock.blockData = o.wallType signBlock.type = Material.AIR diff --git a/src/main/kotlin/io/dico/parcels2/command/CommandsParcelOptions.kt b/src/main/kotlin/io/dico/parcels2/command/CommandsParcelOptions.kt index 7f900d5..c77686e 100644 --- a/src/main/kotlin/io/dico/parcels2/command/CommandsParcelOptions.kt +++ b/src/main/kotlin/io/dico/parcels2/command/CommandsParcelOptions.kt @@ -25,6 +25,7 @@ class CommandsParcelOptions(plugin: ParcelsPlugin) : AbstractParcelCommands(plug @Desc("Sets whether players who are not allowed to", "build here can interact with inventories", shortVersion = "allows editing inventories") + @RequireParameters(0) fun ParcelScope.cmdInventory(player: Player, enabled: Boolean?): Any? { return runOptionCommand(player, Parcel::allowInteractInventory, enabled, "interaction with inventories") } diff --git a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt index 284c6d4..2ba16e2 100644 --- a/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt +++ b/src/main/kotlin/io/dico/parcels2/command/ParcelCommandBuilder.kt @@ -1,9 +1,13 @@ package io.dico.parcels2.command import io.dico.dicore.command.CommandBuilder +import io.dico.dicore.command.ICommandAddress import io.dico.dicore.command.ICommandDispatcher +import io.dico.dicore.command.predef.PredefinedCommand +import io.dico.dicore.command.registration.reflect.ReflectiveRegistration import io.dico.parcels2.ParcelsPlugin import io.dico.parcels2.logger +import java.util.* @Suppress("UsePropertyAccessSyntax") fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher { @@ -18,7 +22,7 @@ fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher { .registerCommands(CommandsAddedStatus(plugin)) .group("option") - .apply { CommandsParcelOptions.setGroupDescription(this) } + //.apply { CommandsParcelOptions.setGroupDescription(this) } .registerCommands(CommandsParcelOptions(plugin)) .parent() @@ -29,15 +33,34 @@ fun getParcelCommands(plugin: ParcelsPlugin): ICommandDispatcher { .putDebugCommands(plugin) .parent() + .generateHelpAndSyntaxCommands() .getDispatcher() //@formatter:on } private fun CommandBuilder.putDebugCommands(plugin: ParcelsPlugin): CommandBuilder { - if (!logger.isDebugEnabled) return this + //if (!logger.isDebugEnabled) return this //@formatter:off return group("debug", "d") .registerCommands(CommandsDebug(plugin)) .parent() //@formatter:on } + +private fun CommandBuilder.generateHelpAndSyntaxCommands(): CommandBuilder { + generateCommands(dispatcher as ICommandAddress, "help", "syntax") + return this +} + +private fun generateCommands(address: ICommandAddress, vararg names: String) { + val addresses: Queue<ICommandAddress> = LinkedList() + addresses.offer(address) + + while (addresses.isNotEmpty()) { + val cur = addresses.poll() + addresses.addAll(cur.children.values.distinct()) + if (cur.hasCommand()) { + ReflectiveRegistration.generateCommands(cur, names) + } + } +} diff --git a/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt b/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt index a78cab8..fc0591c 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt @@ -17,42 +17,39 @@ object WorldsT : Table("worlds") { val id = integer("world_id").autoIncrement().primaryKey() val name = varchar("name", 50) val uid = binary("uid", 16) - .also { uniqueIndex("index_uid", it) } + val index_uid = uniqueIndexR("index_uid", uid) } object ParcelsT : Table("parcels") { val id = integer("parcel_id").autoIncrement().primaryKey() val px = integer("px") val pz = integer("pz") - val world_id = integer("id") - .also { uniqueIndex("index_location", it, px, pz) } - .references(WorldsT.id) + val world_id = integer("world_id").references(WorldsT.id) val owner_uuid = binary("owner_uuid", 16).nullable() val owner_name = varchar("owner_name", 16).nullable() val claim_time = datetime("claim_time").nullable() + val index_location = uniqueIndexR("index_location", world_id, px, pz) } object AddedLocalT : Table("parcels_added_local") { - val parcel_id = integer("parcel_id") - .references(ParcelsT.id, ReferenceOption.CASCADE) + val parcel_id = integer("parcel_id").references(ParcelsT.id, ReferenceOption.CASCADE) val player_uuid = binary("player_uuid", 16) - .also { uniqueIndex("index_pair", parcel_id, it) } val allowed_flag = bool("allowed_flag") + val index_pair = uniqueIndexR("index_pair", parcel_id, player_uuid) } object AddedGlobalT : Table("parcels_added_global") { val owner_uuid = binary("owner_uuid", 16) val player_uuid = binary("player_uuid", 16) - .also { uniqueIndex("index_pair", owner_uuid, it) } val allowed_flag = bool("allowed_flag") + val index_pair = uniqueIndexR("index_pair", owner_uuid, player_uuid) } object ParcelOptionsT : Table("parcel_options") { - val parcel_id = integer("parcel_id") - .also { uniqueIndex("index_parcel_id", it) } - .references(ParcelsT.id, ReferenceOption.CASCADE) + val parcel_id = integer("parcel_id").references(ParcelsT.id, ReferenceOption.CASCADE) val interact_inventory = bool("interact_inventory").default(false) val interact_inputs = bool("interact_inputs").default(false) + val index_parcel_id = uniqueIndexR("index_parcel_id", parcel_id) } private class ExposedDatabaseException(message: String? = null) : Exception(message) @@ -163,7 +160,6 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing rowToParcelData(row) } - // TODO order by some new column override suspend fun getOwnedParcels(user: ParcelOwner): List<SerializableParcel> = transaction { val where: SqlExpressionBuilder.() -> Op<Boolean> @@ -175,7 +171,8 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing where = { ParcelsT.owner_name eq name } } - ParcelsT.select(where).orderBy(ParcelsT.claim_time, isAsc = true) + ParcelsT.select(where) + .orderBy(ParcelsT.claim_time, isAsc = true) .mapNotNull(::rowToSerializableParcel) .toList() } @@ -243,7 +240,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing } val id = getOrInitParcelId(parcelFor) - AddedLocalT.insertOrUpdate(AddedLocalT.allowed_flag) { + AddedLocalT.upsert(AddedLocalT.parcel_id) { it[AddedLocalT.parcel_id] = id it[AddedLocalT.player_uuid] = binaryUuid } @@ -251,7 +248,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing override suspend fun setParcelAllowsInteractInventory(parcel: Parcel, value: Boolean): Unit = transaction { val id = getOrInitParcelId(parcel) - ParcelOptionsT.insertOrUpdate(ParcelOptionsT.interact_inventory) { + ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) { it[ParcelOptionsT.parcel_id] = id it[ParcelOptionsT.interact_inventory] = value } @@ -259,7 +256,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing override suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean): Unit = transaction { val id = getOrInitParcelId(parcel) - ParcelOptionsT.insertOrUpdate(ParcelOptionsT.interact_inputs) { + ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) { it[ParcelOptionsT.parcel_id] = id it[ParcelOptionsT.interact_inputs] = value } diff --git a/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt b/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt index d4aee11..bb6133d 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt @@ -1,9 +1,8 @@ package io.dico.parcels2.storage -import org.jetbrains.exposed.sql.Column -import org.jetbrains.exposed.sql.Table -import org.jetbrains.exposed.sql.Transaction +import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.statements.InsertStatement +import org.jetbrains.exposed.sql.statements.UpdateStatement import org.jetbrains.exposed.sql.transactions.TransactionManager /* @@ -29,8 +28,82 @@ class InsertOrUpdate<Key : Any>( } +class UpsertStatement<Key : Any>(table: Table, conflictColumn: Column<*>? = null, conflictIndex: Index? = null) + : InsertStatement<Key>(table, false) { + val indexName: String + val indexColumns: List<Column<*>> + init { + if (conflictIndex != null) { + indexName = conflictIndex.indexName + indexColumns = conflictIndex.columns + } else if (conflictColumn != null) { + indexName = conflictColumn.name + indexColumns = listOf(conflictColumn) + } else { + throw IllegalArgumentException() + } + } + + override fun prepareSQL(transaction: Transaction): String { + val insertSQL = super.prepareSQL(transaction) + val args = arguments!!.first() + val map = mutableMapOf<Column<Any?>, Any?>().apply { args.forEach { put(it.first.castUnchecked(), it.second) } } + + val updateSQL = updateBody(table, UpdateStatement(table, null, combineAsConjunctions(indexColumns.castUnchecked(), map))) { + map.forEach { col, value -> + if (col !in columns) { + it[col] = value + } + } + }.prepareSQL(transaction) + + val builder = StringBuilder().apply { + append(insertSQL) + append(" ON CONFLICT(") + append(indexName) + append(") DO UPDATE ") + append(updateSQL) + } + + return builder.toString().also { println(it) } + } + + private companion object { + + inline fun <T : Table> updateBody(table: T, updateStatement: UpdateStatement, + body: T.(UpdateStatement) -> Unit): UpdateStatement { + table.body(updateStatement) + return updateStatement + } + @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") + inline fun <T> Any.castUnchecked() = this as T + private val absent = Any() // marker object + fun combineAsConjunctions(columns: Iterable<Column<Any?>>, map: Map<Column<Any?>, Any?>): Op<Boolean>? { + return with(SqlExpressionBuilder) { + columns.fold<Column<Any?>, Op<Boolean>?>(null) { op, col -> + val arg = map.getOrDefault(col, absent) + if (arg === absent) return@fold op + op?.let { it and (col eq arg) } ?: col eq arg + } + } + } + } +} + +inline fun <T : Table> T.upsert(conflictColumn: Column<*>? = null, conflictIndex: Index? = null, body: T.(UpsertStatement<Number>) -> Unit) = + UpsertStatement<Number>(this, conflictColumn, conflictIndex).apply { + body(this) + execute(TransactionManager.current()) + } + +fun Table.indexR(customIndexName:String? = null, isUnique: Boolean = false, vararg columns: Column<*>): Index { + val index = Index(columns.toList(), isUnique, customIndexName) + indices.add(index) + return index +} +fun Table.uniqueIndexR(customIndexName:String? = null, vararg columns: Column<*>): Index = indexR(customIndexName, true, *columns) |