mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +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:
		| @@ -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>)); | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates