Compare commits
32 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
be620a1247 | |
|
|
b7d5a97452 | |
|
|
ce8fe9c4bf | |
|
|
8596bcae2c | |
|
|
9dfb9d1876 | |
|
|
9c88efae69 | |
|
|
43fc609549 | |
|
|
07512c45d9 | |
|
|
2a93a9e3d5 | |
|
|
3360b596d5 | |
|
|
8633b8e40d | |
|
|
49751521f8 | |
|
|
329f659f41 | |
|
|
b53a0d68d2 | |
|
|
ec7038c311 | |
|
|
4d2bbc8054 | |
|
|
578b820dfe | |
|
|
943f2679f9 | |
|
|
aefa846d3c | |
|
|
2340a7d726 | |
|
|
651feab7e7 | |
|
|
47fa2ddc0a | |
|
|
a3445b4482 | |
|
|
aeff5b4ad4 | |
|
|
3dcbff0684 | |
|
|
438eff19da | |
|
|
170c7e26bf | |
|
|
56b8eaa9a7 | |
|
|
66f4ba911f | |
|
|
bba80af506 | |
|
|
becb3f3578 | |
|
|
4e8d42f4b9 |
25
build.gradle
25
build.gradle
|
|
@ -3,10 +3,13 @@ plugins {
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
id 'java-gradle-plugin'
|
id 'java-gradle-plugin'
|
||||||
id 'com.gradle.plugin-publish' version '0.12.0'
|
id 'com.gradle.plugin-publish' version '0.12.0'
|
||||||
|
id 'org.jetbrains.kotlin.jvm' version '1.5.10'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
group 'io.izzel.taboolib'
|
group 'io.izzel.taboolib'
|
||||||
version '1.5'
|
version '1.27'
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
embed
|
embed
|
||||||
|
|
@ -21,8 +24,10 @@ dependencies {
|
||||||
compile 'org.codehaus.groovy:groovy:2.5.13'
|
compile 'org.codehaus.groovy:groovy:2.5.13'
|
||||||
compile gradleApi()
|
compile gradleApi()
|
||||||
compile localGroovy()
|
compile localGroovy()
|
||||||
embed 'org.ow2.asm:asm:8.0.1'
|
embed 'org.ow2.asm:asm:9.2'
|
||||||
embed 'org.ow2.asm:asm-commons:8.0.1'
|
embed 'org.ow2.asm:asm-commons:9.2'
|
||||||
|
embed 'com.google.code.gson:gson:2.8.7'
|
||||||
|
embed 'org.jetbrains.kotlin:kotlin-stdlib'
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
|
@ -52,4 +57,16 @@ publishing {
|
||||||
url = file("/Users/sky/Desktop/repo")
|
url = file("/Users/sky/Desktop/repo")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compileKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileTestKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
|
distributionUrl=https://skymc.oss-cn-shanghai.aliyuncs.com/files/gradle-6.5-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.objectweb.asm.AnnotationVisitor
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
import org.objectweb.asm.Type
|
||||||
|
|
||||||
|
class IsolatedAnnotationVisitor extends AnnotationVisitor {
|
||||||
|
|
||||||
|
String name
|
||||||
|
Project project
|
||||||
|
TabooLibClassVisitor parent
|
||||||
|
|
||||||
|
IsolatedAnnotationVisitor(AnnotationVisitor annotationVisitor, project, name, parent) {
|
||||||
|
super(Opcodes.ASM7, annotationVisitor)
|
||||||
|
this.name = name
|
||||||
|
this.project = project
|
||||||
|
this.parent = parent
|
||||||
|
this.parent.isolated[name] = new ArrayList<>()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitArray(String name) {
|
||||||
|
return new IsolatedExcludeAnnotationVisitor(super.visitArray(name), this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class IsolatedExcludeAnnotationVisitor extends AnnotationVisitor {
|
||||||
|
|
||||||
|
IsolatedAnnotationVisitor parent
|
||||||
|
|
||||||
|
IsolatedExcludeAnnotationVisitor(AnnotationVisitor annotationVisitor, parent) {
|
||||||
|
super(Opcodes.ASM7, annotationVisitor)
|
||||||
|
this.parent = parent
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visit(String name, Object value) {
|
||||||
|
parent.parent.isolated[parent.name] += (value as Type).className
|
||||||
|
super.visit(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.objectweb.asm.AnnotationVisitor
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
|
class KotlinAnnotationVisitor extends AnnotationVisitor {
|
||||||
|
|
||||||
|
Project project
|
||||||
|
|
||||||
|
KotlinAnnotationVisitor(AnnotationVisitor annotationVisitor, project) {
|
||||||
|
super(Opcodes.ASM7, annotationVisitor)
|
||||||
|
this.project = project
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visit(String name, Object value) {
|
||||||
|
if (value instanceof String) {
|
||||||
|
super.visit(name, value
|
||||||
|
.replace("@kotlin_version@", getKotlinVersion())
|
||||||
|
.replace("@kotlin_version_escape@", getKotlinVersionEscape())
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
super.visit(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitEnum(String name, String descriptor, String value) {
|
||||||
|
super.visitEnum(name, descriptor, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitAnnotation(String name, String descriptor) {
|
||||||
|
return new KotlinAnnotationVisitor(super.visitAnnotation(name, descriptor), project)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitArray(String name) {
|
||||||
|
return new KotlinAnnotationVisitor(super.visitArray(name), project)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitEnd() {
|
||||||
|
super.visitEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
String getKotlinVersion() {
|
||||||
|
return project.plugins.findPlugin("org.jetbrains.kotlin.jvm").kotlinPluginVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
String getKotlinVersionEscape() {
|
||||||
|
return getKotlinVersion().replaceAll("[._-]", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.objectweb.asm.AnnotationVisitor
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
|
class KotlinMetaAnnotationVisitor extends AnnotationVisitor {
|
||||||
|
|
||||||
|
Project project
|
||||||
|
|
||||||
|
KotlinMetaAnnotationVisitor(AnnotationVisitor annotationVisitor, project) {
|
||||||
|
super(Opcodes.ASM7, annotationVisitor)
|
||||||
|
this.project = project
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visit(String name, Object value) {
|
||||||
|
if (value instanceof String) {
|
||||||
|
super.visit(name, value.replace("taboolib", "${project.group.replace('.', '/')}/taboolib"))
|
||||||
|
} else {
|
||||||
|
super.visit(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitArray(String name) {
|
||||||
|
return new KotlinMetaAnnotationVisitor(super.visitArray(name), project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
|
import groovy.transform.EqualsAndHashCode
|
||||||
|
import groovy.transform.TupleConstructor
|
||||||
|
|
||||||
|
@TupleConstructor
|
||||||
|
@EqualsAndHashCode
|
||||||
|
class MethodVisit {
|
||||||
|
|
||||||
|
String owner
|
||||||
|
String name
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString() {
|
||||||
|
return owner.substring(owner.lastIndexOf("/") + 1) + "." + name + "()"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,11 +4,11 @@ import org.gradle.api.Project
|
||||||
import org.objectweb.asm.AnnotationVisitor
|
import org.objectweb.asm.AnnotationVisitor
|
||||||
import org.objectweb.asm.Opcodes
|
import org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
class SpongeAnnotationVisitor extends AnnotationVisitor {
|
class PluginAnnotationVisitor extends AnnotationVisitor {
|
||||||
|
|
||||||
Project project
|
Project project
|
||||||
|
|
||||||
SpongeAnnotationVisitor(AnnotationVisitor annotationVisitor, project) {
|
PluginAnnotationVisitor(AnnotationVisitor annotationVisitor, project) {
|
||||||
super(Opcodes.ASM7, annotationVisitor)
|
super(Opcodes.ASM7, annotationVisitor)
|
||||||
this.project = project
|
this.project = project
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package io.izzel.taboolib.gradle
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
import groovy.transform.ToString
|
import groovy.transform.ToString
|
||||||
|
import io.izzel.taboolib.gradle.description.Platforms
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.tasks.Input
|
import org.gradle.api.tasks.Input
|
||||||
|
|
@ -16,6 +17,8 @@ import java.nio.file.StandardCopyOption
|
||||||
import java.util.jar.JarEntry
|
import java.util.jar.JarEntry
|
||||||
import java.util.jar.JarFile
|
import java.util.jar.JarFile
|
||||||
import java.util.jar.JarOutputStream
|
import java.util.jar.JarOutputStream
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
import java.util.zip.ZipException
|
||||||
|
|
||||||
@ToString
|
@ToString
|
||||||
class RelocateJar extends DefaultTask {
|
class RelocateJar extends DefaultTask {
|
||||||
|
|
@ -33,39 +36,201 @@ class RelocateJar extends DefaultTask {
|
||||||
@Input
|
@Input
|
||||||
Project project
|
Project project
|
||||||
|
|
||||||
|
@Input
|
||||||
|
TabooLibExtension tabooExt
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
def relocate() {
|
def relocate() {
|
||||||
|
// 缓存
|
||||||
|
def optimize = []
|
||||||
|
def isolated = new TreeMap<String, List<String>>()
|
||||||
|
def methodVisits = new TreeMap<String, Set<MethodVisit>>()
|
||||||
|
|
||||||
|
// 配置
|
||||||
def mapping = relocations.collectEntries { [(it.key.replace('.', '/')), it.value.replace('.', '/')] }
|
def mapping = relocations.collectEntries { [(it.key.replace('.', '/')), it.value.replace('.', '/')] }
|
||||||
def remapper = new RelocateRemapper(relocations, mapping as Map<String, String>)
|
def remapper = new RelocateRemapper(relocations, mapping as Map<String, String>)
|
||||||
|
|
||||||
|
// 文件
|
||||||
def index = inJar.name.lastIndexOf('.')
|
def index = inJar.name.lastIndexOf('.')
|
||||||
def name = inJar.name.substring(0, index) + (classifier == null ? "" : "-" + classifier) + inJar.name.substring(index)
|
def name = inJar.name.substring(0, index) + (classifier == null ? "" : "-" + classifier) + inJar.name.substring(index)
|
||||||
def outJar = new File(inJar.getParentFile(), name)
|
def outJar = new File(inJar.getParentFile(), name)
|
||||||
def tmpOut = File.createTempFile(name, ".jar")
|
def tempOut1 = File.createTempFile(name, ".jar")
|
||||||
new JarOutputStream(new FileOutputStream(tmpOut)).withCloseable { out ->
|
|
||||||
project.logger.info(outJar.getAbsolutePath())
|
// 第一次工作
|
||||||
|
new JarOutputStream(new FileOutputStream(tempOut1)).withCloseable { out ->
|
||||||
int n
|
int n
|
||||||
def buf = new byte[32768]
|
def buf = new byte[32768]
|
||||||
new JarFile(inJar).withCloseable {jarFile ->
|
new JarFile(inJar).withCloseable { jarFile ->
|
||||||
for (def jarEntry : jarFile.entries()) {
|
jarFile.entries().each { JarEntry jarEntry ->
|
||||||
|
def path = jarEntry.name
|
||||||
|
// 忽略用户定义的文件
|
||||||
|
if (tabooExt.exclude.stream().any { String e -> path.startsWith(e) }) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 忽略模块文件
|
||||||
|
if (path.endsWith(".kotlin_module")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 忽略优化指示文件
|
||||||
|
if (path.startsWith("META-INF/tf") && path.endsWith(".json")) {
|
||||||
|
optimize.add(Bridge.newOptimizeFileReader(project, jarFile.getInputStream(jarEntry)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 忽略 Kotlin 依赖
|
||||||
|
def options = tabooExt.options
|
||||||
|
if (path == "taboolib/common/env/KotlinEnv.class" && options.contains("skip-kotlin")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 忽略依赖加载部分代码
|
||||||
|
if (path.startsWith("taboolib/common/env") && options.contains("skip-env")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 忽略 common 模块打包的第三方库
|
||||||
|
if (path.startsWith("taboolib/library/asm") || path.startsWith("taboolib/library/jarrelocator")) {
|
||||||
|
if (options.contains("skip-env") || options.contains("skip-env-relocate")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
jarFile.getInputStream(jarEntry).withCloseable {
|
jarFile.getInputStream(jarEntry).withCloseable {
|
||||||
if (jarEntry.name.endsWith(".class")) {
|
if (path.endsWith(".class")) {
|
||||||
project.logger.info("Relocating " + jarEntry.name)
|
|
||||||
def reader = new ClassReader(it)
|
def reader = new ClassReader(it)
|
||||||
def writer = new ClassWriter(0)
|
def writer = new ClassWriter(0)
|
||||||
def visitor = new TabooLibClassVisitor(writer, project)
|
def visitor = new TabooLibClassVisitor(writer, project)
|
||||||
reader.accept(new ClassRemapper(visitor, remapper), 0)
|
def rem = new ClassRemapper(visitor, remapper)
|
||||||
out.putNextEntry(new JarEntry(remapper.map(jarEntry.name)))
|
remapper.remapper = rem
|
||||||
|
reader.accept(rem, 0)
|
||||||
|
// 提取孤立类
|
||||||
|
isolated.putAll(visitor.isolated)
|
||||||
|
// 提取方法访问记录
|
||||||
|
methodVisits.put(relocate(project, jarEntry.name), visitor.methodVisits)
|
||||||
|
// 写回文件
|
||||||
|
// 拦截报错防止文件名称重复导致编译终止
|
||||||
|
try {
|
||||||
|
out.putNextEntry(new JarEntry(remapper.map(path)))
|
||||||
|
} catch (ZipException zipException) {
|
||||||
|
println(zipException)
|
||||||
|
return true
|
||||||
|
}
|
||||||
out.write(writer.toByteArray())
|
out.write(writer.toByteArray())
|
||||||
} else {
|
} else {
|
||||||
out.putNextEntry(new JarEntry(remapper.map(jarEntry.name)))
|
try {
|
||||||
|
out.putNextEntry(new JarEntry(remapper.map(path)))
|
||||||
|
} catch (ZipException ex) {
|
||||||
|
println(ex)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
while ((n = it.read(buf)) != -1) {
|
||||||
|
out.write(buf, 0, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据整理
|
||||||
|
// 类 -> 谁正在使用
|
||||||
|
def use = new TreeMap<String, Set<String>>()
|
||||||
|
remapper.use.each {
|
||||||
|
it.value.each { e ->
|
||||||
|
def key = relocate(project, getNameWithOutExtension(e))
|
||||||
|
def value = relocate(project, getNameWithOutExtension(it.key))
|
||||||
|
use.computeIfAbsent(key) { new HashSet() }.add(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def visits = methodVisits[methodVisits.keySet().first()]
|
||||||
|
if (visits != null) {
|
||||||
|
visits.each {
|
||||||
|
println(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def transfer = new TreeMap()
|
||||||
|
isolated.each {
|
||||||
|
transfer[relocate(project, it.key)] = it.value.stream().map { i -> relocate(project, i) }.collect(Collectors.toList())
|
||||||
|
}
|
||||||
|
isolated = transfer
|
||||||
|
|
||||||
|
// 第二次工作
|
||||||
|
def tempOut2 = File.createTempFile(name, ".jar")
|
||||||
|
new JarOutputStream(new FileOutputStream(tempOut2)).withCloseable { out ->
|
||||||
|
int n
|
||||||
|
def buf = new byte[32768]
|
||||||
|
def del = new HashSet()
|
||||||
|
def exclude = new HashSet()
|
||||||
|
new JarFile(tempOut1).withCloseable { jarFile ->
|
||||||
|
jarFile.entries().each { JarEntry jarEntry ->
|
||||||
|
if (optimize.any { it.exclude(jarEntry.name, use) }) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jarFile.getInputStream(jarEntry).withCloseable {
|
||||||
|
if (jarEntry.name.endsWith(".class")) {
|
||||||
|
def nameWithOutExtension = getNameWithOutExtension(jarEntry.name)
|
||||||
|
if (use.containsKey(nameWithOutExtension.toString()) && !exclude.contains(nameWithOutExtension)) {
|
||||||
|
exclude.add(nameWithOutExtension)
|
||||||
|
if (isIsolated(use, use[nameWithOutExtension], isolated, nameWithOutExtension)) {
|
||||||
|
del.add(nameWithOutExtension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!del.contains(getNameWithOutExtension(jarEntry.name))) {
|
||||||
|
out.putNextEntry(new JarEntry(jarEntry.name))
|
||||||
while ((n = it.read(buf)) != -1) {
|
while ((n = it.read(buf)) != -1) {
|
||||||
out.write(buf, 0, n)
|
out.write(buf, 0, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Platforms.values().each {
|
||||||
|
if (tabooExt.modules.contains(it.module)) {
|
||||||
|
out.putNextEntry(new JarEntry(it.file))
|
||||||
|
out.write(it.builder.build(tabooExt.des, project))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Files.copy(tmpOut.toPath(), outJar.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
Files.copy(tempOut2.toPath(), outJar.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getNameWithOutExtension(name) {
|
||||||
|
if (name.contains('$')) {
|
||||||
|
return name.substring(0, name.indexOf('$')).replace('.', '/')
|
||||||
|
} else if (name.contains('.')) {
|
||||||
|
return name.substring(0, name.lastIndexOf('.')).replace('.', '/')
|
||||||
|
} else {
|
||||||
|
return name.replace('.', '/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String relocate(Project project, String name) {
|
||||||
|
if (name.startsWith("taboolib")) {
|
||||||
|
return project.group.toString().replace('.', '/') + '/' + name.replace('.', '/')
|
||||||
|
} else {
|
||||||
|
return name.replace('.', '/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isIsolated(
|
||||||
|
Map<String, Set<String>> use,
|
||||||
|
Set<String> refer,
|
||||||
|
Map<String, List<String>> isolated,
|
||||||
|
String name,
|
||||||
|
String exclude = null
|
||||||
|
) {
|
||||||
|
if (isolated.containsKey(name)) {
|
||||||
|
return refer.size() <= 1 || refer.stream()
|
||||||
|
.filter { it != exclude }
|
||||||
|
.allMatch {
|
||||||
|
name == it || isolated[name].contains(it) || isIsolated(use, use[it], isolated, it, name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RelocateJar{}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package io.izzel.taboolib.gradle
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
import groovy.transform.Canonical
|
import groovy.transform.Canonical
|
||||||
|
import org.objectweb.asm.commons.ClassRemapper
|
||||||
import org.objectweb.asm.commons.Remapper
|
import org.objectweb.asm.commons.Remapper
|
||||||
|
|
||||||
@Canonical
|
@Canonical
|
||||||
|
|
@ -8,6 +9,8 @@ class RelocateRemapper extends Remapper {
|
||||||
|
|
||||||
Map<String, String> dot
|
Map<String, String> dot
|
||||||
Map<String, String> slash
|
Map<String, String> slash
|
||||||
|
Map<String, Set<String>> use = new TreeMap()
|
||||||
|
ClassRemapper remapper
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Object mapValue(Object value) {
|
Object mapValue(Object value) {
|
||||||
|
|
@ -20,8 +23,15 @@ class RelocateRemapper extends Remapper {
|
||||||
return super.mapValue(value)
|
return super.mapValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings('GroovyAccessibility')
|
||||||
@Override
|
@Override
|
||||||
String map(String internalName) {
|
String map(String internalName) {
|
||||||
|
if (remapper != null) {
|
||||||
|
use.computeIfAbsent(remapper.className) { new HashSet() }.add(internalName)
|
||||||
|
}
|
||||||
|
if (internalName.startsWith('kotlin/Metadata')) {
|
||||||
|
return internalName
|
||||||
|
}
|
||||||
def match = slash.find { internalName.startsWith(it.key) }
|
def match = slash.find { internalName.startsWith(it.key) }
|
||||||
if (match) {
|
if (match) {
|
||||||
return match.value + internalName.substring(match.key.length())
|
return match.value + internalName.substring(match.key.length())
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,60 @@ package io.izzel.taboolib.gradle
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.objectweb.asm.AnnotationVisitor
|
import org.objectweb.asm.AnnotationVisitor
|
||||||
import org.objectweb.asm.ClassVisitor
|
import org.objectweb.asm.ClassVisitor
|
||||||
|
import org.objectweb.asm.MethodVisitor
|
||||||
import org.objectweb.asm.Opcodes
|
import org.objectweb.asm.Opcodes
|
||||||
|
|
||||||
class TabooLibClassVisitor extends ClassVisitor {
|
class TabooLibClassVisitor extends ClassVisitor {
|
||||||
|
|
||||||
|
String name
|
||||||
|
|
||||||
Project project
|
Project project
|
||||||
|
|
||||||
|
Map<String, List<String>> isolated = new HashMap()
|
||||||
|
|
||||||
|
Set<MethodVisit> methodVisits = new HashSet<>()
|
||||||
|
|
||||||
|
List<String> annotations = [
|
||||||
|
"Lorg/spongepowered/api/plugin/Plugin;",
|
||||||
|
"Lorg/spongepowered/plugin/jvm/Plugin;",
|
||||||
|
"Lcom/velocitypowered/api/plugin/Plugin;"
|
||||||
|
]
|
||||||
|
|
||||||
TabooLibClassVisitor(ClassVisitor classVisitor, Project project) {
|
TabooLibClassVisitor(ClassVisitor classVisitor, Project project) {
|
||||||
super(Opcodes.ASM7, classVisitor);
|
super(Opcodes.ASM7, classVisitor);
|
||||||
this.project = project
|
this.project = project
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||||
|
this.name = name
|
||||||
|
super.visit(version, access, name, signature, superName, interfaces)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||||
|
return new TabooLibMethodVisitor(super.visitMethod(access, name, descriptor, signature, exceptions), this)
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||||
if (descriptor == "Lorg/spongepowered/api/plugin/Plugin;") {
|
if (descriptor == "Lkotlin/Metadata;") {
|
||||||
return new SpongeAnnotationVisitor(super.visitAnnotation(descriptor, visible), project)
|
return new KotlinMetaAnnotationVisitor(super.visitAnnotation(descriptor, visible), project)
|
||||||
|
} else if (descriptor == "L${project.group.replace('.', '/')}/taboolib/common/Isolated;") {
|
||||||
|
return new IsolatedAnnotationVisitor(super.visitAnnotation(descriptor, visible), project, name, this)
|
||||||
|
} else if (descriptor == "L${project.group.replace('.', '/')}/taboolib/common/env/RuntimeDependency;") {
|
||||||
|
return new KotlinAnnotationVisitor(super.visitAnnotation(descriptor, visible), project)
|
||||||
|
} else if (descriptor == "L${project.group.replace('.', '/')}/taboolib/common/env/RuntimeDependencies;") {
|
||||||
|
return new KotlinAnnotationVisitor(super.visitAnnotation(descriptor, visible), project)
|
||||||
|
} else if (descriptor in annotations) {
|
||||||
|
return new PluginAnnotationVisitor(super.visitAnnotation(descriptor, visible), project)
|
||||||
} else {
|
} else {
|
||||||
return super.visitAnnotation(descriptor, visible)
|
return super.visitAnnotation(descriptor, visible)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitEnd() {
|
||||||
|
super.visitEnd()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package io.izzel.taboolib.gradle
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
import groovy.transform.Canonical
|
import groovy.transform.Canonical
|
||||||
|
import io.izzel.taboolib.gradle.description.Description
|
||||||
|
import org.gradle.api.Action
|
||||||
|
|
||||||
@Canonical
|
@Canonical
|
||||||
class TabooLibExtension {
|
class TabooLibExtension {
|
||||||
|
|
@ -9,15 +11,33 @@ class TabooLibExtension {
|
||||||
|
|
||||||
String classifier = "all"
|
String classifier = "all"
|
||||||
|
|
||||||
List<String> modules = new ArrayList<>();
|
List<String> modules = []
|
||||||
|
|
||||||
|
List<String> exclude = []
|
||||||
|
|
||||||
|
Description des = new Description()
|
||||||
|
|
||||||
Map<String, String> relocation = new LinkedHashMap<>()
|
Map<String, String> relocation = new LinkedHashMap<>()
|
||||||
|
|
||||||
|
List<String> options = []
|
||||||
|
|
||||||
def install(String... name) {
|
def install(String... name) {
|
||||||
name.each { modules += it }
|
name.each { modules += it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def options(String... opt) {
|
||||||
|
opt.each { options += it }
|
||||||
|
}
|
||||||
|
|
||||||
|
def exclude(String match) {
|
||||||
|
exclude += match
|
||||||
|
}
|
||||||
|
|
||||||
def relocate(String pre, String post) {
|
def relocate(String pre, String post) {
|
||||||
relocation[pre] = post
|
relocation[pre] = post
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def description(Action<? super Description> action) {
|
||||||
|
action.execute(des)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
|
|
||||||
|
import groovy.transform.EqualsAndHashCode
|
||||||
|
import groovy.transform.TupleConstructor
|
||||||
|
import org.objectweb.asm.AnnotationVisitor
|
||||||
|
import org.objectweb.asm.Attribute
|
||||||
|
import org.objectweb.asm.Handle
|
||||||
|
import org.objectweb.asm.Label
|
||||||
|
import org.objectweb.asm.MethodVisitor
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
import org.objectweb.asm.TypePath
|
||||||
|
|
||||||
|
class TabooLibMethodVisitor extends MethodVisitor {
|
||||||
|
|
||||||
|
TabooLibClassVisitor classVisitor
|
||||||
|
|
||||||
|
TabooLibMethodVisitor(MethodVisitor methodVisitor, TabooLibClassVisitor classVisitor) {
|
||||||
|
super(Opcodes.ASM7, methodVisitor)
|
||||||
|
this.classVisitor = classVisitor
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitParameter(String name, int access) {
|
||||||
|
super.visitParameter(name, access)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitAnnotationDefault() {
|
||||||
|
return super.visitAnnotationDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||||
|
return super.visitAnnotation(descriptor, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
|
||||||
|
return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitAnnotableParameterCount(int parameterCount, boolean visible) {
|
||||||
|
super.visitAnnotableParameterCount(parameterCount, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) {
|
||||||
|
return super.visitParameterAnnotation(parameter, descriptor, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitAttribute(Attribute attribute) {
|
||||||
|
super.visitAttribute(attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitCode() {
|
||||||
|
super.visitCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) {
|
||||||
|
super.visitFrame(type, numLocal, local, numStack, stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitInsn(int opcode) {
|
||||||
|
super.visitInsn(opcode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitIntInsn(int opcode, int operand) {
|
||||||
|
super.visitIntInsn(opcode, operand)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitVarInsn(int opcode, int i) {
|
||||||
|
super.visitVarInsn(opcode, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitTypeInsn(int opcode, String type) {
|
||||||
|
super.visitTypeInsn(opcode, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
|
||||||
|
super.visitFieldInsn(opcode, owner, name, descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitMethodInsn(int opcode, String owner, String name, String descriptor) {
|
||||||
|
super.visitMethodInsn(opcode, owner, name, descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
|
||||||
|
classVisitor.methodVisits.add(new MethodVisit(owner, name))
|
||||||
|
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
|
||||||
|
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitJumpInsn(int opcode, Label label) {
|
||||||
|
super.visitJumpInsn(opcode, label)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitLabel(Label label) {
|
||||||
|
super.visitLabel(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitLdcInsn(Object value) {
|
||||||
|
super.visitLdcInsn(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitIincInsn(int i, int increment) {
|
||||||
|
super.visitIincInsn(i, increment)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
|
||||||
|
super.visitTableSwitchInsn(min, max, dflt, labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
|
||||||
|
super.visitLookupSwitchInsn(dflt, keys, labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitMultiANewArrayInsn(String descriptor, int numDimensions) {
|
||||||
|
super.visitMultiANewArrayInsn(descriptor, numDimensions)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
|
||||||
|
return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
|
||||||
|
super.visitTryCatchBlock(start, end, handler, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
|
||||||
|
return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
|
||||||
|
super.visitLocalVariable(name, descriptor, signature, start, end, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) {
|
||||||
|
return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitLineNumber(int line, Label start) {
|
||||||
|
super.visitLineNumber(line, start)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitMaxs(int maxStack, int maxLocals) {
|
||||||
|
super.visitMaxs(maxStack, maxLocals)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void visitEnd() {
|
||||||
|
super.visitEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,6 @@ class TabooLibPlugin implements Plugin<Project> {
|
||||||
def tabooExt = project.extensions.create('taboolib', TabooLibExtension)
|
def tabooExt = project.extensions.create('taboolib', TabooLibExtension)
|
||||||
def taboo = project.configurations.maybeCreate('taboo')
|
def taboo = project.configurations.maybeCreate('taboo')
|
||||||
def tabooTask = project.tasks.create('tabooRelocateJar', RelocateJar)
|
def tabooTask = project.tasks.create('tabooRelocateJar', RelocateJar)
|
||||||
|
|
||||||
project.afterEvaluate {
|
project.afterEvaluate {
|
||||||
project.configurations.compileClasspath.extendsFrom(taboo)
|
project.configurations.compileClasspath.extendsFrom(taboo)
|
||||||
// subprojects
|
// subprojects
|
||||||
|
|
@ -23,13 +22,18 @@ class TabooLibPlugin implements Plugin<Project> {
|
||||||
project.tasks.jar.configure { Jar task ->
|
project.tasks.jar.configure { Jar task ->
|
||||||
task.from(taboo.collect { it.isDirectory() ? it : project.zipTree(it) })
|
task.from(taboo.collect { it.isDirectory() ? it : project.zipTree(it) })
|
||||||
}
|
}
|
||||||
|
def kv = project.plugins.findPlugin("org.jetbrains.kotlin.jvm").kotlinPluginVersion.replaceAll("[._-]", "")
|
||||||
def jarTask = project.tasks.jar as Jar
|
def jarTask = project.tasks.jar as Jar
|
||||||
tabooTask.configure { RelocateJar task ->
|
tabooTask.configure { RelocateJar task ->
|
||||||
|
task.tabooExt = tabooExt
|
||||||
task.project = project
|
task.project = project
|
||||||
task.inJar = task.inJar ?: jarTask.archivePath
|
task.inJar = task.inJar ?: jarTask.archivePath
|
||||||
task.relocations = tabooExt.relocation
|
task.relocations = tabooExt.relocation
|
||||||
task.classifier = tabooExt.classifier
|
task.classifier = tabooExt.classifier
|
||||||
task.relocations['taboolib'] = task.relocations['taboolib'] ?: project.group.toString() + '.taboolib'
|
task.relocations['taboolib'] = project.group.toString() + '.taboolib'
|
||||||
|
if (!tabooExt.options.contains("skip-kotlin") && !tabooExt.options.contains("skip-kotlin-relocate")) {
|
||||||
|
task.relocations['kotlin.'] = 'kotlin' + kv + '.'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonElement
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
abstract class Builder {
|
||||||
|
|
||||||
|
abstract byte[] build(Description description, Project project)
|
||||||
|
|
||||||
|
static List<String> startBukkitFile() {
|
||||||
|
def str = []
|
||||||
|
str += ''
|
||||||
|
str += ''
|
||||||
|
str += '# Powered by TabooLib 6.0 #'
|
||||||
|
str += ''
|
||||||
|
str += ''
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
static def writeLine(body) {
|
||||||
|
body.add("")
|
||||||
|
}
|
||||||
|
|
||||||
|
static def write(List<String> body, data, key) {
|
||||||
|
if (data != null) {
|
||||||
|
body.add("$key: $data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static def write(JsonObject body, data, key) {
|
||||||
|
if (data != null) {
|
||||||
|
body.addProperty("$key", "$data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static def writeList(List<String> body, data, key) {
|
||||||
|
if (data instanceof List<String>) {
|
||||||
|
if (data.size() > 0) {
|
||||||
|
body.add("$key:")
|
||||||
|
for (i in data) {
|
||||||
|
body.add(" - '${i}'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (data != null) {
|
||||||
|
body.add("$key:")
|
||||||
|
body.add(" - '${data}'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static def writeList(JsonObject body, data, key) {
|
||||||
|
def arr = new JsonArray()
|
||||||
|
if (data instanceof List<String>) {
|
||||||
|
if (data.size() > 0) {
|
||||||
|
data.each { arr.add(it) }
|
||||||
|
body.add(key, arr)
|
||||||
|
}
|
||||||
|
} else if (data != null) {
|
||||||
|
arr.add(data.toString())
|
||||||
|
body.add(key, arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] bytes(List<String> body) {
|
||||||
|
return body.join('\n').getBytes(StandardCharsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] bytes(JsonElement body) {
|
||||||
|
return new GsonBuilder().setPrettyPrinting().create().toJson(body).getBytes(StandardCharsets.UTF_8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class BuilderBukkit extends Builder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
byte[] build(Description description, Project project) {
|
||||||
|
def body = startBukkitFile()
|
||||||
|
body += "name: ${project.name}"
|
||||||
|
body += "main: ${project.group}.taboolib.platform.BukkitPlugin"
|
||||||
|
body += "version: ${project.version}"
|
||||||
|
write(body, description.lin.links['homepage'], 'website')
|
||||||
|
writeLine(body)
|
||||||
|
// authors
|
||||||
|
def con = description.con.contributors.collect { it.name }
|
||||||
|
writeList(body, con, 'authors')
|
||||||
|
writeLine(body)
|
||||||
|
// dependency
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('bukkit') }
|
||||||
|
.findAll { it.forceDepend() }
|
||||||
|
.collect { it.name }, 'depend')
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('bukkit') }
|
||||||
|
.findAll { it.optional }
|
||||||
|
.collect { it.name }, 'softdepend')
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('bukkit') }
|
||||||
|
.findAll { it.loadbefore }
|
||||||
|
.collect { it.name }, 'loadbefore')
|
||||||
|
writeLine(body)
|
||||||
|
// custom nodes
|
||||||
|
description.bukkitNodes.each {
|
||||||
|
if (it.value instanceof List) {
|
||||||
|
writeList(body, it.value, it.key)
|
||||||
|
} else {
|
||||||
|
write(body, it.value, it.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes(body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class BuilderBungee extends Builder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
byte[] build(Description description, Project project) {
|
||||||
|
def body = startBukkitFile()
|
||||||
|
body += "name: ${project.name}"
|
||||||
|
body += "main: ${project.group}.taboolib.platform.BungeePlugin"
|
||||||
|
body += "version: ${project.version}"
|
||||||
|
write(body, description.lin.links['homepage'], 'website')
|
||||||
|
writeLine(body)
|
||||||
|
// authors
|
||||||
|
def con = description.con.contributors.collect { it.name }.join(', ')
|
||||||
|
write(body, con, 'author')
|
||||||
|
writeLine(body)
|
||||||
|
// dependency
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('bungee') }
|
||||||
|
.findAll { it.forceDepend() }
|
||||||
|
.collect { it.name }, 'depends')
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('bungee') }
|
||||||
|
.findAll { it.optional }
|
||||||
|
.collect { it.name }, 'softDepends')
|
||||||
|
writeLine(body)
|
||||||
|
// custom nodes
|
||||||
|
description.bungeeNodes.each {
|
||||||
|
if (it.value instanceof List) {
|
||||||
|
writeList(body, it.value, it.key)
|
||||||
|
} else {
|
||||||
|
write(body, it.value, it.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes(body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class BuilderNukkit extends Builder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
byte[] build(Description description, Project project) {
|
||||||
|
def body = startBukkitFile()
|
||||||
|
body += "name: ${project.name}"
|
||||||
|
body += "main: ${project.group}.taboolib.platform.NukkitPlugin"
|
||||||
|
body += "version: ${project.version}"
|
||||||
|
write(body, description.lin.links['homepage'], 'website')
|
||||||
|
writeLine(body)
|
||||||
|
// authors
|
||||||
|
def con = description.con.contributors.collect { it.name }
|
||||||
|
writeList(body, con, 'authors')
|
||||||
|
writeLine(body)
|
||||||
|
// dependency
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('nukkit') }
|
||||||
|
.findAll { it.forceDepend() }
|
||||||
|
.collect { it.name }, 'depend')
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('nukkit') }
|
||||||
|
.findAll { it.optional }
|
||||||
|
.collect { it.name }, 'softdepend')
|
||||||
|
writeList(body, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('nukkit') }
|
||||||
|
.findAll { it.loadbefore }
|
||||||
|
.collect { it.name }, 'loadbefore')
|
||||||
|
writeLine(body)
|
||||||
|
// custom nodes
|
||||||
|
description.nukkitNodes.each {
|
||||||
|
if (it.value instanceof List) {
|
||||||
|
writeList(body, it.value, it.key)
|
||||||
|
} else {
|
||||||
|
write(body, it.value, it.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes(body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class BuilderSponge7 extends Builder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
byte[] build(Description description, Project project) {
|
||||||
|
def json = new JsonArray()
|
||||||
|
def info = new JsonObject()
|
||||||
|
info.addProperty('modid', project.name.toLowerCase())
|
||||||
|
info.addProperty('name', project.name)
|
||||||
|
info.addProperty('version', project.version.toString())
|
||||||
|
write(info, description.spongeDesc, 'description')
|
||||||
|
write(info, description.lin.links['homepage'], 'url')
|
||||||
|
// authors
|
||||||
|
def con = description.con.contributors.collect { it.name }
|
||||||
|
writeList(info, con, 'authorList')
|
||||||
|
// dependencies
|
||||||
|
writeList(info, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('sponge7') }
|
||||||
|
.findAll { !it.mod }
|
||||||
|
.collect { it.fullyName() }, 'dependencies')
|
||||||
|
writeList(info, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('sponge7') }
|
||||||
|
.findAll { it.mod }
|
||||||
|
.collect { it.fullyName() }, 'requiredMods')
|
||||||
|
json.add(info)
|
||||||
|
return bytes(json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class BuilderSponge8 extends Builder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
byte[] build(Description description, Project project) {
|
||||||
|
def json = new JsonObject()
|
||||||
|
def plugins = new JsonArray()
|
||||||
|
def info = new JsonObject()
|
||||||
|
info.addProperty('loader', 'java_plain')
|
||||||
|
info.addProperty('id', project.name.toLowerCase())
|
||||||
|
info.addProperty('name', project.name)
|
||||||
|
info.addProperty('version', project.version.toString())
|
||||||
|
info.addProperty('main-class', "${project.group}.taboolib.platform.Sponge8Plugin")
|
||||||
|
write(info, description.spongeDesc, 'description')
|
||||||
|
// links
|
||||||
|
if (description.lin.links.size() > 0) {
|
||||||
|
def links = new JsonObject()
|
||||||
|
description.lin.links.each {
|
||||||
|
links.addProperty(it.key, it.value.url)
|
||||||
|
}
|
||||||
|
info.add('links', links)
|
||||||
|
}
|
||||||
|
// contributors
|
||||||
|
if (description.con.contributors.size() > 0) {
|
||||||
|
def contributors = new JsonArray()
|
||||||
|
description.con.contributors.each {
|
||||||
|
def con = new JsonObject()
|
||||||
|
write(con, it.name, 'name')
|
||||||
|
write(con, it.description, 'description')
|
||||||
|
contributors.add(con)
|
||||||
|
}
|
||||||
|
info.add('contributors', contributors)
|
||||||
|
}
|
||||||
|
// dependencies
|
||||||
|
if (description.dep.dependencies.size() > 0) {
|
||||||
|
def dependencies = new JsonArray()
|
||||||
|
description.dep.dependencies.findAll { it.with == null || it.with.equalsIgnoreCase('sponge8') }.each {
|
||||||
|
def dep = new JsonObject()
|
||||||
|
write(dep, it.name, 'id')
|
||||||
|
write(dep, it.version, 'version')
|
||||||
|
dep.addProperty('load-order', it.loadafter ? 'AFTER' : 'UNDEFINED')
|
||||||
|
dep.addProperty('optional', it.optional)
|
||||||
|
dependencies.add(dep)
|
||||||
|
}
|
||||||
|
info.add('dependencies', dependencies)
|
||||||
|
}
|
||||||
|
plugins.add(info)
|
||||||
|
json.add('plugins', plugins)
|
||||||
|
return bytes(json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class BuilderVelocity extends Builder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
byte[] build(Description description, Project project) {
|
||||||
|
def info = new JsonObject()
|
||||||
|
info.addProperty('id', project.name.toLowerCase())
|
||||||
|
info.addProperty('name', project.name)
|
||||||
|
info.addProperty('main', "${project.group}.taboolib.platform.VelocityPlugin")
|
||||||
|
info.addProperty('version', project.version.toString())
|
||||||
|
// authors
|
||||||
|
def con = description.con.contributors.collect { it.name }
|
||||||
|
writeList(info, con, 'authors')
|
||||||
|
// dependencies
|
||||||
|
writeList(info, description.dep.dependencies
|
||||||
|
.findAll { it.with == null || it.with.equalsIgnoreCase('velocity') }
|
||||||
|
.collect { it.name }, 'dependencies')
|
||||||
|
return bytes(info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
class Contributors {
|
||||||
|
|
||||||
|
List<Contributor> contributors = []
|
||||||
|
|
||||||
|
Contributor name(name) {
|
||||||
|
def con = new Contributor(name)
|
||||||
|
contributors += con
|
||||||
|
return con
|
||||||
|
}
|
||||||
|
|
||||||
|
class Contributor {
|
||||||
|
|
||||||
|
def name
|
||||||
|
def description
|
||||||
|
|
||||||
|
Contributor(name) {
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
Contributor description(description) {
|
||||||
|
this.description = description
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
class Dependencies {
|
||||||
|
|
||||||
|
List<Dependency> dependencies = []
|
||||||
|
|
||||||
|
Dependency name(name) {
|
||||||
|
def dep = new Dependency(name)
|
||||||
|
dependencies += dep
|
||||||
|
return dep
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dependency {
|
||||||
|
|
||||||
|
String name
|
||||||
|
String with
|
||||||
|
String version
|
||||||
|
|
||||||
|
def loadafter = false
|
||||||
|
def loadbefore = false
|
||||||
|
def optional = false
|
||||||
|
def mod = false
|
||||||
|
|
||||||
|
Dependency(name) {
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
def fullyName(spec = '@') {
|
||||||
|
return version == null ? name : name + spec + version
|
||||||
|
}
|
||||||
|
|
||||||
|
def forceDepend() {
|
||||||
|
return !loadafter && !loadbefore && !optional
|
||||||
|
}
|
||||||
|
|
||||||
|
Dependency with(description) {
|
||||||
|
this.with = description
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
Dependency version(version) {
|
||||||
|
this.version = version
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
Dependency loadafter(loadafter) {
|
||||||
|
this.loadafter = loadafter
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
Dependency loadbefore(loadbefore) {
|
||||||
|
this.loadbefore = loadbefore
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
Dependency optional(optional) {
|
||||||
|
this.optional = optional
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
Dependency mod(mod) {
|
||||||
|
this.mod = mod
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
import org.gradle.api.Action
|
||||||
|
|
||||||
|
class Description {
|
||||||
|
|
||||||
|
Contributors con = new Contributors()
|
||||||
|
|
||||||
|
Dependencies dep = new Dependencies()
|
||||||
|
|
||||||
|
Links lin = new Links()
|
||||||
|
|
||||||
|
def bukkitNodes = new HashMap()
|
||||||
|
|
||||||
|
def nukkitNodes = new HashMap()
|
||||||
|
|
||||||
|
def bungeeNodes = new HashMap()
|
||||||
|
|
||||||
|
String spongeDesc
|
||||||
|
|
||||||
|
Description() {
|
||||||
|
bukkitApi('1.13')
|
||||||
|
nukkitApi('1.0.0')
|
||||||
|
}
|
||||||
|
|
||||||
|
def desc(desc) {
|
||||||
|
bukkitNodes['description'] = desc
|
||||||
|
nukkitNodes['description'] = desc
|
||||||
|
bungeeNodes['description'] = desc
|
||||||
|
spongeDesc = desc
|
||||||
|
}
|
||||||
|
|
||||||
|
def load(order) {
|
||||||
|
bukkitNodes['load'] = order
|
||||||
|
nukkitNodes['load'] = order
|
||||||
|
}
|
||||||
|
|
||||||
|
def bukkitApi(api) {
|
||||||
|
bukkitNodes['api-version'] = api
|
||||||
|
}
|
||||||
|
|
||||||
|
def nukkitApi(api) {
|
||||||
|
nukkitNodes['api'] = api
|
||||||
|
}
|
||||||
|
|
||||||
|
def prefix(prefix) {
|
||||||
|
bukkitNodes['prefix'] = prefix
|
||||||
|
nukkitNodes['prefix'] = prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
def contributors(Action<? super Contributors> action) {
|
||||||
|
action.execute(con)
|
||||||
|
}
|
||||||
|
|
||||||
|
def dependencies(Action<? super Dependencies> action) {
|
||||||
|
action.execute(dep)
|
||||||
|
}
|
||||||
|
|
||||||
|
def links(Action<? super Links> action) {
|
||||||
|
action.execute(lin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
class Links {
|
||||||
|
|
||||||
|
def links = new HashMap<String, Link>()
|
||||||
|
|
||||||
|
Link name(name) {
|
||||||
|
def link = new Link(name)
|
||||||
|
links[link.name] = link
|
||||||
|
return link
|
||||||
|
}
|
||||||
|
|
||||||
|
class Link {
|
||||||
|
|
||||||
|
String name
|
||||||
|
String url
|
||||||
|
|
||||||
|
Link(name) {
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
Link url(url) {
|
||||||
|
this.url = url
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString() {
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.izzel.taboolib.gradle.description
|
||||||
|
|
||||||
|
enum Platforms {
|
||||||
|
|
||||||
|
BUKKIT('Bukkit', 'platform-bukkit', 'plugin.yml', new BuilderBukkit()),
|
||||||
|
|
||||||
|
NUKKIT('Nukkit', 'platform-nukkit', 'nukkit.yml', new BuilderNukkit()),
|
||||||
|
|
||||||
|
BUNGEE('Bungee', 'platform-bungee', 'bungee.yml', new BuilderBungee()),
|
||||||
|
|
||||||
|
VELOCITY('Velocity', 'platform-velocity', 'velocity-plugin.json', new BuilderVelocity()),
|
||||||
|
|
||||||
|
SPONGE7('Sponge7', 'platform-sponge-api7', 'mcmod.info', new BuilderSponge7()),
|
||||||
|
|
||||||
|
SPONGE8('Sponge8', 'platform-sponge-api8', 'META-INF/plugins.json', new BuilderSponge8());
|
||||||
|
|
||||||
|
String key
|
||||||
|
String module
|
||||||
|
String file
|
||||||
|
Builder builder
|
||||||
|
|
||||||
|
Platforms(key, module, file, builder) {
|
||||||
|
this.key = key
|
||||||
|
this.module = module
|
||||||
|
this.file = file
|
||||||
|
this.builder = builder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package io.izzel.taboolib.gradle;
|
||||||
|
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* taboolib-gradle-plugin
|
||||||
|
* io.izzel.taboolib.gradle.KotlinFactory
|
||||||
|
*
|
||||||
|
* @author sky
|
||||||
|
* @since 2021/8/14 1:43 下午
|
||||||
|
*/
|
||||||
|
public class Bridge {
|
||||||
|
|
||||||
|
public static OptimizeFileReader newOptimizeFileReader(Project project, InputStream inputStream) {
|
||||||
|
return new OptimizeFileReader(project, inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
|
import com.google.gson.JsonParser
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
/**
|
||||||
|
* taboolib-gradle-plugin
|
||||||
|
* io.izzel.taboolib.gradle.OptimizeFileReader
|
||||||
|
*
|
||||||
|
* @author sky
|
||||||
|
* @since 2021/8/14 1:18 下午
|
||||||
|
*/
|
||||||
|
class OptimizeFileReader(project: Project, input: InputStream) {
|
||||||
|
|
||||||
|
val optimize = ArrayList<Optimize>()
|
||||||
|
val group = ArrayList<Group>()
|
||||||
|
val exclude = ArrayList<String>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
try {
|
||||||
|
val jsonSource = input.readBytes().toString(StandardCharsets.UTF_8)
|
||||||
|
val json = JsonParser.parseString(jsonSource).asJsonObject
|
||||||
|
if (json.has("optimize")) {
|
||||||
|
json.getAsJsonArray("optimize").forEach { ele ->
|
||||||
|
optimize += Optimize(
|
||||||
|
relocate(project, ele.asJsonObject["class"].asString),
|
||||||
|
Optimize.Type.valueOf(ele.asJsonObject["type"].asString)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json.has("group")) {
|
||||||
|
json.getAsJsonArray("group").forEach { ele ->
|
||||||
|
var depend: Group.Depend? = null
|
||||||
|
if (ele.asJsonObject.has("depend")) {
|
||||||
|
depend = Group.Depend(
|
||||||
|
ele.asJsonObject["depend"].asJsonObject["name"].asJsonArray.map { relocate(project, it.asString) },
|
||||||
|
ele.asJsonObject["depend"].asJsonObject["exclude"].asJsonArray.map { relocate(project, it.asString) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
group += Group(
|
||||||
|
ele.asJsonObject["check"].asJsonArray.map { relocate(project, it.asString) },
|
||||||
|
ele.asJsonObject["member"].asJsonArray.map { relocate(project, it.asString) },
|
||||||
|
ele.asJsonObject["exclude"]?.asJsonArray?.map { relocate(project, it.asString) }?.toList() ?: emptyList(),
|
||||||
|
depend,
|
||||||
|
Group.Mode.valueOf(ele.asJsonObject["mode"].asString)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json.has("exclude")) {
|
||||||
|
exclude += json.getAsJsonArray("exclude").map { relocate(project, it.asString) }
|
||||||
|
}
|
||||||
|
} catch (ex: Throwable) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun relocate(project: Project, name: String): String {
|
||||||
|
return if (name.startsWith("taboolib")) {
|
||||||
|
project.group.toString().replace('.', '/') + '/' + name.replace('.', '/')
|
||||||
|
} else {
|
||||||
|
name.replace('.', '/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exclude(name: String, use: Map<String, Set<String>>): Boolean {
|
||||||
|
if (exclude.any { name.startsWith(it) }) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (group.any { it.exclude(name, use) }) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
class Optimize(val path: String, val type: Type) {
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
|
||||||
|
METHOD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Group(check: List<String>, member: List<String>, exclude: List<String>, val depend: Depend? = null, val mode: Mode) {
|
||||||
|
|
||||||
|
val check = check.platformFlatten()
|
||||||
|
|
||||||
|
val member = member.platformFlatten()
|
||||||
|
|
||||||
|
val exclude = exclude.platformFlatten()
|
||||||
|
|
||||||
|
class Depend(name: List<String>, exclude: List<String>) {
|
||||||
|
|
||||||
|
val name = name.platformFlatten()
|
||||||
|
|
||||||
|
val exclude = exclude.platformFlatten()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
|
||||||
|
REMOVE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exclude(name: String, use: Map<String, Set<String>>): Boolean {
|
||||||
|
if (member.any { name.startsWith(it) }) {
|
||||||
|
if (depend != null) {
|
||||||
|
val fail = depend.name.any { n ->
|
||||||
|
val set = use[n]?.toMutableList() ?: ArrayList()
|
||||||
|
set.remove(n)
|
||||||
|
set.removeAll(depend.exclude)
|
||||||
|
set.isNotEmpty()
|
||||||
|
}
|
||||||
|
if (fail) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (s in check) {
|
||||||
|
val set = use[s]?.toMutableList() ?: ArrayList()
|
||||||
|
set.remove(s)
|
||||||
|
set.removeAll(check)
|
||||||
|
set.removeAll(member)
|
||||||
|
set.removeAll(exclude)
|
||||||
|
if (set.isNotEmpty()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package io.izzel.taboolib.gradle
|
||||||
|
|
||||||
|
val platforms = listOf("Bukkit", "Nukkit", "Bungee", "Sponge7", "Sponge8", "Velocity")
|
||||||
|
|
||||||
|
fun List<String>.platformFlatten(): List<String> {
|
||||||
|
return flatMap {
|
||||||
|
if (it.contains("{platform}")) {
|
||||||
|
platforms.map { p -> it.replace("{platform}", p) }
|
||||||
|
} else {
|
||||||
|
listOf(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue