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
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
* [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
* [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
### 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)
* [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 java.util.Date
import java.text.SimpleDateFormat
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 mc_version: String by project
@ -13,7 +10,7 @@ val forge_version: String by project
val mod_id: String by project
val handle_deps: String by project
val use_commit_hash_in_version: String by project
val handleDeps = handle_deps == "true"
val handleDeps = handle_deps.toBoolean()
plugins {
java
@ -23,13 +20,7 @@ plugins {
id("org.spongepowered.mixin")
}
configurations {
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) {
data class GitInfo(val version: String, val tag: String, val buildNumber: String) {
// val tagIsVersion: Boolean get() = tag != "" && tag.matches(Regex("v[0-9]+\\.[0-9]\\.[0-9]"))
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 buildNumber = if (buildNumber != "") "-$buildNumber" else ""
if (tag != "")
return "$mod_version-$version"
return "$mod_version-$version$buildNumber"
// if (count != "")
// return "$mod_version-SNAPSHOT-${version}_$count"
if (version != "") {
return "$mod_version-SNAPSHOT-$version"
return "$mod_version-SNAPSHOT-$version$buildNumber"
} else {
return "$mod_version-SNAPSHOT"
return "$mod_version-SNAPSHOT$buildNumber"
}
}
val modVersion: String get() {
if (tag != "")
return mod_version
if (version != "") {
return "$mod_version-SNAPSHOT-$version"
} else {
return "$mod_version-SNAPSHOT"
}
return if (buildNumber != "") "$mod_version.$buildNumber" else mod_version
}
}
@ -74,7 +60,6 @@ fun getCommitVersion(): GitInfo? {
try {
val versionStream = FastByteArrayOutputStream()
val tagStream = FastByteArrayOutputStream()
val countStream = FastByteArrayOutputStream()
val gotVersion = exec {
commandLine("git", "rev-parse", "--short", "HEAD")
@ -82,27 +67,20 @@ fun getCommitVersion(): GitInfo? {
standardOutput = versionStream
}.exitValue == 0
val gotCount = exec {
commandLine("git", "rev-list", "--count", "HEAD")
workingDir(".")
standardOutput = countStream
}.exitValue == 0
val gotTag = exec {
commandLine("git", "tag", "--points-at", "HEAD")
workingDir(".")
standardOutput = tagStream
}.exitValue == 0
if (!gotVersion || !gotCount || !gotTag) {
if (!gotVersion || !gotTag) {
return null
}
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 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) {
println("Error getting git version")
println(err)
@ -143,10 +121,7 @@ tasks.test {
dependencies {
val jupiter_version: String by project
val kotlin_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
minecraft("net.minecraftforge:forge:$mc_version-$forge_version")
@ -154,72 +129,74 @@ dependencies {
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")
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) {
val jei_version: String by project
val mekanism_version: String by project
val curios_version: String by project
val cosmetic_armor_reworked_version: String by project
val cosmetic_armor_reworked_id: String by project
val jade_id: String by project
val configured_id: String by project
val worldedit_fileid: String by project
val more_overlays_version: String by project
val curios_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("lain.mods.cos:CosmeticArmorReworked:${mc_version}-${cosmetic_armor_reworked_version}"))
compileOnly(fg.deobf("curse.maven:curios-309927:${curios_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-${mc_version}-forge-api:${jei_version}"))
runtimeOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}"))
// implementation("mcjty:theoneprobe:${mc_version}-${the_one_probe_version}:deobf")
compileOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-common-api:${jei_version}"))
compileOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-forge-api:${jei_version}"))
// runtimeOnly(fg.deobf("mezz.jei:jei-${jei_mc_version}-forge:${jei_version}"))
// 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("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 {
getByName("dataImplementation").extendsFrom(getByName("implementation"))
getByName("library").resolutionStrategy.cacheChangingModulesFor(10, "minutes")
}
minecraft {
mappings("official", mc_version)
copyIdeResources.set(true)
accessTransformer(file("src/main/resources/META-INF/accesstransformer.cfg"))
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") {
mods {
create(mod_id) {
@ -239,25 +216,13 @@ minecraft {
val originalUsername = usernameStream.array.copyOfRange(0, usernameStream.length).toString(Charsets.UTF_8).trim()
if (originalUsername.isNotEmpty()) {
var 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)
args("--username", originalUsername)
} else {
args("--username", "Dev_${System.getProperty("user.name")}")
}
} else {
args("--username", "Dev_${System.getProperty("user.name")}")
}
args("-mixin.config=$mod_id.mixins.json")
}
create("server") {
@ -267,7 +232,7 @@ minecraft {
}
}
args("nogui", "-mixin.config=$mod_id.mixins.json")
args("nogui")
}
create("data") {
@ -278,8 +243,6 @@ minecraft {
sources(sourceSets["main"], sourceSets["data"])
}
}
forceExit(false)
}
}
}
@ -287,28 +250,7 @@ minecraft {
mixin {
add(sourceSets.main.get(), "$mod_id.refmap.json")
config("$mod_id.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)
}
config("$mod_id.ad_astra.mixins.json")
}
repositories {
@ -321,11 +263,11 @@ repositories {
url = uri("https://maven.dbotthepony.ru")
content {
includeGroup("top.theillusivec4.curios")
includeGroup("yalter.mousetweaks")
includeGroup("mekanism")
includeGroup("lain.mods.cos")
includeGroup("at.ridgo8.moreoverlays")
includeGroup("ru.dbotthepony")
}
}
@ -349,14 +291,22 @@ repositories {
}
maven {
name = "Progwml6 maven"
url = uri("https://dvs1.progwml6.com/files/maven/")
name = "Jared's Maven"
url = uri("https://maven.blamejared.com/")
content {
includeGroup("mezz.jei")
}
}
maven {
url = uri("https://maven.theillusivec4.top/")
content {
includeGroup("top.theillusivec4.curios")
}
}
// mavenCentral()
}
@ -377,12 +327,24 @@ fun org.gradle.jvm.tasks.Jar.attachManifest() {
// Example configuration to allow publishing using the maven-publish plugin
// This is the preferred method to reobfuscate your jar file
tasks.jar.configure {
from(configurations["library"].map { if (it.isDirectory) it else zipTree(it) })
finalizedBy("reobfJar")
attachManifest()
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 {
create("sourceJar", org.gradle.jvm.tasks.Jar::class.java) {
archiveClassifier.set("sources")
@ -391,7 +353,6 @@ tasks {
create("deobfJar", org.gradle.jvm.tasks.Jar::class.java) {
archiveClassifier.set("deobf")
from(configurations["library"].map { if (it.isDirectory) it else zipTree(it) })
from(sourceSets.main.get().output)
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', [
'convert',
'-compose', 'Multiply',
'-size', `${width}x${height}`,
'(',
`${root_main}${texA}.png`,
`xc:rgb(${rgbA[0]}, ${rgbA[1]}, ${rgbA[2]})`,
'-compose', 'Multiply',
'-composite',
')',
'(',
`${root_main}${texB}.png`,
`xc:rgb(${rgbB[0]}, ${rgbB[1]}, ${rgbB[2]})`,
'-channel', 'rgb',
'-compose', 'Multiply',
'-composite',
')',
'-channel', 'rgba',
'-compose', 'Over',
'-composite',

View File

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

Binary file not shown.

View File

@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
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
zipStorePath=wrapper/dists

28
gradlew vendored
View File

@ -1,7 +1,7 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (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
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (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.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -80,10 +80,10 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
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.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
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 ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | 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" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -205,6 +209,12 @@ set -- \
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.
#
# 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
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
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
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
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")})")
pluginManagement {
val kotlin_version: String by settings
val forge_gradle_version: String by settings
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)
repositories {
gradlePluginPortal()
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention").version("0.5.0")
}
buildscript {
repositories {
// These repositories are only for Gradle plugins, put any other repositories in the repository block further below
maven(url = "https://maven.minecraftforge.net") {
name = "Minecraft Forge"
content {
includeGroup("net.minecraftforge.gradle")
includeGroup("net.minecraftforge")
@ -24,6 +24,8 @@ buildscript {
}
maven(url = "https://repo.spongepowered.org/repository/maven-public/") {
name = "Spongepowered"
content {
includeGroup("org.spongepowered")
}
@ -40,5 +42,7 @@ buildscript {
classpath(group = "net.minecraftforge.gradle", name = "ForgeGradle", version = forge_gradle_version)
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_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
import net.minecraft.core.RegistrySetBuilder
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.DyeColor
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.Half
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.fml.common.Mod
import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidResearchDataProvider
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.MatterBankProvider
import ru.dbotthepony.mc.otm.datagen.blocks.MatteryBlockStateProvider
import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider
import ru.dbotthepony.mc.otm.datagen.lang.AddEnglishLanguage
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.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.addAndroidAdvancements
import ru.dbotthepony.mc.otm.datagen.advancements.addMachineAdvancements
import ru.dbotthepony.mc.otm.datagen.blocks.addBlockStates
import ru.dbotthepony.mc.otm.datagen.blocks.addComplexBlockStates
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.loot.*
import ru.dbotthepony.mc.otm.datagen.loot.LootModifiers
import ru.dbotthepony.mc.otm.datagen.models.addBlockModels
import ru.dbotthepony.mc.otm.datagen.recipes.addBlastingRecipes
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.recipes.*
import ru.dbotthepony.mc.otm.datagen.tags.TagsProvider
import ru.dbotthepony.mc.otm.datagen.tags.addTags
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 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)
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) {
var doorBottomLeft by Delegates.notNull<ModelFile>()
var doorBottomLeftOpen by Delegates.notNull<ModelFile>()
@ -271,7 +350,7 @@ object DataGen {
}
}
).rotationY(
facing.toYRotBlockstate() - 90 +
facing.yRotationBlockstateNorth() - 90 +
(if (open) when (hinge) {
DoorHingeSide.LEFT -> 90
DoorHingeSide.RIGHT -> -90
@ -321,7 +400,7 @@ object DataGen {
Half.BOTTOM -> trapdoorBottom
}
).rotationY(
facing.toYRotBlockstate()
facing.yRotationBlockstateNorth()
).addModel()
.condition(TrapDoorBlock.FACING, facing)
.condition(TrapDoorBlock.OPEN, open)
@ -406,7 +485,7 @@ object DataGen {
val lootModifier = LootModifiers(event.generator)
val languageProvider = MatteryLanguageProvider(event.generator)
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.blockStateProvider = blockStateProvider
@ -419,7 +498,12 @@ object DataGen {
this.matterData = matterData
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)
@ -436,14 +520,21 @@ object DataGen {
event.generator.addProvider(event.includeServer(), advancementProvider)
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)
AddRussianLanguage(languageProvider)
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" } ?: ""}"))
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()}"))
addBlockModels(blockModelProvider)
@ -460,17 +551,15 @@ object DataGen {
addCraftingTableRecipes(consumer)
addBlastingRecipes(consumer)
addDecorativesRecipes(recipeProvider, consumer)
addMachineUpgradeRecipes(consumer)
addShapelessRecipes(consumer)
addOreSmeltingRecipes(consumer)
}
advancementProvider.exec { it, files ->
addAdvancements(it, files, languageProvider)
addAndroidAdvancements(it, files, languageProvider)
addMachineAdvancements(it, files, languageProvider)
addPainterRecipes(consumer)
addMatterEntanglerRecipes(consumer)
}
addPlatePressRecipes(recipeProvider)
addMicrowaveRecipes(recipeProvider)
lootModifier.lambda {
addLootModifiers(it)
@ -479,5 +568,7 @@ object DataGen {
languageProvider.registerProviders()
addMatterData(matterData)
tagsProvider.register()
}
}

View File

@ -1,21 +1,21 @@
package ru.dbotthepony.mc.otm.datagen
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.PressurePlateBlock
import net.minecraft.world.level.block.AnvilBlock
import net.minecraft.world.level.block.SlabBlock
import net.minecraft.world.level.block.StairBlock
import net.minecraft.world.level.block.WallBlock
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.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.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.datagen.blocks.MatteryBlockStateProvider
import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider
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.MItems
import ru.dbotthepony.mc.otm.registry.MNames
@ -37,6 +37,17 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
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) {
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)
blockStateProvider.simpleBlockM(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
blockStateProvider.simpleBlockM(MBlocks.FLUID_TANK)
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_BLOCK.blocksWithColor) {
DataGen.decorativeColumn(
block,
@ -181,17 +194,17 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
DataGen.decorativeCubeAll(MBlocks.DANGER_STRIPE_BLOCK)
DataGen.decorativeColumn(MBlocks.METAL_BEAM, "metal_beam_side", "metal_beam_top")
var labLampOn: MatteryModelBuilder? = null
var labLampOff: MatteryModelBuilder? = null
var labLampOn: BlockModelBuilder? = null
var labLampOff: BlockModelBuilder? = null
blockModelProvider.exec {
val top = ResourceLocation(DataGen.MOD_ID, "block/decorative/metal_beam_top")
val top = modLocation("block/decorative/metal_beam_top")
labLampOn = it.cube(
MBlocks.LABORATORY_LAMP.registryName!!.path,
top,
top,
ResourceLocation(DataGen.MOD_ID, "block/decorative/laboratory_lamp_front"),
modLocation("block/decorative/laboratory_lamp_front"),
top,
top,
top,
@ -201,7 +214,7 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
MBlocks.LABORATORY_LAMP.registryName!!.path + "_unlit",
top,
top,
ResourceLocation(DataGen.MOD_ID, "block/decorative/laboratory_lamp_front_off"),
modLocation("block/decorative/laboratory_lamp_front_off"),
top,
top,
top,
@ -217,28 +230,28 @@ fun addDecorativeData(blockStateProvider: MatteryBlockStateProvider, itemModelPr
blockStateProvider.getVariantBuilder(MBlocks.LABORATORY_LAMP).forAllStates {
return@forAllStates ConfiguredModel.builder()
.modelFile(if (it[BlockStateProperties.LIT]) labLampOn!! else labLampOff!!)
.rotationX(it[RotatableMatteryBlock.FACING_FULL].toXRotBlockstate())
.rotationY(it[RotatableMatteryBlock.FACING_FULL].toYRotBlockstate())
.rotationX(it[BlockRotationFreedom.DIRECTIONAL.property].front.xRotationBlockstateNorth())
.rotationY(it[BlockRotationFreedom.DIRECTIONAL.property].front.yRotationBlockstateNorth())
.build()
}
blockStateProvider.getVariantBuilder(MBlocks.LABORATORY_LAMP_INVERTED).forAllStates {
return@forAllStates ConfiguredModel.builder()
.modelFile(if (it[BlockStateProperties.LIT]) labLampOn!! else labLampOff!!)
.rotationX(it[RotatableMatteryBlock.FACING_FULL].toXRotBlockstate())
.rotationY(it[RotatableMatteryBlock.FACING_FULL].toYRotBlockstate())
.rotationX(it[BlockRotationFreedom.DIRECTIONAL.property].front.xRotationBlockstateNorth())
.rotationY(it[BlockRotationFreedom.DIRECTIONAL.property].front.yRotationBlockstateNorth())
.build()
}
}
blockModelProvider.exec {
for (crate in MRegistry.CARGO_CRATES.blocks.values) {
it.withExistingParent("${crate.registryName!!.path}_closed", ResourceLocation(OverdriveThatMatters.MOD_ID, "${MNames.CARGO_CRATE}_closed"))
.texture("texture", "block/cargo_crates/${crate.registryName!!.path}")
it.withExistingParent("${crate.registryName!!.path}_closed", modLocation("${MNames.CARGO_CRATE}_closed"))
.texture("body", "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"))
.texture("texture", "block/cargo_crates/${crate.registryName!!.path}")
it.withExistingParent("${crate.registryName!!.path}_open", modLocation("${MNames.CARGO_CRATE}_open"))
.texture("body", "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) {
val name = MRegistry.INDUSTRIAL_GLASS.allBlocks[color]!!.registryName!!.path
val textureSide = ResourceLocation(DataGen.MOD_ID, "block/decorative/$name")
val textureRailing = ResourceLocation(DataGen.MOD_ID, "block/decorative/industrial_glass_frame")
val textureSide = modLocation("block/decorative/$name")
val textureRailing = modLocation("block/decorative/industrial_glass_frame")
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.Items
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.registry.MItemTags
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.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>>(
listOf(
Items.EXPOSED_COPPER,
@ -101,7 +125,7 @@ fun addMatterData(provider: MatterDataProvider) {
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_ANDROID, 20, 20)
@ -205,6 +229,7 @@ fun addMatterData(provider: MatterDataProvider) {
relative(Items.HONEY_BLOCK, 6, 1.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(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.minecraftforge.common.Tags
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.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.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
@ -47,6 +43,45 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
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))
.withExperience(24)
.addFeatureResult(AndroidFeatures.STEP_ASSIST)
@ -103,7 +138,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
.addPrerequisite(OverdriveThatMatters.loc(MNames.NANOBOTS))
.addFeatureResult(OverdriveThatMatters.loc(MNames.NANOBOTS_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.COPPER_WIRES, 8)
.build()
@ -128,15 +163,18 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
TranslatableComponent(
"android_research.overdrive_that_matters.limb_overclocking.description",
(i + 1) * 8,
(i + 1) * 6
(i + 1) * 6,
(i + 1) * 20
)
)
.addItem(MItemTags.COPPER_WIRES, 4 + i * 2)
.addFeatureResult(OverdriveThatMatters.loc(MNames.LIMB_OVERCLOCKING), i)
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)
} else {
research.addFeatureResult(AndroidFeatures.LIMB_OVERCLOCKING)
}
research.build()
@ -152,21 +190,26 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
.withDescription(
TranslatableComponent(
"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)
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()
})
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)
.withIconText(TextComponent((i + 1).toString()))
.withIcon(ResearchIcons.ICON_NANOBOTS)
@ -179,15 +222,16 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
.addItem(MItems.MATTER_CAPACITOR_PARTS, 1)
.addItem(Items.SUGAR, 2 + i * 2)
.addItem(Tags.Items.DUSTS_REDSTONE, 2 + i * 2)
.addFeatureResult(AndroidFeatures.NANOBOTS_REGENERATION, i)
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 {
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(Items.SUGAR, 1 + i)
.addItem(MItems.ELECTROMAGNET)
.addFeatureResult(AndroidFeatures.NANOBOTS_ARMOR, 0,
transformersUp = listOf(NanobotsArmorFeature.STRENGTH_TRANSFORMER_UP.bind(level)),
transformersDown = listOf(NanobotsArmorFeature.STRENGTH_TRANSFORMER_DOWN.bind(level)),
)
.addResult(AndroidResearchResults.NANOBOTS_ARMOR_STRENGTH)
.build()
})
@ -243,10 +284,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
)
)
.addItem(Tags.Items.DUSTS_REDSTONE, 4 + i * 4)
.addFeatureResult(AndroidFeatures.NANOBOTS_ARMOR, 0,
transformersUp = listOf(NanobotsArmorFeature.SPEED_TRANSFORMER_UP.bind(level)),
transformersDown = listOf(NanobotsArmorFeature.SPEED_TRANSFORMER_DOWN.bind(level)),
)
.addResult(AndroidResearchResults.NANOBOTS_ARMOR_SPEED)
.build()
})
}
@ -261,7 +299,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.SHOCKWAVE))
.withExperience(40)
.withDescription(0 .. 1)
.appendDescription(ShockwaveFeature.POWER_COST_DESCRIPTION)
.withDescription(AndroidResearchDescriptions.SHOCKWAVE)
.withIcon(ResearchIcons.ICON_SHOCKWAVE)
.addFeatureResult(AndroidFeatures.SHOCKWAVE)
.addPrerequisite(attackBoostList[2])
@ -276,7 +314,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.ITEM_MAGNET))
.withExperience(28)
.withDescription(0 .. 1)
.appendDescription(ItemMagnetFeature.POWER_COST_DESCRIPTION)
.withDescription(AndroidResearchDescriptions.ITEM_MAGNET)
.withIcon(ResearchIcons.ICON_ITEM_MAGNET)
.addFeatureResult(AndroidFeatures.ITEM_MAGNET)
.addPrerequisite(STEP_ASSIST)
@ -292,9 +330,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_1"))
.withExperience(25)
.withDescription()
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(1))
.withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(1))
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 0)
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS)
.addPrerequisite(STEP_ASSIST)
.addItem(MItems.ELECTROMAGNET, 2)
.addItem(ItemTags.WOOL, 2)
@ -305,9 +343,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_2"))
.withExperience(30)
.withDescription()
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(2))
.withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(2))
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 1)
.addFeatureLevel(AndroidFeatures.FALL_DAMPENERS)
.addPrerequisite(FALL_DAMPENERS_1)
.addItem(MItemTags.GOLD_PLATES, 2)
.addItem(MItemTags.COPPER_WIRES, 4)
@ -319,9 +357,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.FALL_DAMPENERS + "_3"))
.withExperience(35)
.withDescription(0 .. 1)
.appendDescription(FallDampenersFeature.DESCRIPTION.bind(3))
.withDescription(AndroidResearchDescriptions.FALL_DAMPENERS.Instance(3))
.withIcon(ResearchIcons.ICON_FEATHER_FALLING)
.addFeatureResult(AndroidFeatures.FALL_DAMPENERS, 2)
.addFeatureLevel(AndroidFeatures.FALL_DAMPENERS)
.addPrerequisite(FALL_DAMPENERS_2)
.addItem(MItemTags.ADVANCED_CIRCUIT, 2)
.addItem(Tags.Items.GEMS_DIAMOND, 4)
@ -337,7 +375,7 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.ENDER_TELEPORTER))
.withExperience(35)
.withDescription()
.appendDescription(EnderTeleporterFeature.POWER_COST_DESCRIPTION)
.withDescription(AndroidResearchDescriptions.ENDER_TELEPORTER)
.withIcon(ResearchIcons.ICON_ENDER_TELEPORT)
.addFeatureResult(AndroidFeatures.ENDER_TELEPORTER)
.addPrerequisite(FALL_DAMPENERS_1)
@ -350,27 +388,13 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
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 =
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_1"))
.withExperience(27)
.withDescription(0 .. 1)
.appendDescription(JumpBoostFeature.POWER_COST_DESCRIPTION)
.withDescription(AndroidResearchDescriptions.JUMP_BOOST)
.withIcon(ResearchIcons.ICON_JUMP_BOOST)
.addFeatureResult(AndroidFeatures.JUMP_BOOST, 0)
.addFeatureResult(AndroidFeatures.JUMP_BOOST)
.addItem(MItemTags.PISTONS, 2)
.addItem(MItemTags.GOLD_WIRES, 4)
.addItem(MItems.ELECTROMAGNET, 2)
@ -382,9 +406,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
AndroidResearchType.Builder(modLocation(MNames.JUMP_BOOST + "_2"))
.withExperience(34)
.withDescription()
.appendDescription(JumpBoostFeature.POWER_COST_DESCRIPTION)
.withDescription(AndroidResearchDescriptions.JUMP_BOOST)
.withIcon(ResearchIcons.ICON_JUMP_BOOST)
.addFeatureResult(AndroidFeatures.JUMP_BOOST, 1)
.addFeatureLevel(AndroidFeatures.JUMP_BOOST)
.addItem(MItems.ELECTRIC_PARTS, 4)
.addItem(MItems.ELECTROMAGNET, 4)
.addPrerequisite(JUMP_BOOST_1)
@ -394,74 +418,179 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
serializer.accept(JUMP_BOOST_1)
serializer.accept(JUMP_BOOST_2)
with(lang.english) {
misc("fall_dampeners.description", "Reduces fall damage by %s%%")
with(lang) {
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], "description", "Boosts unit's mobility by %s%% and attack speed by %s%%")
add(limbList[0], "Limb Overclocking %s") {
russian("Разгон конечностей %s")
}
add(AIR_BAGS, "Air Bags")
add(NANOBOTS, "Nanobots")
add(AIR_BAGS, "description", "Allows unit to swim in water")
add(NANOBOTS, "description", "Various useful nanobots for doing various tasks")
add(limbList[0], "description", "Boosts mobility by %s%%, attack speed by %s%% and brushing speed by %s%%") {
russian("Увеличивает мобильность на %s%%, скорость атак на %s%% и скорость чистки блоков на %s%%")
}
add(regenList[0], "Regeneration %s")
add(regenList[0], "description", "Nanobots get ability to repair unit's internal systems on the move")
add(regenList[0], "description_improve", "Improves regeneration speed")
add(AIR_BAGS, "Air Bags") {
russian("Воздушные мешки")
}
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(NANOBOTS_ARMOR, "description", "Allows nanobots to align themselves in cell shape, reducing incoming damage by a %% by absorbing impacts")
add(regenList[0], "Regeneration %s") {
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(armorSpeedList[0], "description", "Reduces time required for nanobots to form protection layer")
add(NANOBOTS_ARMOR, "Nanobots Armor") {
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(armorStrengthList[0], "description", "Increases impact absorption strength of nanobots")
add(armorSpeedList[0], "Nanobots Armor Build Speed %s") {
russian("Скорость аостроения слоя брони наноботов %s")
}
add(armorSpeedList[0], "description", "Reduces time required for nanobots to form protection layer") {
russian("Уменьшает время необходимое наноботам для формирования защитного слоя")
}
add(EXTENDED_REACH, "Extended Reach")
add(EXTENDED_REACH, "description", "Increases block interaction distance")
add(armorStrengthList[0], "Nanobots Armor Strength %s") {
russian("Сила слоя брони наноботов %s")
}
add(armorStrengthList[0], "description", "Increases impact absorption strength of nanobots") {
russian("Увеличивает поглощающею силу брони наноботов")
}
add(IMPROVED_LIMBS, "Improved Limbs")
add(IMPROVED_LIMBS, "description", "Allows limbs to be upgraded")
add(EXTENDED_REACH, "Extended Reach") {
russian("Удлинённые манипуляторы")
}
add(EXTENDED_REACH, "description", "Increases block interaction distance") {
russian("Увеличивает радиус взаимодействия с блоками")
}
add(STEP_ASSIST, "Step Assist")
add(STEP_ASSIST, "description", "Allows unit to step up whole blocks")
add(IMPROVED_LIMBS, "Improved Limbs") {
russian("Улучшенные конечности")
}
add(IMPROVED_LIMBS, "description", "Allows limbs to be upgraded") {
russian("Позволяет улучшать конечности")
}
add(ITEM_MAGNET, "Item Magnet")
add(ITEM_MAGNET, "description0", "Pulls nearby items to unit while active")
add(ITEM_MAGNET, "description1", "Drains energy for each item stack it pulls")
add(SWIM_BOOSTERS, "Swim Boosters") {
russian("Плавательные лопасти")
}
add(SWIM_BOOSTERS, "description", "Increases swimming speed by %s%%") {
russian("Ускоряет скорость плавания на %s%%")
}
add(FALL_DAMPENERS_1, "Fall Dampeners")
add(FALL_DAMPENERS_1, "description", "Installs basic equipment in unit's limbs to negate some fall damage")
add(SWIM_BOOSTERS_2, "Swim Boosters 2") {
russian("Плавательные лопасти 2")
}
add(FALL_DAMPENERS_2, "Fall Dampeners 2")
add(FALL_DAMPENERS_2, "description", "Installs micro displacing and dampening equipment in unit's limbs to negate great deal of fall damage")
add(SWIM_BOOSTERS_3, "Swim Boosters 3") {
russian("Плавательные лопасти 3")
}
add(FALL_DAMPENERS_3, "Fall Dampeners 3")
add(FALL_DAMPENERS_3, "description0", "Installs autonomous calculation matrices and hardening to crucial parts")
add(FALL_DAMPENERS_3, "description1", "of unit's limbs to land on to negate most of fall damage")
add(STEP_ASSIST, "Step Assist") {
russian("Помощь подъёма")
}
add(STEP_ASSIST, "description", "Allows unit to step up whole blocks") {
russian("Позволяет переступать полные блоки")
}
add(SHOCKWAVE, "Shockwave Pulsator")
add(SHOCKWAVE, "description0", "Releases a shockwave around unit, damaging everything in small radius, as unit quickly land on ground")
add(SHOCKWAVE, "description1", "It does not, however, help with ground impact damage!")
add(ITEM_MAGNET, "Item Magnet") {
russian("Предметный магнит")
}
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(PHANTOM_ATTRACTOR, "description", "Allows unit to attract phantoms while active under same conditions as non-androids")
add(FALL_DAMPENERS_1, "Fall Dampeners") {
russian("Поглотители инерции")
}
add(FALL_DAMPENERS_1, "description", "Installs basic equipment in limbs to negate some fall damage") {
russian("Обустраивает конечности примитивными деталями для небольшого смягчения падения")
}
add(JUMP_BOOST_1, "Jump Boost")
add(JUMP_BOOST_1, "description0", "Allows unit to perform higher jump")
add(JUMP_BOOST_1, "description1", "Can be activated by crouching and jumping at the same time")
add(FALL_DAMPENERS_2, "Fall Dampeners 2") {
russian("Поглотители инерции 2")
}
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(JUMP_BOOST_2, "description", "Allows unit to perform extra higher jump")
add(FALL_DAMPENERS_3, "Fall Dampeners 3") {
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(ENDER_TELEPORTER, "description", "Allows unit to perform instant, short distance teleports without damage to internal systems")
add(SHOCKWAVE, "Shockwave Pulsator") {
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(NIGHT_VISION, "description", "Allows unit to clearly see in the dark")
add(JUMP_BOOST_1, "Jump Boost") {
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(attackBoostList[0], "description", "Increases total melee attack strength by %s%%")
add(JUMP_BOOST_2, "Jump Boost 2") {
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)
}
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() {
add(MSoundEvents.PLASMA_WEAPON_OVERHEAT,
definition().subtitle("otm.sound.plasma_weapon_overheat")
@ -34,6 +34,11 @@ class SoundDataProvider(event: GatherDataEvent) : SoundDefinitionsProvider(event
add(MSoundEvents.ANDROID_SHOCKWAVE,
definition().subtitle("otm.sound.android.shockwave")
.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) {

View File

@ -1,14 +1,11 @@
package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.Advancement
import net.minecraft.advancements.AdvancementRewards
import net.minecraft.advancements.FrameType
import net.minecraft.advancements.RequirementsStrategy
import net.minecraft.advancements.critereon.InventoryChangeTrigger
import net.minecraft.world.item.DyeColor
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.datagen.lang.MatteryLanguageProvider
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.MRegistry
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
import ru.dbotthepony.mc.otm.triggers.NailedEntityTrigger
import java.util.function.Consumer
fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) {
val translation = lang.english.Prepended("otm.advancements.regular")
typealias Strategy = RequirementsStrategy
fun addAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider) {
val translation = lang.MultiBuilder("otm.advancements.regular")
val root = AdvancementBuilder()
.requirements(RequirementsStrategy.OR)
.requirements(Strategy.OR)
.display(
itemStack = ItemStack(MItems.TRITANIUM_INGOT),
title = TranslatableComponent(translation.add("root", "Overdrive That Matters")),
description = TranslatableComponent(translation.add("root.desc", "Its all about things that matter")),
title = translation.add("root", "Overdrive That Matters"),
description = translation.add("root.desc", "It's all about things that matter") {
russian("Мод про все штуки которые материальны")
},
showToast = false,
announceChat = false,
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_clump", criterion(MItemTags.TRITANIUM_ORE_CLUMPS))
.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()
.parent(root)
.display(
itemStack = ItemStack(MItems.BATTERY_CRUDE),
title = TranslatableComponent(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")),
title = translation.add("crude_battery", "Potato Power!") {
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))
.save(serializer, modLocation("regular/crude_battery"), existingFileHelper)
.save(serializer, modLocation("regular/crude_battery"))
val normal = AdvancementBuilder()
.parent(crude)
.display(
itemStack = ItemStack(MItems.BATTERY_NORMAL),
title = TranslatableComponent(translation.add("normal_battery", "Power Storage")),
description = TranslatableComponent(translation.add("normal_battery.desc", "Put together an Ordinary Battery")),
title = translation.add("normal_battery", "Power Storage") {
russian("Хранилище энергии")
},
description = translation.add("normal_battery.desc", "Put together a Battery") {
russian("Создайте аккумулятор")
},
)
.addCriterion("has_item", criterion(MItems.BATTERY_NORMAL))
.save(serializer, modLocation("regular/normal_battery"), existingFileHelper)
.save(serializer, modLocation("regular/normal_battery"))
AdvancementBuilder()
.parent(normal)
.display(
itemStack = ItemStack(MItems.BATTERY_DENSE),
title = TranslatableComponent(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!")),
title = translation.add("dense_battery", "Extra Space Battery") {
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))
.save(serializer, modLocation("regular/dense_battery"), existingFileHelper)
.save(serializer, modLocation("regular/dense_battery"))
val capacitor = AdvancementBuilder()
.parent(normal)
.display(
itemStack = ItemStack(MItems.BATTERY_CAPACITOR),
title = TranslatableComponent(translation.add("capacitor_battery", "Supercapacitor")),
description = TranslatableComponent(translation.add("capacitor_battery.desc", "Put together a Capacitor Battery. Surely, you gonna need them somewhere...")),
title = translation.add("capacitor_battery", "Supercapacitor") {
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))
.save(serializer, modLocation("regular/capacitor_battery"), existingFileHelper)
.save(serializer, modLocation("regular/capacitor_battery"))
AdvancementBuilder()
.parent(capacitor)
.display(
itemStack = ItemStack(MItems.ENERGY_SWORD),
title = TranslatableComponent(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...")),
title = translation.add("energy_sword", "Self Sharpening Blade") {
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
)
.addCriterion("has_item", criterion(MItems.ENERGY_SWORD))
.save(serializer, modLocation("regular/energy_sword"), existingFileHelper)
.save(serializer, modLocation("regular/energy_sword"))
AdvancementBuilder()
.parent(normal)
.display(
itemStack = ItemStack(MItems.QUANTUM_BATTERY),
title = TranslatableComponent(translation.add("quantum_battery", "Power, in Superposition")),
description = TranslatableComponent(translation.add("quantum_battery.desc", "Put together a Quantum Battery, powered by Ender technologies")),
title = translation.add("quantum_battery", "Power, in Superposition") {
russian("Энергия, в суперпозиции")
},
description = translation.add("quantum_battery.desc", "Put together a Quantum Battery, powered by Ender technologies") {
russian("Создайте квантовый аккумулятор, пропитанную технологиями Края")
},
frameType = FrameType.GOAL
)
.rewards(AdvancementRewards.Builder.experience(50))
.requirements(RequirementsStrategy.OR)
.requirements(Strategy.OR)
.addCriterion("has_item0", criterion(MItems.QUANTUM_BATTERY))
.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)
.display(
itemStack = ItemStack(MItems.ZPM_BATTERY),
title = TranslatableComponent(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")),
title = translation.add("zpm_battery", "Pocket Universe, as Power Source") {
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,
hidden = true
)
.rewards(AdvancementRewards.Builder.experience(800))
.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()
.parent(root)
.display(
itemStack = ItemStack(MItems.BLACK_HOLE),
title = TranslatableComponent(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")),
title = translation.add("black_hole_pull", "Something Massive and Something Close") {
russian("Что то массивное и близкое")
},
description = translation.add("black_hole_pull.desc", "Experience Singularity's gravitational force, better not to get closer") {
russian("Испытайте на себе гравитационную силу сингулярности, лучше не подходить ближе")
},
hidden = true
)
.addCriterion("pulled_by_black_hole", BlackHoleTrigger.Instance)
.save(serializer, modLocation("regular/black_hole"), existingFileHelper)
.addCriterion("pulled_by_black_hole", BlackHoleTrigger.criterion)
.save(serializer, modLocation("regular/black_hole"))
AdvancementBuilder()
.parent(blackhole)
.display(
itemStack = ItemStack(MItems.BLACK_HOLE_SCANNER),
title = TranslatableComponent(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")),
title = translation.add("black_hole_scanner", "Determining the Mass") {
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))
.save(serializer, modLocation("regular/black_hole_scanner"), existingFileHelper)
.save(serializer, modLocation("regular/black_hole_scanner"))
AdvancementBuilder()
.parent(blackhole)
.display(
itemStack = ItemStack(MItems.GRAVITATION_STABILIZER),
title = TranslatableComponent(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")),
title = translation.add("stabilizer", "Reducing the Impact") {
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))
.save(serializer, modLocation("regular/stabilizer"), existingFileHelper)
.save(serializer, modLocation("regular/stabilizer"))
AdvancementBuilder()
.parent(blackhole)
.display(
itemStack = ItemStack(MItems.PORTABLE_GRAVITATION_STABILIZER),
title = TranslatableComponent(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")),
title = translation.add("portable_stabilizer", "Local Gravity Field") {
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))
.save(serializer, modLocation("regular/portable_stabilizer"), existingFileHelper)
.save(serializer, modLocation("regular/portable_stabilizer"))
val ore = AdvancementBuilder()
.parent(root)
.requirements(RequirementsStrategy.OR)
.requirements(Strategy.OR)
.display(
itemStack = ItemStack(MItems.TRITANIUM_ORE_CLUMP),
title = TranslatableComponent(translation.add("ore", "Blue Metal Discovery")),
description = TranslatableComponent(translation.add("ore.desc", "Mine some Tritanium")),
title = translation.add("ore", "Blue Metal Discovery") {
russian("Открытие синего металла")
},
description = translation.add("ore.desc", "Mine some Tritanium") {
russian("Добудьте немного тритана")
},
)
.addCriterion("has_tritanium_ore", criterion(MItemTags.TRITANIUM_ORES))
.addCriterion("has_tritanium_ore_clump", criterion(MItemTags.TRITANIUM_ORE_CLUMPS))
.save(serializer, modLocation("regular/ore"), existingFileHelper)
.save(serializer, modLocation("regular/ore"))
val ingot = AdvancementBuilder()
.parent(ore)
.display(
itemStack = ItemStack(MItems.TRITANIUM_INGOT),
title = TranslatableComponent(translation.add("ingot", "Acquire Harder-ware")),
description = TranslatableComponent(translation.add("ingot.desc", "Smelt a Tritanium ingot")),
title = translation.add("ingot", "Acquire Harder-ware") {
russian("Куй сильнее...")
},
description = translation.add("ingot.desc", "Smelt a Tritanium ingot") {
russian("Выплавьте тритановый слиток")
},
)
.addCriterion("has_tritanium_ingot", criterion(MItemTags.TRITANIUM_INGOTS))
.save(serializer, modLocation("regular/ingot"), existingFileHelper)
.save(serializer, modLocation("regular/ingot"))
AdvancementBuilder()
.parent(ingot)
.display(
itemStack = ItemStack(MItems.TRITANIUM_PICKAXE),
title = TranslatableComponent(translation.add("pickaxe", "A Tool for Patient Miners")),
description = TranslatableComponent(translation.add("pickaxe.desc", "Craft a Tritanium Pickaxe")),
title = translation.add("pickaxe", "A Tool for Patient Miners") {
russian("Инструмент для неспешных шахтёров")
},
description = translation.add("pickaxe.desc", "Craft a Tritanium Pickaxe") {
russian("Создайте тритановую кирку")
},
)
.addCriterion("has_tritanium_pickaxe", criterion(MItems.TRITANIUM_PICKAXE))
.save(serializer, modLocation("regular/pickaxe"), existingFileHelper)
.save(serializer, modLocation("regular/pickaxe"))
AdvancementBuilder()
.parent(ingot)
.display(
itemStack = ItemStack(MItems.TRITANIUM_HOE),
title = TranslatableComponent(translation.add("hoe", "A Tool for Farmers")),
description = TranslatableComponent(translation.add("hoe.desc", "Tritanium is a very good choice for making a sturdy Hoe")),
title = translation.add("hoe", "A Tool for Farmers") {
russian("Инструмент для фермеров")
},
description = translation.add("hoe.desc", "Tritanium is a very good choice for making a sturdy Hoe") {
russian("Тритан - очень хороший выбор для создания прочной Мотыги")
},
hidden = true
)
.addCriterion("hoe", criterion(MItems.TRITANIUM_HOE))
.save(serializer, modLocation("regular/hoe"), existingFileHelper)
.save(serializer, modLocation("regular/hoe"))
val plate = AdvancementBuilder()
.parent(ingot)
.display(
itemStack = ItemStack(MItems.TRITANIUM_PLATE),
title = TranslatableComponent(translation.add("plate", "Hard Plating")),
description = TranslatableComponent(translation.add("plate.desc", "Roll down some Tritanium using a Plate Press"))
title = translation.add("plate", "Hard Plating") {
russian("Прочные пластины")
},
description = translation.add("plate.desc", "Roll down some Tritanium using a Plate Press") {
russian("Раскатайте немного тритана используя пресс пластин")
}
)
.addCriterion("has_item", criterion(MItemTags.TRITANIUM_PLATES))
.save(serializer, modLocation("regular/plate"), existingFileHelper)
.save(serializer, modLocation("regular/plate"))
AdvancementBuilder()
.parent(plate)
.display(
itemStack = ItemStack(MItems.TRITANIUM_CHESTPLATE),
title = TranslatableComponent(translation.add("armor", "Composite Armor")),
description = TranslatableComponent(translation.add("armor.desc", "Bend some Tritanium plates into simple yet sturdy armor"))
title = translation.add("armor", "Composite 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_item1", criterion(MItems.TRITANIUM_CHESTPLATE))
.addCriterion("has_item2", criterion(MItems.TRITANIUM_PANTS))
.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()
.parent(plate)
.display(
itemStack = ItemStack(MRegistry.INDUSTRIAL_GLASS.item),
title = TranslatableComponent(translation.add("industrial_glass", "Extra Hard Glass")),
description = TranslatableComponent(translation.add("industrial_glass.desc", "Manual says it should be bulletproof."))
title = translation.add("industrial_glass", "Extra Hard Glass") {
russian("Дополнительно прочное стекло")
},
description = translation.add("industrial_glass.desc", "Manual says it should be bulletproof.") {
russian("В инструкции указано что оно должно быть пуленепробиваемо.")
}
)
.requirements(RequirementsStrategy.OR)
.requirements(Strategy.OR)
.also { advancement ->
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()
.parent(glass)
.display(
itemStack = ItemStack(MRegistry.INDUSTRIAL_GLASS.getItem(DyeColor.GREEN)),
title = TranslatableComponent(translation.add("industrial_glass2", "Glass-tacular Artist")),
description = TranslatableComponent(translation.add("industrial_glass2.desc", "Paint Industrial Glass all possible colors")),
title = translation.add("industrial_glass2", "Glass-Tacular Artist") {
russian("Стекло-чаровательный артист")
},
description = translation.add("industrial_glass2.desc", "Paint Industrial Glass all possible colors") {
russian("Покрасьте промышленное стекло во все возможные цвета")
},
frameType = FrameType.GOAL
)
.requirements(RequirementsStrategy.AND)
.requirements(Strategy.AND)
.also { advancement ->
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()
.parent(plate)
.display(
itemStack = ItemStack(MRegistry.CARGO_CRATES.item),
title = TranslatableComponent(translation.add("cargo_crate", "Sturdy Item Stash")),
description = TranslatableComponent(translation.add("cargo_crate.desc", "Cargo Crates, like Double Chest, but Single."))
title = translation.add("cargo_crate", "Sturdy Item Stash") {
russian("Прочное хранилище предметов")
},
description = translation.add("cargo_crate.desc", "Cargo Crates, like Double Chest, but Single") {
russian("Грузовые ящики, будто двойные сундуки, но одинарные.")
}
)
.requirements(RequirementsStrategy.OR)
.requirements(Strategy.OR)
.also { advancement ->
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()
.parent(cargoCrate)
.display(
itemStack = ItemStack(MItems.CARGO_CRATE_MINECARTS[null]!!),
title = TranslatableComponent(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"))
title = translation.add("cargo_crate_minecart", "Crate On a Rail") {
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 ->
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()
.parent(cargoCrateInMinecart)
.display(
itemStack = ItemStack(MItems.CARGO_CRATE_MINECARTS[DyeColor.GREEN]!!),
title = TranslatableComponent(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")),
title = translation.add("cargo_crate_minecart2", "A Motley Train") {
russian("Пёстрый поезд")
},
description = translation.add("cargo_crate_minecart2.desc", "Have all color variants of Minecarts with Cargo Crates") {
russian("Создайте все варианты покрасок вагонеток с грузовыми Ящиками")
},
frameType = FrameType.GOAL
)
.requirements(RequirementsStrategy.AND)
.requirements(Strategy.AND)
.also { advancement ->
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()
.parent(cargoCrate)
.display(
itemStack = ItemStack(MRegistry.CARGO_CRATES.item),
title = TranslatableComponent(translation.add("cargo_crate2", "Colorful Warehouse")),
description = TranslatableComponent(translation.add("cargo_crate2.desc", "Craft all color variants of Cargo Crates")),
title = translation.add("cargo_crate2", "Colorful Warehouse") {
russian("Разноцветный склад")
},
description = translation.add("cargo_crate2.desc", "Craft all color variants of Cargo Crates") {
russian("Покрасьте грузовые ящики во все возможные цвета")
},
frameType = FrameType.GOAL
)
.requirements(RequirementsStrategy.AND)
.requirements(Strategy.AND)
.also { advancement ->
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()
.parent(plate)
.parent(ingot)
.display(
itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.item),
title = TranslatableComponent(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"))
title = translation.add("tritanium_block", "Cold, Impregnable Wall") {
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 ->
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)) }
@ -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_STAIRS.also { advancement.addCriterion(it.registryName!!.path, criterion(it)) }
}
.save(serializer, modLocation("regular/tritanium_block"), existingFileHelper)
.save(serializer, modLocation("regular/tritanium_block"))
AdvancementBuilder()
.parent(tritaniumBlock)
.display(
itemStack = ItemStack(MItems.TRITANIUM_STRIPED_BLOCK),
title = TranslatableComponent(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"))
title = translation.add("striped_tritanium_block", "Old Fashion Color Touch") {
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_item1", criterion(MItems.TRITANIUM_STRIPED_STAIRS))
.addCriterion("has_item2", criterion(MItems.TRITANIUM_STRIPED_SLAB))
.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()
.parent(tritaniumBlock)
.display(
itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.getItem(DyeColor.GREEN)),
title = TranslatableComponent(translation.add("tritanium_block2", "Colorful Fortress")),
description = TranslatableComponent(translation.add("tritanium_block2.desc", "Put some paint over Tritanium Block to make it look fabulous"))
title = translation.add("tritanium_block2", "Colorful Fortress") {
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 ->
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)) }
@ -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_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()
.parent(colorTritaniumBlock)
.display(
itemStack = ItemStack(MRegistry.TRITANIUM_BLOCK.getItem(DyeColor.BLACK)),
title = TranslatableComponent(translation.add("tritanium_block3", "Paint Me A Castle")),
description = TranslatableComponent(translation.add("tritanium_block3.desc", "Craft all color variants of Tritanium Blocks")),
title = translation.add("tritanium_block3", "Paint Me A Castle") {
russian("Разукрась мне замок")
},
description = translation.add("tritanium_block3.desc", "Craft all color variants of Tritanium Blocks") {
russian("Создайте все варианты покрасок тритановых Блоков")
},
frameType = FrameType.GOAL
)
.rewards(AdvancementRewards.Builder.loot(modLocation("tritanium_block3")).addExperience(100))
.requirements(RequirementsStrategy.AND)
.requirements(Strategy.AND)
.also { advancement ->
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()
.parent(colorfulTritaniumBlock)
.display(
itemStack = ItemStack(MRegistry.TRITANIUM_STRIPED_BLOCK.getItem(DyeColor.BLACK, DyeColor.WHITE)),
title = TranslatableComponent(translation.add("tritanium_block4", "All The Colors")),
description = TranslatableComponent(translation.add("tritanium_block4.desc", "Craft ALL color variants of Tritanium Blocks including striped ones")),
title = translation.add("tritanium_block4", "All The Colors") {
russian("Все цвета всё сюда")
},
description = translation.add("tritanium_block4.desc", "Craft ALL color variants of Tritanium Blocks including striped ones") {
russian("Создайте АБСОЛЮТНО ВСЕ варианты покрасок тритановых блоков, включая с полосками")
},
frameType = FrameType.CHALLENGE
)
.rewards(AdvancementRewards.Builder.loot(modLocation("tritanium_block4")).addExperience(400))
.requirements(RequirementsStrategy.AND)
.requirements(Strategy.AND)
.also { advancement ->
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)) }
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()
.parent(root)
.display(
itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(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.")),
title = translation.add("pill", "Side Colored Mystery") {
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("pill2", criterion(MItems.PILL_HEAL))
.addCriterion("pill3", criterion(MItems.PILL_HUMANE))
.addCriterion("pill4", criterion(MItems.PILL_OBLIVION))
.save(serializer, modLocation("regular/pill"), existingFileHelper)
.save(serializer, modLocation("regular/pill"))
AdvancementBuilder()
.parent(pill)
.display(
itemStack = ItemStack(MItems.PILL_HEAL),
title = TranslatableComponent(translation.add("all_pills", "Take Your Meds")),
description = TranslatableComponent(translation.add("all_pills.desc", "Find all possible pill types")),
title = translation.add("all_pills", "Take Your Meds") {
russian("Пей таблетки")
},
description = translation.add("all_pills.desc", "Find all possible pill types") {
russian("Найдите всевозможные варианты пилюль")
},
frameType = FrameType.CHALLENGE,
hidden = true
)
.rewards(AdvancementRewards.Builder.experience(200))
.requirements(RequirementsStrategy.AND)
.requirements(Strategy.AND)
.addCriterion("pill1", criterion(MItems.PILL_ANDROID))
.addCriterion("pill2", criterion(MItems.PILL_HEAL))
.addCriterion("pill3", criterion(MItems.PILL_HUMANE))
.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
import net.minecraft.advancements.Advancement
import net.minecraft.advancements.AdvancementRewards
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.InventoryChangeTrigger
import net.minecraft.advancements.critereon.ItemPredicate
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.item.ItemStack
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.lang.MatteryLanguageProvider
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.MNames
import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger
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.BecomeAndroidSleepTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidTrigger
import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
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.PhantomSpawnDeniedTrigger
import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger
import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
import java.util.*
import java.util.function.Consumer
fun addAndroidAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) {
val translation = lang.english.Prepended("otm.advancements.android")
fun addAndroidAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider) {
val translation = lang.MultiBuilder("otm.advancements.android")
val root = AdvancementBuilder()
.display(
itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(translation.add("root", "Androids and Humans")),
description = TranslatableComponent(translation.add("root.desc", "Can you make out who is cruel machine and who can love?")),
title = translation.add("root", "Androids and Humans") {
russian("Андроиды и люди")
},
description = translation.add("root.desc", "Can you make out who is cruel machine and who shows empathy?") {
russian("Сможете ли вы отличить бездушную машину от того, кто показывает сочувствие?")
},
showToast = false,
announceChat = false,
background = modLocation("textures/block/decorative/metal_beam_top.png")
)
.addCriterion("became_android", BecomeAndroidTrigger.Instance)
.save(serializer, modLocation("android/root"), existingFileHelper)
.addCriterion("became_android", BecomeAndroidTrigger.criterion)
.save(serializer, modLocation("android/root"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.ZPM_BATTERY),
title = TranslatableComponent(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")),
title = translation.add("zpm", "Fully Autonomous") {
russian("Полностью автономный")
},
description = translation.add("zpm.desc", "Use Zero Point Module as internal battery power source. Only eternity is your enemy now") {
russian("Используйте модуль нулевой точки как внутренний источник питания. Теперь только вечность будет вашим злейшим врагом")
},
hidden = true,
frameType = FrameType.CHALLENGE
)
.addCriterion("item", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.ZPM_BATTERY).build()))
.save(serializer, modLocation("android/zpm"), existingFileHelper)
.addCriterion("item", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.ZPM_BATTERY).build()).criterion())
.save(serializer, modLocation("android/zpm"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.QUANTUM_BATTERY),
title = TranslatableComponent(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")),
title = translation.add("quantum_battery", "Wireless Charged") {
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,
frameType = FrameType.GOAL
)
.requirements(RequirementsStrategy.OR)
.addCriterion("item0", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_BATTERY).build()))
.addCriterion("item1", AndroidBatteryTrigger.Instance(ItemPredicate.Builder.item().of(MItems.QUANTUM_CAPACITOR).build()))
.save(serializer, modLocation("android/quantum_battery"), existingFileHelper)
.requirements(Strategy.OR)
.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()).criterion())
.save(serializer, modLocation("android/quantum_battery"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(translation.add("normal", "Last Sweet Dreams")),
description = TranslatableComponent(translation.add("normal.desc", "Become an Android in your dreams, a soulless machine... Or is it?")),
title = translation.add("normal", "Last Sweet Dreams") {
russian("Последние сновидения")
},
description = translation.add("normal.desc", "Become an Android in your dreams, a soulless machine... Or is it?") {
russian("Превратитесь в андроида во сне, в бездушную машину... Или нет?")
},
hidden = true,
)
.addCriterion("became_android", BecomeAndroidSleepTrigger.Instance)
.save(serializer, modLocation("android/become_thru_sleep"), existingFileHelper)
.addCriterion("became_android", BecomeAndroidSleepTrigger.criterion)
.save(serializer, modLocation("android/become_thru_sleep"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.PILL_ANDROID),
title = TranslatableComponent(translation.add("death", "The Old Way")),
description = TranslatableComponent(translation.add("death.desc", "Become an Android in event of death, veteran's favorite")),
title = translation.add("death", "The Old Way") {
russian("Изготовленный по старинке")
},
description = translation.add("death.desc", "In event of death, become an Android; Veteran's favorite") {
russian("Станьте андроидом, будучи умерев; Ветераны оценят")
},
hidden = true,
)
.addCriterion("became_android", BecomeAndroidDeathTrigger.Instance)
.save(serializer, modLocation("android/become_thru_death"), existingFileHelper)
.addCriterion("became_android", BecomeAndroidDeathTrigger.criterion)
.save(serializer, modLocation("android/become_thru_death"))
AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.PILL_HUMANE),
title = TranslatableComponent(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...")),
title = translation.add("unandroid", "Feel Humane Again") {
russian("Вкусить человечность вновь")
},
description = translation.add("unandroid.desc", "Become fleshy after being a machine, yet something is still missing that you had before...") {
russian("Вновь обретите плоть после своей жизни как набор гаек и болтов, но вот чего-то всё равно не хватает, что было при вас с самого начала...")
},
hidden = true,
frameType = FrameType.GOAL
)
.addCriterion("become_humane", BecomeHumaneTrigger.Instance)
.save(serializer, modLocation("android/become_humane"), existingFileHelper)
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)
.addCriterion("become_humane", BecomeHumaneTrigger.criterion)
.save(serializer, modLocation("android/become_humane"))
val attractor = AdvancementBuilder()
.parent(phantoms)
.parent(root)
.display(
itemStack = ItemStack(MItems.PHANTOM_ATTRACTOR),
title = TranslatableComponent(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")),
title = translation.add("phantom_attractor", "Eversleeping Decoy") {
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))
.save(serializer, modLocation("regular/phantom_attractor"), existingFileHelper)
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)
.save(serializer, modLocation("regular/phantom_attractor"))
val researchAnything = AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.ANDROID_STATION),
title = TranslatableComponent(translation.add("research_anything", "New Trick")),
description = TranslatableComponent(translation.add("research_anything.desc", "Research anything as Android")),
title = translation.add("research_anything", "New Trick") {
russian("Новый фокус")
},
description = translation.add("research_anything.desc", "Research anything as Android") {
russian("Исследуйте что либо за андроида")
},
)
.addCriterion("research_anything", AndroidResearchTrigger.Instance(null))
.save(serializer, modLocation("android/research_anything"), existingFileHelper)
.addCriterion("research_anything", AndroidResearchTrigger.Instance(Optional.empty(), Optional.empty()).criterion())
.save(serializer, modLocation("android/research_anything"))
AdvancementBuilder()
.parent(researchAnything)
.display(
itemStack = ItemStack(Items.WATER_BUCKET),
title = TranslatableComponent(translation.add("air_bags", "Patching Up Wooden Vessel")),
description = TranslatableComponent(translation.add("air_bags.desc", "Research Air Bags as Android, to float in water")),
title = translation.add("air_bags", "Patching Up Wooden Vessel") {
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)))
.save(serializer, modLocation("android/research_air_bags"), existingFileHelper)
.addCriterion("air_bags", AndroidResearchTrigger.Instance(modLocation(MNames.AIR_BAGS)).criterion())
.save(serializer, modLocation("android/research_air_bags"))
AdvancementBuilder()
.parent(researchAnything)
.display(
itemStack = ItemStack(Items.ENDER_EYE),
title = TranslatableComponent(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")),
title = translation.add("night_vision", "Second Pair of Eyes") {
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)))
.save(serializer, modLocation("android/research_night_vision"), existingFileHelper)
.addCriterion("night_vision", AndroidResearchTrigger.Instance(modLocation(MNames.NIGHT_VISION)).criterion())
.save(serializer, modLocation("android/research_night_vision"))
val nanobots = AdvancementBuilder()
.parent(researchAnything)
.display(
itemStack = ItemStack(MItems.MATTER_TRANSFORM_MATRIX),
title = TranslatableComponent(translation.add("nanobots", "Nanomachines, Son!")),
description = TranslatableComponent(translation.add("nanobots.desc", "Research Nanobots as Android, to unlock potent research that come after it")),
title = translation.add("nanobots", "Nanomachines, son.") {
russian("Наномашины, сынок.")
},
description = translation.add("nanobots.desc", "Research Nanobots as Android, to unlock potent research that come after it") {
russian("Исследуйте наномашины за андроида, для разблокировки очень больших возможностей")
},
hidden = true
)
.addCriterion("nanobots", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS)))
.save(serializer, modLocation("android/research_nanobots"), existingFileHelper)
.addCriterion("nanobots", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS)).criterion())
.save(serializer, modLocation("android/research_nanobots"))
val shielding = AdvancementBuilder()
.parent(nanobots)
.display(
itemStack = ItemStack(Items.SHIELD),
title = TranslatableComponent(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")),
title = translation.add("nanobots_armor_deflect", "Like a Concrete Wall") {
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,
frameType = FrameType.GOAL
)
.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(10.0)))
.save(serializer, modLocation("android/nanobots_armor_deflect"), existingFileHelper)
.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(10.0)).criterion())
.save(serializer, modLocation("android/nanobots_armor_deflect"))
AdvancementBuilder()
.parent(shielding)
.display(
itemStack = ItemStack(Items.SHIELD),
title = TranslatableComponent(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")),
title = translation.add("nanobots_armor_deflect2", "Unstoppable Force vs Immovable Object") {
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,
frameType = FrameType.CHALLENGE
)
.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(20.0)))
.save(serializer, modLocation("android/nanobots_armor_deflect2"), existingFileHelper)
.addCriterion("damage", NanobotsArmorTrigger.Instance(Doubles.atLeast(20.0)).criterion())
.save(serializer, modLocation("android/nanobots_armor_deflect2"))
AdvancementBuilder()
.parent(researchAnything)
.display(
itemStack = ItemStack(Items.FEATHER),
title = TranslatableComponent(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")),
title = translation.add("fall_dampeners_save", "Lucky Landing") {
russian("Удачное приземление")
},
description = translation.add("fall_dampeners_save.desc", "Survive fall that would have otherwise be fatal without Fall Dampeners") {
russian("Выживите после падения, которое было бы фатальным без поглотителей инерции")
},
frameType = FrameType.GOAL
)
.addCriterion("saved", FallDampenersSaveTrigger.Instance)
.save(serializer, modLocation("android/fall_dampeners_save"), existingFileHelper)
.addCriterion("saved", FallDampenersSaveTrigger.criterion)
.save(serializer, modLocation("android/fall_dampeners_save"))
AdvancementBuilder()
.parent(researchAnything)
.display(
itemStack = ItemStack(Items.SKELETON_SKULL),
title = TranslatableComponent(translation.add("ender_teleport_fall_death", "Navigation Error")),
description = TranslatableComponent(translation.add("ender_teleport_fall_death.desc", "Fall to your death moments after Teleporting")),
title = translation.add("ender_teleport_fall_death", "Navigation Error") {
russian("Ошибка навигации")
},
description = translation.add("ender_teleport_fall_death.desc", "Fall to your demise moments after Teleporting as Android") {
russian("Разбейтесь насмерть через мгновения после телепортации за андроида")
},
frameType = FrameType.GOAL,
hidden = true
)
.addCriterion("death", EnderTeleporterFallDeathTrigger.Instance)
.save(serializer, modLocation("android/ender_teleport_fall_death"), existingFileHelper)
.addCriterion("death", EnderTeleporterFallDeathTrigger.criterion)
.save(serializer, modLocation("android/ender_teleport_fall_death"))
val regen = AdvancementBuilder()
.parent(nanobots)
.display(
itemStack = ItemStack(Items.GOLDEN_APPLE),
title = TranslatableComponent(translation.add("regen", "Field Repair Done Easy")),
description = TranslatableComponent(translation.add("regen.desc", "Research Nanobots Regeneration as Android")),
title = translation.add("regen", "Field Repair Done Easy") {
russian("Починка на ходу - легко")
},
description = translation.add("regen.desc", "Research Nanobots Regeneration as Android") {
russian("Исследуйте регенерацию наноботов за андроида")
},
)
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)))
.save(serializer, modLocation("android/regen"), existingFileHelper)
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)).criterion())
.save(serializer, modLocation("android/regen"))
AdvancementBuilder()
.parent(regen)
.display(
itemStack = ItemStack(Items.ENCHANTED_GOLDEN_APPLE),
title = TranslatableComponent(translation.add("regen_all", "Field Repair Done Effortless")),
description = TranslatableComponent(translation.add("regen_all.desc", "Max out Nanobots Regeneration research")),
title = translation.add("regen_all", "Field Repair Done Effortless") {
russian("Починка на ходу - без усилий")
},
description = translation.add("regen_all.desc", "Max out Nanobots Regeneration research") {
russian("Полностью исследуйте регенерацию наноботов за андроида")
},
frameType = FrameType.GOAL,
)
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)))
.addCriterion("regen1", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_2)))
.addCriterion("regen2", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_3)))
.addCriterion("regen3", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_4)))
.save(serializer, modLocation("android/regen_all"), existingFileHelper)
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)).criterion())
.addCriterion("regen1", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_2)).criterion())
.addCriterion("regen2", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_3)).criterion())
.addCriterion("regen3", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_4)).criterion())
.save(serializer, modLocation("android/regen_all"))
AdvancementBuilder()
.parent(researchAnything)
.display(
itemStack = ItemStack(MItems.ANDROID_STATION),
title = TranslatableComponent(translation.add("research_all", "Mecha-agnomination")),
description = TranslatableComponent(translation.add("research_all.desc", "Research everything (that don't block any other research)")),
title = translation.add("research_all", "Mecha-Agnomination") {
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
)
.rewards(AdvancementRewards.Builder.experience(400).addLootTable(modLocation("research_all_android")))
@ -268,29 +312,106 @@ fun addAndroidAdvancements(serializer: Consumer<Advancement>, existingFileHelper
DataGen.researchProvider.generatedView.stream()
.filter { it.allBlockedBy.isEmpty() && it.allBlocking.isEmpty() }
.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()
.parent(researchAnything)
.display(
itemStack = ItemStack(Items.PISTON),
title = TranslatableComponent(translation.add("shockwave", "Supersonic Landing")),
description = TranslatableComponent(translation.add("shockwave.desc", "Perform a Shockwave upon landing")),
title = translation.add("shockwave", "Supersonic Landing") {
russian("Сверхзвуковое приземление")
},
description = translation.add("shockwave.desc", "Make a Shockwave upon landing") {
russian("Вызовите ударную волну при приземлении")
},
)
.addCriterion("shockwave", ShockwaveTrigger.Instance)
.save(serializer, modLocation("android/shockwave"), existingFileHelper)
.addCriterion("shockwave", ShockwaveTrigger.criterion)
.save(serializer, modLocation("android/shockwave"))
AdvancementBuilder()
.parent(shockwave)
.display(
itemStack = ItemStack(Items.WARDEN_SPAWN_EGG),
title = TranslatableComponent(translation.add("shockwave_warden", "Music To Their Ears")),
description = TranslatableComponent(translation.add("shockwave_warden.desc", "Hurt Warden using Shockwave ability")),
title = translation.add("shockwave_warden", "Music to their Ears") {
russian("Музыка для их ушей")
},
description = translation.add("shockwave_warden.desc", "Hurt Warden using Shockwave ability") {
russian("Нанесите хранителю урон используя ударную волну")
},
frameType = FrameType.GOAL
)
.addCriterion("shockwave_warden", ShockwaveDamageMobTrigger.Instance(EntityPredicate.Builder.entity().of(EntityType.WARDEN).build().wrap()))
.save(serializer, modLocation("android/shockwave_warden"), existingFileHelper)
.addCriterion("shockwave_warden", ShockwaveDamageMobTrigger.Instance(Optional.of(EntityPredicate.Builder.entity().of(EntityType.WARDEN).build().wrap())).criterion())
.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.level.ItemLike
import ru.dbotthepony.mc.otm.core.TextComponent
import java.util.function.Consumer
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 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
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.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.key
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
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.triggers.TakeItemOutOfReplicatorTrigger
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) {
val translation = lang.english.Prepended("otm.advancements.machine")
private data class CraftEntry(
val item: Item,
val englishName: String,
val englishSuffix: String? = null,
val root = AdvancementBuilder()
.requirements(RequirementsStrategy.OR)
.display(
itemStack = ItemStack(MItems.CHEMICAL_GENERATOR),
title = TranslatableComponent(translation.add("root", "Tritanium Empowered Machinery")),
description = TranslatableComponent(translation.add("root.desc", "Do not drop in anything if you want the latter preserved intact")),
showToast = false,
announceChat = false,
background = modLocation("textures/block/decorative/floor_tiles_gray.png")
)
.addCriterion("has_machine", criterion(MItemTags.MACHINES))
.addCriterion("has_tritanium_ingot", criterion(MItemTags.TRITANIUM_INGOTS))
.addCriterion("has_tritanium_plate_somehow", criterion(MItemTags.TRITANIUM_PLATES))
.save(serializer, modLocation("machines/root"), existingFileHelper)
val russianName: String? = null,
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(
itemStack = ItemStack(item),
title = translation.add(path, englishName) {
if (russianName != null) {
russian(russianName)
}
},
description = TranslatableComponent(translated.contents.key, item.description, translatedSuffix),
)
.addCriterion("has_machine", criterion(item))
.save(serializer, modLocation("machines/$path"))
}
}
fun addMachineAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider, root: AdvancementHolder) {
val translation = lang.MultiBuilder("otm.advancements.machine")
val chem = AdvancementBuilder()
.parent(root)
.display(
itemStack = ItemStack(MItems.CHEMICAL_GENERATOR),
title = TranslatableComponent(translation.add("chemical_generator", "Burning the Organics")),
description = TranslatableComponent(translation.add("chemical_generator.desc", "Craft a Chemical Generator, better to put it outside")),
title = translation.add("chemical_generator", "Burning the Organics") {
russian("Сжигание органики")
},
description = translation.add("chemical_generator.desc", "Craft a Chemical Generator, better to put it outside") {
russian("Создайте химический генератор. Лучше установить его снаружи")
},
)
.addCriterion("has_machine", criterion(MItems.CHEMICAL_GENERATOR))
.save(serializer, modLocation("machines/chemical_generator"), existingFileHelper)
.save(serializer, modLocation("machines/chemical_generator"))
val press = AdvancementBuilder()
.parent(chem)
.display(
itemStack = ItemStack(MItems.PLATE_PRESS),
title = TranslatableComponent(translation.add("plate_press", "Bending the Material")),
description = TranslatableComponent(translation.add("plate_press.desc", "Craft a Plate Press, avoid having limbs inside during operation")),
title = translation.add("plate_press", "Bending the Material") {
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))
.save(serializer, modLocation("machines/plate_press"), existingFileHelper)
.save(serializer, modLocation("machines/plate_press"))
val entries = listOf(
CraftEntry(MItems.MATTER_SCANNER, "Scanning Things that Matter"),
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.TWIN_PLATE_PRESS, "Twice the Thud",
russianName = "Двойной стук").make(serializer, press, translation)
CraftEntry(MItems.ENERGY_COUNTER, "Visualize Power Burn"),
CraftEntry(MItems.BATTERY_BANK, "Batteries Not Included", "By all means avoid the urge to hammer incompatible batteries into the power bus."),
)
val scanner = CraftEntry(MItems.MATTER_SCANNER, "Scanning Things that Matter",
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 path = entry.item.registryName!!.path
val pattern = CraftEntry(MItems.PATTERN_STORAGE, "Digital Knowledge Library",
russianName = "Цифровая библиотека знаний")
built[entry.item] = AdvancementBuilder()
.parent(press)
.display(
itemStack = ItemStack(entry.item),
title = TranslatableComponent(translation.add(path, entry.englishName)),
description = TranslatableComponent(translation.add("$path.desc", "Craft a %s%s"), entry.item.description, if (entry.englishSuffix != null) ". " + entry.englishSuffix else ""),
)
.addCriterion("has_machine", criterion(entry.item))
.save(serializer, modLocation("machines/$path"), existingFileHelper)
val reconstructor = CraftEntry(MItems.MATTER_RECONSTRUCTOR, "Flipping Hourglass",
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(
itemStack = ItemStack(Items.BREAD),
title = translation.add("replicate_something", "Local Bakery") {
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("replicate_something", TakeItemOutOfReplicatorTrigger.Instance(ItemPredicate.Builder.item().of(MItems.MATTER_DUST).build(), true).criterion())
.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
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.Block
import net.minecraftforge.client.model.generators.BlockStateProvider
import net.minecraftforge.client.model.generators.ConfiguredModel
import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.block.BatteryBankBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.core.get
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.toYRotBlockstate
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MBlocks
private fun nothingOrNumber(input: Int): String {
@ -17,29 +18,25 @@ private fun nothingOrNumber(input: Int): String {
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 batteryPath = "block/battery/battery"
protected var registry: Block = MBlocks.BATTERY_BANK
override fun registerStatesAndModels() {
with(getMultipartBuilder(registry)) {
val battery_bank = models().getExistingFile(ResourceLocation("overdrive_that_matters:block/$block"))
RotatableMatteryBlock.FACING.possibleValues.forEach {
part().modelFile(battery_bank).rotationY(it.toYRotBlockstate()).addModel().condition(
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)
}
with(getVariantBuilder(registry)) {
forAllStates {
ConfiguredModel.builder()
.modelFile(models().getExistingFile(modLocation("block/$block")))
.rotationY(it[BlockRotationFreedom.HORIZONTAL.property].front.yRotationBlockstateNorth())
.build()
}
}
}
override fun getName(): String {
return "Battery Bank Model Provider"
}
}
class MatterBankProvider(event: GatherDataEvent) : BatteryBankProvider(event) {
@ -48,4 +45,8 @@ class MatterBankProvider(event: GatherDataEvent) : BatteryBankProvider(event) {
batteryPath = "block/battery/matter_capacitor"
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
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.state.properties.BlockStateProperties
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
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.CargoCrateBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
import ru.dbotthepony.mc.otm.block.entity.WorkerState
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.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.MNames
import ru.dbotthepony.mc.otm.registry.MRegistry
@ -28,48 +27,63 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
provider.ore(MBlocks.TRITANIUM_ORE)
provider.ore(MBlocks.TRITANIUM_RAW_BLOCK)
provider.block(MBlocks.TRITANIUM_INGOT_BLOCK)
provider.block(MBlocks.METAL_MESH)
provider.block(MBlocks.CHEMICAL_GENERATOR)
provider.block(MBlocks.MATTER_SCANNER)
provider.block(MBlocks.ITEM_MONITOR)
provider.block(MBlocks.HOLO_SIGN)
provider.exec {
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}")))
.rotationY(dir.toYRotBlockstate())
.rotationY(dir.front.yRotationBlockstateNorth())
.addModel()
.condition(BlockStateProperties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER)
.condition(RotatableMatteryBlock.FACING, dir)
.condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.end()
}
}
with(provider.getMultipartBuilder(MBlocks.MATTER_BOTTLER)) {
for (dir in RotatableMatteryBlock.FACING.possibleValues) {
for (enum in WorkerState.SEMI_WORKER_STATE.possibleValues) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "matter_bottler_${enum.name.lowercase()}")))
.rotationY(dir.toYRotBlockstate())
with(provider.getMultipartBuilder(MBlocks.ANDROID_CHARGER)) {
for (dir in BlockRotationFreedom.HORIZONTAL.possibleValues) {
for (part in AndroidChargerBlock.PART.possibleValues) {
part().modelFile(provider.models().getExistingFile(modLocation("block/${MNames.ANDROID_CHARGER}_${part.serializedName}")))
.rotationY(dir.front.yRotationBlockstateNorth())
.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)
.end()
}
}
for (dir in RotatableMatteryBlock.FACING.possibleValues) {
for (dir in BlockRotationFreedom.HORIZONTAL.possibleValues) {
for (enum in MatterBottlerBlock.SLOT_PROPERTIES) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "matter_bottler_${enum.name}_open")))
.rotationY(dir.toYRotBlockstate())
part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name}_open")))
.rotationY(dir.front.yRotationBlockstateNorth())
.addModel()
.condition(RotatableMatteryBlock.FACING, dir)
.condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.condition(enum, false)
.end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "matter_bottler_${enum.name}_closed")))
.rotationY(dir.toYRotBlockstate())
part().modelFile(provider.models().getExistingFile(modLocation("matter_bottler_${enum.name}_closed")))
.rotationY(dir.front.yRotationBlockstateNorth())
.addModel()
.condition(RotatableMatteryBlock.FACING, dir)
.condition(BlockRotationFreedom.HORIZONTAL.property, dir)
.condition(enum, true)
.end()
}
@ -80,12 +94,18 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
provider.block(MBlocks.MATTER_DECOMPOSER)
provider.block(MBlocks.MATTER_REPLICATOR)
provider.block(MBlocks.PLATE_PRESS)
provider.block(MBlocks.TWIN_PLATE_PRESS)
provider.block(MBlocks.GRAVITATION_STABILIZER)
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.MATTER_RECYCLER)
provider.block(MBlocks.MATTER_RECONSTRUCTOR)
provider.block(MBlocks.ENERGY_SERVO)
provider.block(MBlocks.COBBLESTONE_GENERATOR)
provider.block(MBlocks.ESSENCE_STORAGE)
provider.exec {
for (crate in MRegistry.CARGO_CRATES.allBlocks.values) {
@ -93,76 +113,75 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
return@forAllStates arrayOf(
ConfiguredModel.builder()
.modelFile(provider.models().getExistingFile(
ResourceLocation(
OverdriveThatMatters.MOD_ID, "${crate.registryName!!.path}_${if (it.getValue(
modLocation("${crate.registryName!!.path}_${if (it.getValue(
CargoCrateBlock.IS_OPEN)) "open" else "closed"}")
))
.rotationY(it.getValue(RotatableMatteryBlock.FACING).toYRotBlockstate())
.rotationY(it.getValue(BlockRotationFreedom.HORIZONTAL.property).front.yRotationBlockstateNorth())
.buildLast()
)
}
}
with(provider.getMultipartBuilder(MBlocks.STORAGE_BUS)) {
for (dir in net.minecraft.core.Direction.values()) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_bus")))
.rotationX(dir.toXRotBlockstate())
.rotationY(dir.toYRotBlockstate())
for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) {
part().modelFile(provider.models().getExistingFile(modLocation("storage_bus")))
.rotationX(dir.front.xRotationBlockstateNorth())
.rotationY(dir.front.yRotationBlockstateNorth())
.addModel()
.condition(RotatableMatteryBlock.FACING_FULL, dir)
.condition(BlockRotationFreedom.DIRECTIONAL.property, dir)
.end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_connection")))
.rotationX(dir.toXRotBlockstateInv())
.rotationY(dir.toYRotBlockstateInv())
part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
.rotationX(dir.front.xRotationBlockstateSouth())
.rotationY(dir.front.yRotationBlockstateSouth())
.addModel()
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.ordinal], true)
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
.end()
}
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_core")))
part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
.addModel().end()
}
with(provider.getMultipartBuilder(MBlocks.STORAGE_IMPORTER)) {
for (dir in net.minecraft.core.Direction.values()) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_importer")))
.rotationX(dir.toXRotBlockstate())
.rotationY(dir.toYRotBlockstate())
for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) {
part().modelFile(provider.models().getExistingFile(modLocation("storage_importer")))
.rotationX(dir.front.xRotationBlockstateNorth())
.rotationY(dir.front.yRotationBlockstateNorth())
.addModel()
.condition(RotatableMatteryBlock.FACING_FULL, dir)
.condition(BlockRotationFreedom.DIRECTIONAL.property, dir)
.end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_connection")))
.rotationX(dir.toXRotBlockstateInv())
.rotationY(dir.toYRotBlockstateInv())
part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
.rotationX(dir.front.xRotationBlockstateSouth())
.rotationY(dir.front.yRotationBlockstateSouth())
.addModel()
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.ordinal], true)
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
.end()
}
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_core")))
part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
.addModel().end()
}
with(provider.getMultipartBuilder(MBlocks.STORAGE_EXPORTER)) {
for (dir in net.minecraft.core.Direction.values()) {
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_exporter")))
.rotationX(dir.toXRotBlockstate())
.rotationY(dir.toYRotBlockstate())
for (dir in BlockRotationFreedom.DIRECTIONAL.possibleValues) {
part().modelFile(provider.models().getExistingFile(modLocation("storage_exporter")))
.rotationX(dir.front.xRotationBlockstateNorth())
.rotationY(dir.front.yRotationBlockstateNorth())
.addModel()
.condition(RotatableMatteryBlock.FACING_FULL, dir)
.condition(BlockRotationFreedom.DIRECTIONAL.property, dir)
.end()
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_connection")))
.rotationX(dir.toXRotBlockstateInv())
.rotationY(dir.toYRotBlockstateInv())
part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_connection")))
.rotationX(dir.front.xRotationBlockstateSouth())
.rotationY(dir.front.yRotationBlockstateSouth())
.addModel()
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.ordinal], true)
.condition(CableBlock.MAPPING_CONNECTION_PROP[dir.front]!!, true)
.end()
}
part().modelFile(provider.models().getExistingFile(ResourceLocation(OverdriveThatMatters.MOD_ID, "storage_cable_core")))
part().modelFile(provider.models().getExistingFile(modLocation("storage_cable_core")))
.addModel().end()
}
}

View File

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

View File

@ -1,18 +1,18 @@
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.state.BlockState
import net.minecraftforge.client.model.generators.BlockStateProvider
import net.minecraftforge.client.model.generators.ConfiguredModel
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.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.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.datagen.modLocation
import java.util.LinkedList
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 {
@Suppress("NAME_SHADOWING") var modelPath = modelPath
it.getValueNullable(RotatableMatteryBlock.FACING)?.let {
builder.rotationY(it.toYRotBlockstate())
it.getValueNullable(BlockRotationFreedom.HORIZONTAL.property)?.let {
builder.rotationY(it.front.yRotationBlockstateNorth())
}
it.getValueNullable(RotatableMatteryBlock.FACING_FULL)?.let {
builder.rotationY(it.toYRotBlockstate())
builder.rotationX(it.toXRotBlockstate())
it.getValueNullable(BlockRotationFreedom.DIRECTIONAL.property)?.let {
builder.rotationY(it.front.yRotationBlockstateNorth())
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 {
@ -41,7 +46,7 @@ private fun initialTransform(it: BlockState, modelPath: String, builder: Configu
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>()
fun exec(lambda: () -> Unit): MatteryBlockStateProvider {
@ -55,7 +60,7 @@ class MatteryBlockStateProvider(event: GatherDataEvent) : BlockStateProvider(eve
var modelPath = initialTransform(it, "block/${block.registryName!!.path}", builder)
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()
}

View File

@ -1,9 +1,7 @@
package ru.dbotthepony.mc.otm.datagen.items
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.DyeColor
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.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
@ -22,6 +20,9 @@ fun addItemModels(provider: MatteryItemModelProvider) {
}
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.TRITANIUM_ORE)
provider.block(MItems.TRITANIUM_STRIPED_BLOCK)
@ -29,6 +30,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.block(MItems.TRITANIUM_INGOT_BLOCK)
provider.block(MItems.ITEM_MONITOR)
provider.block(MItems.PHANTOM_ATTRACTOR)
provider.block(MItems.HOLO_SIGN)
MRegistry.VENT.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) {
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)
@ -53,6 +55,10 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.generated(MItems.PILL_HEAL)
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) {
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.CRAFTING_UPGRADE)
provider.generated(MItems.ExopackUpgrades.SMELTING_UPGRADE)
provider.generated(MItems.ExopackUpgrades.ENDER_UPGRADE)
provider.component(MItems.TRITANIUM_DUST)
provider.component(MItems.TRITANIUM_INGOT)
provider.component(MItems.TRITANIUM_NUGGET)
provider.resource(MItems.TRITANIUM_ORE_CLUMP)
provider.generated(MItems.EXOPACK_PROBE)
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.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_NORMAL, ResourceLocation(DataGen.MOD_ID, "item/matter_capacitor_tier2"))
provider.generated(MItems.MATTER_CAPACITOR_DENSE, ResourceLocation(DataGen.MOD_ID, "item/matter_capacitor_tier3"))
provider.generated(MItems.MATTER_CAPACITOR_BASIC, modLocation("item/matter_capacitor_tier1"))
provider.generated(MItems.MATTER_CAPACITOR_NORMAL, modLocation("item/matter_capacitor_tier2"))
provider.generated(MItems.MATTER_CAPACITOR_DENSE, modLocation("item/matter_capacitor_tier3"))
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_CAPACITOR)
provider.generated(MItems.QUANTUM_BATTERY_CREATIVE)
@ -100,6 +158,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.block(MItems.TRITANIUM_TRAPDOOR[null]!!, "tritanium_trapdoor_bottom")
for (color in DyeColor.values())
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_DECOMPOSER, "matter_decomposer_working")
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.TWIN_PLATE_PRESS, "twin_plate_press_idle")
provider.block(MItems.STORAGE_POWER_SUPPLIER, "storage_power_supplier")
provider.block(MItems.MATTER_RECYCLER, "matter_recycler_working")
provider.block(MItems.COBBLESTONE_GENERATOR, "cobblestone_generator")
provider.block(MItems.STORAGE_BUS)
provider.block(MItems.STORAGE_IMPORTER)
provider.block(MItems.STORAGE_EXPORTER)
for (item in MItems.TRITANIUM_ANVIL) {
provider.block(item)
}
for ((color, item) in MItems.CARGO_CRATE_MINECARTS) {
provider.generated(item)
}

