Merge branch '1.19.3' into 1.19.2

This commit is contained in:
DBotThePony 2024-01-01 23:06:05 +07:00
commit 9956aa1ba4
Signed by: DBot
GPG Key ID: DCC23B5715498507
1435 changed files with 72859 additions and 34736 deletions

View File

@ -1,4 +1,4 @@
### Licensing exclusions/External copyrighted material ### Licensing exclusions/External copyrighted material
Shockwave landing sound: [ULTRAKILL Game](https://store.steampowered.com/app/1229490/), ARR, got permission to use in mod Shockwave landing and projectile punch sounds: [ULTRAKILL Game](https://store.steampowered.com/app/1229490/), ARR, got permission to use in mod

View File

@ -5,19 +5,21 @@ Minecraft mod with science fiction style, about matter, and energy, combined.
### Required mods ### Required mods
* [Kotlin for Forge](https://www.curseforge.com/minecraft/mc-mods/kotlin-for-forge) or have Kotlin standard library in classpath * [Kotlin for Forge](https://www.curseforge.com/minecraft/mc-mods/kotlin-for-forge) or have Kotlin standard library in classpath (at least 1.8.0 is required)
### Recommended mods ### Recommended mods
* [Ferrite Core](https://www.curseforge.com/minecraft/mc-mods/ferritecore), reduces memory usage * [Ferrite Core](https://www.curseforge.com/minecraft/mc-mods/ferritecore), reduces memory usage
* In case of Overdrive That Matters, ***greatly*** reduces JVM heap bloat caused by model data being duplicated * In case of Overdrive That Matters, ***greatly*** reduces JVM heap bloat caused by model data being duplicated
### Supported mods * Particle Collider, reduces world join time
### Mods with special compatibility code
* [Mekanism](https://www.curseforge.com/minecraft/mc-mods/Mekanism) (full duplex Mekanism Joules support, QIO)
* [Curios](https://www.curseforge.com/minecraft/mc-mods/curios) (GUI support, technical inventory access)
* [Cosmetic Armor Reworked](https://www.curseforge.com/minecraft/mc-mods/cosmetic-armor-reworked) (GUI support, technical inventory access)
* [JEI](https://www.curseforge.com/minecraft/mc-mods/jei) * [JEI](https://www.curseforge.com/minecraft/mc-mods/jei)
* [Mekanism](https://www.curseforge.com/minecraft/mc-mods/Mekanism)
* [Curios](https://www.curseforge.com/minecraft/mc-mods/curios)
* [Cosmetic Armor Reworked](https://www.curseforge.com/minecraft/mc-mods/cosmetic-armor-reworked)
---- ----

View File

@ -1,11 +1,8 @@
import groovy.lang.Closure
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.util.Date import java.util.Date
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import kotlin.text.Regex
import java.util.UUID
import org.spongepowered.asm.gradle.plugins.MixinExtension
val mod_version: String by project val mod_version: String by project
val mc_version: String by project val mc_version: String by project
@ -13,7 +10,7 @@ val forge_version: String by project
val mod_id: String by project val mod_id: String by project
val handle_deps: String by project val handle_deps: String by project
val use_commit_hash_in_version: String by project val use_commit_hash_in_version: String by project
val handleDeps = handle_deps == "true" val handleDeps = handle_deps.toBoolean()
plugins { plugins {
java java
@ -23,13 +20,7 @@ plugins {
id("org.spongepowered.mixin") id("org.spongepowered.mixin")
} }
configurations { data class GitInfo(val version: String, val tag: String, val buildNumber: String) {
create("library") // non-mod libraries
create("klibrary") // kotlin libs
get("implementation").extendsFrom(get("library"), get("klibrary"))
}
data class GitInfo(val version: String, val count: String, val tag: String) {
// val tagIsVersion: Boolean get() = tag != "" && tag.matches(Regex("v[0-9]+\\.[0-9]\\.[0-9]")) // val tagIsVersion: Boolean get() = tag != "" && tag.matches(Regex("v[0-9]+\\.[0-9]\\.[0-9]"))
val publishVersion: String get() { val publishVersion: String get() {
@ -40,28 +31,23 @@ data class GitInfo(val version: String, val count: String, val tag: String) {
} }
val jarName: String get() { val jarName: String get() {
val buildNumber = if (buildNumber != "") "-$buildNumber" else ""
if (tag != "") if (tag != "")
return "$mod_version-$version" return "$mod_version-$version$buildNumber"
// if (count != "") // if (count != "")
// return "$mod_version-SNAPSHOT-${version}_$count" // return "$mod_version-SNAPSHOT-${version}_$count"
if (version != "") { if (version != "") {
return "$mod_version-SNAPSHOT-$version" return "$mod_version-SNAPSHOT-$version$buildNumber"
} else { } else {
return "$mod_version-SNAPSHOT" return "$mod_version-SNAPSHOT$buildNumber"
} }
} }
val modVersion: String get() { val modVersion: String get() {
if (tag != "") return if (buildNumber != "") "$mod_version.$buildNumber" else mod_version
return mod_version
if (version != "") {
return "$mod_version-SNAPSHOT-$version"
} else {
return "$mod_version-SNAPSHOT"
}
} }
} }
@ -74,7 +60,6 @@ fun getCommitVersion(): GitInfo? {
try { try {
val versionStream = FastByteArrayOutputStream() val versionStream = FastByteArrayOutputStream()
val tagStream = FastByteArrayOutputStream() val tagStream = FastByteArrayOutputStream()
val countStream = FastByteArrayOutputStream()
val gotVersion = exec { val gotVersion = exec {
commandLine("git", "rev-parse", "--short", "HEAD") commandLine("git", "rev-parse", "--short", "HEAD")
@ -82,27 +67,20 @@ fun getCommitVersion(): GitInfo? {
standardOutput = versionStream standardOutput = versionStream
}.exitValue == 0 }.exitValue == 0
val gotCount = exec {
commandLine("git", "rev-list", "--count", "HEAD")
workingDir(".")
standardOutput = countStream
}.exitValue == 0
val gotTag = exec { val gotTag = exec {
commandLine("git", "tag", "--points-at", "HEAD") commandLine("git", "tag", "--points-at", "HEAD")
workingDir(".") workingDir(".")
standardOutput = tagStream standardOutput = tagStream
}.exitValue == 0 }.exitValue == 0
if (!gotVersion || !gotCount || !gotTag) { if (!gotVersion || !gotTag) {
return null return null
} }
val version = versionStream.array.copyOfRange(0, versionStream.length).toString(Charsets.UTF_8).trim() val version = versionStream.array.copyOfRange(0, versionStream.length).toString(Charsets.UTF_8).trim()
val tag = tagStream.array.copyOfRange(0, tagStream.length).toString(Charsets.UTF_8).trim() val tag = tagStream.array.copyOfRange(0, tagStream.length).toString(Charsets.UTF_8).trim()
val count = countStream.array.copyOfRange(0, countStream.length).toString(Charsets.UTF_8).trim()
return GitInfo(version, count, tag) return GitInfo(version, tag, System.getenv("BUILD_NUMBER") ?: "")
} catch(err: Throwable) { } catch(err: Throwable) {
println("Error getting git version") println("Error getting git version")
println(err) println(err)
@ -143,10 +121,7 @@ tasks.test {
dependencies { dependencies {
val jupiter_version: String by project val jupiter_version: String by project
val kotlin_version: String by project
val kotlin_for_forge_version: String by project val kotlin_for_forge_version: String by project
val kotlin_coroutines_version: String by project
val kotlin_serialization_version: String by project
val mixin_version: String by project val mixin_version: String by project
minecraft("net.minecraftforge:forge:$mc_version-$forge_version") minecraft("net.minecraftforge:forge:$mc_version-$forge_version")
@ -154,72 +129,74 @@ dependencies {
implementation("thedarkcolour:kotlinforforge:$kotlin_for_forge_version") implementation("thedarkcolour:kotlinforforge:$kotlin_for_forge_version")
fun library(notation: Any) { this.add("library", notation) }
fun klibrary(notation: Any) { this.add("klibrary", notation) }
val excludeKGroup = closureOf<Any> {
(this as ExternalModuleDependency).exclude(group = "org.jetbrains", module = "annotations")
} as Closure<Any>
// Add everything to the classpath correctly
klibrary(create("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version", excludeKGroup))
klibrary(create("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version", excludeKGroup))
klibrary(create("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version", excludeKGroup))
klibrary(create("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlin_coroutines_version", excludeKGroup))
klibrary(create("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlin_serialization_version", excludeKGroup))
// Real mod deobf dependency examples - these get remapped to your current mappings
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency
// runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency
// implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency
// Examples using mod jars from ./libs
compileOnly("yalter.mousetweaks:MouseTweaks:2.23:api") compileOnly("yalter.mousetweaks:MouseTweaks:2.23:api")
annotationProcessor("org.spongepowered:mixin:${mixin_version}:processor") annotationProcessor("org.spongepowered:mixin:${mixin_version}:processor")
// compile against the JEI API but do not include it at runtime
//compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api")
// at runtime, use the full JEI jar
//runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}")
if (handleDeps) { if (handleDeps) {
val jei_version: String by project val jei_version: String by project
val mekanism_version: String by project val cosmetic_armor_reworked_id: String by project
val curios_version: String by project
val cosmetic_armor_reworked_version: String by project
val jade_id: String by project val jade_id: String by project
val configured_id: String by project val configured_id: String by project
val worldedit_fileid: String by project val curios_version: String by project
val more_overlays_version: String by project val jei_mc_version: String by project
val resourceful_lib_id: String by project
val resourceful_config_id: String by project
val botarium_id: String by project
val ad_astra_id: String by project
implementation(fg.deobf("top.theillusivec4.curios:curios-forge:${mc_version}-${curios_version}")) compileOnly(fg.deobf("curse.maven:curios-309927:${curios_version}"))
compileOnly(fg.deobf("lain.mods.cos:CosmeticArmorReworked:${mc_version}-${cosmetic_armor_reworked_version}")) compileOnly(fg.deobf("curse.maven:cosmetic-armor-reworked-237307:$cosmetic_armor_reworked_id"))
compileOnly(fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")) compileOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-common-api:${jei_version}"))
compileOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}")) compileOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-forge-api:${jei_version}"))
runtimeOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}")) // runtimeOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-forge:${jei_version}"))
// implementation("mcjty:theoneprobe:${mc_version}-${the_one_probe_version}:deobf")
// runtimeOnly(fg.deobf("ru.dbotthepony:particle-collider:0.4.5"))
compileOnly(fg.deobf("curse.maven:jade-324717:${jade_id}"))
//runtimeOnly(fg.deobf("curse.maven:configured-457570:${configured_id}"))
compileOnly(fg.deobf("curse.maven:resourceful-lib-570073:${resourceful_lib_id}"))
compileOnly(fg.deobf("curse.maven:resourceful-config-714059:${resourceful_config_id}"))
compileOnly(fg.deobf("curse.maven:botarium-704113:${botarium_id}"))
compileOnly(fg.deobf("curse.maven:ad-astra-635042:${ad_astra_id}"))
runtimeOnly(fg.deobf("curse.maven:jade-324717:${jade_id}"))
runtimeOnly(fg.deobf("curse.maven:configured-457570:${configured_id}"))
// runtimeOnly(fg.deobf("curse.maven:worldedit-225608:${worldedit_fileid}")) // runtimeOnly(fg.deobf("curse.maven:worldedit-225608:${worldedit_fileid}"))
// runtimeOnly(fg.deobf("at.ridgo8.moreoverlays:MoreOverlays-updated:${more_overlays_version}")) // runtimeOnly(fg.deobf("at.ridgo8.moreoverlays:MoreOverlays-updated:${more_overlays_version}"))
compileOnly(fg.deobf("mekanism:Mekanism:${mc_version}-${mekanism_version}:all")) // runtimeOnly(fg.deobf("curse.maven:cyclops-core-232758:4392602"))
// runtimeOnly(fg.deobf("curse.maven:integrated-dynamics-236307:4391535"))
// runtimeOnly(fg.deobf("curse.maven:integrated-crafting-287357:4391487"))
// runtimeOnly(fg.deobf("curse.maven:integrated-terminals-295910:4400924"))
// runtimeOnly(fg.deobf("curse.maven:common-capabilities-247007:4391468"))
// runtimeOnly(fg.deobf("curse.maven:integrated-tunnels-251389:4344632"))
} }
} }
configurations { configurations {
getByName("dataImplementation").extendsFrom(getByName("implementation")) getByName("dataImplementation").extendsFrom(getByName("implementation"))
getByName("library").resolutionStrategy.cacheChangingModulesFor(10, "minutes")
} }
minecraft { minecraft {
mappings("official", mc_version) mappings("official", mc_version)
copyIdeResources.set(true)
accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg")) accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg"))
runs { runs {
configureEach {
workingDirectory = project.file("run").absolutePath
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property("forge.logging.markers", "REGISTRIES")
// Log4j console level
property("forge.logging.console.level", "debug")
}
create("client") { create("client") {
mods { mods {
create(mod_id) { create(mod_id) {
@ -239,25 +216,13 @@ minecraft {
val originalUsername = usernameStream.array.copyOfRange(0, usernameStream.length).toString(Charsets.UTF_8).trim() val originalUsername = usernameStream.array.copyOfRange(0, usernameStream.length).toString(Charsets.UTF_8).trim()
if (originalUsername.isNotEmpty()) { if (originalUsername.isNotEmpty()) {
var username = originalUsername args("--username", originalUsername)
var speculatedUUID = UUID.nameUUIDFromBytes("OfflinePlayer:$username".toByteArray(Charsets.UTF_8))
var counter = 1
while (speculatedUUID.hashCode() and 1 == 1) {
username = originalUsername + "_".repeat(counter)
speculatedUUID = UUID.nameUUIDFromBytes("OfflinePlayer:$username".toByteArray(Charsets.UTF_8))
counter++
}
args("--username", username)
} else { } else {
args("--username", "Dev_${System.getProperty("user.name")}") args("--username", "Dev_${System.getProperty("user.name")}")
} }
} else { } else {
args("--username", "Dev_${System.getProperty("user.name")}") args("--username", "Dev_${System.getProperty("user.name")}")
} }
args("-mixin.config=$mod_id.mixins.json")
} }
create("server") { create("server") {
@ -267,7 +232,7 @@ minecraft {
} }
} }
args("nogui", "-mixin.config=$mod_id.mixins.json") args("nogui")
} }
create("data") { create("data") {
@ -278,8 +243,6 @@ minecraft {
sources(sourceSets["main"], sourceSets["data"]) sources(sourceSets["main"], sourceSets["data"])
} }
} }
forceExit(false)
} }
} }
} }
@ -287,28 +250,7 @@ minecraft {
mixin { mixin {
add(sourceSets.main.get(), "$mod_id.refmap.json") add(sourceSets.main.get(), "$mod_id.refmap.json")
config("$mod_id.mixins.json") config("$mod_id.mixins.json")
} config("$mod_id.ad_astra.mixins.json")
minecraft.runs.all {
workingDirectory = project.file("run").absolutePath
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property("forge.logging.markers", "REGISTRIES")
// Log4j console level
property("forge.logging.console.level", "debug")
lazyToken("minecraft_classpath") {
configurations["library"]
.copyRecursive()
.resolve()
.map { it.absolutePath }
.toMutableList()
.also { it.addAll(configurations["klibrary"].copyRecursive().resolve().map { it.absolutePath }) }
.joinToString(File.pathSeparator)
}
} }
repositories { repositories {
@ -321,11 +263,11 @@ repositories {
url = uri("https://maven.dbotthepony.ru") url = uri("https://maven.dbotthepony.ru")
content { content {
includeGroup("top.theillusivec4.curios")
includeGroup("yalter.mousetweaks") includeGroup("yalter.mousetweaks")
includeGroup("mekanism") includeGroup("mekanism")
includeGroup("lain.mods.cos") includeGroup("lain.mods.cos")
includeGroup("at.ridgo8.moreoverlays") includeGroup("at.ridgo8.moreoverlays")
includeGroup("ru.dbotthepony")
} }
} }
@ -349,14 +291,22 @@ repositories {
} }
maven { maven {
name = "Progwml6 maven" name = "Jared's Maven"
url = uri("https://dvs1.progwml6.com/files/maven/") url = uri("https://maven.blamejared.com/")
content { content {
includeGroup("mezz.jei") includeGroup("mezz.jei")
} }
} }
maven {
url = uri("https://maven.theillusivec4.top/")
content {
includeGroup("top.theillusivec4.curios")
}
}
// mavenCentral() // mavenCentral()
} }
@ -377,12 +327,24 @@ fun org.gradle.jvm.tasks.Jar.attachManifest() {
// Example configuration to allow publishing using the maven-publish plugin // Example configuration to allow publishing using the maven-publish plugin
// This is the preferred method to reobfuscate your jar file // This is the preferred method to reobfuscate your jar file
tasks.jar.configure { tasks.jar.configure {
from(configurations["library"].map { if (it.isDirectory) it else zipTree(it) })
finalizedBy("reobfJar") finalizedBy("reobfJar")
attachManifest() attachManifest()
archiveVersion.set(gitVersion.jarName) archiveVersion.set(gitVersion.jarName)
} }
tasks.withType(ProcessResources::class.java) {
val replaceProperties = mapOf(
"mc_version" to mc_version,
"mod_id" to mod_id,
"mod_version" to gitVersion.modVersion
)
inputs.properties(replaceProperties)
filesMatching(arrayListOf("META-INF/mods.toml", "pack.mcmeta")) {
expand(replaceProperties)
}
}
tasks { tasks {
create("sourceJar", org.gradle.jvm.tasks.Jar::class.java) { create("sourceJar", org.gradle.jvm.tasks.Jar::class.java) {
archiveClassifier.set("sources") archiveClassifier.set("sources")
@ -391,7 +353,6 @@ tasks {
create("deobfJar", org.gradle.jvm.tasks.Jar::class.java) { create("deobfJar", org.gradle.jvm.tasks.Jar::class.java) {
archiveClassifier.set("deobf") archiveClassifier.set("deobf")
from(configurations["library"].map { if (it.isDirectory) it else zipTree(it) })
from(sourceSets.main.get().output) from(sourceSets.main.get().output)
attachManifest() attachManifest()
} }
@ -437,21 +398,3 @@ if (project.hasProperty("mavenUser") && project.hasProperty("mavenPassword") &&
} }
} }
} }
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
// publish.dependsOn("reobfJar")
/*
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
}
}
repositories {
maven {
url "file://${project.projectDir}/mcmodsrepo"
}
}
}
*/

View File

@ -48,21 +48,24 @@ for (const colorA of colors) {
const magick = child_process.spawn('magick', [ const magick = child_process.spawn('magick', [
'convert', 'convert',
'-compose', 'Multiply',
'-size', `${width}x${height}`, '-size', `${width}x${height}`,
'(', '(',
`${root_main}${texA}.png`, `${root_main}${texA}.png`,
`xc:rgb(${rgbA[0]}, ${rgbA[1]}, ${rgbA[2]})`, `xc:rgb(${rgbA[0]}, ${rgbA[1]}, ${rgbA[2]})`,
'-compose', 'Multiply',
'-composite', '-composite',
')', ')',
'(', '(',
`${root_main}${texB}.png`, `${root_main}${texB}.png`,
`xc:rgb(${rgbB[0]}, ${rgbB[1]}, ${rgbB[2]})`, `xc:rgb(${rgbB[0]}, ${rgbB[1]}, ${rgbB[2]})`,
'-channel', 'rgb',
'-compose', 'Multiply',
'-composite', '-composite',
')', ')',
'-channel', 'rgba',
'-compose', 'Over', '-compose', 'Over',
'-composite', '-composite',

View File

@ -6,29 +6,31 @@ kotlin.stdlib.default.dependency=false
org.gradle.vfs.watch=true org.gradle.vfs.watch=true
mod_id=overdrive_that_matters mod_id=overdrive_that_matters
mod_version=1.0 mod_version=1.4
use_commit_hash_in_version=true use_commit_hash_in_version=true
mc_version=1.19.2 mc_version=1.19.3
forge_gradle_version=5.1.27 jei_mc_version=1.19.3
forge_version=43.1.43 curios_mc_version=1.19.3
mixingradle_version=0.7.32
forge_gradle_version=[6.0.14,6.2)
forge_version=44.1.23
mixingradle_version=0.7.33
mixin_version=0.8.5 mixin_version=0.8.5
jei_version=11.3.0.262 jei_version=12.4.0.22
jupiter_version=5.8.2 jupiter_version=5.9.2
mekanism_version=10.3.5.homebaked curios_version=4440173
curios_version=5.1.1.0 cosmetic_armor_reworked_id=4439659
cosmetic_armor_reworked_version=v1 ad_astra_id=4452072
jade_id=4010505 botarium_id=4416456
configured_id=4011355 resourceful_lib_id=4378849
worldedit_fileid=3922622 resourceful_config_id=4441381
more_overlays_version=1.21.3-mc1.19 jade_id=4434045
configured_id=4462894
kotlin_for_forge_version=3.1.0 kotlin_for_forge_version=4.7.0
kotlin_version=1.6.10 kotlin_version=1.9.0
kotlin_coroutines_version=1.6.0
kotlin_serialization_version=1.3.2
handle_deps=true handle_deps=true

Binary file not shown.

View File

@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

28
gradlew vendored
View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -32,10 +32,10 @@
# Busybox and similar reduced shells will NOT work, because this script # Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features: # requires all of these POSIX shell features:
# * functions; # * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»; # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»; # * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit». # * various built-in commands including «command», «set», and «ulimit».
# #
# Important for patching: # Important for patching:
# #
@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
@ -80,10 +80,10 @@ do
esac esac
done done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # This is normally unused
# shellcheck disable=SC2034
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #( case $MAX_FD in #(
max*) max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) || MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit" warn "Could not query maximum file descriptor limit"
esac esac
case $MAX_FD in #( case $MAX_FD in #(
'' | soft) :;; #( '' | soft) :;; #(
*) *)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" || ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD" warn "Could not set maximum file descriptor limit to $MAX_FD"
esac esac
@ -205,6 +209,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \ org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args. # Use "xargs" to parse quoted args.
# #
# With -n1 it outputs one arg per line, with the quotes and backslashes removed. # With -n1 it outputs one arg per line, with the quotes and backslashes removed.

15
gradlew.bat vendored
View File

@ -14,7 +14,7 @@
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@rem Gradle startup script for Windows @rem Gradle startup script for Windows
@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 set EXIT_CODE=%ERRORLEVEL%
exit /b 1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal

View File

@ -2,21 +2,21 @@
println("Running with Java ${System.getProperty("java.version")} on JVM: ${System.getProperty("java.vendor")} ${System.getProperty("java.vm.version")} (Architecture: ${System.getProperty("os.arch")})") println("Running with Java ${System.getProperty("java.version")} on JVM: ${System.getProperty("java.vendor")} ${System.getProperty("java.vm.version")} (Architecture: ${System.getProperty("os.arch")})")
pluginManagement { pluginManagement {
val kotlin_version: String by settings repositories {
val forge_gradle_version: String by settings gradlePluginPortal()
val mixingradle_version: String by settings
plugins {
kotlin("jvm") version(kotlin_version)
id("net.minecraftforge.gradle") version(forge_gradle_version)
id("org.spongepowered.mixin") version(mixingradle_version)
} }
} }
plugins {
id("org.gradle.toolchains.foojay-resolver-convention").version("0.5.0")
}
buildscript { buildscript {
repositories { repositories {
// These repositories are only for Gradle plugins, put any other repositories in the repository block further below // These repositories are only for Gradle plugins, put any other repositories in the repository block further below
maven(url = "https://maven.minecraftforge.net") { maven(url = "https://maven.minecraftforge.net") {
name = "Minecraft Forge"
content { content {
includeGroup("net.minecraftforge.gradle") includeGroup("net.minecraftforge.gradle")
includeGroup("net.minecraftforge") includeGroup("net.minecraftforge")
@ -24,6 +24,8 @@ buildscript {
} }
maven(url = "https://repo.spongepowered.org/repository/maven-public/") { maven(url = "https://repo.spongepowered.org/repository/maven-public/") {
name = "Spongepowered"
content { content {
includeGroup("org.spongepowered") includeGroup("org.spongepowered")
} }
@ -40,5 +42,7 @@ buildscript {
classpath(group = "net.minecraftforge.gradle", name = "ForgeGradle", version = forge_gradle_version) classpath(group = "net.minecraftforge.gradle", name = "ForgeGradle", version = forge_gradle_version)
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}")
classpath("org.spongepowered:mixingradle:${mixingradle_version}") classpath("org.spongepowered:mixingradle:${mixingradle_version}")
classpath(group = "org.gradle.toolchains", name = "foojay-resolver", version = "0.5.0")
} }
} }

View File

@ -1,5 +1,7 @@
package ru.dbotthepony.mc.otm.datagen package ru.dbotthepony.mc.otm.datagen
import net.minecraft.core.RegistrySetBuilder
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
@ -13,39 +15,36 @@ import net.minecraft.world.level.block.state.properties.DoorHingeSide
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
import net.minecraft.world.level.block.state.properties.Half import net.minecraft.world.level.block.state.properties.Half
import net.minecraftforge.client.model.generators.ModelFile import net.minecraftforge.client.model.generators.ModelFile
import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider
import net.minecraftforge.common.data.ForgeAdvancementProvider
import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidResearchDataProvider import ru.dbotthepony.mc.otm.android.AndroidResearchDataProvider
import ru.dbotthepony.mc.otm.block.* import ru.dbotthepony.mc.otm.block.*
import ru.dbotthepony.mc.otm.core.WriteOnce import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.datagen.blocks.BatteryBankProvider import ru.dbotthepony.mc.otm.datagen.blocks.BatteryBankProvider
import ru.dbotthepony.mc.otm.datagen.blocks.MatterBankProvider import ru.dbotthepony.mc.otm.datagen.blocks.MatterBankProvider
import ru.dbotthepony.mc.otm.datagen.blocks.MatteryBlockStateProvider import ru.dbotthepony.mc.otm.datagen.blocks.MatteryBlockStateProvider
import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider
import ru.dbotthepony.mc.otm.datagen.lang.AddEnglishLanguage import ru.dbotthepony.mc.otm.datagen.lang.AddEnglishLanguage
import ru.dbotthepony.mc.otm.datagen.models.MatteryBlockModelProvider import ru.dbotthepony.mc.otm.datagen.models.MatteryBlockModelProvider
import ru.dbotthepony.mc.otm.datagen.recipes.MatteryRecipeProvider
import ru.dbotthepony.mc.otm.registry.* import ru.dbotthepony.mc.otm.registry.*
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.advancements.AdvancementProvider
import ru.dbotthepony.mc.otm.datagen.advancements.addAdvancements import ru.dbotthepony.mc.otm.datagen.advancements.addAdvancements
import ru.dbotthepony.mc.otm.datagen.advancements.addAndroidAdvancements import ru.dbotthepony.mc.otm.datagen.advancements.addAndroidAdvancements
import ru.dbotthepony.mc.otm.datagen.advancements.addMachineAdvancements import ru.dbotthepony.mc.otm.datagen.advancements.addMachineAdvancements
import ru.dbotthepony.mc.otm.datagen.blocks.addBlockStates import ru.dbotthepony.mc.otm.datagen.blocks.addBlockStates
import ru.dbotthepony.mc.otm.datagen.blocks.addComplexBlockStates import ru.dbotthepony.mc.otm.datagen.blocks.addComplexBlockStates
import ru.dbotthepony.mc.otm.datagen.items.addItemModels import ru.dbotthepony.mc.otm.datagen.items.addItemModels
import ru.dbotthepony.mc.otm.datagen.lang.AddRussianLanguage
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.loot.* import ru.dbotthepony.mc.otm.datagen.loot.*
import ru.dbotthepony.mc.otm.datagen.loot.LootModifiers import ru.dbotthepony.mc.otm.datagen.loot.LootModifiers
import ru.dbotthepony.mc.otm.datagen.models.addBlockModels import ru.dbotthepony.mc.otm.datagen.models.addBlockModels
import ru.dbotthepony.mc.otm.datagen.recipes.addBlastingRecipes import ru.dbotthepony.mc.otm.datagen.recipes.*
import ru.dbotthepony.mc.otm.datagen.recipes.addCraftingTableRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addDecorativesRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addPlatePressRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addShapelessRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addOreSmeltingRecipes
import ru.dbotthepony.mc.otm.datagen.tags.TagsProvider import ru.dbotthepony.mc.otm.datagen.tags.TagsProvider
import ru.dbotthepony.mc.otm.datagen.tags.addTags import ru.dbotthepony.mc.otm.datagen.tags.addTags
import ru.dbotthepony.mc.otm.matter.MatterDataProvider import ru.dbotthepony.mc.otm.matter.MatterDataProvider
@ -53,7 +52,7 @@ import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock
import ru.dbotthepony.mc.otm.registry.objects.DecorativeBlock import ru.dbotthepony.mc.otm.registry.objects.DecorativeBlock
import kotlin.properties.Delegates import kotlin.properties.Delegates
fun modLocation(string: String) = ResourceLocation(DataGen.MOD_ID, string) internal fun modLocation(string: String) = ResourceLocation(DataGen.MOD_ID, string)
@Mod.EventBusSubscriber(modid = DataGen.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) @Mod.EventBusSubscriber(modid = DataGen.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
object DataGen { object DataGen {
@ -217,6 +216,86 @@ object DataGen {
} }
} }
private fun MatteryBlockModelProvider.bars(name: String, parent: String, texture: ResourceLocation): ModelFile {
return withExistingParent(name, "block/$parent")
.texture("bars", texture)
.texture("edge", texture)
.texture("particle", texture)
.renderType("cutout_mipped")
}
@Suppress("LocalVariableName")
fun bars(block: Block, texture: ResourceLocation) {
val name = block.registryName?.path ?: throw IllegalStateException("Invalid state of glass pane $block")
val cap = "${name}_cap"
val cap_alt = "${name}_cap_alt"
val post = "${name}_post"
val post_ends = "${name}_post_ends"
val side = "${name}_side"
val side_alt = "${name}_side_alt"
var mdl_cap by Delegates.notNull<ModelFile>()
var mdl_cap_alt by Delegates.notNull<ModelFile>()
var mdl_post by Delegates.notNull<ModelFile>()
var mdl_post_ends by Delegates.notNull<ModelFile>()
var mdl_side by Delegates.notNull<ModelFile>()
var mdl_side_alt by Delegates.notNull<ModelFile>()
with(blockModelProvider) {
exec {
mdl_cap = bars(cap, "iron_bars_cap", texture)
mdl_cap_alt = bars(cap_alt, "iron_bars_cap_alt", texture)
mdl_post = bars(post, "iron_bars_post", texture)
mdl_post_ends = bars(post_ends, "iron_bars_post_ends", texture)
mdl_side = bars(side, "iron_bars_side", texture)
mdl_side_alt = bars(side_alt, "iron_bars_side_alt", texture)
}
}
@Suppress("name_shadowing")
blockStateProvider.exec {
with(blockStateProvider.getMultipartBuilder(block)) {
part().modelFile(mdl_post_ends).addModel()
part().modelFile(mdl_post).addModel()
.condition(IronBarsBlock.EAST, false)
.condition(IronBarsBlock.WEST, false)
.condition(IronBarsBlock.NORTH, false)
.condition(IronBarsBlock.SOUTH, false)
part().modelFile(mdl_cap).addModel()
.condition(IronBarsBlock.EAST, false)
.condition(IronBarsBlock.WEST, false)
.condition(IronBarsBlock.NORTH, true)
.condition(IronBarsBlock.SOUTH, false)
part().modelFile(mdl_cap).rotationY(90).addModel()
.condition(IronBarsBlock.EAST, true)
.condition(IronBarsBlock.WEST, false)
.condition(IronBarsBlock.NORTH, false)
.condition(IronBarsBlock.SOUTH, false)
part().modelFile(mdl_cap_alt).addModel()
.condition(IronBarsBlock.EAST, false)
.condition(IronBarsBlock.WEST, false)
.condition(IronBarsBlock.NORTH, false)
.condition(IronBarsBlock.SOUTH, true)
part().modelFile(mdl_cap_alt).rotationY(90).addModel()
.condition(IronBarsBlock.EAST, false)
.condition(IronBarsBlock.WEST, true)
.condition(IronBarsBlock.NORTH, false)
.condition(IronBarsBlock.SOUTH, false)
part().modelFile(mdl_side).addModel().condition(IronBarsBlock.NORTH, true)
part().modelFile(mdl_side).rotationY(90).addModel().condition(IronBarsBlock.EAST, true)
part().modelFile(mdl_side_alt).addModel().condition(IronBarsBlock.SOUTH, true)
part().modelFile(mdl_side_alt).rotationY(90).addModel().condition(IronBarsBlock.WEST, true)
}
}
}
fun door(block: Block, textureTop: ResourceLocation, textureBottom: ResourceLocation) { fun door(block: Block, textureTop: ResourceLocation, textureBottom: ResourceLocation) {
var doorBottomLeft by Delegates.notNull<ModelFile>() var doorBottomLeft by Delegates.notNull<ModelFile>()
var doorBottomLeftOpen by Delegates.notNull<ModelFile>() var doorBottomLeftOpen by Delegates.notNull<ModelFile>()
@ -271,7 +350,7 @@ object DataGen {
} }
} }
).rotationY( ).rotationY(
facing.toYRotBlockstate() - 90 + facing.yRotationBlockstateNorth() - 90 +
(if (open) when (hinge) { (if (open) when (hinge) {
DoorHingeSide.LEFT -> 90 DoorHingeSide.LEFT -> 90
DoorHingeSide.RIGHT -> -90 DoorHingeSide.RIGHT -> -90
@ -321,7 +400,7 @@ object DataGen {
Half.BOTTOM -> trapdoorBottom Half.BOTTOM -> trapdoorBottom
} }
).rotationY( ).rotationY(
facing.toYRotBlockstate() facing.yRotationBlockstateNorth()
).addModel() ).addModel()
.condition(TrapDoorBlock.FACING, facing) .condition(TrapDoorBlock.FACING, facing)
.condition(TrapDoorBlock.OPEN, open) .condition(TrapDoorBlock.OPEN, open)
@ -406,7 +485,7 @@ object DataGen {
val lootModifier = LootModifiers(event.generator) val lootModifier = LootModifiers(event.generator)
val languageProvider = MatteryLanguageProvider(event.generator) val languageProvider = MatteryLanguageProvider(event.generator)
val matterData = MatterDataProvider(event) val matterData = MatterDataProvider(event)
val researchProvider = AndroidResearchDataProvider(event.generator).also { it.exec { addResearchData(it, languageProvider) } } val researchProvider = AndroidResearchDataProvider(event).also { it.exec { addResearchData(it, languageProvider) } }
this.blockModelProvider = blockModelProvider this.blockModelProvider = blockModelProvider
this.blockStateProvider = blockStateProvider this.blockStateProvider = blockStateProvider
@ -419,7 +498,12 @@ object DataGen {
this.matterData = matterData this.matterData = matterData
val tagsProvider = TagsProvider(event) val tagsProvider = TagsProvider(event)
val advancementProvider = AdvancementProvider(event) val advancementProvider = object : ForgeAdvancementProvider(event.generator.packOutput, event.lookupProvider, event.existingFileHelper, listOf(
AdvancementGenerator { registries, saver, existingFileHelper ->
addAdvancements(saver, languageProvider)
addAndroidAdvancements(saver, languageProvider)
}
)) {}
addTags(tagsProvider) addTags(tagsProvider)
@ -436,14 +520,21 @@ object DataGen {
event.generator.addProvider(event.includeServer(), advancementProvider) event.generator.addProvider(event.includeServer(), advancementProvider)
event.generator.addProvider(event.includeServer(), matterData) event.generator.addProvider(event.includeServer(), matterData)
val registrySetBuilder = RegistrySetBuilder()
.add(Registries.CONFIGURED_FEATURE, ::registerConfiguredFeatures)
.add(Registries.PLACED_FEATURE, ::registerPlacedFeatures)
event.generator.addProvider(event.includeServer(), DatapackBuiltinEntriesProvider(event.generator.packOutput, event.lookupProvider, registrySetBuilder, setOf(MOD_ID)))
AddEnglishLanguage(languageProvider) AddEnglishLanguage(languageProvider)
AddRussianLanguage(languageProvider)
for ((color, door) in MBlocks.TRITANIUM_DOOR) for ((color, door) in MBlocks.TRITANIUM_DOOR)
door(door, modLocation("block/decorative/tritanium_door_top${color?.name?.lowercase()?.let { "_$it" } ?: ""}"), modLocation("block/decorative/tritanium_door_bottom${color?.name?.lowercase()?.let { "_$it" } ?: ""}")) door(door, modLocation("block/decorative/tritanium_door_top${color?.name?.lowercase()?.let { "_$it" } ?: ""}"), modLocation("block/decorative/tritanium_door_bottom${color?.name?.lowercase()?.let { "_$it" } ?: ""}"))
trapdoor(MBlocks.TRITANIUM_TRAPDOOR[null]!!, modLocation("block/decorative/tritanium_trapdoor")) trapdoor(MBlocks.TRITANIUM_TRAPDOOR[null]!!, modLocation("block/decorative/tritanium_trapdoor"))
for (color in DyeColor.values()) for (color in DyeColor.entries)
trapdoor(MBlocks.TRITANIUM_TRAPDOOR[color]!!, modLocation("block/decorative/tritanium_trapdoor_${color.name.lowercase()}")) trapdoor(MBlocks.TRITANIUM_TRAPDOOR[color]!!, modLocation("block/decorative/tritanium_trapdoor_${color.name.lowercase()}"))
addBlockModels(blockModelProvider) addBlockModels(blockModelProvider)
@ -460,17 +551,15 @@ object DataGen {
addCraftingTableRecipes(consumer) addCraftingTableRecipes(consumer)
addBlastingRecipes(consumer) addBlastingRecipes(consumer)
addDecorativesRecipes(recipeProvider, consumer) addDecorativesRecipes(recipeProvider, consumer)
addMachineUpgradeRecipes(consumer)
addShapelessRecipes(consumer) addShapelessRecipes(consumer)
addOreSmeltingRecipes(consumer) addOreSmeltingRecipes(consumer)
} addPainterRecipes(consumer)
addMatterEntanglerRecipes(consumer)
advancementProvider.exec { it, files ->
addAdvancements(it, files, languageProvider)
addAndroidAdvancements(it, files, languageProvider)
addMachineAdvancements(it, files, languageProvider)
} }
addPlatePressRecipes(recipeProvider) addPlatePressRecipes(recipeProvider)
addMicrowaveRecipes(recipeProvider)
lootModifier.lambda { lootModifier.lambda {
addLootModifiers(it) addLootModifiers(it)
@ -479,5 +568,7 @@ object DataGen {
languageProvider.registerProviders() languageProvider.registerProviders()
addMatterData(matterData) addMatterData(matterData)
tagsProvider.register()
} }
} }

View File

@ -1,21 +1,21 @@
package ru.dbotthepony.mc.otm.datagen package ru.dbotthepony.mc.otm.datagen
import net.minecraft.resources.ResourceLocation import net.minecraft.world.level.block.AnvilBlock
import net.minecraft.world.level.block.PressurePlateBlock
import net.minecraft.world.level.block.SlabBlock import net.minecraft.world.level.block.SlabBlock
import net.minecraft.world.level.block.StairBlock import net.minecraft.world.level.block.StairBlock
import net.minecraft.world.level.block.WallBlock import net.minecraft.world.level.block.WallBlock
import net.minecraft.world.level.block.state.properties.BlockStateProperties import net.minecraft.world.level.block.state.properties.BlockStateProperties
import net.minecraftforge.client.model.generators.BlockModelBuilder
import net.minecraftforge.client.model.generators.ConfiguredModel import net.minecraftforge.client.model.generators.ConfiguredModel
import net.minecraftforge.client.model.generators.ModelFile import net.minecraftforge.client.model.generators.ModelFile
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.blocks.MatteryBlockStateProvider import ru.dbotthepony.mc.otm.datagen.blocks.MatteryBlockStateProvider
import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider
import ru.dbotthepony.mc.otm.datagen.models.MatteryBlockModelProvider import ru.dbotthepony.mc.otm.datagen.models.MatteryBlockModelProvider
import ru.dbotthepony.mc.otm.datagen.models.MatteryModelBuilder
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.registry.MNames
@ -37,6 +37,17 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
DataGen.decoratives(MRegistry.TRITANIUM_BLOCK) DataGen.decoratives(MRegistry.TRITANIUM_BLOCK)
for (anvil in MBlocks.TRITANIUM_ANVIL) {
blockStateProvider.exec {
blockStateProvider.getVariantBuilder(anvil).forAllStates {
ConfiguredModel.builder()
.modelFile(blockStateProvider.models().getExistingFile(modLocation("block/${anvil.registryName!!.path}")))
.rotationY(it[AnvilBlock.FACING].yRotationBlockstateNorth())
.build()
}
}
}
for ((color, block) in MRegistry.TRITANIUM_STAIRS.allBlocks) { for ((color, block) in MRegistry.TRITANIUM_STAIRS.allBlocks) {
DataGen.decorativeStairs(block as StairBlock, MRegistry.TRITANIUM_BLOCK.allBlocks[color]!!.registryName!!.path, MRegistry.TRITANIUM_BLOCK.allBlocks[color]!!.registryName!!.path) DataGen.decorativeStairs(block as StairBlock, MRegistry.TRITANIUM_BLOCK.allBlocks[color]!!.registryName!!.path, MRegistry.TRITANIUM_BLOCK.allBlocks[color]!!.registryName!!.path)
} }
@ -129,6 +140,8 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
blockModelProvider.decorativeGlassAll(MRegistry.INDUSTRIAL_GLASS.allBlocks.values) blockModelProvider.decorativeGlassAll(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
blockStateProvider.simpleBlockM(MRegistry.INDUSTRIAL_GLASS.allBlocks.values) blockStateProvider.simpleBlockM(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
blockStateProvider.simpleBlockM(MBlocks.FLUID_TANK)
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_BLOCK.blocksWithColor) { for ((block, colors) in MRegistry.TRITANIUM_STRIPED_BLOCK.blocksWithColor) {
DataGen.decorativeColumn( DataGen.decorativeColumn(
block, block,
@ -181,17 +194,17 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
DataGen.decorativeCubeAll(MBlocks.DANGER_STRIPE_BLOCK) DataGen.decorativeCubeAll(MBlocks.DANGER_STRIPE_BLOCK)
DataGen.decorativeColumn(MBlocks.METAL_BEAM, "metal_beam_side", "metal_beam_top") DataGen.decorativeColumn(MBlocks.METAL_BEAM, "metal_beam_side", "metal_beam_top")
var labLampOn: MatteryModelBuilder? = null var labLampOn: BlockModelBuilder? = null
var labLampOff: MatteryModelBuilder? = null var labLampOff: BlockModelBuilder? = null
blockModelProvider.exec { blockModelProvider.exec {
val top = ResourceLocation(DataGen.MOD_ID, "block/decorative/metal_beam_top") val top = modLocation("block/decorative/metal_beam_top")
labLampOn = it.cube( labLampOn = it.cube(
MBlocks.LABORATORY_LAMP.registryName!!.path, MBlocks.LABORATORY_LAMP.registryName!!.path,
top, top,
top, top,
ResourceLocation(DataGen.MOD_ID, "block/decorative/laboratory_lamp_front"), modLocation("block/decorative/laboratory_lamp_front"),
top, top,
top, top,
top, top,
@ -201,7 +214,7 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
MBlocks.LABORATORY_LAMP.registryName!!.path + "_unlit", MBlocks.LABORATORY_LAMP.registryName!!.path + "_unlit",
top, top,
top, top,
ResourceLocation(DataGen.MOD_ID, "block/decorative/laboratory_lamp_front_off"), modLocation("block/decorative/laboratory_lamp_front_off"),
top, top,
top, top,
top, top,
@ -217,28 +230,28 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
blockStateProvider.getVariantBuilder(MBlocks.LABORATORY_LAMP).forAllStates { blockStateProvider.getVariantBuilder(MBlocks.LABORATORY_LAMP).forAllStates {
return@forAllStates ConfiguredModel.builder() return@forAllStates ConfiguredModel.builder()
.modelFile(if (it[BlockStateProperties.LIT]) labLampOn!! else labLampOff!!) .modelFile(if (it[BlockStateProperties.LIT]) labLampOn!! else labLampOff!!)
.rotationX(it[RotatableMatteryBlock.FACING_FULL].toXRotBlockstate()) .rotationX(it[BlockRotationFreedom.DIRECTIONAL.property].front.xRotationBlockstateNorth())
.rotationY(it[RotatableMatteryBlock.FACING_FULL].toYRotBlockstate()) .rotationY(it[BlockRotationFreedom.DIRECTIONAL.property].front.yRotationBlockstateNorth())
.build() .build()
} }
blockStateProvider.getVariantBuilder(MBlocks.LABORATORY_LAMP_INVERTED).forAllStates { blockStateProvider.getVariantBuilder(MBlocks.LABORATORY_LAMP_INVERTED).forAllStates {
return@forAllStates ConfiguredModel.builder() return@forAllStates ConfiguredModel.builder()
.modelFile(if (it[BlockStateProperties.LIT]) labLampOn!! else labLampOff!!) .modelFile(if (it[BlockStateProperties.LIT]) labLampOn!! else labLampOff!!)
.rotationX(it[RotatableMatteryBlock.FACING_FULL].toXRotBlockstate()) .rotationX(it[BlockRotationFreedom.DIRECTIONAL.property].front.xRotationBlockstateNorth())
.rotationY(it[RotatableMatteryBlock.FACING_FULL].toYRotBlockstate()) .rotationY(it[BlockRotationFreedom.DIRECTIONAL.property].front.yRotationBlockstateNorth())
.build() .build()
} }
} }
blockModelProvider.exec { blockModelProvider.exec {
for (crate in MRegistry.CARGO_CRATES.blocks.values) { for (crate in MRegistry.CARGO_CRATES.blocks.values) {
it.withExistingParent("${crate.registryName!!.path}_closed", ResourceLocation(OverdriveThatMatters.MOD_ID, "${MNames.CARGO_CRATE}_closed")) it.withExistingParent("${crate.registryName!!.path}_closed", modLocation("${MNames.CARGO_CRATE}_closed"))
.texture("texture", "block/cargo_crates/${crate.registryName!!.path}") .texture("body", "block/cargo_crates/${crate.registryName!!.path}")
.texture("particle", "block/cargo_crates/${crate.registryName!!.path}") .texture("particle", "block/cargo_crates/${crate.registryName!!.path}")
it.withExistingParent("${crate.registryName!!.path}_open", ResourceLocation(OverdriveThatMatters.MOD_ID, "${MNames.CARGO_CRATE}_open")) it.withExistingParent("${crate.registryName!!.path}_open", modLocation("${MNames.CARGO_CRATE}_open"))
.texture("texture", "block/cargo_crates/${crate.registryName!!.path}") .texture("body", "block/cargo_crates/${crate.registryName!!.path}")
.texture("particle", "block/cargo_crates/${crate.registryName!!.path}") .texture("particle", "block/cargo_crates/${crate.registryName!!.path}")
} }
} }
@ -258,8 +271,13 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
for ((color, glass) in MRegistry.INDUSTRIAL_GLASS_PANE.allBlocks) { for ((color, glass) in MRegistry.INDUSTRIAL_GLASS_PANE.allBlocks) {
val name = MRegistry.INDUSTRIAL_GLASS.allBlocks[color]!!.registryName!!.path val name = MRegistry.INDUSTRIAL_GLASS.allBlocks[color]!!.registryName!!.path
val textureSide = ResourceLocation(DataGen.MOD_ID, "block/decorative/$name") val textureSide = modLocation("block/decorative/$name")
val textureRailing = ResourceLocation(DataGen.MOD_ID, "block/decorative/industrial_glass_frame") val textureRailing = modLocation("block/decorative/industrial_glass_frame")
DataGen.pane(glass, textureSide, textureRailing) DataGen.pane(glass, textureSide, textureRailing)
} }
DataGen.bars(MBlocks.TRITANIUM_BARS, modLocation("block/decorative/tritanium_bars"))
blockStateProvider.block(MBlocks.ENGINE)
itemModelProvider.block(MItems.ENGINE)
} }

View File

@ -1,60 +0,0 @@
package ru.dbotthepony.mc.otm.datagen
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import net.minecraft.core.Direction
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.properties.Property
import kotlin.math.roundToInt
fun Direction.toYRotBlockstate(): Int {
return when (this) {
Direction.DOWN -> 0
Direction.UP -> 0
Direction.NORTH -> 0
Direction.SOUTH -> 180
Direction.WEST -> -90
Direction.EAST -> 90
}
}
fun Direction.toYRotBlockstateInv(): Int {
return when (this) {
Direction.DOWN -> 0
Direction.UP -> 0
Direction.NORTH -> 180
Direction.SOUTH -> 0
Direction.WEST -> 90
Direction.EAST -> -90
}
}
fun Direction.toXRotBlockstate(): Int {
return when (this) {
Direction.DOWN -> 90
Direction.UP -> -90
Direction.NORTH -> 0
Direction.SOUTH -> 0
Direction.WEST -> 0
Direction.EAST -> 0
}
}
fun Direction.toXRotBlockstateInv(): Int {
return when (this) {
Direction.DOWN -> -90
Direction.UP -> 90
Direction.NORTH -> 0
Direction.SOUTH -> 0
Direction.WEST -> 0
Direction.EAST -> 0
}
}
fun <T : Comparable<T>> BlockState.getValueNullable(prop: Property<T>): T? {
if (hasProperty(prop)) {
return getValue(prop)
}
return null
}

View File

@ -4,7 +4,8 @@ import net.minecraft.tags.ItemTags
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.core.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.matter.ComputeAction
import ru.dbotthepony.mc.otm.matter.MatterDataProvider import ru.dbotthepony.mc.otm.matter.MatterDataProvider
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
@ -16,6 +17,29 @@ fun addMatterData(provider: MatterDataProvider) {
provider.inherit(Items.CHIPPED_ANVIL, Items.ANVIL, 0.75) provider.inherit(Items.CHIPPED_ANVIL, Items.ANVIL, 0.75)
provider.inherit(Items.DAMAGED_ANVIL, Items.ANVIL, 0.5) provider.inherit(Items.DAMAGED_ANVIL, Items.ANVIL, 0.5)
for (i in 1 until MItems.TRITANIUM_ANVIL.size) {
provider.inherit(MItems.TRITANIUM_ANVIL[i], MItems.TRITANIUM_ANVIL[i - 1], 0.85)
}
provider.inherit(Items.WATER_BUCKET, Items.BUCKET) {
plus(Decimal(1), 20.0)
}
provider.inherit(Items.LAVA_BUCKET, Items.MAGMA_BLOCK) {
plus(Decimal(0), 666.0)
plus(Items.BUCKET)
}
provider.inherit(Items.POWDER_SNOW_BUCKET, Items.SNOW_BLOCK) {
multiply(Decimal(0.75), 1.0)
plus(Decimal(0), 200.0)
plus(Items.BUCKET)
}
provider.inherit(Items.MILK_BUCKET, Items.BUCKET) {
plus(Decimal(7), 480.0)
}
val copper = listOf<Pair<List<Item>, Item>>( val copper = listOf<Pair<List<Item>, Item>>(
listOf( listOf(
Items.EXPOSED_COPPER, Items.EXPOSED_COPPER,
@ -101,7 +125,7 @@ fun addMatterData(provider: MatterDataProvider) {
relative(Items.NETHER_STAR, 2000, 1200) relative(Items.NETHER_STAR, 2000, 1200)
relative(MItems.ZPM_BATTERY, 60000, 7200) relative(MItems.ZPM_BATTERY, 80000000, 720000)
relative(MItems.PILL_HEAL, 14, 8) relative(MItems.PILL_HEAL, 14, 8)
relative(MItems.PILL_ANDROID, 20, 20) relative(MItems.PILL_ANDROID, 20, 20)
@ -205,6 +229,7 @@ fun addMatterData(provider: MatterDataProvider) {
relative(Items.HONEY_BLOCK, 6, 1.75) relative(Items.HONEY_BLOCK, 6, 1.75)
relative(Tags.Items.GEMS_PRISMARINE, 6, 2.75) relative(Tags.Items.GEMS_PRISMARINE, 6, 2.75)
relative(Items.PRISMARINE_SHARD, 6, 2.75)
relative(Tags.Items.RODS_BLAZE, 1.4, 2) relative(Tags.Items.RODS_BLAZE, 1.4, 2)
relative(Items.GHAST_TEAR, 2.5, 2.5) relative(Items.GHAST_TEAR, 2.5, 2.5)

View File

@ -0,0 +1,58 @@
package ru.dbotthepony.mc.otm.datagen
import net.minecraft.core.RegistrySetBuilder
import net.minecraft.core.registries.Registries
import net.minecraft.data.worldgen.BootstapContext
import net.minecraft.resources.ResourceKey
import net.minecraft.tags.BlockTags
import net.minecraft.world.level.levelgen.VerticalAnchor
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature
import net.minecraft.world.level.levelgen.feature.Feature
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration
import net.minecraft.world.level.levelgen.placement.CountPlacement
import net.minecraft.world.level.levelgen.placement.HeightRangePlacement
import net.minecraft.world.level.levelgen.placement.InSquarePlacement
import net.minecraft.world.level.levelgen.placement.PlacedFeature
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest
import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider
import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.registry.MBlocks
private val oreKey by lazy { ResourceKey.create(Registries.CONFIGURED_FEATURE, modLocation("tritanium_ore")) }
fun registerConfiguredFeatures(context: BootstapContext<ConfiguredFeature<*, *>>) {
val stone = TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES)
val deepslate = TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES)
val target = listOf(
OreConfiguration.target(stone, MBlocks.TRITANIUM_ORE.defaultBlockState()),
OreConfiguration.target(deepslate, MBlocks.DEEPSLATE_TRITANIUM_ORE.defaultBlockState()),
)
context.register(oreKey, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 9)))
}
fun registerPlacedFeatures(context: BootstapContext<PlacedFeature>) {
fun location(name: String) = ResourceKey.create(Registries.PLACED_FEATURE, modLocation(name))
val configured = context.lookup(Registries.CONFIGURED_FEATURE)
val ore = configured.getOrThrow(oreKey)
context.register(location("normal_tritanium"), PlacedFeature(
ore,
listOf(
CountPlacement.of(8),
InSquarePlacement.spread(),
HeightRangePlacement.triangle(VerticalAnchor.absolute(0), VerticalAnchor.absolute(50))
)
))
context.register(location("deep_tritanium"), PlacedFeature(
ore,
listOf(
CountPlacement.of(10),
InSquarePlacement.spread(),
HeightRangePlacement.uniform(VerticalAnchor.aboveBottom(8), VerticalAnchor.absolute(0))
)
))
}

View File

@ -4,13 +4,9 @@ import net.minecraft.tags.ItemTags
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidResearchDescriptions
import ru.dbotthepony.mc.otm.android.AndroidResearchResults
import ru.dbotthepony.mc.otm.android.AndroidResearchType import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature
import ru.dbotthepony.mc.otm.android.feature.FallDampenersFeature
import ru.dbotthepony.mc.otm.android.feature.ItemMagnetFeature
import ru.dbotthepony.mc.otm.android.feature.JumpBoostFeature
import ru.dbotthepony.mc.otm.android.feature.NanobotsArmorFeature
import ru.dbotthepony.mc.otm.android.feature.ShockwaveFeature
import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
@ -47,6 +43,45 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
serializer.accept(IMPROVED_LIMBS) serializer.accept(IMPROVED_LIMBS)
val SWIM_BOOSTERS = AndroidResearchType.Builder(modLocation(MNames.SWIM_BOOSTERS))
.withExperience(26)
.withDescription(AndroidResearchDescriptions.SWIM_BOOSTERS.Instance(0))
.addPrerequisite(IMPROVED_LIMBS)
.addPrerequisite(AIR_BAGS)
.addFeatureResult(AndroidFeatures.SWIM_BOOSTERS)
.withIcon(ResearchIcons.ICON_LIMB_OVERCLOCKING)
.addItem(MItemTags.TRITANIUM_PLATES, 2)
.addItem(MItemTags.COPPER_WIRES, 2)
.addItem(MItems.ELECTROMOTOR, 2)
.build()
serializer.accept(SWIM_BOOSTERS)
val SWIM_BOOSTERS_2 = AndroidResearchType.Builder(modLocation(MNames.SWIM_BOOSTERS + "_2"))
.withExperience(30)
.withDescription(AndroidResearchDescriptions.SWIM_BOOSTERS.Instance(1))
.addPrerequisite(SWIM_BOOSTERS)
.addFeatureLevel(AndroidFeatures.SWIM_BOOSTERS)
.withIcon(ResearchIcons.ICON_LIMB_OVERCLOCKING)
.addItem(MItemTags.GOLD_WIRES, 8)
.addItem(MItems.ELECTROMOTOR, 2)
.build()
serializer.accept(SWIM_BOOSTERS_2)
val SWIM_BOOSTERS_3 = AndroidResearchType.Builder(modLocation(MNames.SWIM_BOOSTERS + "_3"))
.withExperience(30)
.withDescription(AndroidResearchDescriptions.SWIM_BOOSTERS.Instance(2))
.addPrerequisite(SWIM_BOOSTERS_2)
.addFeatureLevel(AndroidFeatures.SWIM_BOOSTERS)
.withIcon(ResearchIcons.ICON_LIMB_OVERCLOCKING)
.addItem(MItemTags.CARBON_PLATES, 8)
.addItem(MItemTags.TRITANIUM_NUGGETS, 4)
.addItem(MItemTags.COPPER_WIRES, 2)
.build()
serializer.accept(SWIM_BOOSTERS_3)
val STEP_ASSIST = AndroidResearchType.Builder(modLocation(MNames.STEP_ASSIST)) val STEP_ASSIST = AndroidResearchType.Builder(modLocation(MNames.STEP_ASSIST))
.withExperience(24) .withExperience(24)
.addFeatureResult(AndroidFeatures.STEP_ASSIST) .addFeatureResult(AndroidFeatures.STEP_ASSIST)
@ -103,7 +138,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS)) .addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS))
.addFeatureResult(OverdriveThatMatters.loc(MNames.NANOBOTS_ARMOR)) .addFeatureResult(OverdriveThatMatters.loc(MNames.NANOBOTS_ARMOR))
.withIcon(ResearchIcons.ICON_ARMOR) .withIcon(ResearchIcons.ICON_ARMOR)
.addBlocker(OverdriveThatMatters.loc(MNames.ATTACK_BOOST_1), rigid = true) .addBlocker(OverdriveThatMatters.loc(MNames.ATTACK_BOOST_1), optional = true)
.addItem(MItemTags.TRITANIUM_PLATES, 4) .addItem(MItemTags.TRITANIUM_PLATES, 4)
.addItem(MItemTags.COPPER_WIRES, 8) .addItem(MItemTags.COPPER_WIRES, 8)
.build() .build()
@ -128,15 +163,18 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
TranslatableComponent( TranslatableComponent(
"android_research.overdrive_that_matters.limb_overclocking.description", "android_research.overdrive_that_matters.limb_overclocking.description",
(i + 1) * 8, (i + 1) * 8,
(i + 1) * 6 (i + 1) * 6,
(i + 1) * 20
) )
) )
.addItem(MItemTags.COPPER_WIRES, 4 + i * 2) .addItem(MItemTags.COPPER_WIRES, 4 + i * 2)
.addFeatureResult(OverdriveThatMatters.loc(MNames.LIMB_OVERCLOCKING), i)
if (i > 0) { if (i > 0) {
research.addPrerequisite(OverdriveThatMatters.loc(MNames.LIMB_OVERCLOCKING_LIST[i - 1]), rigid = true) research.addFeatureLevel(AndroidFeatures.LIMB_OVERCLOCKING)
research.addPrerequisite(OverdriveThatMatters.loc(MNames.LIMB_OVERCLOCKING_LIST[i - 1]), optional = true)
research.addItem(MItemTags.GOLD_WIRES, i * 2) research.addItem(MItemTags.GOLD_WIRES, i * 2)
} else {
research.addFeatureResult(AndroidFeatures.LIMB_OVERCLOCKING)
} }
research.build() research.build()
@ -152,21 +190,26 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
.withDescription( .withDescription(
TranslatableComponent( TranslatableComponent(
"android_research.overdrive_that_matters.attack_boost.description", "android_research.overdrive_that_matters.attack_boost.description",
(i + 1) * 6 (i + 1) * 15
) )
) )
.addFeatureResult(AndroidFeatures.ATTACK_BOOST, i) .addItem(MItems.ELECTROMAGNET, 2 + i)
.addItem(MItemTags.GOLD_WIRES, 4 * i + 8)
.addItem(MItemTags.PISTONS)
.addBlocker(NANOBOTS_ARMOR) .addBlocker(NANOBOTS_ARMOR)
if (i > 0) { if (i > 0) {
research.addPrerequisite(OverdriveThatMatters.loc(MNames.ATTACK_BOOST_LIST[i - 1]), rigid = true) research.addFeatureLevel(AndroidFeatures.ATTACK_BOOST)
research.addPrerequisite(OverdriveThatMatters.loc(MNames.ATTACK_BOOST_LIST[i - 1]), optional = true)
} else {
research.addFeatureResult(AndroidFeatures.ATTACK_BOOST)
} }
research.build() research.build()
}) })
regenList.add(run { regenList.add(run {
val regeneration = AndroidResearchType.Builder(modLocation(MNames.NANOBOTS_REGENERATION_LIST[i])) val research = AndroidResearchType.Builder(modLocation(MNames.NANOBOTS_REGENERATION_LIST[i]))
.withExperience(20 + i * 6) .withExperience(20 + i * 6)
.withIconText(TextComponent((i + 1).toString())) .withIconText(TextComponent((i + 1).toString()))
.withIcon(ResearchIcons.ICON_NANOBOTS) .withIcon(ResearchIcons.ICON_NANOBOTS)
@ -179,15 +222,16 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
.addItem(MItems.MATTER_CAPACITOR_PARTS, 1) .addItem(MItems.MATTER_CAPACITOR_PARTS, 1)
.addItem(Items.SUGAR, 2 + i * 2) .addItem(Items.SUGAR, 2 + i * 2)
.addItem(Tags.Items.DUSTS_REDSTONE, 2 + i * 2) .addItem(Tags.Items.DUSTS_REDSTONE, 2 + i * 2)
.addFeatureResult(AndroidFeatures.NANOBOTS_REGENERATION, i)
if (i > 0) { if (i > 0) {
regeneration.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS_REGENERATION_LIST[i - 1]), rigid = true) research.addFeatureLevel(AndroidFeatures.NANOBOTS_REGENERATION)
research.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS_REGENERATION_LIST[i - 1]), optional = true)
} else { } else {
regeneration.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS), rigid = true) research.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS), optional = true)
research.addFeatureResult(AndroidFeatures.NANOBOTS_REGENERATION)
} }
regeneration.build() research.build()
}) })
} }
@ -216,10 +260,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
.addItem(MItemTags.TRITANIUM_PLATES, 2 + i * 2) .addItem(MItemTags.TRITANIUM_PLATES, 2 + i * 2)
.addItem(Items.SUGAR, 1 + i) .addItem(Items.SUGAR, 1 + i)
.addItem(MItems.ELECTROMAGNET) .addItem(MItems.ELECTROMAGNET)
.addFeatureResult(AndroidFeatures.NANOBOTS_ARMOR, 0, .addResult(AndroidResearchResults.NANOBOTS_ARMOR_STRENGTH)
transformersUp = listOf(NanobotsArmorFeature.STRENGTH_TRANSFORMER_UP.bind(level)),
transformersDown = listOf(NanobotsArmorFeature.STRENGTH_TRANSFORMER_DOWN.bind(level)),
)
.build() .build()
}) })
@ -243,10 +284,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
) )
) )
.addItem(Tags.Items.DUSTS_REDSTONE, 4 + i * 4) .addItem(Tags.Items.DUSTS_REDSTONE, 4 + i * 4)
.addFeatureResult(AndroidFeatures.NANOBOTS_ARMOR, 0, .addResult(AndroidResearchResults.NANOBOTS_ARMOR_SPEED)
transformersUp = listOf(NanobotsArmorFeature.SPEED_TRANSFORMER_UP.bind(level)),
transformersDown = listOf(NanobotsArmorFeature.SPEED_TRANSFORMER_DOWN.bind(level)),
)
.build() .build()
}) })
} }
@ -261,7 +299,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.SHOCKWAVE)) AndroidResearchType.Builder(modLocation(MNames.SHOCKWAVE))
.withExperience(40) .withExperience(40)
.withDescription(0 .. 1) .withDescription(0 .. 1)
.appendDescription(ShockwaveFeature.POWER_COST_DESCRIPTION) .withDescription(AndroidResearchDescriptions.SHOCKWAVE)
.withIcon(ResearchIcons.ICON_SHOCKWAVE) .withIcon(ResearchIcons.ICON_SHOCKWAVE)
.addFeatureResult(AndroidFeatures.SHOCKWAVE) .addFeatureResult(AndroidFeatures.SHOCKWAVE)
.addPrerequisite(attackBoostList[2]) .addPrerequisite(attackBoostList[2])
@ -276,7 +314,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.ITEM_MAGNET)) AndroidResearchType.Builder(modLocation(MNames.ITEM_MAGNET))
.withExperience(28) .withExperience(28)
.withDescription(0 .. 1) .withDescription(0 .. 1)
.appendDescription(ItemMagnetFeature.POWER_COST_DESCRIPTION) .withDescription(AndroidResearchDescriptions.ITEM_MAGNET)
.withIcon(ResearchIcons.ICON_ITEM_MAGNET) .withIcon(ResearchIcons.ICON_ITEM_MAGNET)
.addFeatureResult(AndroidFeatures.ITEM_MAGNET) .addFeatureResult(AndroidFeatures.ITEM_MAGNET)
.addPrerequisite(STEP_ASSIST) .addPrerequisite(STEP_ASSIST)
@ -292,9 +330,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_1")) AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_1"))
.withExperience(25) .withExperience(25)
.withDescription() .withDescription()
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(1)) .withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(1))
.withIcon(ResearchIcons.ICON_FEATHER_FALLING) .withIcon(ResearchIcons.ICON_FEATHER_FALLING)
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 0) .addFeatureResult(AndroidFeatures.FALL_DAMPENERS)
.addPrerequisite(STEP_ASSIST) .addPrerequisite(STEP_ASSIST)
.addItem(MItems.ELECTROMAGNET, 2) .addItem(MItems.ELECTROMAGNET, 2)
.addItem(ItemTags.WOOL, 2) .addItem(ItemTags.WOOL, 2)
@ -305,9 +343,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_2")) AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_2"))
.withExperience(30) .withExperience(30)
.withDescription() .withDescription()
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(2)) .withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(2))
.withIcon(ResearchIcons.ICON_FEATHER_FALLING) .withIcon(ResearchIcons.ICON_FEATHER_FALLING)
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 1) .addFeatureLevel(AndroidFeatures.FALL_DAMPENERS)
.addPrerequisite(FALL_DAMPENERS_1) .addPrerequisite(FALL_DAMPENERS_1)
.addItem(MItemTags.GOLD_PLATES, 2) .addItem(MItemTags.GOLD_PLATES, 2)
.addItem(MItemTags.COPPER_WIRES, 4) .addItem(MItemTags.COPPER_WIRES, 4)
@ -319,9 +357,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_3")) AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_3"))
.withExperience(35) .withExperience(35)
.withDescription(0 .. 1) .withDescription(0 .. 1)
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(3)) .withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(3))
.withIcon(ResearchIcons.ICON_FEATHER_FALLING) .withIcon(ResearchIcons.ICON_FEATHER_FALLING)
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 2) .addFeatureLevel(AndroidFeatures.FALL_DAMPENERS)
.addPrerequisite(FALL_DAMPENERS_2) .addPrerequisite(FALL_DAMPENERS_2)
.addItem(MItemTags.ADVANCED_CIRCUIT, 2) .addItem(MItemTags.ADVANCED_CIRCUIT, 2)
.addItem(Tags.Items.GEMS_DIAMOND, 4) .addItem(Tags.Items.GEMS_DIAMOND, 4)
@ -337,7 +375,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.ENDER_TELEPORTER)) AndroidResearchType.Builder(modLocation(MNames.ENDER_TELEPORTER))
.withExperience(35) .withExperience(35)
.withDescription() .withDescription()
.appendDescription(EnderTeleporterFeature.POWER_COST_DESCRIPTION) .withDescription(AndroidResearchDescriptions.ENDER_TELEPORTER)
.withIcon(ResearchIcons.ICON_ENDER_TELEPORT) .withIcon(ResearchIcons.ICON_ENDER_TELEPORT)
.addFeatureResult(AndroidFeatures.ENDER_TELEPORTER) .addFeatureResult(AndroidFeatures.ENDER_TELEPORTER)
.addPrerequisite(FALL_DAMPENERS_1) .addPrerequisite(FALL_DAMPENERS_1)
@ -350,27 +388,13 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
serializer.accept(ENDER_TELEPORTER) serializer.accept(ENDER_TELEPORTER)
val PHANTOM_ATTRACTOR =
AndroidResearchType.Builder(modLocation(MNames.PHANTOM_ATTRACTOR))
.withExperience(20)
.withDescription()
.withIcon(ResearchIcons.ICON_PHANTOM_ATTRACTOR)
.addFeatureResult(AndroidFeatures.PHANTOM_ATTRACTOR)
.addPrerequisite(NANOBOTS)
.addItem(MItems.PHANTOM_ATTRACTOR)
.addItem(MItemTags.COPPER_WIRES, 2)
.addItem(MItemTags.TRITANIUM_PLATES, 2)
.build()
serializer.accept(PHANTOM_ATTRACTOR)
val JUMP_BOOST_1 = val JUMP_BOOST_1 =
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_1")) AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_1"))
.withExperience(27) .withExperience(27)
.withDescription(0 .. 1) .withDescription(0 .. 1)
.appendDescription(JumpBoostFeature.POWER_COST_DESCRIPTION) .withDescription(AndroidResearchDescriptions.JUMP_BOOST)
.withIcon(ResearchIcons.ICON_JUMP_BOOST) .withIcon(ResearchIcons.ICON_JUMP_BOOST)
.addFeatureResult(AndroidFeatures.JUMP_BOOST, 0) .addFeatureResult(AndroidFeatures.JUMP_BOOST)
.addItem(MItemTags.PISTONS, 2) .addItem(MItemTags.PISTONS, 2)
.addItem(MItemTags.GOLD_WIRES, 4) .addItem(MItemTags.GOLD_WIRES, 4)
.addItem(MItems.ELECTROMAGNET, 2) .addItem(MItems.ELECTROMAGNET, 2)
@ -382,9 +406,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_2")) AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_2"))
.withExperience(34) .withExperience(34)
.withDescription() .withDescription()
.appendDescription(JumpBoostFeature.POWER_COST_DESCRIPTION) .withDescription(AndroidResearchDescriptions.JUMP_BOOST)
.withIcon(ResearchIcons.ICON_JUMP_BOOST) .withIcon(ResearchIcons.ICON_JUMP_BOOST)
.addFeatureResult(AndroidFeatures.JUMP_BOOST, 1) .addFeatureLevel(AndroidFeatures.JUMP_BOOST)
.addItem(MItems.ELECTRIC_PARTS, 4) .addItem(MItems.ELECTRIC_PARTS, 4)
.addItem(MItems.ELECTROMAGNET, 4) .addItem(MItems.ELECTROMAGNET, 4)
.addPrerequisite(JUMP_BOOST_1) .addPrerequisite(JUMP_BOOST_1)
@ -394,74 +418,179 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
serializer.accept(JUMP_BOOST_1) serializer.accept(JUMP_BOOST_1)
serializer.accept(JUMP_BOOST_2) serializer.accept(JUMP_BOOST_2)
with(lang.english) { with(lang) {
misc("fall_dampeners.description", "Reduces fall damage by %s%%") misc("fall_dampeners.description", "Reduces fall damage by %s%% and increases fall damage flat resist by %s half a hearts") {
russian("Уменьшает урон от падения на %s%% и повышает сопротивление урону от падения на %s полусердец")
}
add(limbList[0], "Limb Overclocking %s") add(limbList[0], "Limb Overclocking %s") {
add(limbList[0], "description", "Boosts unit's mobility by %s%% and attack speed by %s%%") russian("Разгон конечностей %s")
}
add(AIR_BAGS, "Air Bags") add(limbList[0], "description", "Boosts mobility by %s%%, attack speed by %s%% and brushing speed by %s%%") {
add(NANOBOTS, "Nanobots") russian("Увеличивает мобильность на %s%%, скорость атак на %s%% и скорость чистки блоков на %s%%")
add(AIR_BAGS, "description", "Allows unit to swim in water") }
add(NANOBOTS, "description", "Various useful nanobots for doing various tasks")
add(regenList[0], "Regeneration %s") add(AIR_BAGS, "Air Bags") {
add(regenList[0], "description", "Nanobots get ability to repair unit's internal systems on the move") russian("Воздушные мешки")
add(regenList[0], "description_improve", "Improves regeneration speed") }
add(NANOBOTS, "Nanobots") {
russian("Наноботы")
}
add(AIR_BAGS, "description", "Allows to swim in water") {
russian("Позволяет плавать в воде")
}
add(NANOBOTS, "description", "Various useful nanobots for doing various tasks") {
russian("Различные наноботы для различных задач")
}
add(NANOBOTS_ARMOR, "Nanobots Armor") add(regenList[0], "Regeneration %s") {
add(NANOBOTS_ARMOR, "description", "Allows nanobots to align themselves in cell shape, reducing incoming damage by a %% by absorbing impacts") russian("Регенерация %s")
}
add(regenList[0], "description", "Nanobots get ability to repair internal Android' systems on the move") {
russian("Наноботы получают возможность чинить внутренние системы Андроида на ходу")
}
add(regenList[0], "description_improve", "Improves health regeneration speed") {
russian("Улучшает скорость регенерации здоровья")
}
add(armorSpeedList[0], "Nanobots Armor Build Speed %s") add(NANOBOTS_ARMOR, "Nanobots Armor") {
add(armorSpeedList[0], "description", "Reduces time required for nanobots to form protection layer") russian("Броня из наноботов")
}
add(NANOBOTS_ARMOR, "description", "Allows nanobots to align themselves in cell shape, reducing incoming damage by a %% by absorbing impacts") {
russian("Позволяет наноботам выстраиваться в клеточную структуру, уменьшая внешний урон на определённый проект путём поглощения ударов")
}
add(armorStrengthList[0], "Nanobots Armor Strength %s") add(armorSpeedList[0], "Nanobots Armor Build Speed %s") {
add(armorStrengthList[0], "description", "Increases impact absorption strength of nanobots") russian("Скорость аостроения слоя брони наноботов %s")
}
add(armorSpeedList[0], "description", "Reduces time required for nanobots to form protection layer") {
russian("Уменьшает время необходимое наноботам для формирования защитного слоя")
}
add(EXTENDED_REACH, "Extended Reach") add(armorStrengthList[0], "Nanobots Armor Strength %s") {
add(EXTENDED_REACH, "description", "Increases block interaction distance") russian("Сила слоя брони наноботов %s")
}
add(armorStrengthList[0], "description", "Increases impact absorption strength of nanobots") {
russian("Увеличивает поглощающею силу брони наноботов")
}
add(IMPROVED_LIMBS, "Improved Limbs") add(EXTENDED_REACH, "Extended Reach") {
add(IMPROVED_LIMBS, "description", "Allows limbs to be upgraded") russian("Удлинённые манипуляторы")
}
add(EXTENDED_REACH, "description", "Increases block interaction distance") {
russian("Увеличивает радиус взаимодействия с блоками")
}
add(STEP_ASSIST, "Step Assist") add(IMPROVED_LIMBS, "Improved Limbs") {
add(STEP_ASSIST, "description", "Allows unit to step up whole blocks") russian("Улучшенные конечности")
}
add(IMPROVED_LIMBS, "description", "Allows limbs to be upgraded") {
russian("Позволяет улучшать конечности")
}
add(ITEM_MAGNET, "Item Magnet") add(SWIM_BOOSTERS, "Swim Boosters") {
add(ITEM_MAGNET, "description0", "Pulls nearby items to unit while active") russian("Плавательные лопасти")
add(ITEM_MAGNET, "description1", "Drains energy for each item stack it pulls") }
add(SWIM_BOOSTERS, "description", "Increases swimming speed by %s%%") {
russian("Ускоряет скорость плавания на %s%%")
}
add(FALL_DAMPENERS_1, "Fall Dampeners") add(SWIM_BOOSTERS_2, "Swim Boosters 2") {
add(FALL_DAMPENERS_1, "description", "Installs basic equipment in unit's limbs to negate some fall damage") russian("Плавательные лопасти 2")
}
add(FALL_DAMPENERS_2, "Fall Dampeners 2") add(SWIM_BOOSTERS_3, "Swim Boosters 3") {
add(FALL_DAMPENERS_2, "description", "Installs micro displacing and dampening equipment in unit's limbs to negate great deal of fall damage") russian("Плавательные лопасти 3")
}
add(FALL_DAMPENERS_3, "Fall Dampeners 3") add(STEP_ASSIST, "Step Assist") {
add(FALL_DAMPENERS_3, "description0", "Installs autonomous calculation matrices and hardening to crucial parts") russian("Помощь подъёма")
add(FALL_DAMPENERS_3, "description1", "of unit's limbs to land on to negate most of fall damage") }
add(STEP_ASSIST, "description", "Allows unit to step up whole blocks") {
russian("Позволяет переступать полные блоки")
}
add(SHOCKWAVE, "Shockwave Pulsator") add(ITEM_MAGNET, "Item Magnet") {
add(SHOCKWAVE, "description0", "Releases a shockwave around unit, damaging everything in small radius, as unit quickly land on ground") russian("Предметный магнит")
add(SHOCKWAVE, "description1", "It does not, however, help with ground impact damage!") }
add(ITEM_MAGNET, "description0", "Pulls nearby items while active") {
russian("Притягивает ближайшие предметы пока активен")
}
add(ITEM_MAGNET, "description1", "Drains energy for each item stack it pulls") {
russian("Потребляет энергию за каждую стопку которую притягивает магнит")
}
add(PHANTOM_ATTRACTOR, "Builtin Phantom Attractor") add(FALL_DAMPENERS_1, "Fall Dampeners") {
add(PHANTOM_ATTRACTOR, "description", "Allows unit to attract phantoms while active under same conditions as non-androids") russian("Поглотители инерции")
}
add(FALL_DAMPENERS_1, "description", "Installs basic equipment in limbs to negate some fall damage") {
russian("Обустраивает конечности примитивными деталями для небольшого смягчения падения")
}
add(JUMP_BOOST_1, "Jump Boost") add(FALL_DAMPENERS_2, "Fall Dampeners 2") {
add(JUMP_BOOST_1, "description0", "Allows unit to perform higher jump") russian("Поглотители инерции 2")
add(JUMP_BOOST_1, "description1", "Can be activated by crouching and jumping at the same time") }
add(FALL_DAMPENERS_2, "description", "Installs micro displacing and dampening equipment in limbs to negate great deal of fall damage") {
russian("Оборудует конечности микро смещающимися и смягчающим оборудованием, которое поглощает значительный урон от падения")
}
add(JUMP_BOOST_2, "Jump Boost 2") add(FALL_DAMPENERS_3, "Fall Dampeners 3") {
add(JUMP_BOOST_2, "description", "Allows unit to perform extra higher jump") russian("Поглотители инерции 3")
}
add(FALL_DAMPENERS_3, "description0", "Installs autonomous fall damage avoidance calculation matrices and hardening to crucial parts") {
russian("Устанавливает автономные матрицы калькуляции избегания урона от падения, а так же усиливает защиту важных деталей")
}
add(FALL_DAMPENERS_3, "description1", "of limbs to land on to negate most of fall damage") {
russian("от урона от падения для почти полного поглощения урона от падения")
}
add(ENDER_TELEPORTER, "Ender Teleporter") add(SHOCKWAVE, "Shockwave Pulsator") {
add(ENDER_TELEPORTER, "description", "Allows unit to perform instant, short distance teleports without damage to internal systems") russian("Генератор ударных волн")
}
add(SHOCKWAVE, "description0", "Releases a shockwave, damaging everything in small radius, as you quickly land on ground") {
russian("Вызывает ударную волну при стремительном падении на землю, нанося урон всему, что вас окружает")
}
add(SHOCKWAVE, "description1", "It does not, however, help with ground impact damage!") {
russian("Используйте с осторожностью, так как данная технология сама по себе не поглащает урон от падения!")
}
add(NIGHT_VISION, "Night Vision") add(JUMP_BOOST_1, "Jump Boost") {
add(NIGHT_VISION, "description", "Allows unit to clearly see in the dark") russian("Усилитель прыжка")
}
add(JUMP_BOOST_1, "description0", "Allows to perform higher jump") {
russian("Позволяет совершить высокий прыжок")
}
add(JUMP_BOOST_1, "description1", "Can be activated by crouching and jumping at the same time") {
russian("Для прыжка удерживайте кнопку приседания и нажмите кнопку прыжка")
}
add(attackBoostList[0], "Attack Boost %s") add(JUMP_BOOST_2, "Jump Boost 2") {
add(attackBoostList[0], "description", "Increases total melee attack strength by %s%%") russian("Усилитель прыжка 2")
}
add(JUMP_BOOST_2, "description", "Allows to perform extra higher jump") {
russian("Позволяет совершить ещё более высокий прыжок")
}
add(ENDER_TELEPORTER, "Ender Teleporter") {
russian("Телепортатор Края")
}
add(ENDER_TELEPORTER, "description", "Allows to perform instant, short distance teleports without damage to internal systems") {
russian("Позволяет совершать мгновенную телепортацию на короткую дистанцию без нанесения урона внутренним системам")
}
add(NIGHT_VISION, "Night Vision") {
russian("Ночное зрение")
}
add(NIGHT_VISION, "description", "Allows to clearly see in the dark") {
russian("Позволяет видеть в темноте")
}
add(attackBoostList[0], "Attack Boost %s") {
russian("Усиление атаки %s")
}
add(attackBoostList[0], "description", "Increases total melee attack strength by %s%%") {
russian("Увеличивает урон в ближнем бою на %s%%")
}
} }
} }

View File

@ -11,7 +11,7 @@ fun SoundDefinition.subtitle(value: SoundEvent): SoundDefinition {
return subtitle("otm.sound." + value.location.path) return subtitle("otm.sound." + value.location.path)
} }
class SoundDataProvider(event: GatherDataEvent) : SoundDefinitionsProvider(event.generator, DataGen.MOD_ID, event.existingFileHelper) { class SoundDataProvider(event: GatherDataEvent) : SoundDefinitionsProvider(event.generator.packOutput, DataGen.MOD_ID, event.existingFileHelper) {
override fun registerSounds() { override fun registerSounds() {
add(MSoundEvents.PLASMA_WEAPON_OVERHEAT, add(MSoundEvents.PLASMA_WEAPON_OVERHEAT,
definition().subtitle("otm.sound.plasma_weapon_overheat") definition().subtitle("otm.sound.plasma_weapon_overheat")
@ -34,6 +34,11 @@ class SoundDataProvider(event: GatherDataEvent) : SoundDefinitionsProvider(event
add(MSoundEvents.ANDROID_SHOCKWAVE, add(MSoundEvents.ANDROID_SHOCKWAVE,
definition().subtitle("otm.sound.android.shockwave") definition().subtitle("otm.sound.android.shockwave")
.with(SoundDefinition.Sound.sound(modLocation("android/shockwave"), SoundDefinition.SoundType.SOUND))) .with(SoundDefinition.Sound.sound(modLocation("android/shockwave"), SoundDefinition.SoundType.SOUND)))
add(MSoundEvents.ANDROID_PROJ_PARRY,
definition().subtitle("otm.sound.android.projectile_parry")
.with(SoundDefinition.Sound.sound(modLocation("android/punch_projectile"), SoundDefinition.SoundType.SOUND))
)
} }
private inline fun add(value: SoundEvent, block: SoundDefinition.() -> Unit) { private inline fun add(value: SoundEvent, block: SoundDefinition.() -> Unit) {

View File

@ -1,14 +1,11 @@
package ru.dbotthepony.mc.otm.datagen.advancements package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.Advancement
import net.minecraft.advancements.AdvancementRewards import net.minecraft.advancements.AdvancementRewards
import net.minecraft.advancements.FrameType import net.minecraft.advancements.FrameType
import net.minecraft.advancements.RequirementsStrategy import net.minecraft.advancements.RequirementsStrategy
import net.minecraft.advancements.critereon.InventoryChangeTrigger import net.minecraft.advancements.critereon.InventoryChangeTrigger
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.data.ExistingFileHelper
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
@ -16,17 +13,22 @@ import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
import ru.dbotthepony.mc.otm.triggers.NailedEntityTrigger
import java.util.function.Consumer import java.util.function.Consumer
fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) { typealias Strategy = RequirementsStrategy
val translation = lang.english.Prepended("otm.advancements.regular")
fun addAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider) {
val translation = lang.MultiBuilder("otm.advancements.regular")
val root = AdvancementBuilder() val root = AdvancementBuilder()
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_INGOT), itemStack = ItemStack(MItems.TRITANIUM_INGOT),
title = TranslatableComponent(translation.add("root", "Overdrive That Matters")), title = translation.add("root", "Overdrive That Matters"),
description = TranslatableComponent(translation.add("root.desc", "Its all about things that matter")), description = translation.add("root.desc", "It's all about things that matter") {
russian("Мод про все штуки которые материальны")
},
showToast = false, showToast = false,
announceChat = false, announceChat = false,
background = modLocation("textures/block/decorative/tritanium_block_gray.png") background = modLocation("textures/block/decorative/tritanium_block_gray.png")
@ -34,283 +36,401 @@ fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: Exist
.addCriterion("has_tritanium_ore", criterion(MItemTags.TRITANIUM_ORES)) .addCriterion("has_tritanium_ore", criterion(MItemTags.TRITANIUM_ORES))
.addCriterion("has_tritanium_ore_clump", criterion(MItemTags.TRITANIUM_ORE_CLUMPS)) .addCriterion("has_tritanium_ore_clump", criterion(MItemTags.TRITANIUM_ORE_CLUMPS))
.addCriterion("has_tritanium_ingot", InventoryChangeTrigger.TriggerInstance.hasItems(MItems.TRITANIUM_INGOT)) .addCriterion("has_tritanium_ingot", InventoryChangeTrigger.TriggerInstance.hasItems(MItems.TRITANIUM_INGOT))
.save(serializer, modLocation("regular/root"), existingFileHelper) .save(serializer, modLocation("regular/root"))
addMachineAdvancements(serializer, lang, root)
val crude = AdvancementBuilder() val crude = AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.BATTERY_CRUDE), itemStack = ItemStack(MItems.BATTERY_CRUDE),
title = TranslatableComponent(translation.add("crude_battery", "Potato Power!")), title = translation.add("crude_battery", "Potato Power!") {
description = TranslatableComponent(translation.add("crude_battery.desc", "Put together a Crude Battery. Better hope for getter better power source soon")), russian("Сила картофеля!")
},
description = translation.add("crude_battery.desc", "Put together a Crude Battery. Better hope for getting better power source soon") {
russian("Создайте Простой Аккумулятор. Надо бы поторопиться с созданием более продвинутого аккумулятора")
},
) )
.addCriterion("has_item", criterion(MItems.BATTERY_CRUDE)) .addCriterion("has_item", criterion(MItems.BATTERY_CRUDE))
.save(serializer, modLocation("regular/crude_battery"), existingFileHelper) .save(serializer, modLocation("regular/crude_battery"))
val normal = AdvancementBuilder() val normal = AdvancementBuilder()
.parent(crude) .parent(crude)
.display( .display(
itemStack = ItemStack(MItems.BATTERY_NORMAL), itemStack = ItemStack(MItems.BATTERY_NORMAL),
title = TranslatableComponent(translation.add("normal_battery", "Power Storage")), title = translation.add("normal_battery", "Power Storage") {
description = TranslatableComponent(translation.add("normal_battery.desc", "Put together an Ordinary Battery")), russian("Хранилище энергии")
},
description = translation.add("normal_battery.desc", "Put together a Battery") {
russian("Создайте аккумулятор")
},
) )
.addCriterion("has_item", criterion(MItems.BATTERY_NORMAL)) .addCriterion("has_item", criterion(MItems.BATTERY_NORMAL))
.save(serializer, modLocation("regular/normal_battery"), existingFileHelper) .save(serializer, modLocation("regular/normal_battery"))
AdvancementBuilder() AdvancementBuilder()
.parent(normal) .parent(normal)
.display( .display(
itemStack = ItemStack(MItems.BATTERY_DENSE), itemStack = ItemStack(MItems.BATTERY_DENSE),
title = TranslatableComponent(translation.add("dense_battery", "Extra Space Battery")), title = translation.add("dense_battery", "Extra Space Battery") {
description = TranslatableComponent(translation.add("dense_battery.desc", "Put together a Dense Battery. Better not to expose it to fires!")), russian("Больше места для энергии")
},
description = translation.add("dense_battery.desc", "Put together a Dense Battery. Better not to expose it to fires!") {
russian("Создайте плотный аккумулятор. Держите подальше от огня!")
},
) )
.addCriterion("has_item", criterion(MItems.BATTERY_DENSE)) .addCriterion("has_item", criterion(MItems.BATTERY_DENSE))
.save(serializer, modLocation("regular/dense_battery"), existingFileHelper) .save(serializer, modLocation("regular/dense_battery"))
val capacitor = AdvancementBuilder() val capacitor = AdvancementBuilder()
.parent(normal) .parent(normal)
.display( .display(
itemStack = ItemStack(MItems.BATTERY_CAPACITOR), itemStack = ItemStack(MItems.BATTERY_CAPACITOR),
title = TranslatableComponent(translation.add("capacitor_battery", "Supercapacitor")), title = translation.add("capacitor_battery", "Supercapacitor") {
description = TranslatableComponent(translation.add("capacitor_battery.desc", "Put together a Capacitor Battery. Surely, you gonna need them somewhere...")), russian("Сверхконденсатор")
},
description = translation.add("capacitor_battery.desc", "Put together a Capacitor Battery. Surely, you gonna need them somewhere...") {
russian("Создайте аккумулятор-конденсатор. Очень вероятно, что вы найдете ему применение...")
},
) )
.addCriterion("has_item", criterion(MItems.BATTERY_CAPACITOR)) .addCriterion("has_item", criterion(MItems.BATTERY_CAPACITOR))
.save(serializer, modLocation("regular/capacitor_battery"), existingFileHelper) .save(serializer, modLocation("regular/capacitor_battery"))
AdvancementBuilder() AdvancementBuilder()
.parent(capacitor) .parent(capacitor)
.display( .display(
itemStack = ItemStack(MItems.ENERGY_SWORD), itemStack = ItemStack(MItems.ENERGY_SWORD),
title = TranslatableComponent(translation.add("energy_sword", "Self Sharpening Blade")), title = translation.add("energy_sword", "Self Sharpening Blade") {
description = TranslatableComponent(translation.add("energy_sword.desc", "Wield a High-Frequency Blade, a melee weapon intended to slice Creepers into creep-cakes. Rational folks won't attempt to slice their Android fellows...")), russian("Клинок с самозаточкой")
},
description = translation.add("energy_sword.desc", "Wield a High-Frequency Blade, a melee weapon intended to slice Creepers into creep-cakes") {
russian("Получите высокочастотный клинок, оружие ближнего боя предназначенное для нарезания Криперов на крипо-тортики")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.addCriterion("has_item", criterion(MItems.ENERGY_SWORD)) .addCriterion("has_item", criterion(MItems.ENERGY_SWORD))
.save(serializer, modLocation("regular/energy_sword"), existingFileHelper) .save(serializer, modLocation("regular/energy_sword"))
AdvancementBuilder() AdvancementBuilder()
.parent(normal) .parent(normal)
.display( .display(
itemStack = ItemStack(MItems.QUANTUM_BATTERY), itemStack = ItemStack(MItems.QUANTUM_BATTERY),
title = TranslatableComponent(translation.add("quantum_battery", "Power, in Superposition")), title = translation.add("quantum_battery", "Power, in Superposition") {
description = TranslatableComponent(translation.add("quantum_battery.desc", "Put together a Quantum Battery, powered by Ender technologies")), russian("Энергия, в суперпозиции")
},
description = translation.add("quantum_battery.desc", "Put together a Quantum Battery, powered by Ender technologies") {
russian("Создайте квантовый аккумулятор, пропитанную технологиями Края")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.rewards(AdvancementRewards.Builder.experience(50)) .rewards(AdvancementRewards.Builder.experience(50))
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.addCriterion("has_item0", criterion(MItems.QUANTUM_BATTERY)) .addCriterion("has_item0", criterion(MItems.QUANTUM_BATTERY))
.addCriterion("has_item1", criterion(MItems.QUANTUM_CAPACITOR)) .addCriterion("has_item1", criterion(MItems.QUANTUM_CAPACITOR))
.save(serializer, modLocation("regular/quantum_battery"), existingFileHelper) .save(serializer, modLocation("regular/quantum_battery"))
AdvancementBuilder() val zpm = AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.ZPM_BATTERY), itemStack = ItemStack(MItems.ZPM_BATTERY),
title = TranslatableComponent(translation.add("zpm_battery", "Pocket Universe, as Power Source")), title = translation.add("zpm_battery", "Pocket Universe, as Power Source") {
description = TranslatableComponent(translation.add("zpm_battery.desc", "Find Zero Point Module, something from different universe of ours, created using technologies lost in time in all possible multiverses")), russian("Карманная вселенная, как источник питания")
},
description = translation.add("zpm_battery.desc", "Find Zero Point Module, something from different multiverse of ours, created using technologies lost in time in all possible multiverses") {
russian("Найдите модуль нулевой точки, вещь из другой мультивселенной, созданная с использованием технологий, потерянных во времени во всех возможных мультивслеленных")
},
frameType = FrameType.CHALLENGE, frameType = FrameType.CHALLENGE,
hidden = true hidden = true
) )
.rewards(AdvancementRewards.Builder.experience(800)) .rewards(AdvancementRewards.Builder.experience(800))
.addCriterion("has_item", criterion(MItems.ZPM_BATTERY)) .addCriterion("has_item", criterion(MItems.ZPM_BATTERY))
.save(serializer, modLocation("regular/zpm_battery"), existingFileHelper) .save(serializer, modLocation("regular/zpm_battery"))
addExopackAdvancements(serializer, lang, root, zpm)
val blackhole = AdvancementBuilder() val blackhole = AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.BLACK_HOLE), itemStack = ItemStack(MItems.BLACK_HOLE),
title = TranslatableComponent(translation.add("black_hole_pull", "Something Massive and Something Close")), title = translation.add("black_hole_pull", "Something Massive and Something Close") {
description = TranslatableComponent(translation.add("black_hole_pull.desc", "Experience Singularity's gravitational force, better not to get closer")), russian("Что то массивное и близкое")
},
description = translation.add("black_hole_pull.desc", "Experience Singularity's gravitational force, better not to get closer") {
russian("Испытайте на себе гравитационную силу сингулярности, лучше не подходить ближе")
},
hidden = true hidden = true
) )
.addCriterion("pulled_by_black_hole", BlackHoleTrigger.Instance) .addCriterion("pulled_by_black_hole", BlackHoleTrigger.criterion)
.save(serializer, modLocation("regular/black_hole"), existingFileHelper) .save(serializer, modLocation("regular/black_hole"))
AdvancementBuilder() AdvancementBuilder()
.parent(blackhole) .parent(blackhole)
.display( .display(
itemStack = ItemStack(MItems.BLACK_HOLE_SCANNER), itemStack = ItemStack(MItems.BLACK_HOLE_SCANNER),
title = TranslatableComponent(translation.add("black_hole_scanner", "Determining the Mass")), title = translation.add("black_hole_scanner", "Determining the Mass") {
description = TranslatableComponent(translation.add("black_hole_scanner.desc", "Craft the Singularity Scanner, to determine mass of Singularity from safe distance")), russian("Определяем массу")
},
description = translation.add("black_hole_scanner.desc", "Craft the Singularity Scanner, to determine mass of... Singularities, from safe distance") {
russian("Создайте сканер сингулярностей, для определения массы... Сингулярностей на безопасном расстоянии")
},
) )
.addCriterion("has_item", criterion(MItems.BLACK_HOLE_SCANNER)) .addCriterion("has_item", criterion(MItems.BLACK_HOLE_SCANNER))
.save(serializer, modLocation("regular/black_hole_scanner"), existingFileHelper) .save(serializer, modLocation("regular/black_hole_scanner"))
AdvancementBuilder() AdvancementBuilder()
.parent(blackhole) .parent(blackhole)
.display( .display(
itemStack = ItemStack(MItems.GRAVITATION_STABILIZER), itemStack = ItemStack(MItems.GRAVITATION_STABILIZER),
title = TranslatableComponent(translation.add("stabilizer", "Reducing the Impact")), title = translation.add("stabilizer", "Reducing the Impact") {
description = TranslatableComponent(translation.add("stabilizer.desc", "Put together a device that defy physical laws and also defy gravity of Singularities. Better hope it does not cause any side effects")), russian("Уменьшаем воздействие")
},
description = translation.add("stabilizer.desc", "Put together a device that defy physical laws and also defy gravity of Singularities. Better hope it does not cause any side effects") {
russian("Создайте устройство, которое смеётся перед законами физики, а так же смеётся перед силами гравитации сингулярностей. Надо надеется, что это не принесёт никаких последствий")
},
) )
.addCriterion("has_item", criterion(MItems.GRAVITATION_STABILIZER)) .addCriterion("has_item", criterion(MItems.GRAVITATION_STABILIZER))
.save(serializer, modLocation("regular/stabilizer"), existingFileHelper) .save(serializer, modLocation("regular/stabilizer"))
AdvancementBuilder() AdvancementBuilder()
.parent(blackhole) .parent(blackhole)
.display( .display(
itemStack = ItemStack(MItems.PORTABLE_GRAVITATION_STABILIZER), itemStack = ItemStack(MItems.PORTABLE_GRAVITATION_STABILIZER),
title = TranslatableComponent(translation.add("portable_stabilizer", "Local Gravity Field")), title = translation.add("portable_stabilizer", "Local Gravity Field") {
description = TranslatableComponent(translation.add("portable_stabilizer.desc", "Protect yourself from gravitational effect of Singularity using Portable Gravitation Stabilizer")), russian("Локальное поле гравитации")
},
description = translation.add("portable_stabilizer.desc", "Protect yourself from gravitational effect of Singularity using Portable Space-Time Equalizer") {
russian("Защитите себя от гравитационных эффектов Сингулярностей используя Портативный")
},
) )
.addCriterion("has_item", criterion(MItems.PORTABLE_GRAVITATION_STABILIZER)) .addCriterion("has_item", criterion(MItems.PORTABLE_GRAVITATION_STABILIZER))
.save(serializer, modLocation("regular/portable_stabilizer"), existingFileHelper) .save(serializer, modLocation("regular/portable_stabilizer"))
val ore = AdvancementBuilder() val ore = AdvancementBuilder()
.parent(root) .parent(root)
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_ORE_CLUMP), itemStack = ItemStack(MItems.TRITANIUM_ORE_CLUMP),
title = TranslatableComponent(translation.add("ore", "Blue Metal Discovery")), title = translation.add("ore", "Blue Metal Discovery") {
description = TranslatableComponent(translation.add("ore.desc", "Mine some Tritanium")), russian("Открытие синего металла")
},
description = translation.add("ore.desc", "Mine some Tritanium") {
russian("Добудьте немного тритана")
},
) )
.addCriterion("has_tritanium_ore", criterion(MItemTags.TRITANIUM_ORES)) .addCriterion("has_tritanium_ore", criterion(MItemTags.TRITANIUM_ORES))
.addCriterion("has_tritanium_ore_clump", criterion(MItemTags.TRITANIUM_ORE_CLUMPS)) .addCriterion("has_tritanium_ore_clump", criterion(MItemTags.TRITANIUM_ORE_CLUMPS))
.save(serializer, modLocation("regular/ore"), existingFileHelper) .save(serializer, modLocation("regular/ore"))
val ingot = AdvancementBuilder() val ingot = AdvancementBuilder()
.parent(ore) .parent(ore)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_INGOT), itemStack = ItemStack(MItems.TRITANIUM_INGOT),
title = TranslatableComponent(translation.add("ingot", "Acquire Harder-ware")), title = translation.add("ingot", "Acquire Harder-ware") {
description = TranslatableComponent(translation.add("ingot.desc", "Smelt a Tritanium ingot")), russian("Куй сильнее...")
},
description = translation.add("ingot.desc", "Smelt a Tritanium ingot") {
russian("Выплавьте тритановый слиток")
},
) )
.addCriterion("has_tritanium_ingot", criterion(MItemTags.TRITANIUM_INGOTS)) .addCriterion("has_tritanium_ingot", criterion(MItemTags.TRITANIUM_INGOTS))
.save(serializer, modLocation("regular/ingot"), existingFileHelper) .save(serializer, modLocation("regular/ingot"))
AdvancementBuilder() AdvancementBuilder()
.parent(ingot) .parent(ingot)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_PICKAXE), itemStack = ItemStack(MItems.TRITANIUM_PICKAXE),
title = TranslatableComponent(translation.add("pickaxe", "A Tool for Patient Miners")), title = translation.add("pickaxe", "A Tool for Patient Miners") {
description = TranslatableComponent(translation.add("pickaxe.desc", "Craft a Tritanium Pickaxe")), russian("Инструмент для неспешных шахтёров")
},
description = translation.add("pickaxe.desc", "Craft a Tritanium Pickaxe") {
russian("Создайте тритановую кирку")
},
) )
.addCriterion("has_tritanium_pickaxe", criterion(MItems.TRITANIUM_PICKAXE)) .addCriterion("has_tritanium_pickaxe", criterion(MItems.TRITANIUM_PICKAXE))
.save(serializer, modLocation("regular/pickaxe"), existingFileHelper) .save(serializer, modLocation("regular/pickaxe"))
AdvancementBuilder() AdvancementBuilder()
.parent(ingot) .parent(ingot)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_HOE), itemStack = ItemStack(MItems.TRITANIUM_HOE),
title = TranslatableComponent(translation.add("hoe", "A Tool for Farmers")), title = translation.add("hoe", "A Tool for Farmers") {
description = TranslatableComponent(translation.add("hoe.desc", "Tritanium is a very good choice for making a sturdy Hoe")), russian("Инструмент для фермеров")
},
description = translation.add("hoe.desc", "Tritanium is a very good choice for making a sturdy Hoe") {
russian("Тритан - очень хороший выбор для создания прочной Мотыги")
},
hidden = true hidden = true
) )
.addCriterion("hoe", criterion(MItems.TRITANIUM_HOE)) .addCriterion("hoe", criterion(MItems.TRITANIUM_HOE))
.save(serializer, modLocation("regular/hoe"), existingFileHelper) .save(serializer, modLocation("regular/hoe"))
val plate = AdvancementBuilder() val plate = AdvancementBuilder()
.parent(ingot) .parent(ingot)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_PLATE), itemStack = ItemStack(MItems.TRITANIUM_PLATE),
title = TranslatableComponent(translation.add("plate", "Hard Plating")), title = translation.add("plate", "Hard Plating") {
description = TranslatableComponent(translation.add("plate.desc", "Roll down some Tritanium using a Plate Press")) russian("Прочные пластины")
},
description = translation.add("plate.desc", "Roll down some Tritanium using a Plate Press") {
russian("Раскатайте немного тритана используя пресс пластин")
}
) )
.addCriterion("has_item", criterion(MItemTags.TRITANIUM_PLATES)) .addCriterion("has_item", criterion(MItemTags.TRITANIUM_PLATES))
.save(serializer, modLocation("regular/plate"), existingFileHelper) .save(serializer, modLocation("regular/plate"))
AdvancementBuilder() AdvancementBuilder()
.parent(plate) .parent(plate)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_CHESTPLATE), itemStack = ItemStack(MItems.TRITANIUM_CHESTPLATE),
title = TranslatableComponent(translation.add("armor", "Composite Armor")), title = translation.add("armor", "Composite Armor") {
description = TranslatableComponent(translation.add("armor.desc", "Bend some Tritanium plates into simple yet sturdy armor")) russian("Композитная броня")
},
description = translation.add("armor.desc", "Bend some Tritanium Plates and Carbon Mesh into incredibly sturdy armor") {
russian("Согните немного тритановых пластин вместе с углеродной сеткой в невероятно прочную броню")
}
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.addCriterion("has_item0", criterion(MItems.TRITANIUM_HELMET)) .addCriterion("has_item0", criterion(MItems.TRITANIUM_HELMET))
.addCriterion("has_item1", criterion(MItems.TRITANIUM_CHESTPLATE)) .addCriterion("has_item1", criterion(MItems.TRITANIUM_CHESTPLATE))
.addCriterion("has_item2", criterion(MItems.TRITANIUM_PANTS)) .addCriterion("has_item2", criterion(MItems.TRITANIUM_PANTS))
.addCriterion("has_item3", criterion(MItems.TRITANIUM_BOOTS)) .addCriterion("has_item3", criterion(MItems.TRITANIUM_BOOTS))
.save(serializer, modLocation("regular/armor"), existingFileHelper) .save(serializer, modLocation("regular/armor"))
AdvancementBuilder()
.parent(ingot)
.display(
itemStack = ItemStack(MItems.SIMPLE_TRITANIUM_CHESTPLATE),
title = translation.add("simple_armor", "Sturdy Armor") {
russian("Прочная броня")
},
description = translation.add("simple_armor.desc", "Put togeher Simple Tritanium Armor from Tritanium Ingots, simple and effective") {
russian("Создайте простую тритановую броню из слитков, просто и эффективно")
}
)
.requirements(Strategy.OR)
.addCriterion("has_item0", criterion(MItems.SIMPLE_TRITANIUM_HELMET))
.addCriterion("has_item1", criterion(MItems.SIMPLE_TRITANIUM_CHESTPLATE))
.addCriterion("has_item2", criterion(MItems.SIMPLE_TRITANIUM_PANTS))
.addCriterion("has_item3", criterion(MItems.SIMPLE_TRITANIUM_BOOTS))
.save(serializer, modLocation("regular/simple_armor"))
val glass = AdvancementBuilder() val glass = AdvancementBuilder()
.parent(plate) .parent(plate)
.display( .display(
itemStack = ItemStack(MRegistry.INDUSTRIAL_GLASS.item), itemStack = ItemStack(MRegistry.INDUSTRIAL_GLASS.item),
title = TranslatableComponent(translation.add("industrial_glass", "Extra Hard Glass")), title = translation.add("industrial_glass", "Extra Hard Glass") {
description = TranslatableComponent(translation.add("industrial_glass.desc", "Manual says it should be bulletproof.")) russian("Дополнительно прочное стекло")
},
description = translation.add("industrial_glass.desc", "Manual says it should be bulletproof.") {
russian("В инструкции указано что оно должно быть пуленепробиваемо.")
}
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.also { advancement -> .also { advancement ->
MRegistry.INDUSTRIAL_GLASS.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.INDUSTRIAL_GLASS.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/industrial_glass"), existingFileHelper) .save(serializer, modLocation("regular/industrial_glass"))
AdvancementBuilder() AdvancementBuilder()
.parent(glass) .parent(glass)
.display( .display(
itemStack = ItemStack(MRegistry.INDUSTRIAL_GLASS.getItem(DyeColor.GREEN)), itemStack = ItemStack(MRegistry.INDUSTRIAL_GLASS.getItem(DyeColor.GREEN)),
title = TranslatableComponent(translation.add("industrial_glass2", "Glass-tacular Artist")), title = translation.add("industrial_glass2", "Glass-Tacular Artist") {
description = TranslatableComponent(translation.add("industrial_glass2.desc", "Paint Industrial Glass all possible colors")), russian("Стекло-чаровательный артист")
},
description = translation.add("industrial_glass2.desc", "Paint Industrial Glass all possible colors") {
russian("Покрасьте промышленное стекло во все возможные цвета")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.requirements(RequirementsStrategy.AND) .requirements(Strategy.AND)
.also { advancement -> .also { advancement ->
MRegistry.INDUSTRIAL_GLASS.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.INDUSTRIAL_GLASS.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/industrial_glass2"), existingFileHelper) .save(serializer, modLocation("regular/industrial_glass2"))
val cargoCrate = AdvancementBuilder() val cargoCrate = AdvancementBuilder()
.parent(plate) .parent(plate)
.display( .display(
itemStack = ItemStack(MRegistry.CARGO_CRATES.item), itemStack = ItemStack(MRegistry.CARGO_CRATES.item),
title = TranslatableComponent(translation.add("cargo_crate", "Sturdy Item Stash")), title = translation.add("cargo_crate", "Sturdy Item Stash") {
description = TranslatableComponent(translation.add("cargo_crate.desc", "Cargo Crates, like Double Chest, but Single.")) russian("Прочное хранилище предметов")
},
description = translation.add("cargo_crate.desc", "Cargo Crates, like Double Chest, but Single") {
russian("Грузовые ящики, будто двойные сундуки, но одинарные.")
}
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.also { advancement -> .also { advancement ->
MRegistry.CARGO_CRATES.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.CARGO_CRATES.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/cargo_crate"), existingFileHelper) .save(serializer, modLocation("regular/cargo_crate"))
val cargoCrateInMinecart = AdvancementBuilder() val cargoCrateInMinecart = AdvancementBuilder()
.parent(cargoCrate) .parent(cargoCrate)
.display( .display(
itemStack = ItemStack(MItems.CARGO_CRATE_MINECARTS[null]!!), itemStack = ItemStack(MItems.CARGO_CRATE_MINECARTS[null]!!),
title = TranslatableComponent(translation.add("cargo_crate_minecart", "Crate On a Rail")), title = translation.add("cargo_crate_minecart", "Crate On a Rail") {
description = TranslatableComponent(translation.add("cargo_crate_minecart.desc", "Drop a Cargo Crate onto Minecart and see how it goes")) russian("Ящик на рельсах")
},
description = translation.add("cargo_crate_minecart.desc", "Drop a Cargo Crate onto Minecart and see how it goes") {
russian("Сбросьте грузовой ящик в вагонетку и посмотрите, что получится")
}
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.also { advancement -> .also { advancement ->
MItems.CARGO_CRATE_MINECARTS.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MItems.CARGO_CRATE_MINECARTS.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/cargo_crate_minecart"), existingFileHelper) .save(serializer, modLocation("regular/cargo_crate_minecart"))
AdvancementBuilder() AdvancementBuilder()
.parent(cargoCrateInMinecart) .parent(cargoCrateInMinecart)
.display( .display(
itemStack = ItemStack(MItems.CARGO_CRATE_MINECARTS[DyeColor.GREEN]!!), itemStack = ItemStack(MItems.CARGO_CRATE_MINECARTS[DyeColor.GREEN]!!),
title = TranslatableComponent(translation.add("cargo_crate_minecart2", "A Motley Train")), title = translation.add("cargo_crate_minecart2", "A Motley Train") {
description = TranslatableComponent(translation.add("cargo_crate_minecart2.desc", "Have all color variants of Minecarts with Cargo Crates")), russian("Пёстрый поезд")
},
description = translation.add("cargo_crate_minecart2.desc", "Have all color variants of Minecarts with Cargo Crates") {
russian("Создайте все варианты покрасок вагонеток с грузовыми Ящиками")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.requirements(RequirementsStrategy.AND) .requirements(Strategy.AND)
.also { advancement -> .also { advancement ->
MItems.CARGO_CRATE_MINECARTS.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MItems.CARGO_CRATE_MINECARTS.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/cargo_crate_minecart2"), existingFileHelper) .save(serializer, modLocation("regular/cargo_crate_minecart2"))
AdvancementBuilder() AdvancementBuilder()
.parent(cargoCrate) .parent(cargoCrate)
.display( .display(
itemStack = ItemStack(MRegistry.CARGO_CRATES.item), itemStack = ItemStack(MRegistry.CARGO_CRATES.item),
title = TranslatableComponent(translation.add("cargo_crate2", "Colorful Warehouse")), title = translation.add("cargo_crate2", "Colorful Warehouse") {
description = TranslatableComponent(translation.add("cargo_crate2.desc", "Craft all color variants of Cargo Crates")), russian("Разноцветный склад")
},
description = translation.add("cargo_crate2.desc", "Craft all color variants of Cargo Crates") {
russian("Покрасьте грузовые ящики во все возможные цвета")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.requirements(RequirementsStrategy.AND) .requirements(Strategy.AND)
.also { advancement -> .also { advancement ->
MRegistry.CARGO_CRATES.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.CARGO_CRATES.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/cargo_crate2"), existingFileHelper) .save(serializer, modLocation("regular/cargo_crate2"))
val tritaniumBlock = AdvancementBuilder() val tritaniumBlock = AdvancementBuilder()
.parent(plate) .parent(ingot)
.display( .display(
itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.item), itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.item),
title = TranslatableComponent(translation.add("tritanium_block", "Cold, Impregnable Wall")), title = translation.add("tritanium_block", "Cold, Impregnable Wall") {
description = TranslatableComponent(translation.add("tritanium_block.desc", "Coat stones in Tritanium Plates, a cheap yet incredibly sturdy material")) russian("Холодная, неприступная стена")
},
description = translation.add("tritanium_block.desc", "Coat stones in Tritanium, a cheap yet incredibly sturdy material") {
russian("Покройте булыжник в тритане, дешёвый, но невероятно прочный материал")
}
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.also { advancement -> .also { advancement ->
MRegistry.TRITANIUM_BLOCK.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.TRITANIUM_BLOCK.allItems.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
MRegistry.TRITANIUM_STRIPED_BLOCK.flatItems.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.TRITANIUM_STRIPED_BLOCK.flatItems.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
@ -319,30 +439,38 @@ fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: Exist
MItems.TRITANIUM_STRIPED_BLOCK.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MItems.TRITANIUM_STRIPED_BLOCK.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
MItems.TRITANIUM_STRIPED_STAIRS.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MItems.TRITANIUM_STRIPED_STAIRS.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/tritanium_block"), existingFileHelper) .save(serializer, modLocation("regular/tritanium_block"))
AdvancementBuilder() AdvancementBuilder()
.parent(tritaniumBlock) .parent(tritaniumBlock)
.display( .display(
itemStack = ItemStack(MItems.TRITANIUM_STRIPED_BLOCK), itemStack = ItemStack(MItems.TRITANIUM_STRIPED_BLOCK),
title = TranslatableComponent(translation.add("striped_tritanium_block", "Old Fashion Color Touch")), title = translation.add("striped_tritanium_block", "Old Fashion Color Touch") {
description = TranslatableComponent(translation.add("striped_tritanium_block.desc", "Pale Blue coat with Yellow stripe, I bet you know whose design is this")) russian("Старомодная цветовая отделка")
},
description = translation.add("striped_tritanium_block.desc", "Pale Blue coat with Yellow stripe, I bet you know whose design is this") {
russian("Бледно синяя покраска с жёлтой полоской, я готов поспорить вы знаете чей это дизайн")
}
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.addCriterion("has_item", criterion(MItems.TRITANIUM_STRIPED_BLOCK)) .addCriterion("has_item", criterion(MItems.TRITANIUM_STRIPED_BLOCK))
.addCriterion("has_item1", criterion(MItems.TRITANIUM_STRIPED_STAIRS)) .addCriterion("has_item1", criterion(MItems.TRITANIUM_STRIPED_STAIRS))
.addCriterion("has_item2", criterion(MItems.TRITANIUM_STRIPED_SLAB)) .addCriterion("has_item2", criterion(MItems.TRITANIUM_STRIPED_SLAB))
.addCriterion("has_item3", criterion(MItems.TRITANIUM_STRIPED_WALL)) .addCriterion("has_item3", criterion(MItems.TRITANIUM_STRIPED_WALL))
.save(serializer, modLocation("regular/striped_tritanium_block"), existingFileHelper) .save(serializer, modLocation("regular/striped_tritanium_block"))
val colorTritaniumBlock = AdvancementBuilder() val colorTritaniumBlock = AdvancementBuilder()
.parent(tritaniumBlock) .parent(tritaniumBlock)
.display( .display(
itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.getItem(DyeColor.GREEN)), itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.getItem(DyeColor.GREEN)),
title = TranslatableComponent(translation.add("tritanium_block2", "Colorful Fortress")), title = translation.add("tritanium_block2", "Colorful Fortress") {
description = TranslatableComponent(translation.add("tritanium_block2.desc", "Put some paint over Tritanium Block to make it look fabulous")) russian("Разноцветная крепость")
},
description = translation.add("tritanium_block2.desc", "Put some paint over Tritanium Block to make it look fabulous") {
russian("Покрасьте тритановый блок для придания ему сказочных оттенков")
}
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.also { advancement -> .also { advancement ->
MRegistry.TRITANIUM_BLOCK.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.TRITANIUM_BLOCK.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
MRegistry.TRITANIUM_STAIRS.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.TRITANIUM_STAIRS.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
@ -351,68 +479,114 @@ fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: Exist
MItems.TRITANIUM_STRIPED_BLOCK.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MItems.TRITANIUM_STRIPED_BLOCK.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
MItems.TRITANIUM_STRIPED_STAIRS.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MItems.TRITANIUM_STRIPED_STAIRS.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/tritanium_block2"), existingFileHelper) .save(serializer, modLocation("regular/tritanium_block2"))
val colorfulTritaniumBlock = AdvancementBuilder() val colorfulTritaniumBlock = AdvancementBuilder()
.parent(colorTritaniumBlock) .parent(colorTritaniumBlock)
.display( .display(
itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.getItem(DyeColor.BLACK)), itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.getItem(DyeColor.BLACK)),
title = TranslatableComponent(translation.add("tritanium_block3", "Paint Me A Castle")), title = translation.add("tritanium_block3", "Paint Me A Castle") {
description = TranslatableComponent(translation.add("tritanium_block3.desc", "Craft all color variants of Tritanium Blocks")), russian("Разукрась мне замок")
},
description = translation.add("tritanium_block3.desc", "Craft all color variants of Tritanium Blocks") {
russian("Создайте все варианты покрасок тритановых Блоков")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.rewards(AdvancementRewards.Builder.loot(modLocation("tritanium_block3")).addExperience(100)) .rewards(AdvancementRewards.Builder.loot(modLocation("tritanium_block3")).addExperience(100))
.requirements(RequirementsStrategy.AND) .requirements(Strategy.AND)
.also { advancement -> .also { advancement ->
MRegistry.TRITANIUM_BLOCK.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.TRITANIUM_BLOCK.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/tritanium_block3"), existingFileHelper) .save(serializer, modLocation("regular/tritanium_block3"))
AdvancementBuilder() AdvancementBuilder()
.parent(colorfulTritaniumBlock) .parent(colorfulTritaniumBlock)
.display( .display(
itemStack = ItemStack(MRegistry.TRITANIUM_STRIPED_BLOCK.getItem(DyeColor.BLACK, DyeColor.WHITE)), itemStack = ItemStack(MRegistry.TRITANIUM_STRIPED_BLOCK.getItem(DyeColor.BLACK, DyeColor.WHITE)),
title = TranslatableComponent(translation.add("tritanium_block4", "All The Colors")), title = translation.add("tritanium_block4", "All The Colors") {
description = TranslatableComponent(translation.add("tritanium_block4.desc", "Craft ALL color variants of Tritanium Blocks including striped ones")), russian("Все цвета всё сюда")
},
description = translation.add("tritanium_block4.desc", "Craft ALL color variants of Tritanium Blocks including striped ones") {
russian("Создайте АБСОЛЮТНО ВСЕ варианты покрасок тритановых блоков, включая с полосками")
},
frameType = FrameType.CHALLENGE frameType = FrameType.CHALLENGE
) )
.rewards(AdvancementRewards.Builder.loot(modLocation("tritanium_block4")).addExperience(400)) .rewards(AdvancementRewards.Builder.loot(modLocation("tritanium_block4")).addExperience(400))
.requirements(RequirementsStrategy.AND) .requirements(Strategy.AND)
.also { advancement -> .also { advancement ->
MRegistry.TRITANIUM_BLOCK.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.TRITANIUM_BLOCK.items.values.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
MRegistry.TRITANIUM_STRIPED_BLOCK.flatItems.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MRegistry.TRITANIUM_STRIPED_BLOCK.flatItems.forEach { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
MItems.TRITANIUM_STRIPED_BLOCK.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) } MItems.TRITANIUM_STRIPED_BLOCK.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
} }
.save(serializer, modLocation("regular/tritanium_block4"), existingFileHelper) .save(serializer, modLocation("regular/tritanium_block4"))
val pill = AdvancementBuilder() val pill = AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.PILL_ANDROID), itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(translation.add("pill", "Side Colored Mystery")), title = translation.add("pill", "Side Colored Mystery") {
description = TranslatableComponent(translation.add("pill.desc", "Find some of those mysterious pills. Consult with Cleric before trying to ingest them.")), russian("Мистика с цветными краями")
},
description = translation.add("pill.desc", "Find some of those mysterious pills") {
russian("Найдите одну из этих ваших мистических пилюль")
},
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.addCriterion("pill1", criterion(MItems.PILL_ANDROID)) .addCriterion("pill1", criterion(MItems.PILL_ANDROID))
.addCriterion("pill2", criterion(MItems.PILL_HEAL)) .addCriterion("pill2", criterion(MItems.PILL_HEAL))
.addCriterion("pill3", criterion(MItems.PILL_HUMANE)) .addCriterion("pill3", criterion(MItems.PILL_HUMANE))
.addCriterion("pill4", criterion(MItems.PILL_OBLIVION)) .addCriterion("pill4", criterion(MItems.PILL_OBLIVION))
.save(serializer, modLocation("regular/pill"), existingFileHelper) .save(serializer, modLocation("regular/pill"))
AdvancementBuilder() AdvancementBuilder()
.parent(pill) .parent(pill)
.display( .display(
itemStack = ItemStack(MItems.PILL_HEAL), itemStack = ItemStack(MItems.PILL_HEAL),
title = TranslatableComponent(translation.add("all_pills", "Take Your Meds")), title = translation.add("all_pills", "Take Your Meds") {
description = TranslatableComponent(translation.add("all_pills.desc", "Find all possible pill types")), russian("Пей таблетки")
},
description = translation.add("all_pills.desc", "Find all possible pill types") {
russian("Найдите всевозможные варианты пилюль")
},
frameType = FrameType.CHALLENGE, frameType = FrameType.CHALLENGE,
hidden = true hidden = true
) )
.rewards(AdvancementRewards.Builder.experience(200)) .rewards(AdvancementRewards.Builder.experience(200))
.requirements(RequirementsStrategy.AND) .requirements(Strategy.AND)
.addCriterion("pill1", criterion(MItems.PILL_ANDROID)) .addCriterion("pill1", criterion(MItems.PILL_ANDROID))
.addCriterion("pill2", criterion(MItems.PILL_HEAL)) .addCriterion("pill2", criterion(MItems.PILL_HEAL))
.addCriterion("pill3", criterion(MItems.PILL_HUMANE)) .addCriterion("pill3", criterion(MItems.PILL_HUMANE))
.addCriterion("pill4", criterion(MItems.PILL_OBLIVION)) .addCriterion("pill4", criterion(MItems.PILL_OBLIVION))
.save(serializer, modLocation("regular/all_pills"), existingFileHelper) .save(serializer, modLocation("regular/all_pills"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.ESSENCE_CAPSULE),
title = translation.add("essence_capsule", "Forgot To Forget") {
russian("Я забыл забыть")
},
description = translation.add("essence_capsule.desc", "Recover Essence Capsule. Memories...") {
russian("Верните капсулу эссенции. Воспоминания...")
},
)
.requirements(Strategy.OR)
.addCriterion("essence1", criterion(MItems.ESSENCE_CAPSULE))
.addCriterion("essence2", criterion(MItems.ESSENCE_DRIVE))
.save(serializer, modLocation("regular/essence_capsule"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.EXPLOSIVE_HAMMER).also { MItems.EXPLOSIVE_HAMMER.prime(it) },
title = translation.add("explosive_hammer", "I Did It Like This") {
russian("Я сделал это вот так")
},
description = translation.add("explosive_hammer.desc", "Nail down something (or someone)") {
russian("Пригвоздите что-либо (или кого-либо)")
}
)
.addCriterion("damage", NailedEntityTrigger.Instance().criterion())
.save(serializer, modLocation("regular/explosive_hammer"))
} }

View File

@ -1,27 +0,0 @@
package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.Advancement
import net.minecraftforge.common.data.ExistingFileHelper
import net.minecraftforge.data.event.GatherDataEvent
import java.util.LinkedList
import java.util.function.Consumer
class AdvancementProvider(event: GatherDataEvent) : net.minecraft.data.advancements.AdvancementProvider(event.generator, event.existingFileHelper) {
private val callbacks = LinkedList<(Consumer<Advancement>, ExistingFileHelper) -> Unit>()
fun exec(callback: (Consumer<Advancement>, ExistingFileHelper) -> Unit) {
callbacks.add(callback)
}
fun exec(callback: (Consumer<Advancement>) -> Unit) {
callbacks.add { it, _ ->
callback.invoke(it)
}
}
override fun registerAdvancements(consumer: Consumer<Advancement>, fileHelper: ExistingFileHelper) {
for (callback in callbacks) {
callback.invoke(consumer, fileHelper)
}
}
}

View File

@ -1,266 +1,310 @@
package ru.dbotthepony.mc.otm.datagen.advancements package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.Advancement
import net.minecraft.advancements.AdvancementRewards import net.minecraft.advancements.AdvancementRewards
import net.minecraft.advancements.FrameType import net.minecraft.advancements.FrameType
import net.minecraft.advancements.RequirementsStrategy
import net.minecraft.advancements.critereon.DamagePredicate
import net.minecraft.advancements.critereon.DamageSourcePredicate
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.InventoryChangeTrigger
import net.minecraft.advancements.critereon.ItemPredicate import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.advancements.critereon.MinMaxBounds.Doubles import net.minecraft.advancements.critereon.MinMaxBounds.Doubles
import net.minecraft.advancements.critereon.PlayerHurtEntityTrigger
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.EntityType
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraftforge.common.data.ExistingFileHelper
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
import ru.dbotthepony.mc.otm.triggers.AndroidTravelUnderwater
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidDeathTrigger import ru.dbotthepony.mc.otm.triggers.BecomeAndroidDeathTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidSleepTrigger import ru.dbotthepony.mc.otm.triggers.BecomeAndroidSleepTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidTrigger import ru.dbotthepony.mc.otm.triggers.BecomeAndroidTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
import ru.dbotthepony.mc.otm.triggers.KillAsAndroidTrigger
import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger
import ru.dbotthepony.mc.otm.triggers.PhantomSpawnDeniedTrigger
import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger
import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
import java.util.*
import java.util.function.Consumer import java.util.function.Consumer
fun addAndroidAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) { fun addAndroidAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider) {
val translation = lang.english.Prepended("otm.advancements.android") val translation = lang.MultiBuilder("otm.advancements.android")
val root = AdvancementBuilder() val root = AdvancementBuilder()
.display( .display(
itemStack = ItemStack(MItems.PILL_ANDROID), itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(translation.add("root", "Androids and Humans")), title = translation.add("root", "Androids and Humans") {
description = TranslatableComponent(translation.add("root.desc", "Can you make out who is cruel machine and who can love?")), russian("Андроиды и люди")
},
description = translation.add("root.desc", "Can you make out who is cruel machine and who shows empathy?") {
russian("Сможете ли вы отличить бездушную машину от того, кто показывает сочувствие?")
},
showToast = false, showToast = false,
announceChat = false, announceChat = false,
background = modLocation("textures/block/decorative/metal_beam_top.png") background = modLocation("textures/block/decorative/metal_beam_top.png")
) )
.addCriterion("became_android", BecomeAndroidTrigger.Instance) .addCriterion("became_android", BecomeAndroidTrigger.criterion)
.save(serializer, modLocation("android/root"), existingFileHelper) .save(serializer, modLocation("android/root"))
AdvancementBuilder() AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.ZPM_BATTERY), itemStack = ItemStack(MItems.ZPM_BATTERY),
title = TranslatableComponent(translation.add("zpm", "Fully Autonomous")), title = translation.add("zpm", "Fully Autonomous") {
description = TranslatableComponent(translation.add("zpm.desc", "Use Zero Point Module as internal battery power source. Only time is your enemy now")), russian("Полностью автономный")
},
description = translation.add("zpm.desc", "Use Zero Point Module as internal battery power source. Only eternity is your enemy now") {
russian("Используйте модуль нулевой точки как внутренний источник питания. Теперь только вечность будет вашим злейшим врагом")
},
hidden = true, hidden = true,
frameType = FrameType.CHALLENGE frameType = FrameType.CHALLENGE
) )
.addCriterion("item", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.ZPM_BATTERY).build())) .addCriterion("item", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.ZPM_BATTERY).build()).criterion())
.save(serializer, modLocation("android/zpm"), existingFileHelper) .save(serializer, modLocation("android/zpm"))
AdvancementBuilder() AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.QUANTUM_BATTERY), itemStack = ItemStack(MItems.QUANTUM_BATTERY),
title = TranslatableComponent(translation.add("quantum_battery", "Wireless Charged")), title = translation.add("quantum_battery", "Wireless Charged") {
description = TranslatableComponent(translation.add("quantum_battery.desc", "Use Quantum Battery as internal battery power source, might as well have Fission Reactor charge other side of the link")), russian("Беспроводная зарядка")
},
description = translation.add("quantum_battery.desc", "Use Quantum Battery as internal battery power source, might as well have Fission Reactor charge other side of the link") {
russian("Используйте Квантовый Аккумулятор как внутренний источник питания, можно даже подключить другой конец к Реактору Распада")
},
hidden = true, hidden = true,
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.requirements(RequirementsStrategy.OR) .requirements(Strategy.OR)
.addCriterion("item0", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_BATTERY).build())) .addCriterion("item0", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_BATTERY).build()).criterion())
.addCriterion("item1", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_CAPACITOR).build())) .addCriterion("item1", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_CAPACITOR).build()).criterion())
.save(serializer, modLocation("android/quantum_battery"), existingFileHelper) .save(serializer, modLocation("android/quantum_battery"))
AdvancementBuilder() AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.PILL_ANDROID), itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(translation.add("normal", "Last Sweet Dreams")), title = translation.add("normal", "Last Sweet Dreams") {
description = TranslatableComponent(translation.add("normal.desc", "Become an Android in your dreams, a soulless machine... Or is it?")), russian("Последние сновидения")
},
description = translation.add("normal.desc", "Become an Android in your dreams, a soulless machine... Or is it?") {
russian("Превратитесь в андроида во сне, в бездушную машину... Или нет?")
},
hidden = true, hidden = true,
) )
.addCriterion("became_android", BecomeAndroidSleepTrigger.Instance) .addCriterion("became_android", BecomeAndroidSleepTrigger.criterion)
.save(serializer, modLocation("android/become_thru_sleep"), existingFileHelper) .save(serializer, modLocation("android/become_thru_sleep"))
AdvancementBuilder() AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.PILL_ANDROID), itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(translation.add("death", "The Old Way")), title = translation.add("death", "The Old Way") {
description = TranslatableComponent(translation.add("death.desc", "Become an Android in event of death, veteran's favorite")), russian("Изготовленный по старинке")
},
description = translation.add("death.desc", "In event of death, become an Android; Veteran's favorite") {
russian("Станьте андроидом, будучи умерев; Ветераны оценят")
},
hidden = true, hidden = true,
) )
.addCriterion("became_android", BecomeAndroidDeathTrigger.Instance) .addCriterion("became_android", BecomeAndroidDeathTrigger.criterion)
.save(serializer, modLocation("android/become_thru_death"), existingFileHelper) .save(serializer, modLocation("android/become_thru_death"))
AdvancementBuilder() AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.PILL_HUMANE), itemStack = ItemStack(MItems.PILL_HUMANE),
title = TranslatableComponent(translation.add("unandroid", "Feel Humane Again")), title = translation.add("unandroid", "Feel Humane Again") {
description = TranslatableComponent(translation.add("unandroid.desc", "Become fleshy after being a machine, yet something is still missing that you had before...")), russian("Вкусить человечность вновь")
},
description = translation.add("unandroid.desc", "Become fleshy after being a machine, yet something is still missing that you had before...") {
russian("Вновь обретите плоть после своей жизни как набор гаек и болтов, но вот чего-то всё равно не хватает, что было при вас с самого начала...")
},
hidden = true, hidden = true,
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.addCriterion("become_humane", BecomeHumaneTrigger.Instance) .addCriterion("become_humane", BecomeHumaneTrigger.criterion)
.save(serializer, modLocation("android/become_humane"), existingFileHelper) .save(serializer, modLocation("android/become_humane"))
val phantoms = AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(Items.PHANTOM_MEMBRANE),
title = TranslatableComponent(translation.add("phantom_spawn_denied", "Insomnia Immune")),
description = TranslatableComponent(translation.add("phantom_spawn_denied.desc", "Have Phantoms not come after you because you are not someone who needs to sleep")),
hidden = true
)
.addCriterion("phantom_spawn_denied", PhantomSpawnDeniedTrigger.Instance)
.save(serializer, modLocation("android/phantom_spawn_denied"), existingFileHelper)
val attractor = AdvancementBuilder() val attractor = AdvancementBuilder()
.parent(phantoms) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.PHANTOM_ATTRACTOR), itemStack = ItemStack(MItems.PHANTOM_ATTRACTOR),
title = TranslatableComponent(translation.add("phantom_attractor", "Eversleeping Decoy")), title = translation.add("phantom_attractor", "Eversleeping Decoy") {
description = TranslatableComponent(translation.add("phantom_attractor.desc", "Put together a Phantom Attractor, to be able to fight Phantoms as Android again")), russian("Фантоматичная приманка")
},
description = translation.add("phantom_attractor.desc", "Put together a Phantom Attractor, to be able to fight Phantoms as Android again") {
russian("Создайте приманщик фантомов, для привлечения фантомов вновь, будучи андроидом")
},
) )
.addCriterion("has_item", criterion(MItems.PHANTOM_ATTRACTOR)) .addCriterion("has_item", criterion(MItems.PHANTOM_ATTRACTOR))
.save(serializer, modLocation("regular/phantom_attractor"), existingFileHelper) .save(serializer, modLocation("regular/phantom_attractor"))
AdvancementBuilder()
.parent(attractor)
.display(
itemStack = ItemStack(MItems.PHANTOM_ATTRACTOR),
title = TranslatableComponent(translation.add("phantom_attractor_research", "Deception of Phantoms")),
description = TranslatableComponent(translation.add("phantom_attractor_research.desc", "Research into how to attract Phantoms the same way as the ones who need to sleep")),
)
.addCriterion("researched", AndroidResearchTrigger.Instance(modLocation(MNames.PHANTOM_ATTRACTOR)))
.save(serializer, modLocation("regular/phantom_attractor_research"), existingFileHelper)
val researchAnything = AdvancementBuilder() val researchAnything = AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.ANDROID_STATION), itemStack = ItemStack(MItems.ANDROID_STATION),
title = TranslatableComponent(translation.add("research_anything", "New Trick")), title = translation.add("research_anything", "New Trick") {
description = TranslatableComponent(translation.add("research_anything.desc", "Research anything as Android")), russian("Новый фокус")
},
description = translation.add("research_anything.desc", "Research anything as Android") {
russian("Исследуйте что либо за андроида")
},
) )
.addCriterion("research_anything", AndroidResearchTrigger.Instance(null)) .addCriterion("research_anything", AndroidResearchTrigger.Instance(Optional.empty(), Optional.empty()).criterion())
.save(serializer, modLocation("android/research_anything"), existingFileHelper) .save(serializer, modLocation("android/research_anything"))
AdvancementBuilder() AdvancementBuilder()
.parent(researchAnything) .parent(researchAnything)
.display( .display(
itemStack = ItemStack(Items.WATER_BUCKET), itemStack = ItemStack(Items.WATER_BUCKET),
title = TranslatableComponent(translation.add("air_bags", "Patching Up Wooden Vessel")), title = translation.add("air_bags", "Patching Up Wooden Vessel") {
description = TranslatableComponent(translation.add("air_bags.desc", "Research Air Bags as Android, to float in water")), russian("В бочку - затычку")
},
description = translation.add("air_bags.desc", "Research Air Bags as Android, to float in water") {
russian("Исследуйте воздушные мешки, дабы быть вновь поплавком в воде")
},
) )
.addCriterion("air_bags", AndroidResearchTrigger.Instance(modLocation(MNames.AIR_BAGS))) .addCriterion("air_bags", AndroidResearchTrigger.Instance(modLocation(MNames.AIR_BAGS)).criterion())
.save(serializer, modLocation("android/research_air_bags"), existingFileHelper) .save(serializer, modLocation("android/research_air_bags"))
AdvancementBuilder() AdvancementBuilder()
.parent(researchAnything) .parent(researchAnything)
.display( .display(
itemStack = ItemStack(Items.ENDER_EYE), itemStack = ItemStack(Items.ENDER_EYE),
title = TranslatableComponent(translation.add("night_vision", "Second Pair of Eyes")), title = translation.add("night_vision", "Second Pair of Eyes") {
description = TranslatableComponent(translation.add("night_vision.desc", "Research Night Vision as Android, to see in the dark")), russian("Вторая пара глаз")
},
description = translation.add("night_vision.desc", "Research Night Vision as Android, to see in the dark") {
russian("Исследуйте ночное зрение за андроида, дабы видеть во темноте")
},
) )
.addCriterion("night_vision", AndroidResearchTrigger.Instance(modLocation(MNames.NIGHT_VISION))) .addCriterion("night_vision", AndroidResearchTrigger.Instance(modLocation(MNames.NIGHT_VISION)).criterion())
.save(serializer, modLocation("android/research_night_vision"), existingFileHelper) .save(serializer, modLocation("android/research_night_vision"))
val nanobots = AdvancementBuilder() val nanobots = AdvancementBuilder()
.parent(researchAnything) .parent(researchAnything)
.display( .display(
itemStack = ItemStack(MItems.MATTER_TRANSFORM_MATRIX), itemStack = ItemStack(MItems.MATTER_TRANSFORM_MATRIX),
title = TranslatableComponent(translation.add("nanobots", "Nanomachines, Son!")), title = translation.add("nanobots", "Nanomachines, son.") {
description = TranslatableComponent(translation.add("nanobots.desc", "Research Nanobots as Android, to unlock potent research that come after it")), russian("Наномашины, сынок.")
},
description = translation.add("nanobots.desc", "Research Nanobots as Android, to unlock potent research that come after it") {
russian("Исследуйте наномашины за андроида, для разблокировки очень больших возможностей")
},
hidden = true hidden = true
) )
.addCriterion("nanobots", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS))) .addCriterion("nanobots", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS)).criterion())
.save(serializer, modLocation("android/research_nanobots"), existingFileHelper) .save(serializer, modLocation("android/research_nanobots"))
val shielding = AdvancementBuilder() val shielding = AdvancementBuilder()
.parent(nanobots) .parent(nanobots)
.display( .display(
itemStack = ItemStack(Items.SHIELD), itemStack = ItemStack(Items.SHIELD),
title = TranslatableComponent(translation.add("nanobots_armor_deflect", "Like a Concrete Wall")), title = translation.add("nanobots_armor_deflect", "Like a Concrete Wall") {
description = TranslatableComponent(translation.add("nanobots_armor_deflect.desc", "Have Nanobots absorb more than 5 hears of damage while you are left still functioning")), russian("Как за каменной стеной")
},
description = translation.add("nanobots_armor_deflect.desc", "Have Nanobots absorb more than 5 hears of damage while you are left still functioning") {
russian("Дайте наноботам поглотить 5 сердец урона, не отключившись насовсем")
},
hidden = true, hidden = true,
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(10.0))) .addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(10.0)).criterion())
.save(serializer, modLocation("android/nanobots_armor_deflect"), existingFileHelper) .save(serializer, modLocation("android/nanobots_armor_deflect"))
AdvancementBuilder() AdvancementBuilder()
.parent(shielding) .parent(shielding)
.display( .display(
itemStack = ItemStack(Items.SHIELD), itemStack = ItemStack(Items.SHIELD),
title = TranslatableComponent(translation.add("nanobots_armor_deflect2", "Unstoppable Force vs Immovable Object")), title = translation.add("nanobots_armor_deflect2", "Unstoppable Force vs Immovable Object") {
description = TranslatableComponent(translation.add("nanobots_armor_deflect2.desc", "Have Nanobots absorb more than 10 hears of damage while you are left still functioning")), russian("Неостановимая сила против недвижимого объекта")
},
description = translation.add("nanobots_armor_deflect2.desc", "Have Nanobots absorb more than 10 hears of damage while you are left still functioning") {
russian("Дайте наноботам поглотить 10 сердец урона, не отключившись насовсем")
},
hidden = true, hidden = true,
frameType = FrameType.CHALLENGE frameType = FrameType.CHALLENGE
) )
.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(20.0))) .addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(20.0)).criterion())
.save(serializer, modLocation("android/nanobots_armor_deflect2"), existingFileHelper) .save(serializer, modLocation("android/nanobots_armor_deflect2"))
AdvancementBuilder() AdvancementBuilder()
.parent(researchAnything) .parent(researchAnything)
.display( .display(
itemStack = ItemStack(Items.FEATHER), itemStack = ItemStack(Items.FEATHER),
title = TranslatableComponent(translation.add("fall_dampeners_save", "Lucky Landing")), title = translation.add("fall_dampeners_save", "Lucky Landing") {
description = TranslatableComponent(translation.add("fall_dampeners_save.desc", "Survive fall that would have otherwise be fatal without Fall Dampeners research")), russian("Удачное приземление")
},
description = translation.add("fall_dampeners_save.desc", "Survive fall that would have otherwise be fatal without Fall Dampeners") {
russian("Выживите после падения, которое было бы фатальным без поглотителей инерции")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.addCriterion("saved", FallDampenersSaveTrigger.Instance) .addCriterion("saved", FallDampenersSaveTrigger.criterion)
.save(serializer, modLocation("android/fall_dampeners_save"), existingFileHelper) .save(serializer, modLocation("android/fall_dampeners_save"))
AdvancementBuilder() AdvancementBuilder()
.parent(researchAnything) .parent(researchAnything)
.display( .display(
itemStack = ItemStack(Items.SKELETON_SKULL), itemStack = ItemStack(Items.SKELETON_SKULL),
title = TranslatableComponent(translation.add("ender_teleport_fall_death", "Navigation Error")), title = translation.add("ender_teleport_fall_death", "Navigation Error") {
description = TranslatableComponent(translation.add("ender_teleport_fall_death.desc", "Fall to your death moments after Teleporting")), russian("Ошибка навигации")
},
description = translation.add("ender_teleport_fall_death.desc", "Fall to your demise moments after Teleporting as Android") {
russian("Разбейтесь насмерть через мгновения после телепортации за андроида")
},
frameType = FrameType.GOAL, frameType = FrameType.GOAL,
hidden = true hidden = true
) )
.addCriterion("death", EnderTeleporterFallDeathTrigger.Instance) .addCriterion("death", EnderTeleporterFallDeathTrigger.criterion)
.save(serializer, modLocation("android/ender_teleport_fall_death"), existingFileHelper) .save(serializer, modLocation("android/ender_teleport_fall_death"))
val regen = AdvancementBuilder() val regen = AdvancementBuilder()
.parent(nanobots) .parent(nanobots)
.display( .display(
itemStack = ItemStack(Items.GOLDEN_APPLE), itemStack = ItemStack(Items.GOLDEN_APPLE),
title = TranslatableComponent(translation.add("regen", "Field Repair Done Easy")), title = translation.add("regen", "Field Repair Done Easy") {
description = TranslatableComponent(translation.add("regen.desc", "Research Nanobots Regeneration as Android")), russian("Починка на ходу - легко")
},
description = translation.add("regen.desc", "Research Nanobots Regeneration as Android") {
russian("Исследуйте регенерацию наноботов за андроида")
},
) )
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1))) .addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)).criterion())
.save(serializer, modLocation("android/regen"), existingFileHelper) .save(serializer, modLocation("android/regen"))
AdvancementBuilder() AdvancementBuilder()
.parent(regen) .parent(regen)
.display( .display(
itemStack = ItemStack(Items.ENCHANTED_GOLDEN_APPLE), itemStack = ItemStack(Items.ENCHANTED_GOLDEN_APPLE),
title = TranslatableComponent(translation.add("regen_all", "Field Repair Done Effortless")), title = translation.add("regen_all", "Field Repair Done Effortless") {
description = TranslatableComponent(translation.add("regen_all.desc", "Max out Nanobots Regeneration research")), russian("Починка на ходу - без усилий")
},
description = translation.add("regen_all.desc", "Max out Nanobots Regeneration research") {
russian("Полностью исследуйте регенерацию наноботов за андроида")
},
frameType = FrameType.GOAL, frameType = FrameType.GOAL,
) )
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1))) .addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)).criterion())
.addCriterion("regen1", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_2))) .addCriterion("regen1", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_2)).criterion())
.addCriterion("regen2", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_3))) .addCriterion("regen2", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_3)).criterion())
.addCriterion("regen3", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_4))) .addCriterion("regen3", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_4)).criterion())
.save(serializer, modLocation("android/regen_all"), existingFileHelper) .save(serializer, modLocation("android/regen_all"))
AdvancementBuilder() AdvancementBuilder()
.parent(researchAnything) .parent(researchAnything)
.display( .display(
itemStack = ItemStack(MItems.ANDROID_STATION), itemStack = ItemStack(MItems.ANDROID_STATION),
title = TranslatableComponent(translation.add("research_all", "Mecha-agnomination")), title = translation.add("research_all", "Mecha-Agnomination") {
description = TranslatableComponent(translation.add("research_all.desc", "Research everything (that don't block any other research)")), russian("Меха-зумие")
},
description = translation.add("research_all.desc", "Research everything as Android (that don't block or get blocked by any other research)") {
russian("Исследуйте все технологии за андроида (которые не блокируют и не блокируются другими технологиями)")
},
frameType = FrameType.CHALLENGE frameType = FrameType.CHALLENGE
) )
.rewards(AdvancementRewards.Builder.experience(400).addLootTable(modLocation("research_all_android"))) .rewards(AdvancementRewards.Builder.experience(400).addLootTable(modLocation("research_all_android")))
@ -268,29 +312,106 @@ fun addAndroidAdvancements(serializer: Consumer<Advancement>, existingFileHelper
DataGen.researchProvider.generatedView.stream() DataGen.researchProvider.generatedView.stream()
.filter { it.allBlockedBy.isEmpty() && it.allBlocking.isEmpty() } .filter { it.allBlockedBy.isEmpty() && it.allBlocking.isEmpty() }
.forEach { .forEach {
advancement.addCriterion(it.id.toString(), AndroidResearchTrigger.Instance(it)) advancement.addCriterion(it.id.toString(), AndroidResearchTrigger.Instance(it).criterion())
} }
} }
.save(serializer, modLocation("android/research_everything"), existingFileHelper) .save(serializer, modLocation("android/research_everything"))
val shockwave = AdvancementBuilder() val shockwave = AdvancementBuilder()
.parent(researchAnything) .parent(researchAnything)
.display( .display(
itemStack = ItemStack(Items.PISTON), itemStack = ItemStack(Items.PISTON),
title = TranslatableComponent(translation.add("shockwave", "Supersonic Landing")), title = translation.add("shockwave", "Supersonic Landing") {
description = TranslatableComponent(translation.add("shockwave.desc", "Perform a Shockwave upon landing")), russian("Сверхзвуковое приземление")
},
description = translation.add("shockwave.desc", "Make a Shockwave upon landing") {
russian("Вызовите ударную волну при приземлении")
},
) )
.addCriterion("shockwave", ShockwaveTrigger.Instance) .addCriterion("shockwave", ShockwaveTrigger.criterion)
.save(serializer, modLocation("android/shockwave"), existingFileHelper) .save(serializer, modLocation("android/shockwave"))
AdvancementBuilder() AdvancementBuilder()
.parent(shockwave) .parent(shockwave)
.display( .display(
itemStack = ItemStack(Items.WARDEN_SPAWN_EGG), itemStack = ItemStack(Items.WARDEN_SPAWN_EGG),
title = TranslatableComponent(translation.add("shockwave_warden", "Music To Their Ears")), title = translation.add("shockwave_warden", "Music to their Ears") {
description = TranslatableComponent(translation.add("shockwave_warden.desc", "Hurt Warden using Shockwave ability")), russian("Музыка для их ушей")
},
description = translation.add("shockwave_warden.desc", "Hurt Warden using Shockwave ability") {
russian("Нанесите хранителю урон используя ударную волну")
},
frameType = FrameType.GOAL frameType = FrameType.GOAL
) )
.addCriterion("shockwave_warden", ShockwaveDamageMobTrigger.Instance(EntityPredicate.Builder.entity().of(EntityType.WARDEN).build().wrap())) .addCriterion("shockwave_warden", ShockwaveDamageMobTrigger.Instance(Optional.of(EntityPredicate.Builder.entity().of(EntityType.WARDEN).build().wrap())).criterion())
.save(serializer, modLocation("android/shockwave_warden"), existingFileHelper) .save(serializer, modLocation("android/shockwave_warden"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(Items.WITHER_SKELETON_SKULL),
title = translation.add("wither", "Not Quite Alive, Not Quite Undead") {
russian("Ни живой, ни мёртвый")
},
description = translation.add("wither.desc", "Defeat The Wither as Android. The Wither was surely confused over kind of thing you are") {
russian("Победите Иссушителя будучи андроидом. Наверняка Иссушитель был ошеломлён таким раскладом дел")
},
frameType = FrameType.GOAL,
hidden = true
)
.addCriterion("kill_wither", KillAsAndroidTrigger.Instance(
predicate = Optional.of(EntityPredicate.Builder.entity().of(EntityType.WITHER).build().wrap()),
).criterion())
.save(serializer, modLocation("android/wither"))
val underwater = AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(Items.TURTLE_SPAWN_EGG),
title = translation.add("travel_underwater", "Underwater Walk") {
russian("Подводная прогулка")
},
description = translation.add("travel_underwater.desc", "Travel at least 200 meters underwater as Android without Air Bags research. This reminds us of someone...") {
russian("Преодолейте как минимум 200 метров под водой будучи андроидом без исследования воздушных мешков. Кого-то это нам напоминает...")
},
frameType = FrameType.GOAL,
hidden = true
)
.addCriterion("travel", AndroidTravelUnderwater.Instance(200.0).criterion())
.save(serializer, modLocation("android/underwater"))
AdvancementBuilder()
.parent(underwater)
.display(
itemStack = ItemStack(Items.TURTLE_SPAWN_EGG),
title = translation.add("travel_underwater2", "Underwater Travel") {
russian("Подводная прогулка")
},
description = translation.add("travel_underwater2.desc", "Travel at least 1046 meters underwater as Android without Air Bags research, like someone else did so") {
russian("Преодолейте как минимум 1046 метров под водой будучи андроидом без исследования воздушных мешков, прям как тот, кто так однажды так и сделал")
},
frameType = FrameType.CHALLENGE,
hidden = true
)
.addCriterion("travel", AndroidTravelUnderwater.Instance(1046.0).criterion())
.save(serializer, modLocation("android/underwater2"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(Items.PRISMARINE_CRYSTALS),
title = translation.add("elder_guardian", "Drowned, but Still Determined") {
russian("Затонувший, но всё ещё целеустремлённый")
},
description = translation.add("elder_guardian.desc", "Slay Elder Guardian as Android without Air Bags researched") {
russian("Победите Древнего стража будучи андроидом без исследования воздушных мешков")
},
frameType = FrameType.CHALLENGE,
hidden = true
)
.addCriterion("kill_elder_guardian", KillAsAndroidTrigger.Instance(
predicate = Optional.of(EntityPredicate.Builder.entity().of(EntityType.ELDER_GUARDIAN).build().wrap()),
featurePredicate = KillAsAndroidTrigger.Not(KillAsAndroidTrigger.Has(AndroidFeatures.AIR_BAGS.registryName!!))
).criterion())
.save(serializer, modLocation("android/elder_guardian"))
} }

View File

@ -0,0 +1,262 @@
package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.FrameType
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.triggers.ExopackBatterySlotTrigger
import ru.dbotthepony.mc.otm.triggers.ExopackGainedCraftingTrigger
import ru.dbotthepony.mc.otm.triggers.ExopackGainedEnderAccessTrigger
import ru.dbotthepony.mc.otm.triggers.ExopackGainedSmeltingTrigger
import ru.dbotthepony.mc.otm.triggers.ExopackObtainedTrigger
import ru.dbotthepony.mc.otm.triggers.ExopackSlotsExpandedTrigger
import java.util.function.Consumer
fun addExopackAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider, root: AdvancementHolder, zpm: AdvancementHolder) {
val translation = lang.MultiBuilder("otm.advancements.exopack")
AdvancementBuilder()
.parent(zpm)
.display(
hidden = true,
itemStack = ItemStack(MItems.ZPM_BATTERY),
title = translation.add("zpm_battery", "At Maximum Battery Capacity") {
russian("Достигнут максимальный заряд батареи")
},
description = translation.add("zpm_battery.desc", "Use Zero Point Module as power source in Exopack") {
russian("Используйте модуль нулевой точки как источник питания в Экзопаке")
},
frameType = FrameType.GOAL
)
.addCriterion("zpm_battery", ExopackBatterySlotTrigger.Instance(ItemPredicate.Builder.item().of(MItems.ZPM_BATTERY).build()).criterion())
.save(serializer, modLocation("exopack/zpm_battery"))
val obtained = AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.EXOPACK_PROBE),
title = translation.add("obtained", "One Dimension Bigger") {
russian("Больше на одно измерение")
},
description = translation.add("obtained.desc", "Obtain an Exopack, a mysterious, semi-present, light as a feather, stuff storage on your back") {
russian("Получите Экзопак, загадочное, полу-присутствующее, лёгкое как пёрышко, хранилище штуковин на вашей спине")
},
frameType = FrameType.GOAL
)
.addCriterion("obtained", ExopackObtainedTrigger.criterion)
.save(serializer, modLocation("exopack/obtained"))
AdvancementBuilder()
.parent(obtained)
.display(
itemStack = ItemStack(Items.CRAFTING_TABLE),
title = translation.add("crafting", "Crafting on Go") {
russian("Крафт по пути")
},
description = translation.add("crafting.desc", "Install Crafting Upgrade in your Exopack, allowing to craft 3x3 recipes") {
russian("Установите улучшение сетки крафта в ваш Экзопаке, который позволяет создавать предметы, требующие сетку крафта рабочего стола")
},
)
.addCriterion("crafting", ExopackGainedCraftingTrigger.criterion)
.save(serializer, modLocation("exopack/crafting"))
AdvancementBuilder()
.parent(obtained)
.display(
itemStack = ItemStack(Items.FURNACE),
title = translation.add("smelting", "Pocket Furnace") {
russian("Печь в кармане")
},
description = translation.add("smelting.desc", "Install Smelting Module in your Exopack, allowing to smelt items right inside your inventory") {
russian("Установите модуль переплавки в ваш Экзопак, позволяющий переплавлять предметы прямо у вас в инвентаре")
},
)
.addCriterion("smelting", ExopackGainedSmeltingTrigger.criterion)
.save(serializer, modLocation("exopack/smelting"))
AdvancementBuilder()
.parent(obtained)
.display(
itemStack = ItemStack(Items.ENDER_CHEST),
title = translation.add("ender_access", "Ender-ious Access") {
russian("Эендер-иумый Доступ")
},
description = translation.add("ender_access.desc", "Gain direct access to your Ender Chest out of your Exopack") {
russian("Получите прямой доступ к содержимому вашего сундука края прямо из Экзопака")
},
)
.addCriterion("ender_access", ExopackGainedEnderAccessTrigger.criterion)
.save(serializer, modLocation("ender_access/smelting"))
var size = AdvancementBuilder()
.parent(obtained)
.display(
itemStack = ItemStack(Items.CHEST),
title = translation.add("size0", "Closet Upgrade") {
russian("Обновление чуланчика")
},
description = translation.add("size0.desc", "Upgrade Exopack storage") {
russian("Улучшите размер инвентаря Экзопака")
},
)
.addCriterion("size0", ExopackSlotsExpandedTrigger.Instance(minTotal = 1).criterion())
.save(serializer, modLocation("exopack/size0"))
val size0 = size
size = AdvancementBuilder()
.parent(size)
.display(
itemStack = ItemStack(Items.CHEST),
title = translation.add("size1", "Double the Capacity") {
russian("Двойной объём")
},
description = translation.add("size1.desc", "Reach 27 slots in your Exopack storage") {
russian("Достигните 27 слотов хранилища Экзопака")
},
)
.addCriterion("size1", ExopackSlotsExpandedTrigger.Instance(minTotal = 27).criterion())
.save(serializer, modLocation("exopack/size1"))
size = AdvancementBuilder()
.parent(size)
.display(
itemStack = ItemStack(Items.CHEST),
hidden = true,
title = translation.add("size2", "Pack Rat") {
russian("Воришка")
},
description = translation.add("size2.desc", "Reach 54 slots in your Exopack storage") {
russian("Достигните 54 слотов хранилища Экзопака")
},
)
.addCriterion("size2", ExopackSlotsExpandedTrigger.Instance(minTotal = 54).criterion())
.save(serializer, modLocation("exopack/size2"))
size = AdvancementBuilder()
.parent(size)
.display(
itemStack = ItemStack(Items.CHEST),
hidden = true,
title = translation.add("size3", "Its Getting Big In Here") {
russian("Тут становится просторно")
},
description = translation.add("size3.desc", "Reach 108 slots in your Exopack storage") {
russian("Достигните 108 слотов хранилища Экзопака")
},
frameType = FrameType.GOAL
)
.addCriterion("size3", ExopackSlotsExpandedTrigger.Instance(minTotal = 108).criterion())
.save(serializer, modLocation("exopack/size3"))
size = AdvancementBuilder()
.parent(size)
.display(
itemStack = ItemStack(Items.ENDER_CHEST),
hidden = true,
title = translation.add("size4", "Warehousing Pioneer") {
russian("Пионер складских решений")
},
description = translation.add("size4.desc", "Reach 432 slots in your Exopack storage. You could fit a house in there") {
russian("Достигните 432 слотов хранилища Экзопака. Туда можно уже впихнуть целый дом")
},
frameType = FrameType.CHALLENGE
)
.addCriterion("size4", ExopackSlotsExpandedTrigger.Instance(minTotal = 432).criterion())
.save(serializer, modLocation("exopack/size4"))
AdvancementBuilder()
.parent(size)
.display(
itemStack = ItemStack(Items.ENDER_CHEST),
hidden = true,
title = translation.add("size5", "With Volume Like This...") {
russian("С таким объёмом...")
},
description = translation.add("size5.desc", "Reach 1728 slots in your Exopack storage. Why would you need to go any bigger?!") {
russian("Достигните 1728 слотов хранилища Экзопака. Куда вам столько?!")
},
frameType = FrameType.CHALLENGE
)
.addCriterion("size5", ExopackSlotsExpandedTrigger.Instance(minTotal = 1728).criterion())
.save(serializer, modLocation("exopack/size5"))
var once = AdvancementBuilder()
.parent(size0)
.display(
itemStack = ItemStack(Items.CHEST),
title = translation.add("once0", "One Module - One Row") {
russian("Один модуль - одна строка")
},
description = translation.add("once0.desc", "Upgrade your Exopack storage with 9 slots using one module") {
russian("Улучшите хранилище Экзопака модулем на 9 слотов")
},
)
.addCriterion("once0", ExopackSlotsExpandedTrigger.Instance(minGained = 9).criterion())
.save(serializer, modLocation("exopack/once0"))
once = AdvancementBuilder()
.parent(once)
.display(
itemStack = ItemStack(Items.CHEST),
title = translation.add("once1", "One Module - One Chest") {
russian("Один модуль - один сундук")
},
description = translation.add("once1.desc", "Upgrade your Exopack storage with 27 slots using one module") {
russian("Улучшите хранилище Экзопака модулем на 27 слотов")
},
)
.addCriterion("once1", ExopackSlotsExpandedTrigger.Instance(minGained = 27).criterion())
.save(serializer, modLocation("exopack/once1"))
once = AdvancementBuilder()
.parent(once)
.display(
itemStack = ItemStack(Items.CHEST),
hidden = true,
title = translation.add("once2", "One Module - Two Chests?") {
russian("Один модуль - два сундука?")
},
description = translation.add("once2.desc", "Upgrade your Exopack storage with 54 slots using one module") {
russian("Улучшите хранилище Экзопака модулем на 54 слотов")
},
frameType = FrameType.GOAL
)
.addCriterion("once2", ExopackSlotsExpandedTrigger.Instance(minGained = 54).criterion())
.save(serializer, modLocation("exopack/once2"))
once = AdvancementBuilder()
.parent(once)
.display(
itemStack = ItemStack(Items.ENDER_CHEST),
hidden = true,
title = translation.add("once3", "Storage Housing Construct") {
russian("Хранилище быстрого приготовления")
},
description = translation.add("once3.desc", "Upgrade your Exopack storage with 90 slots using one module") {
russian("Улучшите хранилище Экзопака модулем на 90 слотов")
},
frameType = FrameType.GOAL
)
.addCriterion("once3", ExopackSlotsExpandedTrigger.Instance(minGained = 90).criterion())
.save(serializer, modLocation("exopack/once3"))
AdvancementBuilder()
.parent(once)
.display(
itemStack = ItemStack(Items.ENDER_CHEST),
hidden = true,
title = translation.add("once4", "Non-Euclidean Wardrobe") {
russian("Неевклидов Шкаф")
},
description = translation.add("once4.desc", "Upgrade your Exopack storage with 150 slots using one module. After you open one, tens meters long racks roll out of it!") {
russian("Улучшите хранилище Экзопака модулем на 150 слотов. Открой один - и покатились стеллажи на десятки метров!")
},
frameType = FrameType.CHALLENGE
)
.addCriterion("once4", ExopackSlotsExpandedTrigger.Instance(minGained = 150).criterion())
.save(serializer, modLocation("exopack/once4"))
}

View File

@ -14,6 +14,7 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TextComponent
import java.util.function.Consumer
fun AdvancementBuilder(): Advancement.Builder = Advancement.Builder.advancement() fun AdvancementBuilder(): Advancement.Builder = Advancement.Builder.advancement()
@ -69,3 +70,5 @@ fun criterion(item: ItemLike): CriterionTriggerInstance {
} }
fun EntityPredicate.wrap(): EntityPredicate.Composite = EntityPredicate.Composite.wrap(this) fun EntityPredicate.wrap(): EntityPredicate.Composite = EntityPredicate.Composite.wrap(this)
fun Advancement.Builder.save(advancement: Consumer<Advancement>, name: ResourceLocation) = save(advancement, name.toString())

View File

@ -1,85 +1,193 @@
package ru.dbotthepony.mc.otm.datagen.advancements package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.Advancement import net.minecraft.advancements.Advancement
import net.minecraft.advancements.RequirementsStrategy import net.minecraft.advancements.FrameType
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.data.ExistingFileHelper import net.minecraft.world.item.Items
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.key
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.triggers.TakeItemOutOfReplicatorTrigger
import java.util.function.Consumer import java.util.function.Consumer
private data class CraftEntry(val item: Item, val englishName: String, val englishSuffix: String? = null) typealias AdvancementHolder = Advancement
fun addMachineAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) { private data class CraftEntry(
val translation = lang.english.Prepended("otm.advancements.machine") val item: Item,
val englishName: String,
val englishSuffix: String? = null,
val root = AdvancementBuilder() val russianName: String? = null,
.requirements(RequirementsStrategy.OR) val russianSuffix: String? = null,
) {
fun make(serializer: Consumer<AdvancementHolder>, parent: AdvancementHolder, translation: MatteryLanguageProvider.MultiBuilder): AdvancementHolder {
val path = item.registryName!!.path
val translated = translation.add("$path.desc", "Craft a %s%s") {
russian("Создайте %s%s")
}
val translatedSuffix = translation.add("$path.suffix", if (englishSuffix != null) ". $englishSuffix" else "") {
russian(if (russianSuffix != null) ". $russianSuffix" else "")
}
return AdvancementBuilder()
.parent(parent)
.display( .display(
itemStack = ItemStack(MItems.CHEMICAL_GENERATOR), itemStack = ItemStack(item),
title = TranslatableComponent(translation.add("root", "Tritanium Empowered Machinery")), title = translation.add(path, englishName) {
description = TranslatableComponent(translation.add("root.desc", "Do not drop in anything if you want the latter preserved intact")), if (russianName != null) {
showToast = false, russian(russianName)
announceChat = false, }
background = modLocation("textures/block/decorative/floor_tiles_gray.png") },
description = TranslatableComponent(translated.contents.key, item.description, translatedSuffix),
) )
.addCriterion("has_machine", criterion(MItemTags.MACHINES)) .addCriterion("has_machine", criterion(item))
.addCriterion("has_tritanium_ingot", criterion(MItemTags.TRITANIUM_INGOTS)) .save(serializer, modLocation("machines/$path"))
.addCriterion("has_tritanium_plate_somehow", criterion(MItemTags.TRITANIUM_PLATES)) }
.save(serializer, modLocation("machines/root"), existingFileHelper) }
fun addMachineAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider, root: AdvancementHolder) {
val translation = lang.MultiBuilder("otm.advancements.machine")
val chem = AdvancementBuilder() val chem = AdvancementBuilder()
.parent(root) .parent(root)
.display( .display(
itemStack = ItemStack(MItems.CHEMICAL_GENERATOR), itemStack = ItemStack(MItems.CHEMICAL_GENERATOR),
title = TranslatableComponent(translation.add("chemical_generator", "Burning the Organics")), title = translation.add("chemical_generator", "Burning the Organics") {
description = TranslatableComponent(translation.add("chemical_generator.desc", "Craft a Chemical Generator, better to put it outside")), russian("Сжигание органики")
},
description = translation.add("chemical_generator.desc", "Craft a Chemical Generator, better to put it outside") {
russian("Создайте химический генератор. Лучше установить его снаружи")
},
) )
.addCriterion("has_machine", criterion(MItems.CHEMICAL_GENERATOR)) .addCriterion("has_machine", criterion(MItems.CHEMICAL_GENERATOR))
.save(serializer, modLocation("machines/chemical_generator"), existingFileHelper) .save(serializer, modLocation("machines/chemical_generator"))
val press = AdvancementBuilder() val press = AdvancementBuilder()
.parent(chem) .parent(chem)
.display( .display(
itemStack = ItemStack(MItems.PLATE_PRESS), itemStack = ItemStack(MItems.PLATE_PRESS),
title = TranslatableComponent(translation.add("plate_press", "Bending the Material")), title = translation.add("plate_press", "Bending the Material") {
description = TranslatableComponent(translation.add("plate_press.desc", "Craft a Plate Press, avoid having limbs inside during operation")), russian("Раскатка металла")
},
description = translation.add("plate_press.desc", "Craft a Plate Press, avoid having limbs inside at all times") {
russian("Создайте пресс пластин, не суйте свои или чужие конечности внутрь")
},
) )
.addCriterion("has_machine", criterion(MItems.PLATE_PRESS)) .addCriterion("has_machine", criterion(MItems.PLATE_PRESS))
.save(serializer, modLocation("machines/plate_press"), existingFileHelper) .save(serializer, modLocation("machines/plate_press"))
val entries = listOf( CraftEntry(MItems.TWIN_PLATE_PRESS, "Twice the Thud",
CraftEntry(MItems.MATTER_SCANNER, "Scanning Things that Matter"), russianName = "Двойной стук").make(serializer, press, translation)
CraftEntry(MItems.PATTERN_STORAGE, "Digital Knowledge Library"),
CraftEntry(MItems.MATTER_DECOMPOSER, "Decaying the Atoms", "Keep your limbs outside of the working chamber at all times"),
CraftEntry(MItems.MATTER_PANEL, "Indexing the Library"),
CraftEntry(MItems.MATTER_REPLICATOR, "Local Bakery", "Now let's bake some perfect bread"),
CraftEntry(MItems.MATTER_BOTTLER, "Transfusing Pure Matter", "For those who loved to play with water in their childhood"),
CraftEntry(MItems.MATTER_RECYCLER, "Refine and Redefine", "This is what waste recycling should look like"),
CraftEntry(MItems.MATTER_CAPACITOR_BANK, "Modular Matter Tank"),
CraftEntry(MItems.ENERGY_COUNTER, "Visualize Power Burn"), val scanner = CraftEntry(MItems.MATTER_SCANNER, "Scanning Things that Matter",
CraftEntry(MItems.BATTERY_BANK, "Batteries Not Included", "By all means avoid the urge to hammer incompatible batteries into the power bus."), russianName = "Сканируем вещи которые материальны")
) val decomposer = CraftEntry(MItems.MATTER_DECOMPOSER, "Decaying the Atoms", "Keep your limbs outside of the working chamber at all times",
russianName = "Разлагаем атомы", russianSuffix = "Во всех ситуациях держите свои конечности вне рабочей камеры")
val panel = CraftEntry(MItems.MATTER_PANEL, "Indexing the Library",
russianName = "Индексируем библиотеку")
val replicator = CraftEntry(MItems.MATTER_REPLICATOR, "Cook with (Im)Perfection", "Now let's bake some perfect bread",
russianName = "Повар с (не) идеальностями", russianSuffix = "А теперь давайте выпечем немного идеального хлеба")
val bottler = CraftEntry(MItems.MATTER_BOTTLER, "Transfusing Pure Matter", "For those who loved to play with water in their childhood",
russianName = "Переливаем чистую материю", russianSuffix = "Для тех, кто любил играться в воде в детстве")
val recycler = CraftEntry(MItems.MATTER_RECYCLER, "Refine and Redefine", "This is what waste recycling should look like",
russianName = "Переработка и перегонка", russianSuffix = "Вот он, пик переработки отходов")
val capacitor = CraftEntry(MItems.MATTER_CAPACITOR_BANK, "Modular Matter Tank",
russianName = "Модульный бак материи")
val built = mutableMapOf<Item, Advancement>() val counter = CraftEntry(MItems.ENERGY_COUNTER, "Visualize Power Burn",
russianName = "Визуализация сжигания энергии")
val battery = CraftEntry(MItems.BATTERY_BANK, "Batteries Not Included", "By all means avoid the urge to hammer incompatible batteries into the power bus.",
russianName = "Батарейки в комплект не входят", russianSuffix = "Пожалуйста, воздержитесь от вбивания кувалдой несовместимых батарей в энергетическую шину.")
for (entry in entries) { val pattern = CraftEntry(MItems.PATTERN_STORAGE, "Digital Knowledge Library",
val path = entry.item.registryName!!.path russianName = "Цифровая библиотека знаний")
built[entry.item] = AdvancementBuilder() val reconstructor = CraftEntry(MItems.MATTER_RECONSTRUCTOR, "Flipping Hourglass",
.parent(press) russianName = "Переворачиваем песочные часы")
decomposer.make(serializer, press, translation).also {
pattern.make(serializer, it, translation).also {
scanner.make(serializer, it, translation)
panel.make(serializer, it, translation)
replicator.make(serializer, it, translation).also {
AdvancementBuilder()
.parent(it)
.display( .display(
itemStack = ItemStack(entry.item), itemStack = ItemStack(Items.BREAD),
title = TranslatableComponent(translation.add(path, entry.englishName)), title = translation.add("replicate_something", "Local Bakery") {
description = TranslatableComponent(translation.add("$path.desc", "Craft a %s%s"), entry.item.description, if (entry.englishSuffix != null) ". " + entry.englishSuffix else ""), russian("Местная выпечка")
},
description = translation.add("replicate_something.desc", "Replicate something using Matter Replicator. If you replicated some food, be first to taste it among your company") {
russian("Среплицируйте что либо используя репликатор материи. Если это еда, то не стесняйтесь быть первым, кто попробует её на вкус среди вашей компании")
},
frameType = FrameType.GOAL
) )
.addCriterion("has_machine", criterion(entry.item)) .addCriterion("replicate_something", TakeItemOutOfReplicatorTrigger.Instance(ItemPredicate.Builder.item().of(MItems.MATTER_DUST).build(), true).criterion())
.save(serializer, modLocation("machines/$path"), existingFileHelper) .save(serializer, modLocation("machines/replicate_something"))
AdvancementBuilder()
.parent(it)
.display(
hidden = true,
itemStack = ItemStack(MItems.MATTER_DUST),
title = translation.add("replicate_failure", "Unhealthy Flavor") {
russian("Вредная посыпка")
},
description = translation.add("replicate_failure.desc", "Experience replication failure and have your thing turn into matter dust") {
russian("Наблюдайте неудачный результат репликации, где ваш заказ рассыпался в материальную труху")
},
)
.addCriterion("replicate_failure", TakeItemOutOfReplicatorTrigger.Instance(ItemPredicate.Builder.item().of(MItems.MATTER_DUST).build()).criterion())
.save(serializer, modLocation("machines/replicate_failure"))
}
reconstructor.make(serializer, it, translation)
}
bottler.make(serializer, it, translation)
recycler.make(serializer, it, translation)
capacitor.make(serializer, it, translation)
}
counter.make(serializer, press, translation).also {
battery.make(serializer, it, translation)
}
val station = CraftEntry(MItems.ANDROID_STATION, "Android Home Page",
russianName = "Домашняя страница андроидов",
russianSuffix = "Только пользоваться этим устройством могут вёдра с болтами",
englishSuffix = "Except only buckets of bolts can use this thing")
val charger = CraftEntry(MItems.ANDROID_CHARGER, "Android Home Router",
russianName = "Домашняя страница андроидов")
station.make(serializer, press, translation).also {
charger.make(serializer, it, translation)
}
CraftEntry(MItems.COBBLESTONE_GENERATOR, "Cobblestone: Infinity + 1",
russianName = "Булыжник: бесконечность + 1",
russianSuffix = "Смотрите, чтоб он не просыпался во все сундуки",
englishSuffix = "Watch for not to spill it over all your chests").make(serializer, press, translation)
CraftEntry(MItems.POWERED_FURNACE, "One Big Resistor",
russianName = "Один большой резистор",
russianSuffix = "Каждый элемент электрической цепи способен испускать свет и тепло, единожды.",
englishSuffix = "Any electrical element can emit light and heat, once.")
.make(serializer, press, translation)
.also {
CraftEntry(MItems.POWERED_BLAST_FURNACE, "Big Microwave Oven",
russianName = "Большая микроволновая печь").make(serializer, it, translation)
CraftEntry(MItems.POWERED_SMOKER, "Small Microwave Oven",
russianName = "Маленькая микроволновая печь").make(serializer, it, translation)
} }
} }

View File

@ -1,13 +1,14 @@
package ru.dbotthepony.mc.otm.datagen.blocks package ru.dbotthepony.mc.otm.datagen.blocks
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraftforge.client.model.generators.BlockStateProvider import net.minecraftforge.client.model.generators.BlockStateProvider
import net.minecraftforge.client.model.generators.ConfiguredModel
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.block.BatteryBankBlock import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.toYRotBlockstate import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
private fun nothingOrNumber(input: Int): String { private fun nothingOrNumber(input: Int): String {
@ -17,28 +18,24 @@ private fun nothingOrNumber(input: Int): String {
return (input - 1).toString() return (input - 1).toString()
} }
open class BatteryBankProvider(event: GatherDataEvent) : BlockStateProvider(event.generator, DataGen.MOD_ID, event.existingFileHelper) { open class BatteryBankProvider(event: GatherDataEvent) : BlockStateProvider(event.generator.packOutput, DataGen.MOD_ID, event.existingFileHelper) {
protected var block = "battery_bank" protected var block = "battery_bank"
protected var batteryPath = "block/battery/battery" protected var batteryPath = "block/battery/battery"
protected var registry: Block = MBlocks.BATTERY_BANK protected var registry: Block = MBlocks.BATTERY_BANK
override fun registerStatesAndModels() { override fun registerStatesAndModels() {
with(getMultipartBuilder(registry)) { with(getVariantBuilder(registry)) {
val battery_bank = models().getExistingFile(ResourceLocation("overdrive_that_matters:block/$block")) forAllStates {
ConfiguredModel.builder()
.modelFile(models().getExistingFile(modLocation("block/$block")))
.rotationY(it[BlockRotationFreedom.HORIZONTAL.property].front.yRotationBlockstateNorth())
.build()
}
}
}
RotatableMatteryBlock.FACING.possibleValues.forEach { override fun getName(): String {
part().modelFile(battery_bank).rotationY(it.toYRotBlockstate()).addModel().condition( return "Battery Bank Model Provider"
RotatableMatteryBlock.FACING, it)
for (i in 0 .. 11) {
part().modelFile(
models().getExistingFile(ResourceLocation("overdrive_that_matters:$batteryPath$i"))
).rotationY(it.toYRotBlockstate()).addModel()
.condition(RotatableMatteryBlock.FACING, it)
.condition(BatteryBankBlock.BATTERY_SLOTS_PROPS[i], true)
}
}
}
} }
} }
@ -48,4 +45,8 @@ class MatterBankProvider(event: GatherDataEvent) : BatteryBankProvider(event) {
batteryPath = "block/battery/matter_capacitor" batteryPath = "block/battery/matter_capacitor"
registry = MBlocks.MATTER_CAPACITOR_BANK registry = MBlocks.MATTER_CAPACITOR_BANK
} }
override fun getName(): String {
return "Matter Bank Model Provider"
}
} }

View File

@ -1,21 +1,20 @@
package ru.dbotthepony.mc.otm.datagen.blocks package ru.dbotthepony.mc.otm.datagen.blocks
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.state.properties.BlockStateProperties import net.minecraft.world.level.block.state.properties.BlockStateProperties
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
import net.minecraftforge.client.model.generators.ConfiguredModel import net.minecraftforge.client.model.generators.ConfiguredModel
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.block.CableBlock import ru.dbotthepony.mc.otm.block.CableBlock
import ru.dbotthepony.mc.otm.block.CargoCrateBlock import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock
import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateSouth
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateSouth
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.datagen.toXRotBlockstate
import ru.dbotthepony.mc.otm.datagen.toXRotBlockstateInv
import ru.dbotthepony.mc.otm.datagen.toYRotBlockstate
import ru.dbotthepony.mc.otm.datagen.toYRotBlockstateInv
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
@ -28,48 +27,63 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
provider.ore(MBlocks.TRITANIUM_ORE) provider.ore(MBlocks.TRITANIUM_ORE)
provider.ore(MBlocks.TRITANIUM_RAW_BLOCK) provider.ore(MBlocks.TRITANIUM_RAW_BLOCK)
provider.block(MBlocks.TRITANIUM_INGOT_BLOCK) provider.block(MBlocks.TRITANIUM_INGOT_BLOCK)
provider.block(MBlocks.METAL_MESH)
provider.block(MBlocks.CHEMICAL_GENERATOR) provider.block(MBlocks.CHEMICAL_GENERATOR)
provider.block(MBlocks.MATTER_SCANNER) provider.block(MBlocks.MATTER_SCANNER)
provider.block(MBlocks.ITEM_MONITOR) provider.block(MBlocks.ITEM_MONITOR)
provider.block(MBlocks.HOLO_SIGN)
provider.exec { provider.exec {
with(provider.getMultipartBuilder(MBlocks.PHANTOM_ATTRACTOR)) { with(provider.getMultipartBuilder(MBlocks.PHANTOM_ATTRACTOR)) {
for (dir in RotatableMatteryBlock.FACING.possibleValues) { for (dir in BlockRotationFreedom.HORIZONTAL.possibleValues) {
part().modelFile(provider.models().getExistingFile(modLocation("block/${MNames.PHANTOM_ATTRACTOR}"))) part().modelFile(provider.models().getExistingFile(modLocation("block/${MNames.PHANTOM_ATTRACTOR}")))
.rotationY(dir.toYRotBlockstate()) .rotationY(dir.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(BlockStateProperties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER) .condition(BlockStateProperties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER)
.condition(RotatableMatteryBlock.FACING, dir) .condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.end() .end()
} }
} }
with(provider.getMultipartBuilder(MBlocks.MATTER_BOTTLER)) { with(provider.getMultipartBuilder(MBlocks.ANDROID_CHARGER)) {
for (dir in RotatableMatteryBlock.FACING.possibleValues) { for (dir in BlockRotationFreedom.HORIZONTAL.possibleValues) {
for (enum in WorkerState.SEMI_WORKER_STATE.possibleValues) { for (part in AndroidChargerBlock.PART.possibleValues) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "matter_bottler_${enum.name.lowercase()}"))) part().modelFile(provider.models().getExistingFile(modLocation("block/${MNames.ANDROID_CHARGER}_${part.serializedName}")))
.rotationY(dir.toYRotBlockstate()) .rotationY(dir.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING, dir) .condition(AndroidChargerBlock.PART, part)
.condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.end()
}
}
}
with(provider.getMultipartBuilder(MBlocks.MATTER_BOTTLER)) {
for (dir in BlockRotationFreedom.HORIZONTAL.possibleValues) {
for (enum in WorkerState.SEMI_WORKER_STATE.possibleValues) {
part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name.lowercase()}")))
.rotationY(dir.front.yRotationBlockstateNorth())
.addModel()
.condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.condition(WorkerState.WORKER_STATE, enum) .condition(WorkerState.WORKER_STATE, enum)
.end() .end()
} }
} }
for (dir in RotatableMatteryBlock.FACING.possibleValues) { for (dir in BlockRotationFreedom.HORIZONTAL.possibleValues) {
for (enum in MatterBottlerBlock.SLOT_PROPERTIES) { for (enum in MatterBottlerBlock.SLOT_PROPERTIES) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "matter_bottler_${enum.name}_open"))) part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name}_open")))
.rotationY(dir.toYRotBlockstate()) .rotationY(dir.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING, dir) .condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.condition(enum, false) .condition(enum, false)
.end() .end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "matter_bottler_${enum.name}_closed"))) part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name}_closed")))
.rotationY(dir.toYRotBlockstate()) .rotationY(dir.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING, dir) .condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.condition(enum, true) .condition(enum, true)
.end() .end()
} }
@ -80,12 +94,18 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
provider.block(MBlocks.MATTER_DECOMPOSER) provider.block(MBlocks.MATTER_DECOMPOSER)
provider.block(MBlocks.MATTER_REPLICATOR) provider.block(MBlocks.MATTER_REPLICATOR)
provider.block(MBlocks.PLATE_PRESS) provider.block(MBlocks.PLATE_PRESS)
provider.block(MBlocks.TWIN_PLATE_PRESS)
provider.block(MBlocks.GRAVITATION_STABILIZER) provider.block(MBlocks.GRAVITATION_STABILIZER)
provider.block(MBlocks.GRAVITATION_STABILIZER_LENS) provider.block(MBlocks.GRAVITATION_STABILIZER_LENS)
provider.block(MBlocks.POWERED_BLAST_FURNACE)
provider.block(MBlocks.POWERED_FURNACE)
provider.block(MBlocks.STORAGE_POWER_SUPPLIER) provider.block(MBlocks.STORAGE_POWER_SUPPLIER)
provider.block(MBlocks.MATTER_RECYCLER) provider.block(MBlocks.MATTER_RECYCLER)
provider.block(MBlocks.MATTER_RECONSTRUCTOR)
provider.block(MBlocks.ENERGY_SERVO) provider.block(MBlocks.ENERGY_SERVO)
provider.block(MBlocks.COBBLESTONE_GENERATOR)
provider.block(MBlocks.ESSENCE_STORAGE)
provider.exec { provider.exec {
for (crate in MRegistry.CARGO_CRATES.allBlocks.values) { for (crate in MRegistry.CARGO_CRATES.allBlocks.values) {
@ -93,76 +113,75 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
return@forAllStates arrayOf( return@forAllStates arrayOf(
ConfiguredModel.builder() ConfiguredModel.builder()
.modelFile(provider.models().getExistingFile( .modelFile(provider.models().getExistingFile(
ResourceLocation( modLocation("${crate.registryName!!.path}_${if (it.getValue(
OverdriveThatMatters.MOD_ID, "${crate.registryName!!.path}_${if (it.getValue(
CargoCrateBlock.IS_OPEN)) "open" else "closed"}") CargoCrateBlock.IS_OPEN)) "open" else "closed"}")
)) ))
.rotationY(it.getValue(RotatableMatteryBlock.FACING).toYRotBlockstate()) .rotationY(it.getValue(BlockRotationFreedom.HORIZONTAL.property).front.yRotationBlockstateNorth())
.buildLast() .buildLast()
) )
} }
} }
with(provider.getMultipartBuilder(MBlocks.STORAGE_BUS)) { with(provider.getMultipartBuilder(MBlocks.STORAGE_BUS)) {
for (dir in net.minecraft.core.Direction.values()) { for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_bus"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_bus")))
.rotationX(dir.toXRotBlockstate()) .rotationX(dir.front.xRotationBlockstateNorth())
.rotationY(dir.toYRotBlockstate()) .rotationY(dir.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING_FULL, dir) .condition(BlockRotationFreedom.DIRECTIONAL.property, dir)
.end() .end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_connection"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
.rotationX(dir.toXRotBlockstateInv()) .rotationX(dir.front.xRotationBlockstateSouth())
.rotationY(dir.toYRotBlockstateInv()) .rotationY(dir.front.yRotationBlockstateSouth())
.addModel() .addModel()
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.ordinal], true) .condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
.end() .end()
} }
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_core"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
.addModel().end() .addModel().end()
} }
with(provider.getMultipartBuilder(MBlocks.STORAGE_IMPORTER)) { with(provider.getMultipartBuilder(MBlocks.STORAGE_IMPORTER)) {
for (dir in net.minecraft.core.Direction.values()) { for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_importer"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_importer")))
.rotationX(dir.toXRotBlockstate()) .rotationX(dir.front.xRotationBlockstateNorth())
.rotationY(dir.toYRotBlockstate()) .rotationY(dir.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING_FULL, dir) .condition(BlockRotationFreedom.DIRECTIONAL.property, dir)
.end() .end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_connection"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
.rotationX(dir.toXRotBlockstateInv()) .rotationX(dir.front.xRotationBlockstateSouth())
.rotationY(dir.toYRotBlockstateInv()) .rotationY(dir.front.yRotationBlockstateSouth())
.addModel() .addModel()
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.ordinal], true) .condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
.end() .end()
} }
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_core"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
.addModel().end() .addModel().end()
} }
with(provider.getMultipartBuilder(MBlocks.STORAGE_EXPORTER)) { with(provider.getMultipartBuilder(MBlocks.STORAGE_EXPORTER)) {
for (dir in net.minecraft.core.Direction.values()) { for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_exporter"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_exporter")))
.rotationX(dir.toXRotBlockstate()) .rotationX(dir.front.xRotationBlockstateNorth())
.rotationY(dir.toYRotBlockstate()) .rotationY(dir.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING_FULL, dir) .condition(BlockRotationFreedom.DIRECTIONAL.property, dir)
.end() .end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_connection"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
.rotationX(dir.toXRotBlockstateInv()) .rotationX(dir.front.xRotationBlockstateSouth())
.rotationY(dir.toYRotBlockstateInv()) .rotationY(dir.front.yRotationBlockstateSouth())
.addModel() .addModel()
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.ordinal], true) .condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
.end() .end()
} }
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_core"))) part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
.addModel().end() .addModel().end()
} }
} }

View File

@ -1,52 +1,50 @@
package ru.dbotthepony.mc.otm.datagen.blocks package ru.dbotthepony.mc.otm.datagen.blocks
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
import ru.dbotthepony.mc.otm.block.EnergyCounterBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock
import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.datagen.DataGen.MOD_ID import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.datagen.toYRotBlockstate import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
fun addComplexBlockStates(provider: MatteryBlockStateProvider) { fun addComplexBlockStates(provider: MatteryBlockStateProvider) {
with(provider.getMultipartBuilder(MBlocks.DRIVE_VIEWER)) { with(provider.getMultipartBuilder(MBlocks.DRIVE_VIEWER)) {
for (facing in RotatableMatteryBlock.FACING.possibleValues) { for (facing in BlockRotationFreedom.HORIZONTAL.possibleValues) {
part() part()
.modelFile(provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/drive_viewer_drive_part"))) .modelFile(provider.models().getExistingFile(modLocation("block/drive_viewer_drive_part")))
.rotationY(facing.toYRotBlockstate()) .rotationY(facing.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING, facing) .condition(BlockRotationFreedom.HORIZONTAL.property, facing)
.condition(DriveViewerBlock.DRIVE_PRESENT, true) .condition(DriveViewerBlock.DRIVE_PRESENT, true)
for (workState in WorkerState.SEMI_WORKER_STATE.possibleValues) { for (workState in WorkerState.SEMI_WORKER_STATE.possibleValues) {
part() part()
.modelFile(provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/drive_viewer_${workState.name.lowercase()}"))) .modelFile(provider.models().getExistingFile(modLocation("block/drive_viewer_${workState.name.lowercase()}")))
.rotationY(facing.toYRotBlockstate()) .rotationY(facing.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(WorkerState.SEMI_WORKER_STATE, workState) .condition(WorkerState.SEMI_WORKER_STATE, workState)
.condition(RotatableMatteryBlock.FACING, facing) .condition(BlockRotationFreedom.HORIZONTAL.property, facing)
} }
} }
} }
with(provider.getMultipartBuilder(MBlocks.PATTERN_STORAGE)) { with(provider.getMultipartBuilder(MBlocks.PATTERN_STORAGE)) {
for (facing in RotatableMatteryBlock.FACING.possibleValues) { for (facing in BlockRotationFreedom.HORIZONTAL.possibleValues) {
part() part()
.modelFile(provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/pattern_storage"))) .modelFile(provider.models().getExistingFile(modLocation("block/pattern_storage")))
.rotationY(facing.toYRotBlockstate()) .rotationY(facing.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING, facing) .condition(BlockRotationFreedom.HORIZONTAL.property, facing)
for (i in 0 .. 7) { for (i in 0 .. 7) {
part() part()
.modelFile(provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/pattern/model$i"))) .modelFile(provider.models().getExistingFile(modLocation("block/pattern/model$i")))
.rotationY(facing.toYRotBlockstate()) .rotationY(facing.front.yRotationBlockstateNorth())
.addModel() .addModel()
.condition(RotatableMatteryBlock.FACING, facing) .condition(BlockRotationFreedom.HORIZONTAL.property, facing)
.condition(PatternStorageBlock.PATTERN_STORAGE_DISKS_PROPS[i], true) .condition(PatternStorageBlock.PATTERN_STORAGE_DISKS_PROPS[i], true)
} }
} }
@ -54,24 +52,24 @@ fun addComplexBlockStates(provider: MatteryBlockStateProvider) {
with(provider.getMultipartBuilder(MBlocks.ENERGY_COUNTER)) { with(provider.getMultipartBuilder(MBlocks.ENERGY_COUNTER)) {
// даваааййй // даваааййй
val up = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_up")) val up = provider.models().getExistingFile(modLocation("block/energy_counter_up"))
val down = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_down")) val down = provider.models().getExistingFile(modLocation("block/energy_counter_down"))
val west = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_west")) val west = provider.models().getExistingFile(modLocation("block/energy_counter_west"))
val east = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_east")) val east = provider.models().getExistingFile(modLocation("block/energy_counter_east"))
// ДАААА ДАВАЙЙ ДАААВАААЙЙЙЙЙЙ // ДАААА ДАВАЙЙ ДАААВАААЙЙЙЙЙЙ
val north = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_north")) val north = provider.models().getExistingFile(modLocation("block/energy_counter_north"))
val northDown = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_north_down")) val northDown = provider.models().getExistingFile(modLocation("block/energy_counter_north_down"))
val northEast = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_north_east")) val northEast = provider.models().getExistingFile(modLocation("block/energy_counter_north_east"))
val northWest = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_north_west")) val northWest = provider.models().getExistingFile(modLocation("block/energy_counter_north_west"))
val south = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_south")) val south = provider.models().getExistingFile(modLocation("block/energy_counter_south"))
val southDown = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_south_down")) val southDown = provider.models().getExistingFile(modLocation("block/energy_counter_south_down"))
val southEast = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_south_east")) val southEast = provider.models().getExistingFile(modLocation("block/energy_counter_south_east"))
val southWest = provider.models().getExistingFile(ResourceLocation(MOD_ID, "block/energy_counter_south_west")) val southWest = provider.models().getExistingFile(modLocation("block/energy_counter_south_west"))
for (dir in arrayOf(Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.NORTH)) { for (dir in arrayOf(Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.NORTH)) {
part().modelFile(down).rotationY(dir.toYRotBlockstate()).addModel().condition(EnergyCounterBlock.INPUT_DIRECTION, Direction.UP).condition(EnergyCounterBlock.IF_DIRECTION, dir) part().modelFile(down).rotationY(dir.yRotationBlockstateNorth()).addModel().condition(EnergyCounterBlock.INPUT_DIRECTION, Direction.UP).condition(EnergyCounterBlock.IF_DIRECTION, dir)
part().modelFile(up).rotationY(dir.toYRotBlockstate()).addModel().condition(EnergyCounterBlock.INPUT_DIRECTION, Direction.DOWN).condition(EnergyCounterBlock.IF_DIRECTION, dir) part().modelFile(up).rotationY(dir.yRotationBlockstateNorth()).addModel().condition(EnergyCounterBlock.INPUT_DIRECTION, Direction.DOWN).condition(EnergyCounterBlock.IF_DIRECTION, dir)
} }
// низкий поклон за полностью рабочий поворот вокруг оси Z // низкий поклон за полностью рабочий поворот вокруг оси Z

View File

@ -1,18 +1,18 @@
package ru.dbotthepony.mc.otm.datagen.blocks package ru.dbotthepony.mc.otm.datagen.blocks
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.client.model.generators.BlockStateProvider import net.minecraftforge.client.model.generators.BlockStateProvider
import net.minecraftforge.client.model.generators.ConfiguredModel import net.minecraftforge.client.model.generators.ConfiguredModel
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.core.getValueNullable
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.xRotationBlockstateNorth
import ru.dbotthepony.mc.otm.core.math.yRotationBlockstateNorth
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.getValueNullable
import ru.dbotthepony.mc.otm.datagen.toXRotBlockstate
import ru.dbotthepony.mc.otm.datagen.toYRotBlockstate
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation
import java.util.LinkedList import java.util.LinkedList
typealias BlockStateTransform = (state: BlockState, builder: ConfiguredModel.Builder<*>, path: String) -> String? typealias BlockStateTransform = (state: BlockState, builder: ConfiguredModel.Builder<*>, path: String) -> String?
@ -21,13 +21,18 @@ private val EMPTY: BlockStateTransform = { _, _, _ -> null }
private fun initialTransform(it: BlockState, modelPath: String, builder: ConfiguredModel.Builder<*>): String { private fun initialTransform(it: BlockState, modelPath: String, builder: ConfiguredModel.Builder<*>): String {
@Suppress("NAME_SHADOWING") var modelPath = modelPath @Suppress("NAME_SHADOWING") var modelPath = modelPath
it.getValueNullable(RotatableMatteryBlock.FACING)?.let { it.getValueNullable(BlockRotationFreedom.HORIZONTAL.property)?.let {
builder.rotationY(it.toYRotBlockstate()) builder.rotationY(it.front.yRotationBlockstateNorth())
} }
it.getValueNullable(RotatableMatteryBlock.FACING_FULL)?.let { it.getValueNullable(BlockRotationFreedom.DIRECTIONAL.property)?.let {
builder.rotationY(it.toYRotBlockstate()) builder.rotationY(it.front.yRotationBlockstateNorth())
builder.rotationX(it.toXRotBlockstate()) builder.rotationX(it.front.xRotationBlockstateNorth())
}
it.getValueNullable(BlockRotationFreedom.DIRECTIONAL_WITH_ROTATION.property)?.let {
builder.rotationY(it.front.yRotationBlockstateNorth() + it.top.yRotationBlockstateNorth())
builder.rotationX(it.front.xRotationBlockstateNorth())
} }
it.getValueNullable(WorkerState.WORKER_STATE)?.let { it.getValueNullable(WorkerState.WORKER_STATE)?.let {
@ -41,7 +46,7 @@ private fun initialTransform(it: BlockState, modelPath: String, builder: Configu
return modelPath return modelPath
} }
class MatteryBlockStateProvider(event: GatherDataEvent) : BlockStateProvider(event.generator, DataGen.MOD_ID, event.existingFileHelper) { class MatteryBlockStateProvider(event: GatherDataEvent) : BlockStateProvider(event.generator.packOutput, DataGen.MOD_ID, event.existingFileHelper) {
private val callbacks = LinkedList<() -> Unit>() private val callbacks = LinkedList<() -> Unit>()
fun exec(lambda: () -> Unit): MatteryBlockStateProvider { fun exec(lambda: () -> Unit): MatteryBlockStateProvider {
@ -55,7 +60,7 @@ class MatteryBlockStateProvider(event: GatherDataEvent) : BlockStateProvider(eve
var modelPath = initialTransform(it, "block/${block.registryName!!.path}", builder) var modelPath = initialTransform(it, "block/${block.registryName!!.path}", builder)
modelPath = func(it, builder, modelPath) ?: modelPath modelPath = func(it, builder, modelPath) ?: modelPath
builder.modelFile(models().getExistingFile(ResourceLocation(DataGen.MOD_ID, modelPath))) builder.modelFile(models().getExistingFile(modLocation(modelPath)))
return@forAllStates builder.build() return@forAllStates builder.build()
} }

View File

@ -1,9 +1,7 @@
package ru.dbotthepony.mc.otm.datagen.items package ru.dbotthepony.mc.otm.datagen.items
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
@ -22,6 +20,9 @@ fun addItemModels(provider: MatteryItemModelProvider) {
} }
provider.block(MItems.CARBON_FIBRE_BLOCK) provider.block(MItems.CARBON_FIBRE_BLOCK)
provider.block(MItems.METAL_JUNK)
provider.block(MItems.METAL_MESH)
provider.generatedTranslucent(MItems.TRITANIUM_BARS, modLocation("block/decorative/tritanium_bars"))
provider.block(MItems.DEEPSLATE_TRITANIUM_ORE) provider.block(MItems.DEEPSLATE_TRITANIUM_ORE)
provider.block(MItems.TRITANIUM_ORE) provider.block(MItems.TRITANIUM_ORE)
provider.block(MItems.TRITANIUM_STRIPED_BLOCK) provider.block(MItems.TRITANIUM_STRIPED_BLOCK)
@ -29,6 +30,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.block(MItems.TRITANIUM_INGOT_BLOCK) provider.block(MItems.TRITANIUM_INGOT_BLOCK)
provider.block(MItems.ITEM_MONITOR) provider.block(MItems.ITEM_MONITOR)
provider.block(MItems.PHANTOM_ATTRACTOR) provider.block(MItems.PHANTOM_ATTRACTOR)
provider.block(MItems.HOLO_SIGN)
MRegistry.VENT.allItems.values.forEach(provider::block) MRegistry.VENT.allItems.values.forEach(provider::block)
MRegistry.VENT_ALTERNATIVE.allItems.values.forEach(provider::block) MRegistry.VENT_ALTERNATIVE.allItems.values.forEach(provider::block)
@ -40,7 +42,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
} }
for ((color, glass) in MRegistry.INDUSTRIAL_GLASS_PANE.allItems) { for ((color, glass) in MRegistry.INDUSTRIAL_GLASS_PANE.allItems) {
provider.generatedTranslucent(glass, ResourceLocation(DataGen.MOD_ID, "block/decorative/${MRegistry.INDUSTRIAL_GLASS.allItems[color]!!.registryName!!.path}")) provider.generatedTranslucent(glass, modLocation("block/decorative/${MRegistry.INDUSTRIAL_GLASS.allItems[color]!!.registryName!!.path}"))
} }
provider.blocks(MRegistry.DECORATIVE_CRATE.allItems.values) provider.blocks(MRegistry.DECORATIVE_CRATE.allItems.values)
@ -53,6 +55,10 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.generated(MItems.PILL_HEAL) provider.generated(MItems.PILL_HEAL)
provider.generated(MItems.NUTRIENT_PASTE) provider.generated(MItems.NUTRIENT_PASTE)
provider.generated(MItems.ESSENCE_DRIVE)
provider.generated(MItems.ESSENCE_CAPSULE)
provider.generated(MItems.ESSENCE_SERVO)
for (item in MItems.ExopackUpgrades.INVENTORY_UPGRADES) { for (item in MItems.ExopackUpgrades.INVENTORY_UPGRADES) {
provider.generated(item, modLocation("item/exosuit_inventory_upgrade")) provider.generated(item, modLocation("item/exosuit_inventory_upgrade"))
} }
@ -69,24 +75,76 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.generated(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE) provider.generated(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE)
provider.generated(MItems.ExopackUpgrades.CRAFTING_UPGRADE) provider.generated(MItems.ExopackUpgrades.CRAFTING_UPGRADE)
provider.generated(MItems.ExopackUpgrades.SMELTING_UPGRADE)
provider.generated(MItems.ExopackUpgrades.ENDER_UPGRADE)
provider.component(MItems.TRITANIUM_DUST) provider.component(MItems.TRITANIUM_DUST)
provider.component(MItems.TRITANIUM_INGOT) provider.component(MItems.TRITANIUM_INGOT)
provider.component(MItems.TRITANIUM_NUGGET)
provider.resource(MItems.TRITANIUM_ORE_CLUMP) provider.resource(MItems.TRITANIUM_ORE_CLUMP)
provider.generated(MItems.EXOPACK_PROBE) provider.generated(MItems.EXOPACK_PROBE)
provider.handheld(MItems.TRITANIUM_TOOLS) provider.handheld(MItems.TRITANIUM_TOOLS)
provider.generated(MItems.TRITANIUM_ARMOR) provider.armorColored(MItems.TRITANIUM_ARMOR)
provider.generated(MItems.SIMPLE_TRITANIUM_ARMOR)
provider.handheld(MItems.CHEST_UPGRADER)
provider.generatedTiered(MItems.BATTERIES, "battery_tier") provider.generatedTiered(MItems.BATTERIES, "battery_tier")
provider.generated(MItems.BATTERY_CREATIVE) provider.generated(MItems.BATTERY_CREATIVE)
provider.generated(MItems.PROCEDURAL_BATTERY, modLocation("item/battery_procedural"))
provider.generated(MItems.MATTER_CAPACITOR_BASIC, ResourceLocation(DataGen.MOD_ID, "item/matter_capacitor_tier1")) provider.generated(MItems.MATTER_CAPACITOR_BASIC, modLocation("item/matter_capacitor_tier1"))
provider.generated(MItems.MATTER_CAPACITOR_NORMAL, ResourceLocation(DataGen.MOD_ID, "item/matter_capacitor_tier2")) provider.generated(MItems.MATTER_CAPACITOR_NORMAL, modLocation("item/matter_capacitor_tier2"))
provider.generated(MItems.MATTER_CAPACITOR_DENSE, ResourceLocation(DataGen.MOD_ID, "item/matter_capacitor_tier3")) provider.generated(MItems.MATTER_CAPACITOR_DENSE, modLocation("item/matter_capacitor_tier3"))
provider.generated(MItems.MATTER_CAPACITOR_CREATIVE) provider.generated(MItems.MATTER_CAPACITOR_CREATIVE)
provider.generated(MItems.MachineUpgrades.Basic.BLANK, modLocation("item/machine_upgrade_tier1"))
provider.upgrade(MItems.MachineUpgrades.Basic.SPEED, "speed", "tier1")
provider.upgrade(MItems.MachineUpgrades.Basic.ENERGY_CONSUMPTION, "energy", "tier1")
provider.upgrade(MItems.MachineUpgrades.Basic.FAILSAFE, "failure", "tier1")
provider.upgrade(MItems.MachineUpgrades.Basic.ENERGY_STORAGE, "capacity", "tier1")
provider.upgrade(MItems.MachineUpgrades.Basic.MATTER_STORAGE, "matter", "tier1")
provider.upgrade(MItems.MachineUpgrades.Basic.PROCESSING_ITEMS, "processing", "tier1")
provider.generated(MItems.MachineUpgrades.Normal.BLANK, modLocation("item/machine_upgrade_tier2"))
provider.upgrade(MItems.MachineUpgrades.Normal.SPEED, "speed", "tier2")
provider.upgrade(MItems.MachineUpgrades.Normal.ENERGY_CONSUMPTION, "energy", "tier2")
provider.upgrade(MItems.MachineUpgrades.Normal.FAILSAFE, "failure", "tier2")
provider.upgrade(MItems.MachineUpgrades.Normal.ENERGY_STORAGE, "capacity", "tier2")
provider.upgrade(MItems.MachineUpgrades.Normal.MATTER_STORAGE, "matter", "tier2")
provider.upgrade(MItems.MachineUpgrades.Normal.PROCESSING_ITEMS, "processing", "tier2")
provider.generated(MItems.MachineUpgrades.Advanced.BLANK, modLocation("item/machine_upgrade_tier3"))
provider.upgrade(MItems.MachineUpgrades.Advanced.SPEED, "speed", "tier3")
provider.upgrade(MItems.MachineUpgrades.Advanced.ENERGY_CONSUMPTION, "energy", "tier3")
provider.upgrade(MItems.MachineUpgrades.Advanced.FAILSAFE, "failure", "tier3")
provider.upgrade(MItems.MachineUpgrades.Advanced.ENERGY_STORAGE, "capacity", "tier3")
provider.upgrade(MItems.MachineUpgrades.Advanced.MATTER_STORAGE, "matter", "tier3")
provider.upgrade(MItems.MachineUpgrades.Advanced.PROCESSING_ITEMS, "processing", "tier3")
provider.upgrade(MItems.MachineUpgrades.Creative.SPEED, "speed", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.ENERGY_CONSUMPTION, "energy", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT, "energy", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT_FLAT, "energy", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT_FLAT_SMALL, "energy", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.ENERGY_STORAGE, "capacity", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.ENERGY_STORAGE_FLAT, "capacity", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.ENERGY_STORAGE_FLAT_SMALL, "capacity", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.FAILSAFE, "failure", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.FAILURE, "failure", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.PROCESSING_ITEMS, "processing", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.MATTER_STORAGE, "matter", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT, "matter", "creative")
provider.upgrade(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT_SMALL, "matter", "creative")
provider.generated(MItems.QUANTUM_BATTERY) provider.generated(MItems.QUANTUM_BATTERY)
provider.generated(MItems.QUANTUM_CAPACITOR) provider.generated(MItems.QUANTUM_CAPACITOR)
provider.generated(MItems.QUANTUM_BATTERY_CREATIVE) provider.generated(MItems.QUANTUM_BATTERY_CREATIVE)
@ -100,6 +158,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.block(MItems.TRITANIUM_TRAPDOOR[null]!!, "tritanium_trapdoor_bottom") provider.block(MItems.TRITANIUM_TRAPDOOR[null]!!, "tritanium_trapdoor_bottom")
for (color in DyeColor.values()) for (color in DyeColor.values())
provider.block(MItems.TRITANIUM_TRAPDOOR[color]!!, "tritanium_trapdoor_${color.name.lowercase()}_bottom") provider.block(MItems.TRITANIUM_TRAPDOOR[color]!!, "tritanium_trapdoor_${color.name.lowercase()}_bottom")
@ -113,15 +172,25 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.block(MItems.MATTER_CABLE, "matter_cable_core") provider.block(MItems.MATTER_CABLE, "matter_cable_core")
provider.block(MItems.MATTER_DECOMPOSER, "matter_decomposer_working") provider.block(MItems.MATTER_DECOMPOSER, "matter_decomposer_working")
provider.block(MItems.ENERGY_SERVO, "energy_servo") provider.block(MItems.ENERGY_SERVO, "energy_servo")
provider.block(MItems.ESSENCE_STORAGE, "essence_storage")
provider.block(MItems.MATTER_RECONSTRUCTOR, "matter_reconstructor")
provider.block(MItems.POWERED_BLAST_FURNACE, "powered_blast_furnace_working")
provider.block(MItems.POWERED_FURNACE, "powered_furnace_working")
provider.block(MItems.PLATE_PRESS, "plate_press_idle") provider.block(MItems.PLATE_PRESS, "plate_press_idle")
provider.block(MItems.TWIN_PLATE_PRESS, "twin_plate_press_idle")
provider.block(MItems.STORAGE_POWER_SUPPLIER, "storage_power_supplier") provider.block(MItems.STORAGE_POWER_SUPPLIER, "storage_power_supplier")
provider.block(MItems.MATTER_RECYCLER, "matter_recycler_working") provider.block(MItems.MATTER_RECYCLER, "matter_recycler_working")
provider.block(MItems.COBBLESTONE_GENERATOR, "cobblestone_generator")
provider.block(MItems.STORAGE_BUS) provider.block(MItems.STORAGE_BUS)
provider.block(MItems.STORAGE_IMPORTER) provider.block(MItems.STORAGE_IMPORTER)
provider.block(MItems.STORAGE_EXPORTER) provider.block(MItems.STORAGE_EXPORTER)
for (item in MItems.TRITANIUM_ANVIL) {
provider.block(item)
}
for ((color, item) in MItems.CARGO_CRATE_MINECARTS) { for ((color, item) in MItems.CARGO_CRATE_MINECARTS) {
provider.generated(item) provider.generated(item)
} }

View File

@ -1,15 +1,20 @@
package ru.dbotthepony.mc.otm.datagen.items package ru.dbotthepony.mc.otm.datagen.items
import net.minecraft.data.models.ItemModelGenerators
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.PackType
import net.minecraft.world.item.ArmorItem
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraftforge.client.model.generators.ItemModelProvider import net.minecraftforge.client.model.generators.ItemModelProvider
import net.minecraftforge.client.model.generators.ModelBuilder
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.modLocation
import java.util.LinkedList import java.util.LinkedList
class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event.generator, DataGen.MOD_ID, event.existingFileHelper) { class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event.generator.packOutput, DataGen.MOD_ID, event.existingFileHelper) {
private val callbacks = LinkedList<() -> Unit>() private val callbacks = LinkedList<() -> Unit>()
fun exec(func: () -> Unit): MatteryItemModelProvider { fun exec(func: () -> Unit): MatteryItemModelProvider {
@ -23,8 +28,8 @@ class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event
} }
} }
fun block(item: Item) = exec { withExistingParent(item.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/${item.registryName!!.path}")) } fun block(item: Item) = exec { withExistingParent(item.registryName!!.path, modLocation("block/${item.registryName!!.path}")) }
fun block(item: Item, path: String) = exec { withExistingParent(item.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/$path")) } fun block(item: Item, path: String) = exec { withExistingParent(item.registryName!!.path, modLocation("block/$path")) }
fun blocks(vararg items: Item) = items.forEach(this::block) fun blocks(vararg items: Item) = items.forEach(this::block)
fun blocks(items: Collection<Item>) = items.forEach(this::block) fun blocks(items: Collection<Item>) = items.forEach(this::block)
@ -40,18 +45,18 @@ class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event
withExistingParent(item.registryName!!.path, HANDHELD).texture("layer0", texture) withExistingParent(item.registryName!!.path, HANDHELD).texture("layer0", texture)
} }
fun generated(item: Item) = generated(item, ResourceLocation(DataGen.MOD_ID, "item/${item.registryName!!.path}")) fun generated(item: Item) = generated(item, modLocation("item/${item.registryName!!.path}"))
fun generated(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) } fun generated(vararg items: Item) = items.forEach { generated(it, modLocation("item/${it.registryName!!.path}")) }
fun KOT(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "block/ph_kitty")) } fun KOT(vararg items: Item) = items.forEach { generated(it, modLocation("block/ph_kitty")) }
fun generated(items: Collection<Item>) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) } fun generated(items: Collection<Item>) = items.forEach { generated(it, modLocation("item/${it.registryName!!.path}")) }
fun generatedBlock(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "block/${it.registryName!!.path}")) } fun generatedBlock(vararg items: Item) = items.forEach { generated(it, modLocation("block/${it.registryName!!.path}")) }
fun generatedBlockDecorative(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "block/decorative/${it.registryName!!.path}")) } fun generatedBlockDecorative(vararg items: Item) = items.forEach { generated(it, modLocation("block/decorative/${it.registryName!!.path}")) }
fun handheld(vararg items: Item) = items.forEach { handheld(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) } fun handheld(vararg items: Item) = items.forEach { handheld(it, modLocation("item/${it.registryName!!.path}")) }
fun handheld(items: Collection<Item>) = items.forEach { handheld(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) } fun handheld(items: Collection<Item>) = items.forEach { handheld(it, modLocation("item/${it.registryName!!.path}")) }
fun generated(item: Item, prefix: String) = generated(item, ResourceLocation(DataGen.MOD_ID, "item/${prefix}${item.registryName!!.path}")) fun generated(item: Item, prefix: String) = generated(item, modLocation("item/${prefix}${item.registryName!!.path}"))
fun generatedStrict(item: Item, path: String) = generated(item, ResourceLocation(DataGen.MOD_ID, "item/$path")) fun generatedStrict(item: Item, path: String) = generated(item, modLocation("item/$path"))
fun handheld(item: Item, prefix: String) = handheld(item, ResourceLocation(DataGen.MOD_ID, "item/${prefix}${item.registryName!!.path}")) fun handheld(item: Item, prefix: String) = handheld(item, modLocation("item/${prefix}${item.registryName!!.path}"))
fun component(item: Item) = generated(item, "component/") fun component(item: Item) = generated(item, "component/")
fun components(vararg items: Item) = items.forEach(this::component) fun components(vararg items: Item) = items.forEach(this::component)
@ -63,7 +68,7 @@ class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event
var i = 0 var i = 0
for (item in items) { for (item in items) {
generated(item, ResourceLocation(DataGen.MOD_ID, "item/$prefix$i")) generated(item, modLocation("item/$prefix$i"))
i++ i++
} }
} }
@ -72,12 +77,27 @@ class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event
var i = 0 var i = 0
for (item in items) { for (item in items) {
generated(item, ResourceLocation(DataGen.MOD_ID, "item/$prefix$i")) generated(item, modLocation("item/$prefix$i"))
i++ i++
} }
} }
fun armorColored(item: Item) = exec {
withExistingParent(item.registryName!!.path, GENERATED)
.texture("layer0", modLocation("item/${item.registryName!!.path}_base"))
.texture("layer1", modLocation("item/${item.registryName!!.path}_overlay"))
}
fun armorColored(vararg items: Item) = items.forEach { armorColored(it) }
fun armorColored(items: Collection<Item>) = items.forEach { armorColored(it) }
fun upgrade(item: Item, upgradeType: String, tier: String = "tier0") = exec {
withExistingParent(item.registryName!!.path, GENERATED)
.texture("layer0", modLocation("item/machine_upgrade_$tier"))
.texture("layer1", modLocation("item/machine_upgrade_icon_$upgradeType"))
}
companion object { companion object {
val ARMOR_TRIM_MATERIALS = listOf("quartz", "iron", "netherite", "redstone", "copper", "gold", "emerald", "diamond", "lapis", "amethyst")
val GENERATED = ResourceLocation("minecraft", "item/generated") val GENERATED = ResourceLocation("minecraft", "item/generated")
val HANDHELD = ResourceLocation("minecraft", "item/handheld") val HANDHELD = ResourceLocation("minecraft", "item/handheld")
private val LOGGER = LogManager.getLogger() private val LOGGER = LogManager.getLogger()

View File

@ -3,23 +3,25 @@ package ru.dbotthepony.mc.otm.datagen.lang
import ru.dbotthepony.mc.otm.registry.* import ru.dbotthepony.mc.otm.registry.*
private fun decoratives(provider: MatteryLanguageProvider) { private fun decoratives(provider: MatteryLanguageProvider) {
provider.englishColors.add(MRegistry.VENT, "%s Vent") with(provider.englishColors) {
provider.englishColors.add(MRegistry.VENT_ALTERNATIVE, "%s Alternative Vent") add(MRegistry.VENT, "%s Vent")
add(MRegistry.VENT_ALTERNATIVE, "%s Alternative Vent")
provider.englishColors.add(MRegistry.TRITANIUM_BLOCK, "%s Tritanium Block") add(MRegistry.TRITANIUM_BLOCK, "%s Tritanium Block")
provider.englishColors.add(MRegistry.TRITANIUM_STAIRS, "%s Tritanium Stairs") add(MRegistry.TRITANIUM_STAIRS, "%s Tritanium Stairs")
provider.englishColors.add(MRegistry.TRITANIUM_SLAB, "%s Tritanium Slab") add(MRegistry.TRITANIUM_SLAB, "%s Tritanium Slab")
provider.englishColors.add(MRegistry.TRITANIUM_WALL, "%s Tritanium Wall") add(MRegistry.TRITANIUM_WALL, "%s Tritanium Wall")
provider.englishColors.add(MRegistry.FLOOR_TILES, "%s Floor Tiles") add(MRegistry.FLOOR_TILES, "%s Floor Tiles")
provider.englishColors.add(MRegistry.FLOOR_TILES_STAIRS, "%s Floor Tiles Stairs") add(MRegistry.FLOOR_TILES_STAIRS, "%s Floor Tiles Stairs")
provider.englishColors.add(MRegistry.FLOOR_TILES_SLAB, "%s Floor Tiles Slab") add(MRegistry.FLOOR_TILES_SLAB, "%s Floor Tiles Slab")
provider.englishColors.add(MRegistry.UNREFINED_FLOOR_TILES, "Unrefined %s Floor Tiles") add(MRegistry.UNREFINED_FLOOR_TILES, "Unrefined %s Floor Tiles")
provider.englishColors.add(MRegistry.INDUSTRIAL_GLASS, "%s Stained Industrial Glass") add(MRegistry.INDUSTRIAL_GLASS, "%s Stained Industrial Glass")
provider.englishColors.add(MRegistry.INDUSTRIAL_GLASS_PANE, "%s Stained Industrial Glass Pane") add(MRegistry.INDUSTRIAL_GLASS_PANE, "%s Stained Industrial Glass Pane")
provider.englishColors.add(MRegistry.CARGO_CRATES, "%s Cargo Crate") add(MRegistry.CARGO_CRATES, "%s Cargo Crate")
provider.englishColors.add(MRegistry.DECORATIVE_CRATE, "%s Container Block") add(MRegistry.DECORATIVE_CRATE, "%s Container Block")
}
with (provider.english) { with (provider.english) {
for ((color, name) in provider.englishColors.dyeClassMapped) { for ((color, name) in provider.englishColors.dyeClassMapped) {
@ -46,10 +48,10 @@ private fun decoratives(provider: MatteryLanguageProvider) {
add(MRegistry.TRITANIUM_PRESSURE_PLATE.block, "description1", "High blast resistance") add(MRegistry.TRITANIUM_PRESSURE_PLATE.block, "description1", "High blast resistance")
} }
provider.english.add(MItems.CARGO_CRATE_MINECARTS[null]!!, "Minecart with Cargo Crate")
provider.english.add(MEntityTypes.CARGO_CRATE_MINECARTS[null]!!, "Minecart with Cargo Crate")
with(provider.english) { with(provider.english) {
add(MItems.CARGO_CRATE_MINECARTS[null]!!, "Minecart with Cargo Crate")
add(MEntityTypes.CARGO_CRATE_MINECARTS[null]!!, "Minecart with Cargo Crate")
add(MRegistry.CARGO_CRATES.block, "Cargo Crate") add(MRegistry.CARGO_CRATES.block, "Cargo Crate")
add(MRegistry.TRITANIUM_BLOCK.block, "Tritanium Block") add(MRegistry.TRITANIUM_BLOCK.block, "Tritanium Block")
add(MRegistry.TRITANIUM_STAIRS.block, "Tritanium Stairs") add(MRegistry.TRITANIUM_STAIRS.block, "Tritanium Stairs")
@ -64,6 +66,7 @@ private fun decoratives(provider: MatteryLanguageProvider) {
add(MRegistry.VENT.block, "Vent") add(MRegistry.VENT.block, "Vent")
add(MRegistry.VENT_ALTERNATIVE.block, "Alternative Vent") add(MRegistry.VENT_ALTERNATIVE.block, "Alternative Vent")
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_BLOCK.blocksWithColor) { for ((block, colors) in MRegistry.TRITANIUM_STRIPED_BLOCK.blocksWithColor) {
val (base, stripe) = colors val (base, stripe) = colors
@ -114,6 +117,17 @@ private fun sounds(provider: MatteryLanguageProvider) {
private fun misc(provider: MatteryLanguageProvider) { private fun misc(provider: MatteryLanguageProvider) {
with(provider.english) { with(provider.english) {
gui("help.slot_filters", "Hold CTRL to setup slot filters")
gui("help.slot_charging", "Hold ALT to switch slot charging")
gui("needs", "Needs %s")
gui("needs_x", "Needs %s x%d")
misc("needs_no_power", "Requires no power to operate")
gui("lock_holo_screen", "Lock contents")
gui("lock_holo_screen.tip", "Locking and unlocking contents is only possible in creative.\nWhen locked, text boundaries are removed.")
gui("ticks", "Ticks") gui("ticks", "Ticks")
gui("power_cost_per_use", "Power cost per use: %s") gui("power_cost_per_use", "Power cost per use: %s")
@ -125,24 +139,34 @@ private fun misc(provider: MatteryLanguageProvider) {
gui("recipe.ticks", "%s Ticks") gui("recipe.ticks", "%s Ticks")
gui("exopack", "Exopack Inventory") gui("exopack", "Exopack Inventory")
gui("exopack.customize", "Customize Exopack appearance")
gui("exopack.customization", "Exopack appearance settings")
gui("exopack.go_back", "Open vanilla inventory") gui("exopack.go_back", "Open vanilla inventory")
gui("exopack.go_in", "Open Exopack inventory") gui("exopack.go_in", "Open Exopack inventory")
gui("exopack.toggle_visibility", "Toggle Exopack visibility") gui("exopack.toggle_visibility", "Visibile on player")
gui("exopack.toggle_glow", "Glows in dark")
gui("exopack.change_color", "Customize color")
gui("exopack.change_color2", "Remove color")
gui("exopack.go_curios", "Open Curios inventory")
gui("exopack.probe1", "This little device feels unnatural to touch, it is almost certainly resilient to any possible attempt to break it open.") gui("exopack.probe1", "This little device feels unnatural to touch, it is almost certainly resilient to any possible attempt to break it open.")
gui("exopack.probe2", "There is fingerprint reader built into one of sides which gently glow when touched.") gui("exopack.probe2", "There is fingerprint reader built into one of sides which gently glow when touched.")
gui("exopack.probe3", "It seems this box will unlock once you strongly press fingerprint reader, and you feel what's inside will affect you without any way back!") gui("exopack.probe3", "It seems this box will unlock once you strongly press fingerprint reader, and you feel what's inside will affect you without any way back!")
gui("exopack.already_activated", "You already have an Exopack on you!") gui("exopack.already_activated", "You already have an Exopack!")
gui("exopack_upgrades.no_exopack", "This piece of technology seems to be of no use to you.... Or does it?!") gui("exopack_upgrades.no_exopack", "This piece of technology seems to be of no use to you.... Or does it?!")
gui("exopack_upgrades.already_activated", "Upgrade is already active!") gui("exopack_upgrades.already_activated", "Upgrade is already active!")
gui("exopack_upgrades.slots_upgrade", "Using this will permanently grant %s slots in your Exopack inventory.") gui("exopack_upgrades.slots_upgrade", "Using this will permanently grant %s slots in your Exopack inventory.")
gui("exopack_upgrades.crafting_upgrade", "Using this will permanently grant 3x3 crafting grid in your Exopack inventory.") gui("exopack_upgrades.crafting_upgrade", "Using this will permanently grant 3x3 crafting grid in your Exopack inventory.")
gui("exopack_upgrades.smelting_upgrade", "Using this will permanently grant smelter in your Exopack inventory.")
gui("exopack_upgrades.ender_access_upgrade", "Using this will permanently grant Ender Chest access in your Exopack inventory.")
gui("crude_battery.replace_in_world", "Simplistic nature of this battery allows to replace your energy source in the field without using Android Station.") gui("crude_battery.replace_in_world", "Simplistic nature of this battery allows to replace your energy source in the field without using Android Station.")
gui("crude_battery.replace_in_world_warning", "This operation is very unstable and causes serious damage to your systems!") gui("crude_battery.replace_in_world_warning", "This operation is very unstable and can cause extreme damage to your systems!")
gui("power_supplier.active_nodes", "Currently demanding nodes: %s") gui("power_supplier.active_nodes", "Currently demanding nodes: %s")
@ -150,15 +174,16 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("exopack_upgrades.slots_upgraded", "Your Exopack has permanently gained %s slots") misc("exopack_upgrades.slots_upgraded", "Your Exopack has permanently gained %s slots")
misc("exopack_upgrades.crafting_upgraded", "Your Exopack has permanently gained 3x3 crafting grid") misc("exopack_upgrades.crafting_upgraded", "Your Exopack has permanently gained 3x3 crafting grid")
misc("exopack_upgrades.smelting_installed", "Your Exopack has permanently gained smelting module")
misc("exopack_upgrades.ender_access_installed", "Your Exopack has permanently gained access to Ender Chest contents")
misc("exopack.granted1", "As you keep pressing on the fingerprint reader, you are getting hurt in finger.") misc("exopack.granted1", "As you keep pressing on the fingerprint reader, probe disappears.")
misc("exopack.granted2", "After you raise your finger, fingerprint reader glows very bright.") misc("exopack.granted2", "After a moment, you are getting pierced into back multiple times...")
misc("exopack.granted3", "Then, the fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.") misc("exopack.granted3", "As pain signals ease away, you find a new 'friend' on your back: the Exopack.")
misc("exopack.granted4", "The device opens... And whatever was inside it shroud you, yet you feel nothing, as it wasn't even there.") misc("exopack.granted4", "This device provides access to personal pocket dimension in 4th space.")
misc("exopack.granted5", "As whatever shrouded you takes final form, you feel it binds to your soul.") misc("exopack.granted5", "Scavenge for or craft modules to upgrade your Exopack.")
misc("exopack.granted6", "INITIALIZATION SEQUENCE COMPLETE. WELCOME, USER %s") misc("exopack.granted6", "The Exopack itself also exists in 4th dimension, it does not prevent wearing armor.")
misc("exopack.granted7", "You are now permanently equipped with four dimensional omni-present Exopack.") misc("exopack.granted7", "However, despite existing in 4th dimension, items stored in it are still dropped upon unfortunate event.")
misc("exopack.granted8", "As of now, this Exopack is not much, but it's built-in AI hints there are upgrade modules out there somewhere...")
misc("dumping_matter_registry", "Dumping matter registry to %s") misc("dumping_matter_registry", "Dumping matter registry to %s")
misc("dumped_matter_registry", "Dumped matter registry to %s") misc("dumped_matter_registry", "Dumped matter registry to %s")
@ -166,10 +191,11 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("iteration", "Iteration %s") misc("iteration", "Iteration %s")
misc("death_reason", "Decommissioned!") misc("death_reason", "Decommissioned!")
misc("item.blackhole_immunity", "Negates gravitational effects of singularities") misc("item.blackhole_immunity", "Negates spacetime dilating effect of singularities")
misc("suffix.merge", "%s %s") misc("suffix.merge", "%s %s")
misc("suffix.none", "%s %s")
misc("suffix.kilo", "%s k%s") misc("suffix.kilo", "%s k%s")
misc("suffix.mega", "%s M%s") misc("suffix.mega", "%s M%s")
misc("suffix.giga", "%s G%s") misc("suffix.giga", "%s G%s")
@ -190,6 +216,27 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("suffix.zepto", "%s z%s") misc("suffix.zepto", "%s z%s")
misc("suffix.yocto", "%s y%s") misc("suffix.yocto", "%s y%s")
misc("suffix_concise.none", "%s")
misc("suffix_concise.kilo", "%sk")
misc("suffix_concise.mega", "%sM")
misc("suffix_concise.giga", "%sG")
misc("suffix_concise.tera", "%sT")
misc("suffix_concise.peta", "%sP")
misc("suffix_concise.exa", "%sE")
misc("suffix_concise.zetta", "%sZ")
misc("suffix_concise.yotta", "%sY")
misc("suffix_concise.deci", "%sd")
misc("suffix_concise.centi", "%sc")
misc("suffix_concise.milli", "%sm")
misc("suffix_concise.micro", "%sμ")
misc("suffix_concise.nano", "%sn")
misc("suffix_concise.pico", "%sp")
misc("suffix_concise.femto", "%sf")
misc("suffix_concise.atto", "%sa")
misc("suffix_concise.zepto", "%sz")
misc("suffix_concise.yocto", "%sy")
misc("suffix_raw.kilo", "k") misc("suffix_raw.kilo", "k")
misc("suffix_raw.mega", "M") misc("suffix_raw.mega", "M")
misc("suffix_raw.giga", "G") misc("suffix_raw.giga", "G")
@ -209,31 +256,24 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("suffix_raw.zepto", "z") misc("suffix_raw.zepto", "z")
misc("suffix_raw.yocto", "y") misc("suffix_raw.yocto", "y")
misc("container.matter_panel.increase_by", "+%s") misc("item.power.infinite.storage", "Stored energy: ∞ / ∞")
misc("container.matter_panel.decrease_by", "-%s") misc("item.power.infinite.throughput", "Max I/O: ∞ / ∞")
misc("container.matter_panel.send", "Send")
misc("container.matter_panel.close", "Close")
misc("container.matter_panel.cancel_task", "Cancel task")
misc("container.matter_panel.cancel", "Cancel")
misc("container.matter_panel.label", "Replication request")
misc("container.matter_panel.task", "Ongoing replication task")
misc("container.matter_panel.task_line", "%s: %s | %s / %s")
misc("container.matter_panel.tasks", "Tasks")
misc("container.matter_panel.patterns", "Patterns")
misc("item.power.infinite.storage", "Stored energy: Infinity / Infinity")
misc("item.power.infinite.throughput", "Max I/O Infinite / Infinite")
misc("item.power.passed", "Passed energy: %s") misc("item.power.passed", "Passed energy: %s")
misc("item.power.received", "Received energy: %s") misc("item.power.received", "Received energy: %s")
misc("item.power.average", "Average throughput: %s/t") misc("item.power.average", "Average throughput: %s/t")
misc("item.power.last_20_ticks", "Last second: %s") misc("item.power.last_20_ticks", "Last second: %s")
misc("item.power.last_tick", "Last tick: %s") misc("item.power.last_tick", "Last tick: %s")
gui("power.passed", "Total passed energy:")
gui("power.average", "Average throughput per tick:")
gui("power.last_20_ticks", "Last second:")
gui("power.last_tick", "Last tick:")
misc("item.power.storage", "Stored energy: %s / %s") misc("item.power.storage", "Stored energy: %s / %s")
misc("item.power.throughput", "Max throughput: %s / %s") misc("item.power.storage0", "Stored energy: %s")
misc("item.power.throughput_mono", "Max throughput: %s") misc("item.power.throughput", "Max I/O: %s / %s")
misc("item.power.infinity", "Infinity MtJ") misc("item.power.throughput_mono", "Max I/O: %s")
misc("item.power.infinity", "∞ MtJ")
misc("item.worker.work_ticks_mono", "Work ticks: %s") misc("item.worker.work_ticks_mono", "Work ticks: %s")
misc("item.worker.work_ticks", "Work ticks: %s / %s") misc("item.worker.work_ticks", "Work ticks: %s / %s")
@ -241,11 +281,14 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("item.block.stored_battery", "Battery: %s") misc("item.block.stored_battery", "Battery: %s")
misc("item.pattern.stored", "Stored patterns: %s / %s") misc("item.pattern.stored", "Stored patterns: %s / %s")
misc("item.pattern.infinite.stored", "Stored patterns %s") misc("item.pattern.infinite.stored", "Stored patterns: %s")
misc("item.pattern.line", "%s [%s%%]") misc("item.pattern.line", "%s [%s%%]")
misc("item.pattern.research", "Researched: %s%%") misc("item.pattern.research", "Researched: %s%%")
misc("item.pattern.research.item_count", "Items: %s / %s")
misc("item.pattern.research.advance", "Progress per item: %s%%")
misc("item.matter.infinite", "Stored matter: Infinity / Infinity")
misc("item.matter.infinite", "Stored matter: ∞ / ∞")
misc("item.matter.normal", "Stored matter: %s / %s") misc("item.matter.normal", "Stored matter: %s / %s")
misc("gui.matter_task.total", "Total: %s") misc("gui.matter_task.total", "Total: %s")
@ -264,42 +307,47 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("pill.heal", "Instantly restores 4 hearts upon ingestion, provides 2 min Absorption V and 8 seconds Regeneration III.") misc("pill.heal", "Instantly restores 4 hearts upon ingestion, provides 2 min Absorption V and 8 seconds Regeneration III.")
misc("pill.heal_android", "Does nothing to androids.") misc("pill.heal_android", "Does nothing to androids.")
misc("pill.message", "Nothing happened, but you feel exhausted?.. Maybe get rest.") misc("pill.message", "Nothing happened, but you feel... exhausted?.. Maybe get rest.")
misc("pill.message_finish", "§kONE OF US ONE OF US ONE OF US ONE OF US ONE OF US") misc("pill.message_finish", "§kONE OF US ONE OF US ONE OF US")
misc("gui.power.percentage_level", "Energy level: %s%%") gui("power.percentage_level", "Energy level: %s%%")
misc("gui.level", "%s / %s") gui("level", "%s / %s")
misc("gui.power.name", "MtJ") gui("diff", "%s (%s / %s)")
gui("power.name", "MtJ")
gui("fluid.name", "B")
gui("fluid.level", "%s / %s of %s")
misc("gui.power.burn_time", "Burn time left: %s ticks") gui("empty", "Empty")
misc("gui.progress_widget", "Progress: %s%%") gui("power.burn_time", "Burn time left: %s ticks")
misc("gui.progress_widget_stuck", "The machine can not work, check configuration")
misc("gui.total_raw", "Total:") gui("progress_widget", "Progress: %s%%")
gui("progress_widget_stuck", "The machine can not work, check configuration")
misc("gui.matter.percentage_level", "Matter level: %s%%") gui("total_raw", "Total:")
misc("gui.matter.format", "Matter: %s")
misc("gui.matter.format_and_complexity", "%s / Complexity: %s")
misc("gui.matter.format_and_complexity2", "%s (%s) / Complexity: %s (%s)")
misc("gui.matter.name", "MtU")
misc("gui.filter.is_whitelist", "Is Whitelist") gui("matter.percentage_level", "Matter level: %s%%")
misc("gui.filter.match_nbt", "Match NBT") gui("matter.format", "Matter: %s")
misc("gui.filter.match_tag", "Match Tag") gui("matter.format_and_complexity", "%s / Complexity: %s")
gui("matter.format_and_complexity2", "%s (%s) / Complexity: %s (%s)")
gui("matter.name", "MtU")
misc("gui.android_research", "Research Tree") gui("filter.is_whitelist", "Is Whitelist")
gui("filter.match_nbt", "Match NBT")
gui("filter.match_tag", "Match Tag")
misc("gui.pattern.percentage_level", "Fill level: %s%%") gui("android_research", "Research Tree")
misc("gui.pattern.format", "Stored patterns: %s / %s")
misc("gui.redstone.ignored", "Redstone mode: Ignored") gui("pattern.percentage_level", "Fill level: %s%%")
misc("gui.redstone.low", "Redstone mode: Low") gui("pattern.format", "Stored patterns: %s / %s")
misc("gui.redstone.high", "Redstone mode: High")
misc("gui.redstone.ignored.description", "Redstone signal does not affect machine's function") gui("redstone.ignored", "Redstone mode: Ignored")
misc("gui.redstone.low.description", "Machine work if no redstone signal is present") gui("redstone.low", "Redstone mode: Low")
misc("gui.redstone.high.description", "Machine work only if any redstone signal is present") gui("redstone.high", "Redstone mode: High")
gui("redstone.ignored.description", "Redstone signal does not affect machine's function")
gui("redstone.low.description", "Machine work if no redstone signal is present")
gui("redstone.high.description", "Machine work only if any redstone signal is present")
misc("3d2d.gravitation_stabilizer.mass", "Singularity mass: %s") misc("3d2d.gravitation_stabilizer.mass", "Singularity mass: %s")
misc("3d2d.gravitation_stabilizer.strength", "Gravitation strength: %s") misc("3d2d.gravitation_stabilizer.strength", "Gravitation strength: %s")
@ -324,14 +372,12 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("matter_bottler.switch_mode", "Switch work mode") misc("matter_bottler.switch_mode", "Switch work mode")
misc("container.matter_panel.number_input", "Input replication task count")
misc("item.quantum_battery.creative", "Fill this to win Minecraft.") misc("item.quantum_battery.creative", "Fill this to win Minecraft.")
misc("item.quantum_battery.creative2", "See ya after millions of stars burn out.") misc("item.quantum_battery.creative2", "See ya after millions of stars burn out.")
misc("item.quantum_battery.creative_power", "Stored energy: %s / Infinity") misc("item.quantum_battery.creative_power", "Stored energy: %s / ")
misc("item.quantum_link_id", "Quantum link ID: %s") misc("item.quantum_link_id", "Quantum link ID: %s")
misc("item.quantum_description", "This item is sharing it's contents with other similar items using quantum entanglement") misc("item.quantum_description", "This item is sharing its contents with other similar items using quantum entanglement")
} }
} }
@ -342,22 +388,31 @@ private fun death(provider: MatteryLanguageProvider) {
death("otm_event_horizon", "%1\$s never crossed the event horizon") death("otm_event_horizon", "%1\$s never crossed the event horizon")
death("otm_hawking_radiation", "%1\$s discovered Hawking radiation") death("otm_hawking_radiation", "%1\$s discovered Hawking radiation")
death("otm_emp", "%1\$s electronics' fried") death("otm_emp", "%1\$s electronics' fried")
death("otm_cosmic_rays", "%1\$s electronics' got scrambled by cosmic radiation")
death("otm_android_discharge", "%1\$s ran out of power")
death("otm_become_android.player", "%1\$s lost their humanity whilst %2\$s tried to reason with them") death("otm_become_android.player", "%1\$s lost their humanity whilst %2\$s tried to reason with them")
death("otm_become_humane.player", "%1\$s gained their humanity whilst %2\$s tried to reason with them") death("otm_become_humane.player", "%1\$s gained their humanity whilst %2\$s tried to reason with them")
death("otm_event_horizon.player", "%1\$s tried to cross the event horizon whilst trying to escape %2\$s") death("otm_event_horizon.player", "%1\$s tried to cross the event horizon whilst trying to escape %2\$s")
death("otm_hawking_radiation.player", "%1\$s disintegrated whilst fighting %2\$s") death("otm_hawking_radiation.player", "%1\$s disintegrated whilst fighting %2\$s")
death("otm_emp.player", "%1\$s blew fuzes of %2\$s") death("otm_emp.player", "%2\$s blew fuzes of %1\$s")
death("otm_emp.player.item", "%1\$s blew fuzes of %2\$s using %3\$s") death("otm_emp.player.item", "%2\$s blew fuzes of %1\$s using %3\$s")
death(MRegistry.DAMAGE_EXOPACK_PROBE_ID, "%1 couldn't handle spinal surgery") death("otm_explosive_hammer", "%1\$s's fun time with hammer is over")
death("${MRegistry.DAMAGE_EXOPACK_PROBE_ID}.player", "%1 couldn't handle spinal surgery whilst fighting %2\$s") death("otm_hammer_nail", "%1\$s got nailed")
death("otm_hammer_nail" + ".player", "%1\$s got nailed by %\$2")
death("otm_hammer_nail" + ".player.item", "%1\$s got nailed by %2\$s using %3\$s")
death("otm_exopack_probe", "%1\$s couldn't handle spinal surgery")
death("otm_exopack_probe.player", "%1\$s couldn't handle spinal surgery whilst fighting %2\$s")
} }
} }
private fun blocks(provider: MatteryLanguageProvider) { private fun blocks(provider: MatteryLanguageProvider) {
with(provider.english) { with(provider.english) {
add(MBlocks.ANDROID_STATION, "Android Station") add(MBlocks.ANDROID_STATION, "Android Station")
add(MBlocks.ANDROID_CHARGER, "Wireless Charger")
add(MBlocks.ANDROID_CHARGER, "desc", "Charges nearby androids and exopacks")
add(MBlocks.BATTERY_BANK, "Battery Bank") add(MBlocks.BATTERY_BANK, "Battery Bank")
add(MBlocks.MATTER_DECOMPOSER, "Matter Decomposer") add(MBlocks.MATTER_DECOMPOSER, "Matter Decomposer")
add(MBlocks.MATTER_CAPACITOR_BANK, "Matter Capacitor Bank") add(MBlocks.MATTER_CAPACITOR_BANK, "Matter Capacitor Bank")
@ -368,7 +423,24 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.MATTER_REPLICATOR, "Matter Replicator") add(MBlocks.MATTER_REPLICATOR, "Matter Replicator")
add(MBlocks.MATTER_BOTTLER, "Matter Bottler") add(MBlocks.MATTER_BOTTLER, "Matter Bottler")
add(MBlocks.DRIVE_VIEWER, "Drive Viewer") add(MBlocks.DRIVE_VIEWER, "Drive Viewer")
add(MBlocks.BLACK_HOLE, "Local Anomalous Singular Gravitation Field") add(MBlocks.BLACK_HOLE, "Local Anomalous Spacetime Dilation Singular Point")
add(MBlocks.COBBLESTONE_GENERATOR, "Cobblestone Generator")
add(MBlocks.INFINITE_WATER_SOURCE, "Infinite Water Source")
add(MBlocks.ESSENCE_STORAGE, "Essence Storage")
add(MBlocks.ESSENCE_STORAGE, "desc", "Allows to store and retrieve experience levels")
add(MBlocks.MATTER_RECONSTRUCTOR, "Matter Reconstructor")
add(MBlocks.MATTER_RECONSTRUCTOR, "desc", "Repairs tools using matter")
add(MBlocks.DEV_CHEST, "Dev Chest")
add(MBlocks.DEV_CHEST, "desc", "Contains all items present in game")
add(MBlocks.PAINTER, "Painting Table")
add(MBlocks.MATTER_ENTANGLER, "Matter Entangler")
add(MBlocks.FLUID_TANK, "Fluid Tank")
add(MBlocks.FLUID_TANK, "named", "Fluid Tank (%s)")
add(MBlocks.ENGINE, "Ship Engine")
add(MBlocks.ENGINE, "desc", "Unfortunately, it doesn't seem to be functional anymore.")
add(MBlocks.HOLO_SIGN, "Holo Sign")
add(MBlocks.TRITANIUM_INGOT_BLOCK, "Tritanium Plating Block") add(MBlocks.TRITANIUM_INGOT_BLOCK, "Tritanium Plating Block")
@ -381,12 +453,20 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.DRIVE_RACK, "Condensation Drive Rack") add(MBlocks.DRIVE_RACK, "Condensation Drive Rack")
add(MBlocks.ITEM_MONITOR, "Item Monitor") add(MBlocks.ITEM_MONITOR, "Item Monitor")
add(MBlocks.PLATE_PRESS, "Plate Press") add(MBlocks.PLATE_PRESS, "Plate Press")
add(MBlocks.TWIN_PLATE_PRESS, "Twin Plate Press")
add(MBlocks.POWERED_FURNACE, "Electric Furnace")
add(MBlocks.POWERED_SMOKER, "Microwave Oven")
add(MBlocks.POWERED_BLAST_FURNACE, "Induction Furnace")
add(MBlocks.MATTER_RECYCLER, "Matter Recycler") add(MBlocks.MATTER_RECYCLER, "Matter Recycler")
add(MBlocks.ENERGY_SERVO, "Energy Servo") add(MBlocks.ENERGY_SERVO, "Energy Servo")
add(MBlocks.ENERGY_SERVO, "desc", "Charges, Discharges or Exchanges energy of items") add(MBlocks.ENERGY_SERVO, "desc", "Charges, Discharges or Exchanges energy of items")
add(MBlocks.CARBON_FIBRE_BLOCK, "Carbon fibre Block") add(MBlocks.CARBON_FIBRE_BLOCK, "Carbon Fibre Block")
add(MBlocks.METAL_JUNK, "Metal Junk Block")
add(MBlocks.METAL_JUNK, "desc", "Useless junk, or is it?")
add(MBlocks.METAL_MESH, "Metal Mesh")
add(MBlocks.TRITANIUM_STRIPED_BLOCK, "Tritanium Striped Block") add(MBlocks.TRITANIUM_STRIPED_BLOCK, "Tritanium Striped Block")
add(MBlocks.TRITANIUM_STRIPED_STAIRS, "Tritanium Striped Stairs") add(MBlocks.TRITANIUM_STRIPED_STAIRS, "Tritanium Striped Stairs")
@ -402,16 +482,14 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.STORAGE_IMPORTER, "Storage Importer") add(MBlocks.STORAGE_IMPORTER, "Storage Importer")
add(MBlocks.STORAGE_EXPORTER, "Storage Exporter") add(MBlocks.STORAGE_EXPORTER, "Storage Exporter")
add(MBlocks.GRAVITATION_STABILIZER, "Gravitation Stabilizer") add(MBlocks.GRAVITATION_STABILIZER, "Spacetime Normalizer")
add(MBlocks.GRAVITATION_STABILIZER_LENS, "Gravitation Stabilizer Lens") add(MBlocks.GRAVITATION_STABILIZER_LENS, "Spacetime Normalizer Lens")
add(MBlocks.GRAVITATION_STABILIZER, "desc", "Reduces gravitation effects of singularities") add(MBlocks.GRAVITATION_STABILIZER, "desc", "Reduces spacetime distortion effects of singularities")
add(MBlocks.GRAVITATION_STABILIZER, "desc2", "Requires no power to operate") add(MBlocks.GRAVITATION_STABILIZER, "desc2", "Keep in mind the effect of multiple stabilizers produce exponentially increasing result")
add(MBlocks.GRAVITATION_STABILIZER, "desc3", "Keep in mind the effect of multiple stabilizers produce exponentially increasing result") add(MBlocks.GRAVITATION_STABILIZER, "desc3", "Too weak gravitation field will cause singularity to 'evaporate' really fast!")
add(MBlocks.GRAVITATION_STABILIZER, "desc4", "Too weak gravitation field will cause singularity to melt and evaporate away very fast")
add(MBlocks.PHANTOM_ATTRACTOR, "Phantom Attractor") add(MBlocks.PHANTOM_ATTRACTOR, "Phantom Attractor")
add(MBlocks.PHANTOM_ATTRACTOR, "desc", "Attracts Phantoms when it is night time") add(MBlocks.PHANTOM_ATTRACTOR, "desc", "Attracts Phantoms when it is night time")
add(MBlocks.PHANTOM_ATTRACTOR, "desc2", "Requires no power to operate")
add(MBlocks.LABORATORY_LAMP, "Laboratory Lamp") add(MBlocks.LABORATORY_LAMP, "Laboratory Lamp")
add(MBlocks.LABORATORY_LAMP, "description", "Provides directional light with redstone switch") add(MBlocks.LABORATORY_LAMP, "description", "Provides directional light with redstone switch")
@ -426,37 +504,62 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "Tritanium Trapdoor") add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "Tritanium Trapdoor")
add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "description0", "High blast resistance door with redstone latch...") add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "description0", "High blast resistance door with redstone latch...")
add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "description1", "...feeling safe now?") add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "description1", "...feeling safe now?")
add(MBlocks.TRITANIUM_BARS, "Tritanium Bars")
for (block in MBlocks.TRITANIUM_ANVIL)
add(block, "Tritanium Anvil")
} }
} }
private fun items(provider: MatteryLanguageProvider) { private fun items(provider: MatteryLanguageProvider) {
with(provider.english) { with(provider.english) {
add(MItems.PROCEDURAL_BATTERY, "Mythical Battery")
add(MItems.PROCEDURAL_BATTERY, "desc", "These batteries are found in dungeons with randomized stats")
add(MItems.EXPLOSIVE_HAMMER, "Explosive Hammer")
add(MItems.EXPLOSIVE_HAMMER, "desc", "For those who feel bored")
add(MItems.EXPLOSIVE_HAMMER, "primed", "Primed!")
add(MItems.EXPLOSIVE_HAMMER, "not_primed0", "Not primed")
add(MItems.EXPLOSIVE_HAMMER, "not_primed1", "Prime at crafting table with little of gunpowder and nugget payload")
add(MItems.EXOPACK_PROBE, "Exopack Probe") add(MItems.EXOPACK_PROBE, "Exopack Probe")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Creative Exopack Inventory Upgrade") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Creative Exopack Inventory Upgrade")
add(MItems.ExopackUpgrades.CRAFTING_UPGRADE, "Exopack Crafting Upgrade") add(MItems.ExopackUpgrades.CRAFTING_UPGRADE, "Exopack Crafting Upgrade")
add(MItems.ExopackUpgrades.SMELTING_UPGRADE, "Exopack Smelting Module")
add(MItems.ExopackUpgrades.ENDER_UPGRADE, "Exopack Ender Access Module")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "Superdense Packing Upgrade") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "Superdense Packing Upgrade")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "description", "Utilizes similar principle that exhibit Nether Stars") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "description", "Utilizes similar principle that exhibit Nether Stars")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "Ender Link Pocket Dimension Upgrade") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "Ender Link Pocket Dimension Upgrade")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "description", "Allows to store items in portable pocket dimension") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "description", "Allows to store items in portable pocket dimension. Also grants access to Ender Chest contents.")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "Indescribable Exopack Inventory Upgrade") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "Indescribable Exopack Inventory Upgrade")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "description", "They normally generate in dungeons with appropriate NBT tag attached") add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "description", "They normally generate in dungeons with appropriate NBT tag attached")
add(MItems.NUTRIENT_PASTE, "Nutrient paste") add(MItems.ESSENCE_CAPSULE, "Essence Capsule")
add(MItems.ESSENCE_DRIVE, "Essence Memory Holotape")
add(MItems.ESSENCE_SERVO, "Essence Servo")
add(MItems.ESSENCE_SERVO, "desc", "Allows to 'pump' essence involving fleshy humanoids")
add(MItems.ESSENCE_SERVO, "desc2", "Can be used standalone, or as tool inside Essence Servo")
add(MItems.NUTRIENT_PASTE, "Nutrient Paste")
add(MItems.FLUID_CAPSULE, "Fluid Capsule")
add(MItems.FLUID_CAPSULE, "named", "Fluid Capsule (%s)")
add(MItems.BLACK_HOLE_SCANNER, "Singularity Scanner") add(MItems.BLACK_HOLE_SCANNER, "Singularity Scanner")
add(MItems.BLACK_HOLE_SCANNER, "desc", "Scans singularities for their properties") add(MItems.BLACK_HOLE_SCANNER, "desc", "Scans singularities for their properties")
add(MItems.BLACK_HOLE_SCANNER, "desc2", "Hold in hand to determine mass of singularities") add(MItems.BLACK_HOLE_SCANNER, "desc2", "Hold in hand to determine mass of singularities")
add(MItems.GRAVITATION_FIELD_LIMITER, "Gravitation Field Limiter") add(MItems.GRAVITATION_FIELD_LIMITER, "Spacetime Distortion Limiter")
add(MItems.GRAVITATION_FIELD_SENSOR, "Gravitation Field Sensor") add(MItems.GRAVITATION_FIELD_SENSOR, "Spacetime Sensor")
add(MItems.PORTABLE_GRAVITATION_STABILIZER, "Portable Gravitation Stabilizer") add(MItems.PORTABLE_GRAVITATION_STABILIZER, "Portable Spacetime Normalizer")
add(MItems.BATTERY_CRUDE, "Crude Battery") add(MItems.BATTERY_CRUDE, "Crude Battery")
add(MItems.BATTERY_BASIC, "Basic Battery") add(MItems.BATTERY_BASIC, "Basic Battery")
add(MItems.BATTERY_NORMAL, "Ordinary Battery") add(MItems.BATTERY_NORMAL, "Battery")
add(MItems.BATTERY_DENSE, "Dense Battery") add(MItems.BATTERY_DENSE, "Dense Battery")
add(MItems.BATTERY_CAPACITOR, "Capacitor Battery") add(MItems.BATTERY_CAPACITOR, "Capacitor Battery")
add(MItems.BATTERY_CREATIVE, "Creative Battery") add(MItems.BATTERY_CREATIVE, "Creative Battery")
@ -470,14 +573,22 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.TRITANIUM_SHOVEL, "Tritanium Shovel") add(MItems.TRITANIUM_SHOVEL, "Tritanium Shovel")
add(MItems.TRITANIUM_AXE, "Tritanium Axe") add(MItems.TRITANIUM_AXE, "Tritanium Axe")
add(MItems.TRITANIUM_HOE, "Tritanium Hoe") add(MItems.TRITANIUM_HOE, "Tritanium Hoe")
add(MItems.TRITANIUM_SHEARS, "Tritanium Shears")
add(MItems.TRITANIUM_SHIELD, "Tritanium Shield")
add(MItems.TRITANIUM_HELMET, "Tritanium Helmet") add(MItems.TRITANIUM_HELMET, "Tritanium Helmet")
add(MItems.TRITANIUM_CHESTPLATE, "Tritanium Chestplate") add(MItems.TRITANIUM_CHESTPLATE, "Tritanium Chestplate")
add(MItems.TRITANIUM_PANTS, "Tritanium Leggings") add(MItems.TRITANIUM_PANTS, "Tritanium Leggings")
add(MItems.TRITANIUM_BOOTS, "Tritanium Boots") add(MItems.TRITANIUM_BOOTS, "Tritanium Boots")
add(MItems.SIMPLE_TRITANIUM_HELMET, "Simple Tritanium Helmet")
add(MItems.SIMPLE_TRITANIUM_CHESTPLATE, "Simple Tritanium Chestplate")
add(MItems.SIMPLE_TRITANIUM_PANTS, "Simple Tritanium Leggings")
add(MItems.SIMPLE_TRITANIUM_BOOTS, "Simple Tritanium Boots")
add(MItems.TRITANIUM_DUST, "Tritanium Dust") add(MItems.TRITANIUM_DUST, "Tritanium Dust")
add(MItems.TRITANIUM_INGOT, "Tritanium Ingot") add(MItems.TRITANIUM_INGOT, "Tritanium Ingot")
add(MItems.TRITANIUM_NUGGET, "Tritanium Nugget")
add(MItems.MATTER_IO_PORT, "Matter IO Port") add(MItems.MATTER_IO_PORT, "Matter IO Port")
add(MItems.MATTER_TRANSFORM_MATRIX, "Matter Transformation Matrix") add(MItems.MATTER_TRANSFORM_MATRIX, "Matter Transformation Matrix")
add(MItems.ENERGY_BUS, "Energy Bus") add(MItems.ENERGY_BUS, "Energy Bus")
@ -495,14 +606,18 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.ADVANCED_CONTROL_CIRCUIT, "Advanced Control Circuit") add(MItems.ADVANCED_CONTROL_CIRCUIT, "Advanced Control Circuit")
add(MItems.QUANTUM_TRANSCEIVER, "Quantum Transceiver") add(MItems.QUANTUM_TRANSCEIVER, "Quantum Transceiver")
add(MItems.ELECTROMAGNET, "Electromagnet") add(MItems.ELECTROMAGNET, "Electromagnet")
add(MItems.ELECTROMOTOR, "Electromotor")
add(MItems.MIRROR_COMPOUND, "Mirror Compound") add(MItems.MIRROR_COMPOUND, "Mirror Compound")
add(MItems.MIRROR, "Mirror") add(MItems.MIRROR, "Mirror")
add(MItems.MIRROR, "description", "You can clearly see your reflection in this thing") add(MItems.MIRROR, "description", "I can clearly see my own reflection in this mirror")
add(MItems.REINFORCED_TRITANIUM_PLATE, "Reinforced Tritanium Plate")
add(MItems.REINFORCED_TRITANIUM_PLATE, "description", "An armor plate, reinforced to withstand great kinetic forces")
add(MItems.CARBON_MESH, "Carbon Mesh")
add(MItems.GRAVITATIONAL_DISRUPTOR, "Gravitational Disruptor") add(MItems.GRAVITATIONAL_DISRUPTOR, "Spacetime Equalizer")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description", "Once within close proximity of supermassive body, suppresses any gravity in it's radius") add(MItems.GRAVITATIONAL_DISRUPTOR, "description", "Once within close proximity of massive spacetime dilation anomaly, equalizes spacetime in it's radius")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description2", "Allows collapse of black holes") add(MItems.GRAVITATIONAL_DISRUPTOR, "description2", "Allows collapse of singularities")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description3", "Doesn't destroy any of mass singularity had acquired, which result in violent explosion of matter!") add(MItems.GRAVITATIONAL_DISRUPTOR, "description3", "Doesn't destroy any of mass singularity had acquired, which result in violent explosion of matter!")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description4", "The explosion %s be contained by %s. Do not even attempt to contain it.") add(MItems.GRAVITATIONAL_DISRUPTOR, "description4", "The explosion %s be contained by %s. Do not even attempt to contain it.")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description4_clarification", "can not") add(MItems.GRAVITATIONAL_DISRUPTOR, "description4_clarification", "can not")
@ -543,6 +658,49 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.ZPM_BATTERY, "Zero Point Module") add(MItems.ZPM_BATTERY, "Zero Point Module")
add(MItems.ZPM_BATTERY, "description", "Can be found in hands of those who travel between dimensions, if they ever reached different reality of origin of these constructs...") add(MItems.ZPM_BATTERY, "description", "Can be found in hands of those who travel between dimensions, if they ever reached different reality of origin of these constructs...")
add(MItems.MachineUpgrades.Basic.BLANK, "Basic Upgrade Template")
add(MItems.MachineUpgrades.Basic.SPEED, "Basic Speed Upgrade")
add(MItems.MachineUpgrades.Basic.ENERGY_CONSUMPTION, "Basic Energy Consumption Upgrade")
add(MItems.MachineUpgrades.Basic.FAILSAFE, "Basic Failsafe Upgrade")
add(MItems.MachineUpgrades.Basic.ENERGY_STORAGE, "Basic Energy Storage Upgrade")
add(MItems.MachineUpgrades.Basic.MATTER_STORAGE, "Basic Matter Storage Upgrade")
add(MItems.MachineUpgrades.Basic.PROCESSING_ITEMS, "Basic Item Processing Upgrade")
add(MItems.MachineUpgrades.Normal.BLANK, "Upgrade Template")
add(MItems.MachineUpgrades.Normal.SPEED, "Speed Upgrade")
add(MItems.MachineUpgrades.Normal.ENERGY_CONSUMPTION, "Energy Consumption Upgrade")
add(MItems.MachineUpgrades.Normal.FAILSAFE, "Failsafe Upgrade")
add(MItems.MachineUpgrades.Normal.ENERGY_STORAGE, "Energy Storage Upgrade")
add(MItems.MachineUpgrades.Normal.MATTER_STORAGE, "Matter Storage Upgrade")
add(MItems.MachineUpgrades.Normal.PROCESSING_ITEMS, "Item Processing Upgrade")
add(MItems.MachineUpgrades.Advanced.BLANK, "Advanced Upgrade Template")
add(MItems.MachineUpgrades.Advanced.SPEED, "Advanced Speed Upgrade")
add(MItems.MachineUpgrades.Advanced.ENERGY_CONSUMPTION, "Advanced Energy Consumption Upgrade")
add(MItems.MachineUpgrades.Advanced.FAILSAFE, "Advanced Failsafe Upgrade")
add(MItems.MachineUpgrades.Advanced.ENERGY_STORAGE, "Advanced Energy Storage Upgrade")
add(MItems.MachineUpgrades.Advanced.MATTER_STORAGE, "Advanced Matter Storage Upgrade")
add(MItems.MachineUpgrades.Advanced.PROCESSING_ITEMS, "Advanced Item Processing Upgrade")
add(MItems.MachineUpgrades.Creative.SPEED, "Creative Speed Upgrade")
add(MItems.MachineUpgrades.Creative.ENERGY_CONSUMPTION, "Creative Energy Consumption Upgrade")
add(MItems.MachineUpgrades.Creative.ENERGY_STORAGE, "Creative Energy Storage Upgrade")
add(MItems.MachineUpgrades.Creative.ENERGY_STORAGE_FLAT, "Creative Energy Storage Upgrade (Flat)")
add(MItems.MachineUpgrades.Creative.ENERGY_STORAGE_FLAT_SMALL, "Creative Energy Storage Upgrade (Flat Small)")
add(MItems.MachineUpgrades.Creative.MATTER_STORAGE, "Creative Matter Storage Upgrade")
add(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT, "Creative Matter Storage Upgrade (Flat)")
add(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT_SMALL, "Creative Matter Storage Upgrade (Flat Small)")
add(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT, "Creative Energy Throughput Upgrade")
add(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT_FLAT, "Creative Energy Throughput Upgrade (Flat)")
add(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT_FLAT_SMALL, "Creative Energy Throughput Upgrade (Flat Small)")
add(MItems.MachineUpgrades.Creative.FAILSAFE, "Creative Failsafe Upgrade")
add(MItems.MachineUpgrades.Creative.FAILURE, "Creative Failure Upgrade")
add(MItems.MachineUpgrades.Creative.PROCESSING_ITEMS, "Creative Item Processing Upgrade")
add(MItems.CHEST_UPGRADER, "Crate-r")
add(MItems.CHEST_UPGRADER, "desc", "Replaces placed chests and barrels with cargo crates while keeping storage contents")
add(MItems.CHEST_UPGRADER, "desc2", "Hold desired crates in the opposite hand")
} }
} }
@ -576,8 +734,8 @@ private fun androidFeatures(provider: MatteryLanguageProvider) {
add(AndroidFeatures.NIGHT_VISION, "Night Vision") add(AndroidFeatures.NIGHT_VISION, "Night Vision")
add(AndroidFeatures.NANOBOTS_ARMOR, "Nanobots Armor") add(AndroidFeatures.NANOBOTS_ARMOR, "Nanobots Armor")
add(AndroidFeatures.ITEM_MAGNET, "Item Magnet") add(AndroidFeatures.ITEM_MAGNET, "Item Magnet")
add(AndroidFeatures.SWIM_BOOSTERS, "Swim Boosters")
add(AndroidFeatures.STEP_ASSIST, "Step Assist") add(AndroidFeatures.STEP_ASSIST, "Step Assist")
add(AndroidFeatures.PHANTOM_ATTRACTOR, "Phantom Attractor")
add(AndroidFeatures.JUMP_BOOST, "Jump Boost") add(AndroidFeatures.JUMP_BOOST, "Jump Boost")
add(AndroidFeatures.ENDER_TELEPORTER, "Ender Teleporter") add(AndroidFeatures.ENDER_TELEPORTER, "Ender Teleporter")
} }
@ -585,6 +743,35 @@ private fun androidFeatures(provider: MatteryLanguageProvider) {
private fun gui(provider: MatteryLanguageProvider) { private fun gui(provider: MatteryLanguageProvider) {
with(provider.english) { with(provider.english) {
gui("quicksearch", "Quick search...")
gui("painter.is_bulk", "Bulk painting")
gui("painter.is_bulk.desc", "Input slot will be automatically refilled from your inventory")
gui("painter.is_bulk.desc2", "Quick moving result will paint as many items as possible from your inventory")
gui("energy_required", "Energy required: %s")
gui("insert_priority", "Insert priority")
gui("extract_priority", "Extract priority")
gui("increase", "Increase")
gui("decrease", "Decrease")
gui("color_picker", "Color Picker")
gui("color.short.red", "R")
gui("color.short.green", "G")
gui("color.short.blue", "B")
gui("color.short.hue", "H")
gui("color.short.saturation", "S")
gui("color.short.value", "V")
gui("color.full.red", "Red")
gui("color.full.green", "Green")
gui("color.full.blue", "Blue")
gui("color.full.hue", "Hue")
gui("color.full.saturation", "Saturation")
gui("color.full.value", "Value")
gui("item_monitor.refill_source.desc", "Controls from where to take items for slot auto refill") gui("item_monitor.refill_source.desc", "Controls from where to take items for slot auto refill")
gui("item_monitor.refill_source.system", "System only. Crafting grid will be auto refilled only from storage system. This is the behavior you see in AE2 and Refined Storage") gui("item_monitor.refill_source.system", "System only. Crafting grid will be auto refilled only from storage system. This is the behavior you see in AE2 and Refined Storage")
gui("item_monitor.refill_source.inventory", "Inventory only. Crafting grid will be auto refilled only from player's inventory") gui("item_monitor.refill_source.inventory", "Inventory only. Crafting grid will be auto refilled only from player's inventory")
@ -603,6 +790,130 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("item_monitor.amount.full", "Stack of ingredients. Craft until reaching stack size of one of ingredients. If at least one of inputs is not stackable then 'one stack' mode is used instead") gui("item_monitor.amount.full", "Stack of ingredients. Craft until reaching stack size of one of ingredients. If at least one of inputs is not stackable then 'one stack' mode is used instead")
gui("stored_amount", "Exact amount stored: %s") gui("stored_amount", "Exact amount stored: %s")
gui("sides.item_config", "Item Configuration")
gui("sides.energy_config", "Energy Configuration")
gui("sides.fluid_config", "Fluid Configuration")
gui("sides.pull_help", "Hold Shift to cycle pull mode")
gui("sides.push_help", "Hold Ctrl to cycle push mode")
gui("sides.top", "Top")
gui("sides.bottom", "Bottom")
gui("sides.front", "Front")
gui("sides.back", "Back")
gui("sides.left", "Left")
gui("sides.right", "Right")
gui("side_mode.disabled", "Disabled")
gui("side_mode.input", "Input only")
gui("side_mode.output", "Output only")
gui("side_mode.input_output", "Input/Output")
gui("side_mode.battery", "Battery")
gui("side_mode.pull", "Pull")
gui("side_mode.push", "Push")
gui("upgrades", "Upgrades")
gui("upgrades.current", "Active upgrades:")
gui("upgrade.speed", "Operation speed: %s%%")
gui("upgrade.processing_items", "Items processed per cycle: +%s")
gui("upgrade.energy_storage_flat", "Energy capacity: +%s")
gui("upgrade.matter_storage_flat", "Matter capacity: +%s")
gui("upgrade.energy_storage", "Energy capacity: +%s%%")
gui("upgrade.matter_storage", "Matter capacity: +%s%%")
gui("upgrade.energy_consumed", "Energy consumption: %s%%")
gui("upgrade.energy_throughput_flat", "Energy throughput: +%s")
gui("upgrade.energy_throughput", "Energy throughput: +%s%%")
gui("upgrade.failsafe", "Failure chance: %s%%")
gui("upgrade_type.list", "Upgrade classification:")
gui("upgrade_type.allowed", "Allowed upgrades:")
gui("upgrade_type.allowed_none", "No possible upgrades at the moment.")
gui("upgrade_type.speed", "Speed")
gui("upgrade_type.processing", "Processing")
gui("upgrade_type.matter_storage", "Matter Storage")
gui("upgrade_type.energy_storage", "Energy Storage")
gui("upgrade_type.energy_consumption", "Energy Consumption")
gui("upgrade_type.energy_throughput", "Energy Throughput")
gui("upgrade_type.failsafe", "Failsafe")
gui("balance_inputs", "Balance input slots")
gui("sorting.sort_now", "Sort")
gui("sorting.sort_settings", "Right click to show settings")
gui("sorting.default", "Default sorting")
gui("sorting.name", "Sort by name")
gui("sorting.id", "Sort by ID")
gui("sorting.modid", "Sort by Namespace (mod) ID")
gui("sorting.count", "Sort by quantity")
gui("sorting.ascending", "Ascending")
gui("sorting.descending", "Descending")
gui("sorting.matter_value", "Matter value")
gui("sorting.matter_complexity", "Replication complexity")
gui("matter_panel.increase_by", "+%s")
gui("matter_panel.decrease_by", "-%s")
gui("matter_panel.send", "Send")
gui("matter_panel.close", "Close")
gui("matter_panel.cancel_task", "Cancel task")
gui("matter_panel.cancel", "Cancel")
gui("matter_panel.label", "Replication request")
gui("matter_panel.task", "Ongoing replication task")
gui("matter_panel.task_line", "%s: %s | %s / %s")
gui("matter_panel.is_providing_tasks", "Tasks are dispatched to replicators")
gui("matter_panel.not_providing_tasks", "Tasks are NOT dispatched to replicators")
gui("matter_panel.cancel_all", "Cancel all tasks")
gui("matter_panel.cancel_all.desc", "Do you really want to cancel all replication tasks?")
gui("matter_panel.tasks", "Tasks")
gui("matter_panel.patterns", "Patterns")
gui("matter_panel.number_input", "Input replication task count")
gui("matter_panel.matter_stored", "Matter stored: %s")
gui("matter_panel.matter_required", "Matter required: %s")
gui("matter_panel.complexity", "Total complexity: %s")
gui("experience", "%s experience points")
gui("experience_levels", "%s experience levels")
gui("experience.store", "Store %s experience levels")
gui("experience.store_all", "Store all experience levels")
gui("experience.dispense", "Dispense %s experience levels")
gui("experience.dispense_all", "Dispense all experience levels")
gui("experience.set_exact", "Set your experience level to %s")
gui("essence_capsule", "(Almost) Everything you ever knew is within")
gui("essence_capsule2", "This item can be recycled at Essence Servo")
gui("essence_capsule3", "Use to break free most of stored knowledge")
gui("essence_capsule.digital", "Use to scan memories stored within")
gui("slot_filter.filtered", "This slot is filtered for automation")
gui("slot_filter.forbidden", "This slot is forbidden for automation mechanisms")
gui("slot_filter.hint", "To remove slot filter press Ctrl + LMB")
gui("tooltip.enum.active", "> %s")
gui("debug.tags.help", "Hold Shift to display tags")
gui("debug.tags.item.title", "Item tags:")
gui("debug.tags.block.title", "Block tags:")
gui("debug.tags.tag.entry", " - %s")
}
}
private fun jade(provider: MatteryLanguageProvider) {
with(provider.english) {
jadeloc("matter_storage", "Matter Storage")
jadeloc("mattery_energy", "Energy Storage")
jadeloc("mattery_worker", "Machine Job Progress")
jadeloc("matter_bottler", "Matter Bottler Mode")
jadeloc("matter_reconstructor", "Matter Reconstructor Progress")
jade("mode", "Mode: %s")
jade("matter_bottler.mode.fill", "Filling")
jade("matter_bottler.mode.drain", "Emptying")
} }
} }
@ -620,6 +931,8 @@ fun AddEnglishLanguage(provider: MatteryLanguageProvider) {
research(provider) research(provider)
gui(provider) gui(provider)
jade(provider)
with(provider.english) { with(provider.english) {
add("itemGroup.otm", "Overdrive That Matters") add("itemGroup.otm", "Overdrive That Matters")
add("itemGroup.otm_decorative", "Overdrive That Matters Decorative") add("itemGroup.otm_decorative", "Overdrive That Matters Decorative")

View File

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap import com.google.common.collect.ImmutableMap
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import net.minecraft.data.DataGenerator import net.minecraft.data.DataGenerator
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.TranslatableContents import net.minecraft.network.chat.contents.TranslatableContents
import net.minecraft.sounds.SoundEvent import net.minecraft.sounds.SoundEvent
@ -17,7 +18,10 @@ import net.minecraft.world.level.block.Block
import net.minecraftforge.common.data.LanguageProvider import net.minecraftforge.common.data.LanguageProvider
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidFeatureType import ru.dbotthepony.mc.otm.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchType import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock
private fun researchString(key: AndroidResearchType): String { private fun researchString(key: AndroidResearchType): String {
@ -35,7 +39,7 @@ private fun researchString(key: AndroidResearchType): String {
} }
class MatteryLanguageProvider(private val gen: DataGenerator) { class MatteryLanguageProvider(private val gen: DataGenerator) {
private inner class Slave(language: String) : LanguageProvider(gen, OverdriveThatMatters.MOD_ID, language) { private inner class Slave(language: String) : LanguageProvider(gen.packOutput, OverdriveThatMatters.MOD_ID, language) {
override fun addTranslations() {} override fun addTranslations() {}
} }
@ -47,6 +51,30 @@ class MatteryLanguageProvider(private val gen: DataGenerator) {
} }
} }
inner class MultiBuilder(path: String) {
val path = "$path."
constructor(vararg path: String) : this(path.joinToString("."))
constructor(path: Collection<String>) : this(path.joinToString("."))
inner class Path(path: String) {
val fullPath = this@MultiBuilder.path + path
fun english(value: String) = english.add(fullPath, value)
fun russian(value: String) = russian.add(fullPath, value)
}
inline fun add(key: String, configurator: Path.() -> Unit): Component {
return TranslatableComponent(Path(key).also(configurator).fullPath)
}
inline fun add(key: String, english: String, configurator: Path.() -> Unit = {}): Component {
return add(key) {
english(english)
configurator.invoke(this)
}
}
}
@Suppress("unused") @Suppress("unused")
inner class Builder(language: String) { inner class Builder(language: String) {
val slave: LanguageProvider by lazy { slaves.computeIfAbsent(language, ::Slave) } val slave: LanguageProvider by lazy { slaves.computeIfAbsent(language, ::Slave) }
@ -77,6 +105,9 @@ class MatteryLanguageProvider(private val gen: DataGenerator) {
fun sound(key: String, value: String) = slave.add("otm.sound.$key", value) fun sound(key: String, value: String) = slave.add("otm.sound.$key", value)
fun sound(key: SoundEvent, value: String) = slave.add("otm.sound.${key.location.path}", value) fun sound(key: SoundEvent, value: String) = slave.add("otm.sound.${key.location.path}", value)
fun jade(key: String, value: String) = slave.add("otm.jade.$key", value)
fun jadeloc(key: String, value: String) = slave.add("config.jade.plugin_${DataGen.MOD_ID}.$key", value)
inner class Prepended(path: String) { inner class Prepended(path: String) {
val path = "$path." val path = "$path."
constructor(vararg path: String) : this(path.joinToString(".")) constructor(vararg path: String) : this(path.joinToString("."))
@ -382,8 +413,57 @@ class MatteryLanguageProvider(private val gen: DataGenerator) {
"Black", "Black",
) )
val russianColors = Colors("ru_ru",
"Белый",
"Оранжевый",
"Маджентовый",
"Светло Синий",
"Жёлтый",
"Лаймовый",
"Розовый",
"Серый",
"Светло Серый",
"Циановый",
"Пурпурный",
"Синий",
"Коричневый",
"Зелёный",
"Красный",
"Чёрный",
)
val english by lazy { Builder("en_us") } val english by lazy { Builder("en_us") }
val russian by lazy { Builder("ru_ru") } val russian by lazy { Builder("ru_ru") }
inner class Single(val key: String) {
fun english(value: String) = english.add(key, value)
fun russian(value: String) = russian.add(key, value)
}
inline fun add(key: String, configurator: Single.() -> Unit) = Single(key).also(configurator)
fun add(key: AndroidResearchType, configurator: Single.() -> Unit) = Single(researchString(key)).also(configurator)
inline fun add(key: String, english: String, configurator: Single.() -> Unit = {}) = add(key) { english(english); configurator.invoke(this) }
fun add(key: AndroidResearchType, english: String, configurator: Single.() -> Unit = {}) = add(key) { english(english); configurator.invoke(this) }
fun add(key: AndroidResearchType, suffix: String, english: String, configurator: Single.() -> Unit = {}) = add(researchString(key) + ".$suffix") { english(english); configurator.invoke(this) }
inline fun death(key: String, configurator: Single.() -> Unit) = Single("death.attack.$key").also(configurator)
inline fun death(key: String, english: String, configurator: Single.() -> Unit = {}) = death(key) { english(english); configurator.invoke(this) }
inline fun research(key: String, configurator: Single.() -> Unit) = Single("android_research.overdrive_that_matters.$key").also(configurator)
inline fun research(key: String, english: String, configurator: Single.() -> Unit = {}) = research(key) { english(english); configurator.invoke(this) }
inline fun research(key: String, suffix: String, english: String, configurator: Single.() -> Unit = {}) = research("$key.$suffix") { english(english); configurator.invoke(this) }
inline fun misc(key: String, configurator: Single.() -> Unit) = Single("otm.$key").also(configurator)
inline fun misc(key: String, english: String, configurator: Single.() -> Unit = {}) = misc(key) { english(english); configurator.invoke(this) }
inline fun gui(key: String, configurator: Single.() -> Unit) = Single("otm.gui.$key").also(configurator)
inline fun gui(key: String, english: String, configurator: Single.() -> Unit = {}) = gui(key) { english(english); configurator.invoke(this) }
inline fun sound(key: String, configurator: Single.() -> Unit) = Single("otm.sound.$key").also(configurator)
inline fun sound(key: String, english: String, configurator: Single.() -> Unit = {}) = sound(key) { english(english); configurator.invoke(this) }
inline fun sound(key: SoundEvent, configurator: Single.() -> Unit) = Single("otm.sound.${key.location.path}").also(configurator)
inline fun sound(key: SoundEvent, english: String, configurator: Single.() -> Unit = {}) = sound(key) { english(english); configurator.invoke(this) }
fun getProvider(language: String): LanguageProvider = slaves.computeIfAbsent(language, ::Slave) fun getProvider(language: String): LanguageProvider = slaves.computeIfAbsent(language, ::Slave)
} }

View File

@ -0,0 +1,928 @@
package ru.dbotthepony.mc.otm.datagen.lang
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MEntityTypes
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.registry.MSoundEvents
private const val HIGH_BLAST_RESISTANCE = "Высокая взрывоустойчивость"
private const val HIGH_BLAST_RESISTANCE_DOOR = "Взрывоустойчивая дверь с засовом красного камня..."
private const val FEELING_SAFE_NOW = "...ощущаете ли вы себя теперь в безопасности?"
private fun decoratives(provider: MatteryLanguageProvider) {
with(provider.russianColors) {
add(MRegistry.VENT, "%s Вентиляция")
add(MRegistry.VENT_ALTERNATIVE, "%s Альтернативная Вентиляция")
add(MRegistry.TRITANIUM_BLOCK, "%s тритановый блок")
add(MRegistry.TRITANIUM_STAIRS, "%s Тритановые ступеньки")
add(MRegistry.TRITANIUM_SLAB, "%s Тритановая плита")
add(MRegistry.TRITANIUM_WALL, "%s тритановая ограда")
add(MRegistry.FLOOR_TILES, "%s керамическая плитка")
add(MRegistry.FLOOR_TILES_STAIRS, "%s ступеньки из керамической плитки")
add(MRegistry.FLOOR_TILES_SLAB, "%s плита из керамической плитки")
add(MRegistry.UNREFINED_FLOOR_TILES, "Необработанная %s кирамическая Плитка")
add(MRegistry.INDUSTRIAL_GLASS, "%s окрашенное промышленное стекло")
add(MRegistry.INDUSTRIAL_GLASS_PANE, "%s окрашенная промышленная стеклянная панель")
add(MRegistry.CARGO_CRATES, "%s грузовой ящик")
add(MRegistry.DECORATIVE_CRATE, "%s блок контейнера")
}
with (provider.russian) {
for ((color, name) in provider.russianColors.dyeClassMapped) {
add(MItems.CARGO_CRATE_MINECARTS[color]!!, "Вагонетка с $name грузовым ящиком")
add(MEntityTypes.CARGO_CRATE_MINECARTS[color]!!, "Вагонетка с $name грузовым ящиком")
add(MRegistry.TRITANIUM_PRESSURE_PLATE.getBlock(color), "$name тритановая нажимная пластина")
add(MRegistry.TRITANIUM_PRESSURE_PLATE.getBlock(color), "description0", "Активируется только при наступлении игрока на неё")
add(MRegistry.TRITANIUM_PRESSURE_PLATE.getBlock(color), "description1", HIGH_BLAST_RESISTANCE)
add(MBlocks.TRITANIUM_DOOR[color]!!, "$name тритановая дверь")
add(MBlocks.TRITANIUM_DOOR[color]!!, "description0", HIGH_BLAST_RESISTANCE_DOOR)
add(MBlocks.TRITANIUM_DOOR[color]!!, "description1", FEELING_SAFE_NOW)
add(MBlocks.TRITANIUM_DOOR[color]!!, "description2", "Данный вариант выкрашен в $name")
add(MBlocks.TRITANIUM_TRAPDOOR[color]!!, "$name тритановый люк")
add(MBlocks.TRITANIUM_TRAPDOOR[color]!!, "description0", HIGH_BLAST_RESISTANCE_DOOR)
add(MBlocks.TRITANIUM_TRAPDOOR[color]!!, "description1", FEELING_SAFE_NOW)
add(MBlocks.TRITANIUM_TRAPDOOR[color]!!, "description2", "Данный вариант выкрашен в $name")
}
add(MRegistry.TRITANIUM_PRESSURE_PLATE.block, "Тритановая нажимная пластина")
add(MRegistry.TRITANIUM_PRESSURE_PLATE.block, "description0", "Активируется только при наступлении игрока на неё")
add(MRegistry.TRITANIUM_PRESSURE_PLATE.block, "description1", HIGH_BLAST_RESISTANCE)
}
with(provider.russian) {
add(MItems.CARGO_CRATE_MINECARTS[null]!!, "Вагонетка с грузовым ящиком")
add(MEntityTypes.CARGO_CRATE_MINECARTS[null]!!, "Вагонетка с грузовым ящиком")
add(MRegistry.CARGO_CRATES.block, "Грузовой ящик")
add(MRegistry.TRITANIUM_BLOCK.block, "Тритановый блок")
add(MRegistry.TRITANIUM_STAIRS.block, "Тритановые ступеньки")
add(MRegistry.TRITANIUM_SLAB.block, "Тритановая плита")
add(MRegistry.TRITANIUM_WALL.block, "Тритановая ограда")
add(MRegistry.INDUSTRIAL_GLASS.block, "Промышленное стекло")
add(MRegistry.INDUSTRIAL_GLASS_PANE.block, "Панель промышенного стекла")
add(MRegistry.DECORATIVE_CRATE.block, "Ржавый грузовой контейнер")
add(MRegistry.VENT.block, "Вентиляция")
add(MRegistry.VENT_ALTERNATIVE.block, "Альтернаятивная вентиляция")
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_BLOCK.blocksWithColor) {
val (base, stripe) = colors
val baseName = provider.russianColors.dyeClassMapped[base]!!
val stripeName = provider.russianColors.dyeClassMapped[stripe]!!
add(block, "$baseName-окрашенный $stripeName-ополосаченный тритановый блок")
}
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_STAIRS.blocksWithColor) {
val (base, stripe) = colors
val baseName = provider.russianColors.dyeClassMapped[base]!!
val stripeName = provider.russianColors.dyeClassMapped[stripe]!!
add(block, "$baseName-окрашенные $stripeName-ополосаченные тритановые ступеньки")
}
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_SLAB.blocksWithColor) {
val (base, stripe) = colors
val baseName = provider.russianColors.dyeClassMapped[base]!!
val stripeName = provider.russianColors.dyeClassMapped[stripe]!!
add(block, "$baseName-окрашенная $stripeName-ополосаченная тритановая Плита")
}
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_WALL.blocksWithColor) {
val (base, stripe) = colors
val baseName = provider.russianColors.dyeClassMapped[base]!!
val stripeName = provider.russianColors.dyeClassMapped[stripe]!!
add(block, "$baseName-окрашенная $stripeName-ополосаченная тритановая ограда")
}
}
}
private fun sounds(provider: MatteryLanguageProvider) {
with(provider.russian) {
sound("rifle_shot", "Выстрел плазменной винтовки")
sound("plasma_weapon_overheat", "Плазменное оружие перегрелось")
sound("player_become_android", "Игрок превратился в андроида")
sound(MSoundEvents.CARGO_CRATE_OPEN, "Открыт грузовой ящик")
}
}
private fun misc(provider: MatteryLanguageProvider) {
with(provider.russian) {
gui("help.slot_filters", "Удерживайте CTRL для настройки фильтрации слотов")
gui("help.slot_charging", "Удерживайте ALT для переключения зарядки слотов")
gui("needs", "Требуется %s")
gui("needs_x", "Требуется %s x%d")
misc("needs_no_power", "Не требует энергии для работы")
gui("lock_holo_screen", "Заблокировать содержимое")
gui("lock_holo_screen.tip", "Блокировка и разблокировка содержимого возможна только в режиме творчества.\nКогда заблокировано, границы ввода текста отключены.")
gui("ticks", "Тиков")
gui("power_cost_per_use", "Энергии на операцию: %s")
gui("power_cost_per_tick", "Энергии на тик: %s")
gui("cancel", "Отмена")
gui("confirm", "Подтвердить")
gui("recipe.ticks", "%s Тиков")
gui("exopack", "Инвентарь Экзопака")
gui("exopack.customize", "Изменить внешний вид Экзопака")
gui("exopack.customization", "Внешний вид Экзопака")
gui("exopack.go_back", "Открыть обычный инвентарь")
gui("exopack.go_in", "Открыть инвентарь Экзопака")
gui("exopack.toggle_visibility", "Отображать на игроке")
gui("exopack.toggle_glow", "Свечение в темноте")
gui("exopack.change_color", "Изменить окраску")
gui("exopack.change_color2", "Убрать окраску")
gui("exopack.go_curios", "Открыть инвентарь Curios")
gui("exopack.probe1", "Данное маленькое устройство необычно на ощупь, а так же неприступно для любых попыток вскрыть.")
gui("exopack.probe2", "На одной из сторон данного устройства находится сканер отпечатка, который тускло загорается при касании.")
gui("exopack.probe3", "Вероятно, устройство откроется если достаточно сильно нажать на сканер отпечатка, и вы чувствуете, что последствия будут необратимы!")
gui("exopack.already_activated", "У вас уже есть Экзопак!")
gui("exopack_upgrades.no_exopack", "Данный пазл технологии кажется для вас бесполезным... Или..?!")
gui("exopack_upgrades.already_activated", "Улучшение уже активно!")
gui("exopack_upgrades.slots_upgrade", "Активируя данное улучшение даст %s слотов в вашем Экзопаке.")
gui("exopack_upgrades.crafting_upgrade", "Активация данного улучшения даст 3x3 сетку создания в вашем Экзопаке.")
gui("exopack_upgrades.smelting_upgrade", "Активация данного улучшения даст плавильню в вашем Экзопаке.")
gui("exopack_upgrades.ender_access_upgrade", "Активация данного улучшения даст доступ к сундуку края в вашем Экзопаке.")
gui("crude_battery.replace_in_world", "Простота устройства данного аккумулятора позволяет вам заменить .")
gui("crude_battery.replace_in_world_warning", "Данная операция крайне рискованная и может нанести огромный урон вашим системам!")
gui("power_supplier.active_nodes", "Узлы сети, требующие питания: %s")
misc("battery.single_use", "Единоразовая батарейка, не может быть перезаряжена.")
misc("exopack_upgrades.slots_upgraded", "Ваш Экзопак был расширен на %s слотов")
misc("exopack_upgrades.crafting_upgraded", "Ваш Экзопак получил 3x3 сетку создания")
misc("exopack_upgrades.smelting_installed", "Ваш Экзопак получил плавильню")
misc("exopack_upgrades.ender_access_installed", "Ваш Экзопак получил доступ к содержимому сундука края")
misc("exopack.granted1", "После некоторого времени нажатия на сканер отпечатка, маяк исчезает.")
misc("exopack.granted2", "Через мгновение, вашу спину пронзают множество раз...")
misc("exopack.granted3", "Как только боль утихает, вы обнаруживаете нового 'друга' на вашей спине: Экзопак.")
misc("exopack.granted4", "Данное устройство предоставляет вам доступ к карманному измерению в 4том измерении.")
misc("exopack.granted5", "Ищите или создавайте модули для улучшения Экзопака.")
misc("exopack.granted6", "Так же сам Экзопак существует в 4том измерении, что не мешает носить любую броню.")
misc("exopack.granted7", "Но не смотря на то, что экзопак существует в 4том измерении, предметы из него всё равно высыпаются при смерти.")
misc("dumping_matter_registry", "Выгружаю реестр материи в %s")
misc("dumped_matter_registry", "Выгрузил реестр материи в %s")
misc("iteration", "Итерация %s")
misc("death_reason", "Списан!")
misc("item.blackhole_immunity", "Нейтрализует искажение пространства-времени сингулярностями")
misc("suffix.merge", "%s %s")
misc("suffix.none", "%s %s")
misc("suffix.kilo", "%s к%s")
misc("suffix.mega", "%s М%s")
misc("suffix.giga", "%s Г%s")
misc("suffix.tera", "%s Т%s")
misc("suffix.peta", "%s П%s")
misc("suffix.exa", "%s Э%s")
misc("suffix.zetta", "%s З%s")
misc("suffix.yotta", "%s И%s")
misc("suffix.deci", "%s д%s")
misc("suffix.centi", "%s с%s")
misc("suffix.milli", "%s м%s")
misc("suffix.micro", "%s мк%s")
misc("suffix.nano", "%s н%s")
misc("suffix.pico", "%s п%s")
misc("suffix.femto", "%s ф%s")
misc("suffix.atto", "%s а%s")
misc("suffix.zepto", "%s з%s")
misc("suffix.yocto", "%s и%s")
misc("suffix_concise.none", "%s")
misc("suffix_concise.kilo", "%sк")
misc("suffix_concise.mega", "%sМ")
misc("suffix_concise.giga", "%sГ")
misc("suffix_concise.tera", "%sТ")
misc("suffix_concise.peta", "%sП")
misc("suffix_concise.exa", "%sЭ")
misc("suffix_concise.zetta", "%sЗ")
misc("suffix_concise.yotta", "%sИ")
misc("suffix_concise.deci", "%sд")
misc("suffix_concise.centi", "%sс")
misc("suffix_concise.milli", "%sм")
misc("suffix_concise.micro", "%s к")
misc("suffix_concise.nano", "%sн")
misc("suffix_concise.pico", "%sп")
misc("suffix_concise.femto", "%sф")
misc("suffix_concise.atto", "%sа")
misc("suffix_concise.zepto", "%sз")
misc("suffix_concise.yocto", "%sи")
misc("suffix_raw.kilo", "к")
misc("suffix_raw.mega", "М")
misc("suffix_raw.giga", "Г")
misc("suffix_raw.tera", "Т")
misc("suffix_raw.peta", "П")
misc("suffix_raw.exa", "Э")
misc("suffix_raw.zetta", "З")
misc("suffix_raw.yotta", "И")
misc("suffix_raw.deci", "д")
misc("suffix_raw.centi", "с")
misc("suffix_raw.milli", "м")
misc("suffix_raw.micro", "мк")
misc("suffix_raw.nano", "н")
misc("suffix_raw.pico", "п")
misc("suffix_raw.femto", "ф")
misc("suffix_raw.atto", "а")
misc("suffix_raw.zepto", "з")
misc("suffix_raw.yocto", "и")
misc("item.power.infinite.storage", "Хранимая энергия неиссякаема")
misc("item.power.infinite.throughput", "Максимальный ввод/вывод неограничен")
misc("item.power.passed", "Переданная энергия: %s")
misc("item.power.received", "Принятая энергия: %s")
misc("item.power.average", "Среднее: %s в тик")
misc("item.power.last_20_ticks", "Последняя секунда: %s")
misc("item.power.last_tick", "Последний тик: %s")
gui("power.passed", "Всего передано энергии:")
gui("power.average", "Средняя передача в тик:")
gui("power.last_20_ticks", "Последняя секунда:")
gui("power.last_tick", "Последний тик:")
misc("item.power.storage", "Хранимая энергия: %s / %s")
misc("item.power.throughput", "Максимальная пропускная способность: %s / %s")
misc("item.power.throughput_mono", "Максимальная пропускная способность: %s")
misc("item.power.infinity", "∞ МтДж")
misc("item.worker.work_ticks_mono", "Рабочих тиков: %s")
misc("item.worker.work_ticks", "Рабочих тиков: %s / %s")
misc("item.block.stored_battery", "Батарея: %s")
misc("item.pattern.stored", "Хранимые шаблоны: %s / %s")
misc("item.pattern.infinite.stored", "Хранимые шаблоны: %s")
misc("item.pattern.research", "Исследовано: %s%%")
misc("item.pattern.research.item_count", "Предметы: %s / %s")
misc("item.pattern.research.advance", "Исследование за предмет: %s%%")
misc("item.matter.infinite", "Хранимая материя неиссякаема")
misc("item.matter.normal", "Хранимая материя: %s / %s")
misc("gui.matter_task.total", "Всего: %s")
misc("gui.matter_task.required", "Осталось исполнить: %s")
misc("gui.matter_task.in_progress", "В процессе: %s")
misc("gui.matter_task.finished", "Завершено: %s")
misc("pill.warning", "ВНИМАНИЕ: Это МГНОВЕННО спишет вас при употреблении!")
misc("pill.android", "Примешь эту таблетку - войдешь в страну чудес, потеряв то, что удерживает тебя здесь.")
misc("pill.humane", "Примешь эту таблетку - проснешься в своей постели и поверишь, что это был сон.")
misc("pill.oblivion", "Предметы и Очки опыта, потраченные на исследования полностью возвращаются.")
misc("pill.message_oblivion", "Все возможности андроида были удалены, а потраченные на исследования предметы и опыт возвращены.")
misc("pill.heal", "Мгновенно восполняет 4 сердца при употреблении, а так же даёт на 2 минуты поглощение V и на 8 секунд регенерацию III.")
misc("pill.heal_android", "Не действует на андроидов.")
misc("pill.message", "Ничего не произошло, но вы чувствуете... себя уставшим?.. Возможно надо отдохнуть.")
misc("pill.message_finish", "§kОДИН ИЗ НАС ОДИН ИЗ НАС ОДИН ИЗ НАС ОДИН ИЗ НАС ОДИН ИЗ НАС")
gui("power.percentage_level", "Уровень энергии: %s%%")
gui("power.name", "МтДж")
gui("fluid.name", "В")
gui("fluid.level", "%s / %s с %s")
gui("empty", "Пусто")
gui("power.burn_time", "Оставшееся время горения: %s тиков")
gui("progress_widget", "Прогресс: %s%%")
gui("progress_widget_stuck", "Это устройство не может продолжить работу, проверьте конфигурацию")
gui("total_raw", "Всего:")
gui("matter.percentage_level", "Уровень материи: %s%%")
gui("matter.format", "Материя: %s")
gui("matter.format_and_complexity", "%s / Сложность: %s")
gui("matter.format_and_complexity2", "%s (%s) / Сложность: %s (%s)")
gui("matter.name", "МтЕд")
gui("filter.is_whitelist", "Белый список")
gui("filter.match_nbt", "Сравнивать NBT")
gui("filter.match_tag", "Сравнить Теги")
gui("android_research", "Дерево Исследований")
gui("pattern.percentage_level", "Уровень заполнения: %s%%")
gui("pattern.format", "Хранимые шаблоны: %s / %s")
gui("redstone.ignored", "Режим красного камня: Игнорирование")
gui("redstone.low", "Режим красного камня: Нет сигнала")
gui("redstone.high", "Режим красного камня: Есть сигнал")
gui("redstone.ignored.description", "Сигнал красного камня не влияет на работу устройства")
gui("redstone.low.description", "Устройство работает если нет сигнала красного камня")
gui("redstone.high.description", "Устройство работает если есть сигнал красного камня")
misc("3d2d.gravitation_stabilizer.mass", "Масса сингулярности: %s")
misc("3d2d.gravitation_stabilizer.strength", "Гравитационная сила: %s")
misc("android_station.research.low_power", "Мало питания у станции андроидов! Исследования недоступны!")
misc("android_station.research.researched", "Исследовано!")
misc("android_station.research.can_be_researched", "Готово к исследованию!")
misc("android_station.research.can_not_be_researched", "Нельзя исследовать!")
misc("android_station.research.xp_cost", "Требуется %s уровней Опыта")
misc("android_station.research.item", "Требует %s %s шт.")
misc("android_station.research.missing_predecessors", "Сначала надо изучить %s")
misc("android_station.research.confirm", "Подтвердите исследование %s")
misc("android_station.research.research_will_be_blocked", "Следующие исследования станут недоступны:")
misc("android_station.low_power_0", "Недостаточно питания; Невозможно менять части андроида")
misc("android_station.low_power_1", "Слабое питание; Невозможно исследовать")
misc("android_station.power_ok", "Питание в норме")
misc("filter.yes", "Да")
misc("filter.no", "Нет")
misc("matter_bottler.switch_mode", "Переключить режим работы")
misc("item.quantum_battery.creative", "Наполните этот аккумулятор чтоб выиграть Minecraft.")
misc("item.quantum_battery.creative2", "Встретимся после выгорания миллионов звёзд.")
misc("item.quantum_battery.creative_power", "Хранимая энергия: %s / ∞")
misc("item.quantum_link_id", "ID Квантового соединения: %s")
misc("item.quantum_description", "Содержимое данного предмета связано с другими предметами посредством квантовой запутанности")
}
}
private fun death(provider: MatteryLanguageProvider) {
with(provider.russian) {
death("otm_become_android", "%1\$s потерял свою человечность")
death("otm_become_humane", "%1\$s восстановил свою человечность")
death("otm_event_horizon", "%1\$s никогда не пересёк горизонт событий")
death("otm_hawking_radiation", "%1\$s открыл излучение Хокинга")
death("otm_emp", "Электроника %1\$s перегорела")
death("otm_cosmic_rays", "Электроника %1\$s была ошеломлена космическим излучением")
death("otm_android_discharge", "В аккумуляторах %1\$s закончился заряд")
death("otm_become_android.player", "%1\$s потерял свою человечность, когда %2\$s пытался образумить их")
death("otm_become_humane.player", "%1\$s восстановил свою человечность, когда %2\$s пытался образумить их")
death("otm_event_horizon.player", "%1\$s попытался пересечь горизонт событий, спасаясь от %2\$s")
death("otm_hawking_radiation.player", "%1\$s распался пока сражался с %2\$s")
death("otm_emp.player", "%2\$s выбил все предохранители %1\$s")
death("otm_emp.player.item", "%2\$s выбил все предохранители %1\$s используя %3\$s")
death("otm_explosive_hammer", "Время развлечений у %1\$s с молотком подошло к концу")
death("otm_hammer_nail", "%1\$s был пригвождён")
death("otm_hammer_nail" + ".player", "%1\$s был пригвождён %2\$s")
death("otm_hammer_nail" + ".player.item", "%1\$s был пригвождён %2\$s используя %3\$s")
death("otm_exopack_probe", "%1\$s не выдержал спинную хирургию")
death("otm_exopack_probe.player", "%1\$s не выдержал спинную хирургию пока сражался с %2\$s")
}
}
private fun blocks(provider: MatteryLanguageProvider) {
with(provider.russian) {
add(MBlocks.ANDROID_STATION, "Станция андроидов")
add(MBlocks.ANDROID_CHARGER, "Беспроводной зарядник")
add(MBlocks.ANDROID_CHARGER, "desc", "Заряжает ближайших андроидов и экзопаки")
add(MBlocks.BATTERY_BANK, "Банк аккумуляторов")
add(MBlocks.MATTER_DECOMPOSER, "Декомпозитор материи")
add(MBlocks.MATTER_CAPACITOR_BANK, "Банк накопителей материи")
add(MBlocks.MATTER_CABLE, "Кабель сети материи")
add(MBlocks.PATTERN_STORAGE, "Хранилище шаблонов")
add(MBlocks.MATTER_SCANNER, "Сканер материи")
add(MBlocks.MATTER_PANEL, "Монитор шаблонов")
add(MBlocks.MATTER_REPLICATOR, "Репликатор материи")
add(MBlocks.MATTER_BOTTLER, "Бутилировщик материи")
add(MBlocks.DRIVE_VIEWER, "Просмотрщик дисков конденсации")
add(MBlocks.BLACK_HOLE, "Локализированная сингулярная точка аномального искажения пространства-времени")
add(MBlocks.COBBLESTONE_GENERATOR, "Генератор булыжника")
add(MBlocks.INFINITE_WATER_SOURCE, "Неиссякаемый источник воды")
add(MBlocks.ESSENCE_STORAGE, "Хранилище эссенции")
add(MBlocks.ESSENCE_STORAGE, "desc", "Позволяет хранить очки опыта")
add(MBlocks.MATTER_RECONSTRUCTOR, "Материальный реконструктор")
add(MBlocks.MATTER_RECONSTRUCTOR, "desc", "Чинит инструменты используя материю")
add(MBlocks.DEV_CHEST, "Сундук разработчика")
add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре")
add(MBlocks.PAINTER, "Стол маляра")
add(MBlocks.MATTER_ENTANGLER, "Квантовый запутыватель материи")
add(MBlocks.FLUID_TANK, "Жидкостный бак")
add(MBlocks.FLUID_TANK, "named", "Жидкостный бак (%s)")
add(MBlocks.ENGINE, "Двигатель корабля")
add(MBlocks.ENGINE, "desc", "К сожалению, он больше не выглядит рабочим.")
add(MBlocks.HOLO_SIGN, "Голографическая табличка")
add(MBlocks.TRITANIUM_INGOT_BLOCK, "Блок слитков тритана")
add(MBlocks.ENERGY_COUNTER, "Счётчик энергии")
add(MBlocks.ENERGY_COUNTER, "Facing", "сторона входа: %s")
add(MBlocks.ENERGY_COUNTER, "Switch", "сменить сторону входа")
add(MBlocks.ENERGY_COUNTER, "Limit", "лимит ввода/вывода. -1 для отключения лимитов")
add(MBlocks.CHEMICAL_GENERATOR, "Химический генератор")
add(MBlocks.DRIVE_RACK, "Стеллаж дисков конденсации")
add(MBlocks.ITEM_MONITOR, "Монитор предметов")
add(MBlocks.PLATE_PRESS, "Пресс пластин")
add(MBlocks.TWIN_PLATE_PRESS, "Двойной пресс пластин")
add(MBlocks.POWERED_FURNACE, "Электрическая печь")
add(MBlocks.POWERED_BLAST_FURNACE, "Индукционная печь")
add(MBlocks.POWERED_SMOKER, "Микроволновая печь")
add(MBlocks.MATTER_RECYCLER, "Перерабатыватель материи")
add(MBlocks.ENERGY_SERVO, "Энергетическая помпа")
add(MBlocks.ENERGY_SERVO, "Desc", "заряжает, разряжает и передаёт энергию между предметами")
add(MBlocks.CARBON_FIBRE_BLOCK, "Блок углеродных трубок")
add(MBlocks.METAL_MESH, "Блок металлической сетки")
add(MBlocks.METAL_JUNK, "Металлический хлам")
add(MBlocks.METAL_JUNK, "desc", "Бесполезный хлам, или нет?")
add(MBlocks.TRITANIUM_STRIPED_BLOCK, "Тритановый блок с полоской")
add(MBlocks.TRITANIUM_STRIPED_STAIRS, "Тритановые ступеньки с полоской")
add(MBlocks.TRITANIUM_STRIPED_SLAB, "Тритановая плита с полоской")
add(MBlocks.TRITANIUM_STRIPED_WALL, "Тритановая ограда с полоской")
add(MBlocks.TRITANIUM_ORE, "Тритановая руда")
add(MBlocks.DEEPSLATE_TRITANIUM_ORE, "Тританоносный глубинный сланец")
add(MBlocks.TRITANIUM_RAW_BLOCK, "Блок рудного тритана")
add(MBlocks.STORAGE_CABLE, "Кабель хранилища")
add(MBlocks.STORAGE_POWER_SUPPLIER, "Подстанция сети хранилища")
add(MBlocks.STORAGE_BUS, "Шина хранилища")
add(MBlocks.STORAGE_IMPORTER, "Импортер хранилища")
add(MBlocks.STORAGE_EXPORTER, "Экспортер хранилища")
add(MBlocks.GRAVITATION_STABILIZER, "Стабилизатор пространства-времени")
add(MBlocks.GRAVITATION_STABILIZER_LENS, "Линза стабилизатора пространства-времени")
add(MBlocks.GRAVITATION_STABILIZER, "Desc", "Уменьшает искажение пространства-времени сингулярностей")
add(MBlocks.GRAVITATION_STABILIZER, "Desc2", "Имейте ввиду, что несколько стабилизаторов создают экспоненциальный эффект")
add(MBlocks.GRAVITATION_STABILIZER, "Desc3", "Слишком слабое искажение пространства-времени приведёт к быстрому 'испарению' сингулярности!")
add(MBlocks.PHANTOM_ATTRACTOR, "Приманщик фантомов")
add(MBlocks.PHANTOM_ATTRACTOR, "Desc", "приманивает фантомов в ночное время")
add(MBlocks.LABORATORY_LAMP, "Лабораторная лампа")
add(MBlocks.LABORATORY_LAMP, "Description", "освещает на несколько блоков в направлении своей лампы, с переключателем красного камня")
add(MBlocks.LABORATORY_LAMP_INVERTED, "Лабораторная лампа (инвентированный сигнал)")
add(MBlocks.DANGER_STRIPE_BLOCK, "Полоски 'опасность'")
add(MBlocks.METAL_BEAM, "Металлическая опора")
add(MBlocks.TRITANIUM_DOOR[null]!!, "Тритановая дверь")
add(MBlocks.TRITANIUM_DOOR[null]!!, "description0", "Взрывоустойчивая дверь с засовом красного камня...")
add(MBlocks.TRITANIUM_DOOR[null]!!, "description1", FEELING_SAFE_NOW)
add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "Тритановый люк")
add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "description0", "Взрывоустойчивая дверь с засовом красного камня...")
add(MBlocks.TRITANIUM_TRAPDOOR[null]!!, "description1", FEELING_SAFE_NOW)
add(MBlocks.TRITANIUM_BARS, "Тритановая решётка")
for (block in MBlocks.TRITANIUM_ANVIL)
add(block, "Тритановая наковальня")
}
}
private fun items(provider: MatteryLanguageProvider) {
with(provider.russian) {
add(MItems.PROCEDURAL_BATTERY, "Загадочный аккумулятор")
add(MItems.PROCEDURAL_BATTERY, "desc", "Данные аккумуляторы можно найти в подземельях, со случайными характеристиками")
add(MItems.EXPLOSIVE_HAMMER, "Молоток-убийца")
add(MItems.EXPLOSIVE_HAMMER, "desc", "Для тех, кому стало скучно")
add(MItems.EXPLOSIVE_HAMMER, "primed", "Заряжен!")
add(MItems.EXPLOSIVE_HAMMER, "not_primed0", "Не заряжен")
add(MItems.EXPLOSIVE_HAMMER, "not_primed1", "Для зарядки добавьте немного пороха и наконечник-самородок")
add(MItems.EXOPACK_PROBE, "Маяк экзопака")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Творческое обновление инвентаря экзопака")
add(MItems.ExopackUpgrades.CRAFTING_UPGRADE, "Обновление сетки крафта экзопака")
add(MItems.ExopackUpgrades.SMELTING_UPGRADE, "Модуль плавильни экзопака")
add(MItems.ExopackUpgrades.ENDER_UPGRADE, "Модуль доступа к сундуку края экзопака")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "Обновление сверхмассивной упаковки")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_WITHER, "description", "Использует те же принципы, которыми обладают звёзды незера")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "Обновление соединения края экзопака")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON, "description", "Позволяет хранить предметы в карманном измерении. А так же даёт доступ к содержимому сундука края.")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "Неописуемое обновление инвентаря экзопака")
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, "description", "В нормальных условиях, они появляются в сундуках")
add(MItems.ESSENCE_CAPSULE, "Капсула эссенции")
add(MItems.ESSENCE_DRIVE, "Голодиск воспоминаний андроида")
add(MItems.ESSENCE_SERVO, "Помпа эссенции")
add(MItems.ESSENCE_SERVO, "desc", "Позволяет 'перекачивать' эссенцию гуманоидов из плоти")
add(MItems.ESSENCE_SERVO, "desc2", "Может быть использовано напрямую, или как инструмент внутри хранилища эссенции")
add(MItems.NUTRIENT_PASTE, "Питательная паста")
add(MItems.FLUID_CAPSULE, "Жидкостная капсула")
add(MItems.FLUID_CAPSULE, "named", "Жидкостная капсула (%s)")
add(MItems.BLACK_HOLE_SCANNER, "Сканер ёярностей")
add(MItems.BLACK_HOLE_SCANNER, "desc", "Сканирует сингулярности и считывает их свойства")
add(MItems.BLACK_HOLE_SCANNER, "desc2", "Держите в любой их рук для считывания массы сингулярностей")
add(MItems.GRAVITATION_FIELD_LIMITER, "Ограничитель искажения пространства-времени")
add(MItems.GRAVITATION_FIELD_SENSOR, "Сенсор искажения пространства-времени")
add(MItems.PORTABLE_GRAVITATION_STABILIZER, "Портативный стабилизатор пространства-времени")
add(MItems.BATTERY_CRUDE, "Самобытный аккумулятор")
add(MItems.BATTERY_BASIC, "Простой аккумулятор")
add(MItems.BATTERY_NORMAL, "Аккумулятор")
add(MItems.BATTERY_DENSE, "Плотный аккумулятор")
add(MItems.BATTERY_CAPACITOR, "Аккумулятор-конденсатор")
add(MItems.BATTERY_CREATIVE, "Творческий аккумулятор")
add(MItems.QUANTUM_BATTERY, "Квантовый аккумулятор")
add(MItems.QUANTUM_CAPACITOR, "Квантовый аккумулятор-накопитель")
add(MItems.QUANTUM_BATTERY_CREATIVE, "Творческий квантовый аккумулятор")
add(MItems.TRITANIUM_SWORD, "Тритановый меч")
add(MItems.TRITANIUM_PICKAXE, "Тритановая кирка")
add(MItems.TRITANIUM_SHOVEL, "Тритановая лопата")
add(MItems.TRITANIUM_AXE, "Тритановый топор")
add(MItems.TRITANIUM_HOE, "Тритановая мотыга")
add(MItems.TRITANIUM_SHEARS, "Тритановые ножницы")
add(MItems.TRITANIUM_SHIELD, "Тритановый щит")
add(MItems.TRITANIUM_HELMET, "Тритановый шлем")
add(MItems.TRITANIUM_CHESTPLATE, "Тритановый нагрудник")
add(MItems.TRITANIUM_PANTS, "Тритановые поножи")
add(MItems.TRITANIUM_BOOTS, "Тритановые ботинки")
add(MItems.SIMPLE_TRITANIUM_HELMET, "Простой тритановый шлем")
add(MItems.SIMPLE_TRITANIUM_CHESTPLATE, "Простой тритановый нагрудник")
add(MItems.SIMPLE_TRITANIUM_PANTS, "Простые тритановые поножи")
add(MItems.SIMPLE_TRITANIUM_BOOTS, "Простые тритановые ботинки")
add(MItems.TRITANIUM_DUST, "Тритановая пыль")
add(MItems.TRITANIUM_INGOT, "Тритановый слиток")
add(MItems.TRITANIUM_NUGGET, "Тритановый самородок")
add(MItems.MATTER_IO_PORT, "Порт ввода/вывода материи")
add(MItems.MATTER_TRANSFORM_MATRIX, "Матрица преобразования материи")
add(MItems.ENERGY_BUS, "Шина питания")
add(MItems.ELECTRIC_PARTS, "Электрические части")
add(MItems.MACHINE_FRAME, "Каркас механизма")
add(MItems.TRITANIUM_PLATE, "Тритановая пластина")
add(MItems.IRON_PLATE, "Железная пластина")
add(MItems.GOLD_PLATE, "Золотая пластина")
add(MItems.COPPER_WIRING, "Медная проволока")
add(MItems.GOLD_WIRING, "Золотая проволока")
add(MItems.PORTABLE_CONDENSATION_DRIVE_CASING, "Каркас портативного диска конденсации")
add(MItems.PORTABLE_DENSE_CONDENSATION_DRIVE_CASING, "Каркас плотного портативного диска конденсации")
add(MItems.CIRCUIT_PLATING, "Плата электроники")
add(MItems.BASIC_CONTROL_CIRCUIT, "Простая схема управления")
add(MItems.ADVANCED_CONTROL_CIRCUIT, "Продвинутая схема управления")
add(MItems.QUANTUM_TRANSCEIVER, "Квантовый передатчик")
add(MItems.ELECTROMAGNET, "Электромагнит")
add(MItems.ELECTROMOTOR, "Электромотор")
add(MItems.MIRROR_COMPOUND, "Набор выплавки зеркала")
add(MItems.MIRROR, "Зеркало")
add(MItems.MIRROR, "description", "Я могу очень отчётливо видеть своё отражение в этом зеркале")
add(MItems.REINFORCED_TRITANIUM_PLATE, "Укреплённая тритановая пластина")
add(MItems.REINFORCED_TRITANIUM_PLATE, "description", "Бронированная пластина, усиленная что бы выдержать большие кинетические силы")
add(MItems.CARBON_MESH, "Углеродная сетка")
add(MItems.GRAVITATIONAL_DISRUPTOR, "Маяк уравнения пространства-времени")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description", "Будучи находясь около точки искажения пространства-времени, создаёт противоположное искажение пространства-времени")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description2", "Позволяет 'уничтожать' сингулярности")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description3", "Никак не влияет на материю, которую накопила сингулярность, что вызывает неописуемо сильный взрыв материи!")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description4", "Взрыв %s сдержан %s. Даже не пытайтесь его сдержать.")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description4_clarification", "не может быть")
add(MItems.GRAVITATIONAL_DISRUPTOR, "description4_clarification2", "ничем")
add(MItems.MATTER_DUST, "Пыль материи")
add(MItems.MATTER_DUST, "desc", "Данный предмет является результатом неудачной попытки декомпозиции или репликации")
add(MItems.MATTER_DUST, "desc2", "Закиньте в Материальный Переработчик для переработки обратно в чистую материю!")
add(MItems.MATTER_DUST, "desc3", "Не нюхать, не кидать на других и не сыпать на пончики")
add(MItems.PILL_ANDROID, "Пилюля андроида")
add(MItems.PILL_HUMANE, "Пилюля человечности")
add(MItems.PILL_OBLIVION, "Пилюля сброса андроида до заводских настроек")
add(MItems.PILL_HEAL, "Медицинская пилюля")
add(MItems.MATTER_CAPACITOR_PARTS, "Части накопителя материи")
add(MItems.MATTER_CAPACITOR_BASIC, "Простой накопитель материи")
add(MItems.MATTER_CAPACITOR_NORMAL, "Накопитель материи")
add(MItems.MATTER_CAPACITOR_DENSE, "Плотный накопитель материи")
add(MItems.MATTER_CAPACITOR_CREATIVE, "Творческий накопитель материи")
add(MItems.ENERGY_SWORD, "Высокочастотный клинок")
add(MItems.ENERGY_SWORD, "desc", "Требует энергию для работы")
add(MItems.ENERGY_SWORD, "desc2", "Наносит дополнительный урон андроидам если имеет заряд")
add(MItems.ENERGY_SWORD, "desc3", "Всегда наносит полный урон по площади если имеет заряд")
add(MItems.ENERGY_SWORD, "desc4", "Зачарование 'Разящий клинок' не имеет никакого эффекта на данном оружии")
add(MItems.PORTABLE_CONDENSATION_DRIVE, "Portable Condensation Drive")
add(MItems.PORTABLE_DENSE_CONDENSATION_DRIVE, "Portable Dense Condensation Drive")
add(MItems.PLASMA_RIFLE, "Плазменная винтовка")
add(MItems.TRITANIUM_ORE_CLUMP, "Рудный тритан")
add(MItems.PATTERN_DRIVE_NORMAL, "Диск шаблонов")
add(MItems.PATTERN_DRIVE_CREATIVE, "Творческий диск шаблонов")
add(MItems.PATTERN_DRIVE_CREATIVE2, "Вездесущий диск шаблонов")
add(MItems.PATTERN_DRIVE_CREATIVE2, "description1", "Предмет режима творчества")
add(MItems.PATTERN_DRIVE_CREATIVE2, "description2", "Содержит в себе шаблоны всех предметов, которые имеют значение материи")
add(MItems.ZPM_BATTERY, "Модуль нулевой точки")
add(MItems.ZPM_BATTERY, "description", "Может быть найден у тех, кто путешествует между измерениями, если, конечно, они смогли достигнуть вселенной, где данные устройства были созиданы...")
add(MItems.MachineUpgrades.Basic.BLANK, "Шаблон простого улучшения")
add(MItems.MachineUpgrades.Basic.SPEED, "Простое улучшение скорости")
add(MItems.MachineUpgrades.Basic.ENERGY_CONSUMPTION, "Простое улучшение энергоэффективности")
add(MItems.MachineUpgrades.Basic.FAILSAFE, "Простое улучшение отказоустойчивости")
add(MItems.MachineUpgrades.Basic.ENERGY_STORAGE, "Простое улучшение энергохранилища")
add(MItems.MachineUpgrades.Basic.MATTER_STORAGE, "Простое улучшение хранилища материи")
add(MItems.MachineUpgrades.Basic.PROCESSING_ITEMS, "Простое улучшение обработки")
add(MItems.MachineUpgrades.Normal.BLANK, "Шаблон улучшения")
add(MItems.MachineUpgrades.Normal.SPEED, "Улучшение скорости")
add(MItems.MachineUpgrades.Normal.ENERGY_CONSUMPTION, "Улучшение энергоэффективности")
add(MItems.MachineUpgrades.Normal.FAILSAFE, "Улучшение отказоустойчивости")
add(MItems.MachineUpgrades.Normal.ENERGY_STORAGE, "Улучшение энергохранилища")
add(MItems.MachineUpgrades.Normal.MATTER_STORAGE, "Улучшение хранилища материи")
add(MItems.MachineUpgrades.Normal.PROCESSING_ITEMS, "Улучшение обработки")
add(MItems.MachineUpgrades.Advanced.BLANK, "Шаблон продвинутого улучшения")
add(MItems.MachineUpgrades.Advanced.SPEED, "Продвинутое улучшение скорости")
add(MItems.MachineUpgrades.Advanced.ENERGY_CONSUMPTION, "Продвинутое улучшение энергоэффективности")
add(MItems.MachineUpgrades.Advanced.FAILSAFE, "Продвинутое улучшение отказоустойчивости")
add(MItems.MachineUpgrades.Advanced.ENERGY_STORAGE, "Продвинутое улучшение энергохранилища")
add(MItems.MachineUpgrades.Advanced.MATTER_STORAGE, "Продвинутое улучшение хранилища материи")
add(MItems.MachineUpgrades.Advanced.PROCESSING_ITEMS, "Продвинутое улучшение обработки")
add(MItems.MachineUpgrades.Creative.SPEED, "Творческое улучшение скорости")
add(MItems.MachineUpgrades.Creative.ENERGY_CONSUMPTION, "Творческое улучшение энергоэффективности")
add(MItems.MachineUpgrades.Creative.ENERGY_STORAGE, "Творческое улучшение энергохранилища")
add(MItems.MachineUpgrades.Creative.ENERGY_STORAGE_FLAT, "Творческое улучшение энергохранилища (простое)")
add(MItems.MachineUpgrades.Creative.ENERGY_STORAGE_FLAT_SMALL, "Творческое улучшение энергохранилища (малое простое)")
add(MItems.MachineUpgrades.Creative.MATTER_STORAGE, "Творческое улучшение хранилища материи")
add(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT, "Творческое улучшение хранилища материи (простое)")
add(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT_SMALL, "Творческое улучшение хранилища материи (малое простое)")
add(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT, "Творческое улучшение энергоканала")
add(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT_FLAT, "Творческое улучшение энергоканала (простое)")
add(MItems.MachineUpgrades.Creative.ENERGY_THROUGHPUT_FLAT_SMALL, "Творческое улучшение энергоканала (малое простое)")
add(MItems.MachineUpgrades.Creative.FAILSAFE, "Творческое улучшение отказоустойчивости")
add(MItems.MachineUpgrades.Creative.FAILURE, "Творческое улучшение краха")
add(MItems.MachineUpgrades.Creative.PROCESSING_ITEMS, "Творческое улучшение обработки")
add(MItems.CHEST_UPGRADER, "Ящикатор")
add(MItems.CHEST_UPGRADER, "desc", "Заменяет установленные сундуки и бочки грузовыми ящиками с сохранением содержимого")
add(MItems.CHEST_UPGRADER, "desc2", "Удерживайте необходимые ящики в противоположной руке")
}
}
private fun stats(provider: MatteryLanguageProvider) {
with(provider.russian) {
stat("health_regenerated", "Здоровья отрегенерировано наноботами")
stat("damage_absorbed", "Урона поглащено наноботами")
stat("power_consumed", "МтДж сожжено за андроида")
}
}
private fun research(provider: MatteryLanguageProvider) {
with(provider.russian) {
add("android_research.status.requires", "Требует %s для изучения")
add("android_research.status.blocks", "Блокирует %s")
add("android_research.status.blocked_by", "Блокируется %s")
add("android_research.status.requires_item", "Требует %s")
add("android_research.status.requires_item_multiple0", "Требует %s %s шт. (требуется ещё %s шт.)")
add("android_research.status.requires_item_multiple1", "Требует %s %s шт.")
add("android_research.status.requires_item_any", "Требует любое из %s")
add("android_research.status.requires_item_multiple_any0", "Требует любое из %s %s шт. (требуется ещё %s шт.)")
add("android_research.status.requires_item_multiple_any1", "Требует любое из %s %s шт.")
}
}
private fun androidFeatures(provider: MatteryLanguageProvider) {
with(provider.russian) {
add(AndroidFeatures.AIR_BAGS, "Воздушные мешки")
add(AndroidFeatures.SHOCKWAVE, "Генератор ударных волн")
add(AndroidFeatures.NIGHT_VISION, "Ночное зрение")
add(AndroidFeatures.NANOBOTS_ARMOR, "Броня из наноботов")
add(AndroidFeatures.ITEM_MAGNET, "Предметный магнит")
add(AndroidFeatures.SWIM_BOOSTERS, "Плавательные лопасти")
add(AndroidFeatures.STEP_ASSIST, "Помощник подъёма")
add(AndroidFeatures.JUMP_BOOST, "Усилитель прыжка")
add(AndroidFeatures.ENDER_TELEPORTER, "Телепортатор края")
}
}
private fun gui(provider: MatteryLanguageProvider) {
with(provider.russian) {
gui("quicksearch", "Быстрый поиск...")
gui("painter.is_bulk", "Массовая покраска")
gui("painter.is_bulk.desc", "Слот покраски будет автоматически наполняться из вашего инвентаря")
gui("painter.is_bulk.desc2", "Быстрое перемещение покрасит максимальное количество предметов из вашего инвентаря")
gui("energy_required", "Требуется энергии: %s")
gui("insert_priority", "Приоритет вставки")
gui("extract_priority", "Приоритет забора")
gui("increase", "Увеличить")
gui("decrease", "Уменьшить")
gui("color_picker", "Выбор цвета")
gui("color.short.red", "К")
gui("color.short.green", "З")
gui("color.short.blue", "С")
gui("color.short.hue", "Ц")
gui("color.short.saturation", "Н")
gui("color.short.value", "Я")
gui("color.full.red", "Красный")
gui("color.full.green", "Зелёный")
gui("color.full.blue", "Синий")
gui("color.full.hue", "Цвет")
gui("color.full.saturation", "Насыщение")
gui("color.full.value", "Яркость")
gui("item_monitor.refill_source.desc", "Контролирует источник предметов для заполнения сетки создания")
gui("item_monitor.refill_source.system", "Только система. Сетка создания будет заполняться только из системы предметов. Данный параметр соответствует поведению AE2 и Refined Storage")
gui("item_monitor.refill_source.inventory", "Только инвентарь. Сетка создания будет заполняться только из инвентаря игрока")
gui("item_monitor.refill_source.system_first", "Сначала система. Сетка создания сначала будет заполняться из системы предметов, а затем из инвентаря игрока")
gui("item_monitor.refill_source.inventory_first", "Сначала инвентарь. Сетка создания сначала будет заполняться из инвентаря игрока, а затем из системы предметов")
gui("item_monitor.refill_source.do_not", "Не заполнять автоматически")
gui("item_monitor.result_target.desc", "Контролирует поведение сетки создания")
gui("item_monitor.result_target.all_system", "Всё в систему. И результат создания и остаток отправляется в систему предметов")
gui("item_monitor.result_target.mixed", "Смешанный. Результат создания кладётся в инвентарь игрока, остаток отправляется в систему предметов")
gui("item_monitor.result_target.all_inventory", "Всё в инвентарь. И результат создания и остаток кладётся в инвентарь игрока")
gui("item_monitor.amount.desc", "Контролирует сколько предметов создавать при быстром крафте")
gui("item_monitor.amount.one", "Ровно один предмет")
gui("item_monitor.amount.stack", "Ровно одну стопку. Данный параметр соответствует поведению AE2 и Refined Storage")
gui("item_monitor.amount.full", "Стопку ингредиентов. Создание продолжается пока не будет достигнут лимит по стопке одного из ингредиентов. Если хотя бы один из ингредиентов не может быть стопкой, будет использован режим 'одна стопка результата'")
gui("stored_amount", "Точное количество в хранилище: %s шт.")
gui("sides.item_config", "Настройка предметов")
gui("sides.energy_config", "Настройка энергии")
gui("sides.fluid_config", "Настройка жидкости")
gui("sides.pull_help", "Удерживайте Shift для настройки режима забора")
gui("sides.push_help", "Удерживайте Ctrl для настройки режима выталкивания")
gui("sides.top", "Верхняя сторона")
gui("sides.bottom", "Нижняя сторона")
gui("sides.front", "Передняя сторона")
gui("sides.back", "Задняя сторона")
gui("sides.left", "Левая сторона")
gui("sides.right", "Правая сторона")
gui("side_mode.disabled", "Отключено")
gui("side_mode.input", "Только вход")
gui("side_mode.output", "Только выход")
gui("side_mode.input_output", "Вход/Выход")
gui("side_mode.battery", "Батарея")
gui("side_mode.pull", "Автоматическое вытягивание")
gui("side_mode.push", "Автоматическое выталкивание")
gui("upgrades", "Улучшения")
gui("upgrades.current", "Активные улучшения:")
gui("upgrade.speed", "Скорость работы: %s%%")
gui("upgrade.processing_items", "Работы за цикл: +%s")
gui("upgrade.energy_storage_flat", "Хранилище энергии: +%s")
gui("upgrade.matter_storage_flat", "Хранилище материи: +%s")
gui("upgrade.energy_storage", "Хранилище энергии: +%s%%")
gui("upgrade.matter_storage", "Хранилище материи: +%s%%")
gui("upgrade.energy_consumed", "Потребление энергии: %s%%")
gui("upgrade.energy_throughput_flat", "Пропускная способность энергии: +%s")
gui("upgrade.energy_throughput", "Пропускная способность энергии: +%s%%")
gui("upgrade.failsafe", "Шанс неудачи: %s%%")
gui("upgrade_type.list", "Классификация улучшения:")
gui("upgrade_type.allowed", "Допустимые улучшения:")
gui("upgrade_type.allowed_none", "На данный момент нет допустимых улучшений.")
gui("upgrade_type.speed", "Скорость")
gui("upgrade_type.processing", "Обработка")
gui("upgrade_type.matter_storage", "Хранилище материи")
gui("upgrade_type.energy_storage", "Энергохранилище")
gui("upgrade_type.energy_consumption", "Энергоэффективность")
gui("upgrade_type.energy_throughput", "Энергоканал")
gui("upgrade_type.failsafe", "Отказоустойчивость")
gui("balance_inputs", "Балансировать входные слоты")
gui("sorting.sort_now", "Отсортировать")
gui("sorting.sort_settings", "Нажмите правую кнопку мыши для настроек")
gui("sorting.default", "Сортировка по умолчанию")
gui("sorting.name", "Сортировка по имени")
gui("sorting.id", "Сортировка по ID")
gui("sorting.modid", "Сортировка по пространству имён (моду)")
gui("sorting.count", "Сортировка по количеству")
gui("sorting.ascending", "Возрастающая")
gui("sorting.descending", "Убывающая")
gui("sorting.matter_value", "Значение материи")
gui("sorting.matter_complexity", "Сложность репликации")
gui("matter_panel.send", "Запросить")
gui("matter_panel.close", "Закрыть")
gui("matter_panel.cancel_task", "Отменить задание")
gui("matter_panel.cancel", "Отмена")
gui("matter_panel.label", "Запрос на репликацию")
gui("matter_panel.task", "Будущий запрос на репликацию")
gui("matter_panel.is_providing_tasks", "Задачи передаются на репликаторы")
gui("matter_panel.not_providing_tasks", "Задачи НЕ передаются на репликаторы")
gui("matter_panel.cancel_all", "Отменить все задачи")
gui("matter_panel.cancel_all.desc", "Вы действительно хотите отменить все задачи репликации?")
gui("matter_panel.tasks", "Задачи")
gui("matter_panel.patterns", "Шаблоны")
gui("matter_panel.number_input", "Введите кол-во единиц репликации")
gui("matter_panel.matter_stored", "Материи хранится: %s")
gui("matter_panel.matter_required", "Материи требуется: %s")
gui("matter_panel.complexity", "Общая сложность: %s")
gui("experience", "%s очков опыта")
gui("experience_levels", "%s уровней опыта")
gui("experience.store", "Передать %s уровней опыта")
gui("experience.store_all", "Передать все уровни опыта")
gui("experience.dispense", "Вывести %s уровней опыта")
gui("experience.dispense_all", "Вывести все уровни опыта")
gui("experience.set_exact", "Установить уровень опыта в %s")
gui("essence_capsule", "(Почти) Всё, что вы знали, хранится внутри")
gui("essence_capsule2", "Данный предмет может быть переработан внутри хранилища эссенции")
gui("essence_capsule3", "Используйте, чтобы высвободить большую часть хранящихся внутри знаний")
gui("essence_capsule.digital", "Используйте, чтобы вернуть ваши воспоминания")
gui("slot_filter.filtered", "Данный слот отфильтрован для автоматизации")
gui("slot_filter.forbidden", "Данный слот запрещён для взаимодействия средствами автоматизации")
gui("slot_filter.hint", "Для удаления фильтра нажмите Ctrl + ЛКМ")
gui("debug.tags.help", "Удерживайте Shift для отображения тегов")
gui("debug.tags.item.title", "Теги предмета:")
gui("debug.tags.block.title", "Теги блока:")
}
}
private fun jade(provider: MatteryLanguageProvider) {
with(provider.russian) {
jadeloc("matter_storage", "Хранилище материи")
jadeloc("mattery_energy", "Хранилище энергии")
jadeloc("mattery_worker", "Прогресс работы механизма")
jadeloc("matter_bottler", "Режим бутилировщика материи")
jadeloc("matter_reconstructor", "Прогресс материального реконструктора")
jade("mode", "Режим: %s")
jade("matter_bottler.mode.fill", "Заполнение")
jade("matter_bottler.mode.drain", "Опустошение")
}
}
fun AddRussianLanguage(provider: MatteryLanguageProvider) {
decoratives(provider)
blocks(provider)
sounds(provider)
misc(provider)
items(provider)
gui(provider)
stats(provider)
research(provider)
death(provider)
androidFeatures(provider)
jade(provider)
}

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.datagen.loot
import net.minecraft.advancements.critereon.StatePropertiesPredicate import net.minecraft.advancements.critereon.StatePropertiesPredicate
import net.minecraft.util.StringRepresentable import net.minecraft.util.StringRepresentable
import net.minecraft.world.item.Rarity
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.properties.Property import net.minecraft.world.level.block.state.properties.Property
@ -17,7 +16,6 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue import net.minecraft.world.level.storage.loot.providers.number.ConstantValue
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator
import ru.dbotthepony.mc.otm.data.condition.ChanceCondition import ru.dbotthepony.mc.otm.data.condition.ChanceCondition
import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction
inline fun LootTable.Builder.lootPool(configurator: LootPool.Builder.() -> Unit): LootTable.Builder = withPool(LootPool.lootPool().also(configurator)) inline fun LootTable.Builder.lootPool(configurator: LootPool.Builder.() -> Unit): LootTable.Builder = withPool(LootPool.lootPool().also(configurator))
inline fun LootTable.Builder.singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootTable.Builder { inline fun LootTable.Builder.singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootTable.Builder {
@ -28,17 +26,6 @@ inline fun LootTable.Builder.singleItem(item: ItemLike, configurator: LootPoolSi
inline fun lootPool(configurator: LootPool.Builder.() -> Unit): LootPool = LootPool.lootPool().also(configurator).build() inline fun lootPool(configurator: LootPool.Builder.() -> Unit): LootPool = LootPool.lootPool().also(configurator).build()
inline fun singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootPool = lootPool { item(item, configurator) } inline fun singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootPool = lootPool { item(item, configurator) }
fun singleRandomizedItem(item: ItemLike, rarity: Rarity = Rarity.COMMON, chance: Double? = null): LootPool {
return lootPool {
item(item) {
apply(RandomizerFunction.valueOf(rarity))
if (chance != null) {
chanceCondition(chance)
}
}
}
}
inline fun LootPool.Builder.item(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit) { inline fun LootPool.Builder.item(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit) {
add(LootItem.lootTableItem(item).also(configurator)) add(LootItem.lootTableItem(item).also(configurator))

View File

@ -51,7 +51,7 @@ fun PlainLootAppender(
vararg items: Pair<ItemStack, Double> vararg items: Pair<ItemStack, Double>
) = PlainLootAppender(conditions, Arrays.stream(items)) ) = PlainLootAppender(conditions, Arrays.stream(items))
class LootModifiers(generator: DataGenerator) : GlobalLootModifierProvider(generator, DataGen.MOD_ID) { class LootModifiers(generator: DataGenerator) : GlobalLootModifierProvider(generator.packOutput, DataGen.MOD_ID) {
private val lambdas = ArrayList<(LootModifiers) -> Unit>() private val lambdas = ArrayList<(LootModifiers) -> Unit>()
fun lambda(lambda: (LootModifiers) -> Unit) { fun lambda(lambda: (LootModifiers) -> Unit) {

View File

@ -1,18 +1,21 @@
package ru.dbotthepony.mc.otm.datagen.loot package ru.dbotthepony.mc.otm.datagen.loot
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.util.valueproviders.UniformInt
import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.EntityType
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import net.minecraft.world.level.storage.loot.BuiltInLootTables import net.minecraft.world.level.storage.loot.BuiltInLootTables
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraftforge.common.loot.LootTableIdCondition import net.minecraftforge.common.loot.LootTableIdCondition
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.data.UniformDecimal
import ru.dbotthepony.mc.otm.data.condition.ChanceWithPlaytimeCondition import ru.dbotthepony.mc.otm.data.condition.ChanceWithPlaytimeCondition
import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition
import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition
import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly
import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender
import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem
import ru.dbotthepony.mc.otm.item.exopack.ProceduralExopackSlotUpgradeItem
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
@Suppress("FunctionName") @Suppress("FunctionName")
@ -25,60 +28,102 @@ fun LootTableIdCondition(location: ResourceLocation): LootItemCondition {
return LootTableIdCondition.Builder(location).build() return LootTableIdCondition.Builder(location).build()
} }
private fun exosuitModifiers(it: LootModifiers) { fun addLootModifiers(it: LootModifiers) {
it.add("dungeon_exosuit", LootPoolAppender( it.add("dungeon_exopack", LootPoolAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)), arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.2) chanceCondition(0.2)
apply(RandomizerFunction.COMMON) apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(6, 9)))
}, },
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) { singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.05) chanceCondition(0.05)
apply(RandomizerFunction.UNCOMMON) apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(9, 18)))
}, },
)) ))
it.add("mineshaft_exosuit", LootPoolAppender( it.add("mineshaft_additions", LootPoolAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)), arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1, rarity = Rarity.UNCOMMON) singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.1)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(4, 8)))
},
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.1)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(4, 10)))
},
singleItem(MItems.PROCEDURAL_BATTERY) {
chanceCondition(0.15)
apply(ProceduralBatteryItem.Randomizer(
maxBatteryLevel = UniformDecimal(Decimal(8_000_000), Decimal(40_000_000)),
batteryLevel = UniformDecimal(Decimal(0), Decimal(20_000_000)),
maxInput = UniformDecimal(Decimal(700), Decimal(4_000)),
))
}
)) ))
it.add("desert_pyramid_exosuit", LootPoolAppender( it.add("desert_pyramid_exosuit", LootPoolAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)), arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.UNCOMMON),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.25, rarity = Rarity.COMMON) singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.1)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(12, 18)))
},
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.25)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(4, 9)))
},
)) ))
it.add("jungle_temple_exosuit", LootPoolAppender( it.add("jungle_temple_exosuit", LootPoolAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)), arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.UNCOMMON),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.35, rarity = Rarity.RARE) singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.15)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(9, 18)))
},
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.35)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(16, 28), UniformInt.of(2, 6)))
},
)) ))
it.add("end_city_exosuit", LootPoolAppender( it.add("end_city_exosuit", LootPoolAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)), arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.4, rarity = Rarity.UNCOMMON),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.2, rarity = Rarity.RARE),
singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.EPIC),
))
}
fun addLootModifiers(it: LootModifiers) { singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
exosuitModifiers(it) chanceCondition(0.4)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(9, 18)))
},
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.2)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(14, 27), UniformInt.of(2, 6)))
},
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.1)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(27, 56), UniformInt.of(2, 6)))
},
))
it.add("dungeon_pill", PlainLootAppender( it.add("dungeon_pill", PlainLootAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)), arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
ItemStack(MItems.PILL_ANDROID, 1) to 0.4, ItemStack(MItems.PILL_ANDROID, 1) to 0.1,
ItemStack(MItems.PILL_HEAL, 2) to 0.5, ItemStack(MItems.PILL_HEAL, 2) to 0.5,
ItemStack(MItems.PILL_HEAL, 1) to 0.75, ItemStack(MItems.PILL_HEAL, 1) to 0.75,
)) ))
it.add("mineshaft_pill", PlainLootAppender( it.add("mineshaft_pill", PlainLootAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)), arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
ItemStack(MItems.PILL_ANDROID, 1) to 0.075, ItemStack(MItems.PILL_ANDROID, 1) to 0.04,
ItemStack(MItems.PILL_HEAL, 2) to 0.1, ItemStack(MItems.PILL_HEAL, 2) to 0.1,
ItemStack(MItems.PILL_HEAL, 1) to 0.4, ItemStack(MItems.PILL_HEAL, 1) to 0.4,
)) ))
@ -92,7 +137,7 @@ fun addLootModifiers(it: LootModifiers) {
it.add("desert_pyramid_pill", PlainLootAppender( it.add("desert_pyramid_pill", PlainLootAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)), arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)),
ItemStack(MItems.PILL_ANDROID, 1) to 0.05, ItemStack(MItems.PILL_ANDROID, 1) to 0.15,
ItemStack(MItems.PILL_HEAL, 1) to 0.3, ItemStack(MItems.PILL_HEAL, 1) to 0.3,
)) ))
@ -103,7 +148,7 @@ fun addLootModifiers(it: LootModifiers) {
it.add("end_city_modifications", PlainLootAppender( it.add("end_city_modifications", PlainLootAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)), arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)),
ItemStack(MItems.PILL_ANDROID, 1) to 0.1, ItemStack(MItems.PILL_ANDROID, 1) to 0.15,
ItemStack(MItems.PILL_HUMANE, 1) to 0.3, ItemStack(MItems.PILL_HUMANE, 1) to 0.3,
ItemStack(MItems.PILL_OBLIVION, 1) to 0.5, ItemStack(MItems.PILL_OBLIVION, 1) to 0.5,
ItemStack(MItems.ZPM_BATTERY, 1) to 0.005, ItemStack(MItems.ZPM_BATTERY, 1) to 0.005,

View File

@ -3,12 +3,12 @@
package ru.dbotthepony.mc.otm.datagen.loot package ru.dbotthepony.mc.otm.datagen.loot
import com.mojang.datafixers.util.Pair
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction
import net.minecraft.advancements.critereon.StatePropertiesPredicate import net.minecraft.advancements.critereon.StatePropertiesPredicate
import net.minecraft.data.DataGenerator import net.minecraft.data.DataGenerator
import net.minecraft.data.loot.LootTableProvider import net.minecraft.data.loot.LootTableProvider
import net.minecraft.data.loot.LootTableSubProvider
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
@ -24,18 +24,11 @@ import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition
import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue import net.minecraft.world.level.storage.loot.providers.number.ConstantValue
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import java.util.function.BiConsumer import ru.dbotthepony.mc.otm.core.stream
import java.util.function.Consumer import ru.dbotthepony.mc.otm.data.loot.CopyTileNbtFunction
import java.util.function.Supplier
private typealias LootTableSaver = BiConsumer<ResourceLocation, LootTable.Builder>
private typealias LootTableCallback = Consumer<LootTableSaver>
private typealias LootTableCallbackProvider = Supplier<LootTableCallback>
private typealias LootTuple = Pair<LootTableCallbackProvider, LootContextParamSet>
data class NbtCopy(val source: String, val destination: String, val strategy: CopyNbtFunction.MergeStrategy = CopyNbtFunction.MergeStrategy.REPLACE) data class NbtCopy(val source: String, val destination: String, val strategy: CopyNbtFunction.MergeStrategy = CopyNbtFunction.MergeStrategy.REPLACE)
@ -43,29 +36,7 @@ fun TileNbtCopy(source: String, strategy: CopyNbtFunction.MergeStrategy = CopyNb
return NbtCopy(source, "BlockEntityTag.$source", strategy) return NbtCopy(source, "BlockEntityTag.$source", strategy)
} }
private val basicTags = arrayOf( class LootTables(generator: DataGenerator) : LootTableProvider(generator.packOutput, setOf() /* because we don't fucking validate you fuck */, listOf() /* because we attach everything after class is constructed duh */) {
TileNbtCopy(MatteryBlockEntity.REDSTONE_SIGNAL_KEY),
TileNbtCopy(MatteryBlockEntity.REDSTONE_SETTING_KEY),
)
private val poweredTags = arrayOf(
*basicTags,
TileNbtCopy(MatteryBlockEntity.ENERGY_KEY),
TileNbtCopy(MatteryBlockEntity.BATTERY_KEY),
)
private val workerTags = arrayOf(
*poweredTags,
TileNbtCopy(MatteryWorkerBlockEntity.JOB_KEY),
TileNbtCopy(MatteryWorkerBlockEntity.WORK_TICKS_KEY),
)
private val poweredMatterWorker = arrayOf(
*workerTags,
TileNbtCopy(MatteryBlockEntity.MATTER_STORAGE_KEY),
)
class LootTables(generator: DataGenerator) : LootTableProvider(generator) {
private val providersTable = Reference2ObjectArrayMap<LootContextParamSet, HashMap<ResourceLocation, () -> LootTable.Builder>>() private val providersTable = Reference2ObjectArrayMap<LootContextParamSet, HashMap<ResourceLocation, () -> LootTable.Builder>>()
fun builder(context: LootContextParamSet, id: ResourceLocation, provider: LootTable.Builder.() -> Unit) { fun builder(context: LootContextParamSet, id: ResourceLocation, provider: LootTable.Builder.() -> Unit) {
@ -80,10 +51,10 @@ class LootTables(generator: DataGenerator) : LootTableProvider(generator) {
.put(id, provider) == null) { "Duplicate loot pool entry for $id" } .put(id, provider) == null) { "Duplicate loot pool entry for $id" }
} }
override fun getTables(): List<LootTuple> { override fun getTables(): List<SubProviderEntry> {
return providersTable.entries.stream().map { entry -> return providersTable.entries.stream().map { entry ->
Pair.of(LootTableCallbackProvider { SubProviderEntry({
LootTableCallback { LootTableSubProvider {
for ((id, callback) in entry.value) { for ((id, callback) in entry.value) {
it.accept(id, callback.invoke()) it.accept(id, callback.invoke())
} }
@ -163,91 +134,11 @@ class LootTables(generator: DataGenerator) : LootTableProvider(generator) {
} }
} }
fun tile(block: Block, f: (CopyNbtFunction.Builder) -> Unit = {}) { fun tile(block: Block, vararg filterTags: String) {
singleLootPool(LootContextParamSets.BLOCK, block.lootTable) { singleLootPool(LootContextParamSets.BLOCK, block.lootTable) {
add(LootItem.lootTableItem(block).also { add(LootItem.lootTableItem(block).also {
it.apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY).also { it.apply(CopyTileNbtFunction(filterTags.stream()))
it.copy("Name", "BlockEntityTag.Name")
f(it)
})
}) })
} }
} }
fun tile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
}
}
fun basicTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in basicTags) {
it.copy(source, destination, strategy)
}
}
}
fun poweredTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in poweredTags) {
it.copy(source, destination, strategy)
}
}
}
fun workerTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in workerTags) {
it.copy(source, destination, strategy)
}
}
}
fun matterWorkerTile(block: Block, vararg tags: NbtCopy) {
tile(block) {
for ((source, destination, strategy) in tags) {
it.copy(source, destination, strategy)
}
for ((source, destination, strategy) in poweredMatterWorker) {
it.copy(source, destination, strategy)
}
}
}
fun tile(block: Block, vararg tags: String) {
tile(block, *tags.map { NbtCopy(it, "BlockEntityTag.$it", CopyNbtFunction.MergeStrategy.REPLACE) }.toTypedArray())
}
// fix overload resolution by adding extra required argument
fun basicTile(block: Block, f: String, vararg tags: String) {
basicTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
fun poweredTile(block: Block, f: String, vararg tags: String) {
poweredTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
fun workerTile(block: Block, f: String, vararg tags: String) {
workerTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
fun matterWorkerTile(block: Block, f: String, vararg tags: String) {
matterWorkerTile(block, *tags.map { TileNbtCopy(it) }.toMutableList().also { it.add(TileNbtCopy(f)) }.toTypedArray())
}
} }

View File

@ -6,15 +6,6 @@ import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
import net.minecraft.world.level.storage.loot.entries.LootItem import net.minecraft.world.level.storage.loot.entries.LootItem
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.ENERGY_KEY
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.MATTER_STORAGE_KEY
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.REDSTONE_SETTING_KEY
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.REDSTONE_SIGNAL_KEY
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.storage.AbstractStorageImportExport.Companion.FILTER_KEY
import ru.dbotthepony.mc.otm.block.entity.storage.StoragePowerSupplierBlockEntity
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
@ -43,6 +34,7 @@ fun addLootTables(lootTables: LootTables) {
lootTables.createSlabItemTable(MRegistry.FLOOR_TILES_SLAB.blocks.values) { condition(ExplosionCondition.survivesExplosion()) } lootTables.createSlabItemTable(MRegistry.FLOOR_TILES_SLAB.blocks.values) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.CARBON_FIBRE_BLOCK) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.CARBON_FIBRE_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.METAL_MESH) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.TRITANIUM_RAW_BLOCK) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.TRITANIUM_RAW_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_BLOCK) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_WALL) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_WALL) { condition(ExplosionCondition.survivesExplosion()) }
@ -57,6 +49,15 @@ fun addLootTables(lootTables: LootTables) {
lootTables.dropsSelf(MBlocks.DANGER_STRIPE_BLOCK) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.DANGER_STRIPE_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.METAL_BEAM) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.METAL_BEAM) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.TRITANIUM_BARS) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.ENERGY_CABLES.values) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.INFINITE_WATER_SOURCE) { condition(ExplosionCondition.survivesExplosion()) }
lootTables.dropsSelf(MBlocks.ENGINE) { condition(ExplosionCondition.survivesExplosion()) }
for (block in MBlocks.TRITANIUM_ANVIL)
lootTables.dropsSelf(block) { condition(ExplosionCondition.survivesExplosion()) }
for (door in MBlocks.TRITANIUM_TRAPDOOR.values) for (door in MBlocks.TRITANIUM_TRAPDOOR.values)
lootTables.dropsSelf(door) { condition(ExplosionCondition.survivesExplosion()) } lootTables.dropsSelf(door) { condition(ExplosionCondition.survivesExplosion()) }
@ -129,40 +130,42 @@ fun addLootTables(lootTables: LootTables) {
lootPool { item(Items.BLACK_DYE) { setCount(64) } } lootPool { item(Items.BLACK_DYE) { setCount(64) } }
} }
lootTables.tile(MBlocks.COBBLESTONE_GENERATOR)
lootTables.tile(MBlocks.ESSENCE_STORAGE)
lootTables.tile(MBlocks.MATTER_RECONSTRUCTOR)
lootTables.tile(MBlocks.FLUID_TANK)
lootTables.tile(MBlocks.PAINTER)
lootTables.tile(MBlocks.MATTER_ENTANGLER)
lootTables.tile(MBlocks.ENERGY_SERVO) lootTables.tile(MBlocks.ENERGY_SERVO)
lootTables.tile(MBlocks.ENERGY_COUNTER)
lootTables.tile(MBlocks.CHEMICAL_GENERATOR)
lootTables.tile(MBlocks.HOLO_SIGN, "isLocked")
lootTables.tile(MBlocks.STORAGE_CABLE)
lootTables.tile(MBlocks.ANDROID_STATION)
lootTables.tile(MBlocks.ANDROID_CHARGER)
lootTables.tile(MBlocks.BATTERY_BANK)
lootTables.tile(MBlocks.DRIVE_VIEWER)
lootTables.tile(MBlocks.ENERGY_COUNTER, lootTables.tile(MBlocks.STORAGE_BUS)
EnergyCounterBlockEntity.IO_LIMIT_KEY, EnergyCounterBlockEntity.PASSED_ENERGY_KEY, lootTables.tile(MBlocks.STORAGE_IMPORTER)
EnergyCounterBlockEntity.POWER_HISTORY_KEY, EnergyCounterBlockEntity.POWER_HISTORY_POINTER_KEY) lootTables.tile(MBlocks.STORAGE_EXPORTER)
lootTables.tile(MBlocks.STORAGE_POWER_SUPPLIER)
lootTables.tile(MBlocks.DRIVE_RACK)
lootTables.tile(MBlocks.CHEMICAL_GENERATOR, lootTables.tile(MBlocks.MATTER_DECOMPOSER)
ChemicalGeneratorBlockEntity.WORK_TICKS_KEY, lootTables.tile(MBlocks.MATTER_REPLICATOR)
ChemicalGeneratorBlockEntity.WORK_TICKS_TOTAL_KEY, lootTables.tile(MBlocks.MATTER_RECYCLER)
ENERGY_KEY, lootTables.tile(MBlocks.MATTER_SCANNER)
REDSTONE_SIGNAL_KEY, lootTables.tile(MBlocks.PLATE_PRESS)
REDSTONE_SETTING_KEY, lootTables.tile(MBlocks.TWIN_PLATE_PRESS)
)
lootTables.dropsSelf(MBlocks.STORAGE_CABLE) lootTables.tile(MBlocks.POWERED_FURNACE)
lootTables.poweredTile(MBlocks.ANDROID_STATION) lootTables.tile(MBlocks.POWERED_SMOKER)
lootTables.basicTile(MBlocks.BATTERY_BANK) lootTables.tile(MBlocks.POWERED_BLAST_FURNACE)
lootTables.poweredTile(MBlocks.DRIVE_VIEWER)
lootTables.poweredTile(MBlocks.STORAGE_BUS, TileNbtCopy(FILTER_KEY)) lootTables.tile(MBlocks.MATTER_PANEL)
lootTables.poweredTile(MBlocks.STORAGE_IMPORTER, TileNbtCopy(FILTER_KEY)) lootTables.tile(MBlocks.PATTERN_STORAGE)
lootTables.poweredTile(MBlocks.STORAGE_EXPORTER, TileNbtCopy(FILTER_KEY)) lootTables.tile(MBlocks.MATTER_CAPACITOR_BANK)
lootTables.poweredTile(MBlocks.STORAGE_POWER_SUPPLIER, TileNbtCopy(StoragePowerSupplierBlockEntity.POWER_PASSED_KEY)) lootTables.tile(MBlocks.MATTER_BOTTLER)
lootTables.poweredTile(MBlocks.DRIVE_RACK)
lootTables.matterWorkerTile(MBlocks.MATTER_DECOMPOSER)
lootTables.matterWorkerTile(MBlocks.MATTER_REPLICATOR)
lootTables.matterWorkerTile(MBlocks.MATTER_RECYCLER)
lootTables.workerTile(MBlocks.MATTER_SCANNER)
lootTables.workerTile(MBlocks.PLATE_PRESS)
lootTables.basicTile(MBlocks.MATTER_PANEL, TileNbtCopy("tasks"))
lootTables.basicTile(MBlocks.PATTERN_STORAGE)
lootTables.basicTile(MBlocks.MATTER_CAPACITOR_BANK)
lootTables.poweredTile(MBlocks.MATTER_BOTTLER,
TileNbtCopy(MATTER_STORAGE_KEY), TileNbtCopy(MatterBottlerBlockEntity.IS_BOTTLING_KEY))
} }

View File

@ -9,30 +9,5 @@ fun addBlockModels(provider: MatteryBlockModelProvider) {
resourceCubeAll(MBlocks.TRITANIUM_RAW_BLOCK) resourceCubeAll(MBlocks.TRITANIUM_RAW_BLOCK)
resourceCubeAll(MBlocks.DEEPSLATE_TRITANIUM_ORE) resourceCubeAll(MBlocks.DEEPSLATE_TRITANIUM_ORE)
resourceCubeAll(MBlocks.TRITANIUM_INGOT_BLOCK) resourceCubeAll(MBlocks.TRITANIUM_INGOT_BLOCK)
exec {
copy("block/battery/battery1", "block/battery/battery0").also { it.offset(-4f, 0f, 0f) }
copy("block/battery/battery2", "block/battery/battery0").also { it.offset(-8f, 0f, 0f) }
copy("block/battery/battery3", "block/battery/battery0").also { it.offset(0f, 6f, 0f) }
copy("block/battery/battery4", "block/battery/battery0").also { it.offset(-4f, 6f, 0f) }
copy("block/battery/battery5", "block/battery/battery0").also { it.offset(-8f, 6f, 0f) }
copy("block/battery/battery7", "block/battery/battery6").also { it.offset(4f, 0f, 0f) }
copy("block/battery/battery8", "block/battery/battery6").also { it.offset(8f, 0f, 0f) }
copy("block/battery/battery9", "block/battery/battery6").also { it.offset(0f, 6f, 0f) }
copy("block/battery/battery10", "block/battery/battery6").also { it.offset(4f, 6f, 0f) }
copy("block/battery/battery11", "block/battery/battery6").also { it.offset(8f, 6f, 0f) }
for (i in 0 .. 11) {
withExistingParent("block/battery/matter_capacitor$i", ResourceLocation(ru.dbotthepony.mc.otm.datagen.DataGen.MOD_ID, "block/battery/battery$i"))
.texture("1", "block/matterybank_core")
}
for (i in 1 .. 7) {
copy("block/pattern/model$i", "block/pattern/model0").also { it.offset(-2f * i, 0f, 0f) }
}
}
} }
} }

View File

@ -1,163 +0,0 @@
package ru.dbotthepony.mc.otm.datagen.models
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.mojang.math.Vector3f
import net.minecraft.client.renderer.block.model.BlockModel
import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation
import net.minecraftforge.client.model.generators.ModelBuilder
import net.minecraftforge.common.data.ExistingFileHelper
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
data class TextureSize(val width: Float, val height: Float) {
constructor(arr: JsonArray) : this(arr[0].asFloat, arr[1].asFloat)
init {
require(width > 0f) { "Invalid width $width" }
require(height > 0f) { "Invalid width $height" }
}
}
class MatteryModelBuilder(resourceLocation: ResourceLocation, existingFileHelper: ExistingFileHelper) : ModelBuilder<MatteryModelBuilder>(resourceLocation, existingFileHelper) {
var textureSize: TextureSize? = null
fun fromJson(input: JsonObject) {
input["parent"]?.let {
parent(ExistingModelFile(ResourceLocation(it.asString), existingFileHelper))
}
input["ambientocclusion"]?.let {
ambientOcclusion = it.asBoolean
}
input["gui_light"]?.let {
guiLight = BlockModel.GuiLight.valueOf(it.asString)
}
(input["texture_size"] as? JsonArray)?.let {
textureSize = TextureSize(it)
}
(input["textures"] as? JsonObject)?.let {
for ((k, v) in it.entrySet()) {
texture(k, v.asString)
}
}
(input["elements"] as? JsonArray)?.let {
var i = -1
for (value in it) {
i++
check(value is JsonObject) { "Encountered invalid element at $i" }
element().fromJson(value)
}
}
}
override fun toJson(): JsonObject {
return super.toJson().also {
val textureSize = textureSize
if (textureSize != null) {
it["texture_size"] = JsonArray().also {
it.add(textureSize.width)
it.add(textureSize.height)
}
}
}
}
override fun element(): MatteryModelElement {
check(customLoader == null) { "Can not use custom loaders and elements at the same time" }
return MatteryModelElement().also(elements::add)
}
override fun element(index: Int): MatteryModelElement {
return super.element(index) as MatteryModelElement
}
fun offset(x: Float, y: Float, z: Float) {
for (element in elements) {
(element as MatteryModelElement).offset(x, y, z)
}
}
fun offset(value: Vector3f) {
for (element in elements) {
(element as MatteryModelElement).offset(value)
}
}
inner class MatteryModelElement : ElementBuilder() {
private var from: Vector3f = Vector3f()
private var to: Vector3f = Vector3f(16f, 16f, 16f)
fun from(value: Vector3f) = from(value.x(), value.y(), value.z())
fun to(value: Vector3f) = to(value.x(), value.y(), value.z())
override fun from(x: Float, y: Float, z: Float): MatteryModelElement {
from = Vector3f(x, y, z)
super.from(x, y, z)
return this
}
override fun to(x: Float, y: Float, z: Float): MatteryModelElement {
to = Vector3f(x, y, z)
super.to(x, y, z)
return this
}
fun offset(x: Float, y: Float, z: Float): MatteryModelElement {
from(x + from.x(), y + from.y(), z + from.z())
return to(x + to.x(), y + to.y(), z + to.z())
}
fun offset(value: Vector3f) = offset(value.x(), value.y(), value.z())
fun fromJson(input: JsonObject) {
val from = input["from"] as JsonArray
val to = input["to"] as JsonArray
from(from[0].asFloat, from[1].asFloat, from[2].asFloat)
to(to[0].asFloat, to[1].asFloat, to[2].asFloat)
(input["faces"] as? JsonObject)?.let {
for ((k, v) in it.entrySet()) {
with(face(Direction.valueOf(k.uppercase()))) {
check(v is JsonObject) { "Element has invalid face at $k" }
(v["uv"] as? JsonArray)?.also { uv ->
check(uv.size() == 4) { "Element at $k has invalid number of uvs ${uv.size()}" }
uvs(uv[0].asFloat, uv[1].asFloat, uv[2].asFloat, uv[3].asFloat)
}
(v["rotation"] as? JsonPrimitive)?.also { rotation ->
when (rotation.asInt) {
90 -> rotation(FaceRotation.CLOCKWISE_90)
-90, 270 -> rotation(FaceRotation.COUNTERCLOCKWISE_90)
180, -180 -> rotation(FaceRotation.UPSIDE_DOWN)
else -> rotation(FaceRotation.ZERO)
}
}
(v["emissivity"] as? JsonPrimitive)?.asInt?.also { emissivity ->
emissivity(emissivity)
}
(v["ao"] as? JsonPrimitive)?.asBoolean?.also { ao ->
ao(ao)
}
(v["texture"] as? JsonPrimitive)?.also {
texture(it.asString)
}
}
}
}
}
}
}

View File

@ -1,49 +1,17 @@
package ru.dbotthepony.mc.otm.datagen.models package ru.dbotthepony.mc.otm.datagen.models
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.PackType
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.DoorBlock import net.minecraftforge.client.model.generators.BlockModelProvider
import net.minecraftforge.client.model.generators.ModelProvider
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation
import java.util.LinkedList import java.util.LinkedList
private typealias Callback = (MatteryModelProvider) -> Unit class MatteryBlockModelProvider(event: GatherDataEvent) : BlockModelProvider(event.generator.packOutput, DataGen.MOD_ID, event.existingFileHelper) {
private val callbacks = LinkedList<(MatteryBlockModelProvider) -> Unit>()
sealed class MatteryModelProvider(event: GatherDataEvent, folder: String) : ModelProvider<MatteryModelBuilder>(event.generator, DataGen.MOD_ID, folder, ::MatteryModelBuilder, event.existingFileHelper) { fun exec(callback: (MatteryBlockModelProvider) -> Unit) {
private fun extendWithFolder(rl: ResourceLocation): ResourceLocation {
return if (rl.path.contains("/")) rl else ResourceLocation(rl.namespace, folder + "/" + rl.path)
}
fun copy(destination: String, source: String): MatteryModelBuilder {
val destinationLocation = extendWithFolder(if (destination.contains(":")) ResourceLocation(destination) else ResourceLocation(modid, destination))
val sourceLocation = extendWithFolder(if (source.contains(":")) ResourceLocation("models/$source.json") else ResourceLocation(modid, "models/$source.json"))
check(!generatedModels.containsKey(destinationLocation)) { "Model provider already contains model $destinationLocation" }
existingFileHelper.trackGenerated(destinationLocation, MODEL)
return factory.apply(destinationLocation).also {
generatedModels[destinationLocation] = it
val resource = existingFileHelper.getResource(sourceLocation, PackType.CLIENT_RESOURCES)
val stream = resource.open()
val reader = stream.reader()
try {
it.fromJson(JsonParser.parseReader(reader) as JsonObject)
} finally {
reader.close()
stream.close()
}
}
}
private val callbacks = LinkedList<Callback>()
fun exec(callback: Callback) {
callbacks.add(callback) callbacks.add(callback)
} }
@ -52,9 +20,7 @@ sealed class MatteryModelProvider(event: GatherDataEvent, folder: String) : Mode
callback(this) callback(this)
} }
} }
}
class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(event, BLOCK_FOLDER) {
override fun getName(): String { override fun getName(): String {
return "Block Models: $modid" return "Block Models: $modid"
} }
@ -62,7 +28,7 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun decorativeGlassAll(blocks: Collection<Block>) { fun decorativeGlassAll(blocks: Collection<Block>) {
for (block in blocks) { for (block in blocks) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/decorative/${block.registryName!!.path}")).renderType("translucent") cubeAll(block.registryName!!.path, modLocation("block/decorative/${block.registryName!!.path}")).renderType("translucent")
} }
} }
} }
@ -70,7 +36,7 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun decorativeGlassAll(vararg blocks: Block) { fun decorativeGlassAll(vararg blocks: Block) {
for (block in blocks) { for (block in blocks) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/decorative/${block.registryName!!.path}")).renderType("translucent") cubeAll(block.registryName!!.path, modLocation("block/decorative/${block.registryName!!.path}")).renderType("translucent")
} }
} }
} }
@ -78,7 +44,7 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun decorativeCubeAll(vararg blocks: Block) { fun decorativeCubeAll(vararg blocks: Block) {
for (block in blocks) { for (block in blocks) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/decorative/${block.registryName!!.path}")) cubeAll(block.registryName!!.path, modLocation("block/decorative/${block.registryName!!.path}"))
} }
} }
} }
@ -86,7 +52,7 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun decorativeCubeAll(subdir: String, vararg blocks: Block) { fun decorativeCubeAll(subdir: String, vararg blocks: Block) {
for (block in blocks) { for (block in blocks) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/decorative/${subdir}/${block.registryName!!.path}")) cubeAll(block.registryName!!.path, modLocation("block/decorative/${subdir}/${block.registryName!!.path}"))
} }
} }
} }
@ -94,7 +60,7 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun decorativeCubeAll(subdir: String, suffix: String, vararg blocks: Block) { fun decorativeCubeAll(subdir: String, suffix: String, vararg blocks: Block) {
for (block in blocks) { for (block in blocks) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/decorative/${subdir}/${block.registryName!!.path}$suffix")) cubeAll(block.registryName!!.path, modLocation("block/decorative/${subdir}/${block.registryName!!.path}$suffix"))
} }
} }
} }
@ -102,20 +68,20 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun decorativeCubeAll(blocks: Collection<Block>) { fun decorativeCubeAll(blocks: Collection<Block>) {
for (block in blocks) { for (block in blocks) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/decorative/${block.registryName!!.path}")) cubeAll(block.registryName!!.path, modLocation("block/decorative/${block.registryName!!.path}"))
} }
} }
} }
fun decorativeCubeAll(block: Block, texture: String) { fun decorativeCubeAll(block: Block, texture: String) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/decorative/$texture")) cubeAll(block.registryName!!.path, modLocation("block/decorative/$texture"))
} }
} }
fun column(block: Block, end: String, side: String) { fun column(block: Block, end: String, side: String) {
exec { exec {
cubeColumn(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, end), ResourceLocation(DataGen.MOD_ID, side)) cubeColumn(block.registryName!!.path, modLocation(end), modLocation(side))
} }
} }
@ -126,7 +92,7 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun resourceCubeAll(vararg blocks: Block) { fun resourceCubeAll(vararg blocks: Block) {
for (block in blocks) { for (block in blocks) {
exec { exec {
cubeAll(block.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/resource/${block.registryName!!.path}")) cubeAll(block.registryName!!.path, modLocation("block/resource/${block.registryName!!.path}"))
} }
} }
} }

View File

@ -1,16 +0,0 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.SimpleCookingRecipeBuilder
import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
import java.util.function.Consumer
fun addBlastingRecipes(consumer: Consumer<FinishedRecipe>) {
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItems.MIRROR_COMPOUND), MItems.MIRROR, 0.1f, 100).unlockedBy(MItems.MIRROR_COMPOUND).save(consumer)
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_PLATES), MItems.TRITANIUM_INGOT, 0f, 100).unlockedBy(MItemTags.TRITANIUM_PLATES).save(consumer, modLocation("tritanium_ingot_from_plates"))
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_PLATES), MItems.TRITANIUM_INGOT, 0f, 50).unlockedBy(MItemTags.TRITANIUM_PLATES).save(consumer, modLocation("tritanium_ingot_from_plates_blasting"))
}

View File

@ -0,0 +1,55 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.SimpleCookingRecipeBuilder
import net.minecraft.util.valueproviders.ConstantFloat
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
private fun RecipeOutput.addRecyclingRecipe(inputs: Collection<ItemLike>, result: Item, name: String) {
val inputStacks = inputs.map(::ItemStack)
SimpleCookingRecipeBuilder.smelting(
Ingredient.of(inputStacks.stream()),
RecipeCategory.MISC, result, 0f, 200
).also { r -> inputs.forEach { r.unlockedBy(it) } }.save(this, modLocation("smelting/${name}"))
SimpleCookingRecipeBuilder.blasting(
Ingredient.of(inputStacks.stream()),
RecipeCategory.MISC, result, 0f, 100
).also { r -> inputs.forEach { r.unlockedBy(it) } }.save(this, modLocation("blasting/${name}"))
}
fun addBlastingRecipes(consumer: RecipeOutput) {
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItems.MIRROR_COMPOUND), RecipeCategory.MISC, MItems.MIRROR, 0.1f, 100).unlockedBy(
MItems.MIRROR_COMPOUND).save(consumer)
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_PLATES), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 0f, 100).unlockedBy(
MItemTags.TRITANIUM_PLATES).save(consumer, modLocation("tritanium_ingot_from_plates"))
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_PLATES), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 0f, 50).unlockedBy(
MItemTags.TRITANIUM_PLATES).save(consumer, modLocation("tritanium_ingot_from_plates_blasting"))
consumer.addRecyclingRecipe(MItems.TRITANIUM_TOOLS, MItems.TRITANIUM_NUGGET, "tritanium_nugget_from_tools")
consumer.addRecyclingRecipe(MItems.SIMPLE_TRITANIUM_ARMOR, MItems.TRITANIUM_NUGGET, "tritanium_nugger_from_armor")
}
fun addOreSmeltingRecipes(consumer: RecipeOutput) {
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_ORES), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 1f, 200).unlockedBy(MItemTags.TRITANIUM_ORES).save(consumer, modLocation("smelting/tritanium_ingot_from_ore_block"))
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_ORES), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 1f, 100).unlockedBy(MItemTags.TRITANIUM_ORES).save(consumer, modLocation("blasting/tritanium_ingot_from_ore_block"))
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_ORE_CLUMPS), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 1f, 200).unlockedBy(MItemTags.TRITANIUM_ORE_CLUMPS).save(consumer, modLocation("smelting/tritanium_ingot_from_raw_ore"))
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_ORE_CLUMPS), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 1f, 100).unlockedBy(MItemTags.TRITANIUM_ORE_CLUMPS).save(consumer, modLocation("blasting/tritanium_ingot_from_raw_ore"))
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_DUSTS), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 0f, 200).unlockedBy(MItemTags.TRITANIUM_DUSTS).save(consumer, modLocation("smelting/tritanium_ingot_from_dust"))
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_DUSTS), RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 0f, 100).unlockedBy(MItemTags.TRITANIUM_DUSTS).save(consumer, modLocation("blasting/tritanium_ingot_from_dust"))
}
fun addMicrowaveRecipes(provider: MatteryRecipeProvider) {
provider.microwave("pattern_drive_normal_erase", Ingredient.of(MItems.PATTERN_DRIVE_NORMAL), Ingredient.of(MItems.PATTERN_DRIVE_NORMAL), workTicks = 30 * 20, experience = ConstantFloat.of(0f))
}

View File

@ -1,51 +1,60 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.ShapelessRecipeBuilder import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.tags.ItemTags import net.minecraft.tags.ItemTags
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import java.util.function.Consumer import ru.dbotthepony.mc.otm.recipe.ExplosiveHammerPrimingRecipe
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) { fun addCraftingTableRecipes(consumer: RecipeOutput) {
MatteryRecipe(MRegistry.CARGO_CRATES.item) val machinesCategory = RecipeCategory.DECORATIONS
.row(MItemTags.TRITANIUM_PLATES, Tags.Items.CHESTS, MItemTags.TRITANIUM_PLATES)
MatteryRecipe(MRegistry.CARGO_CRATES.item, category = RecipeCategory.DECORATIONS)
.row(MItemTags.TRITANIUM_PLATES, multiIngredient(Tags.Items.CHESTS_WOODEN, Tags.Items.BARRELS_WOODEN), MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItemTags.TRITANIUM_PLATES) .unlockedBy(MItemTags.TRITANIUM_PLATES)
.unlockedBy(Tags.Items.CHESTS) .unlockedBy(Tags.Items.CHESTS)
.build(consumer) .build(consumer)
for ((dye, crate) in MRegistry.CARGO_CRATES.blocks) { for ((dye, crate) in MRegistry.CARGO_CRATES.blocks) {
ShapelessRecipeBuilder(crate, 1) ShapelessRecipeBuilder(RecipeCategory.DECORATIONS, crate, 1)
.requires(Ingredient.of(MRegistry.CARGO_CRATES.allItems.entries.stream().filter { it.key != dye }.map { ItemStack(it.value) })) .requires(Ingredient.of(MRegistry.CARGO_CRATES.allItems.entries.stream().filter { it.key != dye }.map { ItemStack(it.value) }))
.requires(dye.tag) .requires(dye.tag)
.unlockedBy(MRegistry.CARGO_CRATES.allItems.entries.stream().filter { it.key != dye }.map { it.value }) .unlockedBy(MRegistry.CARGO_CRATES.allItems.entries.stream().filter { it.key != dye }.map { it.value })
.save(consumer, "${crate.registryName}_alt") .save(consumer, "${crate.registryName}_alt")
} }
ShapelessRecipeBuilder(MItems.TRITANIUM_INGOT_BLOCK, 1) ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, MItems.TRITANIUM_INGOT_BLOCK, 1)
.requires(Ingredient.of(MItemTags.TRITANIUM_INGOTS), 9) .requires(Ingredient.of(MItemTags.TRITANIUM_INGOTS), 9)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.save(consumer) .save(consumer)
ShapelessRecipeBuilder(MItems.TRITANIUM_INGOT, 9) ShapelessRecipeBuilder(RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 9)
.requires(Ingredient.of(MItemTags.TRITANIUM_INGOTS_STORAGE)) .requires(Ingredient.of(MItemTags.TRITANIUM_INGOTS_STORAGE))
.unlockedBy(MItemTags.TRITANIUM_INGOTS_STORAGE) .unlockedBy(MItemTags.TRITANIUM_INGOTS_STORAGE)
.save(consumer, modLocation("tritanium_ingot_from_storage")) .save(consumer, modLocation("tritanium_ingot_from_storage"))
ShapelessRecipeBuilder(MItems.ENERGY_COUNTER, 1) ShapelessRecipeBuilder(machinesCategory, MItems.ENERGY_COUNTER, 1)
.requires(MItems.ENERGY_COUNTER) .requires(MItems.ENERGY_COUNTER)
.unlockedBy(MItems.ENERGY_COUNTER) .unlockedBy(MItems.ENERGY_COUNTER)
.save(consumer, modLocation("energy_counter_reset")) .save(consumer, modLocation("energy_counter_reset"))
MatteryRecipe(MBlocks.PLATE_PRESS) ShapelessRecipeBuilder(machinesCategory, MItems.HOLO_SIGN, 1)
.requires(MItems.HOLO_SIGN)
.unlockedBy(MItems.HOLO_SIGN)
.save(consumer, modLocation("holo_sign_reset"))
MatteryRecipe(MBlocks.PLATE_PRESS, category = machinesCategory)
.row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS) .row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS)
.row(MItemTags.TRITANIUM_INGOTS, Items.BLAST_FURNACE, MItemTags.TRITANIUM_INGOTS) .row(MItemTags.TRITANIUM_INGOTS, Items.BLAST_FURNACE, MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.PISTONS, MItemTags.TRITANIUM_INGOTS, MItemTags.PISTONS) .row(MItemTags.PISTONS, MItemTags.TRITANIUM_INGOTS, MItemTags.PISTONS)
@ -53,14 +62,23 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.unlockedBy(MItems.ELECTRIC_PARTS) .unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer) .build(consumer)
MatteryRecipe(MBlocks.PLATE_PRESS) MatteryRecipe(MBlocks.PLATE_PRESS, category = machinesCategory)
.rowB(MItemTags.PISTONS)
.rowB(MItems.MACHINE_FRAME) .rowB(MItems.MACHINE_FRAME)
.rowAC(MItemTags.PISTONS, MItemTags.PISTONS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItems.ELECTRIC_PARTS) .unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer, "advanced") .build(consumer, "advanced")
MatteryRecipe(MItems.PATTERN_DRIVE_NORMAL) MatteryRecipe(MBlocks.TWIN_PLATE_PRESS, category = machinesCategory)
.setUpgradeSource(MItems.PLATE_PRESS)
.addUpgradeOps(UpgradeRecipe.Direct("BlockEntityTag"))
.rowB(MItemTags.PISTONS)
.rowB(MItems.PLATE_PRESS)
.rowB(MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.PLATE_PRESS)
.build(consumer)
MatteryRecipe(MItems.PATTERN_DRIVE_NORMAL, category = machinesCategory)
.rowAC(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT) .rowAC(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT)
.row(MItemTags.ADVANCED_CIRCUIT, MItemTags.TRITANIUM_PLATES, MItemTags.ADVANCED_CIRCUIT) .row(MItemTags.ADVANCED_CIRCUIT, MItemTags.TRITANIUM_PLATES, MItemTags.ADVANCED_CIRCUIT)
.rowAC(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT) .rowAC(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT)
@ -68,7 +86,7 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.build(consumer) .build(consumer)
// Машины // Машины
MatteryRecipe(MItems.MATTER_RECYCLER) MatteryRecipe(MItems.MATTER_RECYCLER, category = machinesCategory)
.row(MItems.MATTER_CAPACITOR_PARTS, Items.HOPPER, MItemTags.BASIC_CIRCUIT) .row(MItems.MATTER_CAPACITOR_PARTS, Items.HOPPER, MItemTags.BASIC_CIRCUIT)
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
.row(MItems.MATTER_CABLE, MItems.MATTER_IO_PORT, MItems.MATTER_CABLE) .row(MItems.MATTER_CABLE, MItems.MATTER_IO_PORT, MItems.MATTER_CABLE)
@ -76,21 +94,21 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.build(consumer) .build(consumer)
// Блоки // Блоки
MatteryRecipe(MItems.MATTER_CAPACITOR_BANK) MatteryRecipe(MItems.MATTER_CAPACITOR_BANK, category = machinesCategory)
.row(Tags.Items.GLASS, MItemTags.IRON_PLATES, Tags.Items.GLASS) .row(Tags.Items.GLASS, MItemTags.IRON_PLATES, Tags.Items.GLASS)
.row(MItemTags.IRON_PLATES, MItems.MACHINE_FRAME, MItemTags.IRON_PLATES) .row(MItemTags.IRON_PLATES, MItems.MACHINE_FRAME, MItemTags.IRON_PLATES)
.row(MItems.MATTER_CABLE, MItems.MATTER_IO_PORT, MItems.MATTER_CABLE) .row(MItems.MATTER_CABLE, MItems.MATTER_IO_PORT, MItems.MATTER_CABLE)
.unlockedBy(MItems.MATTER_CABLE) .unlockedBy(MItems.MATTER_CABLE)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.BATTERY_BANK) MatteryRecipe(MItems.BATTERY_BANK, category = machinesCategory)
.row(Tags.Items.GLASS, MItemTags.IRON_PLATES, Tags.Items.GLASS) .row(Tags.Items.GLASS, MItemTags.IRON_PLATES, Tags.Items.GLASS)
.row(MItemTags.IRON_PLATES, MItems.MACHINE_FRAME, MItemTags.IRON_PLATES) .row(MItemTags.IRON_PLATES, MItems.MACHINE_FRAME, MItemTags.IRON_PLATES)
.row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS) .row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS)
.unlockedBy(MItems.ENERGY_BUS) .unlockedBy(MItems.ENERGY_BUS)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.GRAVITATION_STABILIZER) MatteryRecipe(MItems.GRAVITATION_STABILIZER, category = machinesCategory)
.row(MItemTags.ADVANCED_CIRCUIT, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.ADVANCED_CIRCUIT) .row(MItemTags.ADVANCED_CIRCUIT, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.ADVANCED_CIRCUIT)
.row(MItems.MATTER_TRANSFORM_MATRIX, MItems.MACHINE_FRAME, MItems.MATTER_TRANSFORM_MATRIX) .row(MItems.MATTER_TRANSFORM_MATRIX, MItems.MACHINE_FRAME, MItems.MATTER_TRANSFORM_MATRIX)
.row(MItemTags.TRITANIUM_PLATES, MItems.GRAVITATION_FIELD_LIMITER, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.GRAVITATION_FIELD_LIMITER, MItemTags.TRITANIUM_PLATES)
@ -98,7 +116,7 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.unlockedBy(MItems.GRAVITATION_FIELD_SENSOR) .unlockedBy(MItems.GRAVITATION_FIELD_SENSOR)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.PORTABLE_GRAVITATION_STABILIZER) MatteryRecipe(MItems.PORTABLE_GRAVITATION_STABILIZER, category = RecipeCategory.COMBAT)
.rowB(MItemTags.TRITANIUM_PLATES) .rowB(MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItems.GRAVITATION_FIELD_LIMITER, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.GRAVITATION_FIELD_LIMITER, MItemTags.TRITANIUM_PLATES)
@ -106,150 +124,347 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.unlockedBy(MItems.GRAVITATION_FIELD_SENSOR) .unlockedBy(MItems.GRAVITATION_FIELD_SENSOR)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.GRAVITATION_FIELD_SENSOR) MatteryRecipe(MItems.GRAVITATION_FIELD_SENSOR, category = RecipeCategory.MISC)
.rowB(MItemTags.BASIC_CIRCUIT) .rowB(MItemTags.BASIC_CIRCUIT)
.row(MItemTags.TRITANIUM_PLATES, MItems.ELECTROMAGNET, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.ELECTROMAGNET, MItemTags.TRITANIUM_PLATES)
.rowB(MItemTags.IRON_PLATES) .rowB(MItemTags.IRON_PLATES)
.unlockedBy(MItems.ELECTROMAGNET) .unlockedBy(MItems.ELECTROMAGNET)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.GRAVITATION_FIELD_LIMITER) MatteryRecipe(MItems.GRAVITATION_FIELD_LIMITER, category = RecipeCategory.MISC)
.row(Tags.Items.ENDER_PEARLS, MItemTags.ADVANCED_CIRCUIT, Tags.Items.ENDER_PEARLS) .row(Tags.Items.ENDER_PEARLS, MItemTags.ADVANCED_CIRCUIT, Tags.Items.ENDER_PEARLS)
.row(MItemTags.GOLD_WIRES, MItems.QUANTUM_TRANSCEIVER, MItemTags.GOLD_WIRES) .row(MItemTags.GOLD_WIRES, MItems.QUANTUM_TRANSCEIVER, MItemTags.GOLD_WIRES)
.rowB(MItemTags.TRITANIUM_PLATES) .rowB(MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.QUANTUM_TRANSCEIVER) .unlockedBy(MItems.QUANTUM_TRANSCEIVER)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.BLACK_HOLE_SCANNER) MatteryRecipe(MItems.BLACK_HOLE_SCANNER, category = RecipeCategory.TOOLS)
.row(MItemTags.IRON_PLATES, Tags.Items.GLASS_PANES_COLORLESS, MItemTags.IRON_PLATES) .row(MItemTags.IRON_PLATES, Tags.Items.GLASS_PANES_COLORLESS, MItemTags.IRON_PLATES)
.row(MItemTags.GOLD_WIRES, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.ADVANCED_CIRCUIT) .row(MItemTags.GOLD_WIRES, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.ADVANCED_CIRCUIT)
.rowAC(Tags.Items.DUSTS_GLOWSTONE, MItemTags.TRITANIUM_PLATES) .rowAC(Tags.Items.DUSTS_GLOWSTONE, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.GRAVITATION_FIELD_SENSOR) .unlockedBy(MItems.GRAVITATION_FIELD_SENSOR)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.PHANTOM_ATTRACTOR) MatteryRecipe(MItems.PHANTOM_ATTRACTOR, category = machinesCategory)
.row(Tags.Items.DUSTS_REDSTONE, Tags.Items.GLASS_COLORLESS, Tags.Items.DUSTS_REDSTONE) .row(Tags.Items.DUSTS_REDSTONE, Tags.Items.GLASS_COLORLESS, Tags.Items.DUSTS_REDSTONE)
.row(MItemTags.TRITANIUM_PLATES, MItems.QUANTUM_TRANSCEIVER, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.QUANTUM_TRANSCEIVER, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, ItemTags.BEDS, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, ItemTags.BEDS, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.QUANTUM_TRANSCEIVER) .unlockedBy(MItems.QUANTUM_TRANSCEIVER)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.QUANTUM_TRANSCEIVER, 2) MatteryRecipe(MItems.QUANTUM_TRANSCEIVER, 2, category = RecipeCategory.MISC)
.rowAC(MItemTags.COPPER_WIRES, MItemTags.COPPER_WIRES) .rowAC(MItemTags.COPPER_WIRES, MItemTags.COPPER_WIRES)
.row(MItemTags.GOLD_WIRES, Tags.Items.ENDER_PEARLS, MItemTags.GOLD_WIRES) .row(MItemTags.GOLD_WIRES, Tags.Items.ENDER_PEARLS, MItemTags.GOLD_WIRES)
.row(MItemTags.GOLD_WIRES, MItems.ELECTROMAGNET, MItemTags.GOLD_WIRES) .row(MItemTags.GOLD_WIRES, MItems.ELECTROMAGNET, MItemTags.GOLD_WIRES)
.unlockedBy(Tags.Items.ENDER_PEARLS) .unlockedBy(Tags.Items.ENDER_PEARLS)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.ELECTROMAGNET) MatteryRecipe(MItems.ELECTROMAGNET, category = RecipeCategory.MISC)
.row(MItemTags.COPPER_WIRES, Tags.Items.INGOTS_IRON, MItemTags.COPPER_WIRES) .row(MItemTags.COPPER_WIRES, Tags.Items.INGOTS_IRON, MItemTags.COPPER_WIRES)
.unlockedBy(Tags.Items.ENDER_PEARLS) .unlockedBy(Tags.Items.INGOTS_IRON)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.ENERGY_SERVO) MatteryRecipe(MItems.ELECTROMOTOR, category = RecipeCategory.MISC)
.rowB(MItems.ELECTROMAGNET)
.row(MItems.ELECTROMAGNET, Tags.Items.INGOTS_IRON, MItems.ELECTROMAGNET)
.row(MItemTags.COPPER_WIRES, Tags.Items.INGOTS_IRON, MItemTags.COPPER_WIRES)
.unlockedBy(MItems.ELECTROMAGNET)
.build(consumer)
MatteryRecipe(MItems.ENERGY_SERVO, category = RecipeCategory.MISC)
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItems.ENERGY_BUS, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.ENERGY_BUS, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.ENERGY_BUS) .unlockedBy(MItems.ENERGY_BUS)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.MIRROR_COMPOUND, 3) MatteryRecipe(MItems.MIRROR_COMPOUND, 3, category = RecipeCategory.MISC)
.row(Tags.Items.GLASS_PANES_COLORLESS, Tags.Items.GLASS_PANES_COLORLESS, Tags.Items.GLASS_PANES_COLORLESS) .row(Tags.Items.GLASS_PANES_COLORLESS, Tags.Items.GLASS_PANES_COLORLESS, Tags.Items.GLASS_PANES_COLORLESS)
.row(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES) .row(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES)
.unlockedBy(MItemTags.IRON_PLATES) .unlockedBy(MItemTags.IRON_PLATES)
.unlockedBy(Tags.Items.GLASS_PANES_COLORLESS) .unlockedBy(Tags.Items.GLASS_PANES_COLORLESS)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.REINFORCED_TRITANIUM_PLATE, category = RecipeCategory.MISC)
.rowB(MItemTags.CARBON_PLATES)
.row(MItemTags.CARBON_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.CARBON_PLATES)
.rowB(MItemTags.CARBON_PLATES)
.unlockedBy(MItemTags.TRITANIUM_PLATES)
.build(consumer)
MatteryRecipe(MItems.CARBON_FIBRE_BLOCK, category = RecipeCategory.BUILDING_BLOCKS)
.rowAB(MItemTags.CARBON_PLATES, MItemTags.CARBON_PLATES)
.rowAB(MItemTags.CARBON_PLATES, MItemTags.CARBON_PLATES)
.unlockedBy(MItemTags.CARBON_PLATES)
.build(consumer)
ShapelessRecipeBuilder(RecipeCategory.MISC, MItems.CARBON_MESH, 4)
.requires(Ingredient.of(MItems.CARBON_FIBRE_BLOCK))
.unlockedBy(MItemTags.CARBON_PLATES)
.unlockedBy(MItems.CARBON_FIBRE_BLOCK)
.save(consumer, modLocation("carbon_mesh_from_block"))
// броня // броня
MatteryRecipe(MItems.TRITANIUM_HELMET) MatteryRecipe(MItems.TRITANIUM_HELMET, category = RecipeCategory.COMBAT)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) .setUpgradeSource(Items.LEATHER_HELMET)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES) .addUpgradeOps(
.unlockedBy(MItemTags.TRITANIUM_PLATES) UpgradeRecipe.Direct("display"),
UpgradeRecipe.Direct("Enchantments"),
)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, Items.LEATHER_HELMET, MItemTags.REINFORCED_TRITANIUM_PLATES)
.unlockedBy(MItemTags.REINFORCED_TRITANIUM_PLATES)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.TRITANIUM_PANTS) MatteryRecipe(MItems.TRITANIUM_PANTS, category = RecipeCategory.COMBAT)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) .setUpgradeSource(Items.LEATHER_LEGGINGS)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES) .addUpgradeOps(
.rowAC(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) UpgradeRecipe.Direct("display"),
.unlockedBy(MItemTags.TRITANIUM_PLATES) UpgradeRecipe.Direct("Enchantments"),
)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, Items.LEATHER_LEGGINGS, MItemTags.REINFORCED_TRITANIUM_PLATES)
.rowAC(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.unlockedBy(MItemTags.REINFORCED_TRITANIUM_PLATES)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.TRITANIUM_CHESTPLATE) MatteryRecipe(MItems.TRITANIUM_CHESTPLATE, category = RecipeCategory.COMBAT)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES) .setUpgradeSource(Items.LEATHER_CHESTPLATE)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) .addUpgradeOps(
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) UpgradeRecipe.Direct("display"),
.unlockedBy(MItemTags.TRITANIUM_PLATES) UpgradeRecipe.Direct("Enchantments"),
)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, Items.LEATHER_CHESTPLATE, MItemTags.REINFORCED_TRITANIUM_PLATES)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.unlockedBy(MItemTags.REINFORCED_TRITANIUM_PLATES)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.TRITANIUM_BOOTS) MatteryRecipe(MItems.TRITANIUM_BOOTS, category = RecipeCategory.COMBAT)
.rowAC(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) .setUpgradeSource(Items.LEATHER_BOOTS)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES) .addUpgradeOps(
.unlockedBy(MItemTags.TRITANIUM_PLATES) UpgradeRecipe.Direct("display"),
UpgradeRecipe.Direct("Enchantments"),
)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, Items.LEATHER_BOOTS, MItemTags.REINFORCED_TRITANIUM_PLATES)
.rowAC(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.unlockedBy(MItemTags.REINFORCED_TRITANIUM_PLATES)
.build(consumer)
// простая броня
MatteryRecipe(MItems.SIMPLE_TRITANIUM_HELMET, category = RecipeCategory.COMBAT)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.rowAC(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
MatteryRecipe(MItems.SIMPLE_TRITANIUM_PANTS, category = RecipeCategory.COMBAT)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.rowAC(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.rowAC(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
MatteryRecipe(MItems.SIMPLE_TRITANIUM_CHESTPLATE, category = RecipeCategory.COMBAT)
.rowAC(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
MatteryRecipe(MItems.SIMPLE_TRITANIUM_BOOTS, category = RecipeCategory.COMBAT)
.rowAC(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.rowAC(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer) .build(consumer)
// простые батарейки // простые батарейки
MatteryRecipe(MItems.BATTERY_CRUDE) MatteryRecipe(MItems.BATTERY_CRUDE, category = RecipeCategory.MISC)
.rowB(Tags.Items.DUSTS_REDSTONE) .rowB(Tags.Items.DUSTS_REDSTONE)
.rowB(Tags.Items.CROPS_POTATO) .rowB(Tags.Items.CROPS_POTATO)
.rowB(Tags.Items.INGOTS_IRON) .rowB(Tags.Items.INGOTS_IRON)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.BATTERY_BASIC) MatteryRecipe(MItems.BATTERY_BASIC, category = RecipeCategory.MISC)
.rowAC(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE) .rowAC(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE)
.rowB(MItems.ELECTRIC_PARTS) .rowB(MItems.ELECTRIC_PARTS)
.rowB(MItemTags.IRON_PLATES) .rowB(MItemTags.IRON_PLATES)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.BATTERY_NORMAL) MatteryRecipe(MItems.BATTERY_NORMAL, category = RecipeCategory.MISC)
.rowB(MItems.ELECTRIC_PARTS) .rowB(MItems.ELECTRIC_PARTS)
.row(MItemTags.COPPER_WIRES, MItemTags.IRON_PLATES, MItemTags.COPPER_WIRES) .row(MItemTags.COPPER_WIRES, MItemTags.IRON_PLATES, MItemTags.COPPER_WIRES)
.row(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE) .row(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.BATTERY_DENSE) MatteryRecipe(MItems.BATTERY_DENSE, category = RecipeCategory.MISC)
.row(Tags.Items.DUSTS_REDSTONE, MItems.ENERGY_BUS, Tags.Items.DUSTS_REDSTONE) .row(Tags.Items.DUSTS_REDSTONE, MItems.ENERGY_BUS, Tags.Items.DUSTS_REDSTONE)
.row(MItemTags.GOLD_WIRES, MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES) .row(MItemTags.GOLD_WIRES, MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES)
.row(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE) .row(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.BATTERY_CAPACITOR) MatteryRecipe(MItems.BATTERY_CAPACITOR, category = RecipeCategory.MISC)
.row(Tags.Items.DUSTS_REDSTONE, MItems.ENERGY_BUS, Tags.Items.DUSTS_REDSTONE) .row(Tags.Items.DUSTS_REDSTONE, MItems.ENERGY_BUS, Tags.Items.DUSTS_REDSTONE)
.row(MItemTags.GOLD_WIRES, MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES) .row(MItemTags.GOLD_WIRES, MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES)
.row(MItemTags.GOLD_WIRES, Tags.Items.DUSTS_REDSTONE, MItemTags.GOLD_WIRES) .row(MItemTags.GOLD_WIRES, Tags.Items.DUSTS_REDSTONE, MItemTags.GOLD_WIRES)
.build(consumer) .build(consumer)
// накопители материи // накопители материи
MatteryRecipe(MItems.MATTER_CAPACITOR_DENSE) MatteryRecipe(MItems.MATTER_CAPACITOR_DENSE, category = RecipeCategory.MISC)
.row(MItems.MATTER_CAPACITOR_PARTS, Tags.Items.GLASS, MItems.MATTER_CAPACITOR_PARTS) .row(MItems.MATTER_CAPACITOR_PARTS, Tags.Items.GLASS, MItems.MATTER_CAPACITOR_PARTS)
.row(MItemTags.TRITANIUM_PLATES, Tags.Items.ENDER_PEARLS, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, Tags.Items.ENDER_PEARLS, MItemTags.TRITANIUM_PLATES)
.rowAC(Tags.Items.GEMS_DIAMOND, Tags.Items.GEMS_DIAMOND) .rowAC(Tags.Items.GEMS_DIAMOND, Tags.Items.GEMS_DIAMOND)
.build(consumer) .build(consumer)
// станция андроида // станция андроида
MatteryRecipe(MItems.ANDROID_STATION) MatteryRecipe(MItems.ANDROID_STATION, category = machinesCategory)
.row(MItems.ELECTRIC_PARTS, MItemTags.ADVANCED_CIRCUIT, MItems.ELECTRIC_PARTS) .row(MItems.ELECTRIC_PARTS, MItemTags.ADVANCED_CIRCUIT, MItems.ELECTRIC_PARTS)
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItems.ELECTRIC_PARTS, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItems.ELECTRIC_PARTS, MItemTags.TRITANIUM_PLATES)
.build(consumer) .build(consumer)
// беспроводной зарядник андроидов
MatteryRecipe(MItems.ANDROID_CHARGER, category = machinesCategory)
.row(MItems.ELECTRIC_PARTS, MItems.QUANTUM_TRANSCEIVER, MItems.ELECTRIC_PARTS)
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
.build(consumer)
// Энерго меч // Энерго меч
MatteryRecipe(MItems.ENERGY_SWORD) MatteryRecipe(MItems.ENERGY_SWORD, category = RecipeCategory.COMBAT)
.rowBC(MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES) .rowBC(MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES)
.rowBC(MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES) .rowBC(MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES)
.row(MItems.BATTERY_CAPACITOR, MItems.TRITANIUM_SWORD, MItemTags.ADVANCED_CIRCUIT) .row(MItems.BATTERY_CAPACITOR, MItems.TRITANIUM_SWORD, MItemTags.ADVANCED_CIRCUIT)
.unlockedBy(MItems.BATTERY_CAPACITOR) .unlockedBy(MItems.BATTERY_CAPACITOR)
.buildEnergetic(consumer) .buildEnergetic(consumer)
// лампа
MatteryRecipe(MItems.LABORATORY_LAMP)
.row(MItemTags.IRON_PLATES, MItemTags.HARDENED_GLASS_PANES_COLORLESS, MItemTags.IRON_PLATES)
.row(MItems.MIRROR, Items.GLOWSTONE, MItems.MIRROR)
.row(MItemTags.TRITANIUM_PLATES, Tags.Items.DUSTS_REDSTONE, MItemTags.TRITANIUM_PLATES)
.build(consumer)
// апгрейд на сетку крафта // апгрейд на сетку крафта
MatteryRecipe(MItems.ExopackUpgrades.CRAFTING_UPGRADE) MatteryRecipe(MItems.ExopackUpgrades.CRAFTING_UPGRADE, category = RecipeCategory.TOOLS)
.row(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT) .row(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT)
.row(MItemTags.CRAFTING_TABLES, MItems.QUANTUM_TRANSCEIVER, MItemTags.CRAFTING_TABLES) .row(MItemTags.CRAFTING_TABLES, MItems.QUANTUM_TRANSCEIVER, MItemTags.CRAFTING_TABLES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.build(consumer) .build(consumer)
// апгрейд на переплавку
MatteryRecipe(MItems.ExopackUpgrades.SMELTING_UPGRADE, category = RecipeCategory.TOOLS)
.row(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT)
.row(Items.FURNACE, MItems.QUANTUM_TRANSCEIVER, Items.FURNACE)
.row(MItemTags.TRITANIUM_PLATES, Items.FURNACE, MItemTags.TRITANIUM_PLATES)
.build(consumer)
// апгрейд на эндер сундук
MatteryRecipe(MItems.ExopackUpgrades.ENDER_UPGRADE, category = RecipeCategory.TOOLS)
.row(MItemTags.ADVANCED_CIRCUIT, MItems.ELECTROMAGNET, MItemTags.ADVANCED_CIRCUIT)
.row(MItems.ELECTROMAGNET, Items.ENDER_CHEST, MItems.ELECTROMAGNET)
.row(MItemTags.TRITANIUM_PLATES, MItems.ELECTROMAGNET, MItemTags.TRITANIUM_PLATES)
.build(consumer)
// генератор коблы
MatteryRecipe(MItems.COBBLESTONE_GENERATOR, category = machinesCategory)
.row(MItemTags.HARDENED_GLASS_COLORLESS, MItems.TRITANIUM_PICKAXE, MItemTags.HARDENED_GLASS_COLORLESS)
.row(Items.LAVA_BUCKET, Items.HOPPER, Items.WATER_BUCKET)
.rowB(Tags.Items.CHESTS)
.build(consumer)
MatteryRecipe(MItems.TRITANIUM_SHEARS, category = RecipeCategory.TOOLS)
.rowB(MItemTags.TRITANIUM_INGOTS)
.rowA(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
MatteryRecipe(MItems.TRITANIUM_SHIELD, category = RecipeCategory.COMBAT)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, Items.SHIELD, MItemTags.REINFORCED_TRITANIUM_PLATES)
.row(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.rowB(MItemTags.REINFORCED_TRITANIUM_PLATES)
.build(consumer)
ShapelessRecipeBuilder(RecipeCategory.MISC, MItems.TRITANIUM_NUGGET, 9)
.requires(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_NUGGETS)
.save(consumer)
ShapelessRecipeBuilder(RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 1)
.requires(Ingredient.of(MItemTags.TRITANIUM_NUGGETS), 9)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_NUGGETS)
.save(consumer, modLocation("ingot_from_nuggets"))
MatteryRecipe(MItems.ESSENCE_STORAGE, category = machinesCategory)
.row(MItems.MATTER_CAPACITOR_PARTS, Items.ENDER_EYE, MItemTags.ADVANCED_CIRCUIT)
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.GOLD_WIRES, MItemTags.HARDENED_GLASS, MItemTags.HARDENED_GLASS)
.build(consumer)
MatteryRecipe(MItems.ESSENCE_SERVO, category = RecipeCategory.TOOLS)
.row(MItemTags.TRITANIUM_PLATES, MItems.QUANTUM_TRANSCEIVER, MItemTags.TRITANIUM_PLATES)
.rowB(Tags.Items.RODS_WOODEN)
.rowB(Tags.Items.RODS_WOODEN)
.build(consumer)
MatteryRecipe(MItems.MATTER_RECONSTRUCTOR, category = machinesCategory)
.setUpgradeSource(MItems.MATTER_REPLICATOR)
.addUpgradeOps(
UpgradeRecipe.Indirect("BlockEntityTag.${MatteryBlockEntity.ENERGY_KEY}", "BlockEntityTag.energy"),
UpgradeRecipe.Indirect("BlockEntityTag.${MatteryBlockEntity.MATTER_STORAGE_KEY}", "BlockEntityTag.matter"),
)
.row(MItemTags.ADVANCED_CIRCUIT, Tags.Items.GEMS_EMERALD, MItemTags.ADVANCED_CIRCUIT)
.row(MItems.ELECTRIC_PARTS, MItems.MATTER_REPLICATOR, MItems.ELECTRIC_PARTS)
.row(MItems.ELECTROMAGNET, MItems.ELECTROMAGNET, MItems.ELECTROMAGNET)
.build(consumer)
MatteryRecipe(MItems.FLUID_CAPSULE, category = RecipeCategory.TOOLS, count = 8)
.row(MItemTags.TRITANIUM_NUGGETS, MItemTags.TRITANIUM_NUGGETS, MItemTags.TRITANIUM_NUGGETS)
.rowB(MItemTags.HARDENED_GLASS_PANES)
.row(MItemTags.TRITANIUM_NUGGETS, MItemTags.TRITANIUM_NUGGETS, MItemTags.TRITANIUM_NUGGETS)
.unlockedBy(MItemTags.HARDENED_GLASS_PANES)
.unlockedBy(MItemTags.TRITANIUM_NUGGETS)
.build(consumer)
MatteryRecipe(MItems.FLUID_TANK, category = RecipeCategory.DECORATIONS)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.HARDENED_GLASS_PANES, MItemTags.TRITANIUM_INGOTS)
.rowAC(MItemTags.HARDENED_GLASS_PANES, MItemTags.HARDENED_GLASS_PANES)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.HARDENED_GLASS_PANES, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.HARDENED_GLASS_PANES)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
consumer.accept(ExplosiveHammerPrimingRecipe(Ingredient.of(Tags.Items.NUGGETS_IRON), modLocation("hammer_priming")).toFinished())
MatteryRecipe(MItems.EXPLOSIVE_HAMMER, category = RecipeCategory.COMBAT)
.rowB(Tags.Items.INGOTS_IRON)
.rowAB(Tags.Items.INGOTS_IRON, Tags.Items.RODS_WOODEN)
.rowB(Tags.Items.RODS_WOODEN)
.unlockedBy(Items.FLINT_AND_STEEL)
.build(consumer)
MatteryRecipe(MItems.POWERED_FURNACE, category = machinesCategory)
.row(Items.FURNACE, MItems.MACHINE_FRAME, Items.FURNACE)
.unlockedBy(MItems.MACHINE_FRAME)
.build(consumer)
MatteryRecipe(MItems.POWERED_SMOKER, category = machinesCategory)
.rowAC(Items.FURNACE, Items.FURNACE)
.row(MItems.ELECTROMAGNET, MItems.MACHINE_FRAME, MItems.ELECTROMAGNET)
.unlockedBy(MItems.MACHINE_FRAME)
.build(consumer)
MatteryRecipe(MItems.POWERED_BLAST_FURNACE, category = machinesCategory)
.row(MItems.ELECTROMAGNET, Items.FURNACE, MItems.ELECTROMAGNET)
.row(MItems.ELECTROMAGNET, MItems.MACHINE_FRAME, MItems.ELECTROMAGNET)
.row(MItems.ELECTROMAGNET, Items.FURNACE, MItems.ELECTROMAGNET)
.unlockedBy(MItems.MACHINE_FRAME)
.build(consumer)
MatteryRecipe(MItems.INFINITE_WATER_SOURCE, category = machinesCategory)
.row(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES)
.rowAC(Items.WATER_BUCKET, Items.WATER_BUCKET)
.row(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES)
.unlockedBy(Items.WATER_BUCKET)
.build(consumer)
MatteryRecipe(MItems.PAINTER, category = machinesCategory)
.row(Tags.Items.RODS_WOODEN, Items.BUCKET, Items.BUCKET)
.row(MItemTags.IRON_PLATES, Items.BUCKET, MItemTags.IRON_PLATES)
.row(MItemTags.IRON_PLATES, MItemTags.CRAFTING_TABLES, MItemTags.IRON_PLATES)
.unlockedBy(Tags.Items.DYES)
.build(consumer)
} }

View File

@ -1,70 +1,67 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.* import net.minecraft.data.recipes.*
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.ItemTags
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.function.Consumer import java.util.function.Consumer
private fun stairs(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) { private fun stairs(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
MatteryRecipe(result, 4) MatteryRecipe(result, 4, category = RecipeCategory.BUILDING_BLOCKS)
.rowA(base) .rowA(base)
.rowAB(base, base) .rowAB(base, base)
.row(base, base, base) .row(base, base, base)
.unlockedBy(base) .unlockedBy(base)
.build(consumer) .build(consumer, modLocation("decorative/stairs/${base.asItem().registryName!!.path}"))
} }
private fun slab(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) { private fun slab(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
MatteryRecipe(result, 6) MatteryRecipe(result, 6, category = RecipeCategory.BUILDING_BLOCKS)
.row(base, base, base) .row(base, base, base)
.unlockedBy(base) .unlockedBy(base)
.build(consumer) .build(consumer, modLocation("decorative/slabs/${base.asItem().registryName!!.path}"))
} }
private fun wall(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) { private fun wall(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
MatteryRecipe(result, 6) MatteryRecipe(result, 6, category = RecipeCategory.BUILDING_BLOCKS)
.row(base, base, base) .row(base, base, base)
.row(base, base, base) .row(base, base, base)
.unlockedBy(base) .unlockedBy(base)
.build(consumer) .build(consumer, modLocation("decorative/walls/${base.asItem().registryName!!.path}"))
} }
private fun cut(base: ItemLike, result: ItemLike, amount: Int, consumer: Consumer<FinishedRecipe>) { private fun cut(base: ItemLike, result: ItemLike, amount: Int, consumer: RecipeOutput) {
SingleItemRecipeBuilder SingleItemRecipeBuilder
.stonecutting(Ingredient.of(base), result, amount) .stonecutting(Ingredient.of(base), RecipeCategory.BUILDING_BLOCKS, result, amount)
.unlockedBy(base) .unlockedBy(base)
.save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, "stonecutting/${result.asItem().registryName!!.path}_from_${base.asItem().registryName!!.path}")) .save(consumer, modLocation("stonecutting/${result.asItem().registryName!!.path}_from_${base.asItem().registryName!!.path}"))
} }
private fun stairsWithCut(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) { private fun stairsWithCut(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
stairs(base, result, consumer) stairs(base, result, consumer)
cut(base, result, 1, consumer) cut(base, result, 1, consumer)
} }
private fun slabWithCut(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) { private fun slabWithCut(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
slab(base, result, consumer) slab(base, result, consumer)
cut(base, result, 2, consumer) cut(base, result, 2, consumer)
} }
private fun wallWithCut(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) { private fun wallWithCut(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
wall(base, result, consumer) wall(base, result, consumer)
cut(base, result, 1, consumer) cut(base, result, 1, consumer)
} }
fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: Consumer<FinishedRecipe>) { fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: RecipeOutput) {
// Напольная плитка // Напольная плитка
for ((color, unrefinedItem) in MRegistry.UNREFINED_FLOOR_TILES.items) { for ((color, unrefinedItem) in MRegistry.UNREFINED_FLOOR_TILES.items) {
MatteryRecipe(unrefinedItem, 24) MatteryRecipe(unrefinedItem, 24)
@ -72,16 +69,32 @@ fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: Consumer<Fi
.row(Items.SAND, color.tag, Items.SAND) .row(Items.SAND, color.tag, Items.SAND)
.row(Items.CLAY, Items.SAND, Items.CLAY) .row(Items.CLAY, Items.SAND, Items.CLAY)
.unlockedBy(Items.CLAY) .unlockedBy(Items.CLAY)
.build(consumer) .build(consumer, modLocation("decorative/floor_tiles/unrefined/${color.name.lowercase()}"))
if (color != DyeColor.WHITE)
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, unrefinedItem, 8)
.requires(Ingredient.of(MRegistry.UNREFINED_FLOOR_TILES.getItem(DyeColor.WHITE)), 8)
.requires(color.tag)
.unlockedBy(MRegistry.UNREFINED_FLOOR_TILES.getItem(DyeColor.WHITE))
.save(consumer, modLocation("decorative/floor_tiles/unrefined/recolor/${unrefinedItem.registryName!!.path}"))
} }
for ((color, refinedItem) in MRegistry.FLOOR_TILES.items) { for ((color, refinedItem) in MRegistry.FLOOR_TILES.items) {
SimpleCookingRecipeBuilder.smelting( SimpleCookingRecipeBuilder.smelting(
Ingredient.of(MRegistry.UNREFINED_FLOOR_TILES.items[color]!!), Ingredient.of(MRegistry.UNREFINED_FLOOR_TILES.items[color]!!),
RecipeCategory.BUILDING_BLOCKS,
refinedItem, refinedItem,
0.15f, 0.15f,
100 100
).unlockedBy("has_unrefined_block", has(MRegistry.UNREFINED_FLOOR_TILES.items[color]!!)).save(consumer) ).unlockedBy("has_unrefined_block", has(MRegistry.UNREFINED_FLOOR_TILES.items[color]!!))
.save(consumer, modLocation("decorative/floor_tiles/refined/${color.name.lowercase()}"))
if (color != DyeColor.WHITE)
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, refinedItem, 8)
.requires(Ingredient.of(MRegistry.FLOOR_TILES.getItem(DyeColor.WHITE)), 8)
.requires(color.tag)
.unlockedBy(MRegistry.FLOOR_TILES.getItem(DyeColor.WHITE))
.save(consumer, modLocation("decorative/floor_tiles/refined/recolor/${color.name.lowercase()}"))
} }
for ((color, item) in MRegistry.TRITANIUM_BLOCK.allItems) { for ((color, item) in MRegistry.TRITANIUM_BLOCK.allItems) {
@ -111,86 +124,91 @@ fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: Consumer<Fi
val original = MRegistry.TRITANIUM_BLOCK.items[base]!! val original = MRegistry.TRITANIUM_BLOCK.items[base]!!
MatteryRecipe(item, 8) MatteryRecipe(item, 8, category = RecipeCategory.BUILDING_BLOCKS)
.row(original, original, original) .row(original, original, original)
.row(original, stripe.tag, original) .row(original, stripe.tag, original)
.row(original, original, original) .row(original, original, original)
.unlockedBy(original) .unlockedBy(original)
.build(consumer) .build(consumer, modLocation("decorative/tritanium/striped/${base.name.lowercase()}_${stripe.name.lowercase()}"))
} }
MatteryRecipe(MItems.DANGER_STRIPE_BLOCK, 24) MatteryRecipe(MItems.DANGER_STRIPE_BLOCK, 24, category = RecipeCategory.BUILDING_BLOCKS)
.rowAB(Tags.Items.DYES_YELLOW, Tags.Items.INGOTS_IRON) .rowAB(Tags.Items.DYES_YELLOW, Tags.Items.INGOTS_IRON)
.row(Tags.Items.INGOTS_IRON, Tags.Items.COBBLESTONE, Tags.Items.INGOTS_IRON) .row(Tags.Items.INGOTS_IRON, Tags.Items.COBBLESTONE, Tags.Items.INGOTS_IRON)
.rowBC(Tags.Items.INGOTS_IRON, Tags.Items.DYES_BLACK) .rowBC(Tags.Items.INGOTS_IRON, Tags.Items.DYES_BLACK)
.unlockedBy(Tags.Items.INGOTS_IRON) .unlockedBy(Tags.Items.INGOTS_IRON)
.unlockedBy(Tags.Items.DYES_BLACK) .unlockedBy(Tags.Items.DYES_BLACK)
.build(consumer) .build(consumer, modLocation("decorative/danger_stripe"))
MatteryRecipe(MItems.METAL_BEAM, 24) MatteryRecipe(MItems.METAL_BEAM, 24, category = RecipeCategory.BUILDING_BLOCKS)
.rowB(Tags.Items.INGOTS_IRON) .rowB(Tags.Items.INGOTS_IRON)
.row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS) .row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS)
.rowB(Tags.Items.INGOTS_IRON) .rowB(Tags.Items.INGOTS_IRON)
.build(consumer) .build(consumer, modLocation("decorative/metal_beam"))
MatteryRecipe(MRegistry.VENT.item, 24) MatteryRecipe(MRegistry.VENT.item, 24, category = RecipeCategory.BUILDING_BLOCKS)
.rowB(MItemTags.TRITANIUM_INGOTS) .rowB(MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, Items.IRON_BARS, MItemTags.TRITANIUM_INGOTS) .row(MItemTags.TRITANIUM_INGOTS, Items.IRON_BARS, MItemTags.TRITANIUM_INGOTS)
.rowB(MItemTags.TRITANIUM_INGOTS) .rowB(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer) .build(consumer, modLocation("decorative/vent/default"))
for ((color, item) in MRegistry.VENT.items) { for ((color, item) in MRegistry.VENT.items) {
MatteryRecipe(item, 8) MatteryRecipe(item, 8, category = RecipeCategory.BUILDING_BLOCKS)
.row(MRegistry.VENT.item, MRegistry.VENT.item, MRegistry.VENT.item) .row(MRegistry.VENT.item, MRegistry.VENT.item, MRegistry.VENT.item)
.row(MRegistry.VENT.item, color.tag, MRegistry.VENT.item) .row(MRegistry.VENT.item, color.tag, MRegistry.VENT.item)
.row(MRegistry.VENT.item, MRegistry.VENT.item, MRegistry.VENT.item) .row(MRegistry.VENT.item, MRegistry.VENT.item, MRegistry.VENT.item)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(color.tag) .unlockedBy(color.tag)
.build(consumer) .build(consumer, modLocation("decorative/vent/${color.name.lowercase()}"))
} }
for ((color, item) in MRegistry.VENT_ALTERNATIVE.allItems) { for ((color, item) in MRegistry.VENT_ALTERNATIVE.allItems) {
val other = MRegistry.VENT.allItems[color]!! val other = MRegistry.VENT.allItems[color]!!
ShapelessRecipeBuilder(item, 1).requires(other).unlockedBy(item).save(consumer)
ShapelessRecipeBuilder(other, 1).requires(item).unlockedBy(other).save(consumer, ResourceLocation( ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, item, 1).requires(other)
OverdriveThatMatters.MOD_ID, "${other.registryName!!.path}_from_alt")) .unlockedBy(item)
.save(consumer, modLocation("decorative/vent/to_alt/${color?.name?.lowercase() ?: "default"}"))
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, other, 1).requires(item)
.unlockedBy(other)
.save(consumer, modLocation("decorative/vent/from_alt/${color?.name?.lowercase() ?: "default"}"))
} }
MatteryRecipe(MRegistry.DECORATIVE_CRATE.item, 24) MatteryRecipe(MRegistry.DECORATIVE_CRATE.item, 24, category = RecipeCategory.BUILDING_BLOCKS)
.rowB(Tags.Items.INGOTS_IRON) .rowB(Tags.Items.INGOTS_IRON)
.row(Tags.Items.INGOTS_IRON, Tags.Items.COBBLESTONE, Tags.Items.INGOTS_IRON) .row(Tags.Items.INGOTS_IRON, Tags.Items.COBBLESTONE, Tags.Items.INGOTS_IRON)
.rowB(Tags.Items.INGOTS_IRON) .rowB(Tags.Items.INGOTS_IRON)
.unlockedBy(Tags.Items.INGOTS_IRON) .unlockedBy(Tags.Items.INGOTS_IRON)
.build(consumer) .build(consumer, modLocation("decorative/crate/rusty"))
for ((color, crate) in MRegistry.DECORATIVE_CRATE.items) { for ((color, crate) in MRegistry.DECORATIVE_CRATE.items) {
MatteryRecipe(crate, 8) MatteryRecipe(crate, 8, category = RecipeCategory.BUILDING_BLOCKS)
.row(MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item) .row(MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item)
.row(MRegistry.DECORATIVE_CRATE.item, color.tag, MRegistry.DECORATIVE_CRATE.item) .row(MRegistry.DECORATIVE_CRATE.item, color.tag, MRegistry.DECORATIVE_CRATE.item)
.row(MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item) .row(MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item)
.unlockedBy(MRegistry.DECORATIVE_CRATE.item) .unlockedBy(MRegistry.DECORATIVE_CRATE.item)
.build(consumer) .build(consumer, modLocation("decorative/crate/${color.name.lowercase()}"))
} }
for ((color, item) in MRegistry.TRITANIUM_BLOCK.items) { for ((color, item) in MRegistry.TRITANIUM_BLOCK.items) {
MatteryRecipe(item, 8) MatteryRecipe(item, 8, category = RecipeCategory.BUILDING_BLOCKS)
.row(MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item) .row(MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item)
.row(MRegistry.TRITANIUM_BLOCK.item, color.tag, MRegistry.TRITANIUM_BLOCK.item) .row(MRegistry.TRITANIUM_BLOCK.item, color.tag, MRegistry.TRITANIUM_BLOCK.item)
.row(MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item) .row(MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item)
.unlockedBy(MRegistry.TRITANIUM_BLOCK.item) .unlockedBy(MRegistry.TRITANIUM_BLOCK.item)
.unlockedBy(color.tag) .unlockedBy(color.tag)
.build(consumer) .build(consumer, modLocation("decorative/tritanium/default/${color.name.lowercase()}"))
} }
ShapelessRecipeBuilder(MRegistry.INDUSTRIAL_GLASS.item, 8) ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, MRegistry.INDUSTRIAL_GLASS.item, 8)
.requires(Items.GLASS, 8) .requires(Items.GLASS, 8)
.requires(MItemTags.TRITANIUM_PLATES) .requires(MItemTags.TRITANIUM_PLATES)
.unlockedBy("has_plate", has(MItemTags.TRITANIUM_PLATES)) .unlockedBy("has_plate", has(MItemTags.TRITANIUM_PLATES))
.unlockedBy("has_glass", has(Items.GLASS)) .unlockedBy("has_glass", has(Items.GLASS))
.save(consumer) .save(consumer, modLocation("decorative/industrial_glass/default"))
ShapedRecipeBuilder(MRegistry.INDUSTRIAL_GLASS_PANE.item, 16) ShapedRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, MRegistry.INDUSTRIAL_GLASS_PANE.item, 16)
.define('#', MRegistry.INDUSTRIAL_GLASS.item) .define('#', MRegistry.INDUSTRIAL_GLASS.item)
.pattern("###").pattern("###") .pattern("###").pattern("###")
.unlockedBy("has_tritanium_glass", has(MRegistry.INDUSTRIAL_GLASS.item)) .unlockedBy("has_tritanium_glass", has(MRegistry.INDUSTRIAL_GLASS.item))
@ -221,97 +239,138 @@ fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: Consumer<Fi
val mappedVanilla = mappingUpgradeVanilla[color]!! val mappedVanilla = mappingUpgradeVanilla[color]!!
// обычная покраска // обычная покраска
ShapelessRecipeBuilder(item, 8) ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, item, 8)
.requires(MRegistry.INDUSTRIAL_GLASS.item, 8) .requires(MRegistry.INDUSTRIAL_GLASS.item, 8)
.requires(color.tag) .requires(color.tag)
.unlockedBy("has_tritanium_glass", has(MRegistry.INDUSTRIAL_GLASS.item)) .unlockedBy("has_tritanium_glass", has(MRegistry.INDUSTRIAL_GLASS.item))
.save(consumer) .save(consumer, modLocation("decorative/industrial_glass/recolor/${color.name.lowercase()}"))
// апгрейд ванильного крашенного стекла // апгрейд ванильного крашенного стекла
ShapelessRecipeBuilder(item, 8) ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, item, 8)
.requires(mappedVanilla, 8) .requires(mappedVanilla, 8)
.requires(MItemTags.TRITANIUM_PLATES) .requires(MItemTags.TRITANIUM_PLATES)
.unlockedBy("has_plate", has(MItemTags.TRITANIUM_PLATES)) .unlockedBy("has_plate", has(MItemTags.TRITANIUM_PLATES))
.unlockedBy("has_colored_glass", has(mappedVanilla)) .unlockedBy("has_colored_glass", has(mappedVanilla))
.save(consumer, ResourceLocation(DataGen.MOD_ID, "${item.registryName!!.path}_upgrade")) .save(consumer, modLocation("decorative/industrial_glass/upgrade/${color.name.lowercase()}"))
ShapelessRecipeBuilder(paneItem, 8) ShapedRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, paneItem, 16)
.requires(MRegistry.INDUSTRIAL_GLASS_PANE.item, 8)
.requires(color.tag)
.unlockedBy("has_tritanium_glass_pane", has(MRegistry.INDUSTRIAL_GLASS_PANE.item))
.save(consumer)
ShapedRecipeBuilder(paneItem, 16)
.define('#', item) .define('#', item)
.pattern("###").pattern("###") .pattern("###").pattern("###")
.unlockedBy("has_colored_tritanium_glass", has(paneItem)) .unlockedBy("has_colored_tritanium_glass", has(paneItem))
.save(consumer, ResourceLocation(DataGen.MOD_ID, "${paneItem.registryName!!.path}_alt")) .save(consumer, modLocation("decorative/industrial_glass_pane/${color.name.lowercase()}"))
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, paneItem, 8)
.requires(MRegistry.INDUSTRIAL_GLASS_PANE.item, 8)
.requires(color.tag)
.unlockedBy("has_tritanium_glass_pane", has(MRegistry.INDUSTRIAL_GLASS_PANE.item))
.save(consumer, modLocation("decorative/industrial_glass_pane/recolor/${color.name.lowercase()}"))
} }
ShapelessRecipeBuilder(MItems.LABORATORY_LAMP, 1) ShapelessRecipeBuilder(RecipeCategory.REDSTONE, MItems.LABORATORY_LAMP, 1)
.requires(MItems.LABORATORY_LAMP_INVERTED) .requires(MItems.LABORATORY_LAMP_INVERTED)
.unlockedBy(MItems.LABORATORY_LAMP_INVERTED) .unlockedBy(MItems.LABORATORY_LAMP_INVERTED)
.save(consumer, MItems.LABORATORY_LAMP.registryName!!.toString() + "_inv") .save(consumer, MItems.LABORATORY_LAMP.registryName!!.toString() + "_inv")
ShapelessRecipeBuilder(MItems.LABORATORY_LAMP_INVERTED, 1) ShapelessRecipeBuilder(RecipeCategory.REDSTONE, MItems.LABORATORY_LAMP_INVERTED, 1)
.requires(MItems.LABORATORY_LAMP) .requires(MItems.LABORATORY_LAMP)
.unlockedBy(MItems.LABORATORY_LAMP) .unlockedBy(MItems.LABORATORY_LAMP)
.save(consumer, MItems.LABORATORY_LAMP_INVERTED.registryName!!.toString() + "_inv") .save(consumer, MItems.LABORATORY_LAMP_INVERTED.registryName!!.toString() + "_inv")
MatteryRecipe(MBlocks.TRITANIUM_STRIPED_BLOCK, 24) MatteryRecipe(MBlocks.TRITANIUM_STRIPED_BLOCK, 24, category = RecipeCategory.BUILDING_BLOCKS)
.rowB(MItemTags.TRITANIUM_INGOTS) .rowB(MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS) .row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS)
.rowAB(Tags.Items.DYES_YELLOW, MItemTags.TRITANIUM_INGOTS) .rowAB(Tags.Items.DYES_YELLOW, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(Tags.Items.DYES_YELLOW) .unlockedBy(Tags.Items.DYES_YELLOW)
.build(consumer) .build(consumer, modLocation("decorative/blocks/striped_default"))
MatteryRecipe(MRegistry.TRITANIUM_BLOCK.item, 24) MatteryRecipe(MRegistry.TRITANIUM_BLOCK.item, 24, category = RecipeCategory.BUILDING_BLOCKS)
.rowB(MItemTags.TRITANIUM_INGOTS) .rowB(MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS) .row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS)
.rowB(MItemTags.TRITANIUM_INGOTS) .rowB(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer) .build(consumer, modLocation("decorative/blocks/default"))
MatteryRecipe(MBlocks.TRITANIUM_DOOR[null]!!, 3) MatteryRecipe(MBlocks.TRITANIUM_DOOR[null]!!, 3, category = RecipeCategory.REDSTONE)
.rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS) .rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS) .rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS) .rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer) .build(consumer, modLocation("decorative/doors/default"))
for (color in DyeColor.values()) { for (color in DyeColor.values()) {
ShapelessRecipeBuilder.shapeless(MItems.TRITANIUM_DOOR[color]!!, 1) ShapelessRecipeBuilder.shapeless(RecipeCategory.REDSTONE, MItems.TRITANIUM_DOOR[color]!!, 1)
.requires(Ingredient.of(MItems.TRITANIUM_DOOR.entries.stream().filter { it.key != color }.map { ItemStack(it.value) })) .requires(Ingredient.of(MItems.TRITANIUM_DOOR.entries.stream().filter { it.key != color }.map { ItemStack(it.value) }))
.requires(color.tag) .requires(color.tag)
.unlockedBy(MItems.TRITANIUM_DOOR.entries.stream().filter { it.key != color }.map { it.value }) .unlockedBy(MItems.TRITANIUM_DOOR.entries.stream().filter { it.key != color }.map { it.value })
.save(consumer) .save(consumer, modLocation("decorative/doors/${color.name.lowercase()}"))
} }
MatteryRecipe(MBlocks.TRITANIUM_TRAPDOOR[null]!!) MatteryRecipe(MBlocks.TRITANIUM_TRAPDOOR[null]!!, category = RecipeCategory.REDSTONE)
.rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS) .rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS) .rowAB(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS) .unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer) .build(consumer, modLocation("decorative/trapdoors/default"))
for (color in DyeColor.values()) { for (color in DyeColor.values()) {
ShapelessRecipeBuilder.shapeless(MItems.TRITANIUM_TRAPDOOR[color]!!, 1) ShapelessRecipeBuilder.shapeless(RecipeCategory.REDSTONE, MItems.TRITANIUM_TRAPDOOR[color]!!, 1)
.requires(Ingredient.of(MItems.TRITANIUM_TRAPDOOR.entries.stream().filter { it.key != color }.map { ItemStack(it.value) })) .requires(Ingredient.of(MItems.TRITANIUM_TRAPDOOR.entries.stream().filter { it.key != color }.map { ItemStack(it.value) }))
.requires(color.tag) .requires(color.tag)
.unlockedBy(MItems.TRITANIUM_TRAPDOOR.entries.stream().filter { it.key != color }.map { it.value }) .unlockedBy(MItems.TRITANIUM_TRAPDOOR.entries.stream().filter { it.key != color }.map { it.value })
.save(consumer) .save(consumer, modLocation("decorative/trapdoors/${color.name.lowercase()}"))
} }
MatteryRecipe(MRegistry.TRITANIUM_PRESSURE_PLATE.item) MatteryRecipe(MRegistry.TRITANIUM_PRESSURE_PLATE.item, category = RecipeCategory.REDSTONE)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.BASIC_CIRCUIT, MItemTags.TRITANIUM_PLATES) .row(MItemTags.TRITANIUM_PLATES, MItemTags.BASIC_CIRCUIT, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItemTags.TRITANIUM_PLATES) .unlockedBy(MItemTags.TRITANIUM_PLATES)
.build(consumer) .build(consumer, modLocation("pressure_plates/default"))
for (dye in DyeColor.values()) { for (dye in DyeColor.values()) {
ShapelessRecipeBuilder(MRegistry.TRITANIUM_PRESSURE_PLATE.getItem(dye), 1) ShapelessRecipeBuilder(RecipeCategory.REDSTONE, MRegistry.TRITANIUM_PRESSURE_PLATE.getItem(dye), 1)
.requires(Ingredient.of(MRegistry.TRITANIUM_PRESSURE_PLATE.allItems.entries.stream().filter { it.key != dye }.map { ItemStack(it.value) })) .requires(Ingredient.of(MRegistry.TRITANIUM_PRESSURE_PLATE.allItems.entries.stream().filter { it.key != dye }.map { ItemStack(it.value) }))
.requires(dye.tag) .requires(dye.tag)
.unlockedBy(MItemTags.TRITANIUM_PLATES) .unlockedBy(MItemTags.TRITANIUM_PLATES)
.save(consumer) .save(consumer, modLocation("pressure_plates/${dye.name.lowercase()}"))
} }
MatteryRecipe(MItems.ENGINE, count = 9, category = RecipeCategory.BUILDING_BLOCKS)
.rowAC(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, Items.FLINT_AND_STEEL, MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, MItems.MATTER_CABLE, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(Items.FLINT_AND_STEEL)
.build(consumer, modLocation("decorative/engine"))
MatteryRecipe(MItems.METAL_MESH, count = 12, category = RecipeCategory.BUILDING_BLOCKS)
.row(Tags.Items.NUGGETS_IRON, Items.IRON_BARS, Tags.Items.NUGGETS_IRON)
.rowAC(Items.IRON_BARS, Items.IRON_BARS)
.row(Tags.Items.NUGGETS_IRON, Items.IRON_BARS, Tags.Items.NUGGETS_IRON)
.unlockedBy(Tags.Items.NUGGETS_IRON)
.unlockedBy(Items.IRON_BARS)
.build(consumer, modLocation("decorative/metal_mesh"))
// лампа
MatteryRecipe(MItems.LABORATORY_LAMP, category = RecipeCategory.REDSTONE)
.row(MItemTags.IRON_PLATES, MItemTags.HARDENED_GLASS_PANES_COLORLESS, MItemTags.IRON_PLATES)
.row(MItems.MIRROR, Items.GLOWSTONE, MItems.MIRROR)
.row(MItemTags.TRITANIUM_PLATES, Tags.Items.DUSTS_REDSTONE, MItemTags.TRITANIUM_PLATES)
.build(consumer, modLocation("decorative/lamp"))
// Голо табличка
MatteryRecipe(MItems.HOLO_SIGN, category = RecipeCategory.DECORATIONS)
.row(MItemTags.BASIC_CIRCUIT, MItemTags.TRITANIUM_PLATES, MItemTags.HARDENED_GLASS_PANES_COLORLESS)
.rowAB(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_GLOWSTONE)
.rowBC(MItemTags.TRITANIUM_PLATES, MItemTags.HARDENED_GLASS_PANES_COLORLESS)
.build(consumer, modLocation("decorative/holo_sign"))
MatteryRecipe(MItems.TRITANIUM_BARS, category = RecipeCategory.DECORATIONS, count = 16)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.build(consumer, modLocation("decorative/tritanium_bars"))
MatteryRecipe(MItems.TRITANIUM_ANVIL[0], category = RecipeCategory.DECORATIONS)
.row(MItemTags.TRITANIUM_INGOTS_STORAGE, MItemTags.TRITANIUM_INGOTS_STORAGE, MItemTags.TRITANIUM_INGOTS_STORAGE)
.rowB(MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS, MItemTags.TRITANIUM_INGOTS)
.build(consumer)
} }

View File

@ -0,0 +1,82 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.world.item.Items
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
fun addMachineUpgradeRecipes(consumer: RecipeOutput) {
MatteryRecipe(MItems.MachineUpgrades.Basic.BLANK, 4)
.rowB(Items.REDSTONE)
.rowAC(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES)
.rowB(MItems.ELECTRIC_PARTS)
.unlockedBy(MItemTags.IRON_PLATES)
.unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer)
MatteryRecipe(MItems.MachineUpgrades.Normal.BLANK, 4)
.row(MItemTags.COPPER_WIRES, Items.REDSTONE, MItemTags.COPPER_WIRES)
.row(MItemTags.IRON_PLATES, Items.REDSTONE, MItemTags.IRON_PLATES)
.rowB(MItems.ELECTRIC_PARTS)
.unlockedBy(MItemTags.IRON_PLATES)
.unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer)
MatteryRecipe(MItems.MachineUpgrades.Advanced.BLANK, 4)
.row(MItemTags.GOLD_WIRES, Items.REDSTONE, MItemTags.GOLD_WIRES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.COPPER_WIRES, MItemTags.TRITANIUM_PLATES)
.row(MItems.ELECTRIC_PARTS, Items.REDSTONE, MItems.ELECTRIC_PARTS)
.unlockedBy(MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer)
for (tier in MItems.MachineUpgrades.CRAFTABLE_TIERS) {
MatteryRecipe(tier.SPEED, 1)
.rowB(Items.REDSTONE)
.row(Items.SUGAR, MItemTags.COPPER_WIRES, Items.SUGAR)
.rowB(tier.BLANK)
.unlockedBy(tier.BLANK)
.unlockedBy(MItemTags.COPPER_WIRES)
.build(consumer)
MatteryRecipe(tier.ENERGY_CONSUMPTION, 1)
.rowB(Items.REDSTONE)
.row(MItemTags.COPPER_WIRES, MItemTags.GOLD_WIRES, MItemTags.COPPER_WIRES)
.rowB(tier.BLANK)
.unlockedBy(tier.BLANK)
.unlockedBy(MItemTags.GOLD_WIRES)
.build(consumer)
MatteryRecipe(tier.FAILSAFE, 1)
.rowB(MItems.ELECTRIC_PARTS)
.row(MItemTags.COPPER_WIRES, MItems.QUANTUM_TRANSCEIVER, MItemTags.COPPER_WIRES)
.rowB(tier.BLANK)
.unlockedBy(tier.BLANK)
.unlockedBy(MItems.QUANTUM_TRANSCEIVER)
.build(consumer)
MatteryRecipe(tier.ENERGY_STORAGE, 1)
.rowB(Items.REDSTONE)
.row(Items.REDSTONE, MItems.ENERGY_BUS, Items.REDSTONE)
.rowB(tier.BLANK)
.unlockedBy(tier.BLANK)
.unlockedBy(MItems.ENERGY_BUS)
.build(consumer)
MatteryRecipe(tier.MATTER_STORAGE, 1)
.rowB(Tags.Items.GLASS)
.row(Tags.Items.GLASS, MItems.MATTER_CAPACITOR_PARTS, Tags.Items.GLASS)
.rowB(tier.BLANK)
.unlockedBy(tier.BLANK)
.unlockedBy(MItems.MATTER_CAPACITOR_PARTS)
.build(consumer)
MatteryRecipe(tier.PROCESSING_ITEMS, 1)
.rowB(MItems.ELECTRIC_PARTS)
.row(MItems.ELECTROMAGNET, MItemTags.TRITANIUM_PLATES, MItems.ELECTROMAGNET)
.rowB(tier.BLANK)
.unlockedBy(tier.BLANK)
.unlockedBy(MItems.ELECTROMAGNET)
.build(consumer)
}
}

View File

@ -0,0 +1,43 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.IngredientMatrix
import ru.dbotthepony.mc.otm.recipe.MatterEntanglerRecipe
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
fun addMatterEntanglerRecipes(consumer: RecipeOutput) {
consumer.accept(
MatterEntanglerRecipe(
modLocation("quantum_capacitor"),
IngredientMatrix.of(
listOf(Ingredient.of(MItems.ELECTRIC_PARTS), Ingredient.of(MItemTags.GOLD_WIRES), Ingredient.of(MItems.ELECTRIC_PARTS)),
listOf(Ingredient.of(MItems.BATTERY_CAPACITOR), Ingredient.of(MItems.QUANTUM_TRANSCEIVER), Ingredient.of(MItems.BATTERY_CAPACITOR)),
listOf(Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES)),
),
Decimal(40),
400.0,
ItemStack(MItems.QUANTUM_CAPACITOR, 2),
experience = 15f
).energetic().toFinished()
)
consumer.accept(
MatterEntanglerRecipe(
modLocation("quantum_battery"),
IngredientMatrix.of(
listOf(Ingredient.of(Tags.Items.STORAGE_BLOCKS_REDSTONE), Ingredient.of(MItemTags.GOLD_WIRES), Ingredient.of(Tags.Items.STORAGE_BLOCKS_REDSTONE)),
listOf(Ingredient.of(MItems.BATTERY_DENSE), Ingredient.of(MItems.QUANTUM_TRANSCEIVER), Ingredient.of(MItems.BATTERY_DENSE)),
listOf(Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES), Ingredient.of(MItemTags.TRITANIUM_PLATES)),
),
Decimal(120),
600.0,
ItemStack(MItems.QUANTUM_BATTERY, 2),
experience = 20f
).energetic().toFinished()
)
}

View File

@ -1,12 +1,13 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import com.google.common.collect.ImmutableList import com.google.gson.JsonObject
import net.minecraft.advancements.Advancement
import net.minecraft.advancements.Criterion
import net.minecraft.advancements.CriterionTriggerInstance import net.minecraft.advancements.CriterionTriggerInstance
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeBuilder import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.ShapedRecipeBuilder import net.minecraft.data.recipes.ShapedRecipeBuilder
import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
@ -15,7 +16,11 @@ import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.toJsonStrict
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
import java.util.function.Consumer import java.util.function.Consumer
private interface RecipeCell { private interface RecipeCell {
@ -51,11 +56,19 @@ private data class RecipeRow(
val c: RecipeCell?, val c: RecipeCell?,
) )
private fun RecipeOutput.map(mapper: (FinishedRecipe) -> FinishedRecipe): RecipeOutput {
return object : RecipeOutput {
override fun accept(recipe: FinishedRecipe) {
this@map.accept(mapper(recipe))
}
}
}
/** /**
* [ShapedRecipeBuilder] that doesn't suck * [ShapedRecipeBuilder] that doesn't suck
*/ */
@Suppress("unused") @Suppress("unused")
class MatteryRecipe(val result: ItemLike, val count: Int = 1) { class MatteryRecipe(val result: ItemLike, val count: Int = 1, val category: RecipeCategory = RecipeCategory.MISC) {
private val rows = arrayOfNulls<RecipeRow>(3) private val rows = arrayOfNulls<RecipeRow>(3)
private var index = 0 private var index = 0
@ -115,12 +128,12 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1) {
} }
} }
fun build(consumer: Consumer<FinishedRecipe>, name: String? = null) { private fun buildRegular(): ShapedRecipeBuilder {
if (index == 0) { if (index == 0) {
throw NoSuchElementException("No recipe rows were defined") throw NoSuchElementException("No recipe rows were defined")
} }
val builder = ShapedRecipeBuilder(result, count) val builder = ShapedRecipeBuilder(category, result, count)
val pairs = ArrayList<Pair<Char, RecipeCell>>() val pairs = ArrayList<Pair<Char, RecipeCell>>()
val iterator = charlist.iterator() val iterator = charlist.iterator()
@ -139,25 +152,75 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1) {
builder.unlockedBy(a, b) builder.unlockedBy(a, b)
} }
return builder
}
private var upgradeSource: ResourceLocation? = null
private val copyPaths = ArrayList<UpgradeRecipe.Op>()
fun setUpgradeSource(source: ResourceLocation): MatteryRecipe {
this.upgradeSource = source
return this
}
fun setUpgradeSource(source: ItemLike): MatteryRecipe {
this.upgradeSource = source.asItem().registryName!!
return this
}
fun addUpgradeOps(vararg operations: UpgradeRecipe.Op): MatteryRecipe {
for (op in operations) copyPaths.add(op)
return this
}
private fun filter(): (FinishedRecipe) -> FinishedRecipe {
if (upgradeSource != null) {
check(copyPaths.isNotEmpty()) { "Defined upgrade recipe without nbt migration operations" }
return {
object : FinishedRecipe by it {
override fun serializeRecipeData(pJson: JsonObject) {
pJson["parent"] = it.serializeRecipe()
pJson["copyPaths"] = UpgradeRecipe.COPY_PATHS_CODEC.toJsonStrict(copyPaths)
pJson["source"] = upgradeSource!!.toString()
}
override fun getType(): RecipeSerializer<*> {
return UpgradeRecipe.CODEC
}
}
}
}
return { it }
}
fun build(consumer: RecipeOutput, name: String? = null) {
val builder = buildRegular()
if (name != null) { if (name != null) {
builder.save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, builder.save(consumer.map(filter()), modLocation(
if (result.asItem().registryName!!.namespace == OverdriveThatMatters.MOD_ID) if (result.asItem().registryName!!.namespace == OverdriveThatMatters.MOD_ID)
"${result.asItem().registryName!!.path}_$name" "${result.asItem().registryName!!.path}_$name"
else else
"${result.asItem().registryName!!.namespace}_${result.asItem().registryName!!.path}_$name" "${result.asItem().registryName!!.namespace}_${result.asItem().registryName!!.path}_$name"
)) ))
} else { } else {
builder.save(consumer) builder.save(consumer.map(filter()))
} }
} }
fun buildEnergetic(consumer: Consumer<FinishedRecipe>, name: String? = null) { fun build(consumer: RecipeOutput, name: ResourceLocation) {
build({ buildRegular().save(consumer.map(filter()), name)
consumer.accept(object : FinishedRecipe by it { }
fun buildEnergetic(consumer: RecipeOutput, name: String? = null) {
build(consumer.map {
object : FinishedRecipe by it {
override fun getType(): RecipeSerializer<*> { override fun getType(): RecipeSerializer<*> {
return EnergyContainerRecipe.Companion return EnergyContainerRecipe.Companion
} }
}) }
}, name) }, name)
} }

View File

@ -1,40 +1,44 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.advancements.CriterionTriggerInstance
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.InventoryChangeTrigger import net.minecraft.advancements.critereon.InventoryChangeTrigger
import net.minecraft.advancements.critereon.ItemPredicate import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.advancements.critereon.MinMaxBounds import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.data.DataGenerator import net.minecraft.data.DataGenerator
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeBuilder import net.minecraft.data.recipes.RecipeBuilder
import net.minecraft.data.recipes.RecipeProvider import net.minecraft.data.recipes.RecipeProvider
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.ItemTags
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
import net.minecraft.util.valueproviders.ConstantFloat
import net.minecraft.util.valueproviders.FloatProvider
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
import java.util.LinkedList import java.util.*
import java.util.function.Consumer
import java.util.stream.Stream import java.util.stream.Stream
private typealias RecipeBuilderCallback = (MatteryRecipeProvider, consumer: Consumer<FinishedRecipe>) -> Unit private typealias RecipeBuilderCallback = (MatteryRecipeProvider, consumer: RecipeOutput) -> Unit
fun has(p_176521_: MinMaxBounds.Ints, p_176522_: ItemLike): InventoryChangeTrigger.TriggerInstance { fun has(p_176521_: MinMaxBounds.Ints, p_176522_: ItemLike): CriterionTriggerInstance {
return inventoryTrigger(ItemPredicate.Builder.item().of(p_176522_).withCount(p_176521_).build()) return inventoryTrigger(ItemPredicate.Builder.item().of(p_176522_).withCount(p_176521_).build())
} }
fun has(p_125978_: ItemLike): InventoryChangeTrigger.TriggerInstance { fun has(p_125978_: ItemLike): CriterionTriggerInstance {
return inventoryTrigger(ItemPredicate.Builder.item().of(p_125978_).build()) return inventoryTrigger(ItemPredicate.Builder.item().of(p_125978_).build())
} }
fun has(p_125976_: TagKey<Item>): InventoryChangeTrigger.TriggerInstance { fun has(p_125976_: TagKey<Item>): CriterionTriggerInstance {
return inventoryTrigger(ItemPredicate.Builder.item().of(p_125976_).build()) return inventoryTrigger(ItemPredicate.Builder.item().of(p_125976_).build())
} }
fun inventoryTrigger(vararg p_126012_: ItemPredicate): InventoryChangeTrigger.TriggerInstance { fun inventoryTrigger(vararg p_126012_: ItemPredicate): CriterionTriggerInstance {
return InventoryChangeTrigger.TriggerInstance( return InventoryChangeTrigger.TriggerInstance(
EntityPredicate.Composite.ANY, EntityPredicate.Composite.ANY,
MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY,
@ -44,6 +48,20 @@ fun inventoryTrigger(vararg p_126012_: ItemPredicate): InventoryChangeTrigger.Tr
) )
} }
fun multiIngredient(vararg items: Any) : Ingredient {
val values = arrayListOf<Ingredient.Value>()
for (item in items) {
if (item is ItemStack) {
values.add(Ingredient.ItemValue(item))
} else if (item is TagKey<*>) {
values.add(Ingredient.TagValue(item as TagKey<Item>))
}
}
return Ingredient.fromValues(values.stream())
}
fun <T : RecipeBuilder> T.unlockedBy(item: ItemLike): T { fun <T : RecipeBuilder> T.unlockedBy(item: ItemLike): T {
val location = item.asItem().registryName!! val location = item.asItem().registryName!!
unlockedBy("has_${location.namespace}_${location.path}", has(item)) unlockedBy("has_${location.namespace}_${location.path}", has(item))
@ -63,7 +81,7 @@ fun <T : RecipeBuilder> T.unlockedBy(item: TagKey<Item>): T {
return this return this
} }
class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generatorIn) { class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generatorIn.packOutput) {
private val callbacks = LinkedList<RecipeBuilderCallback>() private val callbacks = LinkedList<RecipeBuilderCallback>()
fun exec(callback: RecipeBuilderCallback): MatteryRecipeProvider { fun exec(callback: RecipeBuilderCallback): MatteryRecipeProvider {
@ -71,27 +89,34 @@ class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generat
return this return this
} }
override fun buildCraftingRecipes(callback: Consumer<FinishedRecipe>) { override fun buildRecipes(callback: RecipeOutput) {
for (lambda in callbacks) { for (lambda in callbacks) {
lambda(this, callback) lambda(this, callback)
} }
} }
fun plate(id: String, count: Int = 1, workTicks: Int = 200) { fun plate(id: String, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
exec { _, consumer -> exec { _, consumer ->
consumer.accept(PlatePressShallowFinishedRecipe( consumer.accept(PlatePressRecipe(
ResourceLocation(DataGen.MOD_ID, "plates/$id"), modLocation("plates/$id"),
ResourceLocation("forge", "ingots/$id"), Ingredient.of(ItemTags.create(ResourceLocation("forge", "ingots/$id"))),
ResourceLocation("forge", "plates/$id"), Ingredient.of(ItemTags.create(ResourceLocation("forge", "plates/$id"))),
count, count,
workTicks workTicks,
)) experience = experience
).toFinished())
} }
} }
fun plate(id: String, ingredient: Ingredient, result: Ingredient, count: Int = 1, workTicks: Int = 200) { fun plate(id: String, ingredient: Ingredient, result: Ingredient, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
exec { it, callback -> exec { it, callback ->
callback.accept(PlatePressFinishedRecipe(PlatePressRecipe(ResourceLocation(DataGen.MOD_ID, "plate_$id"), ingredient, result, count, workTicks))) callback.accept(PlatePressRecipe(modLocation("plates/$id"), ingredient, result, count, workTicks, experience = experience).toFinished())
}
}
fun microwave(id: String, ingredient: Ingredient, result: Ingredient, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
exec { it, callback ->
callback.accept(MicrowaveRecipe(modLocation("microwave/$id"), ingredient, result, count, workTicks, experience = experience).toFinished())
} }
} }
} }

View File

@ -1,21 +0,0 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.SimpleCookingRecipeBuilder
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
import java.util.function.Consumer
fun addOreSmeltingRecipes(consumer: Consumer<FinishedRecipe>) {
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_ORES), MItems.TRITANIUM_INGOT, 1f, 100).unlockedBy(MItemTags.TRITANIUM_ORES).save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, "smelting/tritanium_ingot_from_ore_block"))
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_ORES), MItems.TRITANIUM_INGOT, 1f, 200).unlockedBy(MItemTags.TRITANIUM_ORES).save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, "blasting/tritanium_ingot_from_ore_block"))
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_ORE_CLUMPS), MItems.TRITANIUM_INGOT, 1f, 100).unlockedBy(MItemTags.TRITANIUM_ORE_CLUMPS).save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, "smelting/tritanium_ingot_from_raw_ore"))
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_ORE_CLUMPS), MItems.TRITANIUM_INGOT, 1f, 200).unlockedBy(MItemTags.TRITANIUM_ORE_CLUMPS).save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, "blasting/tritanium_ingot_from_raw_ore"))
SimpleCookingRecipeBuilder.blasting(Ingredient.of(MItemTags.TRITANIUM_DUSTS), MItems.TRITANIUM_INGOT, 0f, 100).unlockedBy(MItemTags.TRITANIUM_DUSTS).save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, "smelting/tritanium_ingot_from_dust"))
SimpleCookingRecipeBuilder.smelting(Ingredient.of(MItemTags.TRITANIUM_DUSTS), MItems.TRITANIUM_INGOT, 0f, 200).unlockedBy(MItemTags.TRITANIUM_DUSTS).save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID, "blasting/tritanium_ingot_from_dust"))
}

View File

@ -0,0 +1,292 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.PainterArmorDyeRecipe
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
private val Item.recipeName get() = registryName!!.namespace + "/" + registryName!!.path
private fun generate(consumer: RecipeOutput, items: Map<out DyeColor?, Item>, amount: Int = 1) {
for ((targetColor, targetItem) in items) {
if (targetColor == null) continue
consumer.accept(PainterRecipe(
modLocation("painter/" + targetItem.recipeName),
Ingredient.of(items.entries.stream().filter { it.key != null && it.key != targetColor }.map { ItemStack(it.value) }),
ItemStack(targetItem),
mapOf(targetColor to amount)
).toFinished())
}
}
private fun generate(consumer: RecipeOutput, default: Item, items: Map<out DyeColor?, Item>, amount: Int = 1, cleaning: Boolean = true) {
generate(consumer, items)
if (cleaning)
cleaning(consumer, default, items)
for ((k1, v1) in items) {
if (k1 == null) continue
consumer.accept(PainterRecipe(
modLocation("painter/" + default.recipeName + "/" + v1.recipeName),
Ingredient.of(default),
ItemStack(v1),
mapOf(k1 to amount)
).toFinished())
}
}
private fun cleaning(consumer: RecipeOutput, to: Item, from: Map<out DyeColor?, Item>) {
consumer.accept(PainterRecipe(
modLocation("painter/cleaning/" + to.recipeName),
Ingredient.of(from.entries.stream().filter { it.key != null }.map { ItemStack(it.value) }),
ItemStack(to),
mapOf(null to 15)
).toFinished())
}
private fun striped(consumer: RecipeOutput, name: String, items: List<Pair<Item, Pair<DyeColor, DyeColor>>>, base: Map<DyeColor, Item>) {
for ((stripeItem, colors) in items) {
val (baseColor, stripe) = colors
consumer.accept(PainterRecipe(
modLocation("painter/stripes_$name/${baseColor.getName()}/${stripe.getName()}"),
Ingredient.of(base[baseColor]),
ItemStack(stripeItem),
setOf(stripe)
).toFinished())
}
}
fun addPainterRecipes(consumer: RecipeOutput) {
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_WOOL,
DyeColor.ORANGE to Items.ORANGE_WOOL,
DyeColor.MAGENTA to Items.MAGENTA_WOOL,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_WOOL,
DyeColor.YELLOW to Items.YELLOW_WOOL,
DyeColor.LIME to Items.LIME_WOOL,
DyeColor.PINK to Items.PINK_WOOL,
DyeColor.GRAY to Items.GRAY_WOOL,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_WOOL,
DyeColor.CYAN to Items.CYAN_WOOL,
DyeColor.PURPLE to Items.PURPLE_WOOL,
DyeColor.BLUE to Items.BLUE_WOOL,
DyeColor.BROWN to Items.BROWN_WOOL,
DyeColor.GREEN to Items.GREEN_WOOL,
DyeColor.RED to Items.RED_WOOL,
DyeColor.BLACK to Items.BLACK_WOOL,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CARPET,
DyeColor.ORANGE to Items.ORANGE_CARPET,
DyeColor.MAGENTA to Items.MAGENTA_CARPET,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CARPET,
DyeColor.YELLOW to Items.YELLOW_CARPET,
DyeColor.LIME to Items.LIME_CARPET,
DyeColor.PINK to Items.PINK_CARPET,
DyeColor.GRAY to Items.GRAY_CARPET,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CARPET,
DyeColor.CYAN to Items.CYAN_CARPET,
DyeColor.PURPLE to Items.PURPLE_CARPET,
DyeColor.BLUE to Items.BLUE_CARPET,
DyeColor.BROWN to Items.BROWN_CARPET,
DyeColor.GREEN to Items.GREEN_CARPET,
DyeColor.RED to Items.RED_CARPET,
DyeColor.BLACK to Items.BLACK_CARPET,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_BED,
DyeColor.ORANGE to Items.ORANGE_BED,
DyeColor.MAGENTA to Items.MAGENTA_BED,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_BED,
DyeColor.YELLOW to Items.YELLOW_BED,
DyeColor.LIME to Items.LIME_BED,
DyeColor.PINK to Items.PINK_BED,
DyeColor.GRAY to Items.GRAY_BED,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_BED,
DyeColor.CYAN to Items.CYAN_BED,
DyeColor.PURPLE to Items.PURPLE_BED,
DyeColor.BLUE to Items.BLUE_BED,
DyeColor.BROWN to Items.BROWN_BED,
DyeColor.GREEN to Items.GREEN_BED,
DyeColor.RED to Items.RED_BED,
DyeColor.BLACK to Items.BLACK_BED,
), 3)
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CANDLE,
DyeColor.ORANGE to Items.ORANGE_CANDLE,
DyeColor.MAGENTA to Items.MAGENTA_CANDLE,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CANDLE,
DyeColor.YELLOW to Items.YELLOW_CANDLE,
DyeColor.LIME to Items.LIME_CANDLE,
DyeColor.PINK to Items.PINK_CANDLE,
DyeColor.GRAY to Items.GRAY_CANDLE,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CANDLE,
DyeColor.CYAN to Items.CYAN_CANDLE,
DyeColor.PURPLE to Items.PURPLE_CANDLE,
DyeColor.BLUE to Items.BLUE_CANDLE,
DyeColor.BROWN to Items.BROWN_CANDLE,
DyeColor.GREEN to Items.GREEN_CANDLE,
DyeColor.RED to Items.RED_CANDLE,
DyeColor.BLACK to Items.BLACK_CANDLE,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CONCRETE,
DyeColor.ORANGE to Items.ORANGE_CONCRETE,
DyeColor.MAGENTA to Items.MAGENTA_CONCRETE,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CONCRETE,
DyeColor.YELLOW to Items.YELLOW_CONCRETE,
DyeColor.LIME to Items.LIME_CONCRETE,
DyeColor.PINK to Items.PINK_CONCRETE,
DyeColor.GRAY to Items.GRAY_CONCRETE,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CONCRETE,
DyeColor.CYAN to Items.CYAN_CONCRETE,
DyeColor.PURPLE to Items.PURPLE_CONCRETE,
DyeColor.BLUE to Items.BLUE_CONCRETE,
DyeColor.BROWN to Items.BROWN_CONCRETE,
DyeColor.GREEN to Items.GREEN_CONCRETE,
DyeColor.RED to Items.RED_CONCRETE,
DyeColor.BLACK to Items.BLACK_CONCRETE,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CONCRETE_POWDER,
DyeColor.ORANGE to Items.ORANGE_CONCRETE_POWDER,
DyeColor.MAGENTA to Items.MAGENTA_CONCRETE_POWDER,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CONCRETE_POWDER,
DyeColor.YELLOW to Items.YELLOW_CONCRETE_POWDER,
DyeColor.LIME to Items.LIME_CONCRETE_POWDER,
DyeColor.PINK to Items.PINK_CONCRETE_POWDER,
DyeColor.GRAY to Items.GRAY_CONCRETE_POWDER,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CONCRETE_POWDER,
DyeColor.CYAN to Items.CYAN_CONCRETE_POWDER,
DyeColor.PURPLE to Items.PURPLE_CONCRETE_POWDER,
DyeColor.BLUE to Items.BLUE_CONCRETE_POWDER,
DyeColor.BROWN to Items.BROWN_CONCRETE_POWDER,
DyeColor.GREEN to Items.GREEN_CONCRETE_POWDER,
DyeColor.RED to Items.RED_CONCRETE_POWDER,
DyeColor.BLACK to Items.BLACK_CONCRETE_POWDER,
))
generate(consumer, MRegistry.CARGO_CRATES.item, MRegistry.CARGO_CRATES.items)
generate(consumer, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.items)
generate(consumer, MRegistry.TRITANIUM_STAIRS.item, MRegistry.TRITANIUM_STAIRS.items)
generate(consumer, MRegistry.TRITANIUM_SLAB.item, MRegistry.TRITANIUM_SLAB.items)
generate(consumer, MRegistry.TRITANIUM_WALL.item, MRegistry.TRITANIUM_WALL.items)
generate(consumer, Items.TERRACOTTA, mapOf(
DyeColor.WHITE to Items.WHITE_TERRACOTTA,
DyeColor.ORANGE to Items.ORANGE_TERRACOTTA,
DyeColor.MAGENTA to Items.MAGENTA_TERRACOTTA,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_TERRACOTTA,
DyeColor.YELLOW to Items.YELLOW_TERRACOTTA,
DyeColor.LIME to Items.LIME_TERRACOTTA,
DyeColor.PINK to Items.PINK_TERRACOTTA,
DyeColor.GRAY to Items.GRAY_TERRACOTTA,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_TERRACOTTA,
DyeColor.CYAN to Items.CYAN_TERRACOTTA,
DyeColor.PURPLE to Items.PURPLE_TERRACOTTA,
DyeColor.BLUE to Items.BLUE_TERRACOTTA,
DyeColor.BROWN to Items.BROWN_TERRACOTTA,
DyeColor.GREEN to Items.GREEN_TERRACOTTA,
DyeColor.RED to Items.RED_TERRACOTTA,
DyeColor.BLACK to Items.BLACK_TERRACOTTA,
), cleaning = false)
generate(consumer, Items.SHULKER_BOX, mapOf(
DyeColor.WHITE to Items.WHITE_SHULKER_BOX,
DyeColor.ORANGE to Items.ORANGE_SHULKER_BOX,
DyeColor.MAGENTA to Items.MAGENTA_SHULKER_BOX,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_SHULKER_BOX,
DyeColor.YELLOW to Items.YELLOW_SHULKER_BOX,
DyeColor.LIME to Items.LIME_SHULKER_BOX,
DyeColor.PINK to Items.PINK_SHULKER_BOX,
DyeColor.GRAY to Items.GRAY_SHULKER_BOX,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_SHULKER_BOX,
DyeColor.CYAN to Items.CYAN_SHULKER_BOX,
DyeColor.PURPLE to Items.PURPLE_SHULKER_BOX,
DyeColor.BLUE to Items.BLUE_SHULKER_BOX,
DyeColor.BROWN to Items.BROWN_SHULKER_BOX,
DyeColor.GREEN to Items.GREEN_SHULKER_BOX,
DyeColor.RED to Items.RED_SHULKER_BOX,
DyeColor.BLACK to Items.BLACK_SHULKER_BOX,
))
generate(consumer, Items.GLASS, mapOf(
DyeColor.WHITE to Items.WHITE_STAINED_GLASS,
DyeColor.ORANGE to Items.ORANGE_STAINED_GLASS,
DyeColor.MAGENTA to Items.MAGENTA_STAINED_GLASS,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_STAINED_GLASS,
DyeColor.YELLOW to Items.YELLOW_STAINED_GLASS,
DyeColor.LIME to Items.LIME_STAINED_GLASS,
DyeColor.PINK to Items.PINK_STAINED_GLASS,
DyeColor.GRAY to Items.GRAY_STAINED_GLASS,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_STAINED_GLASS,
DyeColor.CYAN to Items.CYAN_STAINED_GLASS,
DyeColor.PURPLE to Items.PURPLE_STAINED_GLASS,
DyeColor.BLUE to Items.BLUE_STAINED_GLASS,
DyeColor.BROWN to Items.BROWN_STAINED_GLASS,
DyeColor.GREEN to Items.GREEN_STAINED_GLASS,
DyeColor.RED to Items.RED_STAINED_GLASS,
DyeColor.BLACK to Items.BLACK_STAINED_GLASS,
))
generate(consumer, Items.GLASS_PANE, mapOf(
DyeColor.WHITE to Items.WHITE_STAINED_GLASS_PANE,
DyeColor.ORANGE to Items.ORANGE_STAINED_GLASS_PANE,
DyeColor.MAGENTA to Items.MAGENTA_STAINED_GLASS_PANE,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_STAINED_GLASS_PANE,
DyeColor.YELLOW to Items.YELLOW_STAINED_GLASS_PANE,
DyeColor.LIME to Items.LIME_STAINED_GLASS_PANE,
DyeColor.PINK to Items.PINK_STAINED_GLASS_PANE,
DyeColor.GRAY to Items.GRAY_STAINED_GLASS_PANE,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_STAINED_GLASS_PANE,
DyeColor.CYAN to Items.CYAN_STAINED_GLASS_PANE,
DyeColor.PURPLE to Items.PURPLE_STAINED_GLASS_PANE,
DyeColor.BLUE to Items.BLUE_STAINED_GLASS_PANE,
DyeColor.BROWN to Items.BROWN_STAINED_GLASS_PANE,
DyeColor.GREEN to Items.GREEN_STAINED_GLASS_PANE,
DyeColor.RED to Items.RED_STAINED_GLASS_PANE,
DyeColor.BLACK to Items.BLACK_STAINED_GLASS_PANE,
))
generate(consumer, MRegistry.INDUSTRIAL_GLASS.item, MRegistry.INDUSTRIAL_GLASS.items)
generate(consumer, MRegistry.INDUSTRIAL_GLASS_PANE.item, MRegistry.INDUSTRIAL_GLASS_PANE.items)
generate(consumer, MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.items)
generate(consumer, MRegistry.TRITANIUM_PRESSURE_PLATE.item, MRegistry.TRITANIUM_PRESSURE_PLATE.items)
generate(consumer, MItems.TRITANIUM_DOOR[null]!!, MItems.TRITANIUM_DOOR)
generate(consumer, MItems.TRITANIUM_TRAPDOOR[null]!!, MItems.TRITANIUM_TRAPDOOR)
generate(consumer, MRegistry.VENT.item, MRegistry.VENT.items)
generate(consumer, MRegistry.VENT_ALTERNATIVE.item, MRegistry.VENT_ALTERNATIVE.items)
generate(consumer, MItems.CARGO_CRATE_MINECARTS[null]!!, MItems.CARGO_CRATE_MINECARTS)
generate(consumer, MRegistry.UNREFINED_FLOOR_TILES.items)
generate(consumer, MRegistry.FLOOR_TILES.items)
generate(consumer, MRegistry.FLOOR_TILES_SLAB.items)
generate(consumer, MRegistry.FLOOR_TILES_STAIRS.items)
striped(consumer, "full", MRegistry.TRITANIUM_STRIPED_BLOCK.itemsWithColor, MRegistry.TRITANIUM_BLOCK.items)
striped(consumer, "stairs", MRegistry.TRITANIUM_STRIPED_STAIRS.itemsWithColor, MRegistry.TRITANIUM_STAIRS.items)
striped(consumer, "walls", MRegistry.TRITANIUM_STRIPED_WALL.itemsWithColor, MRegistry.TRITANIUM_WALL.items)
striped(consumer, "slabs", MRegistry.TRITANIUM_STRIPED_SLAB.itemsWithColor, MRegistry.TRITANIUM_SLAB.items)
for (color in DyeColor.entries) {
consumer.accept(PainterArmorDyeRecipe(modLocation("painter/armor_dye_" + color.getName().lowercase()), mapOf(color to 1)).toFinished())
}
consumer.accept(PainterArmorDyeRecipe(modLocation("painter/armor_clear_dye"), mapOf(null to 15)).toFinished())
}

View File

@ -1,79 +0,0 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.crafting.RecipeSerializer
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
class PlatePressFinishedRecipe(private val recipe: PlatePressRecipe) : FinishedRecipe {
override fun serializeRecipeData(it: JsonObject) {
it["input"] = recipe.input.toJson()
it["result"] = recipe.output.toJson().also {
if (it is JsonObject && recipe.count != 1)
it["count"] = JsonPrimitive(recipe.count)
}
it["work_time"] = JsonPrimitive(recipe.workTime)
}
override fun getId(): ResourceLocation {
return recipe.id
}
override fun getType(): RecipeSerializer<*> {
return PlatePressRecipeFactory
}
override fun serializeAdvancement(): JsonObject? {
return null
}
override fun getAdvancementId(): ResourceLocation? {
return null
}
}
class PlatePressShallowFinishedRecipe(
private val id: ResourceLocation,
private val input: ResourceLocation,
private val output: ResourceLocation,
private val count: Int = 1,
private val workTime: Int = 200
) : FinishedRecipe {
override fun serializeRecipeData(it: JsonObject) {
it["input"] = JsonObject().also {
it["tag"] = JsonPrimitive(input.toString())
}
it["result"] = JsonObject().also {
it["tag"] = JsonPrimitive(output.toString())
if (count != 1)
it["count"] = JsonPrimitive(count)
}
it["work_time"] = JsonPrimitive(workTime)
}
override fun getId(): ResourceLocation {
return id
}
override fun getType(): RecipeSerializer<*> {
return PlatePressRecipeFactory
}
override fun serializeAdvancement(): JsonObject? {
return null
}
override fun getAdvancementId(): ResourceLocation? {
return null
}
}

View File

@ -1,19 +1,29 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.util.valueproviders.ConstantFloat
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
fun addPlatePressRecipes(provider: MatteryRecipeProvider) { fun addPlatePressRecipes(provider: MatteryRecipeProvider) {
val baselineMetals = arrayOf("iron", "silver", "bronze", "lead", "constantan", "brass") val baselineMetals = arrayOf("iron" to 0.2f, "silver" to 0.3f, "bronze" to 0.3f, "lead" to 0.3f, "constantan" to 0.4f, "brass" to 0.3f)
val softMetals = arrayOf("gold", "aluminum", "aluminium", "copper", "electrum", "zinc") val softMetals = arrayOf("gold" to 0.4f, "aluminum" to 0.3f, "aluminium" to 0.3f, "copper" to 0.2f, "electrum" to 0.4f, "zinc" to 0.3f)
val hardMetals = arrayOf("tritanium", "steel", "tungsten", "uranium") val hardMetals = arrayOf("tritanium" to 0.5f, "steel" to 0.5f, "tungsten" to 0.55f, "uranium" to 0.5f)
for (thing in baselineMetals) { for ((thing, exp) in baselineMetals) {
provider.plate(thing) provider.plate(thing, experience = ConstantFloat.of(exp), workTicks = 160)
} }
for (thing in softMetals) { for ((thing, exp) in softMetals) {
provider.plate(thing, workTicks = 140) provider.plate(thing, workTicks = 120, experience = ConstantFloat.of(exp))
} }
for (thing in hardMetals) { for ((thing, exp) in hardMetals) {
provider.plate(thing, workTicks = 300) provider.plate(thing, workTicks = 240, experience = ConstantFloat.of(exp))
} }
provider.plate("carbon", result = Ingredient.of(MItemTags.CARBON_PLATES), ingredient = Ingredient.of(Items.COAL), workTicks = 140, experience = ConstantFloat.of(0.3f))
provider.plate("circuit_plating", result = Ingredient.of(MItems.CIRCUIT_PLATING), ingredient = Ingredient.of(Tags.Items.SAND), workTicks = 120, experience = ConstantFloat.of(0.2f))
} }

View File

@ -1,11 +1,16 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.ShapelessRecipeBuilder import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.tags.TagKey
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
@ -13,26 +18,50 @@ import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.function.Consumer import java.util.function.Consumer
fun addShapelessRecipes(consumer: Consumer<FinishedRecipe>) { typealias RecipeOutput = Consumer<FinishedRecipe>
for (color in DyeColor.values()) {
ShapelessRecipeBuilder(MItems.CARGO_CRATE_MINECARTS[color]!!, 1) fun hammerRecipe(output: ItemLike, input: ItemLike, consumer: RecipeOutput) {
ShapelessRecipeBuilder(RecipeCategory.MISC, output, 1)
.requires(MItemTags.TOOLS_HAMMERS)
.requires(input)
.unlockedBy(MItemTags.TOOLS_HAMMERS)
.unlockedBy(input)
.save(consumer)
}
fun hammerRecipe(output: ItemLike, input: TagKey<Item>, consumer: RecipeOutput) {
ShapelessRecipeBuilder(RecipeCategory.MISC, output, 1)
.requires(MItemTags.TOOLS_HAMMERS)
.requires(input)
.unlockedBy(MItemTags.TOOLS_HAMMERS)
.unlockedBy(input)
.save(consumer)
}
fun addShapelessRecipes(consumer: RecipeOutput) {
for (color in DyeColor.entries) {
ShapelessRecipeBuilder(RecipeCategory.TRANSPORTATION, MItems.CARGO_CRATE_MINECARTS[color]!!, 1)
.requires(Items.MINECART) .requires(Items.MINECART)
.requires(MRegistry.CARGO_CRATES.items[color]!!) .requires(MRegistry.CARGO_CRATES.items[color]!!)
.unlockedBy(Items.MINECART) .unlockedBy(Items.MINECART)
.unlockedBy(MRegistry.CARGO_CRATES.items[color]!!) .unlockedBy(MRegistry.CARGO_CRATES.items[color]!!)
.save(consumer) .save(consumer)
ShapelessRecipeBuilder(MItems.CARGO_CRATE_MINECARTS[color]!!, 1) ShapelessRecipeBuilder(RecipeCategory.TRANSPORTATION, MItems.CARGO_CRATE_MINECARTS[color]!!, 1)
.requires(Ingredient.of(MItems.CARGO_CRATE_MINECARTS.entries.stream().filter { it.key != color }.map { ItemStack(it.value) })) .requires(Ingredient.of(MItems.CARGO_CRATE_MINECARTS.entries.stream().filter { it.key != color }.map { ItemStack(it.value) }))
.requires(color.tag) .requires(color.tag)
.unlockedBy(MItems.CARGO_CRATE_MINECARTS.entries.stream().filter { it.key != color }.map { it.value }) .unlockedBy(MItems.CARGO_CRATE_MINECARTS.entries.stream().filter { it.key != color }.map { it.value })
.save(consumer, modLocation(MItems.CARGO_CRATE_MINECARTS[color]!!.registryName!!.path + "_alt")) .save(consumer, modLocation(MItems.CARGO_CRATE_MINECARTS[color]!!.registryName!!.path + "_alt"))
} }
ShapelessRecipeBuilder(MItems.CARGO_CRATE_MINECARTS[null]!!, 1) ShapelessRecipeBuilder(RecipeCategory.TRANSPORTATION, MItems.CARGO_CRATE_MINECARTS[null]!!, 1)
.requires(Items.MINECART) .requires(Items.MINECART)
.requires(MRegistry.CARGO_CRATES.item) .requires(MRegistry.CARGO_CRATES.item)
.unlockedBy(Items.MINECART) .unlockedBy(Items.MINECART)
.unlockedBy(MRegistry.CARGO_CRATES.item) .unlockedBy(MRegistry.CARGO_CRATES.item)
.save(consumer) .save(consumer)
hammerRecipe(MItems.TRITANIUM_PLATE, MItemTags.TRITANIUM_INGOTS, consumer)
hammerRecipe(MItems.IRON_PLATE, Tags.Items.INGOTS_IRON, consumer)
hammerRecipe(MItems.GOLD_PLATE, Tags.Items.INGOTS_GOLD, consumer)
} }

View File

@ -1,12 +1,13 @@
package ru.dbotthepony.mc.otm.datagen.tags package ru.dbotthepony.mc.otm.datagen.tags
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.BlockTags import net.minecraft.tags.BlockTags
import net.minecraft.tags.ItemTags import net.minecraft.tags.ItemTags
import net.minecraft.world.effect.MobEffects import net.minecraft.world.effect.MobEffects
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.Tiers import net.minecraft.world.item.Tiers
import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.Blocks
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.registry.MBlockTags import ru.dbotthepony.mc.otm.registry.MBlockTags
import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
@ -20,16 +21,26 @@ fun addTags(tagsProvider: TagsProvider) {
tagsProvider.dusts.add("tritanium", MItems.TRITANIUM_DUST) tagsProvider.dusts.add("tritanium", MItems.TRITANIUM_DUST)
tagsProvider.ingots.add("tritanium", MItems.TRITANIUM_INGOT) tagsProvider.ingots.add("tritanium", MItems.TRITANIUM_INGOT)
tagsProvider.items.Appender(ItemTags.BEACON_PAYMENT_ITEMS).add(MItems.TRITANIUM_INGOT)
tagsProvider.plates.add("tritanium", MItems.TRITANIUM_PLATE) tagsProvider.plates.add("tritanium", MItems.TRITANIUM_PLATE)
tagsProvider.plates.add("iron", MItems.IRON_PLATE) tagsProvider.plates.add("iron", MItems.IRON_PLATE)
tagsProvider.plates.add("gold", MItems.GOLD_PLATE) tagsProvider.plates.add("gold", MItems.GOLD_PLATE)
tagsProvider.plates.add("carbon", MItems.CARBON_MESH)
tagsProvider.items.forge("reinforced_tritanium").add(MItems.REINFORCED_TRITANIUM_PLATE)
tagsProvider.storageBlocksAsItem.add("tritanium", MItems.TRITANIUM_INGOT_BLOCK) tagsProvider.storageBlocksAsItem.add("tritanium", MItems.TRITANIUM_INGOT_BLOCK)
tagsProvider.storageBlocksAsBlock.add("tritanium", MBlocks.TRITANIUM_INGOT_BLOCK) tagsProvider.storageBlocksAsBlock.add("tritanium", MBlocks.TRITANIUM_INGOT_BLOCK)
tagsProvider.blocks.Appender(BlockTags.BEACON_BASE_BLOCKS).add(MBlocks.TRITANIUM_INGOT_BLOCK)
tagsProvider.stoneOre("tritanium", MBlocks.TRITANIUM_ORE)
tagsProvider.deepslateOre("tritanium", MBlocks.DEEPSLATE_TRITANIUM_ORE)
tagsProvider.singleDropOre(
MBlocks.TRITANIUM_ORE,
MBlocks.DEEPSLATE_TRITANIUM_ORE
)
tagsProvider.ore("tritanium", MBlocks.TRITANIUM_ORE)
tagsProvider.ore("tritanium", MBlocks.DEEPSLATE_TRITANIUM_ORE)
tagsProvider.clump("tritanium", MItems.TRITANIUM_ORE_CLUMP, MBlocks.TRITANIUM_RAW_BLOCK) tagsProvider.clump("tritanium", MItems.TRITANIUM_ORE_CLUMP, MBlocks.TRITANIUM_RAW_BLOCK)
tagsProvider.wires.add("copper", MItems.COPPER_WIRING) tagsProvider.wires.add("copper", MItems.COPPER_WIRING)
@ -40,10 +51,21 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.STORAGE_CABLE MBlocks.STORAGE_CABLE
) )
tagsProvider.items.appender(MItemTags.CRAFTING_TABLES).add(Items.CRAFTING_TABLE) tagsProvider.items.Appender(MItemTags.CRAFTING_TABLES).add(Items.CRAFTING_TABLE)
tagsProvider.blocks.appender(MBlockTags.CRAFTING_TABLES).add(Blocks.CRAFTING_TABLE) tagsProvider.items.Appender(MItemTags.WORKBENCHES).add(Items.CRAFTING_TABLE)
tagsProvider.items.Appender(MItemTags.WORKBENCH).add(Items.CRAFTING_TABLE)
tagsProvider.blocks.Appender(MBlockTags.CRAFTING_TABLES).add(Blocks.CRAFTING_TABLE)
tagsProvider.blocks.Appender(MBlockTags.WORKBENCHES).add(Blocks.CRAFTING_TABLE)
tagsProvider.blocks.Appender(MBlockTags.WORKBENCH).add(Blocks.CRAFTING_TABLE)
tagsProvider.items.appender(MItemTags.MINECART_CARGO_CRATES).add(MItems.CARGO_CRATE_MINECARTS.values) tagsProvider.items.Appender(MItemTags.CRAFTING_TABLES)
.add(MItemTags.WORKBENCHES)
.add(MItemTags.WORKBENCH)
tagsProvider.blocks.Appender(MBlockTags.CRAFTING_TABLES)
.add(MBlockTags.WORKBENCHES)
.add(MBlockTags.WORKBENCH)
tagsProvider.items.Appender(MItemTags.MINECART_CARGO_CRATES).add(MItems.CARGO_CRATE_MINECARTS.values)
tagsProvider.items.forge("hardened_glass").add(MRegistry.INDUSTRIAL_GLASS.allItems.values) tagsProvider.items.forge("hardened_glass").add(MRegistry.INDUSTRIAL_GLASS.allItems.values)
tagsProvider.items.forge("hardened_glass/colorless").add(MRegistry.INDUSTRIAL_GLASS.item) tagsProvider.items.forge("hardened_glass/colorless").add(MRegistry.INDUSTRIAL_GLASS.item)
@ -67,51 +89,88 @@ fun addTags(tagsProvider: TagsProvider) {
MRegistry.INDUSTRIAL_GLASS.forEachBlock { s, _, block -> tagsProvider.blocks.forge("hardened_glass/$s").add(block) } MRegistry.INDUSTRIAL_GLASS.forEachBlock { s, _, block -> tagsProvider.blocks.forge("hardened_glass/$s").add(block) }
MRegistry.INDUSTRIAL_GLASS_PANE.forEachBlock { s, _, block -> tagsProvider.blocks.forge("hardened_glass_panes/$s").add(block) } MRegistry.INDUSTRIAL_GLASS_PANE.forEachBlock { s, _, block -> tagsProvider.blocks.forge("hardened_glass_panes/$s").add(block) }
tagsProvider.items.appender(MItemTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allItems.values) tagsProvider.items.Appender(MItemTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allItems.values)
tagsProvider.blocks.appender(MBlockTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allBlocks.values) tagsProvider.blocks.Appender(MBlockTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
tagsProvider.blocks.appender(MBlockTags.CARGO_CRATES).add(MRegistry.CARGO_CRATES.allBlocks.values) tagsProvider.blocks.Appender(MBlockTags.CARGO_CRATES).add(MRegistry.CARGO_CRATES.allBlocks.values)
tagsProvider.items.appender(ItemTags.DOORS).add(MItems.TRITANIUM_DOOR.values) tagsProvider.items.Appender(ItemTags.DOORS).add(MItems.TRITANIUM_DOOR.values)
tagsProvider.blocks.appender(BlockTags.DOORS).add(MBlocks.TRITANIUM_DOOR.values) tagsProvider.blocks.Appender(BlockTags.DOORS).add(MBlocks.TRITANIUM_DOOR.values)
tagsProvider.items.appender(ItemTags.TRAPDOORS).add(MItems.TRITANIUM_TRAPDOOR.values) tagsProvider.items.Appender(ItemTags.TRAPDOORS).add(MItems.TRITANIUM_TRAPDOOR.values)
tagsProvider.blocks.appender(BlockTags.TRAPDOORS).add(MBlocks.TRITANIUM_TRAPDOOR.values) tagsProvider.blocks.Appender(BlockTags.TRAPDOORS).add(MBlocks.TRITANIUM_TRAPDOOR.values)
tagsProvider.blocks.appender(BlockTags.PRESSURE_PLATES).add(MRegistry.TRITANIUM_PRESSURE_PLATE.allBlocks.values) tagsProvider.blocks.Appender(BlockTags.PRESSURE_PLATES).add(MRegistry.TRITANIUM_PRESSURE_PLATE.allBlocks.values)
tagsProvider.items.appender(MItemTags.MACHINES).add(MItems.MACHINES) tagsProvider.items.Appender(MItemTags.MACHINES).add(MItems.MACHINES)
tagsProvider.blocks.appender(MBlockTags.MACHINES).add(MItems.MACHINES.stream().map { it as? BlockItem }.filter { it != null }.map { it!!.block }) tagsProvider.blocks.Appender(MBlockTags.MACHINES).add(MItems.MACHINES.stream().map { it!!.block })
tagsProvider.blocks.appender(BlockTags.STAIRS) tagsProvider.blocks.Appender(BlockTags.ANVIL).add(MBlocks.TRITANIUM_ANVIL)
tagsProvider.items.Appender(ItemTags.ANVIL).add(MItems.TRITANIUM_ANVIL)
tagsProvider.items.Appender(MItemTags.TRITANIUM_NUGGETS).add(MItems.TRITANIUM_NUGGET)
tagsProvider.items.Appender(MItemTags.NUGGETS).add(MItems.TRITANIUM_NUGGET)
tagsProvider.items.Appender(Tags.Items.ARMORS_HELMETS)
.add(MItems.TRITANIUM_HELMET, MItems.SIMPLE_TRITANIUM_HELMET)
tagsProvider.items.Appender(Tags.Items.ARMORS_CHESTPLATES)
.add(MItems.TRITANIUM_CHESTPLATE, MItems.SIMPLE_TRITANIUM_CHESTPLATE, MItems.PORTABLE_GRAVITATION_STABILIZER)
tagsProvider.items.Appender(Tags.Items.ARMORS_LEGGINGS)
.add(MItems.TRITANIUM_PANTS, MItems.SIMPLE_TRITANIUM_PANTS)
tagsProvider.items.Appender(Tags.Items.ARMORS_BOOTS)
.add(MItems.TRITANIUM_BOOTS, MItems.SIMPLE_TRITANIUM_BOOTS)
tagsProvider.items.Appender(ItemTags.FREEZE_IMMUNE_WEARABLES).add(MItems.TRITANIUM_ARMOR)
tagsProvider.items.Appender(Tags.Items.SHEARS).add(MItems.TRITANIUM_SHEARS)
tagsProvider.items.Appender(Tags.Items.TOOLS_SHIELDS).add(MItems.TRITANIUM_SHIELD)
tagsProvider.items.Appender(MItemTags.TOOLS_HAMMERS).add(MItems.EXPLOSIVE_HAMMER)
tagsProvider.items.forge("tools").add(MItemTags.TOOLS_HAMMERS)
tagsProvider.items.Appender(MItemTags.UPGRADES)
.add(MItems.MachineUpgrades.Basic.LIST)
.add(MItems.MachineUpgrades.Normal.LIST)
.add(MItems.MachineUpgrades.Advanced.LIST)
.add(MItems.MachineUpgrades.Creative.LIST)
tagsProvider.blocks.Appender(BlockTags.STAIRS)
.add(MRegistry.FLOOR_TILES_STAIRS.blocks.values) .add(MRegistry.FLOOR_TILES_STAIRS.blocks.values)
.add(MRegistry.TRITANIUM_STAIRS.allBlocks.values) .add(MRegistry.TRITANIUM_STAIRS.allBlocks.values)
.add(MRegistry.TRITANIUM_STRIPED_STAIRS.flatBlocks) .add(MRegistry.TRITANIUM_STRIPED_STAIRS.flatBlocks)
.add(MBlocks.TRITANIUM_STRIPED_STAIRS) .add(MBlocks.TRITANIUM_STRIPED_STAIRS)
tagsProvider.blocks.appender(BlockTags.SLABS) tagsProvider.blocks.Appender(BlockTags.SLABS)
.add(MRegistry.TRITANIUM_SLAB.allBlocks.values) .add(MRegistry.TRITANIUM_SLAB.allBlocks.values)
.add(MRegistry.TRITANIUM_STRIPED_SLAB.flatBlocks) .add(MRegistry.TRITANIUM_STRIPED_SLAB.flatBlocks)
.add(MRegistry.FLOOR_TILES_SLAB.blocks.values) .add(MRegistry.FLOOR_TILES_SLAB.blocks.values)
.add(MBlocks.TRITANIUM_STRIPED_SLAB) .add(MBlocks.TRITANIUM_STRIPED_SLAB)
tagsProvider.blocks.appender(BlockTags.WALLS) tagsProvider.blocks.Appender(BlockTags.WALLS)
.add(MRegistry.TRITANIUM_WALL.allBlocks.values) .add(MRegistry.TRITANIUM_WALL.allBlocks.values)
.add(MRegistry.TRITANIUM_STRIPED_WALL.flatBlocks) .add(MRegistry.TRITANIUM_STRIPED_WALL.flatBlocks)
.add(MBlocks.TRITANIUM_STRIPED_WALL) .add(MBlocks.TRITANIUM_STRIPED_WALL)
tagsProvider.items.appender(ItemTags.SLABS) tagsProvider.items.Appender(ItemTags.STAIRS)
.add(MRegistry.FLOOR_TILES_STAIRS.items.values)
.add(MRegistry.TRITANIUM_STAIRS.allItems.values)
.add(MRegistry.TRITANIUM_STRIPED_STAIRS.flatItems)
.add(MItems.TRITANIUM_STRIPED_STAIRS)
tagsProvider.items.Appender(ItemTags.SLABS)
.add(MRegistry.TRITANIUM_SLAB.allItems.values) .add(MRegistry.TRITANIUM_SLAB.allItems.values)
.add(MRegistry.TRITANIUM_STRIPED_SLAB.flatItems) .add(MRegistry.TRITANIUM_STRIPED_SLAB.flatItems)
.add(MRegistry.FLOOR_TILES_SLAB.items.values) .add(MRegistry.FLOOR_TILES_SLAB.items.values)
.add(MItems.TRITANIUM_STRIPED_SLAB) .add(MItems.TRITANIUM_STRIPED_SLAB)
tagsProvider.items.appender(ItemTags.WALLS) tagsProvider.items.Appender(ItemTags.WALLS)
.add(MRegistry.TRITANIUM_WALL.allItems.values) .add(MRegistry.TRITANIUM_WALL.allItems.values)
.add(MRegistry.TRITANIUM_STRIPED_WALL.flatItems) .add(MRegistry.TRITANIUM_STRIPED_WALL.flatItems)
.add(MItems.TRITANIUM_STRIPED_WALL) .add(MItems.TRITANIUM_STRIPED_WALL)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_DOOR.values, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_DOOR.values, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_TRAPDOOR.values, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_TRAPDOOR.values, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.PAINTER, Tiers.STONE)
tagsProvider.requiresPickaxe(MBlocks.ENERGY_CABLES.values, Tiers.STONE)
tagsProvider.requiresPickaxe(listOf( tagsProvider.requiresPickaxe(listOf(
MBlocks.ANDROID_STATION, MBlocks.ANDROID_STATION,
@ -126,7 +185,13 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.ENERGY_COUNTER, MBlocks.ENERGY_COUNTER,
MBlocks.CHEMICAL_GENERATOR, MBlocks.CHEMICAL_GENERATOR,
MBlocks.PLATE_PRESS, MBlocks.PLATE_PRESS,
MBlocks.TWIN_PLATE_PRESS,
MBlocks.MATTER_RECYCLER, MBlocks.MATTER_RECYCLER,
MBlocks.MATTER_ENTANGLER,
MBlocks.POWERED_FURNACE,
MBlocks.POWERED_SMOKER,
MBlocks.POWERED_BLAST_FURNACE,
MBlocks.STORAGE_BUS, MBlocks.STORAGE_BUS,
MBlocks.STORAGE_IMPORTER, MBlocks.STORAGE_IMPORTER,
@ -141,8 +206,21 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.ENERGY_SERVO, MBlocks.ENERGY_SERVO,
MBlocks.TRITANIUM_INGOT_BLOCK, MBlocks.TRITANIUM_INGOT_BLOCK,
MBlocks.METAL_JUNK,
MBlocks.METAL_MESH,
MBlocks.TRITANIUM_BARS,
MBlocks.ENGINE,
MBlocks.HOLO_SIGN,
MBlocks.COBBLESTONE_GENERATOR,
MBlocks.ESSENCE_STORAGE,
MBlocks.MATTER_RECONSTRUCTOR,
MBlocks.FLUID_TANK,
MBlocks.ANDROID_CHARGER,
), Tiers.IRON) ), Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_ANVIL, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_ORE, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_ORE, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.DEEPSLATE_TRITANIUM_ORE, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.DEEPSLATE_TRITANIUM_ORE, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_RAW_BLOCK, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_RAW_BLOCK, Tiers.IRON)
@ -153,6 +231,8 @@ fun addTags(tagsProvider: TagsProvider) {
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_STRIPED_SLAB, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_STRIPED_SLAB, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.CARBON_FIBRE_BLOCK, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.CARBON_FIBRE_BLOCK, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.INFINITE_WATER_SOURCE, Tiers.STONE)
tagsProvider.requiresPickaxe(MRegistry.CARGO_CRATES.allBlocks.values, Tiers.IRON) tagsProvider.requiresPickaxe(MRegistry.CARGO_CRATES.allBlocks.values, Tiers.IRON)
tagsProvider.requiresPickaxe(MRegistry.VENT.allBlocks.values, Tiers.IRON) tagsProvider.requiresPickaxe(MRegistry.VENT.allBlocks.values, Tiers.IRON)
@ -196,6 +276,12 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.BLACK_HOLE, MBlocks.BLACK_HOLE,
) )
tagsProvider.guardedByPiglins.add(
MBlockTags.CARGO_CRATES,
)
tagsProvider.impermeable.add(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
tagsProvider.androidImmuneEffects.add( tagsProvider.androidImmuneEffects.add(
MobEffects.CONDUIT_POWER, MobEffects.CONDUIT_POWER,
MobEffects.HEAL, MobEffects.HEAL,
@ -212,4 +298,9 @@ fun addTags(tagsProvider: TagsProvider) {
MobEffects.DOLPHINS_GRACE, MobEffects.DOLPHINS_GRACE,
MobEffects.CONFUSION, MobEffects.CONFUSION,
) )
tagsProvider.androidImmuneEffects.add(
ResourceLocation("rats", "plague"),
ResourceLocation("rats", "synesthesia"),
)
} }

View File

@ -1,7 +1,11 @@
package ru.dbotthepony.mc.otm.datagen.tags package ru.dbotthepony.mc.otm.datagen.tags
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.core.HolderLookup
import net.minecraft.core.Registry import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.BlockTags import net.minecraft.tags.BlockTags
import net.minecraft.tags.GameEventTags import net.minecraft.tags.GameEventTags
@ -10,191 +14,212 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.Tier import net.minecraft.world.item.Tier
import net.minecraft.world.item.Tiers import net.minecraft.world.item.Tiers
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraftforge.common.Tags
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.IForgeRegistry
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import java.util.stream.Stream import java.util.stream.Stream
import net.minecraft.data.tags.TagsProvider as MinecraftTagsProvider import net.minecraft.data.tags.TagsProvider as MinecraftTagsProvider
interface MTagAppender<T> { private fun <T : Any> vanillaLookup(key: ResourceKey<Registry<T>>): (T) -> ResourceLocation {
fun add(value: T): MTagAppender<T> val registry by lazy { (BuiltInRegistries.REGISTRY.get(key.location()) ?: throw NoSuchElementException("No such registry $key")) as Registry<T> }
fun addSafe(value: T): Boolean return { registry.getKey(it) ?: throw NoSuchElementException("Registry $key does not contain $it") }
fun add(vararg values: T): MTagAppender<T>
fun addSafe(vararg values: T): Boolean {
var any = false
for (value in values) any = addSafe(value)
return any
}
fun add(values: Collection<T>): MTagAppender<T>
fun add(values: Stream<out T>): MTagAppender<T> = add(values.toList())
fun addSafe(values: Collection<T>): Boolean {
var any = false
for (value in values) any = addSafe(value)
return any
}
} }
interface ForgeTagAppender<T> : MTagAppender<T> { class TagsProvider(private val event: GatherDataEvent) {
fun add(key: String, value: T): MTagAppender<T> inner class Delegate<T : Any> private constructor(key: ResourceKey<Registry<T>>, val lookup: (T) -> ResourceLocation) : MinecraftTagsProvider<T>(event.generator.packOutput, key, event.lookupProvider, DataGen.MOD_ID, event.existingFileHelper) {
fun addSafe(key: String, value: T): Boolean constructor(registry: IForgeRegistry<T>) : this(registry.registryKey, { registry.getKey(it) ?: throw NoSuchElementException("Registry $registry does not contain $it") })
fun add(key: String, vararg values: T): MTagAppender<T> constructor(key: ResourceKey<Registry<T>>) : this(key, vanillaLookup(key))
fun addSafe(key: String, vararg values: T): Boolean {
var any = false
for (value in values) any = addSafe(key, value)
return any
}
fun add(key: String, values: Collection<T>): MTagAppender<T>
fun addSafe(key: String, values: Collection<T>): Boolean {
var any = false
for (value in values) any = addSafe(key, value)
return any
}
}
class TagsProvider(
private val event: GatherDataEvent
) {
inner class Delegate<T>(registry: Registry<T>) : MinecraftTagsProvider<T>(event.generator, registry, DataGen.MOD_ID, event.existingFileHelper) {
init { init {
event.generator.addProvider(true, this) if (isRegistered)
event.generator.addProvider(event.includeServer(), this)
else
delegates.add(this)
} }
private val tags = HashMap<TagKey<T>, ObjectArraySet<T>>() private val tags = HashMap<TagKey<T>, ObjectArraySet<ResourceLocation>>()
private val rigidTags = HashMap<TagKey<T>, ObjectArraySet<ResourceKey<T>>>()
private val tagInTag = HashMap<TagKey<T>, ObjectArraySet<TagKey<T>>>()
override fun addTags() { inner class Appender(val tag: TagKey<T>) {
if (tags.isEmpty()) { constructor(tag: ResourceLocation) : this(TagKey.create(registryKey, tag))
return
init {
require(tag.registry == registryKey) { "Trying to create appender for $tag inside registry $registryKey" }
} }
for ((tag, values) in tags) { private val locations by lazy { tags.computeIfAbsent(tag) { ObjectArraySet() } }
tag(tag).also { private val rigidLocations by lazy { rigidTags.computeIfAbsent(tag) { ObjectArraySet() } }
for (value in values) { private val tagsInTags by lazy { tagInTag.computeIfAbsent(tag) { ObjectArraySet() } }
it.add(value)
}
}
}
}
fun getSet(tag: TagKey<T>): MutableSet<T> {
return tags.computeIfAbsent(tag) { ObjectArraySet() }
}
fun getSet(location: ResourceLocation) = getSet(TagKey.create(registry.key(), location))
fun appender(tag: TagKey<T>, message: ((T) -> Any) = { "$it is already in $tag" }): MTagAppender<T> {
val list = getSet(tag)
return object : MTagAppender<T> {
override fun add(value: T): MTagAppender<T> {
if (!list.add(value)) {
throw IllegalStateException(message.invoke(value).toString())
}
fun add(value: ResourceLocation): Appender {
check(locations.add(value)) { "Tag ${tag.location} of registry ${registryKey.location()} already contains $value" }
return this return this
} }
override fun add(values: Collection<T>): MTagAppender<T> { fun add(value: ResourceKey<T>): Appender {
require(value.registry() == registryKey.location()) { "Invalid registry in provided ResourceKey: ${value.registry()} (this tag appender is for ${registryKey.location()})" }
// check(rigidLocations.add(value)) { "Tag ${tag.location} of registry ${registryKey.location()} already contains $value" }
// return this
return add(value.location())
}
fun add(value: TagKey<T>): Appender {
require(value.registry() == registryKey) { "Invalid registry in provided ResourceKey: ${value.registry().location()} (this tag appender is for ${registryKey.location()})" }
check(tagsInTags.add(value)) { "Tag ${tag.location} of registry ${registryKey.location()} already contains $value" }
return this
}
fun add(value: T): Appender {
return add(ResourceKey.create(registryKey, lookup.invoke(value)))
}
fun add(values: Collection<T>): Appender {
for (value in values) add(value) for (value in values) add(value)
return this return this
} }
override fun addSafe(value: T): Boolean { fun add(vararg values: T): Appender {
return list.add(value) for (value in values) add(value)
}
override fun add(vararg values: T): MTagAppender<T> {
values.forEach(this::add)
return this return this
} }
fun add(vararg values: ResourceKey<T>): Appender {
for (value in values) add(value)
return this
}
fun add(vararg values: TagKey<T>): Appender {
for (value in values) add(value)
return this
}
fun add(vararg values: ResourceLocation): Appender {
for (value in values) add(value)
return this
}
fun add(values: Stream<T>): Appender {
values.forEach { add(it) }
return this
}
fun leaf(name: String) = Appender(TagKey.create(tag.registry, ResourceLocation(tag.location.namespace, tag.location.path + "/$name")))
fun add(leaf: String, value: T) = also { leaf(leaf).add(value) }
fun add(leaf: String, value: TagKey<T>) = also { leaf(leaf).add(value) }
fun add(leaf: String, vararg value: T) = also { leaf(leaf).add(*value) }
fun add(leaf: String, vararg value: TagKey<T>) = also { leaf(leaf).add(*value) }
fun add(leaf: String, value: Stream<T>) = also { leaf(leaf).add(value) }
fun add(leaf: String, value: ResourceKey<T>) = also { leaf(leaf).add(value) }
fun add(leaf: String, vararg value: ResourceKey<T>) = also { leaf(leaf).add(*value) }
fun add(leaf: String, value: ResourceLocation) = also { leaf(leaf).add(value) }
fun add(leaf: String, vararg value: ResourceLocation) = also { leaf(leaf).add(*value) }
}
fun forge(path: String) = Appender(ResourceLocation("forge", path))
fun minecraft(path: String) = Appender(ResourceLocation("minecraft", path))
override fun addTags(provider: HolderLookup.Provider) {
for ((tag, values) in tags) {
val appender = tag(tag)
for (value in values) {
appender.addOptional(value)
} }
} }
fun forge(path: String): ForgeTagAppender<T> { for ((tag, values) in rigidTags) {
val parent by lazy { appender(ResourceLocation("forge", path)) } val appender = tag(tag)
return object : ForgeTagAppender<T> { for (value in values) {
override fun add(key: String, value: T): MTagAppender<T> { appender.add(value)
val tag = TagKey.create(registry.key(), ResourceLocation("forge", "$path/$key"))
if (!getSet(tag).add(value)) {
throw IllegalStateException("$value is already in $tag")
} }
}
for ((tag, values) in tagInTag) {
val appender = tag(tag)
for (value in values) {
appender.addTag(value)
}
}
}
}
private val delegates = ArrayList<Delegate<*>>()
private var isRegistered = false
fun register() {
if (!isRegistered) {
isRegistered = true
for (value in delegates) {
event.generator.addProvider(event.includeServer(), value)
}
delegates.clear()
}
}
val blocks = Delegate(ForgeRegistries.BLOCKS)
val items = Delegate(ForgeRegistries.ITEMS)
val mobEffects = Delegate(ForgeRegistries.MOB_EFFECTS)
val androidImmuneEffects = mobEffects.Appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS)
val requiresShovel = blocks.Appender(BlockTags.MINEABLE_WITH_SHOVEL)
val requiresAxe = blocks.Appender(BlockTags.MINEABLE_WITH_AXE)
val requiresHoe = blocks.Appender(BlockTags.MINEABLE_WITH_HOE)
val requiresPickaxe = blocks.Appender(BlockTags.MINEABLE_WITH_PICKAXE)
val requiresStoneTool = blocks.Appender(BlockTags.NEEDS_STONE_TOOL)
val requiresIronTool = blocks.Appender(BlockTags.NEEDS_IRON_TOOL)
val requiresDiamondTool = blocks.Appender(BlockTags.NEEDS_DIAMOND_TOOL)
val witherImmune = blocks.Appender(BlockTags.WITHER_IMMUNE)
val dragonImmune = blocks.Appender(BlockTags.DRAGON_IMMUNE)
val guardedByPiglins = blocks.Appender(BlockTags.GUARDED_BY_PIGLINS)
val impermeable = blocks.Appender(BlockTags.IMPERMEABLE)
fun stoneOre(key: String, block: Block): TagsProvider {
ore(key, block)
itemGroundOresStone.add(block.asItem())
blockGroundOresStone.add(block)
return this return this
} }
override fun addSafe(key: String, value: T): Boolean { fun deepslateOre(key: String, block: Block): TagsProvider {
val tag = TagKey.create(registry.key(), ResourceLocation("forge", "$path/$key")) ore(key, block)
return getSet(tag).add(value)
} itemGroundOresDeepslate.add(block.asItem())
blockGroundOresDeepslate.add(block)
override fun add(key: String, vararg values: T): MTagAppender<T> {
for (value in values) add(key, value)
return this return this
} }
override fun add(key: String, values: Collection<T>): MTagAppender<T> { fun singleDropOre(vararg blocks: Block): TagsProvider {
for (value in values) add(key, value) for (block in blocks) {
itemOreRatesSingular.add(block.asItem())
blockOreRatesSingular.add(block)
}
return this return this
} }
override fun add(value: T): MTagAppender<T> {
return parent.add(value)
}
override fun addSafe(value: T): Boolean {
return parent.addSafe(value)
}
override fun add(vararg values: T): MTagAppender<T> {
return parent.add(*values)
}
override fun add(values: Collection<T>): MTagAppender<T> {
return parent.add(values)
}
}
}
fun appender(location: ResourceLocation): MTagAppender<T> {
return appender(TagKey.create(registry.key(), location))
}
fun appender(location: ResourceLocation, message: (T) -> Any): MTagAppender<T> {
return appender(TagKey.create(registry.key(), location), message)
}
}
val blocks = Delegate(Registry.BLOCK)
val items = Delegate(Registry.ITEM)
val mobEffects = Delegate(Registry.MOB_EFFECT)
val androidImmuneEffects = mobEffects.appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS)
val requiresShovel = blocks.appender(BlockTags.MINEABLE_WITH_SHOVEL)
val requiresAxe = blocks.appender(BlockTags.MINEABLE_WITH_AXE)
val requiresHoe = blocks.appender(BlockTags.MINEABLE_WITH_HOE)
val requiresPickaxe = blocks.appender(BlockTags.MINEABLE_WITH_PICKAXE)
val requiresStoneTool = blocks.appender(BlockTags.NEEDS_STONE_TOOL)
val requiresIronTool = blocks.appender(BlockTags.NEEDS_IRON_TOOL)
val requiresDiamondTool = blocks.appender(BlockTags.NEEDS_DIAMOND_TOOL)
val witherImmune = blocks.appender(BlockTags.WITHER_IMMUNE)
val dragonImmune = blocks.appender(BlockTags.DRAGON_IMMUNE)
fun ore(key: String, block: Block): TagsProvider { fun ore(key: String, block: Block): TagsProvider {
val forgeKey = ResourceLocation("forge", "ores/$key") val forgeKey = ResourceLocation("forge", "ores/$key")
val b = TagKey.create(Registry.BLOCK_REGISTRY, forgeKey) val b = TagKey.create(Registries.BLOCK, forgeKey)
val i = TagKey.create(Registry.ITEM_REGISTRY, forgeKey) val i = TagKey.create(Registries.ITEM, forgeKey)
items.getSet(i).add(block.asItem()) items.Appender(i).add(block.asItem())
itemOres.add(block.asItem()) itemOres.add(block.asItem())
blocks.getSet(b).add(block) blocks.Appender(b).add(block)
blockOres.add(block) blockOres.add(block)
return this return this
@ -220,18 +245,32 @@ class TagsProvider(
} }
val circuits = items.forge("circuits") val circuits = items.forge("circuits")
val dusts = items.forge("dusts") val dusts = items.Appender(Tags.Items.DUSTS)
val ingots = items.forge("ingots") val ingots = items.Appender(Tags.Items.INGOTS)
val itemOres = items.forge("ores") val itemOres = items.Appender(Tags.Items.ORES)
val blockOres = blocks.forge("ores") val blockOres = blocks.Appender(Tags.Blocks.ORES)
val plates = items.forge("plates") val plates = items.forge("plates")
val storageBlocksAsItem = items.forge("storage_blocks") val storageBlocksAsItem = items.Appender(Tags.Items.STORAGE_BLOCKS)
val storageBlocksAsBlock = blocks.forge("storage_blocks") val storageBlocksAsBlock = blocks.Appender(Tags.Blocks.STORAGE_BLOCKS)
val rawMaterials = items.forge("raw_materials") val rawMaterials = items.Appender(Tags.Items.RAW_MATERIALS)
val wires = items.forge("wires") val wires = items.forge("wires")
val gameEvents = Delegate(Registry.GAME_EVENT) val blockGroundOresStone = blocks.Appender(Tags.Blocks.ORES_IN_GROUND_STONE)
val vibrations = gameEvents.appender(GameEventTags.VIBRATIONS) val blockGroundOresDeepslate = blocks.Appender(Tags.Blocks.ORES_IN_GROUND_DEEPSLATE)
// val blockGroundOresNetherrack = blocks.forge("ores_in_ground/netherrack")
val itemGroundOresStone = items.Appender(Tags.Items.ORES_IN_GROUND_STONE)
val itemGroundOresDeepslate = items.Appender(Tags.Items.ORES_IN_GROUND_DEEPSLATE)
// val itemGroundOresNetherrack = items.forge("ores_in_ground/netherrack")
// val blockOreRatesSparse = blocks.forge("ore_rates/sparse")
val blockOreRatesSingular = blocks.Appender(Tags.Blocks.ORE_RATES_SINGULAR)
// val blockOreRatesDense = blocks.forge("ore_rates/dense")
// val itemOreRatesSparse = items.forge("ore_rates/sparse")
val itemOreRatesSingular = items.Appender(Tags.Items.ORE_RATES_SINGULAR)
// val itemOreRatesDense = items.forge("ore_rates/dense")
val gameEvents = Delegate(Registries.GAME_EVENT)
val vibrations = gameEvents.Appender(GameEventTags.VIBRATIONS)
fun requiresPickaxe(block: Block, tier: Tier? = null): TagsProvider { fun requiresPickaxe(block: Block, tier: Tier? = null): TagsProvider {
requiresPickaxe.add(block) requiresPickaxe.add(block)

View File

@ -4,8 +4,7 @@ import kotlin.KotlinVersion;
import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.EventPriority;
@ -15,12 +14,14 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.IdMappingEvent;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import ru.dbotthepony.mc.otm.android.AndroidResearchManager; import ru.dbotthepony.mc.otm.android.AndroidResearchManager;
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature; import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature;
import ru.dbotthepony.mc.otm.block.entity.SynchronizedBlockEntity; import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity;
import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue; import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue;
import ru.dbotthepony.mc.otm.block.entity.decorative.DevChestBlockEntity;
import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability; import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
import ru.dbotthepony.mc.otm.capability.drive.DrivePool; import ru.dbotthepony.mc.otm.capability.drive.DrivePool;
@ -33,23 +34,35 @@ import ru.dbotthepony.mc.otm.client.model.ExosuitModel;
import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel; import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel; import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer; import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer;
import ru.dbotthepony.mc.otm.client.render.WidgetAtlasHolder; import ru.dbotthepony.mc.otm.client.render.blockentity.BatteryBankRenderer;
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt; import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer;
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt; import ru.dbotthepony.mc.otm.compat.adastra.AdAstraCompatKt;
import ru.dbotthepony.mc.otm.core.Decimal; import ru.dbotthepony.mc.otm.compat.curios.CuriosCompatKt;
import ru.dbotthepony.mc.otm.item.ItemTritaniumArmor; import ru.dbotthepony.mc.otm.config.AndroidConfig;
import ru.dbotthepony.mc.otm.config.CablesConfig;
import ru.dbotthepony.mc.otm.config.ClientConfig;
import ru.dbotthepony.mc.otm.config.ExopackConfig;
import ru.dbotthepony.mc.otm.config.ItemsConfig;
import ru.dbotthepony.mc.otm.config.MachinesConfig;
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
import ru.dbotthepony.mc.otm.config.ServerConfig;
import ru.dbotthepony.mc.otm.config.ToolsConfig;
import ru.dbotthepony.mc.otm.item.ChestUpgraderItem;
import ru.dbotthepony.mc.otm.item.tool.ExplosiveHammerItem;
import ru.dbotthepony.mc.otm.item.armor.TritaniumArmorItem;
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem; import ru.dbotthepony.mc.otm.item.QuantumBatteryItem;
import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem; import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem; import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
import ru.dbotthepony.mc.otm.matter.MatterManager; import ru.dbotthepony.mc.otm.matter.MatterManager;
import ru.dbotthepony.mc.otm.network.*; import ru.dbotthepony.mc.otm.network.*;
import ru.dbotthepony.mc.otm.registry.*; import ru.dbotthepony.mc.otm.registry.*;
import ru.dbotthepony.mc.otm.storage.*; import ru.dbotthepony.mc.otm.triggers.KillAsAndroidTrigger;
import ru.dbotthepony.mc.otm.worldgen.OreGen; import top.theillusivec4.curios.api.CuriosApi;
import static net.minecraftforge.common.MinecraftForge.EVENT_BUS; import static net.minecraftforge.common.MinecraftForge.EVENT_BUS;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.concurrent.atomic.AtomicInteger;
// The value here should match an entry in the META-INF/mods.toml file // The value here should match an entry in the META-INF/mods.toml file
@Mod(OverdriveThatMatters.MOD_ID) @Mod(OverdriveThatMatters.MOD_ID)
@ -59,35 +72,26 @@ public final class OverdriveThatMatters {
// Directly reference a log4j logger. // Directly reference a log4j logger.
public static final String MOD_ID = "overdrive_that_matters"; public static final String MOD_ID = "overdrive_that_matters";
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
public static final AtomicInteger INGREDIENT_CACHE_INVALIDATION_COUNTER;
public static OverdriveThatMatters INSTANCE; static {
private StorageStackType<ItemStackWrapper> ITEM_STORAGE; try {
var f = Ingredient.class.getDeclaredField("INVALIDATION_COUNTER");
public StorageStackType<ItemStackWrapper> ITEM_STORAGE() { f.setAccessible(true);
return ITEM_STORAGE; INGREDIENT_CACHE_INVALIDATION_COUNTER = (AtomicInteger) f.get(null);
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
} }
public static OverdriveThatMatters INSTANCE;
public static ResourceLocation loc(String path) { public static ResourceLocation loc(String path) {
return new ResourceLocation(MOD_ID, path); return new ResourceLocation(MOD_ID, path);
} }
public final CreativeModeTab CREATIVE_TAB = new CreativeModeTab("otm") {
@Override
public ItemStack makeIcon() {
return new ItemStack(MItems.INSTANCE.getBATTERY_CREATIVE(), 1);
}
};
public final CreativeModeTab CREATIVE_TAB_DECORATIVE = new CreativeModeTab("otm_decorative") {
@Override
public ItemStack makeIcon() {
return new ItemStack(MRegistry.INSTANCE.getVENT().getItem(), 1);
}
};
private static void checkIfKotlinIsInstalled() { private static void checkIfKotlinIsInstalled() {
if (!KotlinVersion.CURRENT.isAtLeast(1, 6, 10)) { if (!KotlinVersion.CURRENT.isAtLeast(1, 9, 0)) {
throw new UnsupportedClassVersionError("Installed kotlin version is " + KotlinVersion.CURRENT + ", when at least 1.6.10 is required."); throw new UnsupportedClassVersionError("Installed kotlin version is " + KotlinVersion.CURRENT + ", when at least 1.9.0 is required.");
} }
} }
@ -131,35 +135,43 @@ public final class OverdriveThatMatters {
modBus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register); modBus.addListener(EventPriority.NORMAL, AndroidAbilityKeyMapping.INSTANCE::register);
modBus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register); modBus.addListener(EventPriority.NORMAL, TritaniumArmorModel::register);
modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register); modBus.addListener(EventPriority.NORMAL, GravitationStabilizerModel::register);
modBus.addListener(EventPriority.NORMAL, WidgetAtlasHolder::register); modBus.addListener(EventPriority.NORMAL, MCreativeTabs.INSTANCE::register);
modBus.addListener(EventPriority.NORMAL, BatteryBankRenderer.Companion::onRegisterAdditionalModels);
modBus.addListener(EventPriority.NORMAL, MatterBatteryBankRenderer.Companion::onRegisterAdditionalModels);
}); });
ClientConfig.INSTANCE.register(); ClientConfig.INSTANCE.register();
ServerConfig.INSTANCE.register(); ServerConfig.INSTANCE.register();
CablesConfig.INSTANCE.register();
ServerCompatConfig.INSTANCE.register();
AndroidConfig.INSTANCE.register();
ExopackConfig.INSTANCE.register();
ItemsConfig.INSTANCE.register();
MachinesConfig.INSTANCE.register();
ToolsConfig.INSTANCE.register();
} }
private void setup(final FMLCommonSetupEvent event) { private void setup(final FMLCommonSetupEvent event) {
EVENT_BUS.addListener(EventPriority.LOWEST, DrivePool.INSTANCE::onServerPostTick);
EVENT_BUS.addListener(EventPriority.HIGHEST, DrivePool.INSTANCE::serverStopEvent);
EVENT_BUS.addListener(EventPriority.LOWEST, DrivePool.INSTANCE::serverStartEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, DrivePool.INSTANCE::onWorldSave); EVENT_BUS.addListener(EventPriority.NORMAL, DrivePool.INSTANCE::onWorldSave);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopped); EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopped);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopping); EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopping);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStarting); EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStarting);
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onWorldTick); EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onLevelTick);
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onServerTick); EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onServerTick);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerTick); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerTick);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::isMobEffectApplicable); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::isMobEffectApplicable);
EVENT_BUS.addListener(EventPriority.LOW, MatteryPlayerCapability.Companion::onHurtEvent); EVENT_BUS.addListener(EventPriority.LOW, MatteryPlayerCapability.Companion::onHurtEvent);
EVENT_BUS.addListener(EventPriority.HIGH, MatteryPlayerCapability.Companion::onAttackEvent);
EVENT_BUS.addGenericListener(Entity.class, EventPriority.NORMAL, MatteryPlayerCapability.Companion::onAttachCapabilityEvent); EVENT_BUS.addGenericListener(Entity.class, EventPriority.NORMAL, MatteryPlayerCapability.Companion::onAttachCapabilityEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerChangeDimensionEvent); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerChangeDimensionEvent);
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayerCapability.Companion::onPlayerDeath); EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayerCapability.Companion::onPlayerDeath);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerCloneEvent); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerCloneEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::canEntitySpawn);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStartTracking); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStartTracking);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStopTracking); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onStopTracking);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::addCommands);
EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick); EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick);
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::tick); EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::tick);
@ -174,30 +186,36 @@ public final class OverdriveThatMatters {
EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::onDataPackSync); EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::onDataPackSync);
EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::addCommands); EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::addCommands);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onServerStopping); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onServerStopping);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onLevelUnload); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onLevelUnload);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onWatch); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onWatch);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onForget); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onForget);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::playerDisconnected); EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::playerDisconnected);
EVENT_BUS.addListener(EventPriority.LOWEST, SynchronizedBlockEntity.Companion::postLevelTick);
EVENT_BUS.addListener(EventPriority.LOWEST, KillAsAndroidTrigger.INSTANCE::onKill);
EVENT_BUS.addListener(EventPriority.NORMAL, EnderTeleporterFeature.Companion::onEntityDeath); EVENT_BUS.addListener(EventPriority.NORMAL, EnderTeleporterFeature.Companion::onEntityDeath);
EVENT_BUS.addListener(EventPriority.HIGH, ItemTritaniumArmor.Companion::onHurt); EVENT_BUS.addListener(EventPriority.HIGH, TritaniumArmorItem.Companion::onHurt);
EVENT_BUS.addListener(EventPriority.NORMAL, ExplosiveHammerItem.Companion::onLeftClickBlock);
EVENT_BUS.addListener(EventPriority.NORMAL, ChestUpgraderItem.Companion::onEntityInteract);
EVENT_BUS.addListener(EventPriority.NORMAL, DevChestBlockEntity.Companion::mappingsChanged);
MatteryPlayerNetworkChannel.INSTANCE.register(); MatteryPlayerNetworkChannel.INSTANCE.register();
MenuNetworkChannel.INSTANCE.register(); MenuNetworkChannel.INSTANCE.register();
WeaponNetworkChannel.INSTANCE.register(); WeaponNetworkChannel.INSTANCE.register();
RegistryNetworkChannel.INSTANCE.register();
WorldNetworkChannel.INSTANCE.register();
GenericNetworkChannel.INSTANCE.register(); GenericNetworkChannel.INSTANCE.register();
ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new Decimal("3.125")); if (ModList.get().isLoaded(CuriosApi.MODID)) {
EVENT_BUS.addListener(EventPriority.NORMAL, CuriosCompatKt::onCuriosSlotModifiersUpdated);
if (ModList.get().isLoaded("mekanism")) {
EVENT_BUS.addGenericListener(BlockEntity.class, EventPriority.NORMAL, QIOKt::attachCapabilities);
} }
OreGen.INSTANCE.register(); if (AdAstraCompatKt.isAdAstraLoaded()) {
EVENT_BUS.addListener(EventPriority.NORMAL, AdAstraCompatKt::onDamageEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, AdAstraCompatKt::onMatteryTick);
}
} }
private void setupClient(final FMLClientSetupEvent event) { private void setupClient(final FMLClientSetupEvent event) {
@ -223,13 +241,10 @@ public final class OverdriveThatMatters {
EVENT_BUS.addListener(EventPriority.LOWEST, ClientTickHandlerKt::onClientTick); EVENT_BUS.addListener(EventPriority.LOWEST, ClientTickHandlerKt::onClientTick);
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientConnected); EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientConnected);
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientDisconnected); EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientDisconnected);
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::tooltipEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::clientDisconnect); EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::clientDisconnect);
if (ModList.get().isLoaded("mekanism")) {
EVENT_BUS.addListener(EventPriority.NORMAL, TooltipsKt::tooltipEvent);
}
EVENT_BUS.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::onRenderGuiEvent); EVENT_BUS.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::onRenderGuiEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::onMouseClick); EVENT_BUS.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::onMouseClick);

View File

@ -1,14 +1,18 @@
package ru.dbotthepony.mc.otm.capability; package ru.dbotthepony.mc.otm.capability;
import mekanism.api.energy.IStrictEnergyHandler; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.*; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityToken;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import ru.dbotthepony.mc.otm.block.entity.cable.EnergyCableBlockEntity;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage;
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider; import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider;
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage;
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode; import ru.dbotthepony.mc.otm.graph.matter.MatterNode;
import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode; import ru.dbotthepony.mc.otm.graph.storage.StorageNode;
import top.theillusivec4.curios.api.type.capability.ICurio; import top.theillusivec4.curios.api.type.capability.ICurio;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler; import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
@ -25,11 +29,11 @@ public class MatteryCapability {
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IMatterHandler> MATTER = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<IMatterStorage> MATTER = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IMatterGraphNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<MatterNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull @Nonnull
@NotNull @NotNull
@ -41,15 +45,15 @@ public class MatteryCapability {
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IMatteryDrive> DRIVE = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<IMatteryDrive<?>> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IStorageGraphNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<StorageNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IStrictEnergyHandler> MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<EnergyCableBlockEntity.Node> ENERGY_CABLE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull @Nonnull
@NotNull @NotNull
@ -59,14 +63,19 @@ public class MatteryCapability {
@NotNull @NotNull
public static final Capability<ICurio> CURIOS_ITEM = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<ICurio> CURIOS_ITEM = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IMatteryUpgrade> UPGRADE = CapabilityManager.get(new CapabilityToken<>() {});
public static void register(RegisterCapabilitiesEvent event) { public static void register(RegisterCapabilitiesEvent event) {
event.register(IMatteryEnergyStorage.class); event.register(IMatteryEnergyStorage.class);
event.register(MatteryPlayerCapability.class); event.register(MatteryPlayerCapability.class);
event.register(IMatterHandler.class); event.register(IMatterStorage.class);
event.register(IMatterGraphNode.class); event.register(MatterNode.class);
event.register(IPatternStorage.class); event.register(IPatternStorage.class);
event.register(IReplicationTaskProvider.class); event.register(IReplicationTaskProvider.class);
event.register(IMatteryDrive.class); event.register(IMatteryDrive.class);
event.register(IStorageGraphNode.class); event.register(StorageNode.class);
event.register(IMatteryUpgrade.class);
} }
} }

View File

@ -1,7 +1,9 @@
package ru.dbotthepony.mc.otm.client.model; package ru.dbotthepony.mc.otm.client.model;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.model.geom.PartPose; import net.minecraft.client.model.geom.PartPose;
@ -19,8 +21,11 @@ import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.renderer.entity.player.PlayerRenderer; import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.event.RenderPlayerEvent; import net.minecraftforge.client.event.RenderPlayerEvent;
import org.joml.Vector3f;
import org.joml.Vector4f;
import ru.dbotthepony.mc.otm.OverdriveThatMatters; import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Set; import java.util.Set;
@ -32,6 +37,7 @@ public final class ExosuitModel {
public static final HumanoidModel<AbstractClientPlayer> modelGlow; public static final HumanoidModel<AbstractClientPlayer> modelGlow;
public static final ResourceLocation texture = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/models/armor/exosuit.png"); public static final ResourceLocation texture = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/models/armor/exosuit.png");
public static final ResourceLocation textureColor = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/models/armor/exosuit_color.png");
static { static {
MeshDefinition meshdefinition = new MeshDefinition(); MeshDefinition meshdefinition = new MeshDefinition();
@ -116,13 +122,18 @@ public final class ExosuitModel {
float p_117357_, float p_117357_,
float p_117358_ float p_117358_
) { ) {
if (player.isInvisible())
return;
var cap = player.getCapability(MatteryCapability.MATTERY_PLAYER); var cap = player.getCapability(MatteryCapability.MATTERY_PLAYER);
if (!cap.isPresent()) { if (!cap.isPresent()) {
return; return;
} }
if (cap.resolve().get().getHasExoPack() && cap.resolve().get().getDisplayExoPack()) { var mattery = cap.resolve().get();
if (mattery.getHasExopack() && mattery.isExopackVisible()) {
var model = getParentModel(); var model = getParentModel();
model.copyPropertiesTo(modelNormal); model.copyPropertiesTo(modelNormal);
model.copyPropertiesTo(modelGlow); model.copyPropertiesTo(modelGlow);
@ -138,6 +149,20 @@ public final class ExosuitModel {
1f, 1f, 1f, 1f 1f, 1f, 1f, 1f
); );
var color = cap.resolve().get().getExopackColor();
if (color != null) {
modelNormal.renderToBuffer(
poseStack,
bufferSource.getBuffer(RenderType.entityCutoutNoCull(textureColor)),
packedLight,
overlayCoords,
// rgba
color.getRed(), color.getGreen(), color.getBlue(), 1f
);
}
if (mattery.getExopackGlows()) {
modelGlow.renderToBuffer( modelGlow.renderToBuffer(
poseStack, poseStack,
bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture)), bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture)),
@ -146,6 +171,18 @@ public final class ExosuitModel {
// rgba // rgba
1f, 1f, 1f, 1f 1f, 1f, 1f, 1f
); );
} else {
modelGlow.renderToBuffer(
poseStack,
bufferSource.getBuffer(RenderType.entityCutoutNoCull(texture)),
packedLight,
overlayCoords,
// rgba
1f, 1f, 1f, 1f
);
}
mattery.makeSmokeParticles(poseStack, model);
} }
} }
} }

View File

@ -69,9 +69,6 @@ public class TritaniumArmorModel {
PartDefinition chestplateslope_r1 = body.addOrReplaceChild("chestplateslope_r1", CubeListBuilder.create().texOffs(44, 41).addBox(-4.0F, 0.5F, 0.4F, 8.0F, 4.0F, 2.0F, new CubeDeformation(0.39F)), PartPose.offsetAndRotation(0.0F, 6.4F, -6.2F, 1.2217F, 0.0F, 0.0F)); PartDefinition chestplateslope_r1 = body.addOrReplaceChild("chestplateslope_r1", CubeListBuilder.create().texOffs(44, 41).addBox(-4.0F, 0.5F, 0.4F, 8.0F, 4.0F, 2.0F, new CubeDeformation(0.39F)), PartPose.offsetAndRotation(0.0F, 6.4F, -6.2F, 1.2217F, 0.0F, 0.0F));
PartDefinition thruster_r1 = body.addOrReplaceChild("thruster_r1", CubeListBuilder.create().texOffs(24, 0).addBox(-5.0F, 1.0F, 3.6F, 2.0F, 5.0F, 3.0F, new CubeDeformation(0.4F))
.texOffs(24, 0).addBox(3.0F, 1.0F, 3.6F, 2.0F, 5.0F, 3.0F, new CubeDeformation(0.4F)), PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, 0.3927F, 0.0F, 0.0F));
PartDefinition right_arm = partdefinition.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(24, 32).addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.3F)) PartDefinition right_arm = partdefinition.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(24, 32).addBox(-3.0F, -2.0F, -2.0F, 4.0F, 12.0F, 4.0F, new CubeDeformation(0.3F))
.texOffs(42, 56).addBox(-4.0F, -3.0F, -2.0F, 4.0F, 4.0F, 4.0F, new CubeDeformation(0.4F)), PartPose.offset(-5.0F, 2.0F, 0.0F)); .texOffs(42, 56).addBox(-4.0F, -3.0F, -2.0F, 4.0F, 4.0F, 4.0F, new CubeDeformation(0.4F)), PartPose.offset(-5.0F, 2.0F, 0.0F));

View File

@ -1,191 +0,0 @@
package ru.dbotthepony.mc.otm.client.screen.panels;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class FlexGridPanel<S extends Screen> extends EditablePanel<S> {
public enum FlexAlign {
TOP_LEFT,
TOP_CENTER,
TOP_RIGHT,
MIDDLE_LEFT,
MIDDLE_CENTER,
MIDDLE_RIGHT,
BOTTOM_LEFT,
BOTTOM_CENTER,
BOTTOM_RIGHT
}
protected FlexAlign align = FlexAlign.MIDDLE_CENTER;
public int panels_per_row = 1;
public FlexGridPanel(@Nonnull S screen, @Nullable EditablePanel<?> parent, float x, float y, float width, float height) {
super(screen, parent, x, y, width, height);
}
public FlexGridPanel(@Nonnull S screen, @Nullable EditablePanel<?> parent, float x, float y) {
super(screen, parent, x, y);
}
public FlexGridPanel(@Nonnull S screen, @Nullable EditablePanel<?> parent) {
super(screen, parent);
}
public FlexAlign getAlign() {
return align;
}
public FlexGridPanel<S> setAlign(FlexAlign align) {
this.align = align;
return this;
}
@Override
public void performLayout() {
if (align == FlexAlign.MIDDLE_CENTER) {
// список потомков
var children = getUndockedVisibleChildren();
if (children.size() == 0) {
return;
}
// хранит общую ширину всех потомков в ряд
// а так же ограничитель ширины ряда после
// определения количества рядов
float desired_width = 0;
// минимально допустимая ширина одного ряда
float min_width = getWidth();
// "финальная" ширина этой панели
float this_width = getWidth() - getDockPadding().left() - getDockPadding().right();
if (this_width <= 0) {
return;
}
for (var child : children) {
min_width = Math.min(min_width, child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right());
desired_width += child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right();
}
int rows = 1;
// если общая ширина больше чем ширина панели, делим пополам пока не найдем нужную ширину и количество рядов
while (desired_width > this_width && desired_width > min_width) {
desired_width /= 2;
rows++;
}
if (desired_width < min_width) {
desired_width = min_width;
}
int index;
// определение высоты всех рядов вместе
float total_height = 0;
// утютю никаких goto
// зато код чище некуда!
while (desired_width <= this_width) {
index = 0;
total_height = 0;
panels_per_row = 0;
boolean calculate_row_width = true;
for (int row = 0; row < rows; row++) {
float max_height = 0;
float total_width = 0;
for (int i = index; i < children.size(); i++) {
var child = children.get(i);
var gain_width = child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right();
index = i;
if (gain_width + total_width > desired_width) {
if (calculate_row_width) {
panels_per_row = i + 1;
calculate_row_width = false;
}
break;
}
max_height = Math.max(max_height, child.getHeight() + child.getDockMargin().top() + child.getDockMargin().bottom());
total_width += gain_width;
}
total_height += max_height;
}
if (index + 1 < children.size() && desired_width != this_width) {
// не все панели уместились. ну чтож
desired_width = Math.min(desired_width + min_width, this_width);
} else {
break;
}
}
index = 0;
// ширину на середину для позиционирования по центру
this_width /= 2;
// определение точки по середине по высоте
float h_middle = (getHeight() - getDockPadding().bottom() - getDockPadding().top() - total_height) / 2;
// OverdriveThatMatters.LOGGER.info("Общая высота {}, рядов {}, середина {}", total_height, rows, h_middle);
for (int row = 0; row < rows; row++) {
float max_height = 0;
float total_width = 0;
int until = index;
for (int i = index; i < children.size(); i++) {
var child = children.get(i);
var gain_width = child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right();
until = i;
if (gain_width + total_width > desired_width) {
break;
}
max_height = Math.max(max_height, child.getHeight() + child.getDockMargin().top() + child.getDockMargin().bottom());
total_width += gain_width;
}
total_width /= 2;
max_height /= 2;
// OverdriveThatMatters.LOGGER.info("Ряд {}, общая ширина {}, максимальная высота {}, позиция {}, c {} до {}", row, total_width * 2, max_height * 2, h_middle, index, until);
float accumulate_width = 0;
for (int i = index; i <= until; i++) {
var child = children.get(i);
child.setPos((int) (this_width - total_width + accumulate_width + child.getDockMargin().left()), (int) (h_middle + max_height - child.getHeight() / 2));
accumulate_width += child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right();
}
h_middle += max_height * 2;
index = until;
}
}
super.performLayout();
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.block.entity.DispenserBlockEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.vanilla.MatteryChestMenu;
@Mixin(DispenserBlockEntity.class)
public abstract class DispenserBlockEntityMixin {
@Overwrite
public AbstractContainerMenu createMenu(int p_59312_, Inventory p_59313_) {
return MatteryChestMenu.c3x3(p_59312_, p_59313_, (DispenserBlockEntity) (Object) this);
}
}

View File

@ -0,0 +1,24 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.dbotthepony.mc.otm.item.weapon.EnergySwordItem;
@Mixin(EnchantmentHelper.class)
public class EnchantmentHelperMixin {
@Inject(
method = "getSweepingDamageRatio(Lnet/minecraft/world/entity/LivingEntity;)F",
at = @At("HEAD"),
cancellable = true)
private static void getSweepingDamageRatio(LivingEntity p_44822_, CallbackInfoReturnable<Float> info) {
var result = EnergySwordItem.getSweepingDamageRatioHook(p_44822_);
if (result != null) {
info.setReturnValue(result);
}
}
}

View File

@ -0,0 +1,49 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
@Mixin(FoodData.class)
public class FoodDataMixin {
@Shadow
private int lastFoodLevel;
@Shadow
private int tickTimer;
@Shadow
private int foodLevel;
@Shadow
private float exhaustionLevel;
@Inject(
method = "tick(Lnet/minecraft/world/entity/player/Player;)V",
at = @At("HEAD"),
cancellable = true
)
private void tick(Player player, CallbackInfo info) {
player.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
if (it.isAndroid()) {
info.cancel();
// полностью подменяем логику если андроид
lastFoodLevel = foodLevel;
if (player.level.getDifficulty() == Difficulty.PEACEFUL) {
exhaustionLevel = 0f;
} else {
tickTimer = 0;
}
// не обновляем уровень истощения ибо он обнуляется логикой внутри MatteryPlayerCapability
// а так же не регенерируем
// ну и не получаем урон от "голодания"
}
});
}
}

View File

@ -0,0 +1,16 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.block.entity.HopperBlockEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.compat.vanilla.MatteryChestMenu;
@Mixin(HopperBlockEntity.class)
public abstract class HopperBlockEntityMixin {
@Overwrite
public AbstractContainerMenu createMenu(int p_59312_, Inventory p_59313_) {
return MatteryChestMenu.hopper(p_59312_, p_59313_, (HopperBlockEntity) (Object) this);
}
}

View File

@ -0,0 +1,22 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.advancements.critereon.InventoryChangeTrigger;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import ru.dbotthepony.mc.otm.triggers.MatteryInventoryChangeTrigger;
@Mixin(InventoryChangeTrigger.class)
public abstract class InventoryChangeTriggerMixin {
@Overwrite
public void trigger(ServerPlayer p_43150_, Inventory p_43151_, ItemStack p_43152_) {
MatteryInventoryChangeTrigger.INSTANCE.trigger(p_43150_, p_43151_, p_43152_);
}
@Overwrite
private void trigger(ServerPlayer p_43154_, Inventory p_43155_, ItemStack p_43156_, int p_43157_, int p_43158_, int p_43159_) {
MatteryInventoryChangeTrigger.INSTANCE.trigger(p_43154_, p_43155_, p_43156_, p_43157_, p_43158_, p_43159_);
}
}

View File

@ -0,0 +1,36 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.projectile.AbstractHurtingProjectile;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.registry.MSoundEvents;
@Mixin(AbstractHurtingProjectile.class)
public class MixinAbstractHurtingProjectile {
@Inject(
method = "hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/projectile/AbstractHurtingProjectile;markHurt()V",
ordinal = 0
)
)
public void onProjectileHit(DamageSource pSource, float pAmount, CallbackInfoReturnable<Boolean> cir) {
Entity entity = pSource.getEntity();
if (entity == null) return;
entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(cap -> {
AbstractHurtingProjectile proj = (AbstractHurtingProjectile)(Object)this;
if (cap.isAndroid() && proj.getOwner() != entity) {
entity.level.playSound(entity, proj.blockPosition(), MSoundEvents.INSTANCE.getANDROID_PROJ_PARRY(), SoundSource.PLAYERS, 1.0f, 0.95f + entity.level.random.nextFloat() * 0.1f);
}
});
}
}

View File

@ -0,0 +1,33 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.level.block.AnvilBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.dbotthepony.mc.otm.registry.MBlocks;
@Mixin(AnvilBlock.class)
@SuppressWarnings("unused")
public class MixinAnvilBlock {
@Inject(
method = "damage(Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/world/level/block/state/BlockState;",
at = @At("HEAD"),
cancellable = true)
private static void damage(BlockState pState, CallbackInfoReturnable<BlockState> info) {
var list = MBlocks.INSTANCE.getTRITANIUM_ANVIL();
for (int i = 0; i < list.size(); i++) {
if (pState.is(list.get(i))) {
if (i == list.size() - 1) {
info.setReturnValue(null);
} else {
info.setReturnValue(list.get(i + 1).defaultBlockState().setValue(AnvilBlock.FACING, pState.getValue(AnvilBlock.FACING)));
}
return;
}
}
}
}

View File

@ -0,0 +1,32 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.server.packs.resources.ResourceProvider;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.client.render.GlitchRenderer;
import ru.dbotthepony.mc.otm.client.render.RenderHelperKt;
@Mixin(GameRenderer.class)
public class MixinGameRenderer {
@Inject(
method = "render(FJZ)V",
at = @At(
value = "INVOKE",
target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;bindWrite(Z)V"
)
)
private void render(float p_109094_, long p_109095_, boolean p_109096_, CallbackInfo ci) {
GlitchRenderer.render();
}
@Inject(
method = "reloadShaders(Lnet/minecraft/server/packs/resources/ResourceProvider;)V",
at = @At("HEAD")
)
private void reloadShaders(ResourceProvider p_250719_, CallbackInfo ci) {
RenderHelperKt.reloadShaders(p_250719_);
}
}

View File

@ -0,0 +1,90 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.world.Container;
import net.minecraft.world.ContainerHelper;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.ForgeRegistries;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
import java.util.function.Predicate;
@Mixin(Inventory.class)
public class MixinInventory {
@Final
@Shadow
public Player player;
@Inject(
method = "add(ILnet/minecraft/world/item/ItemStack;)Z",
at = @At("HEAD"),
cancellable = true
)
private void add(int pSlot, ItemStack pStack, CallbackInfoReturnable<Boolean> hook) {
if (pStack.isEmpty()) {
return;
}
if (pSlot == -1) {
this.player.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
try {
hook.setReturnValue(it.inventoryAddImpl(pStack));
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Adding item to inventory (Overdrive That Matters detour)");
CrashReportCategory crashreportcategory = crashreport.addCategory("Item being added");
crashreportcategory.setDetail("Registry Name", () -> String.valueOf(ForgeRegistries.ITEMS.getKey(pStack.getItem())));
crashreportcategory.setDetail("Item Class", () -> pStack.getItem().getClass().getName());
crashreportcategory.setDetail("Item ID", Item.getId(pStack.getItem()));
crashreportcategory.setDetail("Item data", pStack.getDamageValue());
crashreportcategory.setDetail("Item name", () -> pStack.getHoverName().getString());
throw new ReportedException(crashreport);
}
});
}
}
@Inject(
method = "dropAll()V",
at = @At("TAIL")
)
private void dropAll(CallbackInfo ci) {
MatteryPlayerCapability.inventoryDropAll((Inventory)(Object)this);
}
@Inject(
method = "clearContent()V",
at = @At("TAIL")
)
private void clearContent(CallbackInfo ci) {
MatteryPlayerCapability.inventoryClearContent((Inventory)(Object)this);
}
@Inject(
method = "clearOrCountMatchingItems(Ljava/util/function/Predicate;ILnet/minecraft/world/Container;)I",
at = @At("RETURN"),
cancellable = true
)
private void clearOrCountMatchingItems(Predicate<ItemStack> predicate, int count, Container container, CallbackInfoReturnable<Integer> cir) {
player.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
if (!it.getHasExopack()) return;
int i = cir.getReturnValue();
i += ContainerHelper.clearOrCountMatchingItems(it.getExopackContainer(), predicate, count - i, count == 0);
cir.setReturnValue(i);
});
}
}

View File

@ -0,0 +1,68 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.event.ForgeEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.config.ServerConfig;
import ru.dbotthepony.mc.otm.core.util.ExperienceUtilsKt;
import ru.dbotthepony.mc.otm.registry.MItems;
@SuppressWarnings("ConstantConditions")
@Mixin(LivingEntity.class)
public class MixinLivingEntity {
@Shadow
protected Player lastHurtByPlayer;
@Inject(
method = "dropExperience()V",
at = @At("HEAD"),
cancellable = true)
public void dropExperience(CallbackInfo hook) {
if (((Object) this) instanceof Player player && ServerConfig.INSTANCE.getDROP_EXPERIENCE_CAPSULES()) {
player.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
hook.cancel();
long totalExperience = ExperienceUtilsKt.getTotalXpRequiredForLevel(player.experienceLevel);
totalExperience += (long) (player.experienceProgress * player.getXpNeededForNextLevel());
double min = ServerConfig.INSTANCE.getMIN_EXPERIENCE_DROPPED();
double max = ServerConfig.INSTANCE.getMAX_EXPERIENCE_DROPPED();
if (min == max) {
totalExperience *= min;
} else {
if (min > max) {
min = 0.4;
max = 0.8;
}
totalExperience *= min + player.getRandom().nextDouble() * (max - min);
}
if (totalExperience >= Integer.MAX_VALUE) {
int hooked = ForgeEventFactory.getExperienceDrop(player, lastHurtByPlayer, Integer.MAX_VALUE);
if (hooked != Integer.MAX_VALUE) {
totalExperience = hooked;
}
} else {
totalExperience = ForgeEventFactory.getExperienceDrop(player, lastHurtByPlayer, (int) totalExperience);
}
if (totalExperience > 0L) {
if (it.isAndroid()) {
player.drop(MItems.INSTANCE.getESSENCE_DRIVE().make(totalExperience), true, false);
} else {
player.drop(MItems.INSTANCE.getESSENCE_CAPSULE().make(totalExperience), true, false);
}
}
});
}
}
}

View File

@ -0,0 +1,29 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
@Mixin(Minecraft.class)
public class MixinMinecraft {
@Redirect(
method = "pickBlock()V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/player/Inventory;findSlotMatchingItem(Lnet/minecraft/world/item/ItemStack;)I"
)
)
private int pickBlock(Inventory inventory, ItemStack itemStack) {
int i = inventory.findSlotMatchingItem(itemStack);
MatteryPlayerCapability.pickBlockHook(i, itemStack);
return i;
}
}

View File

@ -16,7 +16,8 @@ public class MixinPatchProjectileFinder {
value = "INVOKE", value = "INVOKE",
target = "net.minecraftforge.common.ForgeHooks.getProjectile(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;", target = "net.minecraftforge.common.ForgeHooks.getProjectile(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack;",
ordinal = 2, ordinal = 2,
shift = At.Shift.BEFORE shift = At.Shift.BEFORE,
remap = false
), ),
cancellable = true) cancellable = true)
private void exosuitGetProjectileHook(ItemStack weaponItem, CallbackInfoReturnable<ItemStack> hook) { private void exosuitGetProjectileHook(ItemStack weaponItem, CallbackInfoReturnable<ItemStack> hook) {

View File

@ -0,0 +1,19 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
@Mixin(Player.class)
public class MixinPlayer {
@Inject(
method = "destroyVanishingCursedItems()V",
at = @At("TAIL")
)
private void destroyVanishingCursedItems(CallbackInfo ci) {
MatteryPlayerCapability.playerDestroyVanishingCursedItems((Player)(Object)this);
}
}

View File

@ -0,0 +1,54 @@
package ru.dbotthepony.mc.otm.mixin;
import net.minecraft.advancements.CriterionTrigger;
import net.minecraft.advancements.CriterionTriggerInstance;
import net.minecraft.advancements.critereon.InventoryChangeTrigger;
import net.minecraft.advancements.critereon.SimpleCriterionTrigger;
import net.minecraft.server.PlayerAdvancements;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.triggers.MatteryInventoryChangeTrigger;
// i tried to mixin into InventoryChangeTrigger with extends SimpleCriterionTrigger and @Overwrite+@Override
// while also defining SimpleCriterionTrigger methods non final in accesstransfoer
// it didn't work.
@Mixin(SimpleCriterionTrigger.class)
public abstract class SimpleCriterionTriggerMixin implements CriterionTrigger<CriterionTriggerInstance> {
@Inject(
method = "removePlayerListener(Lnet/minecraft/server/PlayerAdvancements;Lnet/minecraft/advancements/CriterionTrigger$Listener;)V",
at = @At("HEAD"),
cancellable = true
)
public void removePlayerListener(PlayerAdvancements p_66254_, CriterionTrigger.Listener p_66255_, CallbackInfo info) {
if (((Object) this) instanceof InventoryChangeTrigger) {
MatteryInventoryChangeTrigger.INSTANCE.removePlayerListener(p_66254_, p_66255_);
info.cancel();
}
}
@Inject(
method = "addPlayerListener(Lnet/minecraft/server/PlayerAdvancements;Lnet/minecraft/advancements/CriterionTrigger$Listener;)V",
at = @At("HEAD"),
cancellable = true
)
public void addPlayerListener(PlayerAdvancements p_66254_, CriterionTrigger.Listener p_66255_, CallbackInfo info) {
if (((Object) this) instanceof InventoryChangeTrigger) {
MatteryInventoryChangeTrigger.INSTANCE.addPlayerListener(p_66254_, p_66255_);
info.cancel();
}
}
@Inject(
method = "removePlayerListeners(Lnet/minecraft/server/PlayerAdvancements;)V",
at = @At("HEAD"),
cancellable = true
)
public void removePlayerListeners(PlayerAdvancements p_66254_, CallbackInfo info) {
if (((Object) this) instanceof InventoryChangeTrigger) {
MatteryInventoryChangeTrigger.INSTANCE.removePlayerListeners(p_66254_);
info.cancel();
}
}
}

View File

@ -0,0 +1,31 @@
package ru.dbotthepony.mc.otm.mixin.compat.ad_astra;
import earth.terrarium.ad_astra.common.entity.system.EntityOxygenSystem;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
@Mixin(EntityOxygenSystem.class)
public class EntityOxygenSystemMixin {
@Inject(
method = "oxygenTick(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/server/level/ServerLevel;)V",
at = @At("HEAD"),
cancellable = true,
remap = false
)
private static void oxygenTick(LivingEntity entity, ServerLevel level, CallbackInfo hook) {
if (entity instanceof Player && ServerCompatConfig.AdAstra.INSTANCE.getANDROIDS_DO_NOT_NEED_OXYGEN()) {
entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
if (it.isAndroid()) {
hook.cancel();
}
});
}
}
}

View File

@ -0,0 +1,27 @@
package ru.dbotthepony.mc.otm.mixin.compat.ad_astra;
import earth.terrarium.ad_astra.common.entity.system.EntityTemperatureSystem;
import earth.terrarium.ad_astra.common.util.ModUtils;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
// STAHP!
@Mixin(EntityTemperatureSystem.class)
public class EntityTemperatureSystemMixin {
@Inject(
method = "temperatureTick(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/server/level/ServerLevel;)V",
at = @At("HEAD"),
cancellable = true,
remap = false
)
private static void temperatureTick(LivingEntity entity, ServerLevel level, CallbackInfo hook) {
if (ServerCompatConfig.AdAstra.INSTANCE.getWHATS_UP_WITH_TEMPERATURE() && !ModUtils.planetHasAtmosphere(level)) {
hook.cancel();
}
}
}

View File

@ -0,0 +1,31 @@
package ru.dbotthepony.mc.otm.mixin.compat.ad_astra;
import earth.terrarium.ad_astra.common.util.OxygenUtils;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
@Mixin(OxygenUtils.class)
public class OxygenUtilsMixin {
@Inject(
method = "entityHasOxygen(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;)Z",
at = @At("HEAD"),
cancellable = true,
remap = false
)
private static void entityHasOxygen(Level level, LivingEntity entity, CallbackInfoReturnable<Boolean> hook) {
if (entity instanceof Player && ServerCompatConfig.AdAstra.INSTANCE.getANDROIDS_DO_NOT_NEED_OXYGEN()) {
entity.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresent(it -> {
if (it.isAndroid()) {
hook.setReturnValue(true);
}
});
}
}
}

View File

@ -1,46 +0,0 @@
package ru.dbotthepony.mc.otm.registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe;
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe;
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory;
public class MRecipes {
public static class MatteryRecipeType<T extends Recipe<?>> implements RecipeType<T> {
public final ResourceLocation name;
private MatteryRecipeType(ResourceLocation name) {
this.name = name;
}
@Override
public String toString() {
return name.toString();
}
}
public static final MatteryRecipeType<PlatePressRecipe> PLATE_PRESS = new MatteryRecipeType<>(OverdriveThatMatters.loc(MNames.PLATE_PRESS));
public static final MatteryRecipeType<PlatePressRecipe> ENERGY_CONTAINER = new MatteryRecipeType<>(OverdriveThatMatters.loc("energy_container"));
private static final DeferredRegister<RecipeSerializer<?>> serializerRegistry = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, OverdriveThatMatters.MOD_ID);
private static final DeferredRegister<RecipeType<?>> typeRegistry = DeferredRegister.create(ForgeRegistries.RECIPE_TYPES, OverdriveThatMatters.MOD_ID);
static {
serializerRegistry.register(MNames.PLATE_PRESS, () -> PlatePressRecipeFactory.INSTANCE);
serializerRegistry.register(ENERGY_CONTAINER.name.getPath(), () -> EnergyContainerRecipe.Companion);
typeRegistry.register(MNames.PLATE_PRESS, () -> PLATE_PRESS);
typeRegistry.register(ENERGY_CONTAINER.name.getPath(), () -> ENERGY_CONTAINER);
}
public static void register(IEventBus bus) {
serializerRegistry.register(bus);
typeRegistry.register(bus);
}
}

View File

@ -5,6 +5,7 @@ import net.minecraft.core.Direction;
import net.minecraft.world.phys.shapes.BooleanOp; import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import ru.dbotthepony.mc.otm.core.math.BlockRotation;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
@ -47,7 +48,7 @@ public record BlockShape(SimpleCuboid ...shapes) {
return new BlockShape(list); return new BlockShape(list);
} }
public BlockShape rotate(Direction dir) { public BlockShape rotateFromSouth(Direction dir) {
if (dir == Direction.SOUTH) if (dir == Direction.SOUTH)
return this; return this;
@ -69,7 +70,7 @@ public record BlockShape(SimpleCuboid ...shapes) {
return this; return this;
} }
public BlockShape rotateInv(Direction dir) { public BlockShape rotateFromNorth(Direction dir) {
if (dir == Direction.SOUTH) if (dir == Direction.SOUTH)
return rotateAroundY(Math.PI); return rotateAroundY(Math.PI);
@ -91,11 +92,29 @@ public record BlockShape(SimpleCuboid ...shapes) {
return this; return this;
} }
public BlockShape rotateFromNorth(BlockRotation dir) {
var result = rotateFromNorth(dir.getFront());
if (dir.getTop() != Direction.DOWN && dir.getTop() != Direction.UP)
result = result.rotateFromNorth(dir.getTop());
return result;
}
public BlockShape rotateFromSouth(BlockRotation dir) {
var result = rotateFromSouth(dir.getFront());
if (dir.getTop() != Direction.DOWN && dir.getTop() != Direction.UP)
result = result.rotateFromSouth(dir.getTop());
return result;
}
public VoxelShape computeShape() { public VoxelShape computeShape() {
VoxelShape final_shape = shapes[0].getShape(); VoxelShape final_shape = shapes[0].getShape();
for (int i = 1; i < shapes.length; i++) for (int i = 1; i < shapes.length; i++)
final_shape = Shapes.joinUnoptimized(final_shape, shapes[i].getShape(), BooleanOp.OR); final_shape = Shapes.join(final_shape, shapes[i].getShape(), BooleanOp.OR);
return final_shape; return final_shape;
} }

View File

@ -23,11 +23,13 @@ public class BlockShapes {
new SimpleCuboid(0.0625d, 0.0625d, 0.4375d, 0.9375d, 0.9375d, 0.5625d), new SimpleCuboid(0.0625d, 0.0625d, 0.4375d, 0.9375d, 0.9375d, 0.5625d),
new SimpleCuboid(0.125d, 0.03125d, 0.125d, 0.875d, 0.09375d, 0.875d), new SimpleCuboid(0.125d, 0.03125d, 0.125d, 0.875d, 0.09375d, 0.875d),
new SimpleCuboid(0.125d, 0.90625d, 0.125d, 0.875d, 0.96875d, 0.875d), new SimpleCuboid(0.125d, 0.90625d, 0.125d, 0.875d, 0.96875d, 0.875d),
new SimpleCuboid(0.1875d, 0.1875d, 0d, 0.8125d, 0.8125d, 0.1875d), new SimpleCuboid(0.3125d, 0.3125d, 0d, 0.6875d, 0.6875d, 0.1875d),
new SimpleCuboid(0.0625d, 0.125d, 0.125d, 0.125d, 0.875d, 0.25d), new SimpleCuboid(0.0625d, 0.125d, 0.125d, 0.125d, 0.875d, 0.25d),
new SimpleCuboid(0.0625d, 0.125d, 0.75d, 0.125d, 0.875d, 0.875d), new SimpleCuboid(0.0625d, 0.125d, 0.75d, 0.125d, 0.875d, 0.875d),
new SimpleCuboid(0.875d, 0.125d, 0.75d, 0.9375d, 0.875d, 0.875d), new SimpleCuboid(0.875d, 0.125d, 0.75d, 0.9375d, 0.875d, 0.875d),
new SimpleCuboid(0.875d, 0.125d, 0.125d, 0.9375d, 0.875d, 0.25d), new SimpleCuboid(0.875d, 0.125d, 0.125d, 0.9375d, 0.875d, 0.25d),
new SimpleCuboid(0.125d, 0.625d, 0.15625d, 0.875d, 0.75d, 0.21875d),
new SimpleCuboid(0.125d, 0.25d, 0.15625d, 0.875d, 0.375d, 0.21875d),
new SimpleCuboid(0d, 0.125d, 0.375d, 0.125d, 0.875d, 0.625d), new SimpleCuboid(0d, 0.125d, 0.375d, 0.125d, 0.875d, 0.625d),
new SimpleCuboid(0.875d, 0.125d, 0.375d, 1d, 0.875d, 0.625d) new SimpleCuboid(0.875d, 0.125d, 0.375d, 1d, 0.875d, 0.625d)
); );
@ -378,21 +380,52 @@ public class BlockShapes {
); );
public static final BlockShape PLATE_PRESS_IDLE = new BlockShape( public static final BlockShape PLATE_PRESS_IDLE = new BlockShape(
new SimpleCuboid(0d, 0d, 0d, 1d, 0.5d, 1d), new SimpleCuboid(0.625d, 0d, 0d, 1d, 0.375d, 1d),
new SimpleCuboid(0d, 0.5d, 0.4375d, 1d, 0.75d, 1d), new SimpleCuboid(0.625d, 0.625d, 0d, 1d, 1d, 1d),
new SimpleCuboid(0.75d, 0.5d, 0.0625d, 1d, 0.75d, 0.4375d), new SimpleCuboid(0.625d, 0.375d, 0.125d, 1d, 0.625d, 1d),
new SimpleCuboid(0.125d, 0.5d, 0.25d, 0.6875d, 1d, 0.8125d), new SimpleCuboid(0.6875d, 0.375d, 0.0625d, 0.9375d, 0.625d, 0.125d),
new SimpleCuboid(0.8125d, 0.5d, 0d, 0.9375d, 0.75d, 0.0625d), new SimpleCuboid(0.0625d, 0.5d, 0.1875d, 0.5625d, 0.9375d, 0.9375d),
new SimpleCuboid(0.9375d, 0.75d, 0.9375d, 1d, 0.875d, 1d), new SimpleCuboid(0.0625d, 0d, 0d, 0.5625d, 0.4375d, 1d),
new SimpleCuboid(0d, 0.75d, 0.9375d, 0.0625d, 0.875d, 1d), new SimpleCuboid(0.5625d, 0d, 0.0625d, 0.625d, 1d, 0.1875d),
new SimpleCuboid(0.01875d, 0.8125d, 0.0625d, 0.05d, 0.875d, 0.9375d), new SimpleCuboid(0.5625d, 0d, 0.8125d, 0.625d, 1d, 0.9375d),
new SimpleCuboid(0d, 0.5d, 0d, 0.0625d, 0.875d, 0.0625d), new SimpleCuboid(0d, 0d, 0.0625d, 0.0625d, 1d, 0.1875d),
new SimpleCuboid(0.0625d, 0.8125d, 0.95d, 0.9375d, 0.875d, 0.98125d), new SimpleCuboid(0d, 0d, 0.8125d, 0.0625d, 1d, 0.9375d),
new SimpleCuboid(0.6875d, 0.5d, 0.5625d, 0.75d, 0.875d, 0.75d), new SimpleCuboid(0.5625d, 0.8125d, 0.1875d, 0.625d, 0.9375d, 0.8125d),
new SimpleCuboid(0.6875d, 0.5d, 0.3125d, 0.75d, 0.875d, 0.5d), new SimpleCuboid(0.5625d, 0.0625d, 0.1875d, 0.625d, 0.1875d, 0.8125d),
new SimpleCuboid(0.0625d, 0.5d, 0.3125d, 0.125d, 0.875d, 0.5d), new SimpleCuboid(0d, 0.8125d, 0.1875d, 0.0625d, 0.9375d, 0.8125d),
new SimpleCuboid(0.0625d, 0.5d, 0.5625d, 0.125d, 0.875d, 0.75d), new SimpleCuboid(0d, 0.0625d, 0.1875d, 0.0625d, 0.1875d, 0.8125d),
new SimpleCuboid(0.775d, 0.75d, 0.125d, 0.9625d, 0.9375d, 0.875d) new SimpleCuboid(0.125d, 0.5625d, -0.0625d, 0.5d, 0.5625d, 0.0625d),
new SimpleCuboid(0.0625d, 0.5d, 0.0625d, 0.5625d, 0.5625d, 0.1875d),
new SimpleCuboid(0.0625d, 0.875d, 0.0625d, 0.5625d, 0.9375d, 0.1875d),
new SimpleCuboid(0.5d, 0.5625d, 0.0625d, 0.5625d, 0.875d, 0.1875d),
new SimpleCuboid(0.0625d, 0.5625d, 0.0625d, 0.125d, 0.875d, 0.1875d)
);
public static final BlockShape TWIN_PLATE_PRESS_IDLE = new BlockShape(
new SimpleCuboid(0.625d, 0d, 0d, 1d, 0.375d, 1d),
new SimpleCuboid(0.625d, 0.625d, 0d, 1d, 1d, 1d),
new SimpleCuboid(0.625d, 0.375d, 0.125d, 1d, 0.625d, 1d),
new SimpleCuboid(0.6875d, 0.375d, 0.0625d, 0.9375d, 0.625d, 0.125d),
new SimpleCuboid(0.0625d, 0.5d, 0.1875d, 0.5625d, 0.9375d, 0.9375d),
new SimpleCuboid(0.5625d, 0d, 0.0625d, 0.625d, 1d, 0.1875d),
new SimpleCuboid(0.5625d, 0d, 0.8125d, 0.625d, 1d, 0.9375d),
new SimpleCuboid(0d, 0d, 0.0625d, 0.0625d, 1d, 0.1875d),
new SimpleCuboid(0d, 0d, 0.8125d, 0.0625d, 1d, 0.9375d),
new SimpleCuboid(0.5625d, 0.8125d, 0.1875d, 0.625d, 0.9375d, 0.8125d),
new SimpleCuboid(0.5625d, 0.0625d, 0.1875d, 0.625d, 0.1875d, 0.8125d),
new SimpleCuboid(0d, 0.8125d, 0.1875d, 0.0625d, 0.9375d, 0.8125d),
new SimpleCuboid(0d, 0.0625d, 0.1875d, 0.0625d, 0.1875d, 0.8125d),
new SimpleCuboid(0.125d, 0.5625d, -0.0625d, 0.5d, 0.5625d, 0.0625d),
new SimpleCuboid(0.0625d, 0.5d, 0.0625d, 0.5625d, 0.5625d, 0.1875d),
new SimpleCuboid(0.0625d, 0.875d, 0.0625d, 0.5625d, 0.9375d, 0.1875d),
new SimpleCuboid(0.5d, 0.5625d, 0.0625d, 0.5625d, 0.875d, 0.1875d),
new SimpleCuboid(0.0625d, 0.5625d, 0.0625d, 0.125d, 0.875d, 0.1875d),
new SimpleCuboid(0.0625d, 0d, 0.1875d, 0.5625d, 0.4375d, 0.9375d),
new SimpleCuboid(0.5d, 0.0625d, 0.0625d, 0.5625d, 0.375d, 0.1875d),
new SimpleCuboid(0.0625d, 0.375d, 0.0625d, 0.5625d, 0.4375d, 0.1875d),
new SimpleCuboid(0.0625d, 0.0625d, 0.0625d, 0.125d, 0.375d, 0.1875d),
new SimpleCuboid(0.0625d, 0d, 0.0625d, 0.5625d, 0.0625d, 0.1875d),
new SimpleCuboid(0.125d, 0.0625d, -0.0625d, 0.5d, 0.0625d, 0.0625d)
); );
public static final BlockShape GRAVITATION_STABILIZER = new BlockShape( public static final BlockShape GRAVITATION_STABILIZER = new BlockShape(
@ -569,4 +602,187 @@ public class BlockShapes {
new SimpleCuboid(0.03125d, 0.125d, 0.65625d, 0.34375d, 0.625d, 0.96875d), new SimpleCuboid(0.03125d, 0.125d, 0.65625d, 0.34375d, 0.625d, 0.96875d),
new SimpleCuboid(0.65625d, 0.125d, 0.65625d, 0.96875d, 0.625d, 0.96875d) new SimpleCuboid(0.65625d, 0.125d, 0.65625d, 0.96875d, 0.625d, 0.96875d)
); );
public static final BlockShape ENGINE = new BlockShape(
new SimpleCuboid(0d, 0d, 0.875d, 1d, 1d, 1d),
new SimpleCuboid(0.0625d, 0.0625d, 0.625d, 0.9375d, 0.9375d, 0.875d),
new SimpleCuboid(0.25d, 0.25d, 0.4375d, 0.75d, 0.75d, 0.625d),
new SimpleCuboid(0.1875d, 0.1875d, 0.25d, 0.8125d, 0.8125d, 0.4375d),
new SimpleCuboid(0.125d, 0.125d, 0d, 0.875d, 0.875d, 0.25d),
new SimpleCuboid(0d, 0.875d, 0.5625d, 0.125d, 1d, 0.875d),
new SimpleCuboid(0.0625d, 0.875d, 0.25d, 0.125d, 0.9375d, 0.5625d),
new SimpleCuboid(0.0625d, 0.0625d, 0.25d, 0.125d, 0.125d, 0.5625d),
new SimpleCuboid(0.875d, 0.0625d, 0.25d, 0.9375d, 0.125d, 0.5625d),
new SimpleCuboid(0.875d, 0.875d, 0.25d, 0.9375d, 0.9375d, 0.5625d),
new SimpleCuboid(0.875d, 0.125d, 0.4375d, 0.9375d, 0.875d, 0.5625d),
new SimpleCuboid(0.0625d, 0.125d, 0.4375d, 0.125d, 0.875d, 0.5625d),
new SimpleCuboid(0.125d, 0.875d, 0.4375d, 0.875d, 0.9375d, 0.5625d),
new SimpleCuboid(0.125d, 0.0625d, 0.4375d, 0.875d, 0.125d, 0.5625d),
new SimpleCuboid(0.875d, 0.875d, 0.5625d, 1d, 1d, 0.875d),
new SimpleCuboid(0.875d, 0d, 0.5625d, 1d, 0.125d, 0.875d),
new SimpleCuboid(0d, 0d, 0.5625d, 0.125d, 0.125d, 0.875d)
);
public static final BlockShape CARGO_CRATE_OPEN = new BlockShape(
new SimpleCuboid(0d, 0d, 0d, 1d, 0.8125d, 1d),
new SimpleCuboid(0.125d, 0.8125d, 0.125d, 0.875d, 0.9375d, 0.875d),
new SimpleCuboid(0d, 0.9375d, 0d, 1d, 1.125d, 1d),
new SimpleCuboid(0d, 0.8125d, 0.4375d, 0d, 0.9375d, 0.5625d),
new SimpleCuboid(1d, 0.8125d, 0.4375d, 1d, 0.9375d, 0.5625d),
new SimpleCuboid(0.4375d, 0.8125d, 1d, 0.5625d, 0.9375d, 1d),
new SimpleCuboid(0.4375d, 0.8125d, 0d, 0.5625d, 0.9375d, 0d)
);
public static final BlockShape HOLO_SIGN = new BlockShape(
new SimpleCuboid(0d, 0d, 0.875d, 1d, 1d, 1d),
new SimpleCuboid(0.0625d, 0.0625d, 0.8125d, 0.9375d, 0.9375d, 0.875d),
new SimpleCuboid(0d, 0d, 0.625d, 1d, 1d, 0.8125d),
new SimpleCuboid(0.875d, 0.3125d, 0.5625d, 1d, 0.6875d, 0.625d),
new SimpleCuboid(0d, 0.3125d, 0.5625d, 0.125d, 0.6875d, 0.625d),
new SimpleCuboid(0.0625d, 0.875d, 0.625d, 0.125d, 0.9375d, 0.625d),
new SimpleCuboid(0.0625d, 0.0625d, 0.625d, 0.125d, 0.125d, 0.625d),
new SimpleCuboid(0.875d, 0.0625d, 0.625d, 0.9375d, 0.125d, 0.625d),
new SimpleCuboid(0.875d, 0.875d, 0.625d, 0.9375d, 0.9375d, 0.625d),
new SimpleCuboid(0.875d, 0.375d, 0.5625d, 0.875d, 0.625d, 0.625d),
new SimpleCuboid(0.125d, 0.375d, 0.5625d, 0.125d, 0.625d, 0.625d)
);
public static final BlockShape COBBLESTONE_GENERATOR = new BlockShape(
new SimpleCuboid(0d, 0d, 0d, 1d, 0.375d, 1d),
new SimpleCuboid(0.25d, 0.375d, 0d, 0.75d, 1d, 1d),
new SimpleCuboid(0.0625d, 0.375d, 0.0625d, 0.25d, 0.9375d, 0.9375d),
new SimpleCuboid(0.75d, 0.375d, 0.0625d, 0.9375d, 0.9375d, 0.9375d)
);
public static final BlockShape ESSENCE_STORAGE = new BlockShape(
new SimpleCuboid(0d, 0d, 0d, 1d, 0.125d, 1d),
new SimpleCuboid(0d, 0.1875d, 0d, 1d, 0.3125d, 1d),
new SimpleCuboid(0.5625d, 0.3125d, 0d, 1d, 1d, 0.875d),
new SimpleCuboid(0d, 0.625d, 0.875d, 1d, 1d, 1d),
new SimpleCuboid(0d, 0.3125d, 0.5625d, 0.5625d, 1d, 0.875d),
new SimpleCuboid(0.0625d, 0.125d, 0.0625d, 0.9375d, 0.1875d, 0.9375d),
new SimpleCuboid(0.0625d, 0.3125d, 0.875d, 0.9375d, 0.625d, 0.9375d),
new SimpleCuboid(0.0625d, 0.3125d, 0.0625d, 0.5625d, 0.9375d, 0.5625d)
);
public static final BlockShape MATTER_RECONSTRUCTOR = new BlockShape(
new SimpleCuboid(0d, 0.25d, 0d, 1d, 0.5d, 1d),
new SimpleCuboid(0d, 0d, 0d, 1d, 0.25d, 0.6875d),
new SimpleCuboid(0.8125d, 0.5d, 0d, 1d, 1d, 1d),
new SimpleCuboid(0d, 0.5d, 0d, 0.1875d, 1d, 1d),
new SimpleCuboid(0.1875d, 0.5d, 0.0625d, 0.8125d, 0.9375d, 0.9375d),
new SimpleCuboid(-0.0625d, 0.5d, 0.0625d, 0d, 0.9375d, 0.9375d),
new SimpleCuboid(1d, 0.5d, 0.0625d, 1.0625d, 0.9375d, 0.9375d),
new SimpleCuboid(0.25d, 0.5d, 0.25d, 0.75d, 0.5625d, 0.75d),
new SimpleCuboid(0.875d, 0d, 0.6875d, 0.9375d, 0.25d, 0.9375d),
new SimpleCuboid(0.0625d, 0d, 0.6875d, 0.1875d, 0.25d, 0.9375d),
new SimpleCuboid(0.1875d, 0d, 0.6875d, 0.875d, 0.25d, 0.9375d),
new SimpleCuboid(0.36875d, 0.65625d, 0.5875d, 0.44375d, 0.78125d, 0.9d),
new SimpleCuboid(0.4375d, 0.5d, 0.1875d, 0.5625d, 0.625d, 0.3125d)
);
public static final BlockShape FLUID_TANK = new BlockShape(
new SimpleCuboid(0d, 0d, 0d, 1d, 0.125d, 1d),
new SimpleCuboid(0d, 0.875d, 0d, 1d, 1d, 1d),
new SimpleCuboid(0.03125d, 0.125d, 0.03125d, 0.96875d, 0.1875d, 0.96875d),
new SimpleCuboid(0.03125d, 0.8125d, 0.03125d, 0.96875d, 0.875d, 0.96875d),
new SimpleCuboid(0d, 0.1875d, 0d, 1d, 0.8125d, 1d)
);
public static final BlockShape ANDROID_CHARGER_BASE = new BlockShape(
new SimpleCuboid(0d, 0d, 0d, 1d, 0.5d, 1d),
new SimpleCuboid(0.6875d, 0.5d, 0.0625d, 0.9375d, 0.75d, 0.9375d),
new SimpleCuboid(0.3125d, 0.5d, 0.0625d, 0.0625d, 0.75d, 0.9375d),
new SimpleCuboid(0.125d, 0.5d, 0.125d, 0.875d, 0.6875d, 0.875d),
new SimpleCuboid(0.0625d, 0.5d, 0.0625d, 0.3125d, 0.75d, 0.9375d),
new SimpleCuboid(0.9375d, 0.5d, 0.0625d, 0.6875d, 0.75d, 0.9375d),
new SimpleCuboid(0.1875d, 0.6875d, 0.1875d, 0.3125d, 1d, 0.3125d),
new SimpleCuboid(0.25d, 0.6875d, 0.25d, 0.75d, 1d, 0.75d),
new SimpleCuboid(0.6875d, 0.6875d, 0.1875d, 0.8125d, 1d, 0.3125d),
new SimpleCuboid(0.6875d, 0.6875d, 0.6875d, 0.8125d, 1d, 0.8125d),
new SimpleCuboid(0.1875d, 0.6875d, 0.6875d, 0.3125d, 1d, 0.8125d),
new SimpleCuboid(0.3125d, 0.5d, 0.75d, 0.6875d, 1d, 1d)
);
public static final BlockShape ANDROID_CHARGER_MIDDLE = new BlockShape(
new SimpleCuboid(0.25d, 0d, 0.25d, 0.75d, 1d, 0.75d),
new SimpleCuboid(0.1875d, 0d, 0.6875d, 0.3125d, 1d, 0.8125d),
new SimpleCuboid(0.6875d, 0d, 0.1875d, 0.8125d, 1d, 0.3125d),
new SimpleCuboid(0.1875d, 0d, 0.1875d, 0.3125d, 1d, 0.3125d),
new SimpleCuboid(0.6875d, 0d, 0.6875d, 0.8125d, 1d, 0.8125d),
new SimpleCuboid(0.3125d, 0d, 0.75d, 0.6875d, 1d, 1d),
new SimpleCuboid(0.125d, -0.0625d, 0.125d, 0.875d, 0.3125d, 0.875d),
new SimpleCuboid(0.125d, -0.0625d, 0.875d, 0.875d, 0.3125d, 0.125d),
new SimpleCuboid(0.125d, 0.6875d, 0.875d, 0.875d, 1.0625d, 0.125d),
new SimpleCuboid(0.125d, 0.6875d, 0.125d, 0.875d, 1.0625d, 0.875d)
);
public static final BlockShape ANDROID_CHARGER_TOP = new BlockShape(
new SimpleCuboid(0.1875d, 0.6875d, 0d, 0.8125d, 0.875d, 0d),
new SimpleCuboid(0.1875d, 0d, 0.6875d, 0.3125d, 0.3125d, 0.8125d),
new SimpleCuboid(0.6875d, 0d, 0.1875d, 0.8125d, 0.3125d, 0.3125d),
new SimpleCuboid(0.1875d, 0d, 0.1875d, 0.3125d, 0.3125d, 0.3125d),
new SimpleCuboid(0.6875d, 0d, 0.6875d, 0.8125d, 0.3125d, 0.8125d),
new SimpleCuboid(0.25d, 0d, 0.25d, 0.75d, 0.3125d, 0.75d),
new SimpleCuboid(0.3125d, 0d, 0.75d, 0.6875d, 0.5d, 1d),
new SimpleCuboid(0.0625d, 0.25d, 0.0625d, 0.3125d, 0.5d, 0.9375d),
new SimpleCuboid(0.9375d, 0.25d, 0.0625d, 0.6875d, 0.5d, 0.9375d),
new SimpleCuboid(0.6875d, 0.25d, 0.0625d, 0.9375d, 0.5d, 0.9375d),
new SimpleCuboid(0.3125d, 0.25d, 0.0625d, 0.0625d, 0.5d, 0.9375d),
new SimpleCuboid(0.125d, 0.3125d, 0.125d, 0.875d, 0.5d, 0.875d),
new SimpleCuboid(0d, 0.5d, 0d, 1d, 1d, 1d)
);
public static final BlockShape POWERED_FURNACE = new BlockShape(
new SimpleCuboid(0.9375d, 0.5d, 0d, 1d, 1d, 0.0625d),
new SimpleCuboid(0d, 0.5d, 0d, 0.0625d, 1d, 0.0625d),
new SimpleCuboid(0d, 0.5d, 0.0625d, 1d, 1d, 0.6875d),
new SimpleCuboid(0.6875d, 0.5d, 0.6875d, 1d, 1d, 0.9375d),
new SimpleCuboid(0.6875d, 0.3125d, 0.9375d, 0.75d, 1d, 1d),
new SimpleCuboid(0.9375d, 0.3125d, 0.9375d, 1d, 1d, 1d),
new SimpleCuboid(0.75d, 0.9375d, 0.9375d, 0.9375d, 1d, 1d),
new SimpleCuboid(0.6875d, 0d, 0.9375d, 1d, 0.3125d, 1d),
new SimpleCuboid(0d, 0.375d, 0.9375d, 0.6875d, 0.5d, 1d),
new SimpleCuboid(0.0625d, 0.5d, 0d, 0.9375d, 0.5625d, 0.0625d),
new SimpleCuboid(0.0625d, 0.9375d, 0d, 0.9375d, 1d, 0.0625d),
new SimpleCuboid(0d, 0.0625d, 0.0625d, 1d, 0.4375d, 0.4375d),
new SimpleCuboid(0.8125d, 0d, 0d, 0.9375d, 0.5d, 0.5d),
new SimpleCuboid(0.0625d, 0d, 0d, 0.1875d, 0.5d, 0.5d),
new SimpleCuboid(0.0625d, 0.5d, 0.75d, 0.3125d, 1d, 1d),
new SimpleCuboid(0.375d, 0.5d, 0.75d, 0.625d, 1d, 1d),
new SimpleCuboid(0d, 0d, 0.5d, 1d, 0.5d, 0.9375d),
new SimpleCuboid(0d, 0.5d, 0.6875d, 0.6875d, 0.875d, 0.9375d),
new SimpleCuboid(-0.03125d, 1.03125d, 0.0625d, 1.03125d, 1.03125d, 0.125d),
new SimpleCuboid(-0.03125d, 0.71875d, 0.0625d, -0.03125d, 1.03125d, 0.125d),
new SimpleCuboid(-0.03125d, 0.71875d, 0.125d, -0.03125d, 0.78125d, 0.625d),
new SimpleCuboid(1.03125d, 0.71875d, 0.125d, 1.03125d, 0.78125d, 0.625d),
new SimpleCuboid(1.03125d, 0.71875d, 0.0625d, 1.03125d, 1.03125d, 0.125d),
new SimpleCuboid(-0.0625d, 0.625d, 0.375d, 0d, 0.875d, 0.625d),
new SimpleCuboid(1d, 0.625d, 0.375d, 1.0625d, 0.875d, 0.625d),
new SimpleCuboid(0.0625d, 0.5625d, 0.061875d, 0.9375d, 0.9375d, 0.061875d)
);
public static final BlockShape POWERED_BLAST_FURNACE = new BlockShape(
new SimpleCuboid(0.0625d, 0.625d, 0.6875d, 0.9375d, 0.6875d, 0.9375d),
new SimpleCuboid(0.0625d, 0.5d, 0.6875d, 0.9375d, 0.5625d, 0.9375d),
new SimpleCuboid(0.0625d, 0.375d, 0.6875d, 0.9375d, 0.4375d, 0.9375d),
new SimpleCuboid(0d, 0d, 0d, 1d, 0.3125d, 1d),
new SimpleCuboid(0d, 0.3125d, 0.375d, 1d, 1d, 0.6875d),
new SimpleCuboid(0d, 0.75d, 0.6875d, 1d, 1d, 1d),
new SimpleCuboid(0.125d, 0.3125d, 0.6875d, 0.875d, 0.75d, 0.875d),
new SimpleCuboid(0.1875d, 0.3125d, 0d, 0.8125d, 1d, 0.375d),
new SimpleCuboid(0.25d, 1d, 0.25d, 0.75d, 1.0625d, 0.75d),
new SimpleCuboid(0.03125d, 0.3125d, 0.65625d, 0.96875d, 0.5d, 0.96875d),
new SimpleCuboid(0.96875d, 0.3125d, 0.65625d, 0.03125d, 0.75d, 0.96875d),
new SimpleCuboid(0.8125d, 0.3125d, 0.0625d, 0.9375d, 0.9375d, 0.375d),
new SimpleCuboid(0.0625d, 0.3125d, 0.0625d, 0.1875d, 0.9375d, 0.375d),
new SimpleCuboid(0.061875d, 0.5625d, 0.125d, 0.061875d, 0.625d, 0.3125d),
new SimpleCuboid(0.061875d, 0.6875d, 0.125d, 0.061875d, 0.75d, 0.3125d),
new SimpleCuboid(0.061875d, 0.8125d, 0.125d, 0.061875d, 0.875d, 0.3125d),
new SimpleCuboid(0.938125d, 0.8125d, 0.125d, 0.938125d, 0.875d, 0.3125d),
new SimpleCuboid(0.938125d, 0.5625d, 0.125d, 0.938125d, 0.625d, 0.3125d),
new SimpleCuboid(0.938125d, 0.6875d, 0.125d, 0.938125d, 0.75d, 0.3125d),
new SimpleCuboid(0.3125d, 1.000625d, 0.125d, 0.6875d, 1.000625d, 0.1875d)
);
} }

View File

@ -1,34 +0,0 @@
package ru.dbotthepony.mc.otm
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.config.ModConfig
object ClientConfig {
private val specBuilder = ForgeConfigSpec.Builder()
@Suppress("JoinDeclarationAndAssignment")
private val spec: ForgeConfigSpec
private var registered = false
var EXOPACK_INVENTORY_ROWS: Int by specBuilder
.comment("Amount of inventory rows to show when wearing Exosuit")
.defineInRange("exosuitInventoryRows", 3, 3, 6)
var JUMP_BOOST_LOOK_ANGLE: Double by specBuilder
.comment("If looking below this angle (actually, looking 'above' as you see in game, but not as you expect it, check with debug screen), Crouch + Jump will trigger jump boost android ability")
.defineInRange("jumpBoostTriggerAngle", 30.0, -180.0, 180.0)
var EXOPACK_FREE_SCROLL: Boolean by specBuilder
.comment("Allow to scroll Exopack inventory in non OTM inventories when hovering just over inventory slots, not only scrollbar")
.define("exopackFreeScroll", true)
init {
spec = specBuilder.build()
}
fun register() {
check(!registered) { "Already registered config" }
registered = true
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, spec)
}
}

View File

@ -15,44 +15,73 @@ import net.minecraftforge.event.server.ServerStoppedEvent
import net.minecraftforge.event.server.ServerStoppingEvent import net.minecraftforge.event.server.ServerStoppingEvent
import net.minecraftforge.fml.loading.FMLLoader import net.minecraftforge.fml.loading.FMLLoader
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.IConditionalTickable import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
import ru.dbotthepony.mc.otm.core.ITickable import ru.dbotthepony.mc.otm.core.util.AtomicallyInvalidatedLazy
import ru.dbotthepony.mc.otm.core.TickList import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
import ru.dbotthepony.mc.otm.core.TimerQueue import ru.dbotthepony.mc.otm.core.util.ITickable
import ru.dbotthepony.mc.otm.core.util.TickList
import ru.dbotthepony.mc.otm.graph.GraphNodeList
import ru.dbotthepony.mc.otm.network.MatteryNetworkChannel
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicInteger
private val preServerTick = TickList() private val preServerTick = TickList()
private val postServerTick = TickList() private val postServerTick = TickList()
private val preWorldTick = WeakHashMap<Level, TickList>() private val preWorldTick = WeakHashMap<Level, TickList>()
private val postWorldTick = WeakHashMap<Level, TickList>() private val postWorldTick = WeakHashMap<Level, TickList>()
private val preServerTickTimers = TimerQueue() private val clientThreads = WeakHashSet<Thread>()
private val postServerTickTimers = TimerQueue() private val serverThreads = WeakHashSet<Thread>()
fun onceServerPre(inTicks: Int, callback: Runnable): TimerQueue.Timer? { private val serverCounter = AtomicInteger()
private var _server: MinecraftServer? = null
val isClient: Boolean by lazy { FMLLoader.getDist() == Dist.CLIENT }
val UNIVERSE_TICKS get() = postServerTick.ticks
val Level.ticksPassed get() = postWorldTick.computeIfAbsent(this) { TickList() }.ticks
fun <V> lazyPerServer(fn: (MinecraftServer) -> V): Lazy<V> {
return AtomicallyInvalidatedLazy(serverCounter) {
if (!SERVER_IS_LIVE)
throw IllegalStateException("No server is running")
fn.invoke(_server!!)
}
}
fun onceServerPre(inTicks: Int, callback: Runnable): TickList.Timer? {
if (!SERVER_IS_LIVE) { if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping")) LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
return null return null
} }
return preServerTickTimers.Timer(inTicks, callback) return preServerTick.Timer(inTicks, callback)
} }
fun onceServer(inTicks: Int, callback: Runnable): TimerQueue.Timer? { fun onceServer(inTicks: Int, callback: Runnable): TickList.Timer? {
if (!SERVER_IS_LIVE) { if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping")) LOGGER.error("Refusing to add ticker $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
return null return null
} }
return postServerTickTimers.Timer(inTicks, callback) return postServerTick.Timer(inTicks, callback)
} }
private var _server: MinecraftServer? = null /**
private var _serverThread: Thread? = null * schedules execution of Runnable somewhere in the future,
private var _clientThread: Thread? = null * at discretion of tick list
*/
fun sometimeServer(callback: Runnable): TickList.Timer? {
if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $callback while server is dying", IllegalStateException("Server is stopping"))
return null
}
val isClient: Boolean by lazy { FMLLoader.getDist() == Dist.CLIENT } return postServerTick.sometime(callback)
}
private val isPausedImpl: Boolean get() { private val isPausedImpl: Boolean get() {
val server = _server val server = _server
@ -65,7 +94,7 @@ private val isPausedImpl: Boolean get() {
} }
val isPaused: Boolean get() { val isPaused: Boolean get() {
if (_clientThread === null) { if (clientThreads.isEmpty()) {
return false return false
} }
@ -73,11 +102,7 @@ val isPaused: Boolean get() {
} }
fun recordClientThread() { fun recordClientThread() {
if (_clientThread != null) { clientThreads.add(Thread.currentThread())
throw IllegalStateException("Already have client channel")
}
_clientThread = Thread.currentThread()
} }
fun runIfClient(lambda: () -> Unit) { fun runIfClient(lambda: () -> Unit) {
@ -120,11 +145,11 @@ fun <V> runOnClient(value: V, lambda: () -> V): V {
} }
fun isServerThread(): Boolean { fun isServerThread(): Boolean {
return Thread.currentThread() === _serverThread return Thread.currentThread() in serverThreads
} }
fun isClientThread(): Boolean { fun isClientThread(): Boolean {
return Thread.currentThread() === _clientThread return Thread.currentThread() in clientThreads
} }
val MINECRAFT_SERVER: MinecraftServer val MINECRAFT_SERVER: MinecraftServer
@ -146,28 +171,38 @@ private val LOGGER = LogManager.getLogger()
fun onServerTick(event: ServerTickEvent) { fun onServerTick(event: ServerTickEvent) {
if (event.phase === TickEvent.Phase.START) { if (event.phase === TickEvent.Phase.START) {
preServerTickTimers.tick()
preServerTick.tick() preServerTick.tick()
serverThreads.add(Thread.currentThread())
} else { } else {
postServerTickTimers.tick()
postServerTick.tick() postServerTick.tick()
// чтоб не плодить кучу подписчиков, вызовем напрямую отсюда
GraphNodeList.tick()
AbstractProfiledStorage.onServerPostTick()
MatteryNetworkChannel.onServerPostTick()
} }
} }
fun onWorldTick(event: LevelTickEvent) { fun onLevelTick(event: LevelTickEvent) {
if (event.phase === TickEvent.Phase.START) { if (event.phase === TickEvent.Phase.START) {
preWorldTick[event.level]?.tick() preWorldTick[event.level]?.tick()
if (event.side.isClient) {
clientThreads.add(Thread.currentThread())
} else if (event.side.isServer) {
serverThreads.add(Thread.currentThread())
}
} else { } else {
postWorldTick[event.level]?.tick() postWorldTick[event.level]?.tick()
MatteryBlockEntity.postLevelTick(event)
} }
} }
fun onceServerPre(ticker: ITickable) { fun onceServerPre(ticker: ITickable) {
preServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping") preServerTick.once(ticker, SERVER_IS_LIVE, "Server is stopping")
} }
fun onceServer(ticker: ITickable) { fun onceServer(ticker: ITickable) {
postServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping") postServerTick.once(ticker, SERVER_IS_LIVE, "Server is stopping")
} }
fun tickServerPre(ticker: IConditionalTickable) { fun tickServerPre(ticker: IConditionalTickable) {
@ -178,41 +213,31 @@ fun tickServer(ticker: IConditionalTickable) {
postServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping") postServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping")
} }
fun tickUntilServerPre(ticker: () -> Boolean) {
preServerTick.until(ticker, SERVER_IS_LIVE, "Server is stopping")
}
fun tickUntilServer(ticker: () -> Boolean) {
postServerTick.until(ticker, SERVER_IS_LIVE, "Server is stopping")
}
fun tickWhileServerPre(condition: () -> Boolean, ticker: () -> Unit) {
preServerTick.`while`(condition, ticker, SERVER_IS_LIVE, "Server is stopping")
}
fun tickWhileServer(condition: () -> Boolean, ticker: () -> Unit) {
postServerTick.`while`(condition, ticker, SERVER_IS_LIVE, "Server is stopping")
}
fun Level.once(ticker: ITickable) { fun Level.once(ticker: ITickable) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) { if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping")) LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return return
} }
postWorldTick.computeIfAbsent(this) { TickList() }.add(ticker) postWorldTick.computeIfAbsent(this) { TickList() }.once(ticker)
} }
fun Level.oncePre(ticker: ITickable) { fun Level.oncePre(ticker: ITickable) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) { if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping")) LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return return
} }
preWorldTick.computeIfAbsent(this) { TickList() }.add(ticker) preWorldTick.computeIfAbsent(this) { TickList() }.once(ticker)
} }
fun Level.addTicker(ticker: IConditionalTickable) { fun Level.addTicker(ticker: IConditionalTickable) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) { if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping")) LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return return
@ -222,6 +247,8 @@ fun Level.addTicker(ticker: IConditionalTickable) {
} }
fun Level.addTickerPre(ticker: IConditionalTickable) { fun Level.addTickerPre(ticker: IConditionalTickable) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) { if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping")) LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return return
@ -231,24 +258,26 @@ fun Level.addTickerPre(ticker: IConditionalTickable) {
} }
fun Level.until(ticker: () -> Boolean) { fun Level.until(ticker: () -> Boolean) {
if (this.isClientSide) return
addTicker(IConditionalTickable.wrap(ticker)) addTicker(IConditionalTickable.wrap(ticker))
} }
fun Level.untilPre(ticker: () -> Boolean) { fun Level.untilPre(ticker: () -> Boolean) {
if (this.isClientSide) return
addTickerPre(IConditionalTickable.wrap(ticker)) addTickerPre(IConditionalTickable.wrap(ticker))
} }
fun Level.`while`(condition: () -> Boolean, ticker: () -> Unit) { fun Level.`while`(condition: () -> Boolean, ticker: () -> Unit) {
if (this.isClientSide) return
addTicker(IConditionalTickable.wrap(condition, ticker)) addTicker(IConditionalTickable.wrap(condition, ticker))
} }
fun Level.whilePre(condition: () -> Boolean, ticker: () -> Unit) { fun Level.whilePre(condition: () -> Boolean, ticker: () -> Unit) {
if (this.isClientSide) return
addTickerPre(IConditionalTickable.wrap(condition, ticker)) addTickerPre(IConditionalTickable.wrap(condition, ticker))
} }
private fun clear() { private fun clear() {
preServerTickTimers.clear()
postServerTickTimers.clear()
preServerTick.clear() preServerTick.clear()
postServerTick.clear() postServerTick.clear()
preWorldTick.clear() preWorldTick.clear()
@ -259,22 +288,27 @@ fun onServerStarting(event: ServerAboutToStartEvent) {
clear() clear()
SERVER_IS_LIVE = true SERVER_IS_LIVE = true
_server = event.server _server = event.server
_serverThread = Thread.currentThread() serverThreads.add(Thread.currentThread())
serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStarting()
} }
fun onServerStopping(event: ServerStoppingEvent) { fun onServerStopping(event: ServerStoppingEvent) {
clear() clear()
SERVER_IS_LIVE = false SERVER_IS_LIVE = false
serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStopping()
} }
fun onServerStopped(event: ServerStoppedEvent) { fun onServerStopped(event: ServerStoppedEvent) {
if (SERVER_IS_LIVE) { if (SERVER_IS_LIVE) {
LOGGER.fatal("ServerStoppingEvent did not fire. If server has crashed this is normal. However, if server finished it's work 'gracefully' this is a bug.") LOGGER.fatal("ServerStoppingEvent did not fire. If server has crashed this is normal. However, if server finished it's work 'gracefully' this is a bug!")
clear() clear()
SERVER_IS_LIVE = false SERVER_IS_LIVE = false
} }
_server = null _server = null
_serverThread = null serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStopped()
} }

View File

@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.ints.IntArrayList
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraftforge.common.ForgeConfigSpec import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.registries.IForgeRegistry import net.minecraftforge.registries.IForgeRegistry
import ru.dbotthepony.mc.otm.config.getValue
import java.util.LinkedList import java.util.LinkedList
abstract class ObservedConfigList<V : Any>(val parent: ForgeConfigSpec.ConfigValue<MutableList<String>>, private val allowNulls: Boolean = false) : AbstractMutableList<V>(), RandomAccess { abstract class ObservedConfigList<V : Any>(val parent: ForgeConfigSpec.ConfigValue<MutableList<String>>, private val allowNulls: Boolean = false) : AbstractMutableList<V>(), RandomAccess {

View File

@ -1,270 +0,0 @@
package ru.dbotthepony.mc.otm
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.config.ModConfig
import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterDecomposerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterRecyclerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterReplicatorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterScannerBlockEntity
import ru.dbotthepony.mc.otm.capability.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.core.Decimal
import ru.dbotthepony.mc.otm.core.defineDecimal
import ru.dbotthepony.mc.otm.item.EnergySwordItem
import ru.dbotthepony.mc.otm.registry.MNames
interface VerboseBalanceValues {
val capacity: Decimal
val receive: Decimal
val extract: Decimal
}
interface BatteryBalanceValues : VerboseBalanceValues {
val initialBatteryLevel: Decimal
}
interface ConciseBalanceValues {
val capacity: Decimal
val throughput: Decimal
}
object ServerConfig {
private val specBuilder = ForgeConfigSpec.Builder()
@Suppress("JoinDeclarationAndAssignment")
private val spec: ForgeConfigSpec
private var registered = false
private fun verboseValues(name: String, storage: Decimal, receive: Decimal, extract: Decimal = receive): VerboseBalanceValues {
specBuilder.push(name)
val obj = object : VerboseBalanceValues {
override val capacity: Decimal by specBuilder.defineDecimal("capacity", storage, minimum = Decimal.ONE)
override val receive: Decimal by specBuilder.defineDecimal("receive", receive, minimum = Decimal.ONE)
override val extract: Decimal by specBuilder.defineDecimal("extract", extract, minimum = Decimal.ONE)
}
specBuilder.pop()
return obj
}
private fun batteryValues(name: String, storage: Decimal, receive: Decimal, extract: Decimal = receive, initialBatteryLevel: Decimal = Decimal.ZERO): BatteryBalanceValues {
specBuilder.push(name)
val obj = object : BatteryBalanceValues {
override val capacity: Decimal by specBuilder.defineDecimal("capacity", storage, minimum = Decimal.ONE)
override val receive: Decimal by specBuilder.defineDecimal("receive", receive, minimum = Decimal.ONE)
override val extract: Decimal by specBuilder.defineDecimal("extract", extract, minimum = Decimal.ONE)
override val initialBatteryLevel: Decimal by specBuilder.defineDecimal("initialBatteryLevel", initialBatteryLevel, minimum = Decimal.ZERO)
}
specBuilder.pop()
return obj
}
private fun conciseValues(name: String, storage: Decimal, throughput: Decimal): ConciseBalanceValues {
specBuilder.push(name)
val obj = object : ConciseBalanceValues {
override val capacity: Decimal by specBuilder.defineDecimal("capacity", storage, minimum = Decimal.ONE)
override val throughput: Decimal by specBuilder.defineDecimal("throughput", throughput, minimum = Decimal.ONE)
}
specBuilder.pop()
return obj
}
val LABORATORY_LAMP_LIGHT_LENGTH: Int by specBuilder.comment("In blocks").defineInRange("laboratoryLampLightLength", 6, 1, 128)
init {
specBuilder.comment("Energy batteries balance values").push("energyBatteries")
}
val BATTERY_CRUDE = batteryValues(MNames.BATTERY_CRUDE, Decimal(100_000), Decimal(160), Decimal(40), Decimal(80_000))
val BATTERY_BASIC = batteryValues(MNames.BATTERY_BASIC, Decimal(400_000), Decimal(600))
val BATTERY_NORMAL = batteryValues(MNames.BATTERY_NORMAL, Decimal(2_000_000), Decimal(1_000))
val BATTERY_DENSE = batteryValues(MNames.BATTERY_DENSE, Decimal(10_000_000), Decimal(2_000))
val BATTERY_CAPACITOR = batteryValues(MNames.BATTERY_CAPACITOR, Decimal(500_000), Decimal(50_000))
val QUANTUM_BATTERY = conciseValues(MNames.QUANTUM_BATTERY, Decimal(40_000_000), Decimal(10_000))
val QUANTUM_CAPACITOR = conciseValues(MNames.QUANTUM_CAPACITOR, Decimal(1_000_000), Decimal(200_000))
val ZPM_BATTERY = conciseValues(MNames.ZPM_BATTERY, Decimal(200_000_000_000_000L), Decimal(200_000_000L))
init {
specBuilder.pop()
specBuilder.comment("Matter capacitors and pattern drives balance values").push("matterCapacitorsAndDrives")
}
val MATTER_CAPACITOR_BASIC by specBuilder.defineDecimal(MNames.MATTER_CAPACITOR_BASIC, Decimal(2_000), minimum = Decimal.ONE_TENTH)
val MATTER_CAPACITOR_NORMAL by specBuilder.defineDecimal(MNames.MATTER_CAPACITOR_NORMAL, Decimal(40_000), minimum = Decimal.ONE_TENTH)
val MATTER_CAPACITOR_DENSE by specBuilder.defineDecimal(MNames.MATTER_CAPACITOR_DENSE, Decimal(400_000), minimum = Decimal.ONE_TENTH)
val MATTER_DUST_CAPACITY by specBuilder.comment("Maximal matter value one matter dust item can have").defineDecimal("matterDustCapacity", Decimal(2_000), minimum = Decimal.ONE_TENTH)
val PATTERN_DRIVE_NORMAL: Int by specBuilder.defineInRange(MNames.PATTERN_DRIVE_NORMAL, 4, 1, Int.MAX_VALUE)
init {
specBuilder.pop()
specBuilder.comment("Balance values of machinery").push("machines")
AndroidStationBlockEntity.registerConfig(specBuilder)
ChemicalGeneratorBlockEntity.registerConfig(specBuilder)
MatterRecyclerBlockEntity.registerConfig(specBuilder)
MatterBottlerBlockEntity.registerConfig(specBuilder)
MatterReplicatorBlockEntity.registerConfig(specBuilder)
MatterScannerBlockEntity.registerConfig(specBuilder)
MatterDecomposerBlockEntity.registerConfig(specBuilder)
}
val PLATE_PRESS = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.PLATE_PRESS)
val STORAGE_POWER_SUPPLIER = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.STORAGE_POWER_SUPPLIER, capacity = Decimal(100_000), throughput = Decimal(320))
val STORAGE_INTERFACES = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, "storage_interfaces", capacity = Decimal(10_000))
val ITEM_MONITOR = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.ITEM_MONITOR)
val DRIVE_VIEWER = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.DRIVE_VIEWER)
val DRIVE_RACK = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.DRIVE_RACK, capacity = Decimal(80_000))
init {
specBuilder.pop()
specBuilder.comment("Tweaking of android players").push("androidPlayer")
}
val REGENERATE_ENERGY: Boolean by specBuilder
.comment("If (technically) hunger is above threshold, it turns into energy")
.comment("This setting controls whenever to regenerate small amount of energy while eating as Android")
.comment("And also whenever to regenerate energy while in peaceful")
.comment("If this is disabled, any (technically) excess hunger will be nullified, unless playing on peaceful difficulty.")
.define("regenerateEnergy", true)
object NanobotsRegeneration {
val COOLDOWN: List<Int> by specBuilder
.comment("In ticks, time between heal ticks")
.comment("One heal tick restores 1 heart (2 health points) at most")
.comment("If not getting hurt in specified period of ticks, heal tick takes place, tick timer resets to zero and THIS array' index advances by 1")
.comment("Index inside this array can not exceed of one of ability's")
.comment("")
.comment("Wording in pseudocode:")
.comment("if (ticksSinceTakingDamage >= cooldownConfigOption[healTicks /* or config's biggest index, whichever is smaller */]) {")
.comment(" healTicks = min(healTicks + 1, this.level /* ability level */)")
.comment(" ticksSinceTakingDamage = 0")
.comment(" this.ply.heal(...)")
.comment("}")
.defineList("cooldown", { mutableListOf(80, 60, 40, 20) }) { it is Int }
val ENERGY_PER_HITPOINT by specBuilder
.comment("Energy required to regenerate 1 health point (half a heart)")
.defineDecimal("energyPerHitpoint", Decimal(800))
}
val ANDROID_ENERGY_PER_HUNGER_POINT by specBuilder.defineDecimal("energyPerHunger", Decimal(2000), Decimal.ZERO)
val ANDROID_MAX_ENERGY by specBuilder.comment("Internal battery of every android has this much storage").defineDecimal("capacity", Decimal(80_000), Decimal.ZERO)
val NIGHT_VISION_POWER_DRAW by specBuilder.defineDecimal("nightVisionPowerDraw", Decimal(8), Decimal.ZERO)
val FALL_DAMAGE_REDUCTION_PER_LEVEL: Double by specBuilder.comment("In percent. Level of feature is multiplied by this").defineInRange("fallDamageReductionPerDampenerLevel", 0.25, 0.01, 1.0)
object EnderTeleporter {
init {
specBuilder.comment("Ender Teleporter ability").push("ender_teleporter")
}
val ENERGY_COST by specBuilder.defineDecimal("energyCost", Decimal(4096), Decimal.ZERO)
val COOLDOWN: Int by specBuilder.comment("In ticks").defineInRange("cooldown", 40, 0, Int.MAX_VALUE)
val MAX_PHASE_DISTANCE: Int by specBuilder.comment("Determines how much blocks can we 'phase' through to teleport on solid surface").defineInRange("maxPhaseDistance", 6, 0, Int.MAX_VALUE)
val MAX_DISTANCE: Double by specBuilder.comment("In blocks, euclidean distance").defineInRange("maxDistance", 12.0, 2.0, Int.MAX_VALUE.toDouble())
init {
specBuilder.pop()
}
}
object AndroidJumpBoost {
init {
specBuilder.comment("Jump boost ability").push("jump_boost")
}
val ENERGY_COST by specBuilder.defineDecimal("energyCost", Decimal(1024), Decimal.ZERO)
val POWER: Double by specBuilder.comment("The jump height on jump boost, as (level + 1) of feature, in meters per second").defineInRange("power", 6.0, 0.0, Double.MAX_VALUE)
val BASE_COOLDOWN: Int by specBuilder.comment("In ticks").defineInRange("baseCooldown", 40, 0, Int.MAX_VALUE)
val COOLDOWN_REDUCTION: Int by specBuilder.comment("In ticks, per level of feature").defineInRange("cooldownReduction", 20, 0, Int.MAX_VALUE)
init {
specBuilder.pop()
}
}
object AndroidItemMagnet {
init {
specBuilder.comment("Item magnet ability").push("item_magnet")
}
val POWER_DRAW by specBuilder.comment("Per tick per stack").defineDecimal("powerDraw", Decimal(8), Decimal.ZERO)
val RADIUS_HORIZONTAL: Double by specBuilder.defineInRange("radiusHorizontal", 6.0, 0.0, Double.MAX_VALUE / 4.0)
val RADIUS_VERTICAL: Double by specBuilder.defineInRange("radiusVertical", 3.0, 0.0, Double.MAX_VALUE / 4.0)
init {
specBuilder.pop()
}
}
object Shockwave {
init {
specBuilder.comment("Shockwave ability").push("shockwave")
}
val TERMINAL_VELOCITY: Double by specBuilder.comment("In meters per second vertically").defineInRange("terminalVelocity", 5.6, 0.0)
val ACCELERATION: Double by specBuilder.comment("In meters per second vertically").defineInRange("acceleration", 4.0, 0.0)
val COOLDOWN: Int by specBuilder.comment("In ticks").defineInRange("cooldown", 30, 1)
val RADIUS_HORIZONTAL: Double by specBuilder.comment("In meters").defineInRange("radiusHorizontal", 4.0, 0.0)
val RADIUS_VERTICAL: Double by specBuilder.comment("In meters").defineInRange("radiusVertical", 1.0, 0.0)
val RADIUS_HORIZONTAL_WARDEN: Double by specBuilder.comment("In meters, when searching for Warden").defineInRange("radiusHorizontalWarden", 16.0, 0.0)
val RADIUS_VERTICAL_WARDEN: Double by specBuilder.comment("In meters, when searching for Warden").defineInRange("radiusVerticalWarden", 6.0, 0.0)
val BREAK_BLOCKS: Boolean by specBuilder.comment("Break blocks without any blast resistance").define("breakBlocks", true)
val DAMAGE: Double by specBuilder.comment("Max potential damage done by shockwave").defineInRange("damage", 12.0, 0.0, Float.MAX_VALUE.toDouble())
val WARDEN_DAMAGE_MULT: Double by specBuilder.defineInRange("wardenDamageMultiplier", 4.0, 0.0, Float.MAX_VALUE.toDouble())
val ENERGY_COST by specBuilder.defineDecimal("energyCost", Decimal(2048), Decimal.ZERO)
init {
specBuilder.pop()
}
}
init {
// access instances so spec is built
NanobotsRegeneration
EnderTeleporter
AndroidJumpBoost
AndroidItemMagnet
Shockwave
specBuilder.pop()
specBuilder.comment("Tweaking of exosuits").push("exosuitPlayer")
}
val INFINITE_EXOSUIT_UPGRADES: Boolean by specBuilder.comment("Allows to apply the same upgrade over and over again.", "Obviously completely breaks balance.").define("infinite_upgrades", false)
init {
specBuilder.pop()
EnergySwordItem.registerConfig(specBuilder)
}
init {
spec = specBuilder.build()
}
fun register() {
check(!registered) { "Already registered config" }
registered = true
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, spec)
}
}

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.mc.otm package ru.dbotthepony.mc.otm
import net.minecraft.util.TimeSource import net.minecraft.util.TimeSource
import ru.dbotthepony.mc.otm.core.formatTickDuration import ru.dbotthepony.mc.otm.core.util.formatTickDuration
import java.util.function.LongSupplier import java.util.function.LongSupplier
/** /**

View File

@ -3,11 +3,11 @@ package ru.dbotthepony.mc.otm.android
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.event.entity.living.LivingAttackEvent
import net.minecraftforge.event.entity.living.LivingHurtEvent import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.network.FieldSynchronizer import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import java.io.DataInputStream
import java.io.InputStream import java.io.InputStream
abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayerCapability) : INBTSerializable<CompoundTag> { abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayerCapability) : INBTSerializable<CompoundTag> {
@ -35,13 +35,14 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt
open fun removeModifiers() {} open fun removeModifiers() {}
open fun onHurt(event: LivingHurtEvent) {} open fun onHurt(event: LivingHurtEvent) {}
open fun onAttack(event: LivingAttackEvent) {}
open fun collectNetworkPayload(): FastByteArrayOutputStream? { open fun collectNetworkPayload(): FastByteArrayOutputStream? {
return synchronizer.collectNetworkPayload() return synchronizer.collectNetworkPayload()
} }
open fun applyNetworkPayload(stream: InputStream) { open fun applyNetworkPayload(stream: InputStream) {
synchronizer.applyNetworkPayload(stream) synchronizer.read(stream)
} }
override fun serializeNBT(): CompoundTag { override fun serializeNBT(): CompoundTag {

View File

@ -1,44 +1,64 @@
package ru.dbotthepony.mc.otm.android package ru.dbotthepony.mc.otm.android
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.eventbus.api.Cancelable
import net.minecraftforge.eventbus.api.Event
import net.minecraftforge.eventbus.api.Event.HasResult
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.awareItemsStream import ru.dbotthepony.mc.otm.capability.awareItemsStream
import ru.dbotthepony.mc.otm.capability.itemsStream
import ru.dbotthepony.mc.otm.client.render.SkinElement
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.addAll
import ru.dbotthepony.mc.otm.core.getCompoundList
import ru.dbotthepony.mc.otm.core.nonEmpty
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.milliTime import ru.dbotthepony.mc.otm.milliTime
import ru.dbotthepony.mc.otm.nanoTime import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
import java.io.DataInputStream
import java.io.InputStream import java.io.InputStream
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlayerCapability) : INBTSerializable<CompoundTag> { class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlayerCapability) : INBTSerializable<CompoundTag> {
/**
* Fired on main event bus [MinecraftForge.EVENT_BUS]
*/
data class OnResearched(val research: AndroidResearch) : Event()
/**
* Fired on main event bus [MinecraftForge.EVENT_BUS]
*/
data class OnUnResearched(val research: AndroidResearch) : Event()
/**
* Fired on main event bus [MinecraftForge.EVENT_BUS]
*/
data class OnRefunded(val research: AndroidResearch) : Event()
/**
* Fired on main event bus [MinecraftForge.EVENT_BUS]
*/
data class GatherTooltipsEvent(val research: AndroidResearch, val tooltips: MutableList<Component>) : Event()
/**
* Fired on main event bus [MinecraftForge.EVENT_BUS]
*/
@HasResult
data class ConsumeResearchCost(val research: AndroidResearch, val isSimulating: Boolean) : Event()
val ply: Player get() = capability.ply val ply: Player get() = capability.ply
val synchronizer = FieldSynchronizer() val synchronizer = FieldSynchronizer()
var isResearched by synchronizer.bool() var isResearched by synchronizer.bool().property
private set
var tag = CompoundTag()
private set private set
/** /**
@ -53,63 +73,24 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
return return
} }
onUnResearch() onUnResearched()
isResearched = false isResearched = false
} }
private data class RememberResearchLevel(val level: Int?) fun onUnResearched() {
for (result in type.results) {
private val oldResearchLevel = Object2ObjectArrayMap<AndroidFeatureType<*>, RememberResearchLevel>() result.onUnResearched(this)
fun onUnResearch() {
for (feature in type.resolvedFeatures) {
val level = oldResearchLevel[feature.feature]
val get = capability.getFeature(feature.feature)
if (level != null && get != null) {
if (get.level == feature.level) {
if (level.level == null) {
capability.removeFeature(feature.feature)
} else {
get.level = level.level
for (transformer in type.features.first { it.id == feature.feature.registryName }.transformersDown) {
transformer.apply(this to get)
}
}
}
}
} }
oldResearchLevel.clear() MinecraftForge.EVENT_BUS.post(OnUnResearched(this))
} }
fun onResearched() { fun onResearched() {
oldResearchLevel.clear() for (result in type.results) {
result.onResearched(this)
try {
for (feature in type.resolvedFeatures) {
var get = capability.getFeature(feature.feature)
if (get == null) {
get = capability.addFeature(feature.feature)
get.level = feature.level
oldResearchLevel[feature.feature] = RememberResearchLevel(null)
} else {
if (get.level < feature.level) {
oldResearchLevel[feature.feature] = RememberResearchLevel(feature.level)
get.level = feature.level
}
} }
for (transformer in type.features.first { it.id == feature.feature.registryName }.transformersUp) { MinecraftForge.EVENT_BUS.post(OnResearched(this))
transformer.apply(this to get)
}
}
} catch(err: Throwable) {
oldResearchLevel.clear()
throw err
}
} }
/** /**
@ -125,6 +106,15 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
return true return true
} }
val event = ConsumeResearchCost(this, simulate)
MinecraftForge.EVENT_BUS.post(event)
if (event.result == Event.Result.ALLOW) {
return true
} else if (event.result == Event.Result.DENY) {
return false
}
if (!simulate && !consumeResearchCost(true)) { if (!simulate && !consumeResearchCost(true)) {
return false return false
} }
@ -166,11 +156,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
* *
* Returns true whenever player accepted all resources refunded, false otherwise. * Returns true whenever player accepted all resources refunded, false otherwise.
*/ */
fun refund(simulate: Boolean): Boolean { fun refund(): Boolean {
if (simulate) {
return true
}
if (type.experienceLevels > 0) { if (type.experienceLevels > 0) {
var experiencePoints = 0 var experiencePoints = 0
@ -195,6 +181,8 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
} }
} }
MinecraftForge.EVENT_BUS.post(OnRefunded(this))
return true return true
} }
@ -203,7 +191,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
} }
fun applyNetworkPayload(stream: InputStream) { fun applyNetworkPayload(stream: InputStream) {
synchronizer.applyNetworkPayload(stream) synchronizer.read(stream)
} }
val canResearch: Boolean get() { val canResearch: Boolean get() {
@ -304,7 +292,12 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
val tooltipLines: List<Component> get() { val tooltipLines: List<Component> get() {
val lines = ArrayList<Component>() val lines = ArrayList<Component>()
lines.add(type.displayName) lines.add(type.displayName)
lines.addAll(type.description.iterator())
for (line in type.description) {
line.addLines(this, lines)
}
MinecraftForge.EVENT_BUS.post(GatherTooltipsEvent(this, lines))
return lines return lines
} }
@ -389,38 +382,12 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
override fun serializeNBT(): CompoundTag { override fun serializeNBT(): CompoundTag {
return CompoundTag().also { return CompoundTag().also {
it["researched"] = isResearched it["researched"] = isResearched
it["tag"] = tag
it["oldResearchLevel"] = ListTag().also {
for ((k, v) in oldResearchLevel) {
it.add(CompoundTag().also {
it["key"] = k.registryName!!.toString()
it["value"] = CompoundTag().also {
it["isPresent"] = v.level != null
if (v.level != null) {
it["value"] = v.level
}
}
})
}
}
} }
} }
override fun deserializeNBT(nbt: CompoundTag) { override fun deserializeNBT(nbt: CompoundTag) {
isResearched = nbt.getBoolean("researched") isResearched = nbt.getBoolean("researched")
tag = nbt.getCompound("tag")
oldResearchLevel.clear()
for (tag in nbt.getCompoundList("oldResearchLevel")) {
val key = tag.getString("key")
val type = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(key)) ?: continue
val value = tag.getCompound("value")
val isPresent = value.getBoolean("isPresent")
val int = value.getInt("value")
oldResearchLevel[type] = RememberResearchLevel(if (isPresent) int else null)
}
} }
} }

View File

@ -1,17 +1,34 @@
package ru.dbotthepony.mc.otm.android package ru.dbotthepony.mc.otm.android
import com.google.gson.JsonObject
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.data.CachedOutput import net.minecraft.data.CachedOutput
import net.minecraft.data.DataGenerator
import net.minecraft.data.DataProvider import net.minecraft.data.DataProvider
import net.minecraft.data.PackOutput
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.core.toJson
import ru.dbotthepony.mc.otm.core.toJsonStrict
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import java.util.Collections import java.util.Collections
import java.util.LinkedList import java.util.LinkedList
import java.util.concurrent.CompletableFuture
import java.util.function.Consumer import java.util.function.Consumer
@Suppress("unused") @Suppress("unused")
open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerator) : DataProvider { open class AndroidResearchDataProvider() : DataProvider {
protected val pathProvider: DataGenerator.PathProvider = dataGenerator.createPathProvider(DataGenerator.Target.DATA_PACK, AndroidResearchManager.DIRECTORY) var pathProvider: PackOutput.PathProvider by WriteOnce("You need to call bindPackOutput before registering this data provider")
private set
constructor(output: PackOutput) : this() {
bindPackOutput(output)
}
constructor(event: GatherDataEvent) : this(event.generator.packOutput)
fun bindPackOutput(output: PackOutput) {
pathProvider = output.createPathProvider(PackOutput.Target.DATA_PACK, AndroidResearchManager.DIRECTORY)
}
protected val callbacks = LinkedList<(Consumer<AndroidResearchType>) -> Unit>() protected val callbacks = LinkedList<(Consumer<AndroidResearchType>) -> Unit>()
@ -35,15 +52,14 @@ open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerato
return this return this
} }
final override fun run(output: CachedOutput) { final override fun run(output: CachedOutput): CompletableFuture<*> {
AndroidResearchManager.fireRegistrationEvent()
val set = ObjectArraySet<ResourceLocation>() val set = ObjectArraySet<ResourceLocation>()
val added = LinkedList<AndroidResearchType>() val added = LinkedList<AndroidResearchType>()
val futures = ArrayList<CompletableFuture<*>>()
addEverything { addEverything {
if (set.add(it.id)) { if (set.add(it.id)) {
DataProvider.saveStable(output, it.toJson(), pathProvider.json(it.id)) futures.add(DataProvider.saveStable(output, AndroidResearchType.CODEC.toJsonStrict(it).also { (it as JsonObject).remove("id") }, pathProvider.json(it.id)))
AndroidResearchManager.put(it) AndroidResearchManager.put(it)
added.add(it) added.add(it)
} else { } else {
@ -55,6 +71,8 @@ open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerato
value.validate() value.validate()
generated.add(value) generated.add(value)
} }
return CompletableFuture.allOf(*futures.toTypedArray())
} }
override fun getName(): String { override fun getName(): String {

View File

@ -0,0 +1,147 @@
package ru.dbotthepony.mc.otm.android
import com.mojang.datafixers.util.Either
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.DeferredRegister
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.getValue
import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.data.ComponentCodec
import ru.dbotthepony.mc.otm.data.SingletonCodec
import ru.dbotthepony.mc.otm.data.simpleCodec
import ru.dbotthepony.mc.otm.registry.RegistryDelegate
object AndroidResearchDescriptions {
private val registrar = DeferredRegister.create(AndroidResearchDescription.registryKey, OverdriveThatMatters.MOD_ID)
init {
registrar.register("plain") { PlainAndroidResearchDescription }
}
internal fun register(bus: IEventBus) {
registrar.register(bus)
}
val ENDER_TELEPORTER: AndroidResearchDescription.Singleton by registrar.register("ender_teleporter") {
AndroidResearchDescription.singleton {
TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.EnderTeleporter.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
}
val FALL_DAMPENERS: AndroidResearchDescription.Leveled by registrar.register("fall_dampeners") {
AndroidResearchDescription.Leveled { _, list, level ->
list.add(TranslatableComponent("otm.fall_dampeners.description",
TextComponent("%.1f".format((AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * level).toFloat().coerceIn(0f, 1f) * 100f)).withStyle(ChatFormatting.YELLOW),
TextComponent("%.1f".format((AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * level).toFloat())).withStyle(ChatFormatting.YELLOW),
)) }
}
val SWIM_BOOSTERS: AndroidResearchDescription.Leveled by registrar.register("swim_boosters") {
AndroidResearchDescription.Leveled { _, list, level ->
list.add(TranslatableComponent(
"android_research.overdrive_that_matters.swim_boosters.description",
TextComponent("%.1f".format(AndroidConfig.SWIM_BOOSTERS * (1 + level) * 100.0)).withStyle(ChatFormatting.YELLOW)
)) }
}
val ITEM_MAGNET: AndroidResearchDescription.Singleton by registrar.register("item_magnet") {
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_tick", AndroidConfig.Magnet.POWER_DRAW.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
}
val JUMP_BOOST: AndroidResearchDescription.Singleton by registrar.register("jump_boost") {
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.JumpBoost.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
}
val SHOCKWAVE: AndroidResearchDescription.Singleton by registrar.register("shockwave") {
AndroidResearchDescription.singleton { TranslatableComponent("otm.gui.power_cost_per_use", AndroidConfig.Shockwave.ENERGY_COST.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.YELLOW)) }
}
}
/**
* Instance, representing ready to use description populator
*/
interface AndroidResearchDescription {
/**
* Type, representing raw description populator in registry
*/
interface Type<T : AndroidResearchDescription> {
val codec: Codec<T>
}
abstract class Singleton : AndroidResearchDescription, Type<Singleton> {
override val codec = SingletonCodec(this)
override val type: Type<*>
get() = this
}
class Leveled(val callback: (research: AndroidResearch, lines: MutableList<Component>, level: Int) -> Unit) : Type<Leveled.Instance> {
inner class Instance(val level: Int) : AndroidResearchDescription {
override fun addLines(research: AndroidResearch, lines: MutableList<Component>) {
callback.invoke(research, lines, level)
}
override val type: Type<*>
get() = this@Leveled
}
override val codec: Codec<Instance> by lazy {
RecordCodecBuilder.create {
it.group(Codec.INT.fieldOf("level").forGetter(Instance::level)).apply(it, ::Instance)
}
}
}
fun addLines(research: AndroidResearch, lines: MutableList<Component>)
val type: Type<*>
companion object {
private val delegate = RegistryDelegate<Type<*>>("android_research_description") {
disableSaving()
}
val registry by delegate
val registryKey get() = delegate.key
val CODEC: Codec<AndroidResearchDescription> by lazy {
registry.codec.dispatch({ it.type }, { it.codec })
}
internal fun register(bus: IEventBus) {
bus.addListener(delegate::build)
}
fun singleton(callback: (research: AndroidResearch) -> Component): Singleton {
return object : Singleton() {
override fun addLines(research: AndroidResearch, lines: MutableList<Component>) {
lines.add(callback.invoke(research))
}
}
}
}
}
object PlainAndroidResearchDescription : AndroidResearchDescription.Type<PlainAndroidResearchDescription.Instance> {
data class Instance(val line: Component) : AndroidResearchDescription {
override fun addLines(research: AndroidResearch, lines: MutableList<Component>) {
lines.add(line.copy())
}
override val type: PlainAndroidResearchDescription
get() = PlainAndroidResearchDescription
}
fun make(line: Component) = Instance(line)
override val codec: Codec<Instance> by lazy {
Codec
.either(ComponentCodec, simpleCodec(::Instance, Instance::line, ComponentCodec))
.xmap({ c -> c.map({ Instance(it) }, { it }) }, { c -> Either.left(c.line) })
}
}

View File

@ -4,18 +4,15 @@ import com.google.common.collect.ImmutableMap
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonSyntaxException
import net.minecraft.client.server.IntegratedServer import net.minecraft.client.server.IntegratedServer
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceManager import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
import net.minecraft.util.profiling.ProfilerFiller import net.minecraft.util.profiling.ProfilerFiller
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.AddReloadListenerEvent import net.minecraftforge.event.AddReloadListenerEvent
import net.minecraftforge.event.OnDatapackSyncEvent import net.minecraftforge.event.OnDatapackSyncEvent
import net.minecraftforge.eventbus.api.Event
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.PacketDistributor import net.minecraftforge.network.PacketDistributor
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.MINECRAFT_SERVER import ru.dbotthepony.mc.otm.MINECRAFT_SERVER
@ -23,57 +20,17 @@ import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.fromJsonStrict
import ru.dbotthepony.mc.otm.data.SerializedFunctionRegistry import ru.dbotthepony.mc.otm.core.fromNetwork
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.toNetwork
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
import ru.dbotthepony.mc.otm.network.MNetworkContext
import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel
import ru.dbotthepony.mc.otm.network.enqueueWork
import ru.dbotthepony.mc.otm.network.packetHandled
import ru.dbotthepony.mc.otm.onceServer import ru.dbotthepony.mc.otm.onceServer
import java.util.LinkedList import java.util.LinkedList
import java.util.function.Supplier
typealias AndroidResultTransformer = SerializedFunctionRegistry.BoundFunction<Pair<AndroidResearch, AndroidFeature>, Unit>
typealias ComponentSupplier = SerializedFunctionRegistry.BoundFunction<Unit, Component>
object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_android_research"), Iterable<AndroidResearchType> { object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_android_research"), Iterable<AndroidResearchType> {
/**
* Feel free to register functions inside this thing from anywhere in your code
* (registration and querying is completely thread safe).
*
* Just make sure client and server has the same set of functions defined.
*/
val featureResultTransformers = SerializedFunctionRegistry<Pair<AndroidResearch, AndroidFeature>, Unit>()
/**
* Feel free to register functions inside this thing from anywhere in your code
* (registration and querying is completely thread safe).
*
* Just make sure client and server has the same set of functions defined.
*/
val descriptionFuncs = SerializedFunctionRegistry<Unit, Component>()
fun descriptionFunc(name: ResourceLocation, base: String, vararg argument: Supplier<Any>): ComponentSupplier {
return descriptionFuncs.register(name) {->
return@register TranslatableComponent(base, *argument.map { it.get() }.toTypedArray())
}.bind()
}
private var firedRegistrationEvent = false
/**
* Event-style registration of serializable functions, for those who prefer/need it
*
* Fired *once* on [MinecraftForge.EVENT_BUS] before loading android research
*/
object RegisterFuncsEvent : Event() {
val manager get() = AndroidResearchManager
val featureResults by ::featureResultTransformers
val descriptionFunctions by ::descriptionFuncs
fun descriptionFunc(name: ResourceLocation, base: String, vararg argument: Supplier<Any>): ComponentSupplier = AndroidResearchManager.descriptionFunc(name, base, *argument)
}
const val DIRECTORY = "otm_android_research" const val DIRECTORY = "otm_android_research"
private val LOGGER = LogManager.getLogger() private val LOGGER = LogManager.getLogger()
@ -97,23 +54,11 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
var researchMap: Map<ResourceLocation, AndroidResearchType> = mapOf() var researchMap: Map<ResourceLocation, AndroidResearchType> = mapOf()
private set private set
internal fun fireRegistrationEvent() {
if (!firedRegistrationEvent) {
try {
MinecraftForge.EVENT_BUS.post(RegisterFuncsEvent)
} finally {
firedRegistrationEvent = true
}
}
}
override fun apply( override fun apply(
jsonElementMap: Map<ResourceLocation, JsonElement>, jsonElementMap: Map<ResourceLocation, JsonElement>,
manager: ResourceManager, manager: ResourceManager,
profiler: ProfilerFiller profiler: ProfilerFiller
) { ) {
fireRegistrationEvent()
val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>() val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>()
for ((k, v) in jsonElementMap) { for ((k, v) in jsonElementMap) {
@ -122,7 +67,13 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
continue continue
} }
builder.put(k, AndroidResearchType.fromJson(v, k)) v["id"] = k.toString()
try {
builder.put(k, AndroidResearchType.CODEC.fromJsonStrict(v))
} catch(err: RuntimeException) {
throw JsonSyntaxException("Caught an exception while decoding android research $k", err)
}
} }
researchMap = builder.build() researchMap = builder.build()
@ -148,23 +99,23 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
val packet = SyncPacket(researchMap.values) val packet = SyncPacket(researchMap.values)
if (event.player != null) { if (event.player != null) {
RegistryNetworkChannel.send(event.player!!, packet) GenericNetworkChannel.send(event.player!!, packet)
} else { } else {
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), packet) GenericNetworkChannel.send(PacketDistributor.ALL.noArg(), packet)
} }
} }
class SyncPacket(val collection: Collection<AndroidResearchType>) : MatteryPacket { class SyncPacket(val collection: Collection<AndroidResearchType>) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) { override fun write(buff: FriendlyByteBuf) {
buff.writeCollection(collection) { a, b -> b.toNetwork(a) } buff.writeCollection(collection) { a, b -> AndroidResearchType.CODEC.toNetwork(a, b) }
LOGGER.debug("Constructed android research registry packet, ${buff.writerIndex()} bytes in size")
} }
override fun play(context: Supplier<NetworkEvent.Context>) { override fun play(context: MNetworkContext) {
context.packetHandled = true context.packetHandled = true
if (NULLABLE_MINECRAFT_SERVER is IntegratedServer) { if (NULLABLE_MINECRAFT_SERVER is IntegratedServer)
return return
}
val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>() val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>()
@ -185,6 +136,7 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
} }
fun readSyncPacket(buff: FriendlyByteBuf): SyncPacket { fun readSyncPacket(buff: FriendlyByteBuf): SyncPacket {
return SyncPacket(buff.readCollection({ LinkedList() }, AndroidResearchType.Companion::fromNetwork)) LOGGER.info("Received android research registry packet, ${buff.readableBytes()} bytes in size")
return SyncPacket(buff.readCollection({ LinkedList() }, { AndroidResearchType.CODEC.fromNetwork(it) }))
} }
} }

View File

@ -0,0 +1,182 @@
package ru.dbotthepony.mc.otm.android
import com.mojang.datafixers.util.Either
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.resources.ResourceLocation
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.DeferredRegister
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.getValue
import ru.dbotthepony.mc.otm.data.SingletonCodec
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.registry.RegistryDelegate
object AndroidResearchResults {
private val registrar = DeferredRegister.create(AndroidResearchResult.registryKey, OverdriveThatMatters.MOD_ID)
init {
registrar.register("feature") { AndroidResearchResult.Feature.Companion }
registrar.register("feature_level") { AndroidResearchResult.FeatureLevel.Companion }
}
private object NanobotsArmorStrength : AndroidResearchResult.Singleton<NanobotsArmorStrength> {
override val codec: Codec<NanobotsArmorStrength> = SingletonCodec(this)
override val type: AndroidResearchResult.Type<*>
get() = this
override fun onResearched(research: AndroidResearch) {
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
feature.strength++
}
override fun onUnResearched(research: AndroidResearch) {
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
feature.strength--
}
}
private object NanobotsArmorSpeed : AndroidResearchResult.Singleton<NanobotsArmorSpeed> {
override val codec: Codec<NanobotsArmorSpeed> = SingletonCodec(this)
override val type: AndroidResearchResult.Type<*>
get() = this
override fun onResearched(research: AndroidResearch) {
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
feature.speed++
}
override fun onUnResearched(research: AndroidResearch) {
val feature = research.capability.getFeature(AndroidFeatures.NANOBOTS_ARMOR) ?: return
feature.speed--
}
}
val NANOBOTS_ARMOR_STRENGTH: AndroidResearchResult.Singleton<*> by registrar.register("nanobots_armor_strength") { NanobotsArmorStrength }
val NANOBOTS_ARMOR_SPEED: AndroidResearchResult.Singleton<*> by registrar.register("nanobots_armor_speed") { NanobotsArmorSpeed }
internal fun register(bus: IEventBus) {
registrar.register(bus)
}
}
interface AndroidResearchResult {
interface Type<T : AndroidResearchResult> {
val codec: Codec<T>
}
interface Singleton<T : Singleton<T>> : Type<T>, AndroidResearchResult
/**
* Adds specific android feature [id] to target, does nothing if target already has specified feature
*/
class Feature(val id: ResourceLocation, val optional: Boolean = false) : AndroidResearchResult {
val feature = MRegistry.ANDROID_FEATURES.getValue(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
override val type: Type<*>
get() = Companion
override fun onResearched(research: AndroidResearch) {
research.capability.addFeature(feature ?: return)
}
override fun onUnResearched(research: AndroidResearch) {
research.capability.removeFeature(feature ?: return)
}
companion object : Type<Feature> {
override val codec: Codec<Feature> by lazy {
Codec
.either(ResourceLocation.CODEC, RecordCodecBuilder.create<Feature> { // KT-52757
it.group(
ResourceLocation.CODEC.fieldOf("id").forGetter(Feature::id),
Codec.BOOL.optionalFieldOf("optional", false).forGetter(Feature::optional)
).apply(it, ::Feature)
})
.xmap<Feature>(
{ c -> c.map({ Feature(it) }, { it }) },
{ c -> if (c.optional) Either.left(c.id) else Either.right(c) }
)
}
}
}
/**
* Increases level of specific android feature [id] by specified amount [levels]
*/
class FeatureLevel(val id: ResourceLocation, val optional: Boolean = false, val levels: Int = 1) : AndroidResearchResult {
val feature = MRegistry.ANDROID_FEATURES.getValue(id) ?: if (optional) null else throw NoSuchElementException("Unknown android feature $id")
override val type: Type<*>
get() = Companion
override fun onResearched(research: AndroidResearch) {
val get = research.capability.getFeature(feature ?: return)
if (get == null) {
LOGGER.warn("Unable to advance level of android feature $id for ${research.ply} because they have no such android feature.")
} else {
get.level += levels
}
}
override fun onUnResearched(research: AndroidResearch) {
val get = research.capability.getFeature(feature ?: return)
if (get == null) {
LOGGER.warn("Unable to decrease level of android feature $id for ${research.ply} because they have no such android feature.")
} else {
get.level += levels
}
}
companion object : Type<FeatureLevel> {
override val codec: Codec<FeatureLevel> by lazy {
Codec
.either(ResourceLocation.CODEC, RecordCodecBuilder.create<FeatureLevel> { // KT-52757
it.group(
ResourceLocation.CODEC.fieldOf("id").forGetter(FeatureLevel::id),
Codec.BOOL.optionalFieldOf("optional", false).forGetter(FeatureLevel::optional),
Codec.INT.optionalFieldOf("levels", 1).forGetter(FeatureLevel::levels),
).apply(it, ::FeatureLevel)
})
.xmap(
{ c -> c.map({ FeatureLevel(it) }, { it }) },
{ c -> if (c.optional && c.levels == 1) Either.left(c.id) else Either.right(c) }
)
}
}
}
val type: Type<*>
/**
* Called when research is applied
*/
fun onResearched(research: AndroidResearch) {}
/**
* Called when research is refunded
*/
fun onUnResearched(research: AndroidResearch) {}
companion object {
private val LOGGER = LogManager.getLogger()
private val delegate = RegistryDelegate<Type<*>>("android_research_result") {
disableSaving()
}
val registry by delegate
val registryKey get() = delegate.key
val CODEC: Codec<AndroidResearchResult> by lazy {
registry.codec.dispatch({ it.type }, { it.codec })
}
internal fun register(bus: IEventBus) {
bus.addListener(delegate::build)
}
}
}

View File

@ -1,14 +1,13 @@
package ru.dbotthepony.mc.otm.android package ru.dbotthepony.mc.otm.android
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import com.google.common.collect.Streams
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSyntaxException import com.google.gson.JsonSyntaxException
import com.google.gson.internal.bind.TypeAdapters import com.mojang.datafixers.util.Either
import net.minecraft.network.FriendlyByteBuf import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.ListCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.ComponentContents
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
@ -17,30 +16,28 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite
import ru.dbotthepony.mc.otm.client.render.SkinElement import ru.dbotthepony.mc.otm.client.render.sprites.SpriteType
import ru.dbotthepony.mc.otm.client.render.SkinElementType import ru.dbotthepony.mc.otm.core.collect.ListSet
import ru.dbotthepony.mc.otm.core.ListSet
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.isActuallyEmpty import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.data.ComponentCodec
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.data.IngredientCodec
import ru.dbotthepony.mc.otm.core.toImmutableList import ru.dbotthepony.mc.otm.data.JsonElementCodec
import ru.dbotthepony.mc.otm.data.stream
import ru.dbotthepony.mc.otm.isClient import ru.dbotthepony.mc.otm.isClient
import ru.dbotthepony.mc.otm.registry.MRegistry import java.util.Optional
import java.util.LinkedList import java.util.function.Function
import java.util.stream.Stream import java.util.stream.Stream
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashSet import kotlin.collections.HashSet
import kotlin.jvm.optionals.getOrNull
private fun findPrerequisites( private fun findPrerequisites(
initial: Collection<AndroidResearchType>, initial: Collection<AndroidResearchType>,
add: MutableSet<AndroidResearchType> = HashSet(), add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
top: Boolean = true top: Boolean = true
): Set<AndroidResearchType> { ): Set<AndroidResearchType> {
for (value in initial) { for (value in initial) {
@ -56,7 +53,7 @@ private fun findPrerequisites(
private fun findAllPrerequisites( private fun findAllPrerequisites(
initial: Collection<AndroidResearchType>, initial: Collection<AndroidResearchType>,
add: MutableSet<AndroidResearchType> = HashSet(), add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
): Set<AndroidResearchType> { ): Set<AndroidResearchType> {
for (value in initial) { for (value in initial) {
add.add(value) add.add(value)
@ -68,7 +65,7 @@ private fun findAllPrerequisites(
private fun findAllChildren( private fun findAllChildren(
initial: Collection<AndroidResearchType>, initial: Collection<AndroidResearchType>,
add: MutableSet<AndroidResearchType> = HashSet(), add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
): Set<AndroidResearchType> { ): Set<AndroidResearchType> {
for (value in initial) { for (value in initial) {
add.add(value) add.add(value)
@ -84,10 +81,9 @@ class AndroidResearchType(
blockedBy: Collection<Reference>, blockedBy: Collection<Reference>,
items: Collection<Pair<Ingredient, Int>>, items: Collection<Pair<Ingredient, Int>>,
features: Collection<FeatureReference>, results: Collection<AndroidResearchResult>,
descriptionLines: Collection<Component>, description: Collection<AndroidResearchDescription>,
descriptionSuppliers: Collection<ComponentSupplier> = listOf(),
val experienceLevels: Int = 0, val experienceLevels: Int = 0,
private val customName: Component? = null, private val customName: Component? = null,
@ -97,122 +93,56 @@ class AndroidResearchType(
val itemIcon: Item? = null, val itemIcon: Item? = null,
iconText: Component? = null, iconText: Component? = null,
) { ) {
private constructor(
id: ResourceLocation,
prerequisites: Collection<Reference>,
blockedBy: Collection<Reference>,
items: Collection<Pair<Ingredient, Int>>,
results: Collection<AndroidResearchResult>,
description: Collection<AndroidResearchDescription>,
experienceLevels: Int,
customName: Optional<Component>,
// ok
skinIcon: Optional<JsonObject>,
itemIcon: Optional<Item>,
iconText: Optional<Component>,
) : this(id, prerequisites, blockedBy, items, results, description, experienceLevels, customName.getOrNull(), skinIcon.getOrNull(), itemIcon.getOrNull(), iconText.getOrNull())
private val iconTextValue = iconText?.copy() private val iconTextValue = iconText?.copy()
val iconText get() = iconTextValue?.copy() val iconText get() = iconTextValue?.copy()
val resolvedSkinIcon by lazy { val resolvedSkinIcon by lazy {
check(isClient) { "Invalid realm" } check(isClient) { "Invalid realm" }
if (skinIcon != null) if (skinIcon != null)
SkinElementType.fromJson(skinIcon) SpriteType.fromJson(skinIcon)
else else
null null
} }
data class Reference( data class Reference(
val id: ResourceLocation, val id: ResourceLocation,
val isRigid: Boolean val optional: Boolean = false
) { ) {
fun toJson(): JsonObject {
return JsonObject().also {
it["id"] = JsonPrimitive(id.toString())
it["is_rigid"] = JsonPrimitive(isRigid)
}
}
fun toNetwork(buff: FriendlyByteBuf) {
buff.writeUtf(id.toString())
buff.writeBoolean(isRigid)
}
companion object { companion object {
fun fromNetwork(buff: FriendlyByteBuf): Reference { val CODEC: Codec<Reference> by lazy {
return Reference( Codec
ResourceLocation(buff.readUtf()), .either(ResourceLocation.CODEC, RecordCodecBuilder.create<Reference> {
buff.readBoolean() it.group(
ResourceLocation.CODEC.fieldOf("id").forGetter(Reference::id),
Codec.BOOL.optionalFieldOf("optional", false).forGetter(Reference::optional)
).apply(it, ::Reference)
})
.xmap(
{ c -> c.map(::Reference, Function.identity()) },
{ c -> if (c.optional) Either.right(c) else Either.left(c.id) }
) )
} }
fun fromJson(value: JsonElement): Reference {
if (value is JsonPrimitive) {
return Reference(ResourceLocation(value.asString), true)
} else if (value is JsonObject) {
return Reference(
ResourceLocation((value["id"] as? JsonPrimitive ?: throw JsonSyntaxException("Invalid `id` value")).asString),
(value["is_rigid"] as JsonPrimitive?)?.asBoolean ?: true)
} else {
throw JsonSyntaxException("Unknown element type ${value::class.qualifiedName}")
} }
} }
}
}
data class FeatureReference(
val id: ResourceLocation,
val level: Int = 0,
val isRigid: Boolean,
val transformersUp: Collection<AndroidResultTransformer> = listOf(),
val transformersDown: Collection<AndroidResultTransformer> = listOf(),
) {
fun toJson(): JsonObject {
return JsonObject().also {
it["id"] = JsonPrimitive(id.toString())
it["level"] = JsonPrimitive(level)
it["is_rigid"] = JsonPrimitive(isRigid)
it["functions_up"] = JsonArray().also {
for (transformer in transformersUp) {
it.add(transformer.toJson())
}
}
it["functions_down"] = JsonArray().also {
for (transformer in transformersDown) {
it.add(transformer.toJson())
}
}
}
}
fun toNetwork(buff: FriendlyByteBuf) {
buff.writeUtf(id.toString())
buff.writeVarInt(level)
buff.writeBoolean(isRigid)
buff.writeCollection(transformersUp) { a, b -> b.toNetwork(a) }
buff.writeCollection(transformersDown) { a, b -> b.toNetwork(a) }
}
companion object {
fun fromNetwork(buff: FriendlyByteBuf): FeatureReference {
return FeatureReference(
ResourceLocation(buff.readUtf()),
buff.readVarInt(),
buff.readBoolean(),
buff.readCollection({ LinkedList() }, AndroidResearchManager.featureResultTransformers::fromNetwork).filterNotNull().toImmutableList(),
buff.readCollection({ LinkedList() }, AndroidResearchManager.featureResultTransformers::fromNetwork).filterNotNull().toImmutableList()
)
}
fun fromJson(value: JsonElement): FeatureReference {
if (value is JsonPrimitive) {
return FeatureReference(ResourceLocation(value.asString), 0, true)
} else if (value is JsonObject) {
return FeatureReference(
ResourceLocation((value["id"] as? JsonPrimitive ?: throw JsonSyntaxException("Invalid `id` value")).asString),
(value["level"] as JsonPrimitive?)?.asInt ?: 0,
(value["is_rigid"] as JsonPrimitive?)?.asBoolean ?: true,
(value["functions_up"] as JsonArray? ?: JsonArray()).stream().map { AndroidResearchManager.featureResultTransformers.fromJson(it) }.filter { it != null }.collect(ImmutableList.toImmutableList<AndroidResultTransformer>()),
(value["functions_down"] as JsonArray? ?: JsonArray()).stream().map { AndroidResearchManager.featureResultTransformers.fromJson(it) }.filter { it != null }.collect(ImmutableList.toImmutableList<AndroidResultTransformer>()),
)
} else {
throw JsonSyntaxException("Unknown element type ${value::class.qualifiedName}")
}
}
}
}
data class ResolvedFeature(
val feature: AndroidFeatureType<*>,
val level: Int,
)
val researchTreeDepth: Int by lazy { val researchTreeDepth: Int by lazy {
if (flatPrerequisites.isEmpty()) { if (flatPrerequisites.isEmpty()) {
@ -242,38 +172,18 @@ class AndroidResearchType(
val blockedBy: List<Reference> = ImmutableList.copyOf(blockedBy) val blockedBy: List<Reference> = ImmutableList.copyOf(blockedBy)
val resolvedPrerequisites: List<AndroidResearchType> by lazy { val resolvedPrerequisites: List<AndroidResearchType> by lazy {
ImmutableList.copyOf(this.prerequisites.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.isRigid) throw NoSuchElementException("Unable to find research ${it.id}") } }) ImmutableList.copyOf(this.prerequisites.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.optional) throw NoSuchElementException("Unable to find research ${it.id}") } })
} }
val resolvedBlockedBy: List<AndroidResearchType> by lazy { val resolvedBlockedBy: List<AndroidResearchType> by lazy {
ImmutableList.copyOf(this.blockedBy.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.isRigid) throw NoSuchElementException("Unable to find research ${it.id}") } }) ImmutableList.copyOf(this.blockedBy.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.optional) throw NoSuchElementException("Unable to find research ${it.id}") } })
}
val features: List<FeatureReference> = ImmutableList.copyOf(features)
val resolvedFeatures: List<ResolvedFeature> by lazy {
ImmutableList.copyOf(features.mapNotNull {
MRegistry.ANDROID_FEATURES.getValue(it.id)
.let { e -> if (e == null && it.isRigid)
throw NoSuchElementException("Unable to find research ${it.id}")
else if (e != null)
ResolvedFeature(e, it.level)
else
null } })
} }
private val definedItems: List<Pair<Ingredient, Int>> = ImmutableList.copyOf(items) private val definedItems: List<Pair<Ingredient, Int>> = ImmutableList.copyOf(items)
val results: ImmutableList<AndroidResearchResult> = ImmutableList.copyOf(results)
val items: Stream<out Pair<Ingredient, Int>> get() = definedItems.stream().filter { !it.first.isActuallyEmpty } val items: Stream<out Pair<Ingredient, Int>> get() = definedItems.stream().filter { !it.first.isActuallyEmpty }
val description: ImmutableList<AndroidResearchDescription> = ImmutableList.copyOf(description)
private val descriptionLines: List<MutableComponent> = ImmutableList.copyOf(descriptionLines.map { it.copy() })
private val descriptionSuppliers: List<ComponentSupplier> = ImmutableList.copyOf(descriptionSuppliers)
/**
* Stream containing copies of original [Component]s in list
*/
val description: Stream<out Component> get() = Streams.concat(descriptionLines.stream().map { it.copy() }, descriptionSuppliers.stream().map { it.apply(Unit) })
/** /**
* Flat list of research preceding this research. * Flat list of research preceding this research.
@ -468,152 +378,35 @@ class AndroidResearchType(
return customName?.copy() ?: MutableComponent.create(displayContents) return customName?.copy() ?: MutableComponent.create(displayContents)
} }
fun toJson(): JsonElement {
return JsonObject().also {
// it["id"] = JsonPrimitive(id.toString())
it["prerequisites"] = JsonArray().also { for (value in prerequisites) it.add(value.toJson()) }
it["blocked_by"] = JsonArray().also { for (value in blockedBy) it.add(value.toJson()) }
it["required_items"] = JsonArray().also { for (item in definedItems) it.add(JsonObject().also { it["count"] = JsonPrimitive(item.second); it["ingredient"] = item.first.toJson() }) }
it["feature_result"] = JsonArray().also { for (feature in features) it.add(feature.toJson()) }
it["description"] = JsonArray().also { for (line in descriptionLines) it.add(Component.Serializer.toJsonTree(line)) }
it["description_funcs"] = JsonArray().also { for (line in descriptionSuppliers) it.add(line.toJson()) }
it["experience"] = JsonPrimitive(experienceLevels)
if (skinIcon != null) {
it["skin_icon"] = skinIcon
}
if (itemIcon != null) {
it["item_icon"] = JsonPrimitive(itemIcon.registryName!!.toString())
}
if (iconTextValue != null) {
it["icon_text"] = Component.Serializer.toJsonTree(iconTextValue)
}
if (customName != null) {
it["custom_name"] = Component.Serializer.toJsonTree(customName)
}
}
}
fun validate() { fun validate() {
resolvedFeatures
resolvedBlockedBy resolvedBlockedBy
resolvedPrerequisites resolvedPrerequisites
} }
fun toNetwork(buff: FriendlyByteBuf) {
buff.writeUtf(id.toString())
buff.writeCollection(prerequisites) { a, b -> b.toNetwork(a) }
buff.writeCollection(blockedBy) { a, b -> b.toNetwork(a) }
buff.writeCollection(definedItems) { a, b -> b.first.toNetwork(a); a.writeVarInt(b.second) }
buff.writeCollection(features) { a, b -> b.toNetwork(a) }
buff.writeCollection(descriptionLines) { a, b -> a.writeComponent(b) }
buff.writeCollection(descriptionSuppliers) { a, b -> b.toNetwork(a) }
buff.writeVarInt(experienceLevels)
buff.writeBoolean(customName != null)
if (customName != null) buff.writeComponent(customName)
buff.writeBoolean(iconTextValue != null)
if (iconTextValue != null) buff.writeComponent(iconTextValue)
buff.writeBoolean(skinIcon != null)
if (skinIcon != null) buff.writeUtf(skinIcon.toString())
buff.writeBoolean(itemIcon != null)
if (itemIcon != null) buff.writeUtf(itemIcon.registryName!!.toString())
}
companion object { companion object {
fun fromNetwork(buff: FriendlyByteBuf): AndroidResearchType { val CODEC: Codec<AndroidResearchType> by lazy {
val id = ResourceLocation(buff.readUtf()) RecordCodecBuilder.create {
val prerequisites = buff.readCollection({ LinkedList() }, Reference::fromNetwork) it.group(
val blockedBy = buff.readCollection({ LinkedList() }, Reference::fromNetwork) ResourceLocation.CODEC.fieldOf("id").forGetter(AndroidResearchType::id),
val items = buff.readCollection({ LinkedList() }, { Ingredient.fromNetwork(it) to it.readVarInt() }) ListCodec(Reference.CODEC).fieldOf("prerequisites").forGetter(AndroidResearchType::prerequisites),
val features = buff.readCollection({ LinkedList() }, FeatureReference::fromNetwork) ListCodec(Reference.CODEC).fieldOf("blockedBy").forGetter(AndroidResearchType::blockedBy),
val descriptionLines = buff.readCollection({ LinkedList() }, FriendlyByteBuf::readComponent) ListCodec(
val descriptionSuppliers = buff.readCollection({ LinkedList() }, { AndroidResearchManager.descriptionFuncs.fromNetwork(it) }) RecordCodecBuilder.create<Pair<Ingredient, Int>> {
val experienceLevels = buff.readVarInt() it.group(
IngredientCodec.fieldOf("item").forGetter { it.first },
val customName = if (buff.readBoolean()) { Codec.intRange(1, Int.MAX_VALUE).optionalFieldOf("count", 1).forGetter { it.second }
buff.readComponent() ).apply(it, ::Pair)
} else {
null
} }
).fieldOf("items").forGetter { it.definedItems },
val iconTextValue = if (buff.readBoolean()) { ListCodec(AndroidResearchResult.CODEC).fieldOf("results").forGetter(AndroidResearchType::results),
buff.readComponent() ListCodec(AndroidResearchDescription.CODEC).fieldOf("description").forGetter(AndroidResearchType::description),
} else { Codec.intRange(0, Int.MAX_VALUE).fieldOf("experienceLevels").forGetter(AndroidResearchType::experienceLevels),
null ComponentCodec.optionalFieldOf("customName").forGetter { Optional.ofNullable(it.customName) },
JsonElementCodec.xmap({ it as? JsonObject ?: throw JsonSyntaxException("Not a json object: $it") }, { it }).optionalFieldOf("skinIcon").forGetter { Optional.ofNullable(it.skinIcon) },
ForgeRegistries.ITEMS.codec.optionalFieldOf("itemIcon").forGetter { Optional.ofNullable(it.itemIcon) },
ComponentCodec.optionalFieldOf("iconTextValue").forGetter { Optional.ofNullable(it.iconTextValue) },
).apply(it, ::AndroidResearchType)
} }
val skinIcon = if (buff.readBoolean()) {
TypeAdapters.JSON_ELEMENT.fromJson(buff.readUtf()) as JsonObject
} else {
null
}
val itemIcon = if (buff.readBoolean()) {
ForgeRegistries.ITEMS.getValue(ResourceLocation(buff.readUtf()))?.let { if (it == Items.AIR) null else it }
} else {
null
}
return AndroidResearchType(
id = id,
prerequisites = prerequisites,
blockedBy = blockedBy,
items = items,
features = features,
descriptionLines = descriptionLines,
descriptionSuppliers = descriptionSuppliers.filterNotNull(),
experienceLevels = experienceLevels,
customName = customName,
iconText = iconTextValue,
skinIcon = skinIcon,
itemIcon = itemIcon,
)
}
fun fromJson(value: JsonElement, id: ResourceLocation): AndroidResearchType {
if (value !is JsonObject) {
throw JsonSyntaxException("Android research type must be of Json Object")
}
val prerequisites = value["prerequisites"] as JsonArray? ?: JsonArray()
val blocked_by = value["blocked_by"] as JsonArray? ?: JsonArray()
val items = value["required_items"] as JsonArray? ?: JsonArray()
val features = value["feature_result"] as JsonArray? ?: JsonArray()
val description = value["description"] as JsonArray? ?: JsonArray()
val description_funcs = value["description_funcs"] as JsonArray? ?: JsonArray()
val experience = value["experience"]?.asInt ?: 0
val customName = value["custom_name"]?.let(Component.Serializer::fromJson)
val iconText = value["icon_text"]?.let(Component.Serializer::fromJson)
val skinIcon = value["skin_icon"] as JsonObject?
val itemIcon = value["item_icon"]?.let { ForgeRegistries.ITEMS.getValue(ResourceLocation(it.asString)).let { if (it == Items.AIR) null else it } }
return AndroidResearchType(
id = id,
prerequisites = prerequisites.stream().map { Reference.fromJson(it) }.toList(),
blockedBy = blocked_by.stream().map { Reference.fromJson(it) }.toList(),
features = features.stream().map { FeatureReference.fromJson(it) }.toList(),
items = items.stream()
.map { it as? JsonObject ?: throw JsonSyntaxException("One of items is not an JsonObject") }
.map { Ingredient.fromJson(it["ingredient"] ?: throw JsonSyntaxException("Missing ingredient key")) to (it["count"]?.asInt ?: throw JsonSyntaxException("Missing count key")) }
.toList(),
descriptionLines = description.stream().map { Component.Serializer.fromJson(it) }.toList() as List<MutableComponent>,
descriptionSuppliers = description_funcs.stream()
.map { AndroidResearchManager.descriptionFuncs.fromJson(it) ?: throw NullPointerException("$id is missing description supplier function or it is invalid! JSON: $it") }
.toList() as List<ComponentSupplier>,
experienceLevels = experience,
customName = customName,
iconText = iconText,
skinIcon = skinIcon,
itemIcon = itemIcon,
)
} }
} }
@ -622,24 +415,24 @@ class AndroidResearchType(
val id: ResourceLocation, val id: ResourceLocation,
var experience: Int = 0, var experience: Int = 0,
var customName: Component? = null, var customName: Component? = null,
var description: MutableList<Component>? = null, description: MutableList<AndroidResearchDescription>? = null,
var descriptionSuppliers: MutableList<ComponentSupplier>? = null,
var itemIcon: Item? = null, var itemIcon: Item? = null,
var skinIcon: AbstractSkinElement? = null, var skinIcon: AbstractMatterySprite? = null,
var iconText: Component? = null, var iconText: Component? = null,
) { ) {
val description = ArrayList<AndroidResearchDescription>(description ?: listOf())
val results = ArrayList<AndroidResearchResult>()
private val items = ArrayList<Pair<Ingredient, Int>>() private val items = ArrayList<Pair<Ingredient, Int>>()
private val prerequisites = ArrayList<Reference>() private val prerequisites = ArrayList<Reference>()
private val blockers = ArrayList<Reference>() private val blockers = ArrayList<Reference>()
private val features = ArrayList<FeatureReference>()
fun withIconText(icon: Component? = null): Builder { fun withIconText(icon: Component? = null): Builder {
this.iconText = icon this.iconText = icon
return this return this
} }
fun withIcon(icon: AbstractSkinElement? = null): Builder { fun withIcon(icon: AbstractMatterySprite? = null): Builder {
this.skinIcon = icon this.skinIcon = icon
this.itemIcon = null this.itemIcon = null
return this return this
@ -662,19 +455,20 @@ class AndroidResearchType(
return this return this
} }
fun withDescription(): Builder { fun clearDescription(): Builder {
this.description = mutableListOf(TranslatableComponent("android_research.${id.namespace}.${id.path}.description")) this.description.clear()
return this return this
} }
fun withDescription(range: IntRange): Builder { fun withDescription(): Builder {
val result = ArrayList<Component>() return withDescription(TranslatableComponent("android_research.${id.namespace}.${id.path}.description"))
}
for (i in range) {
result.add(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i")) fun withDescription(range: IntRange): Builder {
for (i in range) {
withDescription(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i"))
} }
this.description = result
return this return this
} }
@ -684,73 +478,21 @@ class AndroidResearchType(
} }
fun withDescription(vararg description: Component): Builder { fun withDescription(vararg description: Component): Builder {
this.description = description.toMutableList() for (component in description)
withDescription(PlainAndroidResearchDescription.Instance(component))
return this return this
} }
fun withDescription(description: Collection<Component>): Builder { fun withDescription(description: Collection<Component>): Builder {
this.description = ArrayList<Component>(description.size).also { it.addAll(description) } for (component in description)
withDescription(PlainAndroidResearchDescription.Instance(component))
return this return this
} }
fun appendDescription(range: IntRange): Builder { fun withDescription(vararg description: AndroidResearchDescription): Builder {
val result = this.description ?: ArrayList() this.description.addAll(description)
for (i in range) {
result.add(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i"))
}
this.description = result
return this
}
fun appendDescription(description: Component): Builder {
this.description = (this.description ?: mutableListOf()).also { it.add(description) }
return this
}
fun appendDescription(vararg description: Component): Builder {
this.description = (this.description ?: mutableListOf()).also { it.addAll(description) }
return this
}
fun appendDescription(description: Collection<Component>): Builder {
this.description = (this.description ?: mutableListOf()).also { it.addAll(description) }
return this
}
fun withDescription(vararg description: ComponentSupplier): Builder {
this.descriptionSuppliers = description.toMutableList()
return this
}
fun withDescriptionSupplier(description: Collection<ComponentSupplier>): Builder {
this.descriptionSuppliers = ArrayList<ComponentSupplier>(description.size).also { it.addAll(description) }
return this
}
fun appendDescription(description: ComponentSupplier): Builder {
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.add(description) }
return this
}
fun appendDescriptionSupplier(description: ComponentSupplier): Builder {
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.add(description) }
return this
}
fun appendDescription(vararg description: ComponentSupplier): Builder {
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.addAll(description) }
return this
}
fun appendDescriptionSupplier(vararg description: ComponentSupplier): Builder {
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.addAll(description) }
return this
}
fun appendDescriptionSupplier(description: Collection<ComponentSupplier>): Builder {
this.descriptionSuppliers = (this.descriptionSuppliers ?: mutableListOf()).also { it.addAll(description) }
return this return this
} }
@ -759,14 +501,14 @@ class AndroidResearchType(
* research tree render logic (yet). * research tree render logic (yet).
*/ */
@JvmOverloads @JvmOverloads
fun addPrerequisite(id: ResourceLocation, rigid: Boolean = false): Builder { fun addPrerequisite(id: ResourceLocation, optional: Boolean = true): Builder {
prerequisites.add(Reference(id, rigid)) prerequisites.add(Reference(id, optional))
return this return this
} }
@JvmOverloads @JvmOverloads
fun addBlocker(id: ResourceLocation, rigid: Boolean = false): Builder { fun addBlocker(id: ResourceLocation, optional: Boolean = true): Builder {
blockers.add(Reference(id, rigid)) blockers.add(Reference(id, optional))
return this return this
} }
@ -774,46 +516,28 @@ class AndroidResearchType(
* Please avoid having multiple prerequisites as case with more than 1 prerequisite does not have proper * Please avoid having multiple prerequisites as case with more than 1 prerequisite does not have proper
* research tree render logic (yet). * research tree render logic (yet).
*/ */
fun addPrerequisite(type: AndroidResearchType, rigid: Boolean = true) = addPrerequisite(type.id, rigid) fun addPrerequisite(type: AndroidResearchType, optional: Boolean = false) = addPrerequisite(type.id, optional)
fun addBlocker(type: AndroidResearchType, rigid: Boolean = true) = addBlocker(type.id, rigid) fun addBlocker(type: AndroidResearchType, optional: Boolean = false) = addBlocker(type.id, optional)
@JvmOverloads fun addResult(result: AndroidResearchResult): Builder {
fun addFeatureResult( results.add(result)
id: ResourceLocation,
level: Int = 0,
rigid: Boolean = false,
transformersUp: Collection<AndroidResultTransformer> = listOf(),
transformersDown: Collection<AndroidResultTransformer> = listOf(),
): Builder {
features.add(FeatureReference(id, level, rigid, transformersUp, transformersDown))
return this return this
} }
@JvmOverloads fun addFeatureResult(id: ResourceLocation, optional: Boolean = false): Builder {
fun addFeatureResult( return addResult(AndroidResearchResult.Feature(id, optional))
feature: AndroidFeatureType<*>,
level: Int = 0,
rigid: Boolean = true,
transformersUp: Collection<AndroidResultTransformer> = listOf(),
transformersDown: Collection<AndroidResultTransformer> = listOf(),
): Builder {
features.add(FeatureReference(feature.registryName ?: throw NullPointerException("Feature $feature does not have registry name"), level, rigid, transformersUp, transformersDown))
return this
} }
fun addFeatureResult( fun addFeatureResult(feature: AndroidFeatureType<*>, optional: Boolean = false): Builder {
id: ResourceLocation, return addFeatureResult(feature.registryName!!, optional)
rigid: Boolean = false,
transformersUp: Collection<AndroidResultTransformer> = listOf(),
transformersDown: Collection<AndroidResultTransformer> = listOf(),
): Builder {
features.add(FeatureReference(id, 0, rigid, transformersUp, transformersDown))
return this
} }
fun addFeatureResult(ref: FeatureReference): Builder { fun addFeatureLevel(id: ResourceLocation, optional: Boolean = false, levels: Int = 1): Builder {
features.add(ref) return addResult(AndroidResearchResult.FeatureLevel(id, optional, levels))
return this }
fun addFeatureLevel(feature: AndroidFeatureType<*>, optional: Boolean = false, levels: Int = 1): Builder {
return addFeatureLevel(feature.registryName!!, optional, levels)
} }
fun addItem(cost: ItemStack): Builder { fun addItem(cost: ItemStack): Builder {
@ -845,9 +569,8 @@ class AndroidResearchType(
prerequisites = prerequisites, prerequisites = prerequisites,
blockedBy = blockers, blockedBy = blockers,
items = items, items = items,
features = features, results = results,
descriptionLines = description ?: listOf(), description = description,
descriptionSuppliers = descriptionSuppliers ?: listOf(),
experienceLevels = experience, experienceLevels = experience,
customName = customName, customName = customName,
skinIcon = skinIcon?.toJson(), skinIcon = skinIcon?.toJson(),

View File

@ -1,13 +1,16 @@
package ru.dbotthepony.mc.otm.android package ru.dbotthepony.mc.otm.android
import com.mojang.blaze3d.vertex.PoseStack import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.nbt.set
abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: MatteryPlayerCapability) : AndroidFeature(type, android) { abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: MatteryPlayerCapability) : AndroidFeature(type, android) {
var isActive by synchronizer.bool(setter = setter@{ value, access, setByRemote -> var isActive by synchronizer.bool(setter = setter@{ value, access, setByRemote ->
if (value != access.read()) { if (value != access.readBoolean()) {
access.write(value) access.write(value)
if (!setByRemote) { if (!setByRemote) {
@ -18,18 +21,23 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma
} }
} }
} }
}) }).property
open val allowToSwitchByPlayer: Boolean get() = true open val allowToSwitchByPlayer: Boolean get() = true
open val allowToSwitchByPlayerWhileSpectator: Boolean get() = true open val allowToSwitchByPlayerWhileSpectator: Boolean get() = true
open val maxCooldown: Int get() = 0 open val maxCooldown: Int get() = 0
open var cooldown by synchronizer.int() open var cooldown by synchronizer.int().property
val isOnCooldown: Boolean val isOnCooldown: Boolean
get() = maxCooldown > 0 && cooldown > 0 get() = maxCooldown > 0 && cooldown > 0
val cooldownPercent: Float get() { val cooldownPercent: Float get() {
if (maxCooldown <= 0) return 0.0f if (maxCooldown <= 0) return 0.0f
if (ply.level is ClientLevel) {
return ((cooldown.toFloat() - minecraft.partialTick) / maxCooldown.toFloat()).coerceIn(0.0f, 1.0f)
}
return (cooldown.toFloat() / maxCooldown.toFloat()).coerceIn(0.0f, 1.0f) return (cooldown.toFloat() / maxCooldown.toFloat()).coerceIn(0.0f, 1.0f)
} }
@ -37,9 +45,9 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma
cooldown = maxCooldown cooldown = maxCooldown
} }
// TODO: PoseStack is stripped from server dist // TODO: GuiGraphics is stripped from server dist
// but it doesn't seem to cause issues? // but it doesn't seem to cause issues?
abstract fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) abstract fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor = RGBAColor.WHITE)
override fun serializeNBT(): CompoundTag { override fun serializeNBT(): CompoundTag {
return super.serializeNBT().also { return super.serializeNBT().also {

View File

@ -13,7 +13,7 @@ class AttackBoostFeature(android: MatteryPlayerCapability) : AndroidFeature(Andr
if (modifier != null) { if (modifier != null) {
modifier.removePermanentModifier(MODIFIER_ID) modifier.removePermanentModifier(MODIFIER_ID)
modifier.addPermanentModifier(AttributeModifier(MODIFIER_ID, type.displayName.toString(), (level + 1) * 0.06, AttributeModifier.Operation.MULTIPLY_TOTAL)) modifier.addPermanentModifier(AttributeModifier(MODIFIER_ID, type.displayName.toString(), (level + 1) * 0.15, AttributeModifier.Operation.MULTIPLY_TOTAL))
} }
} }

View File

@ -2,8 +2,6 @@ package ru.dbotthepony.mc.otm.android.feature
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Vector3f
import net.minecraft.ChatFormatting
import net.minecraft.client.Camera import net.minecraft.client.Camera
import net.minecraft.client.renderer.LevelRenderer import net.minecraft.client.renderer.LevelRenderer
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
@ -27,29 +25,31 @@ import net.minecraftforge.event.ForgeEventFactory
import net.minecraftforge.event.entity.living.LivingDeathEvent import net.minecraftforge.event.entity.living.LivingDeathEvent
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.client.render.element
import ru.dbotthepony.mc.otm.client.render.linesIgnoreZRenderType import ru.dbotthepony.mc.otm.client.render.linesIgnoreZRenderType
import ru.dbotthepony.mc.otm.core.Vector import ru.dbotthepony.mc.otm.client.render.sprites.sprite
import ru.dbotthepony.mc.otm.core.asVector import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.component1
import ru.dbotthepony.mc.otm.core.component2
import ru.dbotthepony.mc.otm.core.component3
import ru.dbotthepony.mc.otm.core.formatPower
import ru.dbotthepony.mc.otm.core.genericPositions import ru.dbotthepony.mc.otm.core.genericPositions
import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.core.holder
import ru.dbotthepony.mc.otm.core.shortestDistanceBetween import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.times import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.asVector
import ru.dbotthepony.mc.otm.core.math.component1
import ru.dbotthepony.mc.otm.core.math.component2
import ru.dbotthepony.mc.otm.core.math.component3
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.math.rotateXDegrees
import ru.dbotthepony.mc.otm.core.math.rotateYDegrees
import ru.dbotthepony.mc.otm.core.math.shortestDistanceBetween
import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.milliTime import ru.dbotthepony.mc.otm.milliTime
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
import java.util.* import java.util.*
import kotlin.math.sin import kotlin.math.sin
@ -59,10 +59,10 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
private set private set
override val maxCooldown: Int override val maxCooldown: Int
get() = ServerConfig.EnderTeleporter.COOLDOWN get() = AndroidConfig.EnderTeleporter.COOLDOWN
private fun canUse(): Boolean { private fun canUse(): Boolean {
return !isOnCooldown && android.androidEnergy.extractEnergyInnerExact(ServerConfig.EnderTeleporter.ENERGY_COST, true).isPositive return !isOnCooldown && android.androidEnergy.extractEnergyExact(AndroidConfig.EnderTeleporter.ENERGY_COST, true)
} }
private fun isValidGround(blockPos: BlockPos): Boolean { private fun isValidGround(blockPos: BlockPos): Boolean {
@ -111,14 +111,14 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
} }
private fun tryToPhaseThroughWall(blockPos: BlockPos, normal: Vec3i): TraceResult? { private fun tryToPhaseThroughWall(blockPos: BlockPos, normal: Vec3i): TraceResult? {
val phasedBlocks = ArrayList<BlockPos>(ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) val phasedBlocks = ArrayList<BlockPos>(AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE)
phasedBlocks.add(blockPos) phasedBlocks.add(blockPos)
for (extend in 1 .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) { for (extend in 1 .. AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
val pos = blockPos + normal * extend val pos = blockPos + normal * extend
if (isAirGap(pos)) { if (isAirGap(pos)) {
for (y in 0 .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE - extend) { for (y in 0 .. AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE - extend) {
val newPos = BlockPos(pos.x, pos.y - y, pos.z) val newPos = BlockPos(pos.x, pos.y - y, pos.z)
if (isValidPosition(newPos)) { if (isValidPosition(newPos)) {
@ -141,7 +141,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
val result = ply.level.clip(ClipContext( val result = ply.level.clip(ClipContext(
headPosition, headPosition,
headPosition + aimVector * (ServerConfig.EnderTeleporter.MAX_DISTANCE * 2.0), headPosition + aimVector * (AndroidConfig.EnderTeleporter.MAX_DISTANCE * 2.0),
ClipContext.Block.COLLIDER, ClipContext.Block.COLLIDER,
ClipContext.Fluid.NONE, ClipContext.Fluid.NONE,
ply ply
@ -157,7 +157,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
!ply.isShiftKeyDown && !ply.isShiftKeyDown &&
result.direction == Direction.UP && result.direction == Direction.UP &&
isValidPosition(result.blockPos.above()) && isValidPosition(result.blockPos.above()) &&
shortestDistanceBetween(testPositions, result.blockPos.above().asVector()) <= ServerConfig.EnderTeleporter.MAX_DISTANCE shortestDistanceBetween(testPositions, result.blockPos.above().asVector()) <= AndroidConfig.EnderTeleporter.MAX_DISTANCE
) { ) {
return TraceResult(result.blockPos.above()) return TraceResult(result.blockPos.above())
} }
@ -215,14 +215,14 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
if (!isAirGap(pos)) { if (!isAirGap(pos)) {
phasedBlocks++ phasedBlocks++
if (phasedBlocks >= ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) { if (phasedBlocks >= AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
break break
} }
phasedBlocksList.add(pos) phasedBlocksList.add(pos)
} }
if (shortestDistanceBetween(testPositions, pos.asVector()) > ServerConfig.EnderTeleporter.MAX_DISTANCE) { if (shortestDistanceBetween(testPositions, pos.asVector()) > AndroidConfig.EnderTeleporter.MAX_DISTANCE) {
break break
} }
@ -269,14 +269,14 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
if (!isAirGap(pos)) { if (!isAirGap(pos)) {
phasedBlocks++ phasedBlocks++
if (phasedBlocks >= ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) { if (phasedBlocks >= AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
break break
} }
phasedBlocksList.add(pos) phasedBlocksList.add(pos)
} }
if (shortestDistanceBetween(testPositions, pos.asVector()) > ServerConfig.EnderTeleporter.MAX_DISTANCE) { if (shortestDistanceBetween(testPositions, pos.asVector()) > AndroidConfig.EnderTeleporter.MAX_DISTANCE) {
break break
} }
@ -301,13 +301,13 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
val event = ForgeEventFactory.onEnderTeleport(ply, blockPos.x + 0.5, blockPos.y.toDouble(), blockPos.z + 0.5) val event = ForgeEventFactory.onEnderTeleport(ply, blockPos.x + 0.5, blockPos.y.toDouble(), blockPos.z + 0.5)
if (event.isCanceled) { if (event.isCanceled) {
(ply as ServerPlayer).connection.send(ClientboundSoundEntityPacket(SoundEvents.ITEM_BREAK, SoundSource.PLAYERS, ply, 0.3f, 0.5f, ply.level.random.nextLong())) (ply as ServerPlayer).connection.send(ClientboundSoundEntityPacket(SoundEvents.ITEM_BREAK.holder, SoundSource.PLAYERS, ply, 0.3f, 0.5f, ply.level.random.nextLong()))
return false return false
} }
putOnCooldown() putOnCooldown()
lastTeleport = ply.server!!.tickCount lastTeleport = ply.server!!.tickCount
android.androidEnergy.extractEnergyInner(ServerConfig.EnderTeleporter.ENERGY_COST, false) android.androidEnergy.extractEnergy(AndroidConfig.EnderTeleporter.ENERGY_COST, false)
ply.level.playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.3f, 0.8f + ply.level.random.nextFloat() * 0.4f) ply.level.playSound(null, ply, SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 0.3f, 0.8f + ply.level.random.nextFloat() * 0.4f)
ply.teleportTo(event.targetX, event.targetY, event.targetZ) ply.teleportTo(event.targetX, event.targetY, event.targetZ)
@ -333,8 +333,8 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
poseStack.pushPose() poseStack.pushPose()
poseStack.translate(x - vx, y - vy, z - vz) poseStack.translate(x - vx, y - vy, z - vz)
poseStack.mulPose(Vector3f.YP.rotationDegrees(-camera.yRot)) poseStack.rotateYDegrees(-camera.yRot)
poseStack.mulPose(Vector3f.XP.rotationDegrees(camera.xRot)) poseStack.rotateXDegrees(camera.xRot)
val size = 1f + sin(milliTime / 250.0).toFloat() * 0.2f val size = 1f + sin(milliTime / 250.0).toFloat() * 0.2f
val half = size / -2f val half = size / -2f
@ -372,12 +372,12 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
} }
} }
override fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) { override fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor) {
if (cooldown > 0) { if (cooldown > 0) {
RenderSystem.setShaderColor(1f, 0.4f, 0.4f, 1f) RenderSystem.setShaderColor(1f, 0.4f, 0.4f, 1f)
} }
ResearchIcons.ICON_ENDER_TELEPORT.render(stack, x, y, width, height) ResearchIcons.ICON_ENDER_TELEPORT.render(graphics, x, y, width, height, color = color)
if (cooldown > 0) { if (cooldown > 0) {
RenderSystem.setShaderColor(1f, 1f, 1f, 1f) RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
@ -392,20 +392,14 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
private val SHAPE_CHECK_NOT_FENCE = Block.box(6.0, 17.0, 6.0, 10.0, 31.0, 10.0) private val SHAPE_CHECK_NOT_FENCE = Block.box(6.0, 17.0, 6.0, 10.0, 31.0, 10.0)
private val SHAPE_CHECK_SUPPORT_PLAYER = Block.box(6.0, 0.0, 6.0, 10.0, 16.0, 10.0) private val SHAPE_CHECK_SUPPORT_PLAYER = Block.box(6.0, 0.0, 6.0, 10.0, 16.0, 10.0)
val SPRITE = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/item/black_hole.png").element(0f, 0f, 16f, 16f, 16f, 16f) val SPRITE = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/item/black_hole.png").sprite(0f, 0f, 16f, 16f, 16f, 16f)
val POWER_COST_DESCRIPTION =
AndroidResearchManager.descriptionFunc(
ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.ENDER_TELEPORTER),
"otm.gui.power_cost_per_use",
{ ServerConfig.EnderTeleporter.ENERGY_COST.formatPower().copy().withStyle(ChatFormatting.YELLOW) })
fun onEntityDeath(event: LivingDeathEvent) { fun onEntityDeath(event: LivingDeathEvent) {
val android = event.entity.matteryPlayer ?: return val android = event.entity.matteryPlayer ?: return
val server = NULLABLE_MINECRAFT_SERVER ?: return val server = NULLABLE_MINECRAFT_SERVER ?: return
if (android.isAndroid && event.source.isFall) { if (android.isAndroid && event.source.isFall) {
val feature = android.getFeature(AndroidFeatures.ENDER_TELEPORTER) as EnderTeleporterFeature? ?: return val feature = android.getFeature(AndroidFeatures.ENDER_TELEPORTER) ?: return
if (server.tickCount - feature.lastTeleport <= 120) { if (server.tickCount - feature.lastTeleport <= 120) {
EnderTeleporterFallDeathTrigger.trigger(event.entity as ServerPlayer) EnderTeleporterFallDeathTrigger.trigger(event.entity as ServerPlayer)

View File

@ -1,32 +1,25 @@
package ru.dbotthepony.mc.otm.android.feature package ru.dbotthepony.mc.otm.android.feature
import net.minecraft.ChatFormatting
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraftforge.event.entity.living.LivingAttackEvent
import net.minecraftforge.event.entity.living.LivingHurtEvent import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.android.AndroidFeature import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.FALL_DAMPENERS, capability) { class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.FALL_DAMPENERS, capability) {
override fun onHurt(event: LivingHurtEvent) { override fun onHurt(event: LivingHurtEvent) {
if (event.source.isFall) { if (event.source.isFall) {
val reduction = (ServerConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL * (level + 1)).toFloat() val reduction = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * (level + 1)).toFloat().coerceIn(0f, 1f)
val flat = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * (level + 1)).toFloat().coerceIn(0f, Float.MAX_VALUE)
val old = event.amount val old = event.amount
event.amount = ((event.amount - flat) * (1f - reduction)).coerceAtLeast(0f)
if (reduction >= 1f) { if (event.amount == 0f) {
event.isCanceled = true event.isCanceled = true
event.amount = 0f
} else {
event.amount *= (1f - reduction)
} }
if (ply is ServerPlayer && ply.health > event.amount && ply.health <= old) { if (ply is ServerPlayer && ply.health > event.amount && ply.health <= old) {
@ -35,9 +28,14 @@ class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature
} }
} }
companion object { override fun onAttack(event: LivingAttackEvent) {
val DESCRIPTION = AndroidResearchManager.descriptionFuncs.register(ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.FALL_DAMPENERS)) { level: Int -> if (event.source.isFall) {
TranslatableComponent("otm.fall_dampeners.description", TextComponent("%.1f".format((ServerConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL * level).toFloat().coerceAtLeast(0f).coerceAtMost(1f) * 100f)).withStyle(ChatFormatting.YELLOW)) val reduction = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_P * (level + 1)).toFloat().coerceIn(0f, 1f)
val flat = (AndroidConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL_F * (level + 1)).toFloat().coerceIn(0f, Float.MAX_VALUE)
if (reduction >= 1f || event.amount <= flat) {
event.isCanceled = true
}
} }
} }
} }

View File

@ -1,43 +1,30 @@
package ru.dbotthepony.mc.otm.android.feature package ru.dbotthepony.mc.otm.android.feature
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.ChatFormatting
import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
import net.minecraftforge.event.ForgeEventFactory import ru.dbotthepony.mc.otm.config.AndroidConfig
import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.extractEnergyInner import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.Vector
import ru.dbotthepony.mc.otm.core.formatPower
import ru.dbotthepony.mc.otm.core.formatSi
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
import ru.dbotthepony.mc.otm.core.minus import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.core.math.minus
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.position import ru.dbotthepony.mc.otm.core.position
import ru.dbotthepony.mc.otm.core.times import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
import ru.dbotthepony.mc.otm.network.MNetworkContext
import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.WorldNetworkChannel
import ru.dbotthepony.mc.otm.network.packetHandled
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import java.util.UUID import java.util.UUID
import java.util.WeakHashMap import java.util.WeakHashMap
import java.util.function.Predicate import java.util.function.Predicate
import java.util.function.Supplier
private data class SharedItemEntityData(val owner: UUID? = null, val age: Int = 0, val lifespan: Int = 0, val hasPickupDelay: Boolean = true) { private data class SharedItemEntityData(val owner: UUID? = null, val age: Int = 0, val lifespan: Int = 0, val hasPickupDelay: Boolean = true) {
companion object { companion object {
@ -57,8 +44,7 @@ class ItemEntityDataPacket(val itemUUID: Int, val owner: UUID? = null, val age:
buff.writeBoolean(hasPickupDelay) buff.writeBoolean(hasPickupDelay)
} }
override fun play(context: Supplier<NetworkEvent.Context>) { override fun play(context: MNetworkContext) {
context.packetHandled = true
val level = minecraft.player?.level as ClientLevel? ?: return val level = minecraft.player?.level as ClientLevel? ?: return
val entity = level.getEntity(itemUUID) as ItemEntity? ?: return val entity = level.getEntity(itemUUID) as ItemEntity? ?: return
datatable[entity] = SharedItemEntityData(owner, age, lifespan, hasPickupDelay) datatable[entity] = SharedItemEntityData(owner, age, lifespan, hasPickupDelay)
@ -79,13 +65,13 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
private val clientPredicate = Predicate<Entity> { it is ItemEntity && (datatable[it] ?: SharedItemEntityData.EMPTY).let { !it.hasPickupDelay && (it.owner == null || it.owner != ply.uuid || it.lifespan - it.age <= 200) } } private val clientPredicate = Predicate<Entity> { it is ItemEntity && (datatable[it] ?: SharedItemEntityData.EMPTY).let { !it.hasPickupDelay && (it.owner == null || it.owner != ply.uuid || it.lifespan - it.age <= 200) } }
private fun doTick(server: Boolean) { private fun doTick(server: Boolean) {
if (ply.isSpectator || server && !android.androidEnergy.extractEnergyInnerExact(ServerConfig.AndroidItemMagnet.POWER_DRAW, true).isPositive) { if (ply.isSpectator || server && !android.androidEnergy.extractEnergyExact(AndroidConfig.Magnet.POWER_DRAW, true)) {
return return
} }
val entities = ply.level.getEntitiesInEllipsoid( val entities = ply.level.getEntitiesInEllipsoid(
ply.position, ply.position,
Vector(ServerConfig.AndroidItemMagnet.RADIUS_HORIZONTAL, ServerConfig.AndroidItemMagnet.RADIUS_VERTICAL, ServerConfig.AndroidItemMagnet.RADIUS_HORIZONTAL), Vector(AndroidConfig.Magnet.RADIUS_HORIZONTAL, AndroidConfig.Magnet.RADIUS_VERTICAL, AndroidConfig.Magnet.RADIUS_HORIZONTAL),
if (server) Predicate<Entity> { it is ItemEntity } else clientPredicate if (server) Predicate<Entity> { it is ItemEntity } else clientPredicate
) )
@ -93,7 +79,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
ent as ItemEntity ent as ItemEntity
if (server) { if (server) {
WorldNetworkChannel.send(ply, ItemEntityDataPacket(ent.id, ent.owner, ent.age, ent.lifespan, ent.hasPickUpDelay())) GenericNetworkChannel.send(ply, ItemEntityDataPacket(ent.id, ent.owner, ent.age, ent.lifespan, ent.hasPickUpDelay()))
if (!serverPredicate.test(ent)) { if (!serverPredicate.test(ent)) {
continue continue
@ -104,7 +90,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
if (data.position.distanceToSqr(ent.position) < 1.0) { if (data.position.distanceToSqr(ent.position) < 1.0) {
data.ticksSinceActivity++ data.ticksSinceActivity++
} else { } else {
if (!android.androidEnergy.extractEnergyInnerExact(ServerConfig.AndroidItemMagnet.POWER_DRAW, false).isPositive) { if (!android.androidEnergy.extractEnergyExact(AndroidConfig.Magnet.POWER_DRAW, false)) {
return return
} }
@ -120,7 +106,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
override fun tickClient() { override fun tickClient() {
super.tickClient() super.tickClient()
if (!ply.isSpectator && isActive && android.androidEnergy.extractEnergyInnerExact(ServerConfig.AndroidItemMagnet.POWER_DRAW, true).isPositive) { if (!ply.isSpectator && isActive && android.androidEnergy.extractEnergyExact(AndroidConfig.Magnet.POWER_DRAW, true)) {
doTick(false) doTick(false)
} }
} }
@ -133,15 +119,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
} }
} }
override fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) { override fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor) {
ResearchIcons.ICON_ITEM_MAGNET.render(stack, x, y, width, height) ResearchIcons.ICON_ITEM_MAGNET.render(graphics, x, y, width, height, color = color)
}
companion object {
val POWER_COST_DESCRIPTION =
AndroidResearchManager.descriptionFunc(ResourceLocation(
OverdriveThatMatters.MOD_ID, MNames.ITEM_MAGNET),
"otm.gui.power_cost_per_tick",
{ ServerConfig.AndroidItemMagnet.POWER_DRAW.formatPower().copy().withStyle(ChatFormatting.YELLOW) })
} }
} }

View File

@ -1,67 +1,50 @@
package ru.dbotthepony.mc.otm.android.feature package ru.dbotthepony.mc.otm.android.feature
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.ChatFormatting
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource import net.minecraft.sounds.SoundSource
import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.ClientConfig
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.Vector import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.formatPower import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
import ru.dbotthepony.mc.otm.network.MNetworkContext
import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
import ru.dbotthepony.mc.otm.network.enqueueWork import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket
import ru.dbotthepony.mc.otm.network.packetHandled
import ru.dbotthepony.mc.otm.network.sender
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.MSoundEvents import ru.dbotthepony.mc.otm.registry.MSoundEvents
import java.util.function.Supplier
object TriggerJumpBoostPacket : MatteryPacket { object TriggerJumpBoostPacket : MatteryPacket {
override fun write(buff: FriendlyByteBuf) { override fun write(buff: FriendlyByteBuf) {
// no op // no op
} }
override fun play(context: Supplier<NetworkEvent.Context>) { override fun play(context: MNetworkContext) {
context.packetHandled = true val mattery = context.sender?.matteryPlayer ?: return
context.enqueueWork {
val mattery = context.sender?.matteryPlayer ?: return@enqueueWork
if (!mattery.isAndroid) if (!mattery.isAndroid)
return@enqueueWork return
val feature = mattery.getFeature(AndroidFeatures.JUMP_BOOST) as JumpBoostFeature? ?: return@enqueueWork val feature = mattery.getFeature(AndroidFeatures.JUMP_BOOST) ?: return
if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyInnerExact(ServerConfig.AndroidJumpBoost.ENERGY_COST, false).isPositive) { if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, false)) {
feature.putOnCooldown() feature.putOnCooldown()
context.sender?.let { context.sender.level.playSound(
it.level.playSound( context.sender, context.sender,
it, MSoundEvents.ANDROID_JUMP_BOOST, SoundSource.PLAYERS,
it, 1f, 1f
MSoundEvents.ANDROID_JUMP_BOOST,
SoundSource.PLAYERS,
1f,
1f
) )
}
} GenericNetworkChannel.makeSmoke(context.sender, context.sender.x, context.sender.y, context.sender.z)
} }
} }
} }
@ -70,7 +53,7 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
private var tickCooldownClient = false private var tickCooldownClient = false
override val maxCooldown: Int override val maxCooldown: Int
get() = (ServerConfig.AndroidJumpBoost.BASE_COOLDOWN - ServerConfig.AndroidJumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0) get() = (AndroidConfig.JumpBoost.BASE_COOLDOWN - AndroidConfig.JumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0)
override var cooldown by synchronizer.int(setter = setter@{ value, access, setByRemote -> override var cooldown by synchronizer.int(setter = setter@{ value, access, setByRemote ->
access.write(value) access.write(value)
@ -78,7 +61,7 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
if (setByRemote) { if (setByRemote) {
tickCooldownClient = false tickCooldownClient = false
} }
}) }).property
private var lastGround = false private var lastGround = false
@ -92,19 +75,18 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
val old = lastGround val old = lastGround
lastGround = ply.isOnGround lastGround = ply.isOnGround
if (isActive && cooldown <= 0 && old != lastGround && !lastGround && isJumping && isShifting && ply.xRot <= ClientConfig.JUMP_BOOST_LOOK_ANGLE && android.androidEnergy.extractEnergyInnerExact(ServerConfig.AndroidJumpBoost.ENERGY_COST, true).isPositive) { if (isActive && cooldown <= 0 && old != lastGround && !lastGround && isJumping && isShifting && ply.xRot <= ClientConfig.JUMP_BOOST_LOOK_ANGLE && android.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, true)) {
ply.deltaMovement += Vector(0.0, ServerConfig.AndroidJumpBoost.POWER * (level + 1) / 20.0, 0.0) ply.deltaMovement += Vector(0.0, AndroidConfig.JumpBoost.POWER * (level + 1) / 20.0, 0.0)
putOnCooldown() putOnCooldown()
MatteryPlayerNetworkChannel.sendToServer(TriggerJumpBoostPacket) MatteryPlayerNetworkChannel.sendToServer(TriggerJumpBoostPacket)
ply.level.playSound( ply.level.playSound(
ply, ply, ply,
ply, MSoundEvents.ANDROID_JUMP_BOOST, SoundSource.PLAYERS,
MSoundEvents.ANDROID_JUMP_BOOST, 1f, 1f
SoundSource.PLAYERS,
1f,
1f
) )
SmokeParticlesPacket.makeSmoke(ply.x, ply.y, ply.z, ply.random, ply.level)
} }
} }
@ -114,24 +96,7 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
} }
} }
override fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) { override fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor) {
if (cooldown > 0) { ResearchIcons.ICON_JUMP_BOOST.render(graphics, x, y, width, height, color = if (cooldown > 0) color * RGBAColor.REDDISH else color)
RenderSystem.setShaderColor(1f, 0.4f, 0.4f, 1f)
}
ResearchIcons.ICON_JUMP_BOOST.render(stack, x, y, width, height)
if (cooldown > 0) {
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
}
}
companion object {
val POWER_COST_DESCRIPTION =
AndroidResearchManager.descriptionFunc(
ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.JUMP_BOOST),
"otm.gui.power_cost_per_use",
{ ServerConfig.AndroidJumpBoost.ENERGY_COST.formatPower().copy().withStyle(ChatFormatting.YELLOW) })
} }
} }

View File

@ -1,9 +1,12 @@
package ru.dbotthepony.mc.otm.android.feature package ru.dbotthepony.mc.otm.android.feature
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.attributes.AttributeModifier import net.minecraft.world.entity.ai.attributes.AttributeModifier
import net.minecraft.world.entity.ai.attributes.Attributes import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.player.Player
import ru.dbotthepony.mc.otm.android.AndroidFeature import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import java.util.* import java.util.*
@ -31,5 +34,34 @@ class LimbOverclockingFeature(android: MatteryPlayerCapability) : AndroidFeature
companion object { companion object {
private val MODIFIER_ID = UUID.fromString("4a3fae46-e57b-4e20-857d-f5c2b2c8f2f2") private val MODIFIER_ID = UUID.fromString("4a3fae46-e57b-4e20-857d-f5c2b2c8f2f2")
@JvmStatic
fun getBrushCooldown(entity: LivingEntity): Int {
if (entity !is Player) return 10
val matteryPlayer = entity.matteryPlayer ?: return 10
if (!matteryPlayer.isAndroid || !matteryPlayer.hasFeature(AndroidFeatures.LIMB_OVERCLOCKING)) return 10
val level = matteryPlayer.getFeature(AndroidFeatures.LIMB_OVERCLOCKING)!!.level + 1
return (10 - level * 2).coerceAtLeast(2)
}
@JvmStatic
fun getBrushTick(entity: LivingEntity): Int {
if (entity !is Player) return 5
val matteryPlayer = entity.matteryPlayer ?: return 5
if (!matteryPlayer.isAndroid || !matteryPlayer.hasFeature(AndroidFeatures.LIMB_OVERCLOCKING)) return 5
val level = matteryPlayer.getFeature(AndroidFeatures.LIMB_OVERCLOCKING)!!.level + 1
return (5 - level).coerceAtLeast(1)
}
@JvmStatic
fun getBrushableBlockCooldown(player: Player): Long {
val matteryPlayer = player.matteryPlayer ?: return 10L
if (!matteryPlayer.isAndroid || !matteryPlayer.hasFeature(AndroidFeatures.LIMB_OVERCLOCKING)) return 10L
val level = matteryPlayer.getFeature(AndroidFeatures.LIMB_OVERCLOCKING)!!.level + 1
return (10L - level * 2L).coerceAtLeast(2L)
}
} }
} }

View File

@ -4,36 +4,38 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraftforge.event.entity.living.LivingHurtEvent import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidFeature import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.core.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.StatNames import ru.dbotthepony.mc.otm.registry.StatNames
import ru.dbotthepony.mc.otm.core.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.onceServer import ru.dbotthepony.mc.otm.onceServer
import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger
import kotlin.math.roundToInt import kotlin.math.roundToInt
class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) { class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) {
var strength: Int = 0 var strength by synchronizer.int(
set(value) { field = value.coerceIn(0 .. 3) } setter = setter@{
value, access, _ -> access.write(value.coerceIn(0 .. 3))
}
).property
var speed: Int = 0 var speed: Int = 0
set(value) { field = value.coerceIn(0 .. 3) } set(value) { field = value.coerceIn(0 .. 3) }
private var ticksPassed = 0 private var ticksPassed = 0
private var layers = 0 var layers by synchronizer.int().property
override fun tickServer() { override fun tickServer() {
if (layers < strength + 1 && android.androidEnergy.extractEnergyInnerExact(ENERGY_PER_LAYER, true).isPositive) { if (layers < strength + 1 && android.androidEnergy.extractEnergyExact(ENERGY_PER_LAYER, true)) {
ticksPassed++ ticksPassed++
if (ticksPassed >= TICKS[speed]) { if (ticksPassed >= TICKS[speed]) {
layers++ layers++
android.androidEnergy.extractEnergyInner(ENERGY_PER_LAYER, false) android.androidEnergy.extractEnergy(ENERGY_PER_LAYER, false)
ticksPassed = 0
} }
} else { } else {
ticksPassed = 0 ticksPassed = 0
@ -48,7 +50,7 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
if (absorbed > 0.1f) { if (absorbed > 0.1f) {
val powerRequired = ENERGY_PER_HITPOINT * absorbed val powerRequired = ENERGY_PER_HITPOINT * absorbed
val powerExtracted = android.androidEnergy.extractEnergyInner(powerRequired, false) val powerExtracted = android.androidEnergy.extractEnergy(powerRequired, false)
val realAbsorbed = (powerExtracted / ENERGY_PER_HITPOINT).toFloat() val realAbsorbed = (powerExtracted / ENERGY_PER_HITPOINT).toFloat()
val ply = ply val ply = ply
@ -101,33 +103,5 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
0.45f, 0.45f,
0.6f, 0.6f,
) )
val STRENGTH_TRANSFORMER_UP = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_strength_up"))
{ level: Int ->
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).strength == level - 1) {
(second as NanobotsArmorFeature).strength = level
}
}
val STRENGTH_TRANSFORMER_DOWN = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_strength_down"))
{ level: Int ->
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).strength == level) {
(second as NanobotsArmorFeature).strength = level - 1
}
}
val SPEED_TRANSFORMER_UP = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_speed_up"))
{ level: Int ->
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).speed == level - 1) {
(second as NanobotsArmorFeature).speed = level
}
}
val SPEED_TRANSFORMER_DOWN = AndroidResearchManager.featureResultTransformers.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor_speed_down"))
{ level: Int ->
if (second is NanobotsArmorFeature && (second as NanobotsArmorFeature).speed == level) {
(second as NanobotsArmorFeature).speed = level - 1
}
}
} }
} }

Some files were not shown because too many files have changed in this diff Show More