mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-07-07 12:32:54 +00:00
Merge branch 'feature/gradle-vice' into mc-1.16.x
The hills are alive with the sound of build scripts!
This commit is contained in:
commit
b48f590b92
@ -24,6 +24,13 @@ repos:
|
|||||||
|
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
|
- id: license
|
||||||
|
name: Spotless
|
||||||
|
files: ".*\\.(java|kt|kts)$"
|
||||||
|
language: system
|
||||||
|
entry: ./gradlew spotlessApply
|
||||||
|
pass_filenames: false
|
||||||
|
require_serial: true
|
||||||
- id: checkstyle
|
- id: checkstyle
|
||||||
name: Check Java codestyle
|
name: Check Java codestyle
|
||||||
files: ".*\\.java$"
|
files: ".*\\.java$"
|
||||||
@ -31,18 +38,11 @@ repos:
|
|||||||
entry: ./gradlew checkstyleMain checkstyleTest
|
entry: ./gradlew checkstyleMain checkstyleTest
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
require_serial: true
|
require_serial: true
|
||||||
- id: license
|
|
||||||
name: Check Java license headers
|
|
||||||
files: ".*\\.java$"
|
|
||||||
language: system
|
|
||||||
entry: ./gradlew licenseFormat
|
|
||||||
pass_filenames: false
|
|
||||||
require_serial: true
|
|
||||||
- id: illuaminate
|
- id: illuaminate
|
||||||
name: Check Lua code
|
name: Check Lua code
|
||||||
files: ".*\\.(lua|java|md)"
|
files: ".*\\.(lua|java|md)"
|
||||||
language: system
|
language: system
|
||||||
entry: ./gradlew lintLua -i
|
entry: ./gradlew lintLua
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
require_serial: true
|
require_serial: true
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ Before we get into writing tests, it's worth mentioning the various test suites
|
|||||||
- In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
|
- In-game (`./src/testMod/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
|
||||||
the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
|
the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
|
||||||
|
|
||||||
These tests are run with `./gradlew testServer`.
|
These tests are run with `./gradlew runGametest`.
|
||||||
|
|
||||||
## CraftOS tests
|
## CraftOS tests
|
||||||
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
|
CraftOS's tests are written using a test system called "mcfly", heavily inspired by [busted] (and thus RSpec). Groups of
|
||||||
|
621
build.gradle
621
build.gradle
@ -1,621 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "checkstyle"
|
|
||||||
id "jacoco"
|
|
||||||
id "maven-publish"
|
|
||||||
id "org.cadixdev.licenser" version "0.6.1"
|
|
||||||
id "com.matthewprenger.cursegradle" version "1.4.0"
|
|
||||||
id "com.github.breadmoirai.github-release" version "2.2.12"
|
|
||||||
id "org.jetbrains.kotlin.jvm" version "1.7.0"
|
|
||||||
id "com.modrinth.minotaur" version "2.+"
|
|
||||||
id "net.minecraftforge.gradle" version "5.1.+"
|
|
||||||
id "org.spongepowered.mixin" version "0.7.+"
|
|
||||||
id "org.parchmentmc.librarian.forgegradle" version "1.+"
|
|
||||||
id "com.github.johnrengelman.shadow" version "7.1.2"
|
|
||||||
id "cc-tweaked.illuaminate"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
import cc.tweaked.gradle.ExtensionsKt
|
|
||||||
import cc.tweaked.gradle.IlluaminateExec
|
|
||||||
import cc.tweaked.gradle.IlluaminateExecToDir
|
|
||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
|
||||||
|
|
||||||
version = mod_version
|
|
||||||
|
|
||||||
group = "org.squiddev"
|
|
||||||
archivesBaseName = "cc-tweaked-${mc_version}"
|
|
||||||
|
|
||||||
def javaVersion = JavaLanguageVersion.of(8)
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = javaVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
withSourcesJar()
|
|
||||||
withJavadocJar()
|
|
||||||
registerFeature("extraMods") { usingSourceSet(sourceSets.main) }
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main.resources {
|
|
||||||
srcDir 'src/generated/resources'
|
|
||||||
}
|
|
||||||
|
|
||||||
testMod {}
|
|
||||||
}
|
|
||||||
|
|
||||||
minecraft {
|
|
||||||
runs {
|
|
||||||
all {
|
|
||||||
property 'forge.logging.markers', 'REGISTRIES'
|
|
||||||
property 'forge.logging.console.level', 'debug'
|
|
||||||
forceExit = false
|
|
||||||
|
|
||||||
mods {
|
|
||||||
computercraft {
|
|
||||||
source sourceSets.main
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arg "-mixin.config=computercraft.mixins.json"
|
|
||||||
}
|
|
||||||
|
|
||||||
client {
|
|
||||||
workingDirectory project.file('run')
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
workingDirectory project.file("run/server")
|
|
||||||
arg "--nogui"
|
|
||||||
}
|
|
||||||
|
|
||||||
data {
|
|
||||||
workingDirectory project.file('run')
|
|
||||||
args '--mod', 'computercraft', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
|
|
||||||
property("cct.pretty-json", "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
testClient {
|
|
||||||
workingDirectory project.file('test-files/client')
|
|
||||||
parent runs.client
|
|
||||||
|
|
||||||
mods {
|
|
||||||
cctest {
|
|
||||||
source sourceSets.testMod
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testServer {
|
|
||||||
workingDirectory project.file('test-files/server')
|
|
||||||
parent runs.server
|
|
||||||
|
|
||||||
property("cctest.run", "true")
|
|
||||||
property("forge.logging.console.level", "info")
|
|
||||||
|
|
||||||
mods {
|
|
||||||
cctest {
|
|
||||||
source sourceSets.testMod
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mappings channel: 'parchment', version: "${mapping_version}-${mc_version}"
|
|
||||||
|
|
||||||
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
|
|
||||||
accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
|
|
||||||
}
|
|
||||||
|
|
||||||
mixin {
|
|
||||||
add sourceSets.main, 'computercraft.mixins.refmap.json'
|
|
||||||
}
|
|
||||||
|
|
||||||
reobf {
|
|
||||||
shadowJar {}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven {
|
|
||||||
name "SquidDev"
|
|
||||||
url "https://squiddev.cc/maven"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
shade { transitive = false }
|
|
||||||
implementation.extendsFrom shade
|
|
||||||
cctJavadoc
|
|
||||||
|
|
||||||
testModImplementation.extendsFrom(implementation)
|
|
||||||
testModImplementation.extendsFrom(testImplementation)
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
checkstyle "com.puppycrawl.tools:checkstyle:8.25"
|
|
||||||
|
|
||||||
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
|
||||||
annotationProcessor 'org.spongepowered:mixin:0.8.4:processor'
|
|
||||||
|
|
||||||
compileOnly(libs.jetbrainsAnnotations)
|
|
||||||
ExtensionsKt.annotationProcessorEverywhere(dependencies, libs.autoService)
|
|
||||||
|
|
||||||
extraModsCompileOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104:api")
|
|
||||||
extraModsRuntimeOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104")
|
|
||||||
|
|
||||||
extraModsCompileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.5:7.1.0.313")
|
|
||||||
extraModsCompileOnly fg.deobf("commoble.morered:morered-1.16.5:2.1.1.0")
|
|
||||||
|
|
||||||
shade 'org.squiddev:Cobalt:0.5.7'
|
|
||||||
|
|
||||||
testImplementation(libs.bundles.test)
|
|
||||||
testImplementation(libs.bundles.kotlin)
|
|
||||||
testRuntimeOnly(libs.bundles.testRuntime)
|
|
||||||
|
|
||||||
testModImplementation sourceSets.main.output
|
|
||||||
|
|
||||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.7'
|
|
||||||
}
|
|
||||||
|
|
||||||
illuaminate {
|
|
||||||
version.set("0.1.0-3-g0f40379")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile tasks
|
|
||||||
|
|
||||||
javadoc {
|
|
||||||
include "dan200/computercraft/api/**/*.java"
|
|
||||||
}
|
|
||||||
|
|
||||||
def apiJar = tasks.register("apiJar", Jar.class) {
|
|
||||||
archiveClassifier.set("api")
|
|
||||||
from(sourceSets.main.output) {
|
|
||||||
include "dan200/computercraft/api/**/*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assemble.dependsOn(apiJar)
|
|
||||||
|
|
||||||
def luaJavadoc = tasks.register("luaJavadoc", Javadoc.class) {
|
|
||||||
description "Generates documentation for Java-side Lua functions."
|
|
||||||
group "documentation"
|
|
||||||
|
|
||||||
source = sourceSets.main.allJava
|
|
||||||
destinationDir = file("${project.docsDir}/luaJavadoc")
|
|
||||||
classpath = sourceSets.main.compileClasspath
|
|
||||||
|
|
||||||
options.docletpath = configurations.cctJavadoc.files as List
|
|
||||||
options.doclet = "cc.tweaked.javadoc.LuaDoclet"
|
|
||||||
options.noTimestamp = false
|
|
||||||
|
|
||||||
javadocTool = javaToolchains.javadocToolFor {
|
|
||||||
languageVersion = JavaLanguageVersion.of(11)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
finalizedBy("reobfJar")
|
|
||||||
|
|
||||||
archiveClassifier.set("slim")
|
|
||||||
manifest {
|
|
||||||
attributes([
|
|
||||||
"Specification-Title" : "computercraft",
|
|
||||||
"Specification-Vendor" : "SquidDev",
|
|
||||||
"Specification-Version" : "1",
|
|
||||||
"Implementation-Title" : "CC: Tweaked",
|
|
||||||
"Implementation-Version" : "${mod_version}",
|
|
||||||
"Implementation-Vendor" : "SquidDev",
|
|
||||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
|
||||||
"MixinConfigs" : "computercraft.mixins.json",
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowJar {
|
|
||||||
finalizedBy("reobfShadowJar")
|
|
||||||
|
|
||||||
archiveClassifier.set("")
|
|
||||||
configurations = [project.configurations.shade]
|
|
||||||
relocate("org.squiddev.cobalt", "cc.tweaked.internal.cobalt")
|
|
||||||
minimize()
|
|
||||||
}
|
|
||||||
|
|
||||||
assemble.dependsOn("shadowJar")
|
|
||||||
|
|
||||||
[
|
|
||||||
tasks.named("compileJava", JavaCompile.class),
|
|
||||||
tasks.named("compileTestJava", JavaCompile.class),
|
|
||||||
tasks.named("compileTestModJava", JavaCompile.class)
|
|
||||||
].forEach {
|
|
||||||
it.configure {
|
|
||||||
options.compilerArgs << "-Xlint" << "-Xlint:-processing"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
|
||||||
inputs.property "version", mod_version
|
|
||||||
inputs.property "mcversion", mc_version
|
|
||||||
|
|
||||||
def hash = 'none'
|
|
||||||
Set<String> contributors = []
|
|
||||||
try {
|
|
||||||
hash = ["git", "-C", projectDir, "rev-parse", "HEAD"].execute().text.trim()
|
|
||||||
|
|
||||||
def blacklist = ['GitHub', 'Daniel Ratcliffe', 'Weblate']
|
|
||||||
|
|
||||||
// Extract all authors, commiters and co-authors from the git log.
|
|
||||||
def authors = ["git", "-C", projectDir, "log", "--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)"]
|
|
||||||
.execute().text.readLines().unique()
|
|
||||||
|
|
||||||
// We now pass this through git's mailmap to de-duplicate some authors.
|
|
||||||
def remapAuthors = ["git", "check-mailmap", "--stdin"].execute()
|
|
||||||
remapAuthors.withWriter { stdin ->
|
|
||||||
if (stdin !instanceof BufferedWriter) stdin = new BufferedWriter(stdin)
|
|
||||||
|
|
||||||
authors.forEach {
|
|
||||||
if (it == "") return
|
|
||||||
if (!it.endsWith(">")) it += ">" // Some commits have broken Co-Authored-By lines!
|
|
||||||
stdin.writeLine(it)
|
|
||||||
}
|
|
||||||
stdin.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// And finally extract out the actual name.
|
|
||||||
def emailRegex = ~/^([^<]+) <.+>$/
|
|
||||||
remapAuthors.text.readLines().forEach {
|
|
||||||
def matcher = it =~ emailRegex
|
|
||||||
matcher.find()
|
|
||||||
def name = matcher.group(1)
|
|
||||||
if (!blacklist.contains(name)) contributors.add(name)
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
inputs.property "commithash", hash
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
|
||||||
include 'META-INF/mods.toml'
|
|
||||||
include 'data/computercraft/lua/rom/help/credits.txt'
|
|
||||||
|
|
||||||
expand 'version': mod_version,
|
|
||||||
'mcversion': mc_version,
|
|
||||||
'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
|
||||||
exclude 'META-INF/mods.toml'
|
|
||||||
exclude 'data/computercraft/lua/rom/help/credits.txt'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sourcesJar {
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Web tasks
|
|
||||||
|
|
||||||
List<String> mkCommand(String command) {
|
|
||||||
return Os.isFamily(Os.FAMILY_WINDOWS) ? ["cmd", "/c", command] : ["sh", "-c", command]
|
|
||||||
}
|
|
||||||
|
|
||||||
def rollup = tasks.register("rollup", Exec.class) {
|
|
||||||
group = "build"
|
|
||||||
description = "Bundles JS into rollup"
|
|
||||||
|
|
||||||
inputs.files(fileTree("src/web")).withPropertyName("sources")
|
|
||||||
inputs.file("package-lock.json").withPropertyName("package-lock.json")
|
|
||||||
inputs.file("tsconfig.json").withPropertyName("Typescript config")
|
|
||||||
inputs.file("rollup.config.js").withPropertyName("Rollup config")
|
|
||||||
outputs.file("$buildDir/rollup/index.js").withPropertyName("output")
|
|
||||||
|
|
||||||
commandLine mkCommand('"node_modules/.bin/rollup" --config rollup.config.js')
|
|
||||||
}
|
|
||||||
|
|
||||||
def illuaminateDocs = tasks.register("illuaminateDocs", IlluaminateExecToDir.class) {
|
|
||||||
group = "documentation"
|
|
||||||
description = "Generates docs using Illuaminate"
|
|
||||||
dependsOn(rollup)
|
|
||||||
|
|
||||||
// Config files
|
|
||||||
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
|
||||||
// Sources
|
|
||||||
inputs.files(fileTree("doc")).withPropertyName("docs")
|
|
||||||
inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
|
|
||||||
inputs.files(luaJavadoc)
|
|
||||||
// Additional assets
|
|
||||||
inputs.file("$buildDir/rollup/index.js").withPropertyName("scripts")
|
|
||||||
inputs.file("src/web/styles.css").withPropertyName("styles")
|
|
||||||
|
|
||||||
// Output directory. Also defined in illuaminate.sexp and transform.tsx
|
|
||||||
output.set(new File(buildDir, "docs/lua"))
|
|
||||||
|
|
||||||
args = ["doc-gen"]
|
|
||||||
}
|
|
||||||
|
|
||||||
def jsxDocs = tasks.register("jsxDocs", Exec) {
|
|
||||||
group = "documentation"
|
|
||||||
description = "Post-processes documentation to statically render some dynamic content."
|
|
||||||
|
|
||||||
inputs.files(fileTree("src/web")).withPropertyName("sources")
|
|
||||||
inputs.file("src/generated/export/index.json").withPropertyName("export")
|
|
||||||
inputs.file("package-lock.json").withPropertyName("package-lock.json")
|
|
||||||
inputs.file("tsconfig.json").withPropertyName("Typescript config")
|
|
||||||
inputs.files(illuaminateDocs)
|
|
||||||
outputs.dir("$buildDir/docs/site")
|
|
||||||
|
|
||||||
commandLine mkCommand('"node_modules/.bin/ts-node" -T --esm src/web/transform.tsx')
|
|
||||||
}
|
|
||||||
|
|
||||||
def docWebsite = tasks.register("docWebsite", Copy.class) {
|
|
||||||
group = "documentation"
|
|
||||||
description = "Copy additional assets to the website directory."
|
|
||||||
dependsOn(jsxDocs)
|
|
||||||
|
|
||||||
from('doc') {
|
|
||||||
include 'logo.png'
|
|
||||||
include 'images/**'
|
|
||||||
}
|
|
||||||
from("$buildDir/rollup") {
|
|
||||||
exclude 'index.js'
|
|
||||||
}
|
|
||||||
from("$buildDir/docs/lua") {
|
|
||||||
exclude '**/*.html'
|
|
||||||
}
|
|
||||||
from("src/generated/export/items") {
|
|
||||||
into("images/items")
|
|
||||||
}
|
|
||||||
|
|
||||||
into "${project.docsDir}/site"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check tasks
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
testLogging {
|
|
||||||
events "skipped", "failed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jacocoTestReport {
|
|
||||||
dependsOn('test')
|
|
||||||
reports {
|
|
||||||
xml.required = true
|
|
||||||
html.required = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.finalizedBy("jacocoTestReport")
|
|
||||||
|
|
||||||
license {
|
|
||||||
header = file('config/license/main.txt')
|
|
||||||
lineEnding = '\n'
|
|
||||||
newLine = false
|
|
||||||
|
|
||||||
properties {
|
|
||||||
year = Calendar.getInstance().get(Calendar.YEAR)
|
|
||||||
}
|
|
||||||
|
|
||||||
include("**/*.java") // We could apply to Kotlin, but for now let's not
|
|
||||||
matching("dan200/computercraft/api/**") {
|
|
||||||
header = file('config/license/api.txt')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check.dependsOn("licenseCheck")
|
|
||||||
|
|
||||||
def lintLua = tasks.register("lintLua", IlluaminateExec.class) {
|
|
||||||
group = JavaBasePlugin.VERIFICATION_GROUP
|
|
||||||
description = "Lint Lua (and Lua docs) with illuaminate"
|
|
||||||
|
|
||||||
// Config files
|
|
||||||
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
|
||||||
// Sources
|
|
||||||
inputs.files(fileTree("doc")).withPropertyName("docs")
|
|
||||||
inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
|
|
||||||
inputs.files(luaJavadoc)
|
|
||||||
|
|
||||||
args = ["lint"]
|
|
||||||
|
|
||||||
doFirst { if (System.getenv("GITHUB_ACTIONS") != null) println("::add-matcher::.github/matchers/illuaminate.json") }
|
|
||||||
doLast { if (System.getenv("GITHUB_ACTIONS") != null) println("::remove-matcher owner=illuaminate::") }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def setupServer = tasks.register("setupServer", Copy.class) {
|
|
||||||
group "test server"
|
|
||||||
description "Sets up the environment for the test server."
|
|
||||||
|
|
||||||
from("src/testMod/server-files") {
|
|
||||||
include "eula.txt"
|
|
||||||
include "server.properties"
|
|
||||||
}
|
|
||||||
into "test-files/server"
|
|
||||||
}
|
|
||||||
|
|
||||||
def testServerClassDumpDir = new File(buildDir, "jacocoClassDump/runTestServer")
|
|
||||||
|
|
||||||
def testServer = tasks.register("testServer", JavaExec.class) {
|
|
||||||
group("In-game tests")
|
|
||||||
description("Runs tests on a temporary Minecraft instance.")
|
|
||||||
dependsOn(setupServer, "cleanTestServer")
|
|
||||||
finalizedBy("jacocoTestServerReport")
|
|
||||||
|
|
||||||
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
|
||||||
// isn't created until the task is configured (which is no good for us).
|
|
||||||
ExtensionsKt.copyToFull(tasks.getByName("runTestServer"), it)
|
|
||||||
|
|
||||||
// Jacoco and modlauncher don't play well together as the classes loaded in-game don't
|
|
||||||
// match up with those written to disk. We get Jacoco to dump all classes to disk, and
|
|
||||||
// use that when generating the report.
|
|
||||||
jacoco.applyTo(it)
|
|
||||||
it.jacoco.setIncludes(["dan200.computercraft.*"])
|
|
||||||
it.jacoco.setClassDumpDir(testServerClassDumpDir)
|
|
||||||
outputs.dir(testServerClassDumpDir)
|
|
||||||
// Older versions of modlauncher don't include a protection domain (and thus no code
|
|
||||||
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
|
||||||
it.jacoco.setIncludeNoLocationClasses(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register("jacocoTestServerReport", JacocoReport.class) {
|
|
||||||
group("In-game tests")
|
|
||||||
description("Generate coverage reports for testServer")
|
|
||||||
dependsOn(testServer)
|
|
||||||
|
|
||||||
executionData(new File(buildDir, "jacoco/testServer.exec"))
|
|
||||||
sourceDirectories.from(sourceSets.main.allJava.srcDirs)
|
|
||||||
classDirectories.from(testServerClassDumpDir)
|
|
||||||
|
|
||||||
reports {
|
|
||||||
xml.enabled true
|
|
||||||
html.enabled true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check.dependsOn(testServer)
|
|
||||||
|
|
||||||
// Upload tasks
|
|
||||||
|
|
||||||
def checkRelease = tasks.register("checkRelease") {
|
|
||||||
group "upload"
|
|
||||||
description "Verifies that everything is ready for a release"
|
|
||||||
|
|
||||||
inputs.property "version", mod_version
|
|
||||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/changelog.md")
|
|
||||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
def ok = true
|
|
||||||
|
|
||||||
// Check we're targetting the current version
|
|
||||||
def whatsnew = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.md").readLines()
|
|
||||||
if (whatsnew[0] != "New features in CC: Tweaked $mod_version") {
|
|
||||||
ok = false
|
|
||||||
project.logger.error("Expected `whatsnew.md' to target $mod_version.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check "read more" exists and trim it
|
|
||||||
def idx = whatsnew.findIndexOf { it == 'Type "help changelog" to see the full version history.' }
|
|
||||||
if (idx == -1) {
|
|
||||||
ok = false
|
|
||||||
project.logger.error("Must mention the changelog in whatsnew.md")
|
|
||||||
} else {
|
|
||||||
whatsnew = whatsnew.getAt(0..<idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whatsnew and changelog match.
|
|
||||||
def versionChangelog = "# " + whatsnew.join("\n")
|
|
||||||
def changelog = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/changelog.md").getText()
|
|
||||||
if (!changelog.startsWith(versionChangelog)) {
|
|
||||||
ok = false
|
|
||||||
project.logger.error("whatsnew and changelog are not in sync")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) throw new IllegalStateException("Could not check release")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
check.dependsOn(checkRelease)
|
|
||||||
|
|
||||||
def isStable = true
|
|
||||||
|
|
||||||
curseforge {
|
|
||||||
apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
|
|
||||||
project {
|
|
||||||
id = '282001'
|
|
||||||
releaseType = isStable ? 'release' : 'alpha'
|
|
||||||
changelog = "Release notes can be found on the GitHub repository (https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
|
|
||||||
mainArtifact(shadowJar)
|
|
||||||
|
|
||||||
addGameVersion "${mc_version}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modrinth {
|
|
||||||
token = project.hasProperty('modrinthApiKey') ? project.getProperty('modrinthApiKey') : ''
|
|
||||||
projectId = 'gu7yAYhd'
|
|
||||||
versionNumber = "${project.mc_version}-${project.mod_version}"
|
|
||||||
versionName = "${project.mod_version}"
|
|
||||||
versionType = isStable ? 'release' : 'alpha'
|
|
||||||
uploadFile = shadowJar
|
|
||||||
gameVersions = [project.mc_version]
|
|
||||||
changelog = "Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
maven(MavenPublication) {
|
|
||||||
from components.java
|
|
||||||
artifact(apiJar)
|
|
||||||
fg.component(it)
|
|
||||||
|
|
||||||
pom {
|
|
||||||
name = 'CC: Tweaked'
|
|
||||||
description = 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
|
|
||||||
url = 'https://github.com/cc-tweaked/CC-Tweaked'
|
|
||||||
|
|
||||||
scm {
|
|
||||||
url = 'https://github.com/cc-tweaked/CC-Tweaked.git'
|
|
||||||
}
|
|
||||||
|
|
||||||
issueManagement {
|
|
||||||
system = 'github'
|
|
||||||
url = 'https://github.com/cc-tweaked/CC-Tweaked/issues'
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name = 'ComputerCraft Public License, Version 1.0'
|
|
||||||
url = 'https://github.com/cc-tweaked/CC-Tweaked/blob/mc-1.16.x/LICENSE'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
if (project.hasProperty("mavenUser")) {
|
|
||||||
maven {
|
|
||||||
name = "SquidDev"
|
|
||||||
url = "https://squiddev.cc/maven"
|
|
||||||
credentials {
|
|
||||||
username = project.property("mavenUser") as String
|
|
||||||
password = project.property("mavenPass") as String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
githubRelease {
|
|
||||||
token project.hasProperty('githubApiKey') ? project.githubApiKey : ''
|
|
||||||
owner 'cc-tweaked'
|
|
||||||
repo 'CC-Tweaked'
|
|
||||||
targetCommitish.set(project.provider({
|
|
||||||
try {
|
|
||||||
return ["git", "-C", projectDir, "rev-parse", "--abbrev-ref", "HEAD"].execute().text.trim()
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
return "master"
|
|
||||||
}))
|
|
||||||
|
|
||||||
tagName "v${mc_version}-${mod_version}"
|
|
||||||
releaseName "[${mc_version}] ${mod_version}"
|
|
||||||
body.set(project.provider({
|
|
||||||
"## " + new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
|
|
||||||
.readLines()
|
|
||||||
.takeWhile { it != 'Type "help changelog" to see the full version history.' }
|
|
||||||
.join("\n").trim()
|
|
||||||
}))
|
|
||||||
prerelease !isStable
|
|
||||||
}
|
|
||||||
|
|
||||||
def uploadTasks = ["publish", "curseforge", "modrinth", "githubRelease"]
|
|
||||||
uploadTasks.forEach { tasks.named(it) { dependsOn(checkRelease) } }
|
|
||||||
|
|
||||||
tasks.register("uploadAll") {
|
|
||||||
group = "upload"
|
|
||||||
description = "Uploads to all repositories (Maven, Curse, Modrinth, GitHub release)"
|
|
||||||
dependsOn(uploadTasks)
|
|
||||||
}
|
|
445
build.gradle.kts
Normal file
445
build.gradle.kts
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
import cc.tweaked.gradle.*
|
||||||
|
import net.darkhax.curseforgegradle.TaskPublishCurseForge
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
// Build
|
||||||
|
alias(libs.plugins.kotlin)
|
||||||
|
alias(libs.plugins.forgeGradle)
|
||||||
|
alias(libs.plugins.mixinGradle)
|
||||||
|
alias(libs.plugins.librarian)
|
||||||
|
alias(libs.plugins.shadow)
|
||||||
|
// Publishing
|
||||||
|
`maven-publish`
|
||||||
|
alias(libs.plugins.curseForgeGradle)
|
||||||
|
alias(libs.plugins.githubRelease)
|
||||||
|
alias(libs.plugins.minotaur)
|
||||||
|
// Utility
|
||||||
|
alias(libs.plugins.taskTree)
|
||||||
|
|
||||||
|
id("cc-tweaked.illuaminate")
|
||||||
|
id("cc-tweaked.node")
|
||||||
|
id("cc-tweaked.java-convention")
|
||||||
|
id("cc-tweaked")
|
||||||
|
}
|
||||||
|
|
||||||
|
val isStable = true
|
||||||
|
val modVersion: String by extra
|
||||||
|
val mcVersion: String by extra
|
||||||
|
|
||||||
|
group = "org.squiddev"
|
||||||
|
version = modVersion
|
||||||
|
base.archivesName.set("cc-tweaked-$mcVersion")
|
||||||
|
|
||||||
|
java.registerFeature("extraMods") { usingSourceSet(sourceSets.main.get()) }
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
resources.srcDir("src/generated/resources")
|
||||||
|
}
|
||||||
|
|
||||||
|
register("testMod")
|
||||||
|
}
|
||||||
|
|
||||||
|
minecraft {
|
||||||
|
runs {
|
||||||
|
// configureEach would be better, but we need to eagerly configure configs or otherwise the run task doesn't
|
||||||
|
// get set up properly.
|
||||||
|
all {
|
||||||
|
property("forge.logging.markers", "REGISTRIES")
|
||||||
|
property("forge.logging.console.level", "debug")
|
||||||
|
|
||||||
|
forceExit = false
|
||||||
|
|
||||||
|
mods.register("computercraft") { source(sourceSets.main.get()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val client by registering {
|
||||||
|
workingDirectory(file("run"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val server by registering {
|
||||||
|
workingDirectory(file("run/server"))
|
||||||
|
arg("--nogui")
|
||||||
|
}
|
||||||
|
|
||||||
|
val data by registering {
|
||||||
|
workingDirectory(file("run"))
|
||||||
|
args(
|
||||||
|
"--mod",
|
||||||
|
"computercraft",
|
||||||
|
"--all",
|
||||||
|
"--output",
|
||||||
|
file("src/generated/resources/"),
|
||||||
|
"--existing",
|
||||||
|
file("src/main/resources/"),
|
||||||
|
)
|
||||||
|
property("cct.pretty-json", "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
val testClient by registering {
|
||||||
|
workingDirectory(project.file("test-files/client"))
|
||||||
|
parent(client.get())
|
||||||
|
|
||||||
|
mods.register("cctest") { source(sourceSets["testMod"]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val testServer by registering {
|
||||||
|
workingDirectory(project.file("test-files/server"))
|
||||||
|
parent(server.get())
|
||||||
|
|
||||||
|
property("cctest.run", "true")
|
||||||
|
property("forge.logging.console.level", "info")
|
||||||
|
|
||||||
|
mods.register("cctest") { source(sourceSets["testMod"]) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mappings("parchment", "${libs.versions.parchmentMc.get()}-${libs.versions.parchment.get()}-$mcVersion")
|
||||||
|
|
||||||
|
accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg"))
|
||||||
|
accessTransformer(file("src/testMod/resources/META-INF/accesstransformer.cfg"))
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin {
|
||||||
|
add(sourceSets.main.get(), "computercraft.mixins.refmap.json")
|
||||||
|
config("computercraft.mixins.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
reobf {
|
||||||
|
register("shadowJar")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
val shade by registering { isTransitive = false }
|
||||||
|
implementation { extendsFrom(shade.get()) }
|
||||||
|
register("cctJavadoc")
|
||||||
|
|
||||||
|
named("testModImplementation") { extendsFrom(implementation.get(), testImplementation.get()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
minecraft("net.minecraftforge:forge:$mcVersion-${libs.versions.forge.get()}")
|
||||||
|
annotationProcessor("org.spongepowered:mixin:0.8.4:processor")
|
||||||
|
|
||||||
|
compileOnly(libs.jetbrainsAnnotations)
|
||||||
|
annotationProcessorEverywhere(libs.autoService)
|
||||||
|
|
||||||
|
"extraModsCompileOnly"(fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104:api"))
|
||||||
|
"extraModsRuntimeOnly"(fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104"))
|
||||||
|
|
||||||
|
"extraModsCompileOnly"(fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.5:7.1.0.313"))
|
||||||
|
"extraModsCompileOnly"(fg.deobf("commoble.morered:morered-1.16.5:2.1.1.0"))
|
||||||
|
|
||||||
|
"shade"(libs.cobalt)
|
||||||
|
|
||||||
|
testImplementation(libs.bundles.test)
|
||||||
|
testImplementation(libs.bundles.kotlin)
|
||||||
|
testRuntimeOnly(libs.bundles.testRuntime)
|
||||||
|
|
||||||
|
"testModImplementation"(sourceSets.main.get().output)
|
||||||
|
|
||||||
|
"cctJavadoc"(libs.cctJavadoc)
|
||||||
|
}
|
||||||
|
|
||||||
|
illuaminate {
|
||||||
|
version.set(libs.versions.illuaminate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile tasks
|
||||||
|
|
||||||
|
tasks.javadoc {
|
||||||
|
include("dan200/computercraft/api/**/*.java")
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiJar by tasks.registering(Jar::class) {
|
||||||
|
archiveClassifier.set("api")
|
||||||
|
from(sourceSets.main.get().output) {
|
||||||
|
include("dan200/computercraft/api/**/*")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.assemble { dependsOn(apiJar) }
|
||||||
|
|
||||||
|
val luaJavadoc by tasks.registering(Javadoc::class) {
|
||||||
|
description = "Generates documentation for Java-side Lua functions."
|
||||||
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
||||||
|
|
||||||
|
source(sourceSets.main.get().java)
|
||||||
|
setDestinationDir(project.buildDir.resolve("docs/luaJavadoc"))
|
||||||
|
classpath = sourceSets.main.get().compileClasspath
|
||||||
|
|
||||||
|
options.docletpath = configurations["cctJavadoc"].files.toList()
|
||||||
|
options.doclet = "cc.tweaked.javadoc.LuaDoclet"
|
||||||
|
(options as StandardJavadocDocletOptions).noTimestamp(false)
|
||||||
|
|
||||||
|
javadocTool.set(
|
||||||
|
javaToolchains.javadocToolFor {
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(11))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.processResources {
|
||||||
|
inputs.property("modVersion", modVersion)
|
||||||
|
inputs.property("forgeVersion", libs.versions.forge.get())
|
||||||
|
inputs.property("gitHash", cct.gitHash)
|
||||||
|
|
||||||
|
filesMatching("data/computercraft/lua/rom/help/credits.txt") {
|
||||||
|
expand(mapOf("gitContributors" to cct.gitContributors.get().joinToString("\n")))
|
||||||
|
}
|
||||||
|
|
||||||
|
filesMatching("META-INF/mods.toml") {
|
||||||
|
expand(mapOf("forgeVersion" to libs.versions.forge.get(), "file" to mapOf("jarVersion" to modVersion)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
isReproducibleFileOrder = true
|
||||||
|
isPreserveFileTimestamps = false
|
||||||
|
finalizedBy("reobfJar")
|
||||||
|
archiveClassifier.set("slim")
|
||||||
|
|
||||||
|
manifest {
|
||||||
|
attributes(
|
||||||
|
"Specification-Title" to "computercraft",
|
||||||
|
"Specification-Vendor" to "SquidDev",
|
||||||
|
"Specification-Version" to "1",
|
||||||
|
"specificationVersion" to "cctweaked",
|
||||||
|
"Implementation-Version" to modVersion,
|
||||||
|
"Implementation-Vendor" to "SquidDev",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.shadowJar {
|
||||||
|
finalizedBy("reobfShadowJar")
|
||||||
|
|
||||||
|
archiveClassifier.set("")
|
||||||
|
configurations = listOf(project.configurations["shade"])
|
||||||
|
relocate("org.squiddev.cobalt", "cc.tweaked.internal.cobalt")
|
||||||
|
minimize()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.assemble { dependsOn("shadowJar") }
|
||||||
|
|
||||||
|
// Web tasks
|
||||||
|
|
||||||
|
val rollup by tasks.registering(NpxExecToDir::class) {
|
||||||
|
group = LifecycleBasePlugin.BUILD_GROUP
|
||||||
|
description = "Bundles JS into rollup"
|
||||||
|
|
||||||
|
// Sources
|
||||||
|
inputs.files(fileTree("src/web")).withPropertyName("sources")
|
||||||
|
// Config files
|
||||||
|
inputs.file("tsconfig.json").withPropertyName("Typescript config")
|
||||||
|
inputs.file("rollup.config.js").withPropertyName("Rollup config")
|
||||||
|
|
||||||
|
// Output directory. Also defined in illuaminate.sexp and rollup.config.js
|
||||||
|
output.set(buildDir.resolve("rollup"))
|
||||||
|
|
||||||
|
args = listOf("rollup", "--config", "rollup.config.js")
|
||||||
|
}
|
||||||
|
|
||||||
|
val illuaminateDocs by tasks.registering(IlluaminateExecToDir::class) {
|
||||||
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
||||||
|
description = "Generates docs using Illuaminate"
|
||||||
|
|
||||||
|
// Config files
|
||||||
|
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
||||||
|
// Sources
|
||||||
|
inputs.files(fileTree("doc")).withPropertyName("docs")
|
||||||
|
inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
|
||||||
|
inputs.files(luaJavadoc)
|
||||||
|
// Additional assets
|
||||||
|
inputs.files(rollup)
|
||||||
|
inputs.file("src/web/styles.css").withPropertyName("styles")
|
||||||
|
|
||||||
|
// Output directory. Also defined in illuaminate.sexp and transform.tsx
|
||||||
|
output.set(buildDir.resolve("illuaminate"))
|
||||||
|
|
||||||
|
args = listOf("doc-gen")
|
||||||
|
}
|
||||||
|
|
||||||
|
val jsxDocs by tasks.registering(NpxExecToDir::class) {
|
||||||
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
||||||
|
description = "Post-processes documentation to statically render some dynamic content."
|
||||||
|
|
||||||
|
// Config files
|
||||||
|
inputs.file("tsconfig.json").withPropertyName("Typescript config")
|
||||||
|
// Sources
|
||||||
|
inputs.files(fileTree("src/web")).withPropertyName("sources")
|
||||||
|
inputs.file("src/generated/export/index.json").withPropertyName("export")
|
||||||
|
inputs.files(illuaminateDocs)
|
||||||
|
|
||||||
|
// Output directory. Also defined in src/web/transform.tsx
|
||||||
|
output.set(buildDir.resolve("jsxDocs"))
|
||||||
|
|
||||||
|
args = listOf("ts-node", "-T", "--esm", "src/web/transform.tsx")
|
||||||
|
}
|
||||||
|
|
||||||
|
val docWebsite by tasks.registering(Copy::class) {
|
||||||
|
group = JavaBasePlugin.DOCUMENTATION_GROUP
|
||||||
|
description = "Assemble docs and assets together into the documentation website."
|
||||||
|
|
||||||
|
from(jsxDocs)
|
||||||
|
|
||||||
|
from("doc") {
|
||||||
|
include("logo.png")
|
||||||
|
include("images/**")
|
||||||
|
}
|
||||||
|
from(rollup) { exclude("index.js") }
|
||||||
|
from(illuaminateDocs) { exclude("**/*.html") }
|
||||||
|
from("src/generated/export/items") { into("images/items") }
|
||||||
|
|
||||||
|
into(buildDir.resolve("docs/site"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check tasks
|
||||||
|
|
||||||
|
val lintLua by tasks.registering(IlluaminateExec::class) {
|
||||||
|
group = JavaBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Lint Lua (and Lua docs) with illuaminate"
|
||||||
|
|
||||||
|
// Config files
|
||||||
|
inputs.file("illuaminate.sexp").withPropertyName("illuaminate.sexp")
|
||||||
|
// Sources
|
||||||
|
inputs.files(fileTree("doc")).withPropertyName("docs")
|
||||||
|
inputs.files(fileTree("src/main/resources/data/computercraft/lua")).withPropertyName("lua rom")
|
||||||
|
inputs.files(luaJavadoc)
|
||||||
|
|
||||||
|
args = listOf("lint")
|
||||||
|
|
||||||
|
doFirst { if (System.getenv("GITHUB_ACTIONS") != null) println("::add-matcher::.github/matchers/illuaminate.json") }
|
||||||
|
doLast { if (System.getenv("GITHUB_ACTIONS") != null) println("::remove-matcher owner=illuaminate::") }
|
||||||
|
}
|
||||||
|
|
||||||
|
val setupRunGametest by tasks.registering(Copy::class) {
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Sets up the environment for the test server."
|
||||||
|
|
||||||
|
from("src/testMod/server-files") {
|
||||||
|
include("eula.txt")
|
||||||
|
include("server.properties")
|
||||||
|
}
|
||||||
|
into("test-files/server")
|
||||||
|
}
|
||||||
|
|
||||||
|
val runGametest by tasks.registering(JavaExec::class) {
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Runs tests on a temporary Minecraft instance."
|
||||||
|
dependsOn(setupRunGametest, "cleanRunGametest")
|
||||||
|
|
||||||
|
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
||||||
|
// isn't created until the task is configured (which is no good for us).
|
||||||
|
val exec = tasks.getByName<JavaExec>("runTestServer")
|
||||||
|
dependsOn(exec.dependsOn)
|
||||||
|
exec.copyToFull(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
cct.jacoco(runGametest)
|
||||||
|
|
||||||
|
tasks.check { dependsOn(runGametest) }
|
||||||
|
|
||||||
|
// Upload tasks
|
||||||
|
|
||||||
|
val checkChangelog by tasks.registering(CheckChangelog::class) {
|
||||||
|
version.set(modVersion)
|
||||||
|
whatsNew.set(file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md"))
|
||||||
|
changelog.set(file("src/main/resources/data/computercraft/lua/rom/help/changelog.md"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.check { dependsOn(checkChangelog) }
|
||||||
|
|
||||||
|
val publishCurseForge by tasks.registering(TaskPublishCurseForge::class) {
|
||||||
|
group = PublishingPlugin.PUBLISH_TASK_GROUP
|
||||||
|
description = "Upload artifacts to CurseForge"
|
||||||
|
|
||||||
|
apiToken = project.findProperty("curseForgeApiKey") ?: ""
|
||||||
|
enabled = apiToken != ""
|
||||||
|
|
||||||
|
val mainFile = upload("282001", tasks.shadowJar)
|
||||||
|
dependsOn(tasks.shadowJar) // Ughr.
|
||||||
|
mainFile.changelog = "Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion)."
|
||||||
|
mainFile.changelogType = "markdown"
|
||||||
|
mainFile.releaseType = if (isStable) "release" else "alpha"
|
||||||
|
mainFile.gameVersions.add(mcVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.publish { dependsOn(publishCurseForge) }
|
||||||
|
|
||||||
|
modrinth {
|
||||||
|
token.set(project.findProperty("modrinthApiKey") as String? ?: "")
|
||||||
|
projectId.set("gu7yAYhd")
|
||||||
|
versionNumber.set("$mcVersion-$modVersion")
|
||||||
|
versionName.set(modVersion)
|
||||||
|
versionType.set(if (isStable) "release" else "alpha")
|
||||||
|
uploadFile.set(tasks.shadowJar as Any)
|
||||||
|
gameVersions.add(mcVersion)
|
||||||
|
changelog.set("Release notes can be found on the [GitHub repository](https://github.com/cc-tweaked/CC-Tweaked/releases/tag/v$mcVersion-$modVersion).")
|
||||||
|
|
||||||
|
syncBodyFrom.set(project.provider { file("doc/mod-page.md").readText() })
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.publish { dependsOn(tasks.modrinth) }
|
||||||
|
|
||||||
|
githubRelease {
|
||||||
|
token(project.findProperty("githubApiKey") as String? ?: "")
|
||||||
|
owner.set("cc-tweaked")
|
||||||
|
repo.set("CC-Tweaked")
|
||||||
|
targetCommitish.set(cct.gitBranch)
|
||||||
|
|
||||||
|
tagName.set("v$mcVersion-$modVersion")
|
||||||
|
releaseName.set("[$mcVersion] $modVersion")
|
||||||
|
body.set(
|
||||||
|
project.provider(
|
||||||
|
{
|
||||||
|
"## " + file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
|
||||||
|
.readLines()
|
||||||
|
.takeWhile { it != "Type \"help changelog\" to see the full version history." }
|
||||||
|
.joinToString("\n").trim()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
prerelease.set(!isStable)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.publish { dependsOn(tasks.githubRelease) }
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
register<MavenPublication>("maven") {
|
||||||
|
artifactId = base.archivesName.get()
|
||||||
|
from(components["java"])
|
||||||
|
artifact(apiJar)
|
||||||
|
fg.component(this)
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name.set("CC: Tweaked")
|
||||||
|
description.set("CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.")
|
||||||
|
url.set("https://github.com/cc-tweaked/CC-Tweaked")
|
||||||
|
|
||||||
|
scm {
|
||||||
|
url.set("https://github.com/cc-tweaked/CC-Tweaked.git")
|
||||||
|
}
|
||||||
|
|
||||||
|
issueManagement {
|
||||||
|
system.set("github")
|
||||||
|
url.set("https://github.com/cc-tweaked/CC-Tweaked/issues")
|
||||||
|
}
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("ComputerCraft Public License, Version 1.0")
|
||||||
|
url.set("https://github.com/cc-tweaked/CC-Tweaked/blob/HEAD/LICENSE")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven("https://squiddev.cc/maven") {
|
||||||
|
name = "SquidDev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,11 +8,25 @@ repositories {
|
|||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.spotless)
|
||||||
|
}
|
||||||
|
|
||||||
gradlePlugin {
|
gradlePlugin {
|
||||||
plugins {
|
plugins {
|
||||||
|
register("cc-tweaked") {
|
||||||
|
id = "cc-tweaked"
|
||||||
|
implementationClass = "cc.tweaked.gradle.CCTweakedPlugin"
|
||||||
|
}
|
||||||
|
|
||||||
register("cc-tweaked.illuaminate") {
|
register("cc-tweaked.illuaminate") {
|
||||||
id = "cc-tweaked.illuaminate"
|
id = "cc-tweaked.illuaminate"
|
||||||
implementationClass = "cc.tweaked.gradle.IlluaminatePlugin"
|
implementationClass = "cc.tweaked.gradle.IlluaminatePlugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
register("cc-tweaked.node") {
|
||||||
|
id = "cc-tweaked.node"
|
||||||
|
implementationClass = "cc.tweaked.gradle.NodePlugin"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
buildSrc/settings.gradle.kts
Normal file
7
buildSrc/settings.gradle.kts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
dependencyResolutionManagement {
|
||||||
|
versionCatalogs {
|
||||||
|
create("libs") {
|
||||||
|
from(files("../gradle/libs.versions.toml"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts
Normal file
105
buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import cc.tweaked.gradle.LicenseHeader
|
||||||
|
import com.diffplug.gradle.spotless.FormatExtension
|
||||||
|
import com.diffplug.spotless.LineEnding
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
`java-library`
|
||||||
|
jacoco
|
||||||
|
checkstyle
|
||||||
|
id("com.diffplug.spotless")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(8))
|
||||||
|
}
|
||||||
|
|
||||||
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://squiddev.cc/maven") {
|
||||||
|
name = "SquidDev"
|
||||||
|
content {
|
||||||
|
includeGroup("org.squiddev")
|
||||||
|
includeGroup("cc.tweaked")
|
||||||
|
// Things we mirror
|
||||||
|
includeGroup("com.blamejared.crafttweaker")
|
||||||
|
includeGroup("commoble.morered")
|
||||||
|
includeGroup("maven.modrinth")
|
||||||
|
includeGroup("mezz.jei")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
val libs = project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||||
|
checkstyle(libs.findLibrary("checkstyle").get())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure default JavaCompile tasks with our arguments.
|
||||||
|
sourceSets.all {
|
||||||
|
tasks.named(compileJavaTaskName, JavaCompile::class.java) {
|
||||||
|
// Processing just gives us "No processor claimed any of these annotations", so skip that!
|
||||||
|
options.compilerArgs.addAll(listOf("-Xlint", "-Xlint:-processing"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile::class.java).configureEach {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
finalizedBy("jacocoTestReport")
|
||||||
|
|
||||||
|
useJUnitPlatform()
|
||||||
|
testLogging {
|
||||||
|
events("skipped", "failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JacocoReport::class.java).configureEach {
|
||||||
|
reports.xml.required.set(true)
|
||||||
|
reports.html.required.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
spotless {
|
||||||
|
encoding = StandardCharsets.UTF_8
|
||||||
|
lineEndings = LineEnding.UNIX
|
||||||
|
|
||||||
|
fun FormatExtension.defaults() {
|
||||||
|
endWithNewline()
|
||||||
|
trimTrailingWhitespace()
|
||||||
|
indentWithSpaces(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
val licenser = LicenseHeader.create(
|
||||||
|
api = file("config/license/api.txt"),
|
||||||
|
main = file("config/license/main.txt"),
|
||||||
|
)
|
||||||
|
|
||||||
|
java {
|
||||||
|
defaults()
|
||||||
|
addStep(licenser)
|
||||||
|
removeUnusedImports()
|
||||||
|
}
|
||||||
|
|
||||||
|
val ktlintConfig = mapOf(
|
||||||
|
"disabled_rules" to "no-wildcard-imports",
|
||||||
|
"ij_kotlin_allow_trailing_comma" to "true",
|
||||||
|
"ij_kotlin_allow_trailing_comma_on_call_site" to "true",
|
||||||
|
)
|
||||||
|
|
||||||
|
kotlinGradle {
|
||||||
|
defaults()
|
||||||
|
ktlint().editorConfigOverride(ktlintConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
defaults()
|
||||||
|
ktlint().editorConfigOverride(ktlintConfig)
|
||||||
|
}
|
||||||
|
}
|
124
buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt
Normal file
124
buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.NamedDomainObjectProvider
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.TestSuiteType
|
||||||
|
import org.gradle.api.file.FileSystemOperations
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.reporting.ReportingExtension
|
||||||
|
import org.gradle.api.tasks.JavaExec
|
||||||
|
import org.gradle.api.tasks.SourceSetContainer
|
||||||
|
import org.gradle.configurationcache.extensions.capitalized
|
||||||
|
import org.gradle.kotlin.dsl.get
|
||||||
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
|
import org.gradle.testing.jacoco.plugins.JacocoCoverageReport
|
||||||
|
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
|
||||||
|
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
|
||||||
|
import org.gradle.testing.jacoco.tasks.JacocoReport
|
||||||
|
import java.io.BufferedWriter
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.OutputStreamWriter
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
abstract class CCTweakedExtension(
|
||||||
|
private val project: Project,
|
||||||
|
private val fs: FileSystemOperations,
|
||||||
|
) {
|
||||||
|
/** Get the hash of the latest git commit. */
|
||||||
|
val gitHash: Provider<String> = gitProvider(project) {
|
||||||
|
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "HEAD")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the current git branch. */
|
||||||
|
val gitBranch: Provider<String> = gitProvider(project) {
|
||||||
|
ProcessHelpers.captureOut("git", "-C", project.projectDir.absolutePath, "rev-parse", "--abbrev-ref", "HEAD")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a list of all contributors to the project. */
|
||||||
|
val gitContributors: Provider<List<String>> = gitProvider(project) {
|
||||||
|
val authors: Set<String> = HashSet(
|
||||||
|
ProcessHelpers.captureLines(
|
||||||
|
"git", "-C", project.projectDir.absolutePath, "log",
|
||||||
|
"--format=tformat:%an <%ae>%n%cn <%ce>%n%(trailers:key=Co-authored-by,valueonly)",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val process = ProcessHelpers.startProcess("git", "check-mailmap", "--stdin")
|
||||||
|
BufferedWriter(OutputStreamWriter(process.outputStream)).use { writer ->
|
||||||
|
for (authorName in authors) {
|
||||||
|
var author = authorName
|
||||||
|
|
||||||
|
if (author.isEmpty()) continue
|
||||||
|
if (!author.endsWith(">")) author += ">" // Some commits have broken Co-Authored-By lines!
|
||||||
|
writer.write(author)
|
||||||
|
writer.newLine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val contributors: MutableSet<String> = HashSet()
|
||||||
|
for (authorLine in ProcessHelpers.captureLines(process)) {
|
||||||
|
val matcher = EMAIL.matcher(authorLine)
|
||||||
|
matcher.find()
|
||||||
|
val name = matcher.group(1)
|
||||||
|
if (!IGNORED_USERS.contains(name)) contributors.add(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
contributors.sortedWith(String.CASE_INSENSITIVE_ORDER)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun jacoco(task: NamedDomainObjectProvider<JavaExec>) {
|
||||||
|
val classDump = project.buildDir.resolve("jacocoClassDump/${task.name}")
|
||||||
|
val reportTaskName = "jacoco${task.name.capitalized()}Report"
|
||||||
|
|
||||||
|
val jacoco = project.extensions.getByType(JacocoPluginExtension::class.java)
|
||||||
|
task.configure {
|
||||||
|
finalizedBy(reportTaskName)
|
||||||
|
|
||||||
|
doFirst("Clean class dump directory") { fs.delete { delete(classDump) } }
|
||||||
|
|
||||||
|
jacoco.applyTo(this)
|
||||||
|
extensions.configure(JacocoTaskExtension::class.java) {
|
||||||
|
includes = listOf("dan200.computercraft.*")
|
||||||
|
classDumpDir = classDump
|
||||||
|
|
||||||
|
// Older versions of modlauncher don't include a protection domain (and thus no code
|
||||||
|
// source). Jacoco skips such classes by default, so we need to explicitly include them.
|
||||||
|
isIncludeNoLocationClasses = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register(reportTaskName, JacocoReport::class.java) {
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Generates code coverage report for the ${task.name} task."
|
||||||
|
|
||||||
|
executionData(task.get())
|
||||||
|
classDirectories.from(classDump)
|
||||||
|
|
||||||
|
// Don't want to use sourceSets(...) here as we have a custom class directory.
|
||||||
|
val sourceSets = project.extensions.getByType(SourceSetContainer::class.java)
|
||||||
|
sourceDirectories.from(sourceSets["main"].allSource.sourceDirectories)
|
||||||
|
}
|
||||||
|
|
||||||
|
project.extensions.configure(ReportingExtension::class.java) {
|
||||||
|
reports.register("${task.name}CodeCoverageReport", JacocoCoverageReport::class.java) {
|
||||||
|
testType.set(TestSuiteType.INTEGRATION_TEST)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val EMAIL = Pattern.compile("^([^<]+) <.+>$")
|
||||||
|
private val IGNORED_USERS = setOf(
|
||||||
|
"GitHub", "Daniel Ratcliffe", "Weblate",
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun <T> gitProvider(project: Project, supplier: () -> T): Provider<T> {
|
||||||
|
return project.provider {
|
||||||
|
try {
|
||||||
|
supplier()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
project.logger.error("Cannot read Git Repository", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures projects to match a shared configuration.
|
||||||
|
*/
|
||||||
|
class CCTweakedPlugin : Plugin<Project> {
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
project.extensions.create("cct", CCTweakedExtension::class.java)
|
||||||
|
}
|
||||||
|
}
|
65
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckChangelog.kt
Normal file
65
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckChangelog.kt
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the `changelog.md` and `whatsnew.md` files are well-formed.
|
||||||
|
*/
|
||||||
|
@CacheableTask
|
||||||
|
abstract class CheckChangelog : DefaultTask() {
|
||||||
|
init {
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Verifies the changelog and whatsnew file are consistent."
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val version: Property<String>
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:PathSensitive(PathSensitivity.NONE)
|
||||||
|
abstract val changelog: RegularFileProperty
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:PathSensitive(PathSensitivity.NONE)
|
||||||
|
abstract val whatsNew: RegularFileProperty
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun check() {
|
||||||
|
val version = version.get()
|
||||||
|
|
||||||
|
var ok = true
|
||||||
|
|
||||||
|
// Check we're targetting the current version
|
||||||
|
var whatsNew = whatsNew.get().asFile.readLines()
|
||||||
|
if (whatsNew[0] != "New features in CC: Tweaked $version") {
|
||||||
|
ok = false
|
||||||
|
logger.error("Expected `whatsnew.md' to target $version.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check "read more" exists and trim it
|
||||||
|
val idx = whatsNew.indexOfFirst { it == "Type \"help changelog\" to see the full version history." }
|
||||||
|
if (idx == -1) {
|
||||||
|
ok = false
|
||||||
|
logger.error("Must mention the changelog in whatsnew.md")
|
||||||
|
} else {
|
||||||
|
whatsNew = whatsNew.slice(0 until idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whatsnew and changelog match.
|
||||||
|
val expectedChangelog = sequenceOf("# ${whatsNew[0]}") + whatsNew.slice(1 until whatsNew.size).asSequence()
|
||||||
|
val changelog = changelog.get().asFile.readLines()
|
||||||
|
val mismatch = expectedChangelog.zip(changelog.asSequence()).filter { (a, b) -> a != b }.firstOrNull()
|
||||||
|
if (mismatch != null) {
|
||||||
|
ok = false
|
||||||
|
logger.error("whatsnew and changelog are not in sync")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) throw GradleException("Could not check release")
|
||||||
|
}
|
||||||
|
}
|
73
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckLicense.kt
Normal file
73
buildSrc/src/main/kotlin/cc/tweaked/gradle/CheckLicense.kt
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import com.diffplug.spotless.FormatterFunc
|
||||||
|
import com.diffplug.spotless.FormatterStep
|
||||||
|
import com.diffplug.spotless.generic.LicenseHeaderStep
|
||||||
|
import java.io.File
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to [LicenseHeaderStep], but supports multiple licenses.
|
||||||
|
*/
|
||||||
|
object LicenseHeader {
|
||||||
|
/**
|
||||||
|
* The current year to use in templates. Intentionally not dynamic to avoid failing the build.
|
||||||
|
*/
|
||||||
|
private const val YEAR = 2022
|
||||||
|
|
||||||
|
private val COMMENT = Regex("""^/\*(.*?)\*/\n?""", RegexOption.DOT_MATCHES_ALL)
|
||||||
|
|
||||||
|
fun create(api: File, main: File): FormatterStep = FormatterStep.createLazy(
|
||||||
|
"license",
|
||||||
|
{ Licenses(getTemplateText(api), getTemplateText(main)) },
|
||||||
|
{ state -> FormatterFunc.NeedsFile { contents, file -> formatFile(state, contents, file) } },
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun getTemplateText(file: File): String =
|
||||||
|
file.readText().trim().replace("\${year}", "$YEAR")
|
||||||
|
|
||||||
|
private fun formatFile(licenses: Licenses, contents: String, file: File): String {
|
||||||
|
val license = getLicense(contents)
|
||||||
|
val expectedLicense = getExpectedLicense(licenses, file.parentFile)
|
||||||
|
|
||||||
|
return when {
|
||||||
|
license == null -> setLicense(expectedLicense, contents)
|
||||||
|
license.second != expectedLicense -> setLicense(expectedLicense, contents, license.first)
|
||||||
|
else -> contents
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getExpectedLicense(licenses: Licenses, root: File): String {
|
||||||
|
var file: File? = root
|
||||||
|
while (file != null) {
|
||||||
|
if (file.name == "api" && file.parentFile?.name == "computercraft") return licenses.api
|
||||||
|
file = file.parentFile
|
||||||
|
}
|
||||||
|
return licenses.main
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLicense(contents: String): Pair<Int, String>? {
|
||||||
|
val match = COMMENT.find(contents) ?: return null
|
||||||
|
val license = match.groups[1]!!.value
|
||||||
|
.trim().lineSequence()
|
||||||
|
.map { it.trimStart(' ', '*') }
|
||||||
|
.joinToString("\n")
|
||||||
|
return Pair(match.range.last + 1, license)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setLicense(license: String, contents: String, start: Int = 0): String {
|
||||||
|
val out = StringBuilder()
|
||||||
|
out.append("/*\n")
|
||||||
|
for (line in license.lineSequence()) out.append(" * ").append(line).append("\n")
|
||||||
|
out.append(" */\n")
|
||||||
|
out.append(contents, start, contents.length)
|
||||||
|
return out.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class Licenses(val api: String, val main: String) : Serializable {
|
||||||
|
companion object {
|
||||||
|
private const val serialVersionUID: Long = 7741106448372435662L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
buildSrc/src/main/kotlin/cc/tweaked/gradle/Node.kt
Normal file
60
buildSrc/src/main/kotlin/cc/tweaked/gradle/Node.kt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.Directory
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class NodePlugin : Plugin<Project> {
|
||||||
|
override fun apply(project: Project) {
|
||||||
|
val extension = project.extensions.create("node", NodeExtension::class.java)
|
||||||
|
project.tasks.register(NpmInstall.TASK_NAME, NpmInstall::class.java) {
|
||||||
|
projectRoot.convention(extension.projectRoot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NodeExtension(project: Project) {
|
||||||
|
/** The directory containing `package-lock.json` and `node_modules/`. */
|
||||||
|
abstract val projectRoot: DirectoryProperty
|
||||||
|
|
||||||
|
init {
|
||||||
|
projectRoot.convention(project.layout.projectDirectory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Installs node modules as dependencies. */
|
||||||
|
abstract class NpmInstall : DefaultTask() {
|
||||||
|
@get:Internal
|
||||||
|
abstract val projectRoot: DirectoryProperty
|
||||||
|
|
||||||
|
@get:InputFile
|
||||||
|
@get:PathSensitive(PathSensitivity.NONE)
|
||||||
|
val packageLock: Provider<File> = projectRoot.file("package-lock.json").map { it.asFile }
|
||||||
|
|
||||||
|
@get:OutputDirectory
|
||||||
|
val nodeModules: Provider<Directory> = projectRoot.dir("node_modules")
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun install() {
|
||||||
|
project.exec {
|
||||||
|
commandLine("npm", "ci")
|
||||||
|
workingDir = projectRoot.get().asFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal const val TASK_NAME: String = "npmInstall"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NpxExecToDir : ExecToDir() {
|
||||||
|
init {
|
||||||
|
dependsOn(NpmInstall.TASK_NAME)
|
||||||
|
executable = "npx"
|
||||||
|
}
|
||||||
|
}
|
34
buildSrc/src/main/kotlin/cc/tweaked/gradle/ProcessHelpers.kt
Normal file
34
buildSrc/src/main/kotlin/cc/tweaked/gradle/ProcessHelpers.kt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package cc.tweaked.gradle
|
||||||
|
|
||||||
|
import org.codehaus.groovy.runtime.ProcessGroovyMethods
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
|
||||||
|
internal object ProcessHelpers {
|
||||||
|
fun startProcess(vararg command: String): Process {
|
||||||
|
// Something randomly passes in "GIT_DIR=" as an environment variable which clobbers everything else. Don't
|
||||||
|
// inherit the environment array!
|
||||||
|
return Runtime.getRuntime().exec(command, arrayOfNulls(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun captureOut(vararg command: String): String {
|
||||||
|
val process = startProcess(*command)
|
||||||
|
val result = ProcessGroovyMethods.getText(process)
|
||||||
|
if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun captureLines(vararg command: String): List<String> {
|
||||||
|
return captureLines(startProcess(*command))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun captureLines(process: Process): List<String> {
|
||||||
|
val out = BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
|
||||||
|
reader.lines().filter { it.isNotEmpty() }.toList()
|
||||||
|
}
|
||||||
|
ProcessGroovyMethods.closeStreams(process)
|
||||||
|
if (process.waitFor() != 0) throw IOException("Command exited with a non-0 status")
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
61
doc/mod-page.md
Normal file
61
doc/mod-page.md
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# 
|
||||||
|
CC: Tweaked is a mod for Minecraft which adds programmable computers, turtles and more to the game. A fork of the much-beloved [ComputerCraft], it continues its legacy with better performance, stability, and a wealth of new features.
|
||||||
|
|
||||||
|
**Fabric support is added by the [CC: Restitched][ccrestitched] project**
|
||||||
|
|
||||||
|
## Testimonials
|
||||||
|
|
||||||
|
> I'm not sure what that is [...] I don't know where that came from.
|
||||||
|
>
|
||||||
|
> \- [direwolf20, December 2020](https://youtu.be/D8Ue9I-SKeM?t=980)
|
||||||
|
|
||||||
|
> It is basically ComputerCraft. It has the turtles, and the computers, and writing Lua programs and all that stuff.
|
||||||
|
>
|
||||||
|
> \- [direwolf20, May 2022](https://youtu.be/7Ruq33XmQIQ?t=537)
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
Controlled using the [Lua programming language][lua], CC: Tweaked's computers provides all the tools you need to start
|
||||||
|
writing code and automating your Minecraft world.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
While computers are incredibly powerful, they're rather limited by their inability to move about. *Turtles* are the
|
||||||
|
solution here. They can move about the world, placing and breaking blocks, swinging a sword to protect you from zombies,
|
||||||
|
or whatever else you program them to!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Not all problems can be solved with a pickaxe though, and so CC: Tweaked also provides a bunch of additional peripherals
|
||||||
|
for your computers. You can play a tune with speakers, display text or images on a monitor, connect all your
|
||||||
|
computers together with modems, and much more.
|
||||||
|
|
||||||
|
Computers can now also interact with inventories such as chests, allowing you to build complex inventory and item
|
||||||
|
management systems.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
While ComputerCraft is lovely for both experienced programmers and for people who have never coded before, it can be a
|
||||||
|
little daunting getting started. Thankfully, there's several fantastic tutorials out there:
|
||||||
|
|
||||||
|
- [Direwolf20's ComputerCraft tutorials](https://www.youtube.com/watch?v=wrUHUhfCY5A "ComputerCraft Tutorial Episode 1 - HELP! and Hello World")
|
||||||
|
- [Sethbling's ComputerCraft series](https://www.youtube.com/watch?v=DSsx4VSe-Uk "Programming Tutorial with Minecraft Turtles -- Ep. 1: Intro to Turtles and If-Then-Else_End")
|
||||||
|
- [Lyqyd's Computer Basics 1](http://www.computercraft.info/forums2/index.php?/topic/15033-computer-basics-i/ "Computer Basics I")
|
||||||
|
|
||||||
|
Once you're a little more familiar with the mod, the [wiki](https://tweaked.cc/) provides more detailed documentation on the
|
||||||
|
various APIs and peripherals provided by the mod.
|
||||||
|
|
||||||
|
If you get stuck, do [ask a question on GitHub][GitHub Discussions] or pop in to the ComputerCraft's [IRC channel][IRC].
|
||||||
|
|
||||||
|
## Get Involved
|
||||||
|
CC: Tweaked lives on [GitHub]. If you've got any ideas, feedback or bugs please do [create an issue][bug].
|
||||||
|
|
||||||
|
[github]: https://github.com/cc-tweaked/CC-Tweaked/ "CC: Tweaked on GitHub"
|
||||||
|
[bug]: https://github.com/cc-tweaked/CC-Tweaked/issues/new/choose
|
||||||
|
[computercraft]: https://github.com/dan200/ComputerCraft "ComputerCraft on GitHub"
|
||||||
|
[forge]: https://files.minecraftforge.net/ "Download Minecraft Forge."
|
||||||
|
[ccrestitched]: https://modrinth.com/mod/cc-restitched "Download CC: Restitched from Modrinth"
|
||||||
|
[lua]: https://www.lua.org/ "Lua's main website"
|
||||||
|
[GitHub Discussions]: https://github.com/cc-tweaked/CC-Tweaked/discussions
|
||||||
|
[IRC]: http://webchat.esper.net/?channels=computercraft "#computercraft on EsperNet"
|
@ -1,11 +1,11 @@
|
|||||||
org.gradle.jvmargs=-Xmx3G
|
org.gradle.jvmargs=-Xmx3G
|
||||||
|
org.gradle.parallel=true
|
||||||
|
|
||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
|
kotlin.jvm.target.validation.mode=error
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version=1.100.10
|
modVersion=1.100.10
|
||||||
|
|
||||||
# Minecraft properties (update mods.toml when changing)
|
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||||
mc_version=1.16.5
|
mcVersion=1.16.5
|
||||||
mapping_version=2021.08.08
|
|
||||||
forge_version=36.2.34
|
|
||||||
# NO SERIOUSLY, UPDATE mods.toml WHEN CHANGING
|
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
|
# Minecraft
|
||||||
|
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
||||||
|
forge = "36.2.34"
|
||||||
|
parchment = "2021.08.08"
|
||||||
|
parchmentMc = "1.16.5"
|
||||||
|
|
||||||
autoService = "1.0.1"
|
autoService = "1.0.1"
|
||||||
|
cobalt = { strictly = "[0.5.7,0.6.0)", prefer = "0.5.7" }
|
||||||
jetbrainsAnnotations = "23.0.0"
|
jetbrainsAnnotations = "23.0.0"
|
||||||
kotlin = "1.7.10"
|
kotlin = "1.7.10"
|
||||||
kotlin-coroutines = "1.6.0"
|
kotlin-coroutines = "1.6.0"
|
||||||
@ -9,8 +17,23 @@ hamcrest = "2.2"
|
|||||||
jqwik = "1.7.0"
|
jqwik = "1.7.0"
|
||||||
junit = "5.9.1"
|
junit = "5.9.1"
|
||||||
|
|
||||||
|
# Build tools
|
||||||
|
cctJavadoc = "1.5.0"
|
||||||
|
checkstyle = "8.25" # There's a reason we're pinned on an ancient version, but I can't remember what it is.
|
||||||
|
curseForgeGradle = "1.0.11"
|
||||||
|
forgeGradle = "5.1.+"
|
||||||
|
githubRelease = "2.2.12"
|
||||||
|
illuaminate = "0.1.0-3-g0f40379"
|
||||||
|
librarian = "1.+"
|
||||||
|
minotaur = "2.+"
|
||||||
|
mixinGradle = "0.7.+"
|
||||||
|
shadow = "7.1.2"
|
||||||
|
spotless = "6.8.0"
|
||||||
|
taskTree = "2.1.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }
|
||||||
|
cobalt = { module = "org.squiddev:Cobalt", version.ref = "cobalt" }
|
||||||
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
jetbrainsAnnotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" }
|
||||||
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
|
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" }
|
||||||
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
|
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
|
||||||
@ -23,6 +46,22 @@ junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.re
|
|||||||
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
|
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
|
||||||
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
|
||||||
|
|
||||||
|
# Build tools
|
||||||
|
cctJavadoc = { module = "cc.tweaked:cct-javadoc", version.ref = "cctJavadoc" }
|
||||||
|
checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
||||||
|
spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" }
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
|
taskTree = { id = "com.dorongold.task-tree", version.ref = "taskTree" }
|
||||||
|
curseForgeGradle = { id = "net.darkhax.curseforgegradle", version.ref = "curseForgeGradle" }
|
||||||
|
mixinGradle = { id = "org.spongepowered.mixin", version.ref = "mixinGradle" }
|
||||||
|
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }
|
||||||
|
githubRelease = { id = "com.github.breadmoirai.github-release", version.ref = "githubRelease" }
|
||||||
|
forgeGradle = { id = "net.minecraftforge.gradle", version.ref = "forgeGradle" }
|
||||||
|
librarian = { id = "org.parchmentmc.librarian.forgegradle", version.ref = "librarian" }
|
||||||
|
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
|
|
||||||
(doc
|
(doc
|
||||||
(destination build/docs/lua)
|
(destination build/illuaminate)
|
||||||
(index doc/index.md)
|
(index doc/index.md)
|
||||||
|
|
||||||
(site
|
(site
|
||||||
|
@ -13,5 +13,5 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val mc_version: String by settings
|
val mcVersion: String by settings
|
||||||
rootProject.name = "cc-tweaked-${mc_version}"
|
rootProject.name = "cc-tweaked-$mcVersion"
|
||||||
|
@ -11,7 +11,7 @@ license="ComputerCraft Public License (https://raw.githubusercontent.com/dan200/
|
|||||||
|
|
||||||
[[mods]]
|
[[mods]]
|
||||||
modId="computercraft"
|
modId="computercraft"
|
||||||
version="${version}"
|
version="${file.jarVersion}"
|
||||||
displayName="CC: Tweaked"
|
displayName="CC: Tweaked"
|
||||||
description='''
|
description='''
|
||||||
CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.
|
CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.
|
||||||
@ -20,6 +20,6 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a
|
|||||||
[[dependencies.computercraft]]
|
[[dependencies.computercraft]]
|
||||||
modId="forge"
|
modId="forge"
|
||||||
mandatory=true
|
mandatory=true
|
||||||
versionRange="[36.2.34,37)"
|
versionRange="[${forgeVersion},37)"
|
||||||
ordering="NONE"
|
ordering="NONE"
|
||||||
side="BOTH"
|
side="BOTH"
|
||||||
|
@ -12,4 +12,4 @@ Follow @DanTwoHundred on Twitter!
|
|||||||
To help contribute to ComputerCraft, browse the source code at https://github.com/dan200/ComputerCraft.
|
To help contribute to ComputerCraft, browse the source code at https://github.com/dan200/ComputerCraft.
|
||||||
|
|
||||||
GitHub Contributors:
|
GitHub Contributors:
|
||||||
${gitcontributors}
|
${gitContributors}
|
||||||
|
@ -19,7 +19,6 @@ import kotlin.time.Duration
|
|||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
|
|
||||||
|
|
||||||
abstract class NullApiEnvironment : IAPIEnvironment {
|
abstract class NullApiEnvironment : IAPIEnvironment {
|
||||||
private val computerEnv = BasicEnvironment()
|
private val computerEnv = BasicEnvironment()
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ class TestHttpApi {
|
|||||||
ComputerCraft.httpRules = Collections.unmodifiableList(
|
ComputerCraft.httpRules = Collections.unmodifiableList(
|
||||||
listOf(
|
listOf(
|
||||||
AddressRule.parse("\$private", null, Action.DENY.toPartial()),
|
AddressRule.parse("\$private", null, Action.DENY.toPartial()),
|
||||||
AddressRule.parse("*", null, Action.ALLOW.toPartial())
|
AddressRule.parse("*", null, Action.ALLOW.toPartial()),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@ class Computer_Test {
|
|||||||
context.assertBlockState(
|
context.assertBlockState(
|
||||||
lamp,
|
lamp,
|
||||||
{ !it.getValue(RedstoneLampBlock.LIT) },
|
{ !it.getValue(RedstoneLampBlock.LIT) },
|
||||||
{ "Lamp should still not be lit" })
|
{ "Lamp should still not be lit" },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,10 +15,14 @@ class Modem_Test {
|
|||||||
this
|
this
|
||||||
.thenComputerOk(marker = "initial")
|
.thenComputerOk(marker = "initial")
|
||||||
.thenExecute {
|
.thenExecute {
|
||||||
helper.setBlock(position, BlockCable.correctConnections(
|
helper.setBlock(
|
||||||
helper.level, helper.absolutePos(position),
|
position,
|
||||||
Registry.ModBlocks.CABLE.get().defaultBlockState().setValue(BlockCable.CABLE, true)
|
BlockCable.correctConnections(
|
||||||
))
|
helper.level,
|
||||||
|
helper.absolutePos(position),
|
||||||
|
Registry.ModBlocks.CABLE.get().defaultBlockState().setValue(BlockCable.CABLE, true),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.thenComputerOk()
|
.thenComputerOk()
|
||||||
}
|
}
|
@ -24,7 +24,7 @@ class Monitor_Test {
|
|||||||
val toSet = BlockStateInput(
|
val toSet = BlockStateInput(
|
||||||
Registry.ModBlocks.MONITOR_ADVANCED.get().defaultBlockState(),
|
Registry.ModBlocks.MONITOR_ADVANCED.get().defaultBlockState(),
|
||||||
Collections.emptySet(),
|
Collections.emptySet(),
|
||||||
tag
|
tag,
|
||||||
)
|
)
|
||||||
|
|
||||||
context.setBlock(pos, Blocks.AIR.defaultBlockState())
|
context.setBlock(pos, Blocks.AIR.defaultBlockState())
|
@ -2,7 +2,7 @@ package dan200.computercraft.ingame
|
|||||||
|
|
||||||
import dan200.computercraft.ingame.api.*
|
import dan200.computercraft.ingame.api.*
|
||||||
|
|
||||||
class PrintoutTest {
|
class Printout_Test {
|
||||||
@GameTest(batch = "client:Printout_Test.In_frame_at_night", timeoutTicks = Timeouts.CLIENT_TIMEOUT)
|
@GameTest(batch = "client:Printout_Test.In_frame_at_night", timeoutTicks = Timeouts.CLIENT_TIMEOUT)
|
||||||
fun In_frame_at_night(helper: GameTestHelper) = helper.sequence {
|
fun In_frame_at_night(helper: GameTestHelper) = helper.sequence {
|
||||||
this
|
this
|
@ -86,9 +86,9 @@ class Turtle_Test {
|
|||||||
DetailRegistries.ITEM_STACK.addProvider(
|
DetailRegistries.ITEM_STACK.addProvider(
|
||||||
object : BasicItemDetailProvider<ItemPrintout>("printout", ItemPrintout::class.java) {
|
object : BasicItemDetailProvider<ItemPrintout>("printout", ItemPrintout::class.java) {
|
||||||
override fun provideDetails(data: MutableMap<in String, Any>, stack: ItemStack, item: ItemPrintout) {
|
override fun provideDetails(data: MutableMap<in String, Any>, stack: ItemStack, item: ItemPrintout) {
|
||||||
data["type"] = item.type.toString();
|
data["type"] = item.type.toString()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.thenComputerOk()
|
.thenComputerOk()
|
@ -79,7 +79,8 @@ typealias GameTestSequence = TestList
|
|||||||
|
|
||||||
typealias GameTestAssertException = RuntimeException
|
typealias GameTestAssertException = RuntimeException
|
||||||
|
|
||||||
private fun GameTestSequence.addResult(task: () -> Unit, delay: Long? = null): GameTestSequence {
|
private fun GameTestSequence.addResult(task: () -> Unit) = addResult(null, task)
|
||||||
|
private fun GameTestSequence.addResult(delay: Long?, task: () -> Unit): GameTestSequence {
|
||||||
val result = UnsafeHacks.newInstance(TestTickResult::class.java) as TestTickResult
|
val result = UnsafeHacks.newInstance(TestTickResult::class.java) as TestTickResult
|
||||||
result.assertion = Runnable(task)
|
result.assertion = Runnable(task)
|
||||||
result.expectedDelay = delay
|
result.expectedDelay = delay
|
||||||
@ -88,29 +89,29 @@ private fun GameTestSequence.addResult(task: () -> Unit, delay: Long? = null): G
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun GameTestSequence.thenSucceed() {
|
fun GameTestSequence.thenSucceed() {
|
||||||
addResult({
|
addResult {
|
||||||
if (parent.error != null) return@addResult
|
if (parent.error != null) return@addResult
|
||||||
|
|
||||||
parent.finish()
|
parent.finish()
|
||||||
parent.markAsComplete()
|
parent.markAsComplete()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun GameTestSequence.thenWaitUntil(task: () -> Unit) = addResult(task)
|
fun GameTestSequence.thenWaitUntil(task: () -> Unit) = addResult(task)
|
||||||
|
|
||||||
fun GameTestSequence.thenExecute(task: () -> Unit) = addResult({
|
fun GameTestSequence.thenExecute(task: () -> Unit) = addResult {
|
||||||
try {
|
try {
|
||||||
task()
|
task()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
parent.fail(e)
|
parent.fail(e)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
fun GameTestSequence.thenIdle(delay: Long) = addResult({
|
fun GameTestSequence.thenIdle(delay: Long) = addResult {
|
||||||
if (parent.tickCount < lastTick + delay) {
|
if (parent.tickCount < lastTick + delay) {
|
||||||
throw GameTestAssertException("Waiting")
|
throw GameTestAssertException("Waiting")
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proguard strips out all the "on success" code as it's never called anywhere. This is workable most of the time, but
|
* Proguard strips out all the "on success" code as it's never called anywhere. This is workable most of the time, but
|
||||||
|
@ -99,7 +99,7 @@ fun GameTestSequence.thenScreenshot(name: String? = null): GameTestSequence {
|
|||||||
val screenshotPath = screenshotsPath.resolve("$fullName.png")
|
val screenshotPath = screenshotsPath.resolve("$fullName.png")
|
||||||
val originalPath = TestMod.sourceDir.resolve("screenshots").resolve("$fullName.png")
|
val originalPath = TestMod.sourceDir.resolve("screenshots").resolve("$fullName.png")
|
||||||
|
|
||||||
if (!Files.exists(originalPath)) throw GameTestAssertException("$fullName does not exist. Use `/cctest promote' to create it.");
|
if (!Files.exists(originalPath)) throw GameTestAssertException("$fullName does not exist. Use `/cctest promote' to create it.")
|
||||||
|
|
||||||
val screenshot = ImageIO.read(screenshotPath.toFile())
|
val screenshot = ImageIO.read(screenshotPath.toFile())
|
||||||
?: throw GameTestAssertException("Error reading screenshot from $screenshotPath")
|
?: throw GameTestAssertException("Error reading screenshot from $screenshotPath")
|
||||||
@ -147,14 +147,16 @@ fun GameTestHelper.positionAtArmorStand() {
|
|||||||
player.connection.teleport(stand.x, stand.y, stand.z, stand.yRot, stand.xRot)
|
player.connection.teleport(stand.x, stand.y, stand.z, stand.yRot, stand.xRot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ClientTestHelper {
|
class ClientTestHelper {
|
||||||
val minecraft: Minecraft = Minecraft.getInstance()
|
val minecraft: Minecraft = Minecraft.getInstance()
|
||||||
|
|
||||||
fun screenshot(name: String, callback: () -> Unit = {}) {
|
fun screenshot(name: String, callback: () -> Unit = {}) {
|
||||||
ScreenShotHelper.grab(
|
ScreenShotHelper.grab(
|
||||||
minecraft.gameDirectory, name,
|
minecraft.gameDirectory,
|
||||||
minecraft.window.width, minecraft.window.height, minecraft.mainRenderTarget
|
name,
|
||||||
|
minecraft.window.width,
|
||||||
|
minecraft.window.height,
|
||||||
|
minecraft.mainRenderTarget,
|
||||||
) {
|
) {
|
||||||
TestMod.log.info(it.string)
|
TestMod.log.info(it.string)
|
||||||
callback()
|
callback()
|
||||||
|
@ -24,7 +24,7 @@ import { DataExport, WithExport } from "./components/WithExport.js";
|
|||||||
const glob = promisify(globModule);
|
const glob = promisify(globModule);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const base = "build/docs/lua";
|
const base = "build/illuaminate";
|
||||||
|
|
||||||
const processor = unified()
|
const processor = unified()
|
||||||
.use(rehypeParse, { emitParseErrors: true })
|
.use(rehypeParse, { emitParseErrors: true })
|
||||||
@ -46,7 +46,7 @@ const glob = promisify(globModule);
|
|||||||
|
|
||||||
const { result } = await processor.process(contents);
|
const { result } = await processor.process(contents);
|
||||||
|
|
||||||
const outputPath = path.resolve("build/docs/site", path.relative(base, file));
|
const outputPath = path.resolve("build/jsxDocs", path.relative(base, file));
|
||||||
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
||||||
await fs.writeFile(outputPath, "<!doctype HTML>" + renderToStaticMarkup(<WithExport data={dataExport}>{result}</WithExport>));
|
await fs.writeFile(outputPath, "<!doctype HTML>" + renderToStaticMarkup(<WithExport data={dataExport}>{result}</WithExport>));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user