View File

@ -1,15 +1,20 @@
package ru.dbotthepony.mc.otm.datagen.items
import net.minecraft.data.models.ItemModelGenerators
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.minecraftforge.client.model.generators.ItemModelProvider
import net.minecraftforge.client.model.generators.ModelBuilder
import net.minecraftforge.data.event.GatherDataEvent
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.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.modLocation
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>()
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, path: String) = exec { withExistingParent(item.registryName!!.path, ResourceLocation(DataGen.MOD_ID, "block/$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, modLocation("block/$path")) }
fun blocks(vararg items: 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)
}
fun generated(item: Item) = generated(item, ResourceLocation(DataGen.MOD_ID, "item/${item.registryName!!.path}"))
fun generated(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) }
fun KOT(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "block/ph_kitty")) }
fun generated(items: Collection<Item>) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) }
fun generatedBlock(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "block/${it.registryName!!.path}")) }
fun generatedBlockDecorative(vararg items: Item) = items.forEach { generated(it, ResourceLocation(DataGen.MOD_ID, "block/decorative/${it.registryName!!.path}")) }
fun handheld(vararg items: Item) = items.forEach { handheld(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) }
fun handheld(items: Collection<Item>) = items.forEach { handheld(it, ResourceLocation(DataGen.MOD_ID, "item/${it.registryName!!.path}")) }
fun generated(item: Item) = generated(item, modLocation("item/${item.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, modLocation("block/ph_kitty")) }
fun generated(items: Collection<Item>) = items.forEach { generated(it, modLocation("item/${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, modLocation("block/decorative/${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, modLocation("item/${it.registryName!!.path}")) }
fun generated(item: Item, prefix: String) = generated(item, ResourceLocation(DataGen.MOD_ID, "item/${prefix}${item.registryName!!.path}"))
fun generatedStrict(item: Item, path: String) = generated(item, ResourceLocation(DataGen.MOD_ID, "item/$path"))
fun handheld(item: Item, prefix: String) = handheld(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, modLocation("item/$path"))
fun handheld(item: Item, prefix: String) = handheld(item, modLocation("item/${prefix}${item.registryName!!.path}"))
fun component(item: Item) = generated(item, "component/")
fun components(vararg items: Item) = items.forEach(this::component)
@ -63,7 +68,7 @@ class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event
var i = 0
for (item in items) {
generated(item, ResourceLocation(DataGen.MOD_ID, "item/$prefix$i"))
generated(item, modLocation("item/$prefix$i"))
i++
}
}
@ -72,12 +77,27 @@ class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event
var i = 0
for (item in items) {
generated(item, ResourceLocation(DataGen.MOD_ID, "item/$prefix$i"))
generated(item, modLocation("item/$prefix$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 {
val ARMOR_TRIM_MATERIALS = listOf("quartz", "iron", "netherite", "redstone", "copper", "gold", "emerald", "diamond", "lapis", "amethyst")
val GENERATED = ResourceLocation("minecraft", "item/generated")
val HANDHELD = ResourceLocation("minecraft", "item/handheld")
private val LOGGER = LogManager.getLogger()

View File

@ -3,23 +3,25 @@ package ru.dbotthepony.mc.otm.datagen.lang
import ru.dbotthepony.mc.otm.registry.*
private fun decoratives(provider: MatteryLanguageProvider) {
provider.englishColors.add(MRegistry.VENT, "%s Vent")
provider.englishColors.add(MRegistry.VENT_ALTERNATIVE, "%s Alternative Vent")
with(provider.englishColors) {
add(MRegistry.VENT, "%s Vent")
add(MRegistry.VENT_ALTERNATIVE, "%s Alternative Vent")
provider.englishColors.add(MRegistry.TRITANIUM_BLOCK, "%s Tritanium Block")
provider.englishColors.add(MRegistry.TRITANIUM_STAIRS, "%s Tritanium Stairs")
provider.englishColors.add(MRegistry.TRITANIUM_SLAB, "%s Tritanium Slab")
provider.englishColors.add(MRegistry.TRITANIUM_WALL, "%s Tritanium Wall")
provider.englishColors.add(MRegistry.FLOOR_TILES, "%s Floor Tiles")
provider.englishColors.add(MRegistry.FLOOR_TILES_STAIRS, "%s Floor Tiles Stairs")
provider.englishColors.add(MRegistry.FLOOR_TILES_SLAB, "%s Floor Tiles Slab")
provider.englishColors.add(MRegistry.UNREFINED_FLOOR_TILES, "Unrefined %s Floor Tiles")
add(MRegistry.TRITANIUM_BLOCK, "%s Tritanium Block")
add(MRegistry.TRITANIUM_STAIRS, "%s Tritanium Stairs")
add(MRegistry.TRITANIUM_SLAB, "%s Tritanium Slab")
add(MRegistry.TRITANIUM_WALL, "%s Tritanium Wall")
add(MRegistry.FLOOR_TILES, "%s Floor Tiles")
add(MRegistry.FLOOR_TILES_STAIRS, "%s Floor Tiles Stairs")
add(MRegistry.FLOOR_TILES_SLAB, "%s Floor Tiles Slab")
add(MRegistry.UNREFINED_FLOOR_TILES, "Unrefined %s Floor Tiles")
provider.englishColors.add(MRegistry.INDUSTRIAL_GLASS, "%s Stained Industrial Glass")
provider.englishColors.add(MRegistry.INDUSTRIAL_GLASS_PANE, "%s Stained Industrial Glass Pane")
add(MRegistry.INDUSTRIAL_GLASS, "%s Stained Industrial Glass")
add(MRegistry.INDUSTRIAL_GLASS_PANE, "%s Stained Industrial Glass Pane")
provider.englishColors.add(MRegistry.CARGO_CRATES, "%s Cargo Crate")
provider.englishColors.add(MRegistry.DECORATIVE_CRATE, "%s Container Block")
add(MRegistry.CARGO_CRATES, "%s Cargo Crate")
add(MRegistry.DECORATIVE_CRATE, "%s Container Block")
}
with (provider.english) {
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")
}
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) {
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.TRITANIUM_BLOCK.block, "Tritanium Block")
add(MRegistry.TRITANIUM_STAIRS.block, "Tritanium Stairs")
@ -64,6 +66,7 @@ private fun decoratives(provider: MatteryLanguageProvider) {
add(MRegistry.VENT.block, "Vent")
add(MRegistry.VENT_ALTERNATIVE.block, "Alternative Vent")
for ((block, colors) in MRegistry.TRITANIUM_STRIPED_BLOCK.blocksWithColor) {
val (base, stripe) = colors
@ -114,6 +117,17 @@ private fun sounds(provider: MatteryLanguageProvider) {
private fun misc(provider: MatteryLanguageProvider) {
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("power_cost_per_use", "Power cost per use: %s")
@ -125,24 +139,34 @@ private fun misc(provider: MatteryLanguageProvider) {
gui("recipe.ticks", "%s Ticks")
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_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.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.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.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.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_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")
@ -150,15 +174,16 @@ private fun misc(provider: MatteryLanguageProvider) {
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.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.granted2", "After you raise your finger, fingerprint reader glows very bright.")
misc("exopack.granted3", "Then, the fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.")
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.granted5", "As whatever shrouded you takes final form, you feel it binds to your soul.")
misc("exopack.granted6", "INITIALIZATION SEQUENCE COMPLETE. WELCOME, USER %s")
misc("exopack.granted7", "You are now permanently equipped with four dimensional omni-present Exopack.")
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("exopack.granted1", "As you keep pressing on the fingerprint reader, probe disappears.")
misc("exopack.granted2", "After a moment, you are getting pierced into back multiple times...")
misc("exopack.granted3", "As pain signals ease away, you find a new 'friend' on your back: the Exopack.")
misc("exopack.granted4", "This device provides access to personal pocket dimension in 4th space.")
misc("exopack.granted5", "Scavenge for or craft modules to upgrade your Exopack.")
misc("exopack.granted6", "The Exopack itself also exists in 4th dimension, it does not prevent wearing armor.")
misc("exopack.granted7", "However, despite existing in 4th dimension, items stored in it are still dropped upon unfortunate event.")
misc("dumping_matter_registry", "Dumping 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("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.none", "%s %s")
misc("suffix.kilo", "%s k%s")
misc("suffix.mega", "%s M%s")
misc("suffix.giga", "%s G%s")
@ -190,6 +216,27 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("suffix.zepto", "%s z%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.mega", "M")
misc("suffix_raw.giga", "G")
@ -209,31 +256,24 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("suffix_raw.zepto", "z")
misc("suffix_raw.yocto", "y")
misc("container.matter_panel.increase_by", "+%s")
misc("container.matter_panel.decrease_by", "-%s")
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.infinite.storage", "Stored energy: ∞ / ∞")
misc("item.power.infinite.throughput", "Max I/O: ∞ / ∞")
misc("item.power.passed", "Passed energy: %s")
misc("item.power.received", "Received energy: %s")
misc("item.power.average", "Average throughput: %s/t")
misc("item.power.last_20_ticks", "Last second: %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.throughput", "Max throughput: %s / %s")
misc("item.power.throughput_mono", "Max throughput: %s")
misc("item.power.infinity", "Infinity MtJ")
misc("item.power.storage0", "Stored energy: %s")
misc("item.power.throughput", "Max I/O: %s / %s")
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", "Work ticks: %s / %s")
@ -241,11 +281,14 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("item.block.stored_battery", "Battery: %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.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("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_android", "Does nothing to androids.")
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", "Nothing happened, but you feel... exhausted?.. Maybe get rest.")
misc("pill.message_finish", "§kONE OF US ONE OF US ONE OF US")
misc("gui.power.percentage_level", "Energy level: %s%%")
misc("gui.level", "%s / %s")
misc("gui.power.name", "MtJ")
gui("power.percentage_level", "Energy level: %s%%")
gui("level", "%s / %s")
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%%")
misc("gui.progress_widget_stuck", "The machine can not work, check configuration")
gui("power.burn_time", "Burn time left: %s ticks")
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%%")
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")
gui("total_raw", "Total:")
misc("gui.filter.is_whitelist", "Is Whitelist")
misc("gui.filter.match_nbt", "Match NBT")
misc("gui.filter.match_tag", "Match Tag")
gui("matter.percentage_level", "Matter level: %s%%")
gui("matter.format", "Matter: %s")
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%%")
misc("gui.pattern.format", "Stored patterns: %s / %s")
gui("android_research", "Research Tree")
misc("gui.redstone.ignored", "Redstone mode: Ignored")
misc("gui.redstone.low", "Redstone mode: Low")
misc("gui.redstone.high", "Redstone mode: High")
gui("pattern.percentage_level", "Fill level: %s%%")
gui("pattern.format", "Stored patterns: %s / %s")
misc("gui.redstone.ignored.description", "Redstone signal does not affect machine's function")
misc("gui.redstone.low.description", "Machine work if no redstone signal is present")
misc("gui.redstone.high.description", "Machine work only if any redstone signal is present")
gui("redstone.ignored", "Redstone mode: Ignored")
gui("redstone.low", "Redstone mode: Low")
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.strength", "Gravitation strength: %s")
@ -324,14 +372,12 @@ private fun misc(provider: MatteryLanguageProvider) {
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.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_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_hawking_radiation", "%1\$s discovered Hawking radiation")
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_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_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.item", "%1\$s blew fuzes of %2\$s using %3\$s")
death("otm_emp.player", "%2\$s blew fuzes of %1\$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("${MRegistry.DAMAGE_EXOPACK_PROBE_ID}.player", "%1 couldn't handle spinal surgery whilst fighting %2\$s")
death("otm_explosive_hammer", "%1\$s's fun time with hammer is over")
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) {
with(provider.english) {
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.MATTER_DECOMPOSER, "Matter Decomposer")
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_BOTTLER, "Matter Bottler")
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")
@ -381,12 +453,20 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.DRIVE_RACK, "Condensation Drive Rack")
add(MBlocks.ITEM_MONITOR, "Item Monitor")
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.ENERGY_SERVO, "Energy Servo")
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_STAIRS, "Tritanium Striped Stairs")
@ -402,16 +482,14 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.STORAGE_IMPORTER, "Storage Importer")
add(MBlocks.STORAGE_EXPORTER, "Storage Exporter")
add(MBlocks.GRAVITATION_STABILIZER, "Gravitation Stabilizer")
add(MBlocks.GRAVITATION_STABILIZER_LENS, "Gravitation Stabilizer Lens")
add(MBlocks.GRAVITATION_STABILIZER, "desc", "Reduces gravitation effects of singularities")
add(MBlocks.GRAVITATION_STABILIZER, "desc2", "Requires no power to operate")
add(MBlocks.GRAVITATION_STABILIZER, "desc3", "Keep in mind the effect of multiple stabilizers produce exponentially increasing result")
add(MBlocks.GRAVITATION_STABILIZER, "desc4", "Too weak gravitation field will cause singularity to melt and evaporate away very fast")
add(MBlocks.GRAVITATION_STABILIZER, "Spacetime Normalizer")
add(MBlocks.GRAVITATION_STABILIZER_LENS, "Spacetime Normalizer Lens")
add(MBlocks.GRAVITATION_STABILIZER, "desc", "Reduces spacetime distortion effects of singularities")
add(MBlocks.GRAVITATION_STABILIZER, "desc2", "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.PHANTOM_ATTRACTOR, "Phantom Attractor")
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, "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]!!, "description0", "High blast resistance door with redstone latch...")
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) {
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.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Creative Exopack Inventory 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, "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, "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, "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, "desc", "Scans singularities for their properties")
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_SENSOR, "Gravitation Field Sensor")
add(MItems.PORTABLE_GRAVITATION_STABILIZER, "Portable Gravitation Stabilizer")
add(MItems.GRAVITATION_FIELD_LIMITER, "Spacetime Distortion Limiter")
add(MItems.GRAVITATION_FIELD_SENSOR, "Spacetime Sensor")
add(MItems.PORTABLE_GRAVITATION_STABILIZER, "Portable Spacetime Normalizer")
add(MItems.BATTERY_CRUDE, "Crude 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_CAPACITOR, "Capacitor 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_AXE, "Tritanium Axe")
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_CHESTPLATE, "Tritanium Chestplate")
add(MItems.TRITANIUM_PANTS, "Tritanium Leggings")
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_INGOT, "Tritanium Ingot")
add(MItems.TRITANIUM_NUGGET, "Tritanium Nugget")
add(MItems.MATTER_IO_PORT, "Matter IO Port")
add(MItems.MATTER_TRANSFORM_MATRIX, "Matter Transformation Matrix")
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.QUANTUM_TRANSCEIVER, "Quantum Transceiver")
add(MItems.ELECTROMAGNET, "Electromagnet")
add(MItems.ELECTROMOTOR, "Electromotor")
add(MItems.MIRROR_COMPOUND, "Mirror Compound")
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, "description2", "Allows collapse of black holes")
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 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, "description4", "The explosion %s be contained by %s. Do not even attempt to contain it.")
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, "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.NANOBOTS_ARMOR, "Nanobots Armor")
add(AndroidFeatures.ITEM_MAGNET, "Item Magnet")
add(AndroidFeatures.SWIM_BOOSTERS, "Swim Boosters")
add(AndroidFeatures.STEP_ASSIST, "Step Assist")
add(AndroidFeatures.PHANTOM_ATTRACTOR, "Phantom Attractor")
add(AndroidFeatures.JUMP_BOOST, "Jump Boost")
add(AndroidFeatures.ENDER_TELEPORTER, "Ender Teleporter")
}
@ -585,6 +743,35 @@ private fun androidFeatures(provider: MatteryLanguageProvider) {
private fun gui(provider: MatteryLanguageProvider) {
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.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")
@ -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("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)
gui(provider)
jade(provider)
with(provider.english) {
add("itemGroup.otm", "Overdrive That Matters")
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 it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import net.minecraft.data.DataGenerator
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.TranslatableContents
import net.minecraft.sounds.SoundEvent
@ -17,7 +18,10 @@ import net.minecraft.world.level.block.Block
import net.minecraftforge.common.data.LanguageProvider
import ru.dbotthepony.mc.otm.OverdriveThatMatters
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.core.TranslatableComponent
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock
private fun researchString(key: AndroidResearchType): String {
@ -35,7 +39,7 @@ private fun researchString(key: AndroidResearchType): String {
}
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() {}
}
@ -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")
inner class Builder(language: String) {
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: 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) {
val path = "$path."
constructor(vararg path: String) : this(path.joinToString("."))
@ -382,8 +413,57 @@ class MatteryLanguageProvider(private val gen: DataGenerator) {
"Black",
)
val russianColors = Colors("ru_ru",
"Белый",
"Оранжевый",
"Маджентовый",
"Светло Синий",
"Жёлтый",
"Лаймовый",
"Розовый",
"Серый",
"Светло Серый",
"Циановый",
"Пурпурный",
"Синий",
"Коричневый",
"Зелёный",
"Красный",
"Чёрный",
)
val english by lazy { Builder("en_us") }
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)
}

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.util.StringRepresentable
import net.minecraft.world.item.Rarity
import net.minecraft.world.level.ItemLike
import net.minecraft.world.level.block.Block
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.UniformGenerator
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.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 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) {
add(LootItem.lootTableItem(item).also(configurator))

View File

@ -51,7 +51,7 @@ fun PlainLootAppender(
vararg items: Pair<ItemStack, Double>
) = 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>()
fun lambda(lambda: (LootModifiers) -> Unit) {

View File

@ -1,18 +1,21 @@
package ru.dbotthepony.mc.otm.datagen.loot
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.valueproviders.UniformInt
import net.minecraft.world.entity.EntityType
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.predicates.LootItemCondition
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.HasExoPackCondition
import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition
import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly
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
@Suppress("FunctionName")
@ -25,60 +28,102 @@ fun LootTableIdCondition(location: ResourceLocation): LootItemCondition {
return LootTableIdCondition.Builder(location).build()
}
private fun exosuitModifiers(it: LootModifiers) {
it.add("dungeon_exosuit", LootPoolAppender(
fun addLootModifiers(it: LootModifiers) {
it.add("dungeon_exopack", LootPoolAppender(
arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
chanceCondition(0.2)
apply(RandomizerFunction.COMMON)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(6, 9)))
},
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
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)),
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(
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(
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(
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) {
exosuitModifiers(it)
singleItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
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(
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, 1) to 0.75,
))
it.add("mineshaft_pill", PlainLootAppender(
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, 1) to 0.4,
))
@ -92,7 +137,7 @@ fun addLootModifiers(it: LootModifiers) {
it.add("desert_pyramid_pill", PlainLootAppender(
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,
))
@ -103,7 +148,7 @@ fun addLootModifiers(it: LootModifiers) {
it.add("end_city_modifications", PlainLootAppender(
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_OBLIVION, 1) to 0.5,
ItemStack(MItems.ZPM_BATTERY, 1) to 0.005,

View File

@ -3,12 +3,12 @@
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.Reference2ObjectFunction
import net.minecraft.advancements.critereon.StatePropertiesPredicate
import net.minecraft.data.DataGenerator
import net.minecraft.data.loot.LootTableProvider
import net.minecraft.data.loot.LootTableSubProvider
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.ItemLike
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.LootContextParamSets
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 ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import java.util.function.BiConsumer
import java.util.function.Consumer
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>
import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.data.loot.CopyTileNbtFunction
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)
}
private val basicTags = arrayOf(
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) {
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 */) {
private val providersTable = Reference2ObjectArrayMap<LootContextParamSet, HashMap<ResourceLocation, () -> LootTable.Builder>>()
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" }
}
override fun getTables(): List<LootTuple> {
override fun getTables(): List<SubProviderEntry> {
return providersTable.entries.stream().map { entry ->
Pair.of(LootTableCallbackProvider {
LootTableCallback {
SubProviderEntry({
LootTableSubProvider {
for ((id, callback) in entry.value) {
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) {
add(LootItem.lootTableItem(block).also {
it.apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY).also {
it.copy("Name", "BlockEntityTag.Name")
f(it)
})
it.apply(CopyTileNbtFunction(filterTags.stream()))
})
}
}
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.parameters.LootContextParamSets
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.registry.MBlocks
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.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_STRIPED_BLOCK) { 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.METAL_BEAM) { 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)
lootTables.dropsSelf(door) { condition(ExplosionCondition.survivesExplosion()) }
@ -129,40 +130,42 @@ fun addLootTables(lootTables: LootTables) {
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_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,
EnergyCounterBlockEntity.IO_LIMIT_KEY, EnergyCounterBlockEntity.PASSED_ENERGY_KEY,
EnergyCounterBlockEntity.POWER_HISTORY_KEY, EnergyCounterBlockEntity.POWER_HISTORY_POINTER_KEY)
lootTables.tile(MBlocks.STORAGE_BUS)
lootTables.tile(MBlocks.STORAGE_IMPORTER)
lootTables.tile(MBlocks.STORAGE_EXPORTER)
lootTables.tile(MBlocks.STORAGE_POWER_SUPPLIER)
lootTables.tile(MBlocks.DRIVE_RACK)
lootTables.tile(MBlocks.CHEMICAL_GENERATOR,
ChemicalGeneratorBlockEntity.WORK_TICKS_KEY,
ChemicalGeneratorBlockEntity.WORK_TICKS_TOTAL_KEY,
ENERGY_KEY,
REDSTONE_SIGNAL_KEY,
REDSTONE_SETTING_KEY,
)
lootTables.tile(MBlocks.MATTER_DECOMPOSER)
lootTables.tile(MBlocks.MATTER_REPLICATOR)
lootTables.tile(MBlocks.MATTER_RECYCLER)
lootTables.tile(MBlocks.MATTER_SCANNER)
lootTables.tile(MBlocks.PLATE_PRESS)
lootTables.tile(MBlocks.TWIN_PLATE_PRESS)
lootTables.dropsSelf(MBlocks.STORAGE_CABLE)
lootTables.poweredTile(MBlocks.ANDROID_STATION)
lootTables.basicTile(MBlocks.BATTERY_BANK)
lootTables.poweredTile(MBlocks.DRIVE_VIEWER)
lootTables.tile(MBlocks.POWERED_FURNACE)
lootTables.tile(MBlocks.POWERED_SMOKER)
lootTables.tile(MBlocks.POWERED_BLAST_FURNACE)
lootTables.poweredTile(MBlocks.STORAGE_BUS, TileNbtCopy(FILTER_KEY))
lootTables.poweredTile(MBlocks.STORAGE_IMPORTER, TileNbtCopy(FILTER_KEY))
lootTables.poweredTile(MBlocks.STORAGE_EXPORTER, TileNbtCopy(FILTER_KEY))
lootTables.poweredTile(MBlocks.STORAGE_POWER_SUPPLIER, TileNbtCopy(StoragePowerSupplierBlockEntity.POWER_PASSED_KEY))
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))
lootTables.tile(MBlocks.MATTER_PANEL)
lootTables.tile(MBlocks.PATTERN_STORAGE)
lootTables.tile(MBlocks.MATTER_CAPACITOR_BANK)
lootTables.tile(MBlocks.MATTER_BOTTLER)
}

View File

@ -9,30 +9,5 @@ fun addBlockModels(provider: MatteryBlockModelProvider) {
resourceCubeAll(MBlocks.TRITANIUM_RAW_BLOCK)
resourceCubeAll(MBlocks.DEEPSLATE_TRITANIUM_ORE)
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
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.DoorBlock
import net.minecraftforge.client.model.generators.ModelProvider
import net.minecraftforge.client.model.generators.BlockModelProvider
import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation
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) {
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) {
fun exec(callback: (MatteryBlockModelProvider) -> Unit) {
callbacks.add(callback)
}
@ -52,9 +20,7 @@ sealed class MatteryModelProvider(event: GatherDataEvent, folder: String) : Mode
callback(this)
}
}
}
class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(event, BLOCK_FOLDER) {
override fun getName(): String {
return "Block Models: $modid"
}
@ -62,7 +28,7 @@ class MatteryBlockModelProvider(event: GatherDataEvent) : MatteryModelProvider(e
fun decorativeGlassAll(blocks: Collection<Block>) {
for (block in blocks) {
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) {
for (block in blocks) {
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) {
for (block in blocks) {
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) {
for (block in blocks) {
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) {
for (block in blocks) {
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>) {
for (block in blocks) {
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) {
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) {
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) {
for (block in blocks) {
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
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.tags.ItemTags
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient
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.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.core.registryName
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>) {
MatteryRecipe(MRegistry.CARGO_CRATES.item)
.row(MItemTags.TRITANIUM_PLATES, Tags.Items.CHESTS, MItemTags.TRITANIUM_PLATES)
fun addCraftingTableRecipes(consumer: RecipeOutput) {
val machinesCategory = RecipeCategory.DECORATIONS
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(Tags.Items.CHESTS)
.build(consumer)
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(dye.tag)
.unlockedBy(MRegistry.CARGO_CRATES.allItems.entries.stream().filter { it.key != dye }.map { it.value })
.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)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.save(consumer)
ShapelessRecipeBuilder(MItems.TRITANIUM_INGOT, 9)
ShapelessRecipeBuilder(RecipeCategory.MISC, MItems.TRITANIUM_INGOT, 9)
.requires(Ingredient.of(MItemTags.TRITANIUM_INGOTS_STORAGE))
.unlockedBy(MItemTags.TRITANIUM_INGOTS_STORAGE)
.save(consumer, modLocation("tritanium_ingot_from_storage"))
ShapelessRecipeBuilder(MItems.ENERGY_COUNTER, 1)
ShapelessRecipeBuilder(machinesCategory, MItems.ENERGY_COUNTER, 1)
.requires(MItems.ENERGY_COUNTER)
.unlockedBy(MItems.ENERGY_COUNTER)
.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(MItemTags.TRITANIUM_INGOTS, Items.BLAST_FURNACE, MItemTags.TRITANIUM_INGOTS)
.row(MItemTags.PISTONS, MItemTags.TRITANIUM_INGOTS, MItemTags.PISTONS)
@ -53,14 +62,23 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer)
MatteryRecipe(MBlocks.PLATE_PRESS)
MatteryRecipe(MBlocks.PLATE_PRESS, category = machinesCategory)
.rowB(MItemTags.PISTONS)
.rowB(MItems.MACHINE_FRAME)
.rowAC(MItemTags.PISTONS, MItemTags.PISTONS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItems.ELECTRIC_PARTS)
.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)
.row(MItemTags.ADVANCED_CIRCUIT, MItemTags.TRITANIUM_PLATES, MItemTags.ADVANCED_CIRCUIT)
.rowAC(MItemTags.ADVANCED_CIRCUIT, MItemTags.ADVANCED_CIRCUIT)
@ -68,7 +86,7 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.build(consumer)
// Машины
MatteryRecipe(MItems.MATTER_RECYCLER)
MatteryRecipe(MItems.MATTER_RECYCLER, category = machinesCategory)
.row(MItems.MATTER_CAPACITOR_PARTS, Items.HOPPER, MItemTags.BASIC_CIRCUIT)
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
.row(MItems.MATTER_CABLE, MItems.MATTER_IO_PORT, MItems.MATTER_CABLE)
@ -76,21 +94,21 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.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(MItemTags.IRON_PLATES, MItems.MACHINE_FRAME, MItemTags.IRON_PLATES)
.row(MItems.MATTER_CABLE, MItems.MATTER_IO_PORT, MItems.MATTER_CABLE)
.unlockedBy(MItems.MATTER_CABLE)
.build(consumer)
MatteryRecipe(MItems.BATTERY_BANK)
MatteryRecipe(MItems.BATTERY_BANK, category = machinesCategory)
.row(Tags.Items.GLASS, MItemTags.IRON_PLATES, Tags.Items.GLASS)
.row(MItemTags.IRON_PLATES, MItems.MACHINE_FRAME, MItemTags.IRON_PLATES)
.row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS)
.unlockedBy(MItems.ENERGY_BUS)
.build(consumer)
MatteryRecipe(MItems.GRAVITATION_STABILIZER)
MatteryRecipe(MItems.GRAVITATION_STABILIZER, category = machinesCategory)
.row(MItemTags.ADVANCED_CIRCUIT, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.ADVANCED_CIRCUIT)
.row(MItems.MATTER_TRANSFORM_MATRIX, MItems.MACHINE_FRAME, MItems.MATTER_TRANSFORM_MATRIX)
.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)
.build(consumer)
MatteryRecipe(MItems.PORTABLE_GRAVITATION_STABILIZER)
MatteryRecipe(MItems.PORTABLE_GRAVITATION_STABILIZER, category = RecipeCategory.COMBAT)
.rowB(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)
@ -106,150 +124,347 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.unlockedBy(MItems.GRAVITATION_FIELD_SENSOR)
.build(consumer)
MatteryRecipe(MItems.GRAVITATION_FIELD_SENSOR)
MatteryRecipe(MItems.GRAVITATION_FIELD_SENSOR, category = RecipeCategory.MISC)
.rowB(MItemTags.BASIC_CIRCUIT)
.row(MItemTags.TRITANIUM_PLATES, MItems.ELECTROMAGNET, MItemTags.TRITANIUM_PLATES)
.rowB(MItemTags.IRON_PLATES)
.unlockedBy(MItems.ELECTROMAGNET)
.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(MItemTags.GOLD_WIRES, MItems.QUANTUM_TRANSCEIVER, MItemTags.GOLD_WIRES)
.rowB(MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.QUANTUM_TRANSCEIVER)
.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.GOLD_WIRES, MItems.GRAVITATION_FIELD_SENSOR, MItemTags.ADVANCED_CIRCUIT)
.rowAC(Tags.Items.DUSTS_GLOWSTONE, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.GRAVITATION_FIELD_SENSOR)
.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(MItemTags.TRITANIUM_PLATES, MItems.QUANTUM_TRANSCEIVER, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, ItemTags.BEDS, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.QUANTUM_TRANSCEIVER)
.build(consumer)
MatteryRecipe(MItems.QUANTUM_TRANSCEIVER, 2)
MatteryRecipe(MItems.QUANTUM_TRANSCEIVER, 2, category = RecipeCategory.MISC)
.rowAC(MItemTags.COPPER_WIRES, MItemTags.COPPER_WIRES)
.row(MItemTags.GOLD_WIRES, Tags.Items.ENDER_PEARLS, MItemTags.GOLD_WIRES)
.row(MItemTags.GOLD_WIRES, MItems.ELECTROMAGNET, MItemTags.GOLD_WIRES)
.unlockedBy(Tags.Items.ENDER_PEARLS)
.build(consumer)
MatteryRecipe(MItems.ELECTROMAGNET)
MatteryRecipe(MItems.ELECTROMAGNET, category = RecipeCategory.MISC)
.row(MItemTags.COPPER_WIRES, Tags.Items.INGOTS_IRON, MItemTags.COPPER_WIRES)
.unlockedBy(Tags.Items.ENDER_PEARLS)
.unlockedBy(Tags.Items.INGOTS_IRON)
.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.ENERGY_BUS, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItems.ENERGY_BUS)
.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(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES)
.unlockedBy(MItemTags.IRON_PLATES)
.unlockedBy(Tags.Items.GLASS_PANES_COLORLESS)
.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)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItemTags.TRITANIUM_PLATES)
MatteryRecipe(MItems.TRITANIUM_HELMET, category = RecipeCategory.COMBAT)
.setUpgradeSource(Items.LEATHER_HELMET)
.addUpgradeOps(
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)
MatteryRecipe(MItems.TRITANIUM_PANTS)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES)
.rowAC(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItemTags.TRITANIUM_PLATES)
MatteryRecipe(MItems.TRITANIUM_PANTS, category = RecipeCategory.COMBAT)
.setUpgradeSource(Items.LEATHER_LEGGINGS)
.addUpgradeOps(
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_LEGGINGS, MItemTags.REINFORCED_TRITANIUM_PLATES)
.rowAC(MItemTags.REINFORCED_TRITANIUM_PLATES, MItemTags.REINFORCED_TRITANIUM_PLATES)
.unlockedBy(MItemTags.REINFORCED_TRITANIUM_PLATES)
.build(consumer)
MatteryRecipe(MItems.TRITANIUM_CHESTPLATE)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItemTags.TRITANIUM_PLATES)
MatteryRecipe(MItems.TRITANIUM_CHESTPLATE, category = RecipeCategory.COMBAT)
.setUpgradeSource(Items.LEATHER_CHESTPLATE)
.addUpgradeOps(
UpgradeRecipe.Direct("display"),
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)
MatteryRecipe(MItems.TRITANIUM_BOOTS)
.rowAC(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.IRON_PLATES, MItemTags.TRITANIUM_PLATES)
.unlockedBy(MItemTags.TRITANIUM_PLATES)
MatteryRecipe(MItems.TRITANIUM_BOOTS, category = RecipeCategory.COMBAT)
.setUpgradeSource(Items.LEATHER_BOOTS)
.addUpgradeOps(
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)
// простые батарейки
MatteryRecipe(MItems.BATTERY_CRUDE)
MatteryRecipe(MItems.BATTERY_CRUDE, category = RecipeCategory.MISC)
.rowB(Tags.Items.DUSTS_REDSTONE)
.rowB(Tags.Items.CROPS_POTATO)
.rowB(Tags.Items.INGOTS_IRON)
.build(consumer)
MatteryRecipe(MItems.BATTERY_BASIC)
MatteryRecipe(MItems.BATTERY_BASIC, category = RecipeCategory.MISC)
.rowAC(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE)
.rowB(MItems.ELECTRIC_PARTS)
.rowB(MItemTags.IRON_PLATES)
.build(consumer)
MatteryRecipe(MItems.BATTERY_NORMAL)
MatteryRecipe(MItems.BATTERY_NORMAL, category = RecipeCategory.MISC)
.rowB(MItems.ELECTRIC_PARTS)
.row(MItemTags.COPPER_WIRES, MItemTags.IRON_PLATES, MItemTags.COPPER_WIRES)
.row(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE)
.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(MItemTags.GOLD_WIRES, MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES)
.row(Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE, Tags.Items.DUSTS_REDSTONE)
.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(MItemTags.GOLD_WIRES, MItemTags.TRITANIUM_PLATES, MItemTags.GOLD_WIRES)
.row(MItemTags.GOLD_WIRES, Tags.Items.DUSTS_REDSTONE, MItemTags.GOLD_WIRES)
.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(MItemTags.TRITANIUM_PLATES, Tags.Items.ENDER_PEARLS, MItemTags.TRITANIUM_PLATES)
.rowAC(Tags.Items.GEMS_DIAMOND, Tags.Items.GEMS_DIAMOND)
.build(consumer)
// станция андроида
MatteryRecipe(MItems.ANDROID_STATION)
MatteryRecipe(MItems.ANDROID_STATION, category = machinesCategory)
.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.ELECTRIC_PARTS, MItemTags.TRITANIUM_PLATES)
.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)
.row(MItems.BATTERY_CAPACITOR, MItems.TRITANIUM_SWORD, MItemTags.ADVANCED_CIRCUIT)
.unlockedBy(MItems.BATTERY_CAPACITOR)
.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.CRAFTING_TABLES, MItems.QUANTUM_TRANSCEIVER, MItemTags.CRAFTING_TABLES)
.row(MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES, MItemTags.TRITANIUM_PLATES)
.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
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.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.OverdriveThatMatters
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.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.function.Consumer
private fun stairs(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) {
MatteryRecipe(result, 4)
private fun stairs(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
MatteryRecipe(result, 4, category = RecipeCategory.BUILDING_BLOCKS)
.rowA(base)
.rowAB(base, base)
.row(base, base, base)
.unlockedBy(base)
.build(consumer)
.build(consumer, modLocation("decorative/stairs/${base.asItem().registryName!!.path}"))
}
private fun slab(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) {
MatteryRecipe(result, 6)
private fun slab(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
MatteryRecipe(result, 6, category = RecipeCategory.BUILDING_BLOCKS)
.row(base, base, base)
.unlockedBy(base)
.build(consumer)
.build(consumer, modLocation("decorative/slabs/${base.asItem().registryName!!.path}"))
}
private fun wall(base: ItemLike, result: ItemLike, consumer: Consumer<FinishedRecipe>) {
MatteryRecipe(result, 6)
private fun wall(base: ItemLike, result: ItemLike, consumer: RecipeOutput) {
MatteryRecipe(result, 6, category = RecipeCategory.BUILDING_BLOCKS)
.row(base, base, base)
.row(base, base, 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
.stonecutting(Ingredient.of(base), result, amount)
.stonecutting(Ingredient.of(base), RecipeCategory.BUILDING_BLOCKS, result, amount)
.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)
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)
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)
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) {
MatteryRecipe(unrefinedItem, 24)
@ -72,16 +69,32 @@ fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: Consumer<Fi
.row(Items.SAND, color.tag, Items.SAND)
.row(Items.CLAY, Items.SAND, 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) {
SimpleCookingRecipeBuilder.smelting(
Ingredient.of(MRegistry.UNREFINED_FLOOR_TILES.items[color]!!),
RecipeCategory.BUILDING_BLOCKS,
refinedItem,
0.15f,
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) {
@ -111,86 +124,91 @@ fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: Consumer<Fi
val original = MRegistry.TRITANIUM_BLOCK.items[base]!!
MatteryRecipe(item, 8)
MatteryRecipe(item, 8, category = RecipeCategory.BUILDING_BLOCKS)
.row(original, original, original)
.row(original, stripe.tag, original)
.row(original, original, 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)
.row(Tags.Items.INGOTS_IRON, Tags.Items.COBBLESTONE, Tags.Items.INGOTS_IRON)
.rowBC(Tags.Items.INGOTS_IRON, Tags.Items.DYES_BLACK)
.unlockedBy(Tags.Items.INGOTS_IRON)
.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)
.row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS)
.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)
.row(MItemTags.TRITANIUM_INGOTS, Items.IRON_BARS, MItemTags.TRITANIUM_INGOTS)
.rowB(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
.build(consumer, modLocation("decorative/vent/default"))
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, color.tag, MRegistry.VENT.item)
.row(MRegistry.VENT.item, MRegistry.VENT.item, MRegistry.VENT.item)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.unlockedBy(color.tag)
.build(consumer)
.build(consumer, modLocation("decorative/vent/${color.name.lowercase()}"))
}
for ((color, item) in MRegistry.VENT_ALTERNATIVE.allItems) {
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(
OverdriveThatMatters.MOD_ID, "${other.registryName!!.path}_from_alt"))
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, item, 1).requires(other)
.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)
.row(Tags.Items.INGOTS_IRON, Tags.Items.COBBLESTONE, Tags.Items.INGOTS_IRON)
.rowB(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) {
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, color.tag, MRegistry.DECORATIVE_CRATE.item)
.row(MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.item, 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) {
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, color.tag, MRegistry.TRITANIUM_BLOCK.item)
.row(MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.item)
.unlockedBy(MRegistry.TRITANIUM_BLOCK.item)
.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(MItemTags.TRITANIUM_PLATES)
.unlockedBy("has_plate", has(MItemTags.TRITANIUM_PLATES))
.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)
.pattern("###").pattern("###")
.unlockedBy("has_tritanium_glass", has(MRegistry.INDUSTRIAL_GLASS.item))
@ -221,97 +239,138 @@ fun addDecorativesRecipes(provider: MatteryRecipeProvider, consumer: Consumer<Fi
val mappedVanilla = mappingUpgradeVanilla[color]!!
// обычная покраска
ShapelessRecipeBuilder(item, 8)
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, item, 8)
.requires(MRegistry.INDUSTRIAL_GLASS.item, 8)
.requires(color.tag)
.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(MItemTags.TRITANIUM_PLATES)
.unlockedBy("has_plate", has(MItemTags.TRITANIUM_PLATES))
.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)
.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)
ShapedRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, paneItem, 16)
.define('#', item)
.pattern("###").pattern("###")
.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)
.unlockedBy(MItems.LABORATORY_LAMP_INVERTED)
.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)
.unlockedBy(MItems.LABORATORY_LAMP)
.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)
.row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS)
.rowAB(Tags.Items.DYES_YELLOW, MItemTags.TRITANIUM_INGOTS)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.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)
.row(MItemTags.TRITANIUM_INGOTS, Tags.Items.COBBLESTONE, MItemTags.TRITANIUM_INGOTS)
.rowB(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)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
.build(consumer, modLocation("decorative/doors/default"))
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(color.tag)
.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)
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
.build(consumer)
.build(consumer, modLocation("decorative/trapdoors/default"))
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(color.tag)
.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)
.unlockedBy(MItemTags.TRITANIUM_PLATES)
.build(consumer)
.build(consumer, modLocation("pressure_plates/default"))
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(dye.tag)
.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
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.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.ShapelessRecipeBuilder
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item
@ -15,7 +16,11 @@ import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.level.ItemLike
import ru.dbotthepony.mc.otm.OverdriveThatMatters
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.UpgradeRecipe
import java.util.function.Consumer
private interface RecipeCell {
@ -51,11 +56,19 @@ private data class RecipeRow(
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
*/
@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 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) {
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 iterator = charlist.iterator()
@ -139,25 +152,75 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1) {
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) {
builder.save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID,
builder.save(consumer.map(filter()), modLocation(
if (result.asItem().registryName!!.namespace == OverdriveThatMatters.MOD_ID)
"${result.asItem().registryName!!.path}_$name"
else
"${result.asItem().registryName!!.namespace}_${result.asItem().registryName!!.path}_$name"
))
} else {
builder.save(consumer)
builder.save(consumer.map(filter()))
}
}
fun buildEnergetic(consumer: Consumer<FinishedRecipe>, name: String? = null) {
build({
consumer.accept(object : FinishedRecipe by it {
fun build(consumer: RecipeOutput, name: ResourceLocation) {
buildRegular().save(consumer.map(filter()), name)
}
fun buildEnergetic(consumer: RecipeOutput, name: String? = null) {
build(consumer.map {
object : FinishedRecipe by it {
override fun getType(): RecipeSerializer<*> {
return EnergyContainerRecipe.Companion
}
})
}
}, name)
}

View File

@ -1,40 +1,44 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.advancements.CriterionTriggerInstance
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.InventoryChangeTrigger
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.data.DataGenerator
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeBuilder
import net.minecraft.data.recipes.RecipeProvider
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.ItemTags
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.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike
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 java.util.LinkedList
import java.util.function.Consumer
import java.util.*
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())
}
fun has(p_125978_: ItemLike): InventoryChangeTrigger.TriggerInstance {
fun has(p_125978_: ItemLike): CriterionTriggerInstance {
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())
}
fun inventoryTrigger(vararg p_126012_: ItemPredicate): InventoryChangeTrigger.TriggerInstance {
fun inventoryTrigger(vararg p_126012_: ItemPredicate): CriterionTriggerInstance {
return InventoryChangeTrigger.TriggerInstance(
EntityPredicate.Composite.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 {
val location = item.asItem().registryName!!
unlockedBy("has_${location.namespace}_${location.path}", has(item))
@ -63,7 +81,7 @@ fun <T : RecipeBuilder> T.unlockedBy(item: TagKey<Item>): T {
return this
}
class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generatorIn) {
class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generatorIn.packOutput) {
private val callbacks = LinkedList<RecipeBuilderCallback>()
fun exec(callback: RecipeBuilderCallback): MatteryRecipeProvider {
@ -71,27 +89,34 @@ class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generat
return this
}
override fun buildCraftingRecipes(callback: Consumer<FinishedRecipe>) {
override fun buildRecipes(callback: RecipeOutput) {
for (lambda in callbacks) {
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 ->
consumer.accept(PlatePressShallowFinishedRecipe(
ResourceLocation(DataGen.MOD_ID, "plates/$id"),
ResourceLocation("forge", "ingots/$id"),
ResourceLocation("forge", "plates/$id"),
consumer.accept(PlatePressRecipe(
modLocation("plates/$id"),
Ingredient.of(ItemTags.create(ResourceLocation("forge", "ingots/$id"))),
Ingredient.of(ItemTags.create(ResourceLocation("forge", "plates/$id"))),
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 ->
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
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) {
val baselineMetals = arrayOf("iron", "silver", "bronze", "lead", "constantan", "brass")
val softMetals = arrayOf("gold", "aluminum", "aluminium", "copper", "electrum", "zinc")
val hardMetals = arrayOf("tritanium", "steel", "tungsten", "uranium")
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" 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" to 0.5f, "steel" to 0.5f, "tungsten" to 0.55f, "uranium" to 0.5f)
for (thing in baselineMetals) {
provider.plate(thing)
for ((thing, exp) in baselineMetals) {
provider.plate(thing, experience = ConstantFloat.of(exp), workTicks = 160)
}
for (thing in softMetals) {
provider.plate(thing, workTicks = 140)
for ((thing, exp) in softMetals) {
provider.plate(thing, workTicks = 120, experience = ConstantFloat.of(exp))
}
for (thing in hardMetals) {
provider.plate(thing, workTicks = 300)
for ((thing, exp) in hardMetals) {
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
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.tags.TagKey
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 net.minecraft.world.level.ItemLike
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation
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 java.util.function.Consumer
fun addShapelessRecipes(consumer: Consumer<FinishedRecipe>) {
for (color in DyeColor.values()) {
ShapelessRecipeBuilder(MItems.CARGO_CRATE_MINECARTS[color]!!, 1)
typealias RecipeOutput = Consumer<FinishedRecipe>
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(MRegistry.CARGO_CRATES.items[color]!!)
.unlockedBy(Items.MINECART)
.unlockedBy(MRegistry.CARGO_CRATES.items[color]!!)
.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(color.tag)
.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"))
}
ShapelessRecipeBuilder(MItems.CARGO_CRATE_MINECARTS[null]!!, 1)
ShapelessRecipeBuilder(RecipeCategory.TRANSPORTATION, MItems.CARGO_CRATE_MINECARTS[null]!!, 1)
.requires(Items.MINECART)
.requires(MRegistry.CARGO_CRATES.item)
.unlockedBy(Items.MINECART)
.unlockedBy(MRegistry.CARGO_CRATES.item)
.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
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.BlockTags
import net.minecraft.tags.ItemTags
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.Items
import net.minecraft.world.item.Tiers
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.MBlocks
import ru.dbotthepony.mc.otm.registry.MItemTags
@ -20,16 +21,26 @@ fun addTags(tagsProvider: TagsProvider) {
tagsProvider.dusts.add("tritanium", MItems.TRITANIUM_DUST)
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("iron", MItems.IRON_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.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.wires.add("copper", MItems.COPPER_WIRING)
@ -40,10 +51,21 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.STORAGE_CABLE
)
tagsProvider.items.appender(MItemTags.CRAFTING_TABLES).add(Items.CRAFTING_TABLE)
tagsProvider.blocks.appender(MBlockTags.CRAFTING_TABLES).add(Blocks.CRAFTING_TABLE)
tagsProvider.items.Appender(MItemTags.CRAFTING_TABLES).add(Items.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/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_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.blocks.appender(MBlockTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
tagsProvider.blocks.appender(MBlockTags.CARGO_CRATES).add(MRegistry.CARGO_CRATES.allBlocks.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.CARGO_CRATES).add(MRegistry.CARGO_CRATES.allBlocks.values)
tagsProvider.items.appender(ItemTags.DOORS).add(MItems.TRITANIUM_DOOR.values)
tagsProvider.blocks.appender(BlockTags.DOORS).add(MBlocks.TRITANIUM_DOOR.values)
tagsProvider.items.Appender(ItemTags.DOORS).add(MItems.TRITANIUM_DOOR.values)
tagsProvider.blocks.Appender(BlockTags.DOORS).add(MBlocks.TRITANIUM_DOOR.values)
tagsProvider.items.appender(ItemTags.TRAPDOORS).add(MItems.TRITANIUM_TRAPDOOR.values)
tagsProvider.blocks.appender(BlockTags.TRAPDOORS).add(MBlocks.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.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.blocks.appender(MBlockTags.MACHINES).add(MItems.MACHINES.stream().map { it as? BlockItem }.filter { it != null }.map { it!!.block })
tagsProvider.items.Appender(MItemTags.MACHINES).add(MItems.MACHINES)
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.TRITANIUM_STAIRS.allBlocks.values)
.add(MRegistry.TRITANIUM_STRIPED_STAIRS.flatBlocks)
.add(MBlocks.TRITANIUM_STRIPED_STAIRS)
tagsProvider.blocks.appender(BlockTags.SLABS)
tagsProvider.blocks.Appender(BlockTags.SLABS)
.add(MRegistry.TRITANIUM_SLAB.allBlocks.values)
.add(MRegistry.TRITANIUM_STRIPED_SLAB.flatBlocks)
.add(MRegistry.FLOOR_TILES_SLAB.blocks.values)
.add(MBlocks.TRITANIUM_STRIPED_SLAB)
tagsProvider.blocks.appender(BlockTags.WALLS)
tagsProvider.blocks.Appender(BlockTags.WALLS)
.add(MRegistry.TRITANIUM_WALL.allBlocks.values)
.add(MRegistry.TRITANIUM_STRIPED_WALL.flatBlocks)
.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_STRIPED_SLAB.flatItems)
.add(MRegistry.FLOOR_TILES_SLAB.items.values)
.add(MItems.TRITANIUM_STRIPED_SLAB)
tagsProvider.items.appender(ItemTags.WALLS)
tagsProvider.items.Appender(ItemTags.WALLS)
.add(MRegistry.TRITANIUM_WALL.allItems.values)
.add(MRegistry.TRITANIUM_STRIPED_WALL.flatItems)
.add(MItems.TRITANIUM_STRIPED_WALL)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_DOOR.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(
MBlocks.ANDROID_STATION,
@ -126,7 +185,13 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.ENERGY_COUNTER,
MBlocks.CHEMICAL_GENERATOR,
MBlocks.PLATE_PRESS,
MBlocks.TWIN_PLATE_PRESS,
MBlocks.MATTER_RECYCLER,
MBlocks.MATTER_ENTANGLER,
MBlocks.POWERED_FURNACE,
MBlocks.POWERED_SMOKER,
MBlocks.POWERED_BLAST_FURNACE,
MBlocks.STORAGE_BUS,
MBlocks.STORAGE_IMPORTER,
@ -141,8 +206,21 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.ENERGY_SERVO,
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)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_ANVIL, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_ORE, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.DEEPSLATE_TRITANIUM_ORE, 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.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.VENT.allBlocks.values, Tiers.IRON)
@ -196,6 +276,12 @@ fun addTags(tagsProvider: TagsProvider) {
MBlocks.BLACK_HOLE,
)
tagsProvider.guardedByPiglins.add(
MBlockTags.CARGO_CRATES,
)
tagsProvider.impermeable.add(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
tagsProvider.androidImmuneEffects.add(
MobEffects.CONDUIT_POWER,
MobEffects.HEAL,
@ -212,4 +298,9 @@ fun addTags(tagsProvider: TagsProvider) {
MobEffects.DOLPHINS_GRACE,
MobEffects.CONFUSION,
)
tagsProvider.androidImmuneEffects.add(
ResourceLocation("rats", "plague"),
ResourceLocation("rats", "synesthesia"),
)
}

View File

@ -1,7 +1,11 @@
package ru.dbotthepony.mc.otm.datagen.tags
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.core.HolderLookup
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.tags.BlockTags
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.Tiers
import net.minecraft.world.level.block.Block
import net.minecraftforge.common.Tags
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.datagen.DataGen
import java.util.stream.Stream
import net.minecraft.data.tags.TagsProvider as MinecraftTagsProvider
interface MTagAppender<T> {
fun add(value: T): MTagAppender<T>
fun addSafe(value: T): Boolean
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
}
private fun <T : Any> vanillaLookup(key: ResourceKey<Registry<T>>): (T) -> ResourceLocation {
val registry by lazy { (BuiltInRegistries.REGISTRY.get(key.location()) ?: throw NoSuchElementException("No such registry $key")) as Registry<T> }
return { registry.getKey(it) ?: throw NoSuchElementException("Registry $key does not contain $it") }
}
interface ForgeTagAppender<T> : MTagAppender<T> {
fun add(key: String, value: T): MTagAppender<T>
fun addSafe(key: String, value: T): Boolean
fun add(key: String, vararg values: T): MTagAppender<T>
fun addSafe(key: String, vararg values: 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 : Any> private constructor(key: ResourceKey<Registry<T>>, val lookup: (T) -> ResourceLocation) : MinecraftTagsProvider<T>(event.generator.packOutput, key, event.lookupProvider, DataGen.MOD_ID, event.existingFileHelper) {
constructor(registry: IForgeRegistry<T>) : this(registry.registryKey, { registry.getKey(it) ?: throw NoSuchElementException("Registry $registry does not contain $it") })
constructor(key: ResourceKey<Registry<T>>) : this(key, vanillaLookup(key))
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 {
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() {
if (tags.isEmpty()) {
return
inner class Appender(val tag: TagKey<T>) {
constructor(tag: ResourceLocation) : this(TagKey.create(registryKey, tag))
init {
require(tag.registry == registryKey) { "Trying to create appender for $tag inside registry $registryKey" }
}
private val locations by lazy { tags.computeIfAbsent(tag) { ObjectArraySet() } }
private val rigidLocations by lazy { rigidTags.computeIfAbsent(tag) { ObjectArraySet() } }
private val tagsInTags by lazy { tagInTag.computeIfAbsent(tag) { ObjectArraySet() } }
fun add(value: ResourceLocation): Appender {
check(locations.add(value)) { "Tag ${tag.location} of registry ${registryKey.location()} already contains $value" }
return this
}
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)
return this
}
fun add(vararg values: T): Appender {
for (value in values) add(value)
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) {
tag(tag).also {
for (value in values) {
it.add(value)
}
val appender = tag(tag)
for (value in values) {
appender.addOptional(value)
}
}
}
fun getSet(tag: TagKey<T>): MutableSet<T> {
return tags.computeIfAbsent(tag) { ObjectArraySet() }
}
for ((tag, values) in rigidTags) {
val appender = tag(tag)
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())
}
return this
}
override fun add(values: Collection<T>): MTagAppender<T> {
for (value in values) add(value)
return this
}
override fun addSafe(value: T): Boolean {
return list.add(value)
}
override fun add(vararg values: T): MTagAppender<T> {
values.forEach(this::add)
return this
for (value in values) {
appender.add(value)
}
}
}
fun forge(path: String): ForgeTagAppender<T> {
val parent by lazy { appender(ResourceLocation("forge", path)) }
for ((tag, values) in tagInTag) {
val appender = tag(tag)
return object : ForgeTagAppender<T> {
override fun add(key: String, value: T): MTagAppender<T> {
val tag = TagKey.create(registry.key(), ResourceLocation("forge", "$path/$key"))
if (!getSet(tag).add(value)) {
throw IllegalStateException("$value is already in $tag")
}
return this
}
override fun addSafe(key: String, value: T): Boolean {
val tag = TagKey.create(registry.key(), ResourceLocation("forge", "$path/$key"))
return getSet(tag).add(value)
}
override fun add(key: String, vararg values: T): MTagAppender<T> {
for (value in values) add(key, value)
return this
}
override fun add(key: String, values: Collection<T>): MTagAppender<T> {
for (value in values) add(key, value)
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)
for (value in values) {
appender.addTag(value)
}
}
}
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)
private val delegates = ArrayList<Delegate<*>>()
private var isRegistered = false
val androidImmuneEffects = mobEffects.appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS)
fun register() {
if (!isRegistered) {
isRegistered = true
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)
for (value in delegates) {
event.generator.addProvider(event.includeServer(), value)
}
val requiresStoneTool = blocks.appender(BlockTags.NEEDS_STONE_TOOL)
val requiresIronTool = blocks.appender(BlockTags.NEEDS_IRON_TOOL)
val requiresDiamondTool = blocks.appender(BlockTags.NEEDS_DIAMOND_TOOL)
delegates.clear()
}
}
val witherImmune = blocks.appender(BlockTags.WITHER_IMMUNE)
val dragonImmune = blocks.appender(BlockTags.DRAGON_IMMUNE)
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
}
fun deepslateOre(key: String, block: Block): TagsProvider {
ore(key, block)
itemGroundOresDeepslate.add(block.asItem())
blockGroundOresDeepslate.add(block)
return this
}
fun singleDropOre(vararg blocks: Block): TagsProvider {
for (block in blocks) {
itemOreRatesSingular.add(block.asItem())
blockOreRatesSingular.add(block)
}
return this
}
fun ore(key: String, block: Block): TagsProvider {
val forgeKey = ResourceLocation("forge", "ores/$key")
val b = TagKey.create(Registry.BLOCK_REGISTRY, forgeKey)
val i = TagKey.create(Registry.ITEM_REGISTRY, forgeKey)
val b = TagKey.create(Registries.BLOCK, forgeKey)
val i = TagKey.create(Registries.ITEM, forgeKey)
items.getSet(i).add(block.asItem())
items.Appender(i).add(block.asItem())
itemOres.add(block.asItem())
blocks.getSet(b).add(block)
blocks.Appender(b).add(block)
blockOres.add(block)
return this
@ -220,18 +245,32 @@ class TagsProvider(
}
val circuits = items.forge("circuits")
val dusts = items.forge("dusts")
val ingots = items.forge("ingots")
val itemOres = items.forge("ores")
val blockOres = blocks.forge("ores")
val dusts = items.Appender(Tags.Items.DUSTS)
val ingots = items.Appender(Tags.Items.INGOTS)
val itemOres = items.Appender(Tags.Items.ORES)
val blockOres = blocks.Appender(Tags.Blocks.ORES)
val plates = items.forge("plates")
val storageBlocksAsItem = items.forge("storage_blocks")
val storageBlocksAsBlock = blocks.forge("storage_blocks")
val rawMaterials = items.forge("raw_materials")
val storageBlocksAsItem = items.Appender(Tags.Items.STORAGE_BLOCKS)
val storageBlocksAsBlock = blocks.Appender(Tags.Blocks.STORAGE_BLOCKS)
val rawMaterials = items.Appender(Tags.Items.RAW_MATERIALS)
val wires = items.forge("wires")
val gameEvents = Delegate(Registry.GAME_EVENT)
val vibrations = gameEvents.appender(GameEventTags.VIBRATIONS)
val blockGroundOresStone = blocks.Appender(Tags.Blocks.ORES_IN_GROUND_STONE)
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 {
requiresPickaxe.add(block)

View File

@ -4,8 +4,7 @@ import kotlin.KotlinVersion;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist;
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.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.IdMappingEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import ru.dbotthepony.mc.otm.android.AndroidResearchManager;
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.decorative.DevChestBlockEntity;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
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.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer;
import ru.dbotthepony.mc.otm.client.render.WidgetAtlasHolder;
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt;
import ru.dbotthepony.mc.otm.core.Decimal;
import ru.dbotthepony.mc.otm.item.ItemTritaniumArmor;
import ru.dbotthepony.mc.otm.client.render.blockentity.BatteryBankRenderer;
import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer;
import ru.dbotthepony.mc.otm.compat.adastra.AdAstraCompatKt;
import ru.dbotthepony.mc.otm.compat.curios.CuriosCompatKt;
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.weapon.AbstractWeaponItem;
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
import ru.dbotthepony.mc.otm.matter.MatterManager;
import ru.dbotthepony.mc.otm.network.*;
import ru.dbotthepony.mc.otm.registry.*;
import ru.dbotthepony.mc.otm.storage.*;
import ru.dbotthepony.mc.otm.worldgen.OreGen;
import ru.dbotthepony.mc.otm.triggers.KillAsAndroidTrigger;
import top.theillusivec4.curios.api.CuriosApi;
import static net.minecraftforge.common.MinecraftForge.EVENT_BUS;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.concurrent.atomic.AtomicInteger;
// The value here should match an entry in the META-INF/mods.toml file
@Mod(OverdriveThatMatters.MOD_ID)
@ -59,35 +72,26 @@ public final class OverdriveThatMatters {
// Directly reference a log4j logger.
public static final String MOD_ID = "overdrive_that_matters";
private static final Logger LOGGER = LogManager.getLogger();
public static final AtomicInteger INGREDIENT_CACHE_INVALIDATION_COUNTER;
public static OverdriveThatMatters INSTANCE;
private StorageStackType<ItemStackWrapper> ITEM_STORAGE;
public StorageStackType<ItemStackWrapper> ITEM_STORAGE() {
return ITEM_STORAGE;
static {
try {
var f = Ingredient.class.getDeclaredField("INVALIDATION_COUNTER");
f.setAccessible(true);
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) {
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() {
if (!KotlinVersion.CURRENT.isAtLeast(1, 6, 10)) {
throw new UnsupportedClassVersionError("Installed kotlin version is " + KotlinVersion.CURRENT + ", when at least 1.6.10 is required.");
if (!KotlinVersion.CURRENT.isAtLeast(1, 9, 0)) {
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, TritaniumArmorModel::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();
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) {
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.HIGHEST, GlobalEventHandlerKt::onServerStopped);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopping);
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.NORMAL, MatteryPlayerCapability.Companion::onPlayerTick);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::isMobEffectApplicable);
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.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerChangeDimensionEvent);
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayerCapability.Companion::onPlayerDeath);
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::onStopTracking);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::addCommands);
EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick);
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::addCommands);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onServerStopping);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onLevelUnload);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onWatch);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onForget);
EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::playerDisconnected);
EVENT_BUS.addListener(EventPriority.LOWEST, SynchronizedBlockEntity.Companion::postLevelTick);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onServerStopping);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onLevelUnload);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onWatch);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::onForget);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::playerDisconnected);
EVENT_BUS.addListener(EventPriority.LOWEST, KillAsAndroidTrigger.INSTANCE::onKill);
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();
MenuNetworkChannel.INSTANCE.register();
WeaponNetworkChannel.INSTANCE.register();
RegistryNetworkChannel.INSTANCE.register();
WorldNetworkChannel.INSTANCE.register();
GenericNetworkChannel.INSTANCE.register();
ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new Decimal("3.125"));
if (ModList.get().isLoaded("mekanism")) {
EVENT_BUS.addGenericListener(BlockEntity.class, EventPriority.NORMAL, QIOKt::attachCapabilities);
if (ModList.get().isLoaded(CuriosApi.MODID)) {
EVENT_BUS.addListener(EventPriority.NORMAL, CuriosCompatKt::onCuriosSlotModifiersUpdated);
}
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) {
@ -223,13 +241,10 @@ public final class OverdriveThatMatters {
EVENT_BUS.addListener(EventPriority.LOWEST, ClientTickHandlerKt::onClientTick);
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientConnected);
EVENT_BUS.addListener(EventPriority.HIGHEST, ClientTickHandlerKt::onClientDisconnected);
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandlerKt::tooltipEvent);
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::onMouseClick);

View File

@ -1,14 +1,18 @@
package ru.dbotthepony.mc.otm.capability;
import mekanism.api.energy.IStrictEnergyHandler;
import net.minecraftforge.common.capabilities.*;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityToken;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
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.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.IPatternStorage;
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode;
import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode;
import ru.dbotthepony.mc.otm.graph.matter.MatterNode;
import ru.dbotthepony.mc.otm.graph.storage.StorageNode;
import top.theillusivec4.curios.api.type.capability.ICurio;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
@ -25,11 +29,11 @@ public class MatteryCapability {
@Nonnull
@NotNull
public static final Capability<IMatterHandler> MATTER = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<IMatterStorage> MATTER = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IMatterGraphNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<MatterNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
@ -41,15 +45,15 @@ public class MatteryCapability {
@Nonnull
@NotNull
public static final Capability<IMatteryDrive> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<IMatteryDrive<?>> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IStorageGraphNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<StorageNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@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
@NotNull
@ -59,14 +63,19 @@ public class MatteryCapability {
@NotNull
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) {
event.register(IMatteryEnergyStorage.class);
event.register(MatteryPlayerCapability.class);
event.register(IMatterHandler.class);
event.register(IMatterGraphNode.class);
event.register(IMatterStorage.class);
event.register(MatterNode.class);
event.register(IPatternStorage.class);
event.register(IReplicationTaskProvider.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;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.PlayerModel;
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.resources.ResourceLocation;
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.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket;
import javax.annotation.Nonnull;
import java.util.Set;
@ -32,6 +37,7 @@ public final class ExosuitModel {
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 textureColor = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/models/armor/exosuit_color.png");
static {
MeshDefinition meshdefinition = new MeshDefinition();
@ -116,13 +122,18 @@ public final class ExosuitModel {
float p_117357_,
float p_117358_
) {
if (player.isInvisible())
return;
var cap = player.getCapability(MatteryCapability.MATTERY_PLAYER);
if (!cap.isPresent()) {
return;
}
if (cap.resolve().get().getHasExoPack() && cap.resolve().get().getDisplayExoPack()) {
var mattery = cap.resolve().get();
if (mattery.getHasExopack() && mattery.isExopackVisible()) {
var model = getParentModel();
model.copyPropertiesTo(modelNormal);
model.copyPropertiesTo(modelGlow);
@ -138,14 +149,40 @@ public final class ExosuitModel {
1f, 1f, 1f, 1f
);
modelGlow.renderToBuffer(
poseStack,
bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture)),
packedLight,
overlayCoords,
// rgba
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(
poseStack,
bufferSource.getBuffer(RenderType.entityTranslucentEmissive(texture)),
packedLight,
overlayCoords,
// rgba
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 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))
.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",
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,
shift = At.Shift.BEFORE
shift = At.Shift.BEFORE,
remap = false
),
cancellable = true)
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.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import ru.dbotthepony.mc.otm.core.math.BlockRotation;
import javax.annotation.ParametersAreNonnullByDefault;
@ -47,7 +48,7 @@ public record BlockShape(SimpleCuboid ...shapes) {
return new BlockShape(list);
}
public BlockShape rotate(Direction dir) {
public BlockShape rotateFromSouth(Direction dir) {
if (dir == Direction.SOUTH)
return this;
@ -69,7 +70,7 @@ public record BlockShape(SimpleCuboid ...shapes) {
return this;
}
public BlockShape rotateInv(Direction dir) {
public BlockShape rotateFromNorth(Direction dir) {
if (dir == Direction.SOUTH)
return rotateAroundY(Math.PI);
@ -91,11 +92,29 @@ public record BlockShape(SimpleCuboid ...shapes) {
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() {
VoxelShape final_shape = shapes[0].getShape();
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;
}

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.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.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.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.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(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(
new SimpleCuboid(0d, 0d, 0d, 1d, 0.5d, 1d),
new SimpleCuboid(0d, 0.5d, 0.4375d, 1d, 0.75d, 1d),
new SimpleCuboid(0.75d, 0.5d, 0.0625d, 1d, 0.75d, 0.4375d),
new SimpleCuboid(0.125d, 0.5d, 0.25d, 0.6875d, 1d, 0.8125d),
new SimpleCuboid(0.8125d, 0.5d, 0d, 0.9375d, 0.75d, 0.0625d),
new SimpleCuboid(0.9375d, 0.75d, 0.9375d, 1d, 0.875d, 1d),
new SimpleCuboid(0d, 0.75d, 0.9375d, 0.0625d, 0.875d, 1d),
new SimpleCuboid(0.01875d, 0.8125d, 0.0625d, 0.05d, 0.875d, 0.9375d),
new SimpleCuboid(0d, 0.5d, 0d, 0.0625d, 0.875d, 0.0625d),
new SimpleCuboid(0.0625d, 0.8125d, 0.95d, 0.9375d, 0.875d, 0.98125d),
new SimpleCuboid(0.6875d, 0.5d, 0.5625d, 0.75d, 0.875d, 0.75d),
new SimpleCuboid(0.6875d, 0.5d, 0.3125d, 0.75d, 0.875d, 0.5d),
new SimpleCuboid(0.0625d, 0.5d, 0.3125d, 0.125d, 0.875d, 0.5d),
new SimpleCuboid(0.0625d, 0.5d, 0.5625d, 0.125d, 0.875d, 0.75d),
new SimpleCuboid(0.775d, 0.75d, 0.125d, 0.9625d, 0.9375d, 0.875d)
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.0625d, 0d, 0d, 0.5625d, 0.4375d, 1d),
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)
);
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(
@ -569,4 +602,187 @@ public class BlockShapes {
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)
);
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.fml.loading.FMLLoader
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.core.IConditionalTickable
import ru.dbotthepony.mc.otm.core.ITickable
import ru.dbotthepony.mc.otm.core.TickList
import ru.dbotthepony.mc.otm.core.TimerQueue
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
import ru.dbotthepony.mc.otm.core.util.AtomicallyInvalidatedLazy
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
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.concurrent.atomic.AtomicInteger
private val preServerTick = TickList()
private val postServerTick = TickList()
private val preWorldTick = WeakHashMap<Level, TickList>()
private val postWorldTick = WeakHashMap<Level, TickList>()
private val preServerTickTimers = TimerQueue()
private val postServerTickTimers = TimerQueue()
private val clientThreads = WeakHashSet<Thread>()
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) {
LOGGER.error("Refusing to add timer $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
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) {
LOGGER.error("Refusing to add ticker $callback in ticks $inTicks while server is dying", IllegalStateException("Server is stopping"))
return null
}
return postServerTickTimers.Timer(inTicks, callback)
return postServerTick.Timer(inTicks, callback)
}
private var _server: MinecraftServer? = null
private var _serverThread: Thread? = null
private var _clientThread: Thread? = null
/**
* schedules execution of Runnable somewhere in the future,
* 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() {
val server = _server
@ -65,7 +94,7 @@ private val isPausedImpl: Boolean get() {
}
val isPaused: Boolean get() {
if (_clientThread === null) {
if (clientThreads.isEmpty()) {
return false
}
@ -73,11 +102,7 @@ val isPaused: Boolean get() {
}
fun recordClientThread() {
if (_clientThread != null) {
throw IllegalStateException("Already have client channel")
}
_clientThread = Thread.currentThread()
clientThreads.add(Thread.currentThread())
}
fun runIfClient(lambda: () -> Unit) {
@ -120,11 +145,11 @@ fun <V> runOnClient(value: V, lambda: () -> V): V {
}
fun isServerThread(): Boolean {
return Thread.currentThread() === _serverThread
return Thread.currentThread() in serverThreads
}
fun isClientThread(): Boolean {
return Thread.currentThread() === _clientThread
return Thread.currentThread() in clientThreads
}
val MINECRAFT_SERVER: MinecraftServer
@ -146,28 +171,38 @@ private val LOGGER = LogManager.getLogger()
fun onServerTick(event: ServerTickEvent) {
if (event.phase === TickEvent.Phase.START) {
preServerTickTimers.tick()
preServerTick.tick()
serverThreads.add(Thread.currentThread())
} else {
postServerTickTimers.tick()
postServerTick.tick()
// чтоб не плодить кучу подписчиков, вызовем напрямую отсюда
GraphNodeList.tick()
AbstractProfiledStorage.onServerPostTick()
MatteryNetworkChannel.onServerPostTick()
}
}
fun onWorldTick(event: LevelTickEvent) {
fun onLevelTick(event: LevelTickEvent) {
if (event.phase === TickEvent.Phase.START) {
preWorldTick[event.level]?.tick()
if (event.side.isClient) {
clientThreads.add(Thread.currentThread())
} else if (event.side.isServer) {
serverThreads.add(Thread.currentThread())
}
} else {
postWorldTick[event.level]?.tick()
MatteryBlockEntity.postLevelTick(event)
}
}
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) {
postServerTick.add(ticker, SERVER_IS_LIVE, "Server is stopping")
postServerTick.once(ticker, SERVER_IS_LIVE, "Server is stopping")
}
fun tickServerPre(ticker: IConditionalTickable) {
@ -178,41 +213,31 @@ fun tickServer(ticker: IConditionalTickable) {
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) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return
}
postWorldTick.computeIfAbsent(this) { TickList() }.add(ticker)
postWorldTick.computeIfAbsent(this) { TickList() }.once(ticker)
}
fun Level.oncePre(ticker: ITickable) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return
}
preWorldTick.computeIfAbsent(this) { TickList() }.add(ticker)
preWorldTick.computeIfAbsent(this) { TickList() }.once(ticker)
}
fun Level.addTicker(ticker: IConditionalTickable) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return
@ -222,6 +247,8 @@ fun Level.addTicker(ticker: IConditionalTickable) {
}
fun Level.addTickerPre(ticker: IConditionalTickable) {
if (this.isClientSide) return
if (!SERVER_IS_LIVE) {
LOGGER.error("Refusing to add ticker $ticker while server is dying", IllegalStateException("Server is stopping"))
return
@ -231,24 +258,26 @@ fun Level.addTickerPre(ticker: IConditionalTickable) {
}
fun Level.until(ticker: () -> Boolean) {
if (this.isClientSide) return
addTicker(IConditionalTickable.wrap(ticker))
}
fun Level.untilPre(ticker: () -> Boolean) {
if (this.isClientSide) return
addTickerPre(IConditionalTickable.wrap(ticker))
}
fun Level.`while`(condition: () -> Boolean, ticker: () -> Unit) {
if (this.isClientSide) return
addTicker(IConditionalTickable.wrap(condition, ticker))
}
fun Level.whilePre(condition: () -> Boolean, ticker: () -> Unit) {
if (this.isClientSide) return
addTickerPre(IConditionalTickable.wrap(condition, ticker))
}
private fun clear() {
preServerTickTimers.clear()
postServerTickTimers.clear()
preServerTick.clear()
postServerTick.clear()
preWorldTick.clear()
@ -259,22 +288,27 @@ fun onServerStarting(event: ServerAboutToStartEvent) {
clear()
SERVER_IS_LIVE = true
_server = event.server
_serverThread = Thread.currentThread()
serverThreads.add(Thread.currentThread())
serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStarting()
}
fun onServerStopping(event: ServerStoppingEvent) {
clear()
SERVER_IS_LIVE = false
serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStopping()
}
fun onServerStopped(event: ServerStoppedEvent) {
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()
SERVER_IS_LIVE = false
}
_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.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.registries.IForgeRegistry
import ru.dbotthepony.mc.otm.config.getValue
import java.util.LinkedList
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
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
/**

View File

@ -3,11 +3,11 @@ package ru.dbotthepony.mc.otm.android
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import net.minecraft.nbt.CompoundTag
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.event.entity.living.LivingAttackEvent
import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
import java.io.DataInputStream
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import java.io.InputStream
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 onHurt(event: LivingHurtEvent) {}
open fun onAttack(event: LivingAttackEvent) {}
open fun collectNetworkPayload(): FastByteArrayOutputStream? {
return synchronizer.collectNetworkPayload()
}
open fun applyNetworkPayload(stream: InputStream) {
synchronizer.applyNetworkPayload(stream)
synchronizer.read(stream)
}
override fun serializeNBT(): CompoundTag {

View File

@ -1,44 +1,64 @@
package ru.dbotthepony.mc.otm.android
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import net.minecraft.ChatFormatting
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
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.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.capability.MatteryPlayerCapability
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.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.set
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.milliTime
import ru.dbotthepony.mc.otm.nanoTime
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
import java.io.DataInputStream
import java.io.InputStream
import kotlin.math.absoluteValue
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 synchronizer = FieldSynchronizer()
var isResearched by synchronizer.bool()
var isResearched by synchronizer.bool().property
private set
var tag = CompoundTag()
private set
/**
@ -53,63 +73,24 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
return
}
onUnResearch()
onUnResearched()
isResearched = false
}
private data class RememberResearchLevel(val level: Int?)
private val oldResearchLevel = Object2ObjectArrayMap<AndroidFeatureType<*>, RememberResearchLevel>()
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)
}
}
}
}
fun onUnResearched() {
for (result in type.results) {
result.onUnResearched(this)
}
oldResearchLevel.clear()
MinecraftForge.EVENT_BUS.post(OnUnResearched(this))
}
fun onResearched() {
oldResearchLevel.clear()
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) {
transformer.apply(this to get)
}
}
} catch(err: Throwable) {
oldResearchLevel.clear()
throw err
for (result in type.results) {
result.onResearched(this)
}
MinecraftForge.EVENT_BUS.post(OnResearched(this))
}
/**
@ -125,6 +106,15 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
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)) {
return false
}
@ -166,11 +156,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
*
* Returns true whenever player accepted all resources refunded, false otherwise.
*/
fun refund(simulate: Boolean): Boolean {
if (simulate) {
return true
}
fun refund(): Boolean {
if (type.experienceLevels > 0) {
var experiencePoints = 0
@ -195,6 +181,8 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
}
}
MinecraftForge.EVENT_BUS.post(OnRefunded(this))
return true
}
@ -203,7 +191,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
}
fun applyNetworkPayload(stream: InputStream) {
synchronizer.applyNetworkPayload(stream)
synchronizer.read(stream)
}
val canResearch: Boolean get() {
@ -304,7 +292,12 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
val tooltipLines: List<Component> get() {
val lines = ArrayList<Component>()
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
}
@ -389,38 +382,12 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
override fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["researched"] = isResearched
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
}
}
})
}
}
it["tag"] = tag
}
}
override fun deserializeNBT(nbt: CompoundTag) {
isResearched = nbt.getBoolean("researched")
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)
}
tag = nbt.getCompound("tag")
}
}

View File

@ -1,17 +1,34 @@
package ru.dbotthepony.mc.otm.android
import com.google.gson.JsonObject
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.data.CachedOutput
import net.minecraft.data.DataGenerator
import net.minecraft.data.DataProvider
import net.minecraft.data.PackOutput
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.LinkedList
import java.util.concurrent.CompletableFuture
import java.util.function.Consumer
@Suppress("unused")
open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerator) : DataProvider {
protected val pathProvider: DataGenerator.PathProvider = dataGenerator.createPathProvider(DataGenerator.Target.DATA_PACK, AndroidResearchManager.DIRECTORY)
open class AndroidResearchDataProvider() : DataProvider {
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>()
@ -35,15 +52,14 @@ open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerato
return this
}
final override fun run(output: CachedOutput) {
AndroidResearchManager.fireRegistrationEvent()
final override fun run(output: CachedOutput): CompletableFuture<*> {
val set = ObjectArraySet<ResourceLocation>()
val added = LinkedList<AndroidResearchType>()
val futures = ArrayList<CompletableFuture<*>>()
addEverything {
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)
added.add(it)
} else {
@ -55,6 +71,8 @@ open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerato
value.validate()
generated.add(value)
}
return CompletableFuture.allOf(*futures.toTypedArray())
}
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.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonSyntaxException
import net.minecraft.client.server.IntegratedServer
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
import net.minecraft.util.profiling.ProfilerFiller
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.AddReloadListenerEvent
import net.minecraftforge.event.OnDatapackSyncEvent
import net.minecraftforge.eventbus.api.Event
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.PacketDistributor
import org.apache.logging.log4j.LogManager
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.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.data.SerializedFunctionRegistry
import ru.dbotthepony.mc.otm.core.fromJsonStrict
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.RegistryNetworkChannel
import ru.dbotthepony.mc.otm.network.enqueueWork
import ru.dbotthepony.mc.otm.network.packetHandled
import ru.dbotthepony.mc.otm.onceServer
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> {
/**
* 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"
private val LOGGER = LogManager.getLogger()
@ -97,23 +54,11 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
var researchMap: Map<ResourceLocation, AndroidResearchType> = mapOf()
private set
internal fun fireRegistrationEvent() {
if (!firedRegistrationEvent) {
try {
MinecraftForge.EVENT_BUS.post(RegisterFuncsEvent)
} finally {
firedRegistrationEvent = true
}
}
}
override fun apply(
jsonElementMap: Map<ResourceLocation, JsonElement>,
manager: ResourceManager,
profiler: ProfilerFiller
) {
fireRegistrationEvent()
val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>()
for ((k, v) in jsonElementMap) {
@ -122,7 +67,13 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
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()
@ -148,23 +99,23 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
val packet = SyncPacket(researchMap.values)
if (event.player != null) {
RegistryNetworkChannel.send(event.player!!, packet)
GenericNetworkChannel.send(event.player!!, packet)
} else {
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), packet)
GenericNetworkChannel.send(PacketDistributor.ALL.noArg(), packet)
}
}
class SyncPacket(val collection: Collection<AndroidResearchType>) : MatteryPacket {
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
if (NULLABLE_MINECRAFT_SERVER is IntegratedServer) {
if (NULLABLE_MINECRAFT_SERVER is IntegratedServer)
return
}
val builder = ImmutableMap.builder<ResourceLocation, AndroidResearchType>()
@ -185,6 +136,7 @@ object AndroidResearchManager : SimpleJsonResourceReloadListener(GsonBuilder().s
}
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
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.JsonPrimitive
import com.google.gson.JsonSyntaxException
import com.google.gson.internal.bind.TypeAdapters
import net.minecraft.network.FriendlyByteBuf
import com.mojang.datafixers.util.Either
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.ComponentContents
import net.minecraft.network.chat.MutableComponent
@ -17,30 +16,28 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey
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 net.minecraft.world.level.ItemLike
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.client.render.AbstractSkinElement
import ru.dbotthepony.mc.otm.client.render.SkinElement
import ru.dbotthepony.mc.otm.client.render.SkinElementType
import ru.dbotthepony.mc.otm.core.ListSet
import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite
import ru.dbotthepony.mc.otm.client.render.sprites.SpriteType
import ru.dbotthepony.mc.otm.core.collect.ListSet
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.toImmutableList
import ru.dbotthepony.mc.otm.data.stream
import ru.dbotthepony.mc.otm.data.ComponentCodec
import ru.dbotthepony.mc.otm.data.IngredientCodec
import ru.dbotthepony.mc.otm.data.JsonElementCodec
import ru.dbotthepony.mc.otm.isClient
import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.LinkedList
import java.util.Optional
import java.util.function.Function
import java.util.stream.Stream
import kotlin.collections.ArrayList
import kotlin.collections.HashSet
import kotlin.jvm.optionals.getOrNull
private fun findPrerequisites(
initial: Collection<AndroidResearchType>,
add: MutableSet<AndroidResearchType> = HashSet(),
add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
top: Boolean = true
): Set<AndroidResearchType> {
for (value in initial) {
@ -56,7 +53,7 @@ private fun findPrerequisites(
private fun findAllPrerequisites(
initial: Collection<AndroidResearchType>,
add: MutableSet<AndroidResearchType> = HashSet(),
add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
): Set<AndroidResearchType> {
for (value in initial) {
add.add(value)
@ -68,7 +65,7 @@ private fun findAllPrerequisites(
private fun findAllChildren(
initial: Collection<AndroidResearchType>,
add: MutableSet<AndroidResearchType> = HashSet(),
add: MutableSet<AndroidResearchType> = ObjectOpenHashSet(),
): Set<AndroidResearchType> {
for (value in initial) {
add.add(value)
@ -84,10 +81,9 @@ class AndroidResearchType(
blockedBy: Collection<Reference>,
items: Collection<Pair<Ingredient, Int>>,
features: Collection<FeatureReference>,
results: Collection<AndroidResearchResult>,
descriptionLines: Collection<Component>,
descriptionSuppliers: Collection<ComponentSupplier> = listOf(),
description: Collection<AndroidResearchDescription>,
val experienceLevels: Int = 0,
private val customName: Component? = null,
@ -97,123 +93,57 @@ class AndroidResearchType(
val itemIcon: Item? = 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()
val iconText get() = iconTextValue?.copy()
val resolvedSkinIcon by lazy {
check(isClient) { "Invalid realm" }
if (skinIcon != null)
SkinElementType.fromJson(skinIcon)
SpriteType.fromJson(skinIcon)
else
null
}
data class Reference(
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 {
fun fromNetwork(buff: FriendlyByteBuf): Reference {
return Reference(
ResourceLocation(buff.readUtf()),
buff.readBoolean()
)
}
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>()),
val CODEC: Codec<Reference> by lazy {
Codec
.either(ResourceLocation.CODEC, RecordCodecBuilder.create<Reference> {
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) }
)
} else {
throw JsonSyntaxException("Unknown element type ${value::class.qualifiedName}")
}
}
}
}
data class ResolvedFeature(
val feature: AndroidFeatureType<*>,
val level: Int,
)
val researchTreeDepth: Int by lazy {
if (flatPrerequisites.isEmpty()) {
return@lazy 0
@ -242,38 +172,18 @@ class AndroidResearchType(
val blockedBy: List<Reference> = ImmutableList.copyOf(blockedBy)
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 {
ImmutableList.copyOf(this.blockedBy.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.isRigid) 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 } })
ImmutableList.copyOf(this.blockedBy.mapNotNull { AndroidResearchManager[it.id].also { e -> if (e == null && it.optional) throw NoSuchElementException("Unable to find research ${it.id}") } })
}
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 }
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) })
val description: ImmutableList<AndroidResearchDescription> = ImmutableList.copyOf(description)
/**
* Flat list of research preceding this research.
@ -468,152 +378,35 @@ class AndroidResearchType(
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() {
resolvedFeatures
resolvedBlockedBy
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 {
fun fromNetwork(buff: FriendlyByteBuf): AndroidResearchType {
val id = ResourceLocation(buff.readUtf())
val prerequisites = buff.readCollection({ LinkedList() }, Reference::fromNetwork)
val blockedBy = buff.readCollection({ LinkedList() }, Reference::fromNetwork)
val items = buff.readCollection({ LinkedList() }, { Ingredient.fromNetwork(it) to it.readVarInt() })
val features = buff.readCollection({ LinkedList() }, FeatureReference::fromNetwork)
val descriptionLines = buff.readCollection({ LinkedList() }, FriendlyByteBuf::readComponent)
val descriptionSuppliers = buff.readCollection({ LinkedList() }, { AndroidResearchManager.descriptionFuncs.fromNetwork(it) })
val experienceLevels = buff.readVarInt()
val customName = if (buff.readBoolean()) {
buff.readComponent()
} else {
null
val CODEC: Codec<AndroidResearchType> by lazy {
RecordCodecBuilder.create {
it.group(
ResourceLocation.CODEC.fieldOf("id").forGetter(AndroidResearchType::id),
ListCodec(Reference.CODEC).fieldOf("prerequisites").forGetter(AndroidResearchType::prerequisites),
ListCodec(Reference.CODEC).fieldOf("blockedBy").forGetter(AndroidResearchType::blockedBy),
ListCodec(
RecordCodecBuilder.create<Pair<Ingredient, Int>> {
it.group(
IngredientCodec.fieldOf("item").forGetter { it.first },
Codec.intRange(1, Int.MAX_VALUE).optionalFieldOf("count", 1).forGetter { it.second }
).apply(it, ::Pair)
}
).fieldOf("items").forGetter { it.definedItems },
ListCodec(AndroidResearchResult.CODEC).fieldOf("results").forGetter(AndroidResearchType::results),
ListCodec(AndroidResearchDescription.CODEC).fieldOf("description").forGetter(AndroidResearchType::description),
Codec.intRange(0, Int.MAX_VALUE).fieldOf("experienceLevels").forGetter(AndroidResearchType::experienceLevels),
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 iconTextValue = if (buff.readBoolean()) {
buff.readComponent()
} else {
null
}
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,
var experience: Int = 0,
var customName: Component? = null,
var description: MutableList<Component>? = null,
var descriptionSuppliers: MutableList<ComponentSupplier>? = null,
description: MutableList<AndroidResearchDescription>? = null,
var itemIcon: Item? = null,
var skinIcon: AbstractSkinElement? = null,
var skinIcon: AbstractMatterySprite? = null,
var iconText: Component? = null,
) {
val description = ArrayList<AndroidResearchDescription>(description ?: listOf())
val results = ArrayList<AndroidResearchResult>()
private val items = ArrayList<Pair<Ingredient, Int>>()
private val prerequisites = ArrayList<Reference>()
private val blockers = ArrayList<Reference>()
private val features = ArrayList<FeatureReference>()
fun withIconText(icon: Component? = null): Builder {
this.iconText = icon
return this
}
fun withIcon(icon: AbstractSkinElement? = null): Builder {
fun withIcon(icon: AbstractMatterySprite? = null): Builder {
this.skinIcon = icon
this.itemIcon = null
return this
@ -662,19 +455,20 @@ class AndroidResearchType(
return this
}
fun withDescription(): Builder {
this.description = mutableListOf(TranslatableComponent("android_research.${id.namespace}.${id.path}.description"))
fun clearDescription(): Builder {
this.description.clear()
return this
}
fun withDescription(range: IntRange): Builder {
val result = ArrayList<Component>()
fun withDescription(): Builder {
return withDescription(TranslatableComponent("android_research.${id.namespace}.${id.path}.description"))
}
fun withDescription(range: IntRange): Builder {
for (i in range) {
result.add(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i"))
withDescription(TranslatableComponent("android_research.${id.namespace}.${id.path}.description$i"))
}
this.description = result
return this
}
@ -684,73 +478,21 @@ class AndroidResearchType(
}
fun withDescription(vararg description: Component): Builder {
this.description = description.toMutableList()
for (component in description)
withDescription(PlainAndroidResearchDescription.Instance(component))
return this
}
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
}
fun appendDescription(range: IntRange): Builder {
val result = this.description ?: ArrayList()
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) }
fun withDescription(vararg description: AndroidResearchDescription): Builder {
this.description.addAll(description)
return this
}
@ -759,14 +501,14 @@ class AndroidResearchType(
* research tree render logic (yet).
*/
@JvmOverloads
fun addPrerequisite(id: ResourceLocation, rigid: Boolean = false): Builder {
prerequisites.add(Reference(id, rigid))
fun addPrerequisite(id: ResourceLocation, optional: Boolean = true): Builder {
prerequisites.add(Reference(id, optional))
return this
}
@JvmOverloads
fun addBlocker(id: ResourceLocation, rigid: Boolean = false): Builder {
blockers.add(Reference(id, rigid))
fun addBlocker(id: ResourceLocation, optional: Boolean = true): Builder {
blockers.add(Reference(id, optional))
return this
}
@ -774,46 +516,28 @@ class AndroidResearchType(
* Please avoid having multiple prerequisites as case with more than 1 prerequisite does not have proper
* research tree render logic (yet).
*/
fun addPrerequisite(type: AndroidResearchType, rigid: Boolean = true) = addPrerequisite(type.id, rigid)
fun addBlocker(type: AndroidResearchType, rigid: Boolean = true) = addBlocker(type.id, rigid)
fun addPrerequisite(type: AndroidResearchType, optional: Boolean = false) = addPrerequisite(type.id, optional)
fun addBlocker(type: AndroidResearchType, optional: Boolean = false) = addBlocker(type.id, optional)
@JvmOverloads
fun addFeatureResult(
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))
fun addResult(result: AndroidResearchResult): Builder {
results.add(result)
return this
}
@JvmOverloads
fun addFeatureResult(
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(id: ResourceLocation, optional: Boolean = false): Builder {
return addResult(AndroidResearchResult.Feature(id, optional))
}
fun addFeatureResult(
id: ResourceLocation,
rigid: Boolean = false,
transformersUp: Collection<AndroidResultTransformer> = listOf(),
transformersDown: Collection<AndroidResultTransformer> = listOf(),
): Builder {
features.add(FeatureReference(id, 0, rigid, transformersUp, transformersDown))
return this
fun addFeatureResult(feature: AndroidFeatureType<*>, optional: Boolean = false): Builder {
return addFeatureResult(feature.registryName!!, optional)
}
fun addFeatureResult(ref: FeatureReference): Builder {
features.add(ref)
return this
fun addFeatureLevel(id: ResourceLocation, optional: Boolean = false, levels: Int = 1): Builder {
return addResult(AndroidResearchResult.FeatureLevel(id, optional, levels))
}
fun addFeatureLevel(feature: AndroidFeatureType<*>, optional: Boolean = false, levels: Int = 1): Builder {
return addFeatureLevel(feature.registryName!!, optional, levels)
}
fun addItem(cost: ItemStack): Builder {
@ -845,9 +569,8 @@ class AndroidResearchType(
prerequisites = prerequisites,
blockedBy = blockers,
items = items,
features = features,
descriptionLines = description ?: listOf(),
descriptionSuppliers = descriptionSuppliers ?: listOf(),
results = results,
description = description,
experienceLevels = experience,
customName = customName,
skinIcon = skinIcon?.toJson(),

View File

@ -1,13 +1,16 @@
package ru.dbotthepony.mc.otm.android
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.nbt.CompoundTag
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) {
var isActive by synchronizer.bool(setter = setter@{ value, access, setByRemote ->
if (value != access.read()) {
if (value != access.readBoolean()) {
access.write(value)
if (!setByRemote) {
@ -18,18 +21,23 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma
}
}
}
})
}).property
open val allowToSwitchByPlayer: Boolean get() = true
open val allowToSwitchByPlayerWhileSpectator: Boolean get() = true
open val maxCooldown: Int get() = 0
open var cooldown by synchronizer.int()
open var cooldown by synchronizer.int().property
val isOnCooldown: Boolean
get() = maxCooldown > 0 && cooldown > 0
val cooldownPercent: Float get() {
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)
}
@ -37,9 +45,9 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma
cooldown = maxCooldown
}
// TODO: PoseStack is stripped from server dist
// TODO: GuiGraphics is stripped from server dist
// 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 {
return super.serializeNBT().also {

View File

@ -13,7 +13,7 @@ class AttackBoostFeature(android: MatteryPlayerCapability) : AndroidFeature(Andr
if (modifier != null) {
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.vertex.PoseStack
import com.mojang.math.Vector3f
import net.minecraft.ChatFormatting
import net.minecraft.client.Camera
import net.minecraft.client.renderer.LevelRenderer
import net.minecraft.core.BlockPos
@ -27,29 +25,31 @@ import net.minecraftforge.event.ForgeEventFactory
import net.minecraftforge.event.entity.living.LivingDeathEvent
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
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.AndroidResearchManager
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.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
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.core.Vector
import ru.dbotthepony.mc.otm.core.asVector
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.client.render.sprites.sprite
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.genericPositions
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.core.shortestDistanceBetween
import ru.dbotthepony.mc.otm.core.times
import ru.dbotthepony.mc.otm.core.holder
import ru.dbotthepony.mc.otm.core.math.RGBAColor
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.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
import java.util.*
import kotlin.math.sin
@ -59,10 +59,10 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
private set
override val maxCooldown: Int
get() = ServerConfig.EnderTeleporter.COOLDOWN
get() = AndroidConfig.EnderTeleporter.COOLDOWN
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 {
@ -111,14 +111,14 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
}
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)
for (extend in 1 .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
for (extend in 1 .. AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
val pos = blockPos + normal * extend
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)
if (isValidPosition(newPos)) {
@ -141,7 +141,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
val result = ply.level.clip(ClipContext(
headPosition,
headPosition + aimVector * (ServerConfig.EnderTeleporter.MAX_DISTANCE * 2.0),
headPosition + aimVector * (AndroidConfig.EnderTeleporter.MAX_DISTANCE * 2.0),
ClipContext.Block.COLLIDER,
ClipContext.Fluid.NONE,
ply
@ -157,7 +157,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
!ply.isShiftKeyDown &&
result.direction == Direction.UP &&
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())
}
@ -215,14 +215,14 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
if (!isAirGap(pos)) {
phasedBlocks++
if (phasedBlocks >= ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
if (phasedBlocks >= AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
break
}
phasedBlocksList.add(pos)
}
if (shortestDistanceBetween(testPositions, pos.asVector()) > ServerConfig.EnderTeleporter.MAX_DISTANCE) {
if (shortestDistanceBetween(testPositions, pos.asVector()) > AndroidConfig.EnderTeleporter.MAX_DISTANCE) {
break
}
@ -269,14 +269,14 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
if (!isAirGap(pos)) {
phasedBlocks++
if (phasedBlocks >= ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
if (phasedBlocks >= AndroidConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
break
}
phasedBlocksList.add(pos)
}
if (shortestDistanceBetween(testPositions, pos.asVector()) > ServerConfig.EnderTeleporter.MAX_DISTANCE) {
if (shortestDistanceBetween(testPositions, pos.asVector()) > AndroidConfig.EnderTeleporter.MAX_DISTANCE) {
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)
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
}
putOnCooldown()
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.teleportTo(event.targetX, event.targetY, event.targetZ)
@ -333,8 +333,8 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
poseStack.pushPose()
poseStack.translate(x - vx, y - vy, z - vz)
poseStack.mulPose(Vector3f.YP.rotationDegrees(-camera.yRot))
poseStack.mulPose(Vector3f.XP.rotationDegrees(camera.xRot))
poseStack.rotateYDegrees(-camera.yRot)
poseStack.rotateXDegrees(camera.xRot)
val size = 1f + sin(milliTime / 250.0).toFloat() * 0.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) {
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) {
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_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 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) })
val SPRITE = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/item/black_hole.png").sprite(0f, 0f, 16f, 16f, 16f, 16f)
fun onEntityDeath(event: LivingDeathEvent) {
val android = event.entity.matteryPlayer ?: return
val server = NULLABLE_MINECRAFT_SERVER ?: return
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) {
EnderTeleporterFallDeathTrigger.trigger(event.entity as ServerPlayer)

View File

@ -1,32 +1,25 @@
package ru.dbotthepony.mc.otm.android.feature
import net.minecraft.ChatFormatting
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraftforge.event.entity.living.LivingAttackEvent
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.AndroidResearchManager
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.FALL_DAMPENERS, capability) {
override fun onHurt(event: LivingHurtEvent) {
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
event.amount = ((event.amount - flat) * (1f - reduction)).coerceAtLeast(0f)
if (reduction >= 1f) {
if (event.amount == 0f) {
event.isCanceled = true
event.amount = 0f
} else {
event.amount *= (1f - reduction)
}
if (ply is ServerPlayer && ply.health > event.amount && ply.health <= old) {
@ -35,9 +28,14 @@ class FallDampenersFeature(capability: MatteryPlayerCapability) : AndroidFeature
}
}
companion object {
val DESCRIPTION = AndroidResearchManager.descriptionFuncs.register(ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.FALL_DAMPENERS)) { level: Int ->
TranslatableComponent("otm.fall_dampeners.description", TextComponent("%.1f".format((ServerConfig.FALL_DAMAGE_REDUCTION_PER_LEVEL * level).toFloat().coerceAtLeast(0f).coerceAtMost(1f) * 100f)).withStyle(ChatFormatting.YELLOW))
override fun onAttack(event: LivingAttackEvent) {
if (event.source.isFall) {
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
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.ChatFormatting
import net.minecraft.client.multiplayer.ClientLevel
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.item.ItemEntity
import net.minecraftforge.event.ForgeEventFactory
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.config.AndroidConfig
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.extractEnergyInner
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.TextComponent
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.math.Vector
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
import ru.dbotthepony.mc.otm.core.minus
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.core.math.RGBAColor
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.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.WorldNetworkChannel
import ru.dbotthepony.mc.otm.network.packetHandled
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import java.util.UUID
import java.util.WeakHashMap
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) {
companion object {
@ -57,8 +44,7 @@ class ItemEntityDataPacket(val itemUUID: Int, val owner: UUID? = null, val age:
buff.writeBoolean(hasPickupDelay)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
override fun play(context: MNetworkContext) {
val level = minecraft.player?.level as ClientLevel? ?: return
val entity = level.getEntity(itemUUID) as ItemEntity? ?: return
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 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
}
val entities = ply.level.getEntitiesInEllipsoid(
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
)
@ -93,7 +79,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
ent as ItemEntity
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)) {
continue
@ -104,7 +90,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
if (data.position.distanceToSqr(ent.position) < 1.0) {
data.ticksSinceActivity++
} else {
if (!android.androidEnergy.extractEnergyInnerExact(ServerConfig.AndroidItemMagnet.POWER_DRAW, false).isPositive) {
if (!android.androidEnergy.extractEnergyExact(AndroidConfig.Magnet.POWER_DRAW, false)) {
return
}
@ -120,7 +106,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
override fun 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)
}
}
@ -133,15 +119,7 @@ class ItemMagnetFeature(capability: MatteryPlayerCapability) : AndroidSwitchable
}
}
override fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) {
ResearchIcons.ICON_ITEM_MAGNET.render(stack, x, y, width, height)
}
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) })
override fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor) {
ResearchIcons.ICON_ITEM_MAGNET.render(graphics, x, y, width, height, color = color)
}
}

View File

@ -1,67 +1,50 @@
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.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
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.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.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.Vector
import ru.dbotthepony.mc.otm.core.formatPower
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.math.RGBAColor
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.MatteryPlayerNetworkChannel
import ru.dbotthepony.mc.otm.network.enqueueWork
import ru.dbotthepony.mc.otm.network.packetHandled
import ru.dbotthepony.mc.otm.network.sender
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.MSoundEvents
import java.util.function.Supplier
object TriggerJumpBoostPacket : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
// no op
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.packetHandled = true
override fun play(context: MNetworkContext) {
val mattery = context.sender?.matteryPlayer ?: return
context.enqueueWork {
val mattery = context.sender?.matteryPlayer ?: return@enqueueWork
if (!mattery.isAndroid)
return
if (!mattery.isAndroid)
return@enqueueWork
val feature = mattery.getFeature(AndroidFeatures.JUMP_BOOST) ?: return
val feature = mattery.getFeature(AndroidFeatures.JUMP_BOOST) as JumpBoostFeature? ?: return@enqueueWork
if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, false)) {
feature.putOnCooldown()
if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyInnerExact(ServerConfig.AndroidJumpBoost.ENERGY_COST, false).isPositive) {
feature.putOnCooldown()
context.sender.level.playSound(
context.sender, context.sender,
MSoundEvents.ANDROID_JUMP_BOOST, SoundSource.PLAYERS,
1f, 1f
)
context.sender?.let {
it.level.playSound(
it,
it,
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
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 ->
access.write(value)
@ -78,7 +61,7 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
if (setByRemote) {
tickCooldownClient = false
}
})
}).property
private var lastGround = false
@ -92,19 +75,18 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
val old = lastGround
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) {
ply.deltaMovement += Vector(0.0, ServerConfig.AndroidJumpBoost.POWER * (level + 1) / 20.0, 0.0)
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, AndroidConfig.JumpBoost.POWER * (level + 1) / 20.0, 0.0)
putOnCooldown()
MatteryPlayerNetworkChannel.sendToServer(TriggerJumpBoostPacket)
ply.level.playSound(
ply,
ply,
MSoundEvents.ANDROID_JUMP_BOOST,
SoundSource.PLAYERS,
1f,
1f
ply, ply,
MSoundEvents.ANDROID_JUMP_BOOST, 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) {
if (cooldown > 0) {
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) })
override fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor) {
ResearchIcons.ICON_JUMP_BOOST.render(graphics, x, y, width, height, color = if (cooldown > 0) color * RGBAColor.REDDISH else color)
}
}

View File

@ -1,9 +1,12 @@
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.Attributes
import net.minecraft.world.entity.player.Player
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import java.util.*
@ -31,5 +34,34 @@ class LimbOverclockingFeature(android: MatteryPlayerCapability) : AndroidFeature
companion object {
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.server.level.ServerPlayer
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.AndroidResearchManager
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact
import ru.dbotthepony.mc.otm.core.Decimal
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
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.triggers.NanobotsArmorTrigger
import kotlin.math.roundToInt
class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) {
var strength: Int = 0
set(value) { field = value.coerceIn(0 .. 3) }
var strength by synchronizer.int(
setter = setter@{
value, access, _ -> access.write(value.coerceIn(0 .. 3))
}
).property
var speed: Int = 0
set(value) { field = value.coerceIn(0 .. 3) }
private var ticksPassed = 0
private var layers = 0
var layers by synchronizer.int().property
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++
if (ticksPassed >= TICKS[speed]) {
layers++
android.androidEnergy.extractEnergyInner(ENERGY_PER_LAYER, false)
android.androidEnergy.extractEnergy(ENERGY_PER_LAYER, false)
ticksPassed = 0
}
} else {
ticksPassed = 0
@ -48,7 +50,7 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
if (absorbed > 0.1f) {
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 ply = ply
@ -101,33 +103,5 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
0.45f,
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