From 27a3496310edf1b59d9004e6653036d7bc33074b Mon Sep 17 00:00:00 2001 From: Zontreck Date: Wed, 28 Feb 2024 15:04:29 -0700 Subject: [PATCH] Port it forward! --- build.gradle | 308 +++-- gradle.properties | 70 +- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 61574 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 18 +- gradlew.bat | 15 +- readme.md | 10 +- settings.gradle | 8 +- .../zontreck/engineerdecor}/ModConfig.java | 13 +- .../zontreck/engineerdecor}/ModContent.java | 8 +- .../engineerdecor}/ModEngineersDecor.java | 17 +- .../engineerdecor}/blocks/EdBreaker.java | 18 +- .../engineerdecor}/blocks/EdCatwalkBlock.java | 6 +- .../blocks/EdCatwalkStairsBlock.java | 8 +- .../blocks/EdCatwalkTopAlignedBlock.java | 6 +- .../engineerdecor}/blocks/EdChair.java | 8 +- .../engineerdecor}/blocks/EdChimneyBlock.java | 4 +- .../blocks/EdChimneyTrunkBlock.java | 2 +- .../blocks/EdCornerOrnamentedBlock.java | 6 +- .../blocks/EdDoubleGateBlock.java | 6 +- .../engineerdecor}/blocks/EdDropper.java | 42 +- .../blocks/EdElectricalFurnace.java | 18 +- .../engineerdecor}/blocks/EdFenceBlock.java | 4 +- .../blocks/EdFloorGratingBlock.java | 4 +- .../engineerdecor}/blocks/EdFluidBarrel.java | 16 +- .../engineerdecor}/blocks/EdFluidFunnel.java | 12 +- .../engineerdecor}/blocks/EdFreezer.java | 12 +- .../engineerdecor}/blocks/EdFurnace.java | 24 +- .../engineerdecor}/blocks/EdGlassBlock.java | 6 +- .../engineerdecor}/blocks/EdHatchBlock.java | 6 +- .../engineerdecor}/blocks/EdHopper.java | 5 +- .../blocks/EdHorizontalSupportBlock.java | 10 +- .../engineerdecor}/blocks/EdLadderBlock.java | 8 +- .../engineerdecor}/blocks/EdMilker.java | 7 +- .../blocks/EdMineralSmelter.java | 18 +- .../engineerdecor}/blocks/EdPipeValve.java | 12 +- .../engineerdecor}/blocks/EdPlacer.java | 5 +- .../engineerdecor}/blocks/EdRoofBlock.java | 6 +- .../engineerdecor}/blocks/EdSolarPanel.java | 16 +- .../blocks/EdStraightPoleBlock.java | 6 +- .../engineerdecor}/blocks/EdTestBlock.java | 5 +- .../engineerdecor}/blocks/EdTreeCutter.java | 16 +- .../engineerdecor}/blocks/EdWallBlock.java | 4 +- .../blocks/EdWasteIncinerator.java | 23 +- .../engineerdecor}/blocks/EdWindowBlock.java | 4 +- .../blocks/EdgeAlignedRailingBlock.java | 4 +- .../engineerdecor}/detail/ModRenderers.java | 2 +- .../engineerdecor}/detail/TreeCutting.java | 4 +- .../engineerdecor}/eapi/jei/JEIPlugin.java | 2 +- .../zontreck/engineerdecor}/items/EdItem.java | 8 +- .../engineersdecor/libmc/Auxiliaries.java | 555 --------- .../wile/engineersdecor/libmc/Containers.java | 119 -- .../wile/engineersdecor/libmc/Crafting.java | 371 ------ .../wile/engineersdecor/libmc/Fluidics.java | 389 ------- .../java/wile/engineersdecor/libmc/Guis.java | 436 ------- .../engineersdecor/libmc/Inventories.java | 1017 ----------------- .../wile/engineersdecor/libmc/Networking.java | 387 ------- .../libmc/OptionalRecipeCondition.java | 195 ---- .../wile/engineersdecor/libmc/Overlay.java | 151 --- .../wile/engineersdecor/libmc/Registries.java | 223 ---- .../wile/engineersdecor/libmc/RfEnergy.java | 158 --- .../wile/engineersdecor/libmc/RsSignals.java | 45 - .../wile/engineersdecor/libmc/SidedProxy.java | 74 -- .../engineersdecor/libmc/SlabSliceBlock.java | 217 ---- .../engineersdecor/libmc/StandardBlocks.java | 650 ----------- .../libmc/StandardDoorBlock.java | 167 --- .../libmc/StandardEntityBlocks.java | 73 -- .../libmc/StandardFenceBlock.java | 199 ---- .../libmc/StandardStairsBlock.java | 53 - .../engineersdecor/libmc/TooltipDisplay.java | 118 -- .../libmc/VariantSlabBlock.java | 205 ---- .../libmc/VariantWallBlock.java | 197 ---- src/main/resources/META-INF/mods.toml | 103 +- src/main/resources/pack.mcmeta | 8 +- 74 files changed, 628 insertions(+), 6325 deletions(-) mode change 100644 => 100755 gradlew rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/ModConfig.java (98%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/ModContent.java (99%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/ModEngineersDecor.java (89%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdBreaker.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdCatwalkBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdCatwalkStairsBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdCatwalkTopAlignedBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdChair.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdChimneyBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdChimneyTrunkBlock.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdCornerOrnamentedBlock.java (94%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdDoubleGateBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdDropper.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdElectricalFurnace.java (98%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdFenceBlock.java (91%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdFloorGratingBlock.java (95%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdFluidBarrel.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdFluidFunnel.java (98%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdFreezer.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdFurnace.java (98%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdGlassBlock.java (92%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdHatchBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdHopper.java (99%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdHorizontalSupportBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdLadderBlock.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdMilker.java (99%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdMineralSmelter.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdPipeValve.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdPlacer.java (99%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdRoofBlock.java (98%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdSolarPanel.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdStraightPoleBlock.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdTestBlock.java (99%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdTreeCutter.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdWallBlock.java (91%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdWasteIncinerator.java (96%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdWindowBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/blocks/EdgeAlignedRailingBlock.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/detail/ModRenderers.java (97%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/detail/TreeCutting.java (98%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/eapi/jei/JEIPlugin.java (98%) rename src/main/java/{wile/engineersdecor => dev/zontreck/engineerdecor}/items/EdItem.java (86%) delete mode 100644 src/main/java/wile/engineersdecor/libmc/Auxiliaries.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Containers.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Crafting.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Fluidics.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Guis.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Inventories.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Networking.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/OptionalRecipeCondition.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Overlay.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/Registries.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/RfEnergy.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/RsSignals.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/SidedProxy.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/SlabSliceBlock.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/StandardBlocks.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/StandardDoorBlock.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/StandardEntityBlocks.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/StandardFenceBlock.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/StandardStairsBlock.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/TooltipDisplay.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/VariantSlabBlock.java delete mode 100644 src/main/java/wile/engineersdecor/libmc/VariantWallBlock.java diff --git a/build.gradle b/build.gradle index c877b89..3b7f962 100644 --- a/build.gradle +++ b/build.gradle @@ -1,85 +1,259 @@ -// @file build.gradle -// Engineer's decor mod gradle build. plugins { - id 'eclipse' - id 'maven-publish' - id 'net.minecraftforge.gradle' version '5.1.+' + id 'eclipse' + id 'idea' + id 'maven-publish' + id 'net.neoforged.gradle' version '[6.0.18,6.2)' + id 'org.spongepowered.mixin' version '0.7.+' + } + +version = mod_version +group = mod_group_id + +base { + archivesName = mod_id +} + + +java { + withSourcesJar() + withJavadocJar() +} + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(17) -//----------------------------------------------------------------------------- -version = "${version_engineersdecor}" -group = "wile.engineersdecor" -archivesBaseName = "engineersdecor-${version_minecraft}-forge" + +println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: mapping_channel, version: mapping_version + + // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. + // In most cases, it is not necessary to enable. + // enableEclipsePrepareRuns = true + // enableIdeaPrepareRuns = true + + // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. + // It is REQUIRED to be set to true for this template to function. + // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html + copyIdeResources = true + + // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. + // The folder name can be set on a run configuration using the "folderName" property. + // By default, the folder name of a run configuration is the name of the Gradle project containing it. + generateRunFolders = true + + // This property enables access transformers for use in development. + // They will be applied to the Minecraft artifact. + // The access transformer file can be anywhere in the project. + // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. + // This default location is a best practice to automatically put the file in the right place in the final jar. + // See https://docs.neoforged.net/docs/1.20.x/advanced/accesstransformers/ for more information. + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + // applies to all the run configs below + configureEach { + workingDirectory project.file("run/${it.name}") + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + "${mod_id}" { + source sourceSets.main + } + } + } + + client { + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', mod_id + } + + server { + property 'forge.enabledGameTestNamespaces', mod_id + + } + + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + property 'forge.enabledGameTestNamespaces', mod_id + } + + data { + // example of overriding the workingDirectory set in configureEach above + workingDirectory project.file('run-data') + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } repositories { - maven { name = "Progwml6 maven"; url = "https://dvs1.progwml6.com/files/maven/" } // JEI files - maven { name = "ModMaven"; url = "https://modmaven.k-4u.nl" } // JEI files, fallback - flatDir { dir 'libs' } // Mod jar dependencies in ./libs -} + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you -minecraft { - mappings channel: "official", version: "${version_minecraft}" - runs { - client { - workingDirectory project.file('run') - property 'forge.logging.markers', '' // SCAN,REGISTRIES,REGISTRYDUMP - property 'forge.logging.console.level', 'info' - mods { engineersdecor { source sourceSets.main } } } - server { - workingDirectory project.file('run') - property 'forge.logging.markers', '' // SCAN,REGISTRIES,REGISTRYDUMP - property 'forge.logging.console.level', 'info' - mods { engineersdecor { source sourceSets.main } } + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver + + maven { + name = "Aria's Creations Caches" + url = "https://maven.zontreck.com/repository/internal" + } + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + flatDir { + dir 'libs' + } + + //maven { + // name = "CurseMaven" + // url = "https://cursemaven.com" + //} + + maven { + name = "zontreck Maven" + url = "https://maven.zontreck.com/repository/zontreck" } - } } dependencies { - minecraft "net.minecraftforge:forge:${version_forge_minecraft}" - //compileOnly fg.deobf("mezz.jei:jei-${version_minecraft}-forge-api:${version_jei}") - //runtimeOnly fg.deobf("mezz.jei:jei-${version_minecraft}-forge:${version_jei}") + // Specify the version of Minecraft to use. + // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. + // The "userdev" classifier will be requested and setup by ForgeGradle. + // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], + // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. + minecraft "net.neoforged:forge:${minecraft_version}-${neo_version}" + + + implementation fg.deobf("dev.zontreck:LibZontreckMod:${libzontreck}") + + //implementation fg.deobf('software.bernie.geckolib:geckolib-forge-1.20:3.0.57') + //238222 4712868 + + //compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge-api:${jei}") + //runtimeOnly fg.deobf("mezz.jei:jei-${minecraft_version}-forge:${jei}") + + runtimeOnly fg.deobf("curse.maven:mekanism-268560:4866575") + runtimeOnly fg.deobf("curse.maven:worldedit-225608:4586218") + + // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings + // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime + // 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}") + + // Example mod dependency using a mod jar from ./libs with a flat dir repository + // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar + // The group id is ignored when searching -- in this case, it is "blank" + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + // For more info: + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + } -processResources { - outputs.upToDateWhen { false } - doLast { file("${sourceSets.main.output.resourcesDir}/.gitversion-engineersdecor").text = 'git log "-1" "--format=%h"'.execute().in.text.trim() } -} +// This block of code expands all declared replace properties in the specified resource targets. +// A missing property will result in an error. Properties are expanded using ${} Groovy notation. +// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. +// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html +tasks.withType(ProcessResources).configureEach { + var replaceProperties = [ + minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, + neo_version : neo_version, neo_version_range: neo_version_range, + loader_version_range: loader_version_range, + mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, + mod_authors : mod_authors, mod_description: mod_description, pack_format_number: pack_format_number, + ] + inputs.properties replaceProperties -jar { - manifest { - attributes([ - "Specification-Title": "engineersdecor", - "Specification-Vendor": "wilechaote", - "Specification-Version": "1", // We are version 1 of ourselves - "Implementation-Title": project.name, - "Implementation-Version": "${version_engineersdecor}", - "Implementation-Vendor" :"wilechaote", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } -} - -jar.finalizedBy('reobfJar') - -// Signing -import net.minecraftforge.gradle.common.tasks.SignJar -project.afterEvaluate { - task signJar(type: SignJar, dependsOn: jar) { - onlyIf { project.hasProperty("keystore_file") } - if(project.hasProperty("keystore_file")) { - keyStore = project.getProperty("keystore_file") - alias = project.getProperty("keystore_alias") - storePass = project.getProperty("keystore_pass") - keyPass = project.getProperty("keystore_keypass") - inputFile = jar.archiveFile - outputFile = jar.archiveFile - } else { - logger.warn("[WARNING] Signing skipped.") + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] } - } - reobfJar.finalizedBy('signJar') } +// Example for how to get properties into the manifest for reading at runtime. +tasks.named('jar', Jar).configure { + manifest { + attributes([ + 'Specification-Title' : mod_id, + 'Specification-Vendor' : mod_authors, + 'Specification-Version' : '1', // We are version 1 of ourselves + 'Implementation-Title' : project.name, + 'Implementation-Version' : project.jar.archiveVersion, + 'Implementation-Vendor' : mod_authors, + 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + + // This is the preferred method to reobfuscate your jar file + finalizedBy 'reobfJar' +} + + +// 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: +// tasks.named('publish').configure { +// dependsOn 'reobfJar' +// } + + +def MAVEN_PASSWORD_PROPERTY = "AriasCreationsMavenPassword" +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + artifact sourcesJar + artifact javadocJar + } + } + repositories { + maven { + url = "https://maven.zontreck.com/repository/zontreck" + name = "ariascreations" + if (project.findProperty(MAVEN_PASSWORD_PROPERTY) != null) { + credentials { + username = "admin" + password = project.findProperty(MAVEN_PASSWORD_PROPERTY) + } + } + } + } +} + + tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation } diff --git a/gradle.properties b/gradle.properties index b0389b1..375a91e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,62 @@ -# @file gradle.properties +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false -org.gradle.jvmargs=-Xmx8G -meta_modid=engineersdecor -meta_issues=https://github.com/stfwi/engineers-decor/issues -meta_download=https://www.curseforge.com/minecraft/mc-mods/engineers-decor/ -version_minecraft=1.19.2 -version_forge_minecraft=1.19.2-43.1.16 -version_jei=11.3.0.262 -version_engineersdecor=1.3.29 + +libzontreck=1201.11.022724.1602 + +## Environment Properties + +# The Minecraft version must agree with the Forge version to get a valid artifact +minecraft_version=1.20.1 + +minecraft_version_range=[1.20,1.21) +# The Neo version must agree with the Minecraft version to get a valid artifact +neo_version=47.1.65 +# The Neo version range can use any version of Neo as bounds or match the loader version range +neo_version_range=[47.1,) +# The loader version range can only use the major version of Neo/FML as bounds +loader_version_range=[47,) +# The mapping channel to use for mappings. +# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. +# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. +# +# | Channel | Version | | +# |-----------|----------------------|--------------------------------------------------------------------------------| +# | official | MCVersion | Official field/method names from Mojang mapping files | +# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | +# +# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. +# See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md +# +# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. +# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started +mapping_channel=official +# The mapping version to query from the mapping channel. +# This must match the format required by the mapping channel. +mapping_version=1.20.1 + + + +## Mod Properties + +# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} +# Must match the String constant located in the main mod class annotated with @Mod. +mod_id=otemod +# The human-readable display name for the mod. +mod_name=Engineer's Decor +# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. +mod_license=GPLv3 +# The mod version. See https://semver.org/ +mod_version=1201.10.022824.1434 +# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. +# This should match the base package used for the mod sources. +# See https://maven.apache.org/guides/mini/guide-naming-conventions.html +mod_group_id=dev.zontreck +# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. +mod_authors=zontreck +# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. +mod_description=Engineer's Decor, ported forward by zontreck, and now under new management + +# Pack version - this changes each minecraft release, in general. +pack_format_number=15 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..943f0cbfa754578e88a3dae77fce6e3dea56edbf 100644 GIT binary patch delta 36987 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 z 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 VBfu2+*qg&~f-ihLS3eum{s(|${^$Sz diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..37aef8d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index 1b6c787..65dcd68 --- a/gradlew +++ b/gradlew @@ -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. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -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 diff --git a/readme.md b/readme.md index ffd4341..a571460 100644 --- a/readme.md +++ b/readme.md @@ -1,16 +1,20 @@ -## Engineer's Decor (MC1.18.x) +## Engineer's Decor (MC1.20.x) -Mod sources for Minecraft version 1.18.x. +Mod sources for Minecraft version 1.20.x. - Description, credits, and features: Please see the readme in the repository root. -- Compiled mod distribution channel is curseforge: https://www.curseforge.com/minecraft/mc-mods/engineers-decor/files. +- Compiled mod distribution channel is modrinth: https://modrinth.com/zontreck/engineers-decor ---- ## Version history + - v1201.1.022824.1456 [P] Ported to 1.20.x + [X] Under new management + [C] Changed the version scheme to match all Aria's Creations mods + - v1.3.29 [F] Fenced config opt-out processing with exception handling in case config apply is called before registry events have finished. diff --git a/settings.gradle b/settings.gradle index fb61b26..8a72e7b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,10 @@ pluginManagement { repositories { gradlePluginPortal() - maven { url = 'https://maven.minecraftforge.net/' } + maven { url = "https://maven.zontreck.com/repository/internal" } } -} \ No newline at end of file +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' +} diff --git a/src/main/java/wile/engineersdecor/ModConfig.java b/src/main/java/dev/zontreck/engineerdecor/ModConfig.java similarity index 98% rename from src/main/java/wile/engineersdecor/ModConfig.java rename to src/main/java/dev/zontreck/engineerdecor/ModConfig.java index 2f127d2..6c1f54b 100644 --- a/src/main/java/wile/engineersdecor/ModConfig.java +++ b/src/main/java/dev/zontreck/engineerdecor/ModConfig.java @@ -7,19 +7,20 @@ * Main class for module settings. Handles reading and * saving the config file. */ -package wile.engineersdecor; +package dev.zontreck.engineerdecor; +import dev.zontreck.engineerdecor.blocks.*; +import dev.zontreck.engineerdecor.detail.TreeCutting; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.OptionalRecipeCondition; +import dev.zontreck.engineerdecor.libmc.SlabSliceBlock; +import dev.zontreck.engineerdecor.libmc.VariantSlabBlock; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraftforge.common.ForgeConfigSpec; import org.apache.commons.lang3.tuple.Pair; import wile.engineersdecor.blocks.*; -import wile.engineersdecor.detail.TreeCutting; -import wile.engineersdecor.libmc.SlabSliceBlock; -import wile.engineersdecor.libmc.VariantSlabBlock; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.OptionalRecipeCondition; import javax.annotation.Nullable; import java.util.*; diff --git a/src/main/java/wile/engineersdecor/ModContent.java b/src/main/java/dev/zontreck/engineerdecor/ModContent.java similarity index 99% rename from src/main/java/wile/engineersdecor/ModContent.java rename to src/main/java/dev/zontreck/engineerdecor/ModContent.java index 2eb6c62..c18cc26 100644 --- a/src/main/java/wile/engineersdecor/ModContent.java +++ b/src/main/java/dev/zontreck/engineerdecor/ModContent.java @@ -10,8 +10,12 @@ * Note: Straight forward definition of different blocks/entities * to make recipes, models and texture definitions easier. */ -package wile.engineersdecor; +package dev.zontreck.engineerdecor; +import dev.zontreck.engineerdecor.blocks.*; +import dev.zontreck.engineerdecor.detail.ModRenderers; +import dev.zontreck.engineerdecor.items.EdItem; +import dev.zontreck.engineerdecor.libmc.*; import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.renderer.entity.EntityRenderers; import net.minecraft.core.BlockPos; @@ -39,8 +43,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import wile.engineersdecor.blocks.*; -import wile.engineersdecor.detail.ModRenderers; -import wile.engineersdecor.items.EdItem; import wile.engineersdecor.libmc.*; import javax.annotation.Nonnull; diff --git a/src/main/java/wile/engineersdecor/ModEngineersDecor.java b/src/main/java/dev/zontreck/engineerdecor/ModEngineersDecor.java similarity index 89% rename from src/main/java/wile/engineersdecor/ModEngineersDecor.java rename to src/main/java/dev/zontreck/engineerdecor/ModEngineersDecor.java index 2cde506..7d2cd71 100644 --- a/src/main/java/wile/engineersdecor/ModEngineersDecor.java +++ b/src/main/java/dev/zontreck/engineerdecor/ModEngineersDecor.java @@ -1,5 +1,7 @@ -package wile.engineersdecor; +package dev.zontreck.engineerdecor; +import dev.zontreck.engineerdecor.blocks.EdLadderBlock; +import dev.zontreck.engineerdecor.libmc.*; import net.minecraft.world.entity.player.Player; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -14,11 +16,10 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.slf4j.Logger; -import wile.engineersdecor.blocks.EdLadderBlock; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.OptionalRecipeCondition; -import wile.engineersdecor.libmc.Overlay; -import wile.engineersdecor.libmc.Registries; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.OptionalRecipeCondition; +import dev.zontreck.engineerdecor.libmc.Overlay; +import dev.zontreck.engineerdecor.libmc.Registries; @Mod("engineersdecor") @@ -46,13 +47,13 @@ public class ModEngineersDecor private void onSetup(final FMLCommonSetupEvent event) { CraftingHelper.register(OptionalRecipeCondition.Serializer.INSTANCE); - wile.engineersdecor.libmc.Networking.init(MODID); + Networking.init(MODID); } private void onClientSetup(final FMLClientSetupEvent event) { Overlay.TextOverlayGui.on_config(0.75, 0x00ffaa00, 0x55333333, 0x55333333, 0x55444444); - wile.engineersdecor.libmc.Networking.OverlayTextMessage.setHandler(Overlay.TextOverlayGui::show); + Networking.OverlayTextMessage.setHandler(Overlay.TextOverlayGui::show); ModContent.registerMenuGuis(event); ModContent.registerBlockEntityRenderers(event); ModContent.processContentClientSide(event); diff --git a/src/main/java/wile/engineersdecor/blocks/EdBreaker.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdBreaker.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdBreaker.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdBreaker.java index 95c86fb..d09dab8 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdBreaker.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdBreaker.java @@ -6,7 +6,7 @@ * * Small Block Breaker */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -41,14 +41,14 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.IEnergyStorage; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Inventories; -import wile.engineersdecor.libmc.Overlay; -import wile.engineersdecor.libmc.RfEnergy; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.libmc.Overlay; +import dev.zontreck.engineerdecor.libmc.RfEnergy; import javax.annotation.Nullable; import java.util.HashSet; diff --git a/src/main/java/wile/engineersdecor/blocks/EdCatwalkBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdCatwalkBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkBlock.java index a7bde70..5f18528 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdCatwalkBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkBlock.java @@ -6,7 +6,7 @@ * * Bottom aligned platforms with railings. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -31,8 +31,8 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Inventories; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/src/main/java/wile/engineersdecor/blocks/EdCatwalkStairsBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkStairsBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdCatwalkStairsBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkStairsBlock.java index 482feee..a49ff35 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdCatwalkStairsBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkStairsBlock.java @@ -6,7 +6,7 @@ * * Stair version of the catwalk block, optional left/right railings. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -34,9 +34,9 @@ import net.minecraft.world.phys.shapes.BooleanOp; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; import javax.annotation.Nullable; import java.util.*; diff --git a/src/main/java/wile/engineersdecor/blocks/EdCatwalkTopAlignedBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkTopAlignedBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdCatwalkTopAlignedBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkTopAlignedBlock.java index 2bc0143..2fd81bb 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdCatwalkTopAlignedBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCatwalkTopAlignedBlock.java @@ -6,7 +6,7 @@ * * Top aligned platforms, down-connection to poles. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -32,8 +32,8 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/src/main/java/wile/engineersdecor/blocks/EdChair.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdChair.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdChair.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdChair.java index c0225c1..6307cc8 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdChair.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdChair.java @@ -6,7 +6,7 @@ * * Full block characteristics class. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -31,9 +31,9 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraftforge.network.PlayMessages; import net.minecraftforge.network.NetworkHooks; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; import java.util.List; diff --git a/src/main/java/wile/engineersdecor/blocks/EdChimneyBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdChimneyBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdChimneyBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdChimneyBlock.java index c62ddfa..5160fae 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdChimneyBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdChimneyBlock.java @@ -6,7 +6,7 @@ * * Block type for smoking chimneys. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -28,7 +28,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import wile.engineersdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; import javax.annotation.Nullable; diff --git a/src/main/java/wile/engineersdecor/blocks/EdChimneyTrunkBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdChimneyTrunkBlock.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdChimneyTrunkBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdChimneyTrunkBlock.java index 8fef447..60d6152 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdChimneyTrunkBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdChimneyTrunkBlock.java @@ -6,7 +6,7 @@ * * Roof block with chimney trunk, only straight. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.state.BlockBehaviour; diff --git a/src/main/java/wile/engineersdecor/blocks/EdCornerOrnamentedBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCornerOrnamentedBlock.java similarity index 94% rename from src/main/java/wile/engineersdecor/blocks/EdCornerOrnamentedBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdCornerOrnamentedBlock.java index 0dbecca..547400b 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdCornerOrnamentedBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdCornerOrnamentedBlock.java @@ -6,7 +6,7 @@ * * Block for corner/quoin ornamentation. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -17,8 +17,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec2; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; import javax.annotation.Nullable; import java.util.Arrays; diff --git a/src/main/java/wile/engineersdecor/blocks/EdDoubleGateBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdDoubleGateBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdDoubleGateBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdDoubleGateBlock.java index 43deb20..a75f1f5 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdDoubleGateBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdDoubleGateBlock.java @@ -6,7 +6,7 @@ * * Gate blocks that can be one or two segments high. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -32,8 +32,8 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/src/main/java/wile/engineersdecor/blocks/EdDropper.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdDropper.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdDropper.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdDropper.java index 9b9106f..3472852 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdDropper.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdDropper.java @@ -6,9 +6,11 @@ * * Dropper factory automation suitable. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import com.mojang.blaze3d.vertex.PoseStack; +import dev.zontreck.engineerdecor.libmc.Networking; +import dev.zontreck.engineerdecor.libmc.TooltipDisplay; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -46,18 +48,16 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Inventories; -import wile.engineersdecor.libmc.Inventories.InventoryRange; -import wile.engineersdecor.libmc.Inventories.StorageInventory; -import wile.engineersdecor.libmc.Networking; -import wile.engineersdecor.libmc.RsSignals; -import wile.engineersdecor.libmc.Guis; -import wile.engineersdecor.libmc.TooltipDisplay.TipRange; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.libmc.Inventories.InventoryRange; +import dev.zontreck.engineerdecor.libmc.Inventories.StorageInventory; +import dev.zontreck.engineerdecor.libmc.RsSignals; +import dev.zontreck.engineerdecor.libmc.Guis; import javax.annotation.Nullable; import java.util.ArrayList; @@ -783,14 +783,14 @@ public class EdDropper final String prefix = block.getDescriptionId() + ".tooltips."; final int x0 = getGuiLeft(), y0 = getGuiTop(); tooltip_.init( - new TipRange(x0+130, y0+10, 12, 25, Component.translatable(prefix + "velocity")), - new TipRange(x0+145, y0+10, 25, 25, Component.translatable(prefix + "direction")), - new TipRange(x0+129, y0+40, 44, 10, Component.translatable(prefix + "dropcount")), - new TipRange(x0+129, y0+50, 44, 10, Component.translatable(prefix + "period")), - new TipRange(x0+114, y0+51, 9, 9, Component.translatable(prefix + "rssignal")), - new TipRange(x0+162, y0+66, 7, 9, Component.translatable(prefix + "triggermode")), - new TipRange(x0+132, y0+66, 9, 9, Component.translatable(prefix + "filtergate")), - new TipRange(x0+148, y0+66, 9, 9, Component.translatable(prefix + "externgate")) + new TooltipDisplay.TipRange(x0+130, y0+10, 12, 25, Component.translatable(prefix + "velocity")), + new TooltipDisplay.TipRange(x0+145, y0+10, 25, 25, Component.translatable(prefix + "direction")), + new TooltipDisplay.TipRange(x0+129, y0+40, 44, 10, Component.translatable(prefix + "dropcount")), + new TooltipDisplay.TipRange(x0+129, y0+50, 44, 10, Component.translatable(prefix + "period")), + new TooltipDisplay.TipRange(x0+114, y0+51, 9, 9, Component.translatable(prefix + "rssignal")), + new TooltipDisplay.TipRange(x0+162, y0+66, 7, 9, Component.translatable(prefix + "triggermode")), + new TooltipDisplay.TipRange(x0+132, y0+66, 9, 9, Component.translatable(prefix + "filtergate")), + new TooltipDisplay.TipRange(x0+148, y0+66, 9, 9, Component.translatable(prefix + "externgate")) ); } } diff --git a/src/main/java/wile/engineersdecor/blocks/EdElectricalFurnace.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdElectricalFurnace.java similarity index 98% rename from src/main/java/wile/engineersdecor/blocks/EdElectricalFurnace.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdElectricalFurnace.java index 921da04..e06a6b3 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdElectricalFurnace.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdElectricalFurnace.java @@ -6,9 +6,10 @@ * * ED small electrical pass-through furnace. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import com.mojang.blaze3d.vertex.PoseStack; +import dev.zontreck.engineerdecor.libmc.*; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -52,12 +53,11 @@ import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; import wile.engineersdecor.libmc.*; -import wile.engineersdecor.libmc.Inventories.MappedItemHandler; -import wile.engineersdecor.libmc.Inventories.StorageInventory; -import wile.engineersdecor.libmc.TooltipDisplay.TipRange; +import dev.zontreck.engineerdecor.libmc.Inventories.MappedItemHandler; +import dev.zontreck.engineerdecor.libmc.Inventories.StorageInventory; import javax.annotation.Nullable; import java.util.ArrayList; @@ -859,9 +859,9 @@ public class EdElectricalFurnace final int x0 = getGuiLeft(), y0 = getGuiTop(); final Slot aux = menu.getSlot(ElectricalFurnaceTileEntity.SMELTING_AUX_SLOT_NO); tooltip_.init( - new TipRange(x0+135, y0+50, 25, 25, Component.translatable(prefix + "speed")), - new TipRange(x0+aux.x, y0+aux.y, 16, 16, Component.translatable(prefix + "auxslot")), - new TipRange(x0+80, y0+55, 50, 14, ()->{ + new TooltipDisplay.TipRange(x0+135, y0+50, 25, 25, Component.translatable(prefix + "speed")), + new TooltipDisplay.TipRange(x0+aux.x, y0+aux.y, 16, 16, Component.translatable(prefix + "auxslot")), + new TooltipDisplay.TipRange(x0+80, y0+55, 50, 14, ()->{ final int soc = getMenu().field(1) * 100 / Math.max(getMenu().field(5), 1); final int consumption = getMenu().field(7); return Component.translatable(prefix + "capacitors", soc, consumption); diff --git a/src/main/java/wile/engineersdecor/blocks/EdFenceBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFenceBlock.java similarity index 91% rename from src/main/java/wile/engineersdecor/blocks/EdFenceBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdFenceBlock.java index 8e66de2..f2de6d8 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFenceBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFenceBlock.java @@ -6,14 +6,14 @@ * * Wall blocks. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; -import wile.engineersdecor.libmc.StandardFenceBlock; +import dev.zontreck.engineerdecor.libmc.StandardFenceBlock; public class EdFenceBlock extends StandardFenceBlock diff --git a/src/main/java/wile/engineersdecor/blocks/EdFloorGratingBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFloorGratingBlock.java similarity index 95% rename from src/main/java/wile/engineersdecor/blocks/EdFloorGratingBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdFloorGratingBlock.java index e92e8dc..45ad2bc 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFloorGratingBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFloorGratingBlock.java @@ -6,7 +6,7 @@ * * Floor gratings. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; @@ -19,7 +19,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; -import wile.engineersdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; import javax.annotation.Nullable; diff --git a/src/main/java/wile/engineersdecor/blocks/EdFluidBarrel.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFluidBarrel.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdFluidBarrel.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdFluidBarrel.java index 1fcc21a..857db4f 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFluidBarrel.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFluidBarrel.java @@ -6,7 +6,7 @@ * * Simple fluid tank with a built-in gauge. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -50,13 +50,13 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Fluidics; -import wile.engineersdecor.libmc.Overlay; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Fluidics; +import dev.zontreck.engineerdecor.libmc.Overlay; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/src/main/java/wile/engineersdecor/blocks/EdFluidFunnel.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFluidFunnel.java similarity index 98% rename from src/main/java/wile/engineersdecor/blocks/EdFluidFunnel.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdFluidFunnel.java index 972f70f..f1a8580 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFluidFunnel.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFluidFunnel.java @@ -8,7 +8,7 @@ * Tracks flowing fluid to their source blocks. Compatible * with vanilla infinite water source. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -43,11 +43,11 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Fluidics; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Fluidics; import javax.annotation.Nullable; import java.util.*; diff --git a/src/main/java/wile/engineersdecor/blocks/EdFreezer.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFreezer.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdFreezer.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdFreezer.java index a6f7fbf..23ff41b 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFreezer.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFreezer.java @@ -7,7 +7,7 @@ * Small highly insulated stone liquification furnace * (magmatic phase). */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -45,11 +45,11 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Fluidics; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Fluidics; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/src/main/java/wile/engineersdecor/blocks/EdFurnace.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFurnace.java similarity index 98% rename from src/main/java/wile/engineersdecor/blocks/EdFurnace.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdFurnace.java index a676476..18a5187 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFurnace.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdFurnace.java @@ -6,7 +6,7 @@ * * ED Lab furnace. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.core.BlockPos; @@ -54,17 +54,17 @@ import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.registries.ForgeRegistries; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Inventories; -import wile.engineersdecor.libmc.Inventories.MappedItemHandler; -import wile.engineersdecor.libmc.Inventories.StorageInventory; -import wile.engineersdecor.libmc.Networking; -import wile.engineersdecor.libmc.RfEnergy; -import wile.engineersdecor.libmc.Guis; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.libmc.Inventories.MappedItemHandler; +import dev.zontreck.engineerdecor.libmc.Inventories.StorageInventory; +import dev.zontreck.engineerdecor.libmc.Networking; +import dev.zontreck.engineerdecor.libmc.RfEnergy; +import dev.zontreck.engineerdecor.libmc.Guis; import javax.annotation.Nullable; import java.util.*; diff --git a/src/main/java/wile/engineersdecor/blocks/EdGlassBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdGlassBlock.java similarity index 92% rename from src/main/java/wile/engineersdecor/blocks/EdGlassBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdGlassBlock.java index 1f96915..6de1b58 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdGlassBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdGlassBlock.java @@ -7,7 +7,7 @@ * Full block characteristics class. Explicitly overrides some * `Block` methods to return faster due to exclusive block properties. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; @@ -20,8 +20,8 @@ import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; import javax.annotation.Nullable; import java.util.List; diff --git a/src/main/java/wile/engineersdecor/blocks/EdHatchBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdHatchBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdHatchBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdHatchBlock.java index 0ba2018..9f368f5 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdHatchBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdHatchBlock.java @@ -6,7 +6,7 @@ * * Floor gratings. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -35,8 +35,8 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; import javax.annotation.Nullable; import java.util.List; diff --git a/src/main/java/wile/engineersdecor/blocks/EdHopper.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdHopper.java similarity index 99% rename from src/main/java/wile/engineersdecor/blocks/EdHopper.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdHopper.java index b4e1fc6..717cdfe 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdHopper.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdHopper.java @@ -6,9 +6,10 @@ * * Hopper, factory automation suitable. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import com.mojang.blaze3d.vertex.PoseStack; +import dev.zontreck.engineerdecor.libmc.*; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -41,7 +42,7 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; -import wile.engineersdecor.ModContent; +import dev.zontreck.engineerdecor.ModContent; import wile.engineersdecor.libmc.*; import javax.annotation.Nullable; diff --git a/src/main/java/wile/engineersdecor/blocks/EdHorizontalSupportBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdHorizontalSupportBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdHorizontalSupportBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdHorizontalSupportBlock.java index 00f03bd..5a8ec13 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdHorizontalSupportBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdHorizontalSupportBlock.java @@ -7,7 +7,7 @@ * Horizontal ceiling support. Symmetric x axis, fixed in * xz plane, therefore boolean placement state. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -38,10 +38,10 @@ import net.minecraft.world.phys.shapes.BooleanOp; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Inventories; import javax.annotation.Nullable; import java.util.HashMap; diff --git a/src/main/java/wile/engineersdecor/blocks/EdLadderBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdLadderBlock.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdLadderBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdLadderBlock.java index 85fe914..cfb5750 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdLadderBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdLadderBlock.java @@ -10,7 +10,7 @@ * time configuration), does not drop when the block behind * is broken, etc. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -34,9 +34,9 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; import javax.annotation.Nullable; import java.util.List; diff --git a/src/main/java/wile/engineersdecor/blocks/EdMilker.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdMilker.java similarity index 99% rename from src/main/java/wile/engineersdecor/blocks/EdMilker.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdMilker.java index 12de8cd..7302bbf 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdMilker.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdMilker.java @@ -6,8 +6,9 @@ * * Frequently attracts and milks nearby cows */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; +import dev.zontreck.engineerdecor.libmc.*; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -49,8 +50,8 @@ import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.registries.ForgeRegistries; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; import wile.engineersdecor.libmc.*; import javax.annotation.Nullable; diff --git a/src/main/java/wile/engineersdecor/blocks/EdMineralSmelter.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdMineralSmelter.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdMineralSmelter.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdMineralSmelter.java index 9e97539..373855c 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdMineralSmelter.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdMineralSmelter.java @@ -7,7 +7,7 @@ * Small highly insulated stone liquification furnace * (magmatic phase). */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -51,14 +51,14 @@ import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Fluidics; -import wile.engineersdecor.libmc.Inventories; -import wile.engineersdecor.libmc.RfEnergy; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Fluidics; +import dev.zontreck.engineerdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.libmc.RfEnergy; import javax.annotation.Nullable; import java.util.*; diff --git a/src/main/java/wile/engineersdecor/blocks/EdPipeValve.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdPipeValve.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdPipeValve.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdPipeValve.java index 23c8223..81ac822 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdPipeValve.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdPipeValve.java @@ -7,7 +7,7 @@ * Basically a piece of pipe that does not connect to * pipes on the side, and conducts fluids only in one way. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -35,11 +35,11 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.RsSignals; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.RsSignals; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/src/main/java/wile/engineersdecor/blocks/EdPlacer.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdPlacer.java similarity index 99% rename from src/main/java/wile/engineersdecor/blocks/EdPlacer.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdPlacer.java index 7ebb369..c00293f 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdPlacer.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdPlacer.java @@ -6,9 +6,10 @@ * * Block placer and planter, factory automation suitable. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import com.mojang.blaze3d.vertex.PoseStack; +import dev.zontreck.engineerdecor.libmc.*; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -53,7 +54,7 @@ import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.IFluidBlock; import net.minecraftforge.items.IItemHandler; -import wile.engineersdecor.ModContent; +import dev.zontreck.engineerdecor.ModContent; import wile.engineersdecor.libmc.*; import javax.annotation.Nullable; diff --git a/src/main/java/wile/engineersdecor/blocks/EdRoofBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdRoofBlock.java similarity index 98% rename from src/main/java/wile/engineersdecor/blocks/EdRoofBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdRoofBlock.java index f2e7973..330f40d 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdRoofBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdRoofBlock.java @@ -6,7 +6,7 @@ * * Roof blocks. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -33,8 +33,8 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; public class EdRoofBlock extends StandardBlocks.HorizontalWaterLoggable diff --git a/src/main/java/wile/engineersdecor/blocks/EdSolarPanel.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdSolarPanel.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdSolarPanel.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdSolarPanel.java index 971b5da..bbc3f52 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdSolarPanel.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdSolarPanel.java @@ -6,7 +6,7 @@ * * Smaller (cutout) block with a defined facing. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -29,13 +29,13 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.IEnergyStorage; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Overlay; -import wile.engineersdecor.libmc.RfEnergy; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Overlay; +import dev.zontreck.engineerdecor.libmc.RfEnergy; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/src/main/java/wile/engineersdecor/blocks/EdStraightPoleBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdStraightPoleBlock.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdStraightPoleBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdStraightPoleBlock.java index a754174..1a902b6 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdStraightPoleBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdStraightPoleBlock.java @@ -6,7 +6,7 @@ * * Smaller (cutout) block with a defined facing. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -26,8 +26,8 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.Inventories; import javax.annotation.Nullable; import java.util.Arrays; diff --git a/src/main/java/wile/engineersdecor/blocks/EdTestBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdTestBlock.java similarity index 99% rename from src/main/java/wile/engineersdecor/blocks/EdTestBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdTestBlock.java index 60d0e49..05cf6cb 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdTestBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdTestBlock.java @@ -6,8 +6,9 @@ * * Creative mod testing block */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; +import dev.zontreck.engineerdecor.libmc.*; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -37,7 +38,7 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.registries.ForgeRegistries; -import wile.engineersdecor.ModContent; +import dev.zontreck.engineerdecor.ModContent; import wile.engineersdecor.libmc.*; diff --git a/src/main/java/wile/engineersdecor/blocks/EdTreeCutter.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdTreeCutter.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdTreeCutter.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdTreeCutter.java index 8ff3850..40c5307 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdTreeCutter.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdTreeCutter.java @@ -6,8 +6,9 @@ * * Small Tree Cutter */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; +import dev.zontreck.engineerdecor.detail.TreeCutting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; @@ -34,13 +35,12 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.IEnergyStorage; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.detail.TreeCutting; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Overlay; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Overlay; import javax.annotation.Nullable; import java.util.Random; diff --git a/src/main/java/wile/engineersdecor/blocks/EdWallBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdWallBlock.java similarity index 91% rename from src/main/java/wile/engineersdecor/blocks/EdWallBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdWallBlock.java index 13fa0cf..e267eef 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdWallBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdWallBlock.java @@ -6,7 +6,7 @@ * * Wall blocks. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -15,7 +15,7 @@ import net.minecraft.world.level.block.IronBarsBlock; import net.minecraft.world.level.block.StainedGlassPaneBlock; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; -import wile.engineersdecor.libmc.VariantWallBlock; +import dev.zontreck.engineerdecor.libmc.VariantWallBlock; public class EdWallBlock extends VariantWallBlock diff --git a/src/main/java/wile/engineersdecor/blocks/EdWasteIncinerator.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdWasteIncinerator.java similarity index 96% rename from src/main/java/wile/engineersdecor/blocks/EdWasteIncinerator.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdWasteIncinerator.java index 3224d64..632272c 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdWasteIncinerator.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdWasteIncinerator.java @@ -6,8 +6,9 @@ * * Trash/void/nullifier device with internal fifos. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; +import dev.zontreck.engineerdecor.libmc.RfEnergy; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; @@ -40,16 +41,14 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.items.IItemHandler; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.blocks.EdFurnace.FurnaceBlock; -import wile.engineersdecor.libmc.StandardBlocks; -import wile.engineersdecor.libmc.StandardEntityBlocks; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Inventories; -import wile.engineersdecor.libmc.RfEnergy; -import wile.engineersdecor.libmc.RsSignals; -import wile.engineersdecor.libmc.Guis; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.ModContent; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardEntityBlocks; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Inventories; +import dev.zontreck.engineerdecor.libmc.RsSignals; +import dev.zontreck.engineerdecor.libmc.Guis; import javax.annotation.Nullable; import java.util.ArrayList; @@ -75,7 +74,7 @@ public class EdWasteIncinerator public static class WasteIncineratorBlock extends StandardBlocks.Cutout implements StandardEntityBlocks.IStandardEntityBlock { - public static final BooleanProperty LIT = FurnaceBlock.LIT; + public static final BooleanProperty LIT = EdFurnace.FurnaceBlock.LIT; public WasteIncineratorBlock(long config, BlockBehaviour.Properties builder, final AABB unrotatedAABB) { super(config, builder, unrotatedAABB); } diff --git a/src/main/java/wile/engineersdecor/blocks/EdWindowBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdWindowBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdWindowBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdWindowBlock.java index f592604..7d5ec06 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdWindowBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdWindowBlock.java @@ -6,7 +6,7 @@ * * Mod windows. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -24,7 +24,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; -import wile.engineersdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; import javax.annotation.Nullable; import java.util.Arrays; diff --git a/src/main/java/wile/engineersdecor/blocks/EdgeAlignedRailingBlock.java b/src/main/java/dev/zontreck/engineerdecor/blocks/EdgeAlignedRailingBlock.java similarity index 97% rename from src/main/java/wile/engineersdecor/blocks/EdgeAlignedRailingBlock.java rename to src/main/java/dev/zontreck/engineerdecor/blocks/EdgeAlignedRailingBlock.java index cbefda8..7067ef8 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdgeAlignedRailingBlock.java +++ b/src/main/java/dev/zontreck/engineerdecor/blocks/EdgeAlignedRailingBlock.java @@ -6,7 +6,7 @@ * * Bottom aligned platforms with railings. */ -package wile.engineersdecor.blocks; +package dev.zontreck.engineerdecor.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -26,7 +26,7 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; -import wile.engineersdecor.libmc.StandardBlocks; +import dev.zontreck.engineerdecor.libmc.StandardBlocks; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/src/main/java/wile/engineersdecor/detail/ModRenderers.java b/src/main/java/dev/zontreck/engineerdecor/detail/ModRenderers.java similarity index 97% rename from src/main/java/wile/engineersdecor/detail/ModRenderers.java rename to src/main/java/dev/zontreck/engineerdecor/detail/ModRenderers.java index af05211..63cdef6 100644 --- a/src/main/java/wile/engineersdecor/detail/ModRenderers.java +++ b/src/main/java/dev/zontreck/engineerdecor/detail/ModRenderers.java @@ -7,7 +7,7 @@ * Yet unstructured initial experiments with TESRs. * May be structured after I know what I am doing there. */ -package wile.engineersdecor.detail; +package dev.zontreck.engineerdecor.detail; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; diff --git a/src/main/java/wile/engineersdecor/detail/TreeCutting.java b/src/main/java/dev/zontreck/engineerdecor/detail/TreeCutting.java similarity index 98% rename from src/main/java/wile/engineersdecor/detail/TreeCutting.java rename to src/main/java/dev/zontreck/engineerdecor/detail/TreeCutting.java index c3b1a56..952b014 100644 --- a/src/main/java/wile/engineersdecor/detail/TreeCutting.java +++ b/src/main/java/dev/zontreck/engineerdecor/detail/TreeCutting.java @@ -6,7 +6,7 @@ * * Simple tree cutting algorithm. */ -package wile.engineersdecor.detail; +package dev.zontreck.engineerdecor.detail; import com.google.common.collect.ImmutableList; import net.minecraft.core.BlockPos; @@ -20,7 +20,7 @@ import net.minecraft.world.level.block.LeavesBlock; import net.minecraft.world.level.block.VineBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.registries.ForgeRegistries; -import wile.engineersdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; import java.util.*; import java.util.stream.Collectors; diff --git a/src/main/java/wile/engineersdecor/eapi/jei/JEIPlugin.java b/src/main/java/dev/zontreck/engineerdecor/eapi/jei/JEIPlugin.java similarity index 98% rename from src/main/java/wile/engineersdecor/eapi/jei/JEIPlugin.java rename to src/main/java/dev/zontreck/engineerdecor/eapi/jei/JEIPlugin.java index 7f2aeaa..a704262 100644 --- a/src/main/java/wile/engineersdecor/eapi/jei/JEIPlugin.java +++ b/src/main/java/dev/zontreck/engineerdecor/eapi/jei/JEIPlugin.java @@ -6,7 +6,7 @@ * * JEI plugin (see https://github.com/mezz/JustEnoughItems/wiki/Creating-Plugins) */ -package wile.engineersdecor.eapi.jei; +package dev.zontreck.engineerdecor.eapi.jei; public class JEIPlugin {} /* diff --git a/src/main/java/wile/engineersdecor/items/EdItem.java b/src/main/java/dev/zontreck/engineerdecor/items/EdItem.java similarity index 86% rename from src/main/java/wile/engineersdecor/items/EdItem.java rename to src/main/java/dev/zontreck/engineerdecor/items/EdItem.java index 718a09c..3cbb714 100644 --- a/src/main/java/wile/engineersdecor/items/EdItem.java +++ b/src/main/java/dev/zontreck/engineerdecor/items/EdItem.java @@ -6,7 +6,7 @@ * * Basic item functionality for mod items. */ -package wile.engineersdecor.items; +package dev.zontreck.engineerdecor.items; import net.minecraft.network.chat.Component; import net.minecraft.world.item.CreativeModeTab; @@ -16,9 +16,9 @@ import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import wile.engineersdecor.ModConfig; -import wile.engineersdecor.libmc.Auxiliaries; -import wile.engineersdecor.libmc.Registries; +import dev.zontreck.engineerdecor.ModConfig; +import dev.zontreck.engineerdecor.libmc.Auxiliaries; +import dev.zontreck.engineerdecor.libmc.Registries; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/src/main/java/wile/engineersdecor/libmc/Auxiliaries.java b/src/main/java/wile/engineersdecor/libmc/Auxiliaries.java deleted file mode 100644 index 58faf4e..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Auxiliaries.java +++ /dev/null @@ -1,555 +0,0 @@ -/* - * @file Auxiliaries.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * General commonly used functionality. - */ -package wile.engineersdecor.libmc; - -import com.mojang.blaze3d.platform.InputConstants; -import net.minecraft.ChatFormatting; -import net.minecraft.SharedConstants; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Registry; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.ComponentUtils; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.BooleanOp; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.registries.ForgeRegistries; -import org.slf4j.Logger; -import org.lwjgl.glfw.GLFW; - -import javax.annotation.Nullable; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - - -public class Auxiliaries -{ - private static String modid; - private static Logger logger; - private static Supplier server_config_supplier = CompoundTag::new; - - public static void init(String modid, Logger logger, Supplier server_config_supplier) - { - Auxiliaries.modid = modid; - Auxiliaries.logger = logger; - Auxiliaries.server_config_supplier = server_config_supplier; - } - - // ------------------------------------------------------------------------------------------------------------------- - // Mod specific exports - // ------------------------------------------------------------------------------------------------------------------- - - public static String modid() - { return modid; } - - public static Logger logger() - { return logger; } - - // ------------------------------------------------------------------------------------------------------------------- - // Sidedness, system/environment, tagging interfaces - // ------------------------------------------------------------------------------------------------------------------- - - public interface IExperimentalFeature {} - - public static boolean isModLoaded(final String registry_name) - { return ModList.get().isLoaded(registry_name); } - - public static boolean isDevelopmentMode() - { return SharedConstants.IS_RUNNING_IN_IDE; } - - @OnlyIn(Dist.CLIENT) - public static boolean isShiftDown() - { - return (InputConstants.isKeyDown(SidedProxy.mc().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT_SHIFT) || - InputConstants.isKeyDown(SidedProxy.mc().getWindow().getWindow(), GLFW.GLFW_KEY_RIGHT_SHIFT)); - } - - @OnlyIn(Dist.CLIENT) - public static boolean isCtrlDown() - { - return (InputConstants.isKeyDown(SidedProxy.mc().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT_CONTROL) || - InputConstants.isKeyDown(SidedProxy.mc().getWindow().getWindow(), GLFW.GLFW_KEY_RIGHT_CONTROL)); - } - - // ------------------------------------------------------------------------------------------------------------------- - // Logging - // ------------------------------------------------------------------------------------------------------------------- - - public static void logInfo(final String msg) - { logger.info(msg); } - - public static void logWarn(final String msg) - { logger.warn(msg); } - - public static void logError(final String msg) - { logger.error(msg); } - - public static void logDebug(final String msg) - { /*logger.debug(msg);*/ } - - // ------------------------------------------------------------------------------------------------------------------- - // Localization, text formatting - // ------------------------------------------------------------------------------------------------------------------- - - /** - * Text localization wrapper, implicitly prepends `MODID` to the - * translation keys. Forces formatting argument, nullable if no special formatting shall be applied.. - */ - public static MutableComponent localizable(String modtrkey, Object... args) - { return Component.translatable((modtrkey.startsWith("block.") || (modtrkey.startsWith("item."))) ? (modtrkey) : (modid+"."+modtrkey), args); } - - public static MutableComponent localizable(String modtrkey, @Nullable ChatFormatting color, Object... args) - { - final MutableComponent tr = Component.translatable(modid+"."+modtrkey, args); - if(color!=null) tr.getStyle().applyFormat(color); - return tr; - } - - public static Component localizable(String modtrkey) - { return localizable(modtrkey, new Object[]{}); } - - public static Component localizable_block_key(String blocksubkey) - { return Component.translatable("block."+modid+"."+blocksubkey); } - - @OnlyIn(Dist.CLIENT) - public static String localize(String translationKey, Object... args) - { - Component tr = Component.translatable(translationKey, args); - tr.getStyle().applyFormat(ChatFormatting.RESET); - final String ft = tr.getString(); - if(ft.contains("${")) { - // Non-recursive, non-argument lang file entry cross referencing. - Pattern pt = Pattern.compile("\\$\\{([^}]+)\\}"); - Matcher mt = pt.matcher(ft); - StringBuffer sb = new StringBuffer(); - while(mt.find()) { - String m = mt.group(1); - if(m.contains("?")) { - String[] kv = m.split("\\?", 2); - String key = kv[0].trim(); - boolean not = key.startsWith("!"); - if(not) key = key.replaceFirst("!", ""); - m = kv[1].trim(); - if(!server_config_supplier.get().contains(key)) { - m = ""; - } else { - boolean r = server_config_supplier.get().getBoolean(key); - if(not) r = !r; - if(!r) m = ""; - } - } - mt.appendReplacement(sb, Matcher.quoteReplacement((Component.translatable(m)).getString().trim())); - } - mt.appendTail(sb); - return sb.toString(); - } else { - return ft; - } - } - - /** - * Returns true if a given key is translated for the current language. - */ - @OnlyIn(Dist.CLIENT) - public static boolean hasTranslation(String key) - { return net.minecraft.client.resources.language.I18n.exists(key); } - - public static MutableComponent join(Collection components, String separator) - { return ComponentUtils.formatList(components, Component.literal(separator), Function.identity()); } - - public static MutableComponent join(Component... components) - { final MutableComponent tc = Component.empty(); for(Component c:components) { tc.append(c); } return tc; } - - public static boolean isEmpty(Component component) - { return component.getSiblings().isEmpty() && component.getString().isEmpty(); } - - public static final class Tooltip - { - @OnlyIn(Dist.CLIENT) - public static boolean extendedTipCondition() - { return isShiftDown(); } - - @OnlyIn(Dist.CLIENT) - public static boolean helpCondition() - { return isShiftDown() && isCtrlDown(); } - - /** - * Adds an extended tooltip or help tooltip depending on the key states of CTRL and SHIFT. - * Returns true if the localisable help/tip was added, false if not (either not CTL/SHIFT or - * no translation found). - */ - @OnlyIn(Dist.CLIENT) - public static boolean addInformation(@Nullable String advancedTooltipTranslationKey, @Nullable String helpTranslationKey, List tooltip, TooltipFlag flag, boolean addAdvancedTooltipHints) - { - // Note: intentionally not using keybinding here, this must be `control` or `shift`. - final boolean help_available = (helpTranslationKey != null) && Auxiliaries.hasTranslation(helpTranslationKey + ".help"); - final boolean tip_available = (advancedTooltipTranslationKey != null) && Auxiliaries.hasTranslation(helpTranslationKey + ".tip"); - if((!help_available) && (!tip_available)) return false; - String tip_text = ""; - if(helpCondition()) { - if(help_available) tip_text = localize(helpTranslationKey + ".help"); - } else if(extendedTipCondition()) { - if(tip_available) tip_text = localize(advancedTooltipTranslationKey + ".tip"); - } else if(addAdvancedTooltipHints) { - if(tip_available) tip_text += localize(modid + ".tooltip.hint.extended") + (help_available ? " " : ""); - if(help_available) tip_text += localize(modid + ".tooltip.hint.help"); - } - if(tip_text.isEmpty()) return false; - String[] tip_list = tip_text.split("\\r?\\n"); - for(String tip:tip_list) { - tooltip.add(Component.literal(tip.replaceAll("\\s+$","").replaceAll("^\\s+", "")).withStyle(ChatFormatting.GRAY)); - } - return true; - } - - /** - * Adds an extended tooltip or help tooltip for a given stack depending on the key states of CTRL and SHIFT. - * Format in the lang file is (e.g. for items): "item.MODID.REGISTRYNAME.tip" and "item.MODID.REGISTRYNAME.help". - * Return value see method pattern above. - */ - @OnlyIn(Dist.CLIENT) - public static boolean addInformation(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag, boolean addAdvancedTooltipHints) - { return addInformation(stack.getDescriptionId(), stack.getDescriptionId(), tooltip, flag, addAdvancedTooltipHints); } - - @OnlyIn(Dist.CLIENT) - public static boolean addInformation(String translation_key, List tooltip) - { - if(!Auxiliaries.hasTranslation(translation_key)) return false; - tooltip.add(Component.literal(localize(translation_key).replaceAll("\\s+$","").replaceAll("^\\s+", "")).withStyle(ChatFormatting.GRAY)); - return true; - } - - } - - @SuppressWarnings("unused") - public static void playerChatMessage(final Player player, final String message) - { player.displayClientMessage(Component.translatable(message.trim()), true); } - - public static @Nullable Component unserializeTextComponent(String serialized) - { return Component.Serializer.fromJson(serialized); } - - public static String serializeTextComponent(Component tc) - { return (tc==null) ? ("") : (Component.Serializer.toJson(tc)); } - - // ------------------------------------------------------------------------------------------------------------------- - // Tag Handling - // ------------------------------------------------------------------------------------------------------------------- - - @SuppressWarnings("deprecation") - public static boolean isInItemTag(Item item, ResourceLocation tag) - { return ForgeRegistries.ITEMS.tags().stream().filter(tg->tg.getKey().location().equals(tag)).anyMatch(tk->tk.contains(item)); } - - @SuppressWarnings("deprecation") - public static boolean isInBlockTag(Block block, ResourceLocation tag) - { return ForgeRegistries.BLOCKS.tags().stream().filter(tg->tg.getKey().location().equals(tag)).anyMatch(tk->tk.contains(block)); } - - @SuppressWarnings("deprecation") - public static ResourceLocation getResourceLocation(Item item) - { return Registry.ITEM.getKey(item); } - - @SuppressWarnings("deprecation") - public static ResourceLocation getResourceLocation(Block block) - { return Registry.BLOCK.getKey(block); } - - @SuppressWarnings("deprecation") - public static ResourceLocation getResourceLocation(net.minecraft.world.inventory.MenuType menu) - { return Registry.MENU.getKey(menu); } - - @SuppressWarnings("deprecation") - public static ResourceLocation getResourceLocation(net.minecraft.world.level.material.Fluid fluid) - { return Registry.FLUID.getKey(fluid); } - - // ------------------------------------------------------------------------------------------------------------------- - // Item NBT data - // ------------------------------------------------------------------------------------------------------------------- - - /** - * Equivalent to getDisplayName(), returns null if no custom name is set. - */ - public static @Nullable Component getItemLabel(ItemStack stack) - { - CompoundTag nbt = stack.getTagElement("display"); - if(nbt != null && nbt.contains("Name", 8)) { - try { - Component tc = unserializeTextComponent(nbt.getString("Name")); - if(tc != null) return tc; - nbt.remove("Name"); - } catch(Exception e) { - nbt.remove("Name"); - } - } - return null; - } - - public static ItemStack setItemLabel(ItemStack stack, @Nullable Component name) - { - if(name != null) { - CompoundTag nbt = stack.getOrCreateTagElement("display"); - nbt.putString("Name", serializeTextComponent(name)); - } else { - if(stack.hasTag()) stack.removeTagKey("display"); - } - return stack; - } - - // ------------------------------------------------------------------------------------------------------------------- - // Block handling - // ------------------------------------------------------------------------------------------------------------------- - - public static boolean isWaterLogged(BlockState state) - { return state.hasProperty(BlockStateProperties.WATERLOGGED) && state.getValue(BlockStateProperties.WATERLOGGED); } - - public static AABB getPixeledAABB(double x0, double y0, double z0, double x1, double y1, double z1) - { return new AABB(x0/16.0, y0/16.0, z0/16.0, x1/16.0, y1/16.0, z1/16.0); } - - public static AABB getRotatedAABB(AABB bb, Direction new_facing) - { return getRotatedAABB(bb, new_facing, false); } - - public static AABB[] getRotatedAABB(AABB[] bb, Direction new_facing) - { return getRotatedAABB(bb, new_facing, false); } - - public static AABB getRotatedAABB(AABB bb, Direction new_facing, boolean horizontal_rotation) - { - if(!horizontal_rotation) { - switch(new_facing.get3DDataValue()) { - case 0: return new AABB(1-bb.maxX, bb.minZ, bb.minY, 1-bb.minX, bb.maxZ, bb.maxY); // D - case 1: return new AABB(1-bb.maxX, 1-bb.maxZ, 1-bb.maxY, 1-bb.minX, 1-bb.minZ, 1-bb.minY); // U - case 2: return new AABB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // N --> bb - case 3: return new AABB(1-bb.maxX, bb.minY, 1-bb.maxZ, 1-bb.minX, bb.maxY, 1-bb.minZ); // S - case 4: return new AABB( bb.minZ, bb.minY, 1-bb.maxX, bb.maxZ, bb.maxY, 1-bb.minX); // W - case 5: return new AABB(1-bb.maxZ, bb.minY, bb.minX, 1-bb.minZ, bb.maxY, bb.maxX); // E - } - } else { - switch(new_facing.get3DDataValue()) { - case 0: return new AABB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // D --> bb - case 1: return new AABB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // U --> bb - case 2: return new AABB( bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); // N --> bb - case 3: return new AABB(1-bb.maxX, bb.minY, 1-bb.maxZ, 1-bb.minX, bb.maxY, 1-bb.minZ); // S - case 4: return new AABB( bb.minZ, bb.minY, 1-bb.maxX, bb.maxZ, bb.maxY, 1-bb.minX); // W - case 5: return new AABB(1-bb.maxZ, bb.minY, bb.minX, 1-bb.minZ, bb.maxY, bb.maxX); // E - } - } - return bb; - } - - public static AABB[] getRotatedAABB(AABB[] bbs, Direction new_facing, boolean horizontal_rotation) - { - final AABB[] transformed = new AABB[bbs.length]; - for(int i=0; i new AABB(1 - bb.maxX, bb.minY, bb.minZ, 1 - bb.minX, bb.maxY, bb.maxZ); - case Y -> new AABB(bb.minX, 1 - bb.maxY, bb.minZ, bb.maxX, 1 - bb.minY, bb.maxZ); - case Z -> new AABB(bb.minX, bb.minY, 1 - bb.maxZ, bb.maxX, bb.maxY, 1 - bb.minZ); - }; - } - - public static AABB[] getMirroredAABB(AABB[] bbs, Direction.Axis axis) - { - final AABB[] transformed = new AABB[bbs.length]; - for(int i=0; i mapper) { - final AABB[] transformed = new AABB[bbs.length]; - for(int i=0; i - { - private final int x0, x1, y0, y1, z0, z1; - - public BlockPosRange(int x0, int y0, int z0, int x1, int y1, int z1) - { - this.x0 = Math.min(x0,x1); this.x1 = Math.max(x0,x1); - this.y0 = Math.min(y0,y1); this.y1 = Math.max(y0,y1); - this.z0 = Math.min(z0,z1); this.z1 = Math.max(z0,z1); - } - - public static BlockPosRange of(AABB range) - { - return new BlockPosRange( - (int)Math.floor(range.minX), - (int)Math.floor(range.minY), - (int)Math.floor(range.minZ), - (int)Math.floor(range.maxX-.0625), - (int)Math.floor(range.maxY-.0625), - (int)Math.floor(range.maxZ-.0625) - ); - } - - public int getXSize() - { return x1-x0+1; } - - public int getYSize() - { return y1-y0+1; } - - public int getZSize() - { return z1-z0+1; } - - public int getArea() - { return getXSize() * getZSize(); } - - public int getHeight() - { return getYSize(); } - - public int getVolume() - { return getXSize() * getYSize() * getZSize(); } - - public BlockPos byXZYIndex(int xyz_index) - { - final int xsz=getXSize(), ysz=getYSize(), zsz=getZSize(); - xyz_index = xyz_index % (xsz*ysz*zsz); - final int y = xyz_index / (xsz*zsz); - xyz_index -= y * (xsz*zsz); - final int z = xyz_index / xsz; - xyz_index -= z * xsz; - final int x = xyz_index; - return new BlockPos(x0+x, y0+y, z0+z); - } - - public BlockPos byXZIndex(int xz_index, int y_offset) - { - final int xsz=getXSize(), zsz=getZSize(); - xz_index = xz_index % (xsz*zsz); - final int z = xz_index / xsz; - xz_index -= z * xsz; - final int x = xz_index; - return new BlockPos(x0+x, y0+y_offset, z0+z); - } - - public static final class BlockRangeIterator implements Iterator - { - private final BlockPosRange range_; - private int x,y,z; - - public BlockRangeIterator(BlockPosRange range) - { range_ = range; x=range.x0; y=range.y0; z=range.z0; } - - @Override - public boolean hasNext() - { return (z <= range_.z1); } - - @Override - public BlockPos next() - { - if(!hasNext()) throw new NoSuchElementException(); - final BlockPos pos = new BlockPos(x,y,z); - ++x; - if(x > range_.x1) { - x = range_.x0; - ++y; - if(y > range_.y1) { - y = range_.y0; - ++z; - } - } - return pos; - } - } - - @Override - public BlockRangeIterator iterator() - { return new BlockRangeIterator(this); } - - public Stream stream() - { return java.util.stream.StreamSupport.stream(spliterator(), false); } - } - - // ------------------------------------------------------------------------------------------------------------------- - // JAR resource related - // ------------------------------------------------------------------------------------------------------------------- - - public static String loadResourceText(InputStream is) - { - try { - if(is==null) return ""; - BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); - return br.lines().collect(Collectors.joining("\n")); - } catch(Throwable e) { - return ""; - } - } - - public static String loadResourceText(String path) - { return loadResourceText(Auxiliaries.class.getResourceAsStream(path)); } - - public static void logGitVersion(String mod_name) - { - try { - // Done during construction to have an exact version in case of a crash while registering. - String version = Auxiliaries.loadResourceText("/.gitversion-" + modid).trim(); - logInfo(mod_name+((version.isEmpty())?(" (dev build)"):(" GIT id #"+version)) + "."); - } catch(Throwable e) { - // (void)e; well, then not. Priority is not to get unneeded crashes because of version logging. - } - } -} diff --git a/src/main/java/wile/engineersdecor/libmc/Containers.java b/src/main/java/wile/engineersdecor/libmc/Containers.java deleted file mode 100644 index 4074f96..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Containers.java +++ /dev/null @@ -1,119 +0,0 @@ -package wile.engineersdecor.libmc; - -import net.minecraft.util.Mth; -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import java.util.function.BiConsumer; - -public class Containers -{ - // ------------------------------------------------------------------------------------------------------------------- - // Slots - // ------------------------------------------------------------------------------------------------------------------- - - public static class StorageSlot extends Slot - { - protected BiConsumer slot_change_action_ = (oldStack, newStack)->{}; - protected int stack_limit_ = 64; - public boolean enabled = true; - - public StorageSlot(Container inventory, int index, int x, int y) - { super(inventory, index, x, y); } - - public StorageSlot setSlotStackLimit(int limit) - { stack_limit_ = Mth.clamp(limit, 1, 64); return this; } - - public int getMaxStackSize() - { return stack_limit_; } - - public StorageSlot setSlotChangeNotifier(BiConsumer action) - { slot_change_action_ = action; return this; } - - @Override - public void onQuickCraft(ItemStack oldStack, ItemStack newStack) - { slot_change_action_.accept(oldStack, newStack);} // no crafting trigger - - @Override - public void set(ItemStack stack) - { - if(stack.sameItem(getItem())) { - super.set(stack); - } else { - final ItemStack before = getItem().copy(); - super.set(stack); // whatever this does else next to setting inventory. - slot_change_action_.accept(before, getItem()); - } - } - - @Override - public boolean mayPlace(ItemStack stack) - { return enabled && this.container.canPlaceItem(this.getSlotIndex(), stack); } - - @Override - public int getMaxStackSize(ItemStack stack) - { return Math.min(getMaxStackSize(), stack_limit_); } - - @OnlyIn(Dist.CLIENT) - public boolean isActive() - { return enabled; } - } - - public static class LockedSlot extends Slot - { - protected int stack_limit_ = 64; - public boolean enabled = true; - - public LockedSlot(Container inventory, int index, int x, int y) - { super(inventory, index, x, y); } - - public LockedSlot setSlotStackLimit(int limit) - { stack_limit_ = Mth.clamp(limit, 1, 64); return this; } - - public int getMaxStackSize() - { return stack_limit_; } - - @Override - public int getMaxStackSize(ItemStack stack) - { return Math.min(getMaxStackSize(), stack_limit_); } - - @Override - public boolean mayPlace(ItemStack stack) - { return false; } - - @Override - public boolean mayPickup(Player player) - { return false; } - - @OnlyIn(Dist.CLIENT) - public boolean isActive() - { return enabled; } - } - - public static class HiddenSlot extends Slot - { - public HiddenSlot(Container inventory, int index) - { super(inventory, index, 0, 0); } - - @Override - public int getMaxStackSize(ItemStack stack) - { return getMaxStackSize(); } - - @Override - public boolean mayPlace(ItemStack stack) - { return false; } - - @Override - public boolean mayPickup(Player player) - { return false; } - - @OnlyIn(Dist.CLIENT) - public boolean isActive() - { return false; } - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/Crafting.java b/src/main/java/wile/engineersdecor/libmc/Crafting.java deleted file mode 100644 index 650a4ae..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Crafting.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * @file Recipes.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Recipe utility functionality. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.NonNullList; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.util.Tuple; -import net.minecraft.world.Container; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.CraftingContainer; -import net.minecraft.world.item.EnchantedBookItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.*; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.EnchantmentInstance; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.ComposterBlock; -import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.common.brewing.BrewingRecipeRegistry; - -import javax.annotation.Nullable; -import java.util.*; -import java.util.function.BiPredicate; - - -public class Crafting -{ - // ------------------------------------------------------------------------------------------------------------------- - - public static final class CraftingGrid extends CraftingContainer - { - protected static final CraftingGrid instance3x3 = new CraftingGrid(3,3); - - protected CraftingGrid(int width, int height) - { super( - new AbstractContainerMenu(null,0) { - public boolean stillValid(Player player) { return false; } - public ItemStack quickMoveStack(Player player, int slot) {return ItemStack.EMPTY; } - } - , width, height - ); - } - - protected void fill(Container grid) - { for(int i=0; i=grid.getContainerSize() ? ItemStack.EMPTY : grid.getItem(i)); } - - public List getRecipes(Level world, Container grid) - { fill(grid); return world.getRecipeManager().getRecipesFor(RecipeType.CRAFTING, this, world); } - - public List getRemainingItems(Level world, Container grid, CraftingRecipe recipe) - { fill(grid); return recipe.getRemainingItems(this); } - - public ItemStack getCraftingResult(Level world, Container grid, CraftingRecipe recipe) - { fill(grid); return recipe.assemble(this); } - } - - /** - * Returns a Crafting recipe by registry name. - */ - public static Optional getCraftingRecipe(Level world, ResourceLocation recipe_id) - { - Recipe recipe = world.getRecipeManager().byKey(recipe_id).orElse(null); - return (recipe instanceof CraftingRecipe) ? Optional.of((CraftingRecipe)recipe) : Optional.empty(); - } - - /** - * Returns a list of matching recipes by the first N slots (crafting grid slots) of the given inventory. - */ - public static List get3x3CraftingRecipes(Level world, Container crafting_grid_slots) - { return CraftingGrid.instance3x3.getRecipes(world, crafting_grid_slots); } - - /** - * Returns a recipe by the first N slots (crafting grid slots). - */ - public static Optional get3x3CraftingRecipe(Level world, Container crafting_grid_slots) - { return get3x3CraftingRecipes(world, crafting_grid_slots).stream().findFirst(); } - - /** - * Returns the result item of the recipe with the given grid layout. - */ - public static ItemStack get3x3CraftingResult(Level world, Container grid, CraftingRecipe recipe) - { return CraftingGrid.instance3x3.getCraftingResult(world, grid, recipe); } - - /** - * Returns the items remaining in the grid after crafting 3x3. - */ - public static List get3x3RemainingItems(Level world, Container grid, CraftingRecipe recipe) - { return CraftingGrid.instance3x3.getRemainingItems(world, grid, recipe); } - - public static List get3x3Placement(Level world, CraftingRecipe recipe, Container item_inventory, @Nullable Container crafting_grid) - { - final int width = 3; - final int height = 3; - if(!recipe.canCraftInDimensions(width,height)) return Collections.emptyList(); - List used = new ArrayList<>(); //NonNullList.withSize(width*height); - for(int i=width*height; i>0; --i) used.add(ItemStack.EMPTY); - Container check_inventory = Inventories.copyOf(item_inventory); - Inventories.InventoryRange source = new Inventories.InventoryRange(check_inventory); - final List ingredients = recipe.getIngredients(); - final List preferred = new ArrayList<>(width*height); - if(crafting_grid != null) { - for(int i=0; i placement = NonNullList.withSize(width*height, ItemStack.EMPTY); - for(int row=0; row> Optional getFurnaceRecipe(RecipeType recipe_type, Level world, ItemStack input_stack) - { - if(input_stack.isEmpty()) { - return Optional.empty(); - } else if(recipe_type == RecipeType.SMELTING) { - SimpleContainer inventory = new SimpleContainer(3); - inventory.setItem(0, input_stack); - SmeltingRecipe recipe = world.getRecipeManager().getRecipeFor(RecipeType.SMELTING, inventory, world).orElse(null); - return (recipe==null) ? Optional.empty() : Optional.of(recipe); - } else if(recipe_type == RecipeType.BLASTING) { - SimpleContainer inventory = new SimpleContainer(3); - inventory.setItem(0, input_stack); - BlastingRecipe recipe = world.getRecipeManager().getRecipeFor(RecipeType.BLASTING, inventory, world).orElse(null); - return (recipe==null) ? Optional.empty() : Optional.of(recipe); - } else if(recipe_type == RecipeType.SMOKING) { - SimpleContainer inventory = new SimpleContainer(3); - inventory.setItem(0, input_stack); - SmokingRecipe recipe = world.getRecipeManager().getRecipeFor(RecipeType.SMOKING, inventory, world).orElse(null); - return (recipe==null) ? Optional.empty() : Optional.of(recipe); - } else { - return Optional.empty(); - } - } - - public static > int getSmeltingTimeNeeded(RecipeType recipe_type, Level world, ItemStack stack) - { - if(stack.isEmpty()) return 0; - final int t = getFurnaceRecipe(recipe_type, world, stack).map((AbstractCookingRecipe::getCookingTime)).orElse(0); - return (t<=0) ? 200 : t; - } - - /** - * Returns the burn time of an item when used as fuel, 0 if it is no fuel. - */ - public static int getFuelBurntime(Level world, ItemStack stack) - { - if(stack.isEmpty()) return 0; - int t = ForgeHooks.getBurnTime(stack, null); - return Math.max(t, 0); - } - - /** - * Returns true if an item can be used as fuel. - */ - public static boolean isFuel(Level world, ItemStack stack) - { return (getFuelBurntime(world, stack) > 0) || (stack.getItem()==Items.LAVA_BUCKET); } - - /** - * Returns burntime and remaining stack then the item shall be used as fuel. - */ - public static Tuple consumeFuel(Level world, ItemStack stack) - { - if(stack.isEmpty()) return new Tuple<>(0,stack); - int burnime = getFuelBurntime(world, stack); - if((stack.getItem()==Items.LAVA_BUCKET)) { - if(burnime <= 0) burnime = 1000*20; - return new Tuple<>(burnime,new ItemStack(Items.BUCKET)); - } else if(burnime <= 0) { - return new Tuple<>(0,stack); - } else { - ItemStack left_over = stack.copy(); - left_over.shrink(1); - return new Tuple<>(burnime,left_over); - } - } - - // ------------------------------------------------------------------------------------------------------------------- - - /** - * Returns true if the item can be used as brewing fuel. - */ - public static boolean isBrewingFuel(Level world, ItemStack stack) - { return (stack.getItem() == Items.BLAZE_POWDER) || (stack.getItem() == Items.BLAZE_ROD); } - - /** - * Returns true if the item can be used as brewing ingredient. - */ - public static boolean isBrewingIngredient(Level world, ItemStack stack) - { return BrewingRecipeRegistry.isValidIngredient(stack); } - - /** - * Returns true if the item can be used as brewing bottle. - */ - public static boolean isBrewingInput(Level world, ItemStack stack) - { return BrewingRecipeRegistry.isValidInput(stack); } - - /** - * Returns the burn time for brewing of the given stack. - */ - public static int getBrewingFuelBurntime(Level world, ItemStack stack) - { - if(stack.isEmpty()) return 0; - if(stack.getItem() == Items.BLAZE_POWDER) return (400*20); - if(stack.getItem() == Items.BLAZE_ROD) return (400*40); - return 0; - } - - /** - * Returns brewing burn time and remaining stack if the item shall be used as fuel. - */ - public static Tuple consumeBrewingFuel(Level world, ItemStack stack) - { - int burntime = getBrewingFuelBurntime(world, stack); - if(burntime <= 0) return new Tuple<>(0, stack.copy()); - stack = stack.copy(); - stack.shrink(1); - return new Tuple<>(burntime, stack.isEmpty() ? ItemStack.EMPTY : stack); - } - - public static final class BrewingOutput - { - public static final int DEFAULT_BREWING_TIME = 400; - public static final BrewingOutput EMPTY = new BrewingOutput(ItemStack.EMPTY, new SimpleContainer(1), new SimpleContainer(1), 0,0, DEFAULT_BREWING_TIME); - public final ItemStack item; - public final Container potionInventory; - public final Container ingredientInventory; - public final int potionSlot; - public final int ingredientSlot; - public final int brewTime; - - public BrewingOutput(ItemStack output_potion, Container potion_inventory, Container ingredient_inventory, int potion_slot, int ingredient_slot, int time_needed) - { - item = output_potion; - potionInventory = potion_inventory; - ingredientInventory = ingredient_inventory; - potionSlot = potion_slot; - ingredientSlot = ingredient_slot; - brewTime = time_needed; - } - - public static BrewingOutput find(Level world, Container potion_inventory, Container ingredient_inventory) - { - for(int potion_slot = 0; potion_slot getEnchantmentsOnItem(Level world, ItemStack stack) - { return (stack.isEmpty() || (stack.getTag()==null)) ? Collections.emptyMap() : EnchantmentHelper.getEnchantments(stack); } - - /** - * Returns an enchanted book with the given enchantment, emtpy stack if not applicable. - */ - public static ItemStack getEnchantmentBook(Level world, Enchantment enchantment, int level) - { return ((!enchantment.isAllowedOnBooks()) || (level <= 0)) ? ItemStack.EMPTY : EnchantedBookItem.createForEnchantment(new EnchantmentInstance(enchantment, level)); } - - /** - * Returns the accumulated repair cost for the given enchantments. - */ - public static int getEnchantmentRepairCost(Level world, Map enchantments) - { - int repair_cost = 0; - for(Map.Entry e:enchantments.entrySet()) repair_cost = repair_cost * 2 + 1; // @see: RepairContainer.getNewRepairCost() - return repair_cost; - } - - /** - * Trys to add an enchtment to the given stack, returns boolean success. - */ - public static boolean addEnchantmentOnItem(Level world, ItemStack stack, Enchantment enchantment, int level) - { - if(stack.isEmpty() || (level <= 0) || (!stack.isEnchantable()) || (level >= enchantment.getMaxLevel())) return false; - final Map on_item = getEnchantmentsOnItem(world, stack); - if(on_item.keySet().stream().anyMatch(ench-> ench.isCompatibleWith(enchantment))) return false; - final ItemStack book = EnchantedBookItem.createForEnchantment(new EnchantmentInstance(enchantment, level)); - if((!(stack.isBookEnchantable(book) && enchantment.isAllowedOnBooks())) && (!stack.canApplyAtEnchantingTable(enchantment)) && (!enchantment.canEnchant(stack))) return false; - final int existing_level = on_item.getOrDefault(enchantment, 0); - if(existing_level > 0) level = Mth.clamp(level+existing_level, 1, enchantment.getMaxLevel()); - on_item.put(enchantment, level); - EnchantmentHelper.setEnchantments(on_item, stack); - stack.setRepairCost(getEnchantmentRepairCost(world, on_item)); - return true; - } - - /** - * Removes enchantments from a stack, returns the removed enchantments. - */ - public static Map removeEnchantmentsOnItem(Level world, ItemStack stack, BiPredicate filter) - { - if(stack.isEmpty()) return Collections.emptyMap(); - final Map on_item = getEnchantmentsOnItem(world, stack); - final Map removed = new HashMap<>(); - for(Map.Entry e:on_item.entrySet()) { - if(filter.test(e.getKey(), e.getValue())) { - removed.put(e.getKey(), e.getValue()); - } - } - for(Enchantment e:removed.keySet()) { - on_item.remove(e); - } - EnchantmentHelper.setEnchantments(on_item, stack); - stack.setRepairCost(getEnchantmentRepairCost(world, on_item)); - return removed; - } - - -} \ No newline at end of file diff --git a/src/main/java/wile/engineersdecor/libmc/Fluidics.java b/src/main/java/wile/engineersdecor/libmc/Fluidics.java deleted file mode 100644 index 5507fc5..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Fluidics.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * @file Fluidics.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * General fluid handling functionality. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.util.Tuple; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraft.nbt.Tag; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidActionResult; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidUtil; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.items.IItemHandler; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Predicate; - - -public class Fluidics -{ - public static class SingleTankFluidHandler implements IFluidHandler - { - private final IFluidTank tank_; - public SingleTankFluidHandler(IFluidTank tank) { tank_ = tank; } - @Override public int getTanks() { return 1; } - @Override public FluidStack getFluidInTank(int tank) { return tank_.getFluid(); } - @Override public int getTankCapacity(int tank) { return tank_.getCapacity(); } - @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return tank_.isFluidValid(stack); } - @Override public int fill(FluidStack resource, FluidAction action) { return tank_.fill(resource, action); } - @Override public FluidStack drain(FluidStack resource, FluidAction action) { return tank_.drain(resource, action); } - @Override public FluidStack drain(int maxDrain, FluidAction action) { return tank_.drain(maxDrain, action); } - } - - private static class SingleTankOutputFluidHandler implements IFluidHandler - { - private final IFluidTank tank_; - public SingleTankOutputFluidHandler(IFluidTank tank) { tank_ = tank; } - @Override public int getTanks() { return 1; } - @Override public FluidStack getFluidInTank(int tank) { return tank_.getFluid().copy(); } - @Override public int getTankCapacity(int tank) { return tank_.getCapacity(); } - @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; } - @Override public int fill(FluidStack resource, FluidAction action) { return 0; } - @Override public FluidStack drain(FluidStack resource, FluidAction action) { return tank_.drain(resource, action); } - @Override public FluidStack drain(int maxDrain, FluidAction action) { return tank_.drain(maxDrain, action); } - } - - public static class Tank implements IFluidTank - { - private Predicate validator_ = ((e)->true); - private BiConsumer interaction_notifier_ = ((tank,diff)->{}); - private FluidStack fluid_ = FluidStack.EMPTY; - private int capacity_; - private int fill_rate_; - private int drain_rate_; - - public Tank(int capacity) - { this(capacity, capacity, capacity); } - - public Tank(int capacity, int fill_rate, int drain_rate) - { this(capacity, fill_rate, drain_rate, e->true); } - - public Tank(int capacity, int fill_rate, int drain_rate, Predicate validator) - { - capacity_ = capacity; - setMaxFillRate(fill_rate); - setMaxDrainRate(drain_rate); - setValidator(validator); - } - - public Tank load(CompoundTag nbt) - { - if(nbt.contains("tank", Tag.TAG_COMPOUND)) { - setFluid(FluidStack.loadFluidStackFromNBT(nbt.getCompound("tank"))); - } else { - clear(); - } - return this; - } - - public CompoundTag save(CompoundTag nbt) - { if(!isEmpty()) { nbt.put("tank", fluid_.writeToNBT(new CompoundTag())); } return nbt; } - - public void reset() - { clear(); } - - public Tank clear() - { setFluid(null); return this; } - - public int getCapacity() - { return capacity_; } - - public Tank setCapacity(int capacity) - { capacity_ = capacity; return this; } - - public int getMaxDrainRate() - { return drain_rate_; } - - public Tank setMaxDrainRate(int rate) - { drain_rate_ = Mth.clamp(rate, 0, capacity_); return this; } - - public int getMaxFillRate() - { return fill_rate_; } - - public Tank setMaxFillRate(int rate) - { fill_rate_ = Mth.clamp(rate, 0, capacity_); return this; } - - public Tank setValidator(Predicate validator) - { validator_ = (validator!=null) ? validator : ((e)->true); return this; } - - public Tank setInteractionNotifier(BiConsumer notifier) - { interaction_notifier_ = (notifier!=null) ? notifier : ((tank,diff)->{}); return this; } - - public LazyOptional createFluidHandler() - { return LazyOptional.of(() -> new Fluidics.SingleTankFluidHandler(this)); } - - public LazyOptional createOutputFluidHandler() - { return LazyOptional.of(() -> new Fluidics.SingleTankOutputFluidHandler(this)); } - - // IFluidTank ------------------------------------------------------------------------------------ - - @Nonnull - public FluidStack getFluid() - { return fluid_; } - - public void setFluid(@Nullable FluidStack stack) - { fluid_ = (stack==null) ? FluidStack.EMPTY : stack; } - - public int getFluidAmount() - { return fluid_.getAmount(); } - - public boolean isEmpty() - { return fluid_.isEmpty(); } - - public boolean isFull() - { return getFluidAmount() >= getCapacity(); } - - public boolean isFluidValid(FluidStack stack) - { return validator_.test(stack); } - - public boolean isFluidEqual(FluidStack stack) - { return (stack==null) ? (fluid_.isEmpty()) : fluid_.isFluidEqual(stack); } - - @Override - public int fill(FluidStack fs, FluidAction action) - { - if((fs==null) || fs.isEmpty() || (!isFluidValid(fs))) { - return 0; - } else if(action.simulate()) { - if(fluid_.isEmpty()) return Math.min(capacity_, fs.getAmount()); - if(!fluid_.isFluidEqual(fs)) return 0; - return Math.min(capacity_-fluid_.getAmount(), fs.getAmount()); - } else if(fluid_.isEmpty()) { - fluid_ = new FluidStack(fs, Math.min(capacity_, fs.getAmount())); - return fluid_.getAmount(); - } else if(!fluid_.isFluidEqual(fs)) { - return 0; - } else { - int amount = capacity_ - fluid_.getAmount(); - if(fs.getAmount() < amount) { - fluid_.grow(fs.getAmount()); - amount = fs.getAmount(); - } else { - fluid_.setAmount(capacity_); - } - if(amount != 0) interaction_notifier_.accept(this, amount); - return amount; - } - } - - @Nonnull - public FluidStack drain(int maxDrain) - { return drain(maxDrain, FluidAction.EXECUTE); } - - @Nonnull - @Override - public FluidStack drain(FluidStack fs, FluidAction action) - { return ((fs.isEmpty()) || (!fs.isFluidEqual(fluid_))) ? FluidStack.EMPTY : drain(fs.getAmount(), action); } - - @Nonnull - @Override - public FluidStack drain(int maxDrain, FluidAction action) - { - final int amount = Math.min(fluid_.getAmount(), maxDrain); - final FluidStack stack = new FluidStack(fluid_, amount); - if((amount > 0) && action.execute()) { - fluid_.shrink(amount); - if(fluid_.isEmpty()) fluid_ = FluidStack.EMPTY; - if(amount != 0) interaction_notifier_.accept(this, -amount); - } - return stack; - } - } - - // ------------------------------------------------------------------------------------------------------------------- - - public static @Nullable IFluidHandler handler(Level world, BlockPos pos, @Nullable Direction side) - { return FluidUtil.getFluidHandler(world, pos, side).orElse(null); } - - /** - * Fills or drains items with fluid handlers from or into tile blocks with fluid handlers. - */ - public static boolean manualFluidHandlerInteraction(Level world, BlockPos pos, @Nullable Direction side, Player player, InteractionHand hand) - { return manualTrackedFluidHandlerInteraction(world, pos, side, player, hand) != null; } - - public static boolean manualFluidHandlerInteraction(Player player, InteractionHand hand, IFluidHandler handler) - { return FluidUtil.interactWithFluidHandler(player, hand, handler); } - - /** - * Fills or drains items with fluid handlers from or into tile blocks with fluid handlers. - * Returns the fluid and (possibly negative) amount that transferred from the item into the block. - */ - public static @Nullable Tuple manualTrackedFluidHandlerInteraction(Level world, BlockPos pos, @Nullable Direction side, Player player, InteractionHand hand) - { - if(world.isClientSide()) return null; - final ItemStack held = player.getItemInHand(hand); - if(held.isEmpty()) return null; - final IFluidHandler fh = handler(world, pos, side); - if(fh==null) return null; - final IItemHandler ih = player.getCapability(ForgeCapabilities.ITEM_HANDLER).orElse(null); - if(ih==null) return null; - FluidActionResult far = FluidUtil.tryFillContainerAndStow(held, fh, ih, Integer.MAX_VALUE, player, true); - if(!far.isSuccess()) far = FluidUtil.tryEmptyContainerAndStow(held, fh, ih, Integer.MAX_VALUE, player, true); - if(!far.isSuccess()) return null; - final ItemStack rstack = far.getResult().copy(); - player.setItemInHand(hand, far.getResult()); - final IFluidHandler fh_before = FluidUtil.getFluidHandler(held).orElse(null); - final IFluidHandler fh_after = FluidUtil.getFluidHandler(rstack).orElse(null); - if((fh_before==null) || (fh_after==null) || (fh_after.getTanks()!=fh_before.getTanks())) return null; // should not be, but y'never know. - for(int i=0; i( - (vol_before>0) ? (fh_before.getFluidInTank(i).getFluid()) : (fh_after.getFluidInTank(i).getFluid()), - (vol_before - vol_after) - ); - } - } - return null; - } - - public static boolean manualFluidHandlerInteraction(Player player, InteractionHand hand, Level world, BlockPos pos, @Nullable Direction side) - { return FluidUtil.interactWithFluidHandler(player, hand, world, pos, side); } - - public static int fill(Level world, BlockPos pos, Direction side, FluidStack fs, FluidAction action) - { - IFluidHandler fh = FluidUtil.getFluidHandler(world, pos, side).orElse(null); - return (fh==null) ? (0) : (fh.fill(fs, action)); - } - - public static int fill(Level world, BlockPos pos, Direction side, FluidStack fs) - { return fill(world, pos, side, fs, FluidAction.EXECUTE); } - - /** - * Fluid tank access when itemized. - */ - public static class FluidContainerItemCapabilityWrapper implements IFluidHandlerItem, ICapabilityProvider - { - private final LazyOptional handler_ = LazyOptional.of(()->this); - private final Function nbt_getter_; - private final BiConsumer nbt_setter_; - private final Predicate validator_; - private final ItemStack container_; - private final int capacity_; - private final int transfer_rate_; - - public FluidContainerItemCapabilityWrapper(ItemStack container, int capacity, int transfer_rate, - Function nbt_getter, - BiConsumer nbt_setter, - Predicate validator) - { - container_ = container; - capacity_ = capacity; - transfer_rate_ = transfer_rate; - nbt_getter_ = nbt_getter; - nbt_setter_ = nbt_setter; - validator_ = (validator!=null) ? validator : (e->true); - } - - @Override - public LazyOptional getCapability(Capability capability, @Nullable Direction side) - { return (capability == ForgeCapabilities.FLUID_HANDLER) ? handler_.cast() : LazyOptional.empty(); } - - protected FluidStack readnbt() - { - final CompoundTag nbt = nbt_getter_.apply(container_); - return ((nbt==null) || (nbt.isEmpty())) ? FluidStack.EMPTY : FluidStack.loadFluidStackFromNBT(nbt); - } - - protected void writenbt(FluidStack fs) - { - CompoundTag nbt = new CompoundTag(); - if(!fs.isEmpty()) fs.writeToNBT(nbt); - nbt_setter_.accept(container_, nbt); - } - - @Override - public ItemStack getContainer() - { return container_; } - - @Override - public int getTanks() - { return 1; } - - @Override - public FluidStack getFluidInTank(int tank) - { return readnbt(); } - - @Override - public int getTankCapacity(int tank) - { return capacity_; } - - @Override - public boolean isFluidValid(int tank, FluidStack fs) - { return isFluidValid(fs); } - - public boolean isFluidValid(FluidStack fs) - { return validator_.test(fs); } - - @Override - public int fill(FluidStack fs, FluidAction action) - { - if((fs.isEmpty()) || (!isFluidValid(fs) || (container_.getCount()!=1))) return 0; - FluidStack tank = readnbt(); - final int amount = Math.min(Math.min(fs.getAmount(),transfer_rate_), capacity_-tank.getAmount()); - if(amount <= 0) return 0; - if(tank.isEmpty()) { - if(action.execute()) { - tank = new FluidStack(fs.getFluid(), amount, fs.getTag()); - writenbt(tank); - } - } else { - if(!tank.isFluidEqual(fs)) { - return 0; - } else if(action.execute()) { - tank.grow(amount); - writenbt(tank); - } - } - return amount; - } - - @Override - public FluidStack drain(FluidStack fs, FluidAction action) - { - if((fs.isEmpty()) || (container_.getCount()!=1)) return FluidStack.EMPTY; - final FluidStack tank = readnbt(); - if((!tank.isEmpty()) && (!tank.isFluidEqual(fs))) return FluidStack.EMPTY; - return drain(fs.getAmount(), action); - } - - @Override - public FluidStack drain(int max, FluidAction action) - { - if((max<=0) || (container_.getCount()!=1)) return FluidStack.EMPTY; - FluidStack tank = readnbt(); - if(tank.isEmpty()) return FluidStack.EMPTY; - final int amount = Math.min(Math.min(tank.getAmount(), max), transfer_rate_); - final FluidStack fs = tank.copy(); - fs.setAmount(amount); - if(action.execute()) { tank.shrink(amount); writenbt(tank); } - return fs; - } - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/Guis.java b/src/main/java/wile/engineersdecor/libmc/Guis.java deleted file mode 100644 index eb85541..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Guis.java +++ /dev/null @@ -1,436 +0,0 @@ -/* - * @file Guis.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Gui Wrappers and Widgets. - */ -package wile.engineersdecor.libmc; - -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.narration.NarrationElementOutput; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.sounds.SoundManager; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import java.util.Arrays; -import java.util.function.Consumer; -import java.util.function.Function; - - -public class Guis -{ - // ------------------------------------------------------------------------------------------------------------------- - // Gui base - // ------------------------------------------------------------------------------------------------------------------- - - @OnlyIn(Dist.CLIENT) - public static abstract class ContainerGui extends AbstractContainerScreen - { - protected final ResourceLocation background_image_; - protected final Player player_; - protected final Guis.BackgroundImage gui_background_; - protected final TooltipDisplay tooltip_ = new TooltipDisplay(); - - public ContainerGui(T menu, Inventory player_inv, Component title, String background_image, int width, int height) - { - super(menu, player_inv, title); - this.background_image_ = new ResourceLocation(Auxiliaries.modid(), background_image); - this.player_ = player_inv.player; - this.imageWidth = width; - this.imageHeight = height; - gui_background_ = new Guis.BackgroundImage(background_image_, width, height, Coord2d.ORIGIN); - } - - public ContainerGui(T menu, Inventory player_inv, Component title, String background_image) - { - super(menu, player_inv, title); - this.background_image_ = new ResourceLocation(Auxiliaries.modid(), background_image); - this.player_ = player_inv.player; - gui_background_ = new Guis.BackgroundImage(background_image_, imageWidth, imageHeight, Coord2d.ORIGIN); - } - - @Override - public void init() - { - super.init(); - gui_background_.init(this, Coord2d.ORIGIN).show(); - } - - @Override - public void render(PoseStack mx, int mouseX, int mouseY, float partialTicks) - { - renderBackground(mx); - super.render(mx, mouseX, mouseY, partialTicks); - if(!tooltip_.render(mx, this, mouseX, mouseY)) renderTooltip(mx, mouseX, mouseY); - } - - @Override - protected void renderLabels(PoseStack mx, int x, int y) - {} - - @Override - @SuppressWarnings("deprecation") - protected final void renderBg(PoseStack mx, float partialTicks, int mouseX, int mouseY) - { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableDepthTest(); - gui_background_.draw(mx, this); - renderBgWidgets(mx, partialTicks, mouseX, mouseY); - RenderSystem.disableBlend(); - } - - public final ResourceLocation getBackgroundImage() - { return background_image_; } - - protected void renderBgWidgets(PoseStack mx, float partialTicks, int mouseX, int mouseY) - {} - - protected void renderItemTemplate(PoseStack mx, ItemStack stack, int x, int y) - { - final ItemRenderer ir = itemRenderer; - final int main_zl = getBlitOffset(); - final float zl = ir.blitOffset; - final int x0 = getGuiLeft(); - final int y0 = getGuiTop(); - ir.blitOffset = -80; - ir.renderGuiItem(stack, x0+x, y0+y); - RenderSystem.disableColorLogicOp(); //RenderSystem.disableColorMaterial(); - RenderSystem.enableDepthTest(); //RenderSystem.enableAlphaTest(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableBlend(); - ir.blitOffset = zl; - setBlitOffset(100); - RenderSystem.colorMask(true, true, true, true); - RenderSystem.setShaderColor(0.7f, 0.7f, 0.7f, 0.8f); - RenderSystem.setShaderTexture(0, background_image_); - blit(mx, x0+x, y0+y, x, y, 16, 16); - RenderSystem.setShaderColor(1f, 1f, 1f, 1f); - setBlitOffset(main_zl); - } - } - - // ------------------------------------------------------------------------------------------------------------------- - // Gui elements - // ------------------------------------------------------------------------------------------------------------------- - - @OnlyIn(Dist.CLIENT) - public static class Coord2d - { - public static final Coord2d ORIGIN = new Coord2d(0,0); - public final int x, y; - public Coord2d(int x, int y) { this.x=x; this.y=y; } - public static Coord2d of(int x, int y) { return new Coord2d(x,y); } - public String toString() { return "["+x+","+y+"]"; } - } - - @OnlyIn(Dist.CLIENT) - public static class UiWidget extends net.minecraft.client.gui.components.AbstractWidget - { - protected static final Component EMPTY_TEXT = Component.literal(""); - protected static final Function NO_TOOLTIP = (uiw)->EMPTY_TEXT; - - private final Minecraft mc_; - private Function tooltip_ = NO_TOOLTIP; - private Screen parent_; - - public UiWidget(int x, int y, int width, int height, Component title) - { super(x, y, width, height, title); mc_ = Minecraft.getInstance(); } - - public UiWidget init(Screen parent) - { - this.parent_ = parent; - this.x += ((parent instanceof AbstractContainerScreen) ? ((AbstractContainerScreen)parent).getGuiLeft() : 0); - this.y += ((parent instanceof AbstractContainerScreen) ? ((AbstractContainerScreen)parent).getGuiTop() : 0); - return this; - } - - public UiWidget init(Screen parent, Coord2d position) - { - this.parent_ = parent; - this.x = position.x + ((parent instanceof AbstractContainerScreen) ? ((AbstractContainerScreen)parent).getGuiLeft() : 0); - this.y = position.y + ((parent instanceof AbstractContainerScreen) ? ((AbstractContainerScreen)parent).getGuiTop() : 0); - return this; - } - - public final UiWidget tooltip(Function tip) - { tooltip_ = tip; return this; } - - public final UiWidget tooltip(Component tip) - { tooltip_ = (o)->tip; return this; } - - public final int getWidth() - { return this.width; } - - public final int getHeight() - { return this.height; } - - public Coord2d getMousePosition() - { - final Window win = mc_.getWindow(); - return Coord2d.of( - Mth.clamp(((int)(mc_.mouseHandler.xpos() * (double)win.getGuiScaledWidth() / (double)win.getScreenWidth()))-this.x, -1, this.width+1), - Mth.clamp(((int)(mc_.mouseHandler.ypos() * (double)win.getGuiScaledHeight() / (double)win.getScreenHeight()))-this.y, -1, this.height+1) - ); - } - - protected final Coord2d screenCoordinates(Coord2d xy, boolean reverse) - { return (reverse) ? (Coord2d.of(xy.x+x, xy.y+y)) : (Coord2d.of(xy.x-x, xy.y-y)); } - - public UiWidget show() - { visible = true; return this; } - - public UiWidget hide() - { visible = false; return this; } - - @Override - public void renderButton(PoseStack mxs, int mouseX, int mouseY, float partialTicks) - { - super.renderButton(mxs, mouseX, mouseY, partialTicks); - if(isHovered) renderToolTip(mxs, mouseX, mouseY); - } - - @Override - @SuppressWarnings("all") - public void renderToolTip(PoseStack mx, int mouseX, int mouseY) - { - if(!visible || (!active) || (tooltip_ == NO_TOOLTIP)) return; - final Component tip = tooltip_.apply(this); - if(tip.getString().trim().isEmpty()) return; - parent_.renderTooltip(mx, Arrays.asList(tip.getVisualOrderText()), mouseX, mouseY); - } - - @Override - public void updateNarration(NarrationElementOutput element_output) - {} - } - - @OnlyIn(Dist.CLIENT) - public static class HorizontalProgressBar extends UiWidget - { - private final Coord2d texture_position_base_; - private final Coord2d texture_position_filled_; - private final ResourceLocation atlas_; - private double progress_max_ = 100; - private double progress_ = 0; - - public HorizontalProgressBar(ResourceLocation atlas, int width, int height, Coord2d base_texture_xy, Coord2d filled_texture_xy) - { - super(0, 0, width, height, EMPTY_TEXT); - atlas_ = atlas; - texture_position_base_ = base_texture_xy; - texture_position_filled_ = filled_texture_xy; - } - - public HorizontalProgressBar setProgress(double progress) - { progress_ = Mth.clamp(progress, 0, progress_max_); return this; } - - public double getProgress() - { return progress_; } - - public HorizontalProgressBar setMaxProgress(double progress) - { progress_max_ = Math.max(progress, 0); return this; } - - public double getMaxProgress() - { return progress_max_; } - - public HorizontalProgressBar show() - { visible = true; return this; } - - public HorizontalProgressBar hide() - { visible = false; return this; } - - @Override - public void playDownSound(SoundManager handler) - {} - - @Override - protected void renderBg(PoseStack mx, Minecraft mc, int x, int y) - {} - - @Override - public void renderButton(PoseStack mxs, int mouseX, int mouseY, float partialTicks) - { - RenderSystem.setShaderTexture(0, atlas_); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableDepthTest(); - blit(mxs, x, y, texture_position_base_.x, texture_position_base_.y, width, height); - if((progress_max_ > 0) && (progress_ > 0)) { - int w = Mth.clamp((int)Math.round((progress_ * width) / progress_max_), 0, width); - blit(mxs, x, y, texture_position_filled_.x, texture_position_filled_.y, w, height); - } - if(isHovered) renderToolTip(mxs, mouseX, mouseY); - } - } - - @OnlyIn(Dist.CLIENT) - public static class BackgroundImage extends UiWidget - { - private final ResourceLocation atlas_; - private final Coord2d atlas_position_; - public boolean visible; - - public BackgroundImage(ResourceLocation atlas, int width, int height, Coord2d atlas_position) - { - super(0, 0, width, height, EMPTY_TEXT); - atlas_ = atlas; - atlas_position_ = atlas_position; - this.width = width; - this.height = height; - visible = true; - } - - public void draw(PoseStack mx, Screen parent) - { - if(!visible) return; - RenderSystem.setShaderTexture(0, atlas_); - parent.blit(mx, x, y, atlas_position_.x, atlas_position_.y, width, height); - } - } - - @OnlyIn(Dist.CLIENT) - public static class CheckBox extends UiWidget - { - private final Coord2d texture_position_off_; - private final Coord2d texture_position_on_; - private final ResourceLocation atlas_; - private boolean checked_ = false; - private Consumer on_click_ = (checkbox)->{}; - - public CheckBox(ResourceLocation atlas, int width, int height, Coord2d atlas_texture_position_off, Coord2d atlas_texture_position_on) - { - super(0, 0, width, height, EMPTY_TEXT); - texture_position_off_ = atlas_texture_position_off; - texture_position_on_ = atlas_texture_position_on; - atlas_ = atlas; - } - - public boolean checked() - { return checked_; } - - public CheckBox checked(boolean on) - { checked_ = on; return this; } - - public CheckBox onclick(Consumer action) - { on_click_ = action; return this; } - - @Override - public void onClick(double mouseX, double mouseY) - { checked_ = !checked_; on_click_.accept(this); } - - @Override - public void renderButton(PoseStack mxs, int mouseX, int mouseY, float partialTicks) - { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderTexture(0, atlas_); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableDepthTest(); - Coord2d pos = checked_ ? texture_position_on_ : texture_position_off_; - blit(mxs, x, y, pos.x, pos.y, width, height); - if(isHovered) renderToolTip(mxs, mouseX, mouseY); - } - } - - @OnlyIn(Dist.CLIENT) - public static class ImageButton extends UiWidget - { - private final Coord2d texture_position_; - private final ResourceLocation atlas_; - private Consumer on_click_ = (bt)->{}; - - - public ImageButton(ResourceLocation atlas, int width, int height, Coord2d atlas_texture_position) - { - super(0, 0, width, height, Component.empty()); - texture_position_ = atlas_texture_position; - atlas_ = atlas; - } - - public ImageButton onclick(Consumer action) - { on_click_ = action; return this; } - - @Override - public void onClick(double mouseX, double mouseY) - { on_click_.accept(this); } - - @Override - public void renderButton(PoseStack mxs, int mouseX, int mouseY, float partialTicks) - { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderTexture(0, atlas_); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableDepthTest(); - Coord2d pos = texture_position_; - blit(mxs, x, y, pos.x, pos.y, width, height); - if(isHovered) renderToolTip(mxs, mouseX, mouseY); - } - } - - @OnlyIn(Dist.CLIENT) - public static class Image extends UiWidget - { - private final Coord2d texture_position_; - private final ResourceLocation atlas_; - - public Image(ResourceLocation atlas, int width, int height, Coord2d atlas_texture_position) - { - super(0, 0, width, height, Component.empty()); - texture_position_ = atlas_texture_position; - atlas_ = atlas; - } - - @Override - public void onClick(double mouseX, double mouseY) - {} - - @Override - public void renderButton(PoseStack mxs, int mouseX, int mouseY, float partialTicks) - { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderTexture(0, atlas_); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableDepthTest(); - Coord2d pos = texture_position_; - blit(mxs, x, y, pos.x, pos.y, width, height); - if(isHovered) renderToolTip(mxs, mouseX, mouseY); - } - } - - @OnlyIn(Dist.CLIENT) - public static class TextBox extends net.minecraft.client.gui.components.EditBox - { - public TextBox(int x, int y, int width, int height, Component title, Font font) { super(font, x, y, width, height, title); setBordered(false); } - public TextBox withMaxLength(int len) { super.setMaxLength(len); return this; } - public TextBox withBordered(boolean b) { super.setBordered(b); return this; } - public TextBox withValue(String s) { super.setValue(s); return this; } - public TextBox withEditable(boolean e) { super.setEditable(e); return this; } - public TextBox withResponder(Consumer r) { super.setResponder(r); return this; } - } -} diff --git a/src/main/java/wile/engineersdecor/libmc/Inventories.java b/src/main/java/wile/engineersdecor/libmc/Inventories.java deleted file mode 100644 index 5714b3b..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Inventories.java +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * @file Inventories.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * General inventory item handling functionality. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.*; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraft.nbt.Tag; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.wrapper.InvWrapper; -import net.minecraftforge.items.wrapper.PlayerMainInvWrapper; -import net.minecraftforge.items.wrapper.SidedInvWrapper; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.BiPredicate; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - - -public class Inventories -{ - public static boolean areItemStacksIdentical(ItemStack a, ItemStack b) - { return (a.getItem()==b.getItem()) && ItemStack.tagMatches(a, b); } - - public static boolean areItemStacksDifferent(ItemStack a, ItemStack b) - { return (a.getItem()!=b.getItem()) || (!ItemStack.tagMatches(a, b)); } - - public static IItemHandler itemhandler(Level world, BlockPos pos, @Nullable Direction side) - { - BlockEntity te = world.getBlockEntity(pos); - if(te==null) return null; - IItemHandler ih = te.getCapability(ForgeCapabilities.ITEM_HANDLER, side).orElse(null); - if(ih!=null) return ih; - if((side!=null) && (te instanceof WorldlyContainer)) return new SidedInvWrapper((WorldlyContainer)te, side); - if(te instanceof Container) return new InvWrapper((Container)te); - return null; - } - - public static IItemHandler itemhandler(Level world, BlockPos pos, @Nullable Direction side, boolean including_entities) - { - IItemHandler ih = itemhandler(world, pos, side); - if(ih != null) return ih; - if(!including_entities) return null; - Entity entity = world.getEntitiesOfClass(Entity.class, new AABB(pos), (e)->(e instanceof Container)).stream().findFirst().orElse(null); - return (entity==null) ? (null) : (itemhandler(entity,side)); - } - - public static IItemHandler itemhandler(Player player) - { return new PlayerMainInvWrapper(player.getInventory()); } - - public static IItemHandler itemhandler(Entity entity) - { return itemhandler(entity, null); } - - public static IItemHandler itemhandler(Entity entity, @Nullable Direction side) - { - if(entity==null) return null; - final IItemHandler ih = entity.getCapability(ForgeCapabilities.ITEM_HANDLER, side).orElse(null); - if(ih!=null) return ih; - if(entity instanceof Container container) return (new InvWrapper(container)); - return null; - } - - public static boolean insertionPossible(Level world, BlockPos pos, @Nullable Direction side, boolean including_entities) - { return itemhandler(world, pos, side, including_entities) != null; } - - public static ItemStack insert(IItemHandler handler, ItemStack stack , boolean simulate) - { return ItemHandlerHelper.insertItemStacked(handler, stack, simulate); } - - public static ItemStack insert(BlockEntity te, @Nullable Direction side, ItemStack stack, boolean simulate) - { - if(te == null) return stack; - IItemHandler hnd = te.getCapability(ForgeCapabilities.ITEM_HANDLER, side).orElse(null); - if(hnd == null) { - if((side != null) && (te instanceof WorldlyContainer)) { - hnd = new SidedInvWrapper((WorldlyContainer)te, side); - } else if(te instanceof Container) { - hnd = new InvWrapper((Container)te); - } - } - return (hnd==null) ? stack : insert(hnd, stack, simulate); - } - - public static ItemStack insert(Level world, BlockPos pos, @Nullable Direction side, ItemStack stack, boolean simulate, boolean including_entities) - { return insert(itemhandler(world, pos, side, including_entities), stack, simulate); } - - public static ItemStack insert(Level world, BlockPos pos, @Nullable Direction side, ItemStack stack, boolean simulate) - { return insert(world, pos, side, stack, simulate, false); } - - public static ItemStack extract(IItemHandler inventory, @Nullable ItemStack match, int amount, boolean simulate) - { - if((inventory==null) || (amount<=0) || ((match!=null) && (match.isEmpty()))) return ItemStack.EMPTY; - final int max = inventory.getSlots(); - ItemStack out_stack = ItemStack.EMPTY; - for(int i=0; i= amount) break; - } - return out_stack; - } - - private static ItemStack checked(ItemStack stack) - { return stack.isEmpty() ? ItemStack.EMPTY : stack; } - - public static Container copyOf(Container src) - { - final int size = src.getContainerSize(); - SimpleContainer dst = new SimpleContainer(size); - for(int i=0; i extraction_predicate_; - private final BiPredicate insertion_predicate_; - private final BiConsumer insertion_notifier_; - private final BiConsumer extraction_notifier_; - private final List slot_map_; - private final Container inv_; - - public MappedItemHandler(Container inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate, BiConsumer insertion_notifier, BiConsumer extraction_notifier) - { inv_ = inv; extraction_predicate_ = extraction_predicate; insertion_predicate_ = insertion_predicate; insertion_notifier_=insertion_notifier; extraction_notifier_=extraction_notifier; slot_map_ = IntStream.range(0, inv.getContainerSize()).boxed().collect(Collectors.toList()); } - - public MappedItemHandler(Container inv, List slot_map, BiPredicate extraction_predicate, BiPredicate insertion_predicate, BiConsumer insertion_notifier, BiConsumer extraction_notifier) - { inv_ = inv; extraction_predicate_ = extraction_predicate; insertion_predicate_ = insertion_predicate; insertion_notifier_=insertion_notifier; extraction_notifier_=extraction_notifier; slot_map_ = slot_map; } - - public MappedItemHandler(Container inv, List slot_map, BiPredicate extraction_predicate, BiPredicate insertion_predicate) - { this(inv, slot_map, extraction_predicate, insertion_predicate, (i,s)->{}, (i,s)->{}); } - - public MappedItemHandler(Container inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate) - { this(inv, IntStream.range(0, inv.getContainerSize()).boxed().collect(Collectors.toList()), extraction_predicate, insertion_predicate); } - - public MappedItemHandler(Container inv) - { this(inv, (i,s)->true, (i,s)->true); } - - @Override - public int hashCode() - { return inv_.hashCode(); } - - @Override - public boolean equals(Object o) - { return (o==this) || ((o!=null) && (getClass()==o.getClass()) && (inv_.equals(((MappedItemHandler)o).inv_))); } - - // IItemHandler ----------------------------------------------------------------------------------------------- - - @Override - public int getSlots() - { return slot_map_.size(); } - - @Override - @Nonnull - public ItemStack getStackInSlot(int slot) - { return (slot >= slot_map_.size()) ? ItemStack.EMPTY : inv_.getItem(slot_map_.get(slot)); } - - @Override - public int getSlotLimit(int slot) - { return inv_.getMaxStackSize(); } - - @Override - public boolean isItemValid(int slot, @Nonnull ItemStack stack) - { - if(slot >= slot_map_.size()) return false; - slot = slot_map_.get(slot); - return insertion_predicate_.test(slot, stack) && inv_.canPlaceItem(slot, stack); - } - - @Override - @Nonnull - public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) - { - if(stack.isEmpty()) return ItemStack.EMPTY; - if(slot >= slot_map_.size()) return stack; - slot = slot_map_.get(slot); - if(!insertion_predicate_.test(slot, stack)) return stack; - if(!inv_.canPlaceItem(slot, stack)) return stack; - ItemStack sst = inv_.getItem(slot); - final int slot_limit = inv_.getMaxStackSize(); - if(!sst.isEmpty()) { - if(sst.getCount() >= Math.min(sst.getMaxStackSize(), slot_limit)) return stack; - if(!ItemHandlerHelper.canItemStacksStack(stack, sst)) return stack; - final int limit = Math.min(stack.getMaxStackSize(), slot_limit) - sst.getCount(); - if(stack.getCount() <= limit) { - if(!simulate) { - stack = stack.copy(); - stack.grow(sst.getCount()); - inv_.setItem(slot, stack); - inv_.setChanged(); - insertion_notifier_.accept(slot, sst); - } - return ItemStack.EMPTY; - } else { - stack = stack.copy(); - if(simulate) { - stack.shrink(limit); - } else { - final ItemStack diff = stack.split(limit); - sst.grow(diff.getCount()); - inv_.setItem(slot, sst); - inv_.setChanged(); - insertion_notifier_.accept(slot, diff); - } - return stack; - } - } else { - final int limit = Math.min(slot_limit, stack.getMaxStackSize()); - if(stack.getCount() >= limit) { - stack = stack.copy(); - final ItemStack ins = stack.split(limit); - if(!simulate) { - inv_.setItem(slot, ins); - inv_.setChanged(); - insertion_notifier_.accept(slot, ins.copy()); - } - if(stack.isEmpty()) { - stack = ItemStack.EMPTY; - } - return stack; - } else { - if(!simulate) { - inv_.setItem(slot, stack.copy()); - inv_.setChanged(); - insertion_notifier_.accept(slot, stack.copy()); - } - return ItemStack.EMPTY; - } - } - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) - { - if(amount <= 0) return ItemStack.EMPTY; - if(slot >= slot_map_.size()) return ItemStack.EMPTY; - slot = slot_map_.get(slot); - ItemStack stack = inv_.getItem(slot); - if(!extraction_predicate_.test(slot, stack)) return ItemStack.EMPTY; - if(simulate) { - stack = stack.copy(); - if(amount < stack.getCount()) stack.setCount(amount); - } else { - stack = inv_.removeItem(slot, Math.min(stack.getCount(), amount)); - inv_.setChanged(); - extraction_notifier_.accept(slot, stack.copy()); - } - return stack; - } - - // Factories -------------------------------------------------------------------------------------------- - - public static LazyOptional createGenericHandler(Container inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate, BiConsumer insertion_notifier, BiConsumer extraction_notifier) - { return LazyOptional.of(() -> new MappedItemHandler(inv, extraction_predicate, insertion_predicate, insertion_notifier, extraction_notifier)); } - - public static LazyOptional createGenericHandler(Container inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate, BiConsumer insertion_notifier, BiConsumer extraction_notifier, List slot_map) - { return LazyOptional.of(() -> new MappedItemHandler(inv, slot_map, extraction_predicate, insertion_predicate, insertion_notifier, extraction_notifier)); } - - public static LazyOptional createGenericHandler(Container inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate, List slot_map) - { return LazyOptional.of(() -> new MappedItemHandler(inv, slot_map, extraction_predicate, insertion_predicate)); } - - public static LazyOptional createGenericHandler(Container inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate) - { return LazyOptional.of(() -> new MappedItemHandler(inv, extraction_predicate, insertion_predicate)); } - - public static LazyOptional createGenericHandler(Container inv) - { return LazyOptional.of(() -> new MappedItemHandler(inv)); } - - public static LazyOptional createExtractionHandler(Container inv, BiPredicate extraction_predicate, List slot_map) - { return LazyOptional.of(() -> new MappedItemHandler(inv, slot_map, extraction_predicate, (i, s)->false)); } - - public static LazyOptional createExtractionHandler(Container inv, BiPredicate extraction_predicate) - { return LazyOptional.of(() -> new MappedItemHandler(inv, extraction_predicate, (i, s)->false)); } - - public static LazyOptional createExtractionHandler(Container inv, Integer... slots) - { return LazyOptional.of(() -> new MappedItemHandler(inv, Arrays.asList(slots), (i, s)->true, (i, s)->false)); } - - public static LazyOptional createExtractionHandler(Container inv) - { return LazyOptional.of(() -> new MappedItemHandler(inv, (i, s)->true, (i, s)->false)); } - - public static LazyOptional createInsertionHandler(Container inv, BiPredicate insertion_predicate, List slot_map) - { return LazyOptional.of(() -> new MappedItemHandler(inv, slot_map, (i, s)->false, insertion_predicate)); } - - public static LazyOptional createInsertionHandler(Container inv, Integer... slots) - { return LazyOptional.of(() -> new MappedItemHandler(inv, Arrays.asList(slots), (i, s)->false, (i, s)->true)); } - - public static LazyOptional createInsertionHandler(Container inv, BiPredicate insertion_predicate) - { return LazyOptional.of(() -> new MappedItemHandler(inv, (i, s)->false, insertion_predicate)); } - - public static LazyOptional createInsertionHandler(Container inv) - { return LazyOptional.of(() -> new MappedItemHandler(inv, (i, s)->false, (i, s)->true)); } - } - - //-------------------------------------------------------------------------------------------------------------------- - - public static class InventoryRange implements Container, Iterable - { - protected final Container inventory_; - protected final int offset_, size_, num_rows; - protected int max_stack_size_ = 64; - protected BiPredicate validator_ = (index, stack)->true; - - public static InventoryRange fromPlayerHotbar(Player player) - { return new InventoryRange(player.getInventory(), 0, 9, 1); } - - public static InventoryRange fromPlayerStorage(Player player) - { return new InventoryRange(player.getInventory(), 9, 27, 3); } - - public static InventoryRange fromPlayerInventory(Player player) - { return new InventoryRange(player.getInventory(), 0, 36, 4); } - - public InventoryRange(Container inventory, int offset, int size, int num_rows) - { - this.inventory_ = inventory; - this.offset_ = Mth.clamp(offset, 0, inventory.getContainerSize()-1); - this.size_ = Mth.clamp(size, 0, inventory.getContainerSize()-this.offset_); - this.num_rows = num_rows; - } - - public InventoryRange(Container inventory, int offset, int size) - { this(inventory, offset, size, 1); } - - public InventoryRange(Container inventory) - { this(inventory, 0, inventory.getContainerSize(), 1); } - - public final Container inventory() - { return inventory_; } - - public final int size() - { return size_; } - - public final int offset() - { return offset_; } - - public final ItemStack get(int index) - { return inventory_.getItem(offset_+index); } - - public final void set(int index, ItemStack stack) - { inventory_.setItem(offset_+index, stack); } - - public final InventoryRange setValidator(BiPredicate validator) - { validator_ = validator; return this; } - - public final BiPredicate getValidator() - { return validator_; } - - public final InventoryRange setMaxStackSize(int count) - { max_stack_size_ = Math.max(count, 1) ; return this; } - - // Container ------------------------------------------------------------------------------------------------------ - - @Override - public void clearContent() - { for(int i=0; i bool until the function matches (returns true). - */ - public boolean iterate(BiPredicate fn) - { for(int i=0; i Optional find(BiFunction> fn) - { - for(int i=0; i r = fn.apply(i,getItem(i)); - if(r.isPresent()) return r; - } - return Optional.empty(); - } - - public List collect(BiFunction> fn) - { - List data = new ArrayList<>(); - for(int i=0; i stream() - { return java.util.stream.StreamSupport.stream(this.spliterator(), false); } - - public Iterator iterator() - { return new InventoryRangeIterator(this); } - - public static class InventoryRangeIterator implements Iterator - { - private final InventoryRange parent_; - private int index = 0; - - public InventoryRangeIterator(InventoryRange range) - { parent_ = range; } - - public boolean hasNext() - { return index < parent_.size_; } - - public ItemStack next() - { - if(index >= parent_.size_) throw new NoSuchElementException(); - return parent_.getItem(index++); - } - } - - //------------------------------------------------------------------------------------------------------------------ - - /** - * Returns the number of stacks that match the given stack with NBT. - */ - public int stackMatchCount(final ItemStack ref_stack) - { - int n = 0; // ... std::accumulate() the old school way. - for(int i=0; i0) ? (Math.min(limit, mvstack.getMaxStackSize())) : (mvstack.getMaxStackSize()); - boolean[] matches = new boolean[size_]; - boolean[] empties = new boolean[size_]; - int num_matches = 0; - for(int i=0; i < size_; ++i) { - final int sno = reverse ? (size_-1-i) : (i); - final ItemStack stack = getItem(sno); - if(stack.isEmpty()) { - empties[sno] = true; - } else if(areItemStacksIdentical(stack, mvstack)) { - matches[sno] = true; - ++num_matches; - } - } - // first iteration: fillup existing stacks - for(int i=0; i0) && ((force_group_stacks) || (inventory_ instanceof Inventory))) { - // second iteration: use appropriate empty slots, - // a) between - { - int insert_start = -1; - int insert_end = -1; - int i = 1; - for(;i= 0) && (canPlaceItem(ii, mvstack))) { - int nmax = Math.min(limit_left, mvstack.getCount()); - ItemStack moved = mvstack.copy(); - moved.setCount(nmax); - mvstack.shrink(nmax); - setItem(ii, moved); - return checked(mvstack); - } - } - } - } - // third iteration: use any empty slots - for(int i=0; i= limit) || !areItemStacksIdentical(stack, stack_to_move)) { - return stack_to_move; - } else { - final int amount = Math.min(limit-stack.getCount(), stack_to_move.getCount()); - ItemStack remaining = stack_to_move.copy(); - remaining.shrink(amount); - stack.grow(amount); - return remaining.isEmpty() ? ItemStack.EMPTY : remaining; - } - } - - //------------------------------------------------------------------------------------------------------------------ - - /** - * Extracts maximum amount of items from the inventory_. - * The first non-empty stack defines the item. - */ - public ItemStack extract(int amount) - { return extract(amount, false); } - - public ItemStack extract(int amount, boolean random) - { - ItemStack out_stack = ItemStack.EMPTY; - int offset = random ? (int)(Math.random()*size_) : 0; - for(int k=0; k matches = new ArrayList<>(); - for(int i=0; i 0) && (nbt.contains("Damage"))) --n; - if(n > 0) continue; - } - matches.add(stack); - } - } - matches.sort(Comparator.comparingInt(ItemStack::getCount)); - if(matches.isEmpty()) return ItemStack.EMPTY; - int n_left = request_stack.getCount(); - ItemStack fetched_stack = matches.get(0).split(n_left); - n_left -= fetched_stack.getCount(); - for(int i=1; (i0); ++i) { - ItemStack stack = matches.get(i).split(n_left); - n_left -= stack.getCount(); - fetched_stack.grow(stack.getCount()); - } - return checked(fetched_stack); - } - - //------------------------------------------------------------------------------------------------------------------ - - /** - * Moves items from this inventory_ range to another. Returns true if something was moved - * (if the inventories should be marked dirty). - */ - public boolean move(int index, final InventoryRange target_range, boolean all_identical_stacks, boolean only_fillup, boolean reverse, boolean force_group_stacks) - { - final ItemStack source_stack = getItem(index); - if(source_stack.isEmpty()) return false; - if(!all_identical_stacks) { - ItemStack remaining = target_range.insert(source_stack, only_fillup, 0, reverse, force_group_stacks); - setItem(index, remaining); - return (remaining.getCount() != source_stack.getCount()); - } else { - ItemStack remaining = source_stack.copy(); - setItem(index, ItemStack.EMPTY); - final ItemStack ref_stack = remaining.copy(); - ref_stack.setCount(ref_stack.getMaxStackSize()); - for(int i=size_; (i>0) && (!remaining.isEmpty()); --i) { - remaining = target_range.insert(remaining, only_fillup, 0, reverse, force_group_stacks); - if(!remaining.isEmpty()) break; - remaining = this.extract(ref_stack); - } - if(!remaining.isEmpty()) { - setItem(index, remaining); // put back - } - return (remaining.getCount() != source_stack.getCount()); - } - } - - public boolean move(int index, final InventoryRange target_range) - { return move(index, target_range, false, false, false, true); } - - /** - * Moves/clears the complete range to another range if possible. Returns true if something was moved - * (if the inventories should be marked dirty). - */ - public boolean move(final InventoryRange target_range, boolean only_fillup, boolean reverse, boolean force_group_stacks) - { - boolean changed = false; - for(int i=0; i - { - protected final NonNullList stacks_; - protected final BlockEntity te_; - protected final int size_; - protected final int num_rows_; - protected int stack_limit_ = 64; - protected BiPredicate validator_ = (index, stack)->true; - protected Consumer open_action_ = (player)->{}; - protected Consumer close_action_ = (player)->{}; - protected BiConsumer slot_set_action_ = (index, stack)->{}; - - public StorageInventory(BlockEntity te, int size) - { this(te, size, 1); } - - public StorageInventory(BlockEntity te, int size, int num_rows) - { - te_ = te; - size_ = Math.max(size, 1); - stacks_ = NonNullList.withSize(size_, ItemStack.EMPTY); - num_rows_ = Mth.clamp(num_rows, 1, size_); - } - public CompoundTag save(CompoundTag nbt, String key) - { nbt.put(key, save(new CompoundTag(), false)); return nbt; } - - public CompoundTag save(CompoundTag nbt) - { return ContainerHelper.saveAllItems(nbt, stacks_); } - - public CompoundTag save(CompoundTag nbt, boolean save_empty) - { return ContainerHelper.saveAllItems(nbt, stacks_, save_empty); } - - public CompoundTag save(boolean save_empty) - { return save(new CompoundTag(), save_empty); } - - public StorageInventory load(CompoundTag nbt, String key) - { - if(!nbt.contains("key", Tag.TAG_COMPOUND)) { - stacks_.clear(); - return this; - } else { - return load(nbt.getCompound(key)); - } - } - - public StorageInventory load(CompoundTag nbt) - { stacks_.clear(); ContainerHelper.loadAllItems(nbt, stacks_); return this; } - - public List stacks() - { return stacks_; } - - public BlockEntity getBlockEntity() - { return te_; } - - public StorageInventory setOpenAction(Consumer fn) - { open_action_ = fn; return this; } - - public StorageInventory setCloseAction(Consumer fn) - { close_action_ = fn; return this; } - - public StorageInventory setSlotChangeAction(BiConsumer fn) - { slot_set_action_ = fn; return this; } - - public StorageInventory setStackLimit(int max_slot_stack_size) - { stack_limit_ = Math.max(max_slot_stack_size, 1); return this; } - - public StorageInventory setValidator(BiPredicate validator) - { validator_ = validator; return this; } - - public BiPredicate getValidator() - { return validator_; } - - // Iterable --------------------------------------------------------------------- - - public Iterator iterator() - { return stacks_.iterator(); } - - public Stream stream() - { return stacks_.stream(); } - - // Container ------------------------------------------------------------------------------ - - @Override - public int getContainerSize() - { return size_; } - - @Override - public boolean isEmpty() - { for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; } - - @Override - public ItemStack getItem(int index) - { return (index < size_) ? stacks_.get(index) : ItemStack.EMPTY; } - - @Override - public ItemStack removeItem(int index, int count) - { return ContainerHelper.removeItem(stacks_, index, count); } - - @Override - public ItemStack removeItemNoUpdate(int index) - { return ContainerHelper.takeItem(stacks_, index); } - - @Override - public void setItem(int index, ItemStack stack) - { - stacks_.set(index, stack); - if((stack.getCount() != stacks_.get(index).getCount()) || !areItemStacksDifferent(stacks_.get(index),stack)) { - slot_set_action_.accept(index, stack); - } - } - - @Override - public int getMaxStackSize() - { return stack_limit_; } - - @Override - public void setChanged() - { te_.setChanged(); } - - @Override - public boolean stillValid(Player player) - { return ((te_.getLevel().getBlockEntity(te_.getBlockPos()) == te_)) && (te_.getBlockPos().distSqr(player.blockPosition()) < 64); } - - @Override - public void startOpen(Player player) - { open_action_.accept(player); } - - @Override - public void stopOpen(Player player) - { setChanged(); close_action_.accept(player); } - - @Override - public boolean canPlaceItem(int index, ItemStack stack) - { return validator_.test(index, stack); } - - @Override - public void clearContent() - { stacks_.clear(); setChanged(); } - - } - - //-------------------------------------------------------------------------------------------------------------------- - - public static void give(Player entity, ItemStack stack) - { ItemHandlerHelper.giveItemToPlayer(entity, stack); } - - public static void setItemInPlayerHand(Player player, InteractionHand hand, ItemStack stack) - { - if(stack.isEmpty()) stack = ItemStack.EMPTY; - if(hand == InteractionHand.MAIN_HAND) { - player.getInventory().items.set(player.getInventory().selected, stack); - } else { - player.getInventory().offhand.set(0, stack); - } - } - - //-------------------------------------------------------------------------------------------------------------------- - - public static Container readNbtStacks(CompoundTag nbt, String key, Container target) - { - NonNullList stacks = Inventories.readNbtStacks(nbt, key, target.getContainerSize()); - for(int i=0; i readNbtStacks(CompoundTag nbt, String key, int size) - { - NonNullList stacks = NonNullList.withSize(size, ItemStack.EMPTY); - if((nbt == null) || (!nbt.contains(key, Tag.TAG_COMPOUND))) return stacks; - CompoundTag stacknbt = nbt.getCompound(key); - ContainerHelper.loadAllItems(stacknbt, stacks); - return stacks; - } - - public static NonNullList readNbtStacks(CompoundTag nbt, int size) - { - NonNullList stacks = NonNullList.withSize(size, ItemStack.EMPTY); - if((nbt == null) || (!nbt.contains("Items", Tag.TAG_LIST))) return stacks; - ContainerHelper.loadAllItems(nbt, stacks); - return stacks; - } - - public static CompoundTag writeNbtStacks(CompoundTag nbt, String key, NonNullList stacks, boolean omit_trailing_empty) - { - CompoundTag stacknbt = new CompoundTag(); - if(omit_trailing_empty) { - for(int i=stacks.size()-1; i>=0; --i) { - if(!stacks.get(i).isEmpty()) break; - stacks.remove(i); - } - } - ContainerHelper.saveAllItems(stacknbt, stacks); - if(nbt == null) nbt = new CompoundTag(); - nbt.put(key, stacknbt); - return nbt; - } - - public static CompoundTag writeNbtStacks(CompoundTag nbt, String key, NonNullList stacks) - { return writeNbtStacks(nbt, key, stacks, false); } - - //-------------------------------------------------------------------------------------------------------------------- - - public static void dropStack(Level world, Vec3 pos, ItemStack stack, Vec3 velocity, double position_noise, double velocity_noise) - { - if(stack.isEmpty()) return; - if(position_noise > 0) { - position_noise = Math.min(position_noise, 0.8); - pos = pos.add( - position_noise * (world.getRandom().nextDouble()-.5), - position_noise * (world.getRandom().nextDouble()-.5), - position_noise * (world.getRandom().nextDouble()-.5) - ); - } - if(velocity_noise > 0) { - velocity_noise = Math.min(velocity_noise, 1.0); - velocity = velocity.add( - (velocity_noise) * (world.getRandom().nextDouble()-.5), - (velocity_noise) * (world.getRandom().nextDouble()-.5), - (velocity_noise) * (world.getRandom().nextDouble()-.5) - ); - } - ItemEntity e = new ItemEntity(world, pos.x, pos.y, pos.z, stack); - e.setDeltaMovement((float)velocity.x, (float)velocity.y, (float)velocity.z); - e.setDefaultPickUpDelay(); - world.addFreshEntity(e); - } - - public static void dropStack(Level world, Vec3 pos, ItemStack stack, Vec3 velocity) - { dropStack(world, pos, stack, velocity, 0.3, 0.2); } - - public static void dropStack(Level world, Vec3 pos, ItemStack stack) - { dropStack(world, pos, stack, Vec3.ZERO, 0.3, 0.2); } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/Networking.java b/src/main/java/wile/engineersdecor/libmc/Networking.java deleted file mode 100644 index 2857340..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Networking.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * @file Networking.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Main client/server message handling. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -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.inventory.AbstractContainerMenu; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkEvent; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.simple.SimpleChannel; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; - - -public class Networking -{ - private static final String PROTOCOL = "1"; - private static SimpleChannel DEFAULT_CHANNEL; - - public static void init(String modid) - { - DEFAULT_CHANNEL = NetworkRegistry.ChannelBuilder - .named(new ResourceLocation(modid, "default_ch")) - .clientAcceptedVersions(PROTOCOL::equals).serverAcceptedVersions(PROTOCOL::equals).networkProtocolVersion(() -> PROTOCOL) - .simpleChannel(); - int discr = -1; - DEFAULT_CHANNEL.registerMessage(++discr, PacketTileNotifyClientToServer.class, PacketTileNotifyClientToServer::compose, PacketTileNotifyClientToServer::parse, PacketTileNotifyClientToServer.Handler::handle); - DEFAULT_CHANNEL.registerMessage(++discr, PacketTileNotifyServerToClient.class, PacketTileNotifyServerToClient::compose, PacketTileNotifyServerToClient::parse, PacketTileNotifyServerToClient.Handler::handle); - DEFAULT_CHANNEL.registerMessage(++discr, PacketContainerSyncClientToServer.class, PacketContainerSyncClientToServer::compose, PacketContainerSyncClientToServer::parse, PacketContainerSyncClientToServer.Handler::handle); - DEFAULT_CHANNEL.registerMessage(++discr, PacketContainerSyncServerToClient.class, PacketContainerSyncServerToClient::compose, PacketContainerSyncServerToClient::parse, PacketContainerSyncServerToClient.Handler::handle); - DEFAULT_CHANNEL.registerMessage(++discr, PacketNbtNotifyClientToServer.class, PacketNbtNotifyClientToServer::compose, PacketNbtNotifyClientToServer::parse, PacketNbtNotifyClientToServer.Handler::handle); - DEFAULT_CHANNEL.registerMessage(++discr, PacketNbtNotifyServerToClient.class, PacketNbtNotifyServerToClient::compose, PacketNbtNotifyServerToClient::parse, PacketNbtNotifyServerToClient.Handler::handle); - DEFAULT_CHANNEL.registerMessage(++discr, OverlayTextMessage.class, OverlayTextMessage::compose, OverlayTextMessage::parse, OverlayTextMessage.Handler::handle); - } - - //-------------------------------------------------------------------------------------------------------------------- - // Tile entity notifications - //-------------------------------------------------------------------------------------------------------------------- - - public interface IPacketTileNotifyReceiver - { - default void onServerPacketReceived(CompoundTag nbt) {} - default void onClientPacketReceived(Player player, CompoundTag nbt) {} - } - - public static class PacketTileNotifyClientToServer - { - CompoundTag nbt = null; - BlockPos pos = BlockPos.ZERO; - - public static void sendToServer(BlockPos pos, CompoundTag nbt) - { if((pos!=null) && (nbt!=null)) DEFAULT_CHANNEL.sendToServer(new PacketTileNotifyClientToServer(pos, nbt)); } - - public static void sendToServer(BlockEntity te, CompoundTag nbt) - { if((te!=null) && (nbt!=null)) DEFAULT_CHANNEL.sendToServer(new PacketTileNotifyClientToServer(te, nbt)); } - - public PacketTileNotifyClientToServer() - {} - - public PacketTileNotifyClientToServer(BlockPos pos, CompoundTag nbt) - { this.nbt = nbt; this.pos = pos; } - - public PacketTileNotifyClientToServer(BlockEntity te, CompoundTag nbt) - { this.nbt = nbt; pos = te.getBlockPos(); } - - public static PacketTileNotifyClientToServer parse(final FriendlyByteBuf buf) - { return new PacketTileNotifyClientToServer(buf.readBlockPos(), buf.readNbt()); } - - public static void compose(final PacketTileNotifyClientToServer pkt, final FriendlyByteBuf buf) - { buf.writeBlockPos(pkt.pos); buf.writeNbt(pkt.nbt); } - - public static class Handler - { - public static void handle(final PacketTileNotifyClientToServer pkt, final Supplier ctx) - { - ctx.get().enqueueWork(() -> { - Player player = ctx.get().getSender(); - if(player==null) return; - Level world = player.level; - final BlockEntity te = world.getBlockEntity(pkt.pos); - if(!(te instanceof IPacketTileNotifyReceiver)) return; - ((IPacketTileNotifyReceiver)te).onClientPacketReceived(ctx.get().getSender(), pkt.nbt); - }); - ctx.get().setPacketHandled(true); - } - } - } - - public static class PacketTileNotifyServerToClient - { - CompoundTag nbt = null; - BlockPos pos = BlockPos.ZERO; - - public static void sendToPlayer(Player player, BlockEntity te, CompoundTag nbt) - { - if((!(player instanceof ServerPlayer)) || (player instanceof FakePlayer) || (te==null) || (nbt==null)) return; - DEFAULT_CHANNEL.sendTo(new PacketTileNotifyServerToClient(te, nbt), ((ServerPlayer)player).connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - public static void sendToPlayers(BlockEntity te, CompoundTag nbt) - { - if(te==null || te.getLevel()==null) return; - for(Player player: te.getLevel().players()) sendToPlayer(player, te, nbt); - } - - public PacketTileNotifyServerToClient() - {} - - public PacketTileNotifyServerToClient(BlockPos pos, CompoundTag nbt) - { this.nbt=nbt; this.pos=pos; } - - public PacketTileNotifyServerToClient(BlockEntity te, CompoundTag nbt) - { this.nbt=nbt; pos=te.getBlockPos(); } - - public static PacketTileNotifyServerToClient parse(final FriendlyByteBuf buf) - { return new PacketTileNotifyServerToClient(buf.readBlockPos(), buf.readNbt()); } - - public static void compose(final PacketTileNotifyServerToClient pkt, final FriendlyByteBuf buf) - { buf.writeBlockPos(pkt.pos); buf.writeNbt(pkt.nbt); } - - public static class Handler - { - public static void handle(final PacketTileNotifyServerToClient pkt, final Supplier ctx) - { - ctx.get().enqueueWork(() -> { - Level world = SidedProxy.getWorldClientSide(); - if(world == null) return; - final BlockEntity te = world.getBlockEntity(pkt.pos); - if(!(te instanceof IPacketTileNotifyReceiver)) return; - ((IPacketTileNotifyReceiver)te).onServerPacketReceived(pkt.nbt); - }); - ctx.get().setPacketHandled(true); - } - } - } - - //-------------------------------------------------------------------------------------------------------------------- - // (GUI) Container synchronization - //-------------------------------------------------------------------------------------------------------------------- - - public interface INetworkSynchronisableContainer - { - void onServerPacketReceived(int windowId, CompoundTag nbt); - void onClientPacketReceived(int windowId, Player player, CompoundTag nbt); - } - - public static class PacketContainerSyncClientToServer - { - int id = -1; - CompoundTag nbt = null; - - public static void sendToServer(int windowId, CompoundTag nbt) - { if(nbt!=null) DEFAULT_CHANNEL.sendToServer(new PacketContainerSyncClientToServer(windowId, nbt)); } - - public static void sendToServer(AbstractContainerMenu container, CompoundTag nbt) - { if(nbt!=null) DEFAULT_CHANNEL.sendToServer(new PacketContainerSyncClientToServer(container.containerId, nbt)); } - - public PacketContainerSyncClientToServer() - {} - - public PacketContainerSyncClientToServer(int id, CompoundTag nbt) - { this.nbt = nbt; this.id = id; } - - public static PacketContainerSyncClientToServer parse(final FriendlyByteBuf buf) - { return new PacketContainerSyncClientToServer(buf.readInt(), buf.readNbt()); } - - public static void compose(final PacketContainerSyncClientToServer pkt, final FriendlyByteBuf buf) - { buf.writeInt(pkt.id); buf.writeNbt(pkt.nbt); } - - public static class Handler - { - public static void handle(final PacketContainerSyncClientToServer pkt, final Supplier ctx) - { - ctx.get().enqueueWork(() -> { - Player player = ctx.get().getSender(); - if((player==null) || !(player.containerMenu instanceof INetworkSynchronisableContainer)) return; - if(player.containerMenu.containerId != pkt.id) return; - ((INetworkSynchronisableContainer)player.containerMenu).onClientPacketReceived(pkt.id, player,pkt.nbt); - }); - ctx.get().setPacketHandled(true); - } - } - } - - public static class PacketContainerSyncServerToClient - { - int id = -1; - CompoundTag nbt = null; - - public static void sendToPlayer(Player player, int windowId, CompoundTag nbt) - { - if((!(player instanceof ServerPlayer)) || (player instanceof FakePlayer) || (nbt==null)) return; - DEFAULT_CHANNEL.sendTo(new PacketContainerSyncServerToClient(windowId, nbt), ((ServerPlayer)player).connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - public static void sendToPlayer(Player player, AbstractContainerMenu container, CompoundTag nbt) - { - if((!(player instanceof ServerPlayer)) || (player instanceof FakePlayer) || (nbt==null)) return; - DEFAULT_CHANNEL.sendTo(new PacketContainerSyncServerToClient(container.containerId, nbt), ((ServerPlayer)player).connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - public static - void sendToListeners(Level world, C container, CompoundTag nbt) - { - for(Player player: world.players()) { - if(player.containerMenu.containerId != container.containerId) continue; - sendToPlayer(player, container.containerId, nbt); - } - } - - public PacketContainerSyncServerToClient() - {} - - public PacketContainerSyncServerToClient(int id, CompoundTag nbt) - { this.nbt=nbt; this.id=id; } - - public static PacketContainerSyncServerToClient parse(final FriendlyByteBuf buf) - { return new PacketContainerSyncServerToClient(buf.readInt(), buf.readNbt()); } - - public static void compose(final PacketContainerSyncServerToClient pkt, final FriendlyByteBuf buf) - { buf.writeInt(pkt.id); buf.writeNbt(pkt.nbt); } - - public static class Handler - { - public static void handle(final PacketContainerSyncServerToClient pkt, final Supplier ctx) - { - ctx.get().enqueueWork(() -> { - Player player = SidedProxy.getPlayerClientSide(); - if((player==null) || !(player.containerMenu instanceof INetworkSynchronisableContainer)) return; - if(player.containerMenu.containerId != pkt.id) return; - ((INetworkSynchronisableContainer)player.containerMenu).onServerPacketReceived(pkt.id,pkt.nbt); - }); - ctx.get().setPacketHandled(true); - } - } - } - - //-------------------------------------------------------------------------------------------------------------------- - // World notifications - //-------------------------------------------------------------------------------------------------------------------- - - public static class PacketNbtNotifyClientToServer - { - public static final Map> handlers = new HashMap<>(); - final CompoundTag nbt; - - public static void sendToServer(CompoundTag nbt) - { if(nbt!=null) DEFAULT_CHANNEL.sendToServer(new PacketNbtNotifyClientToServer(nbt)); } - - public PacketNbtNotifyClientToServer(CompoundTag nbt) - { this.nbt = nbt; } - - public static PacketNbtNotifyClientToServer parse(final FriendlyByteBuf buf) - { return new PacketNbtNotifyClientToServer(buf.readNbt()); } - - public static void compose(final PacketNbtNotifyClientToServer pkt, final FriendlyByteBuf buf) - { buf.writeNbt(pkt.nbt); } - - public static class Handler - { - public static void handle(final PacketNbtNotifyClientToServer pkt, final Supplier ctx) - { - ctx.get().enqueueWork(() -> { - final ServerPlayer player = ctx.get().getSender(); - if(player==null) return; - final String hnd = pkt.nbt.getString("hnd"); - if(hnd.isEmpty()) return; - if(handlers.containsKey(hnd)) handlers.get(hnd).accept(player, pkt.nbt); - }); - ctx.get().setPacketHandled(true); - } - } - } - - public static class PacketNbtNotifyServerToClient - { - public static final Map> handlers = new HashMap<>(); - final CompoundTag nbt; - - public static void sendToPlayer(Player player, CompoundTag nbt) - { - if((!(player instanceof ServerPlayer)) || (player instanceof FakePlayer) || (nbt==null)) return; - DEFAULT_CHANNEL.sendTo(new PacketNbtNotifyServerToClient(nbt), ((ServerPlayer)player).connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - public static void sendToPlayers(Level world, CompoundTag nbt) - { for(Player player: world.players()) sendToPlayer(player, nbt); } - - public PacketNbtNotifyServerToClient(CompoundTag nbt) - { this.nbt = nbt; } - - public static PacketNbtNotifyServerToClient parse(final FriendlyByteBuf buf) - { return new PacketNbtNotifyServerToClient(buf.readNbt()); } - - public static void compose(final PacketNbtNotifyServerToClient pkt, final FriendlyByteBuf buf) - { buf.writeNbt(pkt.nbt); } - - public static class Handler - { - public static void handle(final PacketNbtNotifyServerToClient pkt, final Supplier ctx) - { - ctx.get().enqueueWork(() -> { - final String hnd = pkt.nbt.getString("hnd"); - if(hnd.isEmpty()) return; - if(handlers.containsKey(hnd)) handlers.get(hnd).accept(pkt.nbt); - }); - ctx.get().setPacketHandled(true); - } - } - } - - //-------------------------------------------------------------------------------------------------------------------- - // Main window GUI text message - //-------------------------------------------------------------------------------------------------------------------- - - public static class OverlayTextMessage - { - public static final int DISPLAY_TIME_MS = 3000; - private static BiConsumer handler_ = null; - private final Component data_; - private int delay_ = DISPLAY_TIME_MS; - private Component data() { return data_; } - private int delay() { return delay_; } - - public static void setHandler(BiConsumer handler) - { if(handler_==null) handler_ = handler; } - - public static void sendToPlayer(Player player, Component message, int delay) - { - if((!(player instanceof ServerPlayer)) || (player instanceof FakePlayer) || Auxiliaries.isEmpty(message)) return; - DEFAULT_CHANNEL.sendTo(new OverlayTextMessage(message, delay), ((ServerPlayer)player).connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - public OverlayTextMessage() - { data_ = Component.translatable("[unset]"); } - - public OverlayTextMessage(final Component tct, int delay) - { data_ = tct.copy(); delay_ = delay; } - - public static OverlayTextMessage parse(final FriendlyByteBuf buf) - { - try { - return new OverlayTextMessage(buf.readComponent(), DISPLAY_TIME_MS); - } catch(Throwable e) { - return new OverlayTextMessage(Component.translatable("[incorrect translation]"), DISPLAY_TIME_MS); - } - } - - public static void compose(final OverlayTextMessage pkt, final FriendlyByteBuf buf) - { - try { - buf.writeComponent(pkt.data()); - } catch(Throwable e) { - Auxiliaries.logger().error("OverlayTextMessage.toBytes() failed: " + e); - } - } - - public static class Handler - { - public static void handle(final OverlayTextMessage pkt, final Supplier ctx) - { - if(handler_ != null) ctx.get().enqueueWork(() -> handler_.accept(pkt.data(), pkt.delay())); - ctx.get().setPacketHandled(true); - } - } - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/OptionalRecipeCondition.java b/src/main/java/wile/engineersdecor/libmc/OptionalRecipeCondition.java deleted file mode 100644 index f54abad..0000000 --- a/src/main/java/wile/engineersdecor/libmc/OptionalRecipeCondition.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * @file OptionalRecipeCondition.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Recipe condition to enable opt'ing out JSON based recipes. - */ -package wile.engineersdecor.libmc; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import net.minecraftforge.common.crafting.conditions.ICondition; -import net.minecraftforge.common.crafting.conditions.IConditionSerializer; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.IForgeRegistry; -import org.slf4j.Logger; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; - - -public class OptionalRecipeCondition implements ICondition -{ - private static ResourceLocation NAME; - - private final List all_required; - private final List any_missing; - private final List all_required_tags; - private final List any_missing_tags; - private final @Nullable ResourceLocation result; - private final boolean result_is_tag; - private final boolean experimental; - - private static boolean with_experimental = false; - private static boolean without_recipes = false; - private static Predicate block_optouts = (block)->false; - private static Predicate item_optouts = (item)->false; - - public static void init(String modid, Logger logger) - { - NAME = new ResourceLocation(modid, "optional"); - } - - public static void on_config(boolean enable_experimental, boolean disable_all_recipes, - Predicate block_optout_provider, - Predicate item_optout_provider) - { - with_experimental = enable_experimental; - without_recipes = disable_all_recipes; - block_optouts = block_optout_provider; - item_optouts = item_optout_provider; - } - - public OptionalRecipeCondition(ResourceLocation result, List required, List missing, List required_tags, List missing_tags, boolean isexperimental, boolean result_is_tag) - { - all_required = required; - any_missing = missing; - all_required_tags = required_tags; - any_missing_tags = missing_tags; - this.result = result; - this.result_is_tag = result_is_tag; - experimental=isexperimental; - } - - @Override - public ResourceLocation getID() - { return NAME; } - - @Override - public String toString() - { - StringBuilder sb = new StringBuilder(); - sb.append("Optional recipe, all-required: ["); - for(ResourceLocation e:all_required) sb.append(e.toString()).append(","); - for(ResourceLocation e:all_required_tags) sb.append("#").append(e.toString()).append(","); - sb.delete(sb.length()-1, sb.length()).append("], any-missing: ["); - for(ResourceLocation e:any_missing) sb.append(e.toString()).append(","); - for(ResourceLocation e:any_missing_tags) sb.append("#").append(e.toString()).append(","); - sb.delete(sb.length()-1, sb.length()).append("]"); - if(experimental) sb.append(" EXPERIMENTAL"); - return sb.toString(); - } - - @Override - public boolean test(IContext context) - { - if(without_recipes) return false; - if((experimental) && (!with_experimental)) return false; - final IForgeRegistry item_registry = ForgeRegistries.ITEMS; - //final Collection item_tags = SerializationTags.getInstance().getOrEmpty(Registry.ITEM_REGISTRY).getAvailableTags(); - if(result != null) { - boolean item_registered = item_registry.containsKey(result); - if(!item_registered) return false; // required result not registered - if(item_optouts.test(item_registry.getValue(result))) return false; - if(ForgeRegistries.BLOCKS.containsKey(result) && block_optouts.test(ForgeRegistries.BLOCKS.getValue(result))) return false; - } - if(!all_required.isEmpty()) { - for(ResourceLocation rl:all_required) { - if(!item_registry.containsKey(rl)) return false; - } - } - if(!all_required_tags.isEmpty()) { - for(ResourceLocation rl:all_required_tags) { - if(item_registry.tags().getTagNames().noneMatch(tk->tk.location().equals(rl))) return false; // if(!item_tags.contains(rl)) return false; - } - } - if(!any_missing.isEmpty()) { - for(ResourceLocation rl:any_missing) { - if(!item_registry.containsKey(rl)) return true; - } - return false; - } - if(!any_missing_tags.isEmpty()) { - for(ResourceLocation rl:any_missing_tags) { - if(item_registry.tags().getTagNames().noneMatch(tk->tk.location().equals(rl))) return true; // if(!item_tags.contains(rl)) return true; - } - return false; - } - return true; - } - - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public ResourceLocation getID() - { return OptionalRecipeCondition.NAME; } - - @Override - public void write(JsonObject json, OptionalRecipeCondition condition) - { - JsonArray required = new JsonArray(); - JsonArray missing = new JsonArray(); - for(ResourceLocation e:condition.all_required) required.add(e.toString()); - for(ResourceLocation e:condition.any_missing) missing.add(e.toString()); - json.add("required", required); - json.add("missing", missing); - if(condition.result != null) { - json.addProperty("result", (condition.result_is_tag ? "#" : "") + condition.result); - } - } - - @Override - public OptionalRecipeCondition read(JsonObject json) - { - List required = new ArrayList<>(); - List missing = new ArrayList<>(); - List required_tags = new ArrayList<>(); - List missing_tags = new ArrayList<>(); - ResourceLocation result = null; - boolean experimental = false; - boolean result_is_tag = false; - if(json.has("result")) { - String s = json.get("result").getAsString(); - if(s.startsWith("#")) { - result = new ResourceLocation(s.substring(1)); - result_is_tag = true; - } else { - result = new ResourceLocation(s); - } - } - if(json.has("required")) { - for(JsonElement e:GsonHelper.getAsJsonArray(json, "required")) { - String s = e.getAsString(); - if(s.startsWith("#")) { - required_tags.add(new ResourceLocation(s.substring(1))); - } else { - required.add(new ResourceLocation(s)); - } - } - } - if(json.has("missing")) { - for(JsonElement e:GsonHelper.getAsJsonArray(json, "missing")) { - String s = e.getAsString(); - if(s.startsWith("#")) { - missing_tags.add(new ResourceLocation(s.substring(1))); - } else { - missing.add(new ResourceLocation(s)); - } - } - } - if(json.has("experimental")) experimental = json.get("experimental").getAsBoolean(); - return new OptionalRecipeCondition(result, required, missing, required_tags, missing_tags, experimental, result_is_tag); - } - } -} diff --git a/src/main/java/wile/engineersdecor/libmc/Overlay.java b/src/main/java/wile/engineersdecor/libmc/Overlay.java deleted file mode 100644 index 308fe20..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Overlay.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * @file Overlay.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Renders status messages in one line. - */ -package wile.engineersdecor.libmc; - -import com.mojang.blaze3d.platform.Window; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.util.Tuple; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; - -import javax.annotation.Nullable; -import java.util.Optional; - - -public class Overlay -{ - public static void show(Player player, final Component message) - { Networking.OverlayTextMessage.sendToPlayer(player, message, 3000); } - - public static void show(Player player, final Component message, int delay) - { Networking.OverlayTextMessage.sendToPlayer(player, message, delay); } - - public static void show(BlockState state, BlockPos pos) - { show(state, pos, 100); } - - public static void show(BlockState state, BlockPos pos, int displayTimeoutMs) - { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, ()->(()->TextOverlayGui.show(state, pos, displayTimeoutMs))); } // Only called when client side - - // ----------------------------------------------------------------------------- - // Client side handler - // ----------------------------------------------------------------------------- - - @OnlyIn(Dist.CLIENT) - public static class TextOverlayGui extends Screen - { - public static final TextOverlayGui INSTANCE = new TextOverlayGui(); - private static final Component EMPTY_TEXT = Component.literal(""); - private static final BlockState EMPTY_STATE = null; - private static double overlay_y_ = 0.75; - private static int text_color_ = 0x00ffaa00; - private static int border_color_ = 0xaa333333; - private static int background_color1_ = 0xaa333333; - private static int background_color2_ = 0xaa444444; - private static long text_deadline_ = 0; - private static Component text_ = EMPTY_TEXT; - private static long state_deadline_ = 0; - private static @Nullable BlockState state_ = EMPTY_STATE; - private static BlockPos pos_ = BlockPos.ZERO; - - public static void on_config(double overlay_y) - { on_config(overlay_y, 0x00ffaa00, 0xaa333333, 0xaa333333, 0xaa444444); } - - public static void on_config(double overlay_y, int text_color, int border_color, int background_color1, int background_color2) - { - overlay_y_ = overlay_y; - text_color_ = text_color; - border_color_ = border_color; - background_color1_ = background_color1; - background_color2_ = background_color2; - } - - public static synchronized Component text() - { return text_; } - - public static synchronized long deadline() - { return text_deadline_; } - - public static synchronized void hide() - { text_deadline_ = 0; text_ = EMPTY_TEXT; } - - public static synchronized void show(Component s, int displayTimeoutMs) - { text_ = (s==null)?(EMPTY_TEXT):(s.copy()); text_deadline_ = System.currentTimeMillis() + displayTimeoutMs; } - - public static synchronized void show(String s, int displayTimeoutMs) - { text_ = ((s==null)||(s.isEmpty()))?(EMPTY_TEXT):(Component.literal(s)); text_deadline_ = System.currentTimeMillis() + displayTimeoutMs; } - - public static synchronized void show(BlockState state, BlockPos pos, int displayTimeoutMs) - { pos_ = new BlockPos(pos); state_ = state; state_deadline_ = System.currentTimeMillis() + displayTimeoutMs; } - - private static synchronized Optional> state_pos() - { return ((state_deadline_ < System.currentTimeMillis()) || (state_==EMPTY_STATE)) ? Optional.empty() : Optional.of(new Tuple<>(state_, pos_)); } - - TextOverlayGui() - { super(Component.literal("")); } - - public void onRenderGui(final com.mojang.blaze3d.vertex.PoseStack mxs) - { - if(deadline() < System.currentTimeMillis()) return; - if(text()==EMPTY_TEXT) return; - String txt = text().getString(); - if(txt.isEmpty()) return; - final net.minecraft.client.Minecraft mc = net.minecraft.client.Minecraft.getInstance(); - final Window win = mc.getWindow(); - final Font fr = mc.font; - final boolean was_unicode = fr.isBidirectional(); - final int cx = win.getGuiScaledWidth() / 2; - final int cy = (int)(win.getGuiScaledHeight() * overlay_y_); - final int w = fr.width(txt); - final int h = fr.lineHeight; - fillGradient(mxs, cx-(w/2)-3, cy-2, cx+(w/2)+2, cy+h+2, 0xaa333333, 0xaa444444); - hLine(mxs, cx-(w/2)-3, cx+(w/2)+2, cy-2, 0xaa333333); - hLine(mxs, cx-(w/2)-3, cx+(w/2)+2, cy+h+2, 0xaa333333); - vLine(mxs, cx-(w/2)-3, cy-2, cy+h+2, 0xaa333333); - vLine(mxs, cx+(w/2)+2, cy-2, cy+h+2, 0xaa333333); - drawCenteredString(mxs, fr, text(), cx , cy+1, 0x00ffaa00); - } - - @SuppressWarnings("deprecation") - public void onRenderWorldOverlay(final com.mojang.blaze3d.vertex.PoseStack mxs, final double partialTick) - { - final Optional> sp = state_pos(); - if(sp.isEmpty()) return; - final ClientLevel world = Minecraft.getInstance().level; - final LocalPlayer player = Minecraft.getInstance().player; - if((player==null) || (world==null)) return; - final BlockState state = sp.get().getA(); - final BlockPos pos = sp.get().getB(); - final int light = (world.hasChunkAt(pos)) ? LightTexture.pack(world.getBrightness(LightLayer.BLOCK, pos), world.getBrightness(LightLayer.SKY, pos)) : LightTexture.pack(15, 15); - final MultiBufferSource buffer = Minecraft.getInstance().renderBuffers().bufferSource(); - final double px = Mth.lerp(partialTick, player.xo, player.getX()); - final double py = Mth.lerp(partialTick, player.yo, player.getY()); - final double pz = Mth.lerp(partialTick, player.zo, player.getZ()); - mxs.pushPose(); - mxs.translate((pos.getX()-px), (pos.getY()-py-player.getEyeHeight()), (pos.getZ()-pz)); - Minecraft.getInstance().getBlockRenderer().renderSingleBlock(state, mxs, buffer, light, OverlayTexture.NO_OVERLAY); - mxs.popPose(); - } - - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/Registries.java b/src/main/java/wile/engineersdecor/libmc/Registries.java deleted file mode 100644 index 54d0b6c..0000000 --- a/src/main/java/wile/engineersdecor/libmc/Registries.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * @file Registries.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Common game registry handling. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraftforge.registries.DeferredRegister; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegistryObject; - -import javax.annotation.Nonnull; -import java.util.*; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -public class Registries -{ - private static String modid = null; - private static String creative_tab_icon = ""; - private static CreativeModeTab creative_tab = null; - private static final Map> registered_block_tag_keys = new HashMap<>(); - private static final Map> registered_item_tag_keys = new HashMap<>(); - - private static final Map> registered_blocks = new HashMap<>(); - private static final Map> registered_items = new HashMap<>(); - private static final Map>> registered_block_entity_types = new HashMap<>(); - private static final Map>> registered_entity_types = new HashMap<>(); - private static final Map>> registered_menu_types = new HashMap<>(); - private static final Map>> recipe_serializers = new HashMap<>(); - - private static DeferredRegister BLOCKS; - private static DeferredRegister ITEMS; - private static DeferredRegister> BLOCK_ENTITIES; - private static DeferredRegister> MENUS; - private static DeferredRegister> ENTITIES; - private static DeferredRegister> RECIPE_SERIALIZERS; - private static List> MOD_REGISTRIES; - - public static void init(String mod_id, String creative_tab_icon_item_name, Consumer> registrar) - { - modid = mod_id; - creative_tab_icon = creative_tab_icon_item_name; - BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, modid); - ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, modid); - BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, modid); - MENUS = DeferredRegister.create(ForgeRegistries.MENU_TYPES, modid); - ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, modid); - RECIPE_SERIALIZERS = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, modid); - List.of(BLOCKS, ITEMS, BLOCK_ENTITIES, MENUS, ENTITIES, RECIPE_SERIALIZERS).forEach(registrar); - } - - - public static CreativeModeTab getCreativeModeTab() - { - if(creative_tab==null) { - creative_tab = (new CreativeModeTab("tab" + modid) { - public ItemStack makeIcon() { return new ItemStack(getItem(creative_tab_icon)); } - }); - } - return creative_tab; - } - - // ------------------------------------------------------------------------------------------------------------- - - public static Block getBlock(String block_name) - { return registered_blocks.get(block_name).get(); } - - public static Item getItem(String name) - { return registered_items.get(name).get(); } - - public static EntityType getEntityType(String name) - { return registered_entity_types.get(name).get(); } - - public static BlockEntityType getBlockEntityType(String block_name) - { return registered_block_entity_types.get(block_name).get(); } - - public static MenuType getMenuType(String name) - { return registered_menu_types.get(name).get(); } - - public static RecipeSerializer getRecipeSerializer(String name) - { return recipe_serializers.get(name).get(); } - - public static BlockEntityType getBlockEntityTypeOfBlock(String block_name) - { return getBlockEntityType("tet_"+block_name); } - - public static BlockEntityType getBlockEntityTypeOfBlock(Block block) - { return getBlockEntityTypeOfBlock(ForgeRegistries.BLOCKS.getKey(block).getPath()); } - - public static MenuType getMenuTypeOfBlock(String name) - { return getMenuType("ct_"+name); } - - public static MenuType getMenuTypeOfBlock(Block block) - { return getMenuTypeOfBlock(ForgeRegistries.BLOCKS.getKey(block).getPath()); } - - public static TagKey getBlockTagKey(String name) - { return registered_block_tag_keys.get(name); } - - public static TagKey getItemTagKey(String name) - { return registered_item_tag_keys.get(name); } - - // ------------------------------------------------------------------------------------------------------------- - - @Nonnull - public static List getRegisteredBlocks() - { return Collections.unmodifiableList(registered_blocks.values().stream().map(RegistryObject::get).toList()); } - - @Nonnull - public static List getRegisteredItems() - { return Collections.unmodifiableList(registered_items.values().stream().map(RegistryObject::get).toList()); } - - @Nonnull - public static List> getRegisteredBlockEntityTypes() - { return Collections.unmodifiableList(registered_block_entity_types.values().stream().map(RegistryObject::get).toList()); } - - @Nonnull - public static List> getRegisteredEntityTypes() - { return Collections.unmodifiableList(registered_entity_types.values().stream().map(RegistryObject::get).toList()); } - - // ------------------------------------------------------------------------------------------------------------- - - public static void addItem(String registry_name, Supplier supplier) - { registered_items.put(registry_name, ITEMS.register(registry_name, supplier)); } - - public static void addBlock(String registry_name, Supplier block_supplier) - { - registered_blocks.put(registry_name, BLOCKS.register(registry_name, block_supplier)); - registered_items.put(registry_name, ITEMS.register(registry_name, ()->new BlockItem(registered_blocks.get(registry_name).get(), (new Item.Properties()).tab(getCreativeModeTab())))); - } - - public static void addBlock(String registry_name, Supplier block_supplier, Supplier item_supplier) - { - registered_blocks.put(registry_name, BLOCKS.register(registry_name, block_supplier)); - registered_items.put(registry_name, ITEMS.register(registry_name, item_supplier)); - } - - public static void addBlockEntityType(String registry_name, BlockEntityType.BlockEntitySupplier ctor, String... block_names) - { - registered_block_entity_types.put(registry_name, BLOCK_ENTITIES.register(registry_name, ()->{ - final Block[] blocks = Arrays.stream(block_names).map(s->{ - Block b = BLOCKS.getEntries().stream().filter((ro)->ro.getId().getPath().equals(s)).findFirst().map(RegistryObject::get).orElse(null); - if(b==null) Auxiliaries.logError("registered_blocks does not encompass '" + s + "'"); - return b; - }).filter(Objects::nonNull).collect(Collectors.toList()).toArray(new Block[]{}); - return BlockEntityType.Builder.of(ctor, blocks).build(null); - })); - } - - public static > void addEntityType(String registry_name, Supplier> supplier) - { registered_entity_types.put(registry_name, ENTITIES.register(registry_name, supplier)); } - - public static > void addMenuType(String registry_name, MenuType.MenuSupplier supplier) - { registered_menu_types.put(registry_name, MENUS.register(registry_name, ()->new MenuType<>(supplier))); } - - public static void addRecipeSerializer(String registry_name, Supplier> serializer_supplier) - { recipe_serializers.put(registry_name, RECIPE_SERIALIZERS.register(registry_name, serializer_supplier)); } - - public static void addOptionalBlockTag(String tag_name, ResourceLocation... default_blocks) - { - final Set> default_suppliers = new HashSet<>(); - for(ResourceLocation rl: default_blocks) default_suppliers.add(()->ForgeRegistries.BLOCKS.getValue(rl)); - final TagKey key = ForgeRegistries.BLOCKS.tags().createOptionalTagKey(new ResourceLocation(modid, tag_name), default_suppliers); - registered_block_tag_keys.put(tag_name, key); - } - - public static void addOptionaItemTag(String tag_name, ResourceLocation... default_items) - { - final Set> default_suppliers = new HashSet<>(); - for(ResourceLocation rl: default_items) default_suppliers.add(()->ForgeRegistries.ITEMS.getValue(rl)); - final TagKey key = ForgeRegistries.ITEMS.tags().createOptionalTagKey(new ResourceLocation(modid, tag_name), default_suppliers); - registered_item_tag_keys.put(tag_name, key); - } - - // ------------------------------------------------------------------------------------------------------------- - - public static void addBlock(String registry_name, Supplier block_supplier, BiFunction item_builder) - { - addBlock(registry_name, block_supplier, ()->item_builder.apply(registered_blocks.get(registry_name).get(), (new Item.Properties()).tab(getCreativeModeTab()))); - } - - public static void addBlock(String registry_name, Supplier block_supplier, BlockEntityType.BlockEntitySupplier block_entity_ctor) - { - addBlock(registry_name, block_supplier); - addBlockEntityType("tet_"+registry_name, block_entity_ctor, registry_name); - } - - public static void addBlock(String registry_name, Supplier block_supplier, BiFunction item_builder, BlockEntityType.BlockEntitySupplier block_entity_ctor) - { - addBlock(registry_name, block_supplier, item_builder); - addBlockEntityType("tet_"+registry_name, block_entity_ctor, registry_name); - } - - public static void addBlock(String registry_name, Supplier block_supplier, BiFunction item_builder, BlockEntityType.BlockEntitySupplier block_entity_ctor, MenuType.MenuSupplier menu_type_supplier) - { - addBlock(registry_name, block_supplier, item_builder); - addBlockEntityType("tet_"+registry_name, block_entity_ctor, registry_name); - addMenuType("ct_"+registry_name, menu_type_supplier); - } - - public static void addBlock(String registry_name, Supplier block_supplier, BlockEntityType.BlockEntitySupplier block_entity_ctor, MenuType.MenuSupplier menu_type_supplier) - { - addBlock(registry_name, block_supplier, block_entity_ctor); - addMenuType("ct_"+registry_name, menu_type_supplier); - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/RfEnergy.java b/src/main/java/wile/engineersdecor/libmc/RfEnergy.java deleted file mode 100644 index 4b3962c..0000000 --- a/src/main/java/wile/engineersdecor/libmc/RfEnergy.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * @file RfEnergy.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * General RF/FE energy handling functionality. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.energy.IEnergyStorage; - -import javax.annotation.Nullable; - -public class RfEnergy -{ - public static int feed(Level world, BlockPos pos, @Nullable Direction side, int rf_energy) - { - final BlockEntity te = world.getBlockEntity(pos); - if(te == null) return 0; - final IEnergyStorage es = te.getCapability(ForgeCapabilities.ENERGY, side).orElse(null); - if(es == null) return 0; - return es.receiveEnergy(rf_energy, false); - } - - public static class Battery implements IEnergyStorage - { - protected int capacity_; - protected int charge_rate_; - protected int discharge_rate_; - protected int energy_; - - public Battery(int capacity) - { this(capacity, capacity); } - - public Battery(int capacity, int transfer_rate) - { this(capacity, transfer_rate, transfer_rate, 0); } - - public Battery(int capacity, int charge_rate, int discharge_rate) - { this(capacity, charge_rate, discharge_rate, 0); } - - public Battery(int capacity, int charge_rate, int discharge_rate, int energy) - { - capacity_ = Math.max(capacity, 1); - charge_rate_ = Mth.clamp(charge_rate, 0, capacity_); - discharge_rate_ = Mth.clamp(discharge_rate, 0, capacity_); - energy_ = Mth.clamp(energy, 0, capacity_); - } - - // --------------------------------------------------------------------------------------------------- - - public Battery setMaxEnergyStored(int capacity) - { capacity_ = Math.max(capacity, 1); return this; } - - public Battery setEnergyStored(int energy) - { energy_ = Mth.clamp(energy, 0, capacity_); return this; } - - public Battery setChargeRate(int in_rate) - { charge_rate_ = Mth.clamp(in_rate, 0, capacity_); return this; } - - public Battery setDischargeRate(int out_rate) - { discharge_rate_ = Mth.clamp(out_rate, 0, capacity_); return this; } - - public int getChargeRate() - { return charge_rate_; } - - public int getDischargeRate() - { return discharge_rate_; } - - public boolean isEmpty() - { return energy_ <= 0; } - - public boolean isFull() - { return energy_ >= capacity_; } - - public int getSOC() - { return (int)Mth.clamp((100.0 * energy_ / capacity_ + .5), 0, 100); } - - public int getComparatorOutput() - { return (int)Mth.clamp((15.0 * energy_ / capacity_ + .2), 0, 15); } - - public boolean draw(int energy) - { - if(energy_ < energy) return false; - energy_ -= energy; - return true; - } - - public boolean feed(int energy) - { - energy_ = Math.min(energy_+energy, capacity_); - return energy_ >= capacity_; - } - - public Battery clear() - { energy_ = 0; return this; } - - public Battery load(CompoundTag nbt, String key) - { setEnergyStored(nbt.getInt(key)); return this; } - - public Battery load(CompoundTag nbt) - { return load(nbt, "Energy"); } - - public CompoundTag save(CompoundTag nbt, String key) - { nbt.putInt(key, energy_); return nbt; } - - public CompoundTag save(CompoundTag nbt) - { return save(nbt, "Energy"); } - - public LazyOptional createEnergyHandler() - { return LazyOptional.of(() -> this); } - - // IEnergyStorage ------------------------------------------------------------------------------------ - - @Override - public int receiveEnergy(int feed_energy, boolean simulate) - { - if(!canReceive()) return 0; - int e = Math.min(Math.min(charge_rate_, feed_energy), capacity_-energy_); - if(!simulate) energy_ += e; - return e; - } - - @Override - public int extractEnergy(int draw_energy, boolean simulate) - { - if(!canExtract()) return 0; - int e = Math.min(Math.min(discharge_rate_, draw_energy), energy_); - if(!simulate) energy_ -= e; - return e; - } - - @Override - public int getEnergyStored() - { return energy_; } - - @Override - public int getMaxEnergyStored() - { return capacity_; } - - @Override - public boolean canExtract() - { return discharge_rate_ > 0; } - - @Override - public boolean canReceive() - { return charge_rate_ > 0; } - - } -} diff --git a/src/main/java/wile/engineersdecor/libmc/RsSignals.java b/src/main/java/wile/engineersdecor/libmc/RsSignals.java deleted file mode 100644 index 81fb382..0000000 --- a/src/main/java/wile/engineersdecor/libmc/RsSignals.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * @file RsSignals.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * General redstone signal related functionality. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Container; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.state.BlockState; - -import javax.annotation.Nullable; - -public class RsSignals -{ - - public static boolean hasSignalConnector(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction realSide) - { - return state.isSignalSource(); - } - - public static int fromContainer(@Nullable Container container) - { - if(container == null) return 0; - final double max = container.getMaxStackSize(); - if(max <= 0) return 0; - boolean nonempty = false; - double fill_level = 0; - for(int i=0; i isCtrlDown() - { return proxy.isCtrlDown(); } - - public static Optional isShiftDown() - { return proxy.isShiftDown(); } - - public static Optional getClipboard() - { return proxy.getClipboard(); } - - public static boolean setClipboard(String text) - { return proxy.setClipboard(text); } - - // -------------------------------------------------------------------------------------------------------- - - private static final ISidedProxy proxy = DistExecutor.unsafeRunForDist(()->ClientProxy::new, ()->ServerProxy::new); - - private interface ISidedProxy - { - default @Nullable Player getPlayerClientSide() { return null; } - default @Nullable Level getWorldClientSide() { return null; } - default @Nullable Minecraft mc() { return null; } - default Optional isCtrlDown() { return Optional.empty(); } - default Optional isShiftDown() { return Optional.empty(); } - default Optional getClipboard() { return Optional.empty(); } - default boolean setClipboard(String text) { return false; } - } - - private static final class ClientProxy implements ISidedProxy - { - public @Nullable Player getPlayerClientSide() { return Minecraft.getInstance().player; } - public @Nullable Level getWorldClientSide() { return Minecraft.getInstance().level; } - public @Nullable Minecraft mc() { return Minecraft.getInstance(); } - public Optional isCtrlDown() { return Optional.of(Auxiliaries.isCtrlDown()); } - public Optional isShiftDown() { return Optional.of(Auxiliaries.isShiftDown()); } - public Optional getClipboard() { return (mc()==null) ? Optional.empty() : Optional.of(net.minecraft.client.gui.font.TextFieldHelper.getClipboardContents(mc())); } - public boolean setClipboard(String text) { if(mc()==null) {return false;} net.minecraft.client.gui.font.TextFieldHelper.setClipboardContents(Minecraft.getInstance(), text); return true; } - } - - private static final class ServerProxy implements ISidedProxy - { - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/SlabSliceBlock.java b/src/main/java/wile/engineersdecor/libmc/SlabSliceBlock.java deleted file mode 100644 index ce63004..0000000 --- a/src/main/java/wile/engineersdecor/libmc/SlabSliceBlock.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * @file SlabSliceBlock.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Half slab ("slab slices") characteristics class. Actually - * it's now a quarter slab, but who cares. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class SlabSliceBlock extends StandardBlocks.WaterLoggable implements StandardBlocks.IStandardBlock -{ - public static final IntegerProperty PARTS = IntegerProperty.create("parts", 0, 14); - - protected static final VoxelShape[] AABBs = { - Shapes.create(new AABB(0, 0./16, 0, 1, 2./16, 1)), - Shapes.create(new AABB(0, 0./16, 0, 1, 4./16, 1)), - Shapes.create(new AABB(0, 0./16, 0, 1, 6./16, 1)), - Shapes.create(new AABB(0, 0./16, 0, 1, 8./16, 1)), - Shapes.create(new AABB(0, 0./16, 0, 1, 10./16, 1)), - Shapes.create(new AABB(0, 0./16, 0, 1, 12./16, 1)), - Shapes.create(new AABB(0, 0./16, 0, 1, 14./16, 1)), - Shapes.create(new AABB(0, 0./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0, 2./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0, 4./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0, 6./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0, 8./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0, 10./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0, 12./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0, 14./16, 0, 1, 16./16, 1)), - Shapes.create(new AABB(0,0,0,1,1,1)) // <- with 4bit fill - }; - - protected static final int[] num_slabs_contained_in_parts_ = { 1,2,3,4,5,6,7,8,7,6,5,4,3,2,1 ,0x1 }; // <- with 4bit fill - private static boolean with_pickup = false; - - public static void on_config(boolean direct_slab_pickup) - { with_pickup = direct_slab_pickup; } - - public SlabSliceBlock(long config, BlockBehaviour.Properties builder) - { super(config, builder); } - - protected boolean is_cube(BlockState state) - { return state.getValue(PARTS) == 0x07; } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag) - { - if(!Auxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true)) return; - if(with_pickup) Auxiliaries.Tooltip.addInformation("engineersdecor.tooltip.slabpickup", tooltip); - } - - @Override - public RenderTypeHint getRenderTypeHint() - { return (((config & StandardBlocks.CFG_TRANSLUCENT)!=0) ? (RenderTypeHint.TRANSLUCENT) : (RenderTypeHint.CUTOUT)); } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter source, BlockPos pos, CollisionContext selectionContext) - { return AABBs[state.getValue(PARTS) & 0xf]; } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return getShape(state, world, pos, selectionContext); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(PARTS); } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) - { - final BlockPos pos = context.getClickedPos(); - BlockState state = context.getLevel().getBlockState(pos); - if(state.getBlock() == this) { - int parts = state.getValue(PARTS); - if(parts == 7) return null; // -> is already a full block. - parts += (parts < 7) ? 1 : -1; - if(parts==7) state = state.setValue(WATERLOGGED, false); - return state.setValue(PARTS, parts); - } else { - final Direction face = context.getClickedFace(); - final BlockState placement_state = super.getStateForPlacement(context); // fluid state - if(face == Direction.UP) return placement_state.setValue(PARTS, 0); - if(face == Direction.DOWN) return placement_state.setValue(PARTS, 14); - if(!face.getAxis().isHorizontal()) return placement_state; - final boolean isupper = ((context.getClickLocation().y() - context.getClickedPos().getY()) > 0.5); - return placement_state.setValue(PARTS, isupper ? 14 : 0); - } - } - - @Override - @SuppressWarnings("deprecation") - public boolean canBeReplaced(BlockState state, BlockPlaceContext context) - { - if(context.getItemInHand().getItem() != this.asItem()) return false; - if(!context.replacingClickedOnBlock()) return true; - final Direction face = context.getClickedFace(); - final int parts = state.getValue(PARTS); - if(parts == 7) return false; - if((face == Direction.UP) && (parts < 7)) return true; - if((face == Direction.DOWN) && (parts > 7)) return true; - if(!face.getAxis().isHorizontal()) return false; - final boolean isupper = ((context.getClickLocation().y() - context.getClickedPos().getY()) > 0.5); - return isupper ? (parts==0) : (parts==1); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rot) - { return state; } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirrorIn) - { return state; } - - @Override - public boolean hasDynamicDropList() - { return true; } - - @Override - public List dropList(BlockState state, Level world, BlockEntity te, boolean explosion) - { return new ArrayList<>(Collections.singletonList(new ItemStack(this.asItem(), num_slabs_contained_in_parts_[state.getValue(PARTS) & 0xf]))); } - - @Override - @SuppressWarnings("deprecation") - public void attack(BlockState state, Level world, BlockPos pos, Player player) - { - if((world.isClientSide) || (!with_pickup)) return; - final ItemStack stack = player.getMainHandItem(); - if(stack.isEmpty() || (Block.byItem(stack.getItem()) != this)) return; - if(stack.getCount() >= stack.getMaxStackSize()) return; - Vec3 lv = player.getLookAngle(); - Direction facing = Direction.getNearest((float)lv.x, (float)lv.y, (float)lv.z); - if((facing != Direction.UP) && (facing != Direction.DOWN)) return; - if(state.getBlock() != this) return; - int parts = state.getValue(PARTS); - if((facing == Direction.DOWN) && (parts <= 7)) { - if(parts > 0) { - world.setBlock(pos, state.setValue(PARTS, parts-1), 3); - } else { - world.removeBlock(pos, false); - } - } else if((facing == Direction.UP) && (parts >= 7)) { - if(parts < 14) { - world.setBlock(pos, state.setValue(PARTS, parts + 1), 3); - } else { - world.removeBlock(pos, false); - } - } else { - return; - } - if(!player.isCreative()) { - stack.grow(1); - if(player.getInventory() != null) player.getInventory().setChanged(); - } - SoundType st = this.getSoundType(state, world, pos, null); - world.playSound(player, pos, st.getPlaceSound(), SoundSource.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch()); - } - - @Override - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) - { return (state.getValue(PARTS) != 14) && (super.placeLiquid(world, pos, state, fluidState)); } - - @Override - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) - { return (state.getValue(PARTS) != 14) && (super.canPlaceLiquid(world, pos, state, fluid)); } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/StandardBlocks.java b/src/main/java/wile/engineersdecor/libmc/StandardBlocks.java deleted file mode 100644 index 233a43c..0000000 --- a/src/main/java/wile/engineersdecor/libmc/StandardBlocks.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * @file StandardBlocks.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Common functionality class for decor blocks. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.PushReaction; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.BooleanOp; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nullable; -import java.util.*; -import java.util.function.Function; -import java.util.function.Supplier; - - -@SuppressWarnings("deprecation") -public class StandardBlocks -{ - public static final long CFG_DEFAULT = 0x0000000000000000L; // no special config - public static final long CFG_CUTOUT = 0x0000000000000001L; // cutout rendering - public static final long CFG_MIPPED = 0x0000000000000002L; // cutout mipped rendering - public static final long CFG_TRANSLUCENT = 0x0000000000000004L; // indicates a block/pane is glass like (transparent, etc) - public static final long CFG_WATERLOGGABLE = 0x0000000000000008L; // The derived block extends IWaterLoggable - public static final long CFG_HORIZIONTAL = 0x0000000000000010L; // horizontal block, affects bounding box calculation at construction time and placement - public static final long CFG_LOOK_PLACEMENT = 0x0000000000000020L; // placed in direction the player is looking when placing. - public static final long CFG_FACING_PLACEMENT = 0x0000000000000040L; // placed on the facing the player has clicked. - public static final long CFG_OPPOSITE_PLACEMENT = 0x0000000000000080L; // placed placed in the opposite direction of the face the player clicked. - public static final long CFG_FLIP_PLACEMENT_IF_SAME = 0x0000000000000100L; // placement direction flipped if an instance of the same class was clicked - public static final long CFG_FLIP_PLACEMENT_SHIFTCLICK = 0x0000000000000200L; // placement direction flipped if player is sneaking - public static final long CFG_STRICT_CONNECTIONS = 0x0000000000000400L; // blocks do not connect to similar blocks around (implementation details may vary a bit) - public static final long CFG_AI_PASSABLE = 0x0000000000000800L; // does not block movement path for AI, needed for non-opaque blocks with collision shapes not thin at the bottom or one side. - - public interface IStandardBlock - { - default long config() - { return 0; } - - default boolean hasDynamicDropList() - { return false; } - - default List dropList(BlockState state, Level world, @Nullable BlockEntity te, boolean explosion) - { return Collections.singletonList((!world.isClientSide()) ? (new ItemStack(state.getBlock().asItem())) : (ItemStack.EMPTY)); } - - enum RenderTypeHint { SOLID,CUTOUT,CUTOUT_MIPPED,TRANSLUCENT,TRANSLUCENT_NO_CRUMBLING } - - default RenderTypeHint getRenderTypeHint() - { return getRenderTypeHint(config()); } - - default RenderTypeHint getRenderTypeHint(long config) - { - if((config & CFG_CUTOUT)!=0) return RenderTypeHint.CUTOUT; - if((config & CFG_MIPPED)!=0) return RenderTypeHint.CUTOUT_MIPPED; - if((config & CFG_TRANSLUCENT)!=0) return RenderTypeHint.TRANSLUCENT; - return RenderTypeHint.SOLID; - } - } - - public static class BaseBlock extends Block implements IStandardBlock, SimpleWaterloggedBlock - { - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - public final long config; - - public BaseBlock(long conf, BlockBehaviour.Properties properties) - { - super(properties); - config = conf; - BlockState state = getStateDefinition().any(); - if((conf & CFG_WATERLOGGABLE)!=0) state = state.setValue(WATERLOGGED, false); - registerDefaultState(state); - } - - @Override - public long config() - { return config; } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag) - { Auxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); } - - @Override - public RenderTypeHint getRenderTypeHint() - { return getRenderTypeHint(config); } - - @Override - @SuppressWarnings("deprecation") - public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, PathComputationType type) - { return ((config & CFG_AI_PASSABLE)!=0) && (super.isPathfindable(state, world, pos, type)); } - - public boolean hasSignalConnector(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) - { return state.isSignalSource(); } - - @Override - @SuppressWarnings("deprecation") - public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) - { - final boolean rsup = (state.hasBlockEntity() && (state.getBlock() != newState.getBlock())); - super.onRemove(state, world, pos, newState, isMoving); - if(rsup) world.updateNeighbourForOutputSignal(pos, this); - } - - @Override - @SuppressWarnings("deprecation") - public List getDrops(BlockState state, LootContext.Builder builder) - { - final ServerLevel world = builder.getLevel(); - final Float explosion_radius = builder.getOptionalParameter(LootContextParams.EXPLOSION_RADIUS); - final BlockEntity te = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); - if((!hasDynamicDropList()) || (world==null)) return super.getDrops(state, builder); - boolean is_explosion = (explosion_radius!=null) && (explosion_radius > 0); - return dropList(state, world, te, is_explosion); - } - - @Override - public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) - { return (((config & CFG_WATERLOGGABLE)==0) || (!state.getValue(WATERLOGGED))) && super.propagatesSkylightDown(state, reader, pos); } - - @Override - @SuppressWarnings("deprecation") - public FluidState getFluidState(BlockState state) - { return (((config & CFG_WATERLOGGABLE)!=0) && state.getValue(WATERLOGGED)) ? Fluids.WATER.getSource(false) : super.getFluidState(state); } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) - { - if(((config & CFG_WATERLOGGABLE)!=0) && (state.getValue(WATERLOGGED))) world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - return state; - } - - @Override // SimpleWaterloggedBlock - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) - { return ((config & CFG_WATERLOGGABLE)!=0) && SimpleWaterloggedBlock.super.canPlaceLiquid(world, pos, state, fluid); } - - @Override // SimpleWaterloggedBlock - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) - { return ((config & CFG_WATERLOGGABLE)!=0) && SimpleWaterloggedBlock.super.placeLiquid(world, pos, state, fluidState); } - - @Override // SimpleWaterloggedBlock - public ItemStack pickupBlock(LevelAccessor world, BlockPos pos, BlockState state) - { return ((config & CFG_WATERLOGGABLE)!=0) ? (SimpleWaterloggedBlock.super.pickupBlock(world, pos, state)) : (ItemStack.EMPTY); } - - @Override // SimpleWaterloggedBlock - public Optional getPickupSound() - { return ((config & CFG_WATERLOGGABLE)!=0) ? (SimpleWaterloggedBlock.super.getPickupSound()) : Optional.empty(); } - } - - public static class Cutout extends BaseBlock implements IStandardBlock - { - private final VoxelShape vshape; - - public Cutout(long conf, BlockBehaviour.Properties properties) - { this(conf, properties, Auxiliaries.getPixeledAABB(0, 0, 0, 16, 16,16 )); } - - public Cutout(long conf, BlockBehaviour.Properties properties, AABB aabb) - { this(conf, properties, Shapes.create(aabb)); } - - public Cutout(long conf, BlockBehaviour.Properties properties, AABB[] aabbs) - { this(conf, properties, Arrays.stream(aabbs).map(Shapes::create).reduce(Shapes.empty(), (shape, aabb)->Shapes.joinUnoptimized(shape, aabb, BooleanOp.OR))); } - - public Cutout(long conf, BlockBehaviour.Properties properties, VoxelShape voxel_shape) - { super(conf, properties); vshape = voxel_shape; } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState state, BlockGetter source, BlockPos pos, CollisionContext selectionContext) - { return vshape; } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return vshape; } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) - { - BlockState state = super.getStateForPlacement(context); - if((config & CFG_WATERLOGGABLE)!=0) { - FluidState fs = context.getLevel().getFluidState(context.getClickedPos()); - state = state.setValue(WATERLOGGED,fs.getType()==Fluids.WATER); - } - return state; - } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - @SuppressWarnings("deprecation") - public PushReaction getPistonPushReaction(BlockState state) - { return PushReaction.NORMAL; } - - @Override - public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) - { - if((config & CFG_WATERLOGGABLE)!=0) { - if(state.getValue(WATERLOGGED)) return false; - } - return super.propagatesSkylightDown(state, reader, pos); - } - - @Override - @SuppressWarnings("deprecation") - public FluidState getFluidState(BlockState state) - { - if((config & CFG_WATERLOGGABLE)!=0) { - return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state); - } - return super.getFluidState(state); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState updateShape(BlockState state, Direction facing, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) - { - if((config & CFG_WATERLOGGABLE)!=0) { - if(state.getValue(WATERLOGGED)) world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - } - return state; - } - } - - public static class WaterLoggable extends Cutout implements IStandardBlock - { - public WaterLoggable(long config, BlockBehaviour.Properties properties) - { super(config|CFG_WATERLOGGABLE, properties); } - - public WaterLoggable(long config, BlockBehaviour.Properties properties, AABB aabb) - { super(config|CFG_WATERLOGGABLE, properties, aabb); } - - public WaterLoggable(long config, BlockBehaviour.Properties properties, VoxelShape voxel_shape) - { super(config|CFG_WATERLOGGABLE, properties, voxel_shape); } - - public WaterLoggable(long config, BlockBehaviour.Properties properties, AABB[] aabbs) - { super(config|CFG_WATERLOGGABLE, properties, aabbs); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(WATERLOGGED); } - } - - public static class Directed extends Cutout implements IStandardBlock - { - public static final DirectionProperty FACING = BlockStateProperties.FACING; - protected final Map vshapes; - - public Directed(long config, BlockBehaviour.Properties properties, final Function, Map> shape_supplier) - { - super(config, properties); - registerDefaultState(super.defaultBlockState().setValue(FACING, Direction.UP)); - vshapes = shape_supplier.apply(getStateDefinition().getPossibleStates()); - } - - public Directed(long config, BlockBehaviour.Properties properties, final Supplier> shape_supplier) - { - this(config, properties, (states)->{ - final Map vshapes = new HashMap<>(); - final ArrayList indexed_shapes = shape_supplier.get(); - for(BlockState state:states) vshapes.put(state, indexed_shapes.get(state.getValue(FACING).get3DDataValue())); - return vshapes; - }); - } - - public Directed(long config, BlockBehaviour.Properties properties, final AABB[] unrotatedAABBs) - { - this(config, properties, (states)->{ - final boolean is_horizontal = ((config & CFG_HORIZIONTAL)!=0); - Map vshapes = new HashMap<>(); - for(BlockState state:states) { - vshapes.put(state, Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(unrotatedAABBs, state.getValue(FACING), is_horizontal))); - } - return vshapes; - }); - } - - public Directed(long config, BlockBehaviour.Properties properties, final AABB unrotatedAABB) - { this(config, properties, new AABB[]{unrotatedAABB}); } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter source, BlockPos pos, CollisionContext selectionContext) - { return vshapes.get(state); } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return getShape(state, world, pos, selectionContext); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(FACING); } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) - { - BlockState state = super.getStateForPlacement(context); - if(state == null) return null; - Direction facing = context.getClickedFace(); - if((config & (CFG_HORIZIONTAL|CFG_LOOK_PLACEMENT)) == (CFG_HORIZIONTAL|CFG_LOOK_PLACEMENT)) { - // horizontal placement in direction the player is looking - facing = context.getHorizontalDirection(); - } else if((config & (CFG_HORIZIONTAL|CFG_LOOK_PLACEMENT)) == (CFG_HORIZIONTAL)) { - // horizontal placement on a face - if(((facing==Direction.UP)||(facing==Direction.DOWN))) return null; - } else if((config & CFG_LOOK_PLACEMENT)!=0) { - // placement in direction the player is looking, with up and down - facing = context.getNearestLookingDirection(); - } - if((config & CFG_OPPOSITE_PLACEMENT)!=0) facing = facing.getOpposite(); - if(((config & CFG_FLIP_PLACEMENT_SHIFTCLICK) != 0) && (context.getPlayer()!=null) && (context.getPlayer().isShiftKeyDown())) facing = facing.getOpposite(); - return state.setValue(FACING, facing); - } - } - - public static class AxisAligned extends Cutout implements IStandardBlock - { - public static final EnumProperty AXIS = BlockStateProperties.AXIS; - protected final ArrayList vshapes; - - public AxisAligned(long config, BlockBehaviour.Properties properties, final Supplier> shape_supplier) - { - super(config, properties); - registerDefaultState(super.defaultBlockState().setValue(AXIS, Direction.Axis.X)); - vshapes = shape_supplier.get(); - } - - public AxisAligned(long config, BlockBehaviour.Properties properties, final AABB[] unrotatedAABBs) - { - this(config, properties, ()-> new ArrayList<>(Arrays.asList( - Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(unrotatedAABBs, Direction.EAST, false)), - Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(unrotatedAABBs, Direction.UP, false)), - Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(unrotatedAABBs, Direction.SOUTH, false)), - Shapes.block() - ))); - } - - public AxisAligned(long config, BlockBehaviour.Properties properties, final AABB unrotatedAABB) - { this(config, properties, new AABB[]{unrotatedAABB}); } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter source, BlockPos pos, CollisionContext selectionContext) - { return vshapes.get((state.getValue(AXIS)).ordinal() & 0x3); } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return getShape(state, world, pos, selectionContext); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(AXIS); } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) - { - Direction facing; - if((config & CFG_LOOK_PLACEMENT)!=0) { - facing = context.getNearestLookingDirection(); - } else { - facing = context.getClickedFace(); - } - return super.getStateForPlacement(context).setValue(AXIS, facing.getAxis()); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rotation) - { - switch(rotation) { - case CLOCKWISE_90: - case COUNTERCLOCKWISE_90: - switch(state.getValue(AXIS)) { - case X: return state.setValue(AXIS, Direction.Axis.Z); - case Z: return state.setValue(AXIS, Direction.Axis.X); - } - } - return state; - } - } - - public static class Horizontal extends Cutout implements IStandardBlock - { - public static final DirectionProperty HORIZONTAL_FACING = BlockStateProperties.HORIZONTAL_FACING; - protected final Map vshapes; - protected final Map cshapes; - - public Horizontal(long config, BlockBehaviour.Properties properties, final Function, Map> shape_supplier) - { - super(config|CFG_HORIZIONTAL, properties); - registerDefaultState(super.defaultBlockState().setValue(HORIZONTAL_FACING, Direction.NORTH)); - vshapes = shape_supplier.apply(getStateDefinition().getPossibleStates()); - cshapes = shape_supplier.apply(getStateDefinition().getPossibleStates()); - } - - public Horizontal(long config, BlockBehaviour.Properties properties, final Supplier> shape_supplier) - { - this(config, properties, (states)->{ - final Map vshapes = new HashMap<>(); - final ArrayList indexed_shapes = shape_supplier.get(); - for(BlockState state:states) vshapes.put(state, indexed_shapes.get(state.getValue(HORIZONTAL_FACING).get3DDataValue())); - return vshapes; - }); - } - - public Horizontal(long config, BlockBehaviour.Properties properties, final AABB unrotatedAABB) - { this(config, properties, new AABB[]{unrotatedAABB}); } - - public Horizontal(long config, BlockBehaviour.Properties properties, final AABB[] unrotatedAABBs) - { - this(config, properties, (states)->{ - Map vshapes = new HashMap<>(); - for(BlockState state:states) { - vshapes.put(state, Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(unrotatedAABBs, state.getValue(HORIZONTAL_FACING), true))); - } - return vshapes; - }); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(HORIZONTAL_FACING); } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter source, BlockPos pos, CollisionContext selectionContext) - { return vshapes.get(state); } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return cshapes.get(state); } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) - { - BlockState state = super.getStateForPlacement(context); - if(state == null) return null; - Direction facing = context.getClickedFace(); - if((config & CFG_LOOK_PLACEMENT) != 0) { - // horizontal placement in direction the player is looking - facing = context.getHorizontalDirection(); - } else { - // horizontal placement on a face - facing = ((facing==Direction.UP)||(facing==Direction.DOWN)) ? (context.getHorizontalDirection()) : facing; - } - if((config & CFG_OPPOSITE_PLACEMENT)!=0) facing = facing.getOpposite(); - if(((config & CFG_FLIP_PLACEMENT_SHIFTCLICK) != 0) && (context.getPlayer()!=null) && (context.getPlayer().isShiftKeyDown())) facing = facing.getOpposite(); - return state.setValue(HORIZONTAL_FACING, facing); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rot) - { return state.setValue(HORIZONTAL_FACING, rot.rotate(state.getValue(HORIZONTAL_FACING))); } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirrorIn) - { return state.rotate(mirrorIn.getRotation(state.getValue(HORIZONTAL_FACING))); } - } - - public static class DirectedWaterLoggable extends Directed implements IStandardBlock - { - public DirectedWaterLoggable(long config, BlockBehaviour.Properties properties, AABB aabb) - { super(config|CFG_WATERLOGGABLE, properties, aabb); } - - public DirectedWaterLoggable(long config, BlockBehaviour.Properties properties, AABB[] aabbs) - { super(config|CFG_WATERLOGGABLE, properties, aabbs); } - - public DirectedWaterLoggable(long config, BlockBehaviour.Properties properties, final Function, Map> shape_supplier) - { super(config|CFG_WATERLOGGABLE, properties, shape_supplier); } - - public DirectedWaterLoggable(long config, BlockBehaviour.Properties properties, final Supplier> shape_supplier) - { super(config|CFG_WATERLOGGABLE, properties, shape_supplier); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(WATERLOGGED); } - } - - public static class AxisAlignedWaterLoggable extends AxisAligned implements IStandardBlock - { - public AxisAlignedWaterLoggable(long config, BlockBehaviour.Properties properties, AABB aabb) - { super(config|CFG_WATERLOGGABLE, properties, aabb); } - - public AxisAlignedWaterLoggable(long config, BlockBehaviour.Properties properties, AABB[] aabbs) - { super(config|CFG_WATERLOGGABLE, properties, aabbs); } - - public AxisAlignedWaterLoggable(long config, BlockBehaviour.Properties properties, final Supplier> shape_supplier) - { super(config|CFG_WATERLOGGABLE, properties, shape_supplier); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(WATERLOGGED); } - } - - public static class HorizontalWaterLoggable extends Horizontal implements IStandardBlock - { - public HorizontalWaterLoggable(long config, BlockBehaviour.Properties properties, AABB aabb) - { super(config|CFG_WATERLOGGABLE|CFG_HORIZIONTAL, properties, aabb); } - - public HorizontalWaterLoggable(long config, BlockBehaviour.Properties properties, AABB[] aabbs) - { super(config|CFG_WATERLOGGABLE|CFG_HORIZIONTAL, properties, aabbs); } - - public HorizontalWaterLoggable(long config, BlockBehaviour.Properties properties, final Supplier> shape_supplier) - { super(config|CFG_WATERLOGGABLE|CFG_HORIZIONTAL, properties, shape_supplier); } - - public HorizontalWaterLoggable(long config, BlockBehaviour.Properties properties, final Function, Map> shape_supplier) - { super(config|CFG_WATERLOGGABLE|CFG_HORIZIONTAL, properties, shape_supplier); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(WATERLOGGED); } - } - - static public class HorizontalFourWayWaterLoggable extends WaterLoggable implements IStandardBlock - { - public static final BooleanProperty NORTH = BlockStateProperties.NORTH; - public static final BooleanProperty EAST = BlockStateProperties.EAST; - public static final BooleanProperty SOUTH = BlockStateProperties.SOUTH; - public static final BooleanProperty WEST = BlockStateProperties.WEST; - protected final Map shapes; - protected final Map collision_shapes; - - public HorizontalFourWayWaterLoggable(long config, BlockBehaviour.Properties properties, AABB base_aabb, final AABB[] side_aabb, int railing_height_extension) - { - super(config, properties, base_aabb); - Map build_shapes = new HashMap<>(); - Map build_collision_shapes = new HashMap<>(); - for(BlockState state:getStateDefinition().getPossibleStates()) { - { - VoxelShape shape = ((base_aabb.getXsize()==0) || (base_aabb.getYsize()==0) || (base_aabb.getZsize()==0)) ? Shapes.empty() : Shapes.create(base_aabb); - if(state.getValue(NORTH)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(side_aabb, Direction.NORTH, true)), BooleanOp.OR); - if(state.getValue(EAST)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(side_aabb, Direction.EAST, true)), BooleanOp.OR); - if(state.getValue(SOUTH)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(side_aabb, Direction.SOUTH, true)), BooleanOp.OR); - if(state.getValue(WEST)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getRotatedAABB(side_aabb, Direction.WEST, true)), BooleanOp.OR); - if(shape.isEmpty()) shape = Shapes.block(); - build_shapes.put(state.setValue(WATERLOGGED, false), shape); - build_shapes.put(state.setValue(WATERLOGGED, true), shape); - } - { - // how the hack to extend a shape, these are the above with y+4px. - VoxelShape shape = ((base_aabb.getXsize()==0) || (base_aabb.getYsize()==0) || (base_aabb.getZsize()==0)) ? Shapes.empty() : Shapes.create(base_aabb); - if(state.getValue(NORTH)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getMappedAABB(Auxiliaries.getRotatedAABB(side_aabb, - Direction.NORTH, true), bb->bb.expandTowards(0, railing_height_extension, 0))), BooleanOp.OR); - if(state.getValue(EAST)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getMappedAABB(Auxiliaries.getRotatedAABB(side_aabb, - Direction.EAST, true), bb->bb.expandTowards(0, railing_height_extension, 0))), BooleanOp.OR); - if(state.getValue(SOUTH)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getMappedAABB(Auxiliaries.getRotatedAABB(side_aabb, - Direction.SOUTH, true), bb->bb.expandTowards(0, railing_height_extension, 0))), BooleanOp.OR); - if(state.getValue(WEST)) shape = Shapes.joinUnoptimized(shape,Auxiliaries.getUnionShape(Auxiliaries.getMappedAABB(Auxiliaries.getRotatedAABB(side_aabb, - Direction.WEST, true), bb->bb.expandTowards(0, railing_height_extension, 0))), BooleanOp.OR); - if(shape.isEmpty()) shape = Shapes.block(); - build_collision_shapes.put(state.setValue(WATERLOGGED, false), shape); - build_collision_shapes.put(state.setValue(WATERLOGGED, true), shape); - } - } - shapes = build_shapes; - collision_shapes = build_collision_shapes; - registerDefaultState(super.defaultBlockState().setValue(NORTH, false).setValue(EAST, false).setValue(SOUTH, false).setValue(WEST, false).setValue(WATERLOGGED, false)); - } - - public HorizontalFourWayWaterLoggable(long config, BlockBehaviour.Properties properties, AABB base_aabb, final AABB side_aabb, int railing_height_extension) - { this(config, properties, base_aabb, new AABB[]{side_aabb}, railing_height_extension); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(NORTH,EAST,SOUTH,WEST); } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) - { return super.getStateForPlacement(context).setValue(NORTH, false).setValue(EAST, false).setValue(SOUTH, false).setValue(WEST, false); } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) - { return shapes.getOrDefault(state, Shapes.block()); } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) - { return collision_shapes.getOrDefault(state, Shapes.block()); } - - public static BooleanProperty getDirectionProperty(Direction face) - { - return switch (face) { - case EAST -> HorizontalFourWayWaterLoggable.EAST; - case SOUTH -> HorizontalFourWayWaterLoggable.SOUTH; - case WEST -> HorizontalFourWayWaterLoggable.WEST; - default -> HorizontalFourWayWaterLoggable.NORTH; - }; - } - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/StandardDoorBlock.java b/src/main/java/wile/engineersdecor/libmc/StandardDoorBlock.java deleted file mode 100644 index 464a3a4..0000000 --- a/src/main/java/wile/engineersdecor/libmc/StandardDoorBlock.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * @file StandardDoorBlock.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Door blocks, almost entirely based on vanilla. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.DoorBlock; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.DoorHingeSide; -import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.BooleanOp; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nullable; -import java.util.List; - - -public class StandardDoorBlock extends DoorBlock implements StandardBlocks.IStandardBlock -{ - private final long config_; - protected final VoxelShape[][][][] shapes_; - protected final SoundEvent open_sound_; - protected final SoundEvent close_sound_; - - public StandardDoorBlock(long config, BlockBehaviour.Properties properties, AABB[] open_aabbs_top, AABB[] open_aabbs_bottom, AABB[] closed_aabbs_top, AABB[] closed_aabbs_bottom, SoundEvent open_sound, SoundEvent close_sound) - { - super(properties); - VoxelShape[][][][] shapes = new VoxelShape[Direction.values().length][2][2][2]; - for(Direction facing: Direction.values()) { - for(boolean open: new boolean[]{false,true}) { - for(DoubleBlockHalf half: new DoubleBlockHalf[]{DoubleBlockHalf.UPPER,DoubleBlockHalf.LOWER}) { - for(boolean hinge_right: new boolean[]{false,true}) { - VoxelShape shape = Shapes.empty(); - if(facing.getAxis() == Direction.Axis.Y) { - shape = Shapes.block(); - } else { - final AABB[] aabbs = (open)?((half==DoubleBlockHalf.UPPER) ? open_aabbs_top : open_aabbs_bottom) : ((half==DoubleBlockHalf.UPPER) ? closed_aabbs_top : closed_aabbs_bottom); - for(AABB e:aabbs) { - AABB aabb = Auxiliaries.getRotatedAABB(e, facing, true); - if(!hinge_right) aabb = Auxiliaries.getMirroredAABB(aabb, facing.getClockWise().getAxis()); - shape = Shapes.join(shape, Shapes.create(aabb), BooleanOp.OR); - } - } - shapes[facing.ordinal()][open?1:0][hinge_right?1:0][half==DoubleBlockHalf.UPPER?0:1] = shape; - } - } - } - } - config_ = config; - shapes_ = shapes; - open_sound_ = open_sound; - close_sound_ = close_sound; - } - - public StandardDoorBlock(long config, BlockBehaviour.Properties properties, AABB open_aabb, AABB closed_aabb, SoundEvent open_sound, SoundEvent close_sound) - { this(config, properties, new AABB[]{open_aabb}, new AABB[]{open_aabb}, new AABB[]{closed_aabb}, new AABB[]{closed_aabb}, open_sound, close_sound); } - - public StandardDoorBlock(long config, BlockBehaviour.Properties properties, SoundEvent open_sound, SoundEvent close_sound) - { - this( - config, properties, - Auxiliaries.getPixeledAABB(13,0, 0, 16,16,16), - Auxiliaries.getPixeledAABB( 0,0,13, 16,16,16), - open_sound, - close_sound - ); - } - - public StandardDoorBlock(long config, BlockBehaviour.Properties properties) - { - this( - config, properties, - Auxiliaries.getPixeledAABB(13,0, 0, 16,16,16), - Auxiliaries.getPixeledAABB( 0,0,13, 16,16,16), - SoundEvents.WOODEN_DOOR_OPEN, - SoundEvents.WOODEN_DOOR_CLOSE - ); - } - - @Override - public long config() - { return config_; } - - protected void sound(BlockGetter world, BlockPos pos, boolean open) - { if(world instanceof Level) ((Level)world).playSound(null, pos, open ? open_sound_ : close_sound_, SoundSource.BLOCKS, 0.7f, 1f); } - - protected void actuate_adjacent_wing(BlockState state, BlockGetter world_ro, BlockPos pos, boolean open) - { - if(!(world_ro instanceof final Level world)) return; - final BlockPos adjecent_pos = pos.relative( (state.getValue(HINGE)==DoorHingeSide.LEFT) ? (state.getValue(FACING).getClockWise()) : (state.getValue(FACING).getCounterClockWise())); - if(!world.isLoaded(adjecent_pos)) return; - BlockState adjacent_state = world.getBlockState(adjecent_pos); - if(adjacent_state.getBlock()!=this) return; - if(adjacent_state.getValue(OPEN)==open) return; - world.setBlock(adjecent_pos, adjacent_state.setValue(OPEN, open), 2|10); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag) - { Auxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) - { return shapes_[state.getValue(FACING).ordinal()][state.getValue(OPEN)?1:0][state.getValue(HINGE)==DoorHingeSide.RIGHT?1:0][state.getValue(HALF)==DoubleBlockHalf.UPPER?0:1]; } - - @Override - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) - { setOpen(player, world, state, pos, !state.getValue(OPEN)); return InteractionResult.sidedSuccess(world.isClientSide()); } - - @Override - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) - { - boolean powered = world.hasNeighborSignal(pos) || world.hasNeighborSignal(pos.relative(state.getValue(HALF) == DoubleBlockHalf.LOWER ? Direction.UP : Direction.DOWN)); - if((block == this) || (powered == state.getValue(POWERED))) return; - world.setBlock(pos, state.setValue(POWERED, powered).setValue(OPEN, powered), 2); - actuate_adjacent_wing(state, world, pos, powered); - if(powered != state.getValue(OPEN)) sound(world, pos, powered); - } - - @Override - public void setOpen(@Nullable Entity entity, Level world, BlockState state, BlockPos pos, boolean open) - { - if(!state.is(this) || (state.getValue(OPEN) == open)) return; - state = state.setValue(OPEN, open); - world.setBlock(pos, state, 2|8); - sound(world, pos, open); - actuate_adjacent_wing(state, world, pos, open); - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/StandardEntityBlocks.java b/src/main/java/wile/engineersdecor/libmc/StandardEntityBlocks.java deleted file mode 100644 index cbb2f6e..0000000 --- a/src/main/java/wile/engineersdecor/libmc/StandardEntityBlocks.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * @file StandardEntityBlocks.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Common functionality class for blocks with block entities. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityTicker; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.gameevent.GameEventListener; -import net.minecraftforge.common.util.FakePlayer; - -import javax.annotation.Nullable; - - -public class StandardEntityBlocks -{ - public interface IStandardEntityBlock extends EntityBlock - { - - default boolean isBlockEntityTicking(Level world, BlockState state) - { return false; } - - default InteractionResult useOpenGui(BlockState state, Level world, BlockPos pos, Player player) - { - if(world.isClientSide()) return InteractionResult.SUCCESS; - final BlockEntity te = world.getBlockEntity(pos); - if(!(te instanceof MenuProvider) || ((player instanceof FakePlayer))) return InteractionResult.FAIL; - player.openMenu((MenuProvider)te); - return InteractionResult.CONSUME; - } - - @Override - @Nullable - default BlockEntity newBlockEntity(BlockPos pos, BlockState state) - { - BlockEntityType tet = Registries.getBlockEntityTypeOfBlock(state.getBlock()); - return (tet==null) ? null : tet.create(pos, state); - } - - @Override - @Nullable - default BlockEntityTicker getTicker(Level world, BlockState state, BlockEntityType te_type) - { return (world.isClientSide || (!isBlockEntityTicking(world, state))) ? (null) : ((Level w, BlockPos p, BlockState s, T te) -> ((StandardBlockEntity)te).tick()); } - - @Override - @Nullable - default GameEventListener getListener(ServerLevel world, T te) - { return null; } - } - - public static abstract class StandardBlockEntity extends BlockEntity - { - public StandardBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) - { super(type, pos, state); } - - public void tick() - {} - } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/StandardFenceBlock.java b/src/main/java/wile/engineersdecor/libmc/StandardFenceBlock.java deleted file mode 100644 index b72a829..0000000 --- a/src/main/java/wile/engineersdecor/libmc/StandardFenceBlock.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * @file StandardFenceBlock.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Wall blocks. - */ -package wile.engineersdecor.libmc; - -import com.google.common.collect.ImmutableMap; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.FenceGateBlock; -import net.minecraft.world.level.block.WallBlock; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.block.state.properties.WallSide; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.PushReaction; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nullable; -import java.util.List; -import java.util.Map; - - -public class StandardFenceBlock extends WallBlock implements StandardBlocks.IStandardBlock -{ - public static final BooleanProperty UP = BlockStateProperties.UP; - public static final EnumProperty WALL_EAST = BlockStateProperties.EAST_WALL; - public static final EnumProperty WALL_NORTH = BlockStateProperties.NORTH_WALL; - public static final EnumProperty WALL_SOUTH = BlockStateProperties.SOUTH_WALL; - public static final EnumProperty WALL_WEST = BlockStateProperties.WEST_WALL; - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - private final Map shape_voxels; - private final Map collision_shape_voxels; - private final long config; - - public StandardFenceBlock(long config, BlockBehaviour.Properties properties) - { this(config, properties, 1.5,16, 1.5, 0, 14, 16); } - - public StandardFenceBlock(long config, BlockBehaviour.Properties properties, double pole_width, double pole_height, double side_width, double side_min_y, double side_max_low_y, double side_max_tall_y) - { - super(properties); - shape_voxels = buildShapes(pole_width, pole_height, side_width, side_min_y, side_max_low_y, side_max_tall_y); - collision_shape_voxels = buildShapes(pole_width,24, pole_width, 0, 24, 24); - this.config = config; - } - - @Override - public long config() - { return config; } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag) - { Auxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); } - - private static VoxelShape combinedShape(VoxelShape pole, WallSide height, VoxelShape low, VoxelShape high) - { - if(height == WallSide.TALL) return Shapes.or(pole, high); - if(height == WallSide.LOW) return Shapes.or(pole, low); - return pole; - } - - protected Map buildShapes(double pole_width, double pole_height, double side_width, double side_min_y, double side_max_low_y, double side_max_tall_y) - { - final double px0=8.0-pole_width, px1=8.0+pole_width, sx0=8.0-side_width, sx1=8.0+side_width; - VoxelShape vp = Block.box(px0, 0, px0, px1, pole_height, px1); - VoxelShape vs1 = Block.box(sx0, side_min_y, 0, sx1, side_max_low_y, sx1); - VoxelShape vs2 = Block.box(sx0, side_min_y, sx0, sx1, side_max_low_y, 16); - VoxelShape vs3 = Block.box(0, side_min_y, sx0, sx1, side_max_low_y, sx1); - VoxelShape vs4 = Block.box(sx0, side_min_y, sx0, 16, side_max_low_y, sx1); - VoxelShape vs5 = Block.box(sx0, side_min_y, 0, sx1, side_max_tall_y, sx1); - VoxelShape vs6 = Block.box(sx0, side_min_y, sx0, sx1, side_max_tall_y, 16); - VoxelShape vs7 = Block.box(0, side_min_y, sx0, sx1, side_max_tall_y, sx1); - VoxelShape vs8 = Block.box(sx0, side_min_y, sx0, 16, side_max_tall_y, sx1); - ImmutableMap.Builder builder = ImmutableMap.builder(); - for(Boolean up : UP.getPossibleValues()) { - for(WallSide wh_east : WALL_EAST.getPossibleValues()) { - for(WallSide wh_north : WALL_NORTH.getPossibleValues()) { - for(WallSide wh_west : WALL_WEST.getPossibleValues()) { - for(WallSide wh_south : WALL_SOUTH.getPossibleValues()) { - VoxelShape shape = Shapes.empty(); - shape = combinedShape(shape, wh_east, vs4, vs8); - shape = combinedShape(shape, wh_west, vs3, vs7); - shape = combinedShape(shape, wh_north, vs1, vs5); - shape = combinedShape(shape, wh_south, vs2, vs6); - if(up) shape = Shapes.or(shape, vp); - BlockState bs = defaultBlockState().setValue(UP, up) - .setValue(WALL_EAST, wh_east) - .setValue(WALL_NORTH, wh_north) - .setValue(WALL_WEST, wh_west) - .setValue(WALL_SOUTH, wh_south); - builder.put(bs.setValue(WATERLOGGED, false), shape); - builder.put(bs.setValue(WATERLOGGED, true), shape); - } - } - } - } - } - return builder.build(); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return shape_voxels.getOrDefault(state, Shapes.block()); } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return collision_shape_voxels.getOrDefault(state, Shapes.block()); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); } - - protected boolean attachesTo(BlockState facingState, LevelReader world, BlockPos facingPos, Direction side) - { - final Block block = facingState.getBlock(); - if((block instanceof FenceGateBlock) || (block instanceof StandardFenceBlock) || (block instanceof VariantWallBlock)) return true; - final BlockState oppositeState = world.getBlockState(facingPos.relative(side, 2)); - if(!(oppositeState.getBlock() instanceof StandardFenceBlock)) return false; - return facingState.isRedstoneConductor(world, facingPos) && canSupportCenter(world, facingPos, side); - } - - protected WallSide selectWallHeight(LevelReader world, BlockPos pos, Direction direction) - { - return WallSide.LOW; // @todo: implement - } - - public BlockState getStateForPlacement(BlockPlaceContext context) - { - LevelReader world = context.getLevel(); - BlockPos pos = context.getClickedPos(); - FluidState fs = context.getLevel().getFluidState(context.getClickedPos()); - boolean n = attachesTo(world.getBlockState(pos.north()), world, pos.north(), Direction.SOUTH); - boolean e = attachesTo(world.getBlockState(pos.east()), world, pos.east(), Direction.WEST); - boolean s = attachesTo(world.getBlockState(pos.south()), world, pos.south(), Direction.NORTH); - boolean w = attachesTo(world.getBlockState(pos.west()), world, pos.west(), Direction.EAST); - boolean not_straight = (!n || !s || e || w) && (n || s || !e || !w); - return defaultBlockState() - .setValue(UP, not_straight) - .setValue(WALL_NORTH, n ? selectWallHeight(world, pos, Direction.NORTH) : WallSide.NONE) - .setValue(WALL_EAST , e ? selectWallHeight(world, pos, Direction.EAST) : WallSide.NONE) - .setValue(WALL_SOUTH, s ? selectWallHeight(world, pos, Direction.SOUTH) : WallSide.NONE) - .setValue(WALL_WEST , w ? selectWallHeight(world, pos, Direction.WEST) : WallSide.NONE) - .setValue(WATERLOGGED, fs.getType() == Fluids.WATER); - } - - @Override - public BlockState updateShape(BlockState state, Direction side, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) - { - if(state.getValue(BlockStateProperties.WATERLOGGED)) world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - if(side == Direction.DOWN) return super.updateShape(state, side, facingState, world, pos, facingPos); - boolean n = (side==Direction.NORTH) ? attachesTo(facingState, world, facingPos, side) : (state.getValue(WALL_NORTH)!=WallSide.NONE); - boolean e = (side==Direction.EAST) ? attachesTo(facingState, world, facingPos, side) : (state.getValue(WALL_EAST) !=WallSide.NONE); - boolean s = (side==Direction.SOUTH) ? attachesTo(facingState, world, facingPos, side) : (state.getValue(WALL_SOUTH)!=WallSide.NONE); - boolean w = (side==Direction.WEST) ? attachesTo(facingState, world, facingPos, side) : (state.getValue(WALL_WEST) !=WallSide.NONE); - boolean not_straight = (!n || !s || e || w) && (n || s || !e || !w); - return state.setValue(UP, not_straight) - .setValue(WALL_NORTH, n ? selectWallHeight(world, pos, Direction.NORTH) : WallSide.NONE) - .setValue(WALL_EAST , e ? selectWallHeight(world, pos, Direction.EAST) : WallSide.NONE) - .setValue(WALL_SOUTH, s ? selectWallHeight(world, pos, Direction.SOUTH) : WallSide.NONE) - .setValue(WALL_WEST , w ? selectWallHeight(world, pos, Direction.WEST) : WallSide.NONE); - } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - @SuppressWarnings("deprecation") - public PushReaction getPistonPushReaction(BlockState state) - { return PushReaction.NORMAL; } -} diff --git a/src/main/java/wile/engineersdecor/libmc/StandardStairsBlock.java b/src/main/java/wile/engineersdecor/libmc/StandardStairsBlock.java deleted file mode 100644 index 34019e9..0000000 --- a/src/main/java/wile/engineersdecor/libmc/StandardStairsBlock.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * @file StandardStairsBlock.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Stairs and roof blocks, almost entirely based on vanilla stairs. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.StairBlock; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nullable; -import java.util.List; - - -public class StandardStairsBlock extends StairBlock implements StandardBlocks.IStandardBlock -{ - private final long config; - - public StandardStairsBlock(long config, java.util.function.Supplier state, BlockBehaviour.Properties properties) - { super(state, properties); this.config = config; } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag) - { Auxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - @SuppressWarnings("deprecation") - public PushReaction getPistonPushReaction(BlockState state) - { return PushReaction.NORMAL; } -} diff --git a/src/main/java/wile/engineersdecor/libmc/TooltipDisplay.java b/src/main/java/wile/engineersdecor/libmc/TooltipDisplay.java deleted file mode 100644 index c54cec6..0000000 --- a/src/main/java/wile/engineersdecor/libmc/TooltipDisplay.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * @file Tooltip.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Delayed tooltip for a selected area. Constructed with a - * GUI, invoked in `render()`. - */ -package wile.engineersdecor.libmc; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.network.chat.*; -import net.minecraft.util.Mth; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Supplier; - - -@OnlyIn(Dist.CLIENT) -public class TooltipDisplay -{ - private static long default_delay = 800; - private static int default_max_deviation = 1; - - public static void config(long delay, int max_deviation) - { - default_delay = Mth.clamp(delay, 500, 5000); - default_max_deviation = Mth.clamp(max_deviation, 1, 5); - } - - // --------------------------------------------------------------------------------------------------- - - public static class TipRange - { - public final int x0,y0,x1,y1; - public final Supplier text; - - public TipRange(int x, int y, int w, int h, Component text) - { this(x,y,w,h,()->text); } - - public TipRange(int x, int y, int w, int h, Supplier text) - { this.text=text; this.x0=x; this.y0=y; this.x1=x0+w-1; this.y1=y0+h-1; } - - } - - // --------------------------------------------------------------------------------------------------- - - private List ranges = new ArrayList<>(); - private long delay = default_delay; - private int max_deviation = default_max_deviation; - private int x_last, y_last; - private long t; - private static boolean had_render_exception = false; - - public TooltipDisplay() - { t = System.currentTimeMillis(); } - - public TooltipDisplay init(List ranges, long delay_ms, int max_deviation_xy) - { - this.ranges = ranges; - this.delay = delay_ms; - this.max_deviation = max_deviation_xy; - t = System.currentTimeMillis(); - x_last = y_last = 0; - return this; - } - - public TooltipDisplay init(List ranges) - { return init(ranges, default_delay, default_max_deviation); } - - public TooltipDisplay init(TipRange... ranges) - { return init(Arrays.asList(ranges), default_delay, default_max_deviation); } - - public TooltipDisplay delay(int ms) - { delay = (ms<=0) ? default_delay : ms; return this; } - - public void resetTimer() - { t = System.currentTimeMillis(); } - - public boolean render(PoseStack mx, final AbstractContainerScreen gui, int x, int y) - { - if(had_render_exception) return false; - if((Math.abs(x-x_last) > max_deviation) || (Math.abs(y-y_last) > max_deviation)) { - x_last = x; - y_last = y; - resetTimer(); - return false; - } else if(Math.abs(System.currentTimeMillis()-t) < delay) { - return false; - } else if(ranges.stream().noneMatch( - (tip)->{ - if((xtip.x1) || (ytip.y1)) return false; - String text = tip.text.get().toString(); - if(text.isEmpty()) return false; - try { - gui.renderComponentTooltip(mx, tip.text.get().toFlatList(Style.EMPTY), x, y); - } catch(Exception ex) { - had_render_exception = true; - Auxiliaries.logError("Tooltip rendering disabled due to exception: '" + ex.getMessage() + "'"); - return false; - } - return true; - }) - ){ - resetTimer(); - return false; - } else { - return true; - } - } -} diff --git a/src/main/java/wile/engineersdecor/libmc/VariantSlabBlock.java b/src/main/java/wile/engineersdecor/libmc/VariantSlabBlock.java deleted file mode 100644 index 3bd5a32..0000000 --- a/src/main/java/wile/engineersdecor/libmc/VariantSlabBlock.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * @file VariantSlabBlock.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Standard half block horizontal slab characteristics class. - */ -package wile.engineersdecor.libmc; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.block.state.properties.SlabType; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -public class VariantSlabBlock extends StandardBlocks.WaterLoggable implements StandardBlocks.IStandardBlock -{ - public static final EnumProperty TYPE = BlockStateProperties.SLAB_TYPE; - public static final IntegerProperty TEXTURE_VARIANT = IntegerProperty.create("tvariant", 0, 3); - - protected static final VoxelShape[] AABBs = { - Shapes.create(new AABB(0, 8./16, 0, 1, 16./16, 1)), // top slab - Shapes.create(new AABB(0, 0./16, 0, 1, 8./16, 1)), // bottom slab - Shapes.create(new AABB(0, 0./16, 0, 1, 16./16, 1)), // both slabs - Shapes.create(new AABB(0, 0./16, 0, 1, 16./16, 1)) // << 2bit fill - }; - protected static final int[] num_slabs_contained_in_parts_ = {1,1,2,2}; - private static boolean with_pickup = false; - - public static void on_config(boolean direct_slab_pickup) - { with_pickup = direct_slab_pickup; } - - protected boolean is_cube(BlockState state) - { return state.getValue(TYPE) == SlabType.DOUBLE; } - - public VariantSlabBlock(long config, BlockBehaviour.Properties builder) - { super(config, builder); registerDefaultState(defaultBlockState().setValue(TYPE, SlabType.BOTTOM)); } - - @Override - public RenderTypeHint getRenderTypeHint() - { return (((config & StandardBlocks.CFG_TRANSLUCENT)!=0) ? (RenderTypeHint.TRANSLUCENT) : (RenderTypeHint.CUTOUT)); } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag) - { - if(!Auxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true)) return; - if(with_pickup && Auxiliaries.Tooltip.helpCondition()) Auxiliaries.Tooltip.addInformation("engineersdecor.tooltip.slabpickup", "engineersdecor.tooltip.slabpickup", tooltip, flag, true); - } - - @Override - @OnlyIn(Dist.CLIENT) - @SuppressWarnings("deprecation") - public boolean skipRendering(BlockState state, BlockState adjacentBlockState, Direction side) - { return (adjacentBlockState==state) || (super.skipRendering(state, adjacentBlockState, side)); } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter source, BlockPos pos, CollisionContext selectionContext) - { return AABBs[state.getValue(TYPE).ordinal() & 0x3]; } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return getShape(state, world, pos, selectionContext); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(TYPE, TEXTURE_VARIANT); } - - @Override - @Nullable - public BlockState getStateForPlacement(BlockPlaceContext context) - { - BlockPos pos = context.getClickedPos(); - if(context.getLevel().getBlockState(pos).getBlock() == this) return context.getLevel().getBlockState(pos).setValue(TYPE, SlabType.DOUBLE).setValue(WATERLOGGED, false); - final int rnd = Mth.clamp((int)(Mth.getSeed(context.getClickedPos()) & 0x3), 0, 3); - final Direction face = context.getClickedFace(); - final BlockState placement_state = super.getStateForPlacement(context).setValue(TEXTURE_VARIANT, rnd); // fluid state - if(face == Direction.UP) return placement_state.setValue(TYPE, SlabType.BOTTOM); - if(face == Direction.DOWN) return placement_state.setValue(TYPE, SlabType.TOP); - if(!face.getAxis().isHorizontal()) return placement_state; - final boolean isupper = ((context.getClickLocation().y() - context.getClickedPos().getY()) > 0.5); - return placement_state.setValue(TYPE, isupper ? SlabType.TOP : SlabType.BOTTOM); - } - - @Override - @SuppressWarnings("deprecation") - public boolean canBeReplaced(BlockState state, BlockPlaceContext context) - { - if(context.getItemInHand().getItem() != this.asItem()) return false; - if(!context.replacingClickedOnBlock()) return true; - final Direction face = context.getClickedFace(); - final SlabType type = state.getValue(TYPE); - if((face == Direction.UP) && (type==SlabType.BOTTOM)) return true; - if((face == Direction.DOWN) && (type==SlabType.TOP)) return true; - if(!face.getAxis().isHorizontal()) return false; - final boolean isupper = ((context.getClickLocation().y() - context.getClickedPos().getY()) > 0.5); - return isupper ? (type==SlabType.BOTTOM) : (type==SlabType.TOP); - } - - @Override - @SuppressWarnings("deprecation") - public BlockState rotate(BlockState state, Rotation rot) - { return state; } - - @Override - @SuppressWarnings("deprecation") - public BlockState mirror(BlockState state, Mirror mirrorIn) - { return state; } - - @Override - public boolean hasDynamicDropList() - { return true; } - - @Override - public List dropList(BlockState state, Level world, BlockEntity te, boolean explosion) - { return new ArrayList<>(Collections.singletonList(new ItemStack(this.asItem(), num_slabs_contained_in_parts_[state.getValue(TYPE).ordinal() & 0x3]))); } - - @Override - @SuppressWarnings("deprecation") - public void attack(BlockState state, Level world, BlockPos pos, Player player) - { - if((world.isClientSide) || (!with_pickup)) return; - final ItemStack stack = player.getMainHandItem(); - if(stack.isEmpty() || (Block.byItem(stack.getItem()) != this)) return; - if(stack.getCount() >= stack.getMaxStackSize()) return; - Vec3 lv = player.getLookAngle(); - Direction facing = Direction.getNearest((float)lv.x, (float)lv.y, (float)lv.z); - if((facing != Direction.UP) && (facing != Direction.DOWN)) return; - if(state.getBlock() != this) return; - SlabType type = state.getValue(TYPE); - if(facing == Direction.DOWN) { - if(type == SlabType.DOUBLE) { - world.setBlock(pos, state.setValue(TYPE, SlabType.BOTTOM), 3); - } else { - world.removeBlock(pos, false); - } - } else if(facing == Direction.UP) { - if(type == SlabType.DOUBLE) { - world.setBlock(pos, state.setValue(TYPE, SlabType.TOP), 3); - } else { - world.removeBlock(pos, false); - } - } - if(!player.isCreative()) { - stack.grow(1); - if(player.getInventory() != null) player.getInventory().setChanged(); - } - SoundType st = this.getSoundType(state, world, pos, null); - world.playSound(player, pos, st.getPlaceSound(), SoundSource.BLOCKS, (st.getVolume()+1f)/2.5f, 0.9f*st.getPitch()); - } - - @Override - public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) - { return (state.getValue(TYPE) != SlabType.DOUBLE) && super.placeLiquid(world, pos, state, fluidState); } - - @Override - public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) - { return (state.getValue(TYPE) != SlabType.DOUBLE) && super.canPlaceLiquid(world, pos, state, fluid); } - -} diff --git a/src/main/java/wile/engineersdecor/libmc/VariantWallBlock.java b/src/main/java/wile/engineersdecor/libmc/VariantWallBlock.java deleted file mode 100644 index 889cfea..0000000 --- a/src/main/java/wile/engineersdecor/libmc/VariantWallBlock.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * @file VariantWallBlock.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2020 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Wall blocks. - */ -package wile.engineersdecor.libmc; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.SpawnPlacements; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.FenceGateBlock; -import net.minecraft.world.level.block.WallBlock; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.*; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.PushReaction; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import javax.annotation.Nullable; -import java.util.List; -import java.util.Map; - - -public class VariantWallBlock extends WallBlock implements StandardBlocks.IStandardBlock -{ - public static final BooleanProperty UP = BlockStateProperties.UP; - public static final EnumProperty WALL_EAST = BlockStateProperties.EAST_WALL; - public static final EnumProperty WALL_NORTH = BlockStateProperties.NORTH_WALL; - public static final EnumProperty WALL_SOUTH = BlockStateProperties.SOUTH_WALL; - public static final EnumProperty WALL_WEST = BlockStateProperties.WEST_WALL; - public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; - public static final IntegerProperty TEXTURE_VARIANT = IntegerProperty.create("tvariant", 0, 7); - private final Map shape_voxels; - private final Map collision_shape_voxels; - private final long config; - - public VariantWallBlock(long config, BlockBehaviour.Properties builder) - { - super(builder); - shape_voxels = buildWallShapes(4, 16, 4, 0, 16, 16); - collision_shape_voxels = buildWallShapes(6, 16, 5, 0, 24, 24); - this.config = config; - } - - @Override - public long config() - { return config; } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, @Nullable BlockGetter world, List tooltip, TooltipFlag flag) - { Auxiliaries.Tooltip.addInformation(stack, world, tooltip, flag, true); } - - private static VoxelShape combinedShape(VoxelShape pole, WallSide height, VoxelShape low, VoxelShape high) - { - if(height == WallSide.TALL) return Shapes.or(pole, high); - if(height == WallSide.LOW) return Shapes.or(pole, low); - return pole; - } - - protected Map buildWallShapes(double pole_width, double pole_height, double side_width, double side_min_y, double side_max_low_y, double side_max_tall_y) - { - final double px0=8.0-pole_width, px1=8.0+pole_width, sx0=8.0-side_width, sx1=8.0+side_width; - VoxelShape vp = Block.box(px0, 0, px0, px1, pole_height, px1); - VoxelShape vs1 = Block.box(sx0, side_min_y, 0, sx1, side_max_low_y, sx1); - VoxelShape vs2 = Block.box(sx0, side_min_y, sx0, sx1, side_max_low_y, 16); - VoxelShape vs3 = Block.box(0, side_min_y, sx0, sx1, side_max_low_y, sx1); - VoxelShape vs4 = Block.box(sx0, side_min_y, sx0, 16, side_max_low_y, sx1); - VoxelShape vs5 = Block.box(sx0, side_min_y, 0, sx1, side_max_tall_y, sx1); - VoxelShape vs6 = Block.box(sx0, side_min_y, sx0, sx1, side_max_tall_y, 16); - VoxelShape vs7 = Block.box(0, side_min_y, sx0, sx1, side_max_tall_y, sx1); - VoxelShape vs8 = Block.box(sx0, side_min_y, sx0, 16, side_max_tall_y, sx1); - Builder builder = ImmutableMap.builder(); - for(Boolean up : UP.getPossibleValues()) { - for(WallSide wh_east : WALL_EAST.getPossibleValues()) { - for(WallSide wh_north : WALL_NORTH.getPossibleValues()) { - for(WallSide wh_west : WALL_WEST.getPossibleValues()) { - for(WallSide wh_south : WALL_SOUTH.getPossibleValues()) { - VoxelShape shape = Shapes.empty(); - shape = combinedShape(shape, wh_east, vs4, vs8); - shape = combinedShape(shape, wh_west, vs3, vs7); - shape = combinedShape(shape, wh_north, vs1, vs5); - shape = combinedShape(shape, wh_south, vs2, vs6); - if(up) shape = Shapes.or(shape, vp); - BlockState bs = defaultBlockState().setValue(UP, up) - .setValue(WALL_EAST, wh_east) - .setValue(WALL_NORTH, wh_north) - .setValue(WALL_WEST, wh_west) - .setValue(WALL_SOUTH, wh_south); - final VoxelShape tvs = shape; - TEXTURE_VARIANT.getPossibleValues().forEach((tv)->{ - builder.put(bs.setValue(TEXTURE_VARIANT, tv).setValue(WATERLOGGED, false), tvs); - builder.put(bs.setValue(TEXTURE_VARIANT, tv).setValue(WATERLOGGED, true), tvs); - }); - } - } - } - } - } - return builder.build(); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return shape_voxels.getOrDefault(state, Shapes.block()); } - - @Override - public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) - { return collision_shape_voxels.getOrDefault(state, Shapes.block()); } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { super.createBlockStateDefinition(builder); builder.add(TEXTURE_VARIANT); } - - protected boolean attachesTo(BlockState facingState, LevelReader world, BlockPos facingPos, Direction side) - { - final Block block = facingState.getBlock(); - if((block instanceof FenceGateBlock) || (block instanceof WallBlock)) return true; - final BlockState oppositeState = world.getBlockState(facingPos.relative(side, 2)); - if(!(oppositeState.getBlock() instanceof VariantWallBlock)) return false; - return facingState.isRedstoneConductor(world, facingPos) && Block.canSupportCenter(world, facingPos, side); - } - - protected WallSide selectWallHeight(LevelReader world, BlockPos pos, Direction direction) - { return WallSide.LOW; } - - public BlockState getStateForPlacement(BlockPlaceContext context) - { - LevelReader world = context.getLevel(); - BlockPos pos = context.getClickedPos(); - FluidState fs = context.getLevel().getFluidState(context.getClickedPos()); - boolean n = attachesTo(world.getBlockState(pos.north()), world, pos.north(), Direction.SOUTH); - boolean e = attachesTo(world.getBlockState(pos.east()), world, pos.east(), Direction.WEST); - boolean s = attachesTo(world.getBlockState(pos.south()), world, pos.south(), Direction.NORTH); - boolean w = attachesTo(world.getBlockState(pos.west()), world, pos.west(), Direction.EAST); - boolean not_straight = (!n || !s || e || w) && (n || s || !e || !w); - return defaultBlockState().setValue(UP, not_straight) - .setValue(WALL_NORTH, n ? selectWallHeight(world, pos, Direction.NORTH) : WallSide.NONE) - .setValue(WALL_EAST , e ? selectWallHeight(world, pos, Direction.EAST) : WallSide.NONE) - .setValue(WALL_SOUTH, s ? selectWallHeight(world, pos, Direction.SOUTH) : WallSide.NONE) - .setValue(WALL_WEST , w ? selectWallHeight(world, pos, Direction.WEST) : WallSide.NONE) - .setValue(WATERLOGGED, fs.getType()==Fluids.WATER); - } - - @Override - public BlockState updateShape(BlockState state, Direction side, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) - { - if(state.getValue(WATERLOGGED)) world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - if(side == Direction.DOWN) return super.updateShape(state, side, facingState, world, pos, facingPos); - boolean n = (side==Direction.NORTH) ? this.attachesTo(facingState, world, facingPos, side) : state.getValue(WALL_NORTH)!=WallSide.NONE; - boolean e = (side==Direction.EAST) ? this.attachesTo(facingState, world, facingPos, side) : state.getValue(WALL_EAST)!=WallSide.NONE; - boolean s = (side==Direction.SOUTH) ? this.attachesTo(facingState, world, facingPos, side) : state.getValue(WALL_SOUTH)!=WallSide.NONE; - boolean w = (side==Direction.WEST) ? this.attachesTo(facingState, world, facingPos, side) : state.getValue(WALL_WEST)!=WallSide.NONE; - boolean not_straight = (!n || !s || e || w) && (n || s || !e || !w); - return state.setValue(UP, not_straight) - .setValue(WALL_NORTH, n ? selectWallHeight(world, pos, Direction.NORTH) : WallSide.NONE) - .setValue(WALL_EAST , e ? selectWallHeight(world, pos, Direction.EAST) : WallSide.NONE) - .setValue(WALL_SOUTH, s ? selectWallHeight(world, pos, Direction.SOUTH) : WallSide.NONE) - .setValue(WALL_WEST , w ? selectWallHeight(world, pos, Direction.WEST) : WallSide.NONE) - .setValue(TEXTURE_VARIANT, ((int)Mth.getSeed(pos)) & 0x7); - } - - @Override - public boolean isValidSpawn(BlockState state, BlockGetter world, BlockPos pos, SpawnPlacements.Type type, @Nullable EntityType entityType) - { return false; } - - @Override - public boolean isPossibleToRespawnInThis() - { return false; } - - @Override - @SuppressWarnings("deprecation") - public PushReaction getPistonPushReaction(BlockState state) - { return PushReaction.NORMAL; } -} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index f60f843..a31a21f 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,31 +1,78 @@ -# @file mods.toml -# @spec TOML v0.5.0 (https://github.com/toml-lang/toml) -modLoader="javafml" -loaderVersion="[43,)" -issueTrackerURL="https://github.com/stfwi/engineers-decor/issues/" -license="MIT" +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="${loader_version_range}" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. +# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. +license="${mod_license}" +# A URL to refer people to when problems occur with this mod +#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory +# The modid of the mod +modId="${mod_id}" #mandatory +# The version number of the mod +version="${mod_version}" #mandatory +# A display name for the mod +displayName="${mod_name}" #mandatory +# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/ +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional +# A URL for the "homepage" for this mod, displayed in the mod UI +#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional +# A file name (in the root of the mod JAR) containing a logo for display +logoFile="logo.png" #optional -[[mods]] -modId="engineersdecor" -version="${file.jarVersion}" -displayName="Engineer's Decor" -description="Adds cosmetic blocks for the engineer's workshop, factory and home." -authors="wilechaote" -credits="BluSunrize, Damien Hazard, malte0811, et al., the Forge Smiths." -updateJSONURL="https://raw.githubusercontent.com/stfwi/engineers-decor/versions/forge-1.19.2.json" -displayURL="https://www.curseforge.com/minecraft/mc-mods/engineers-decor" -logoFile="logo.png" +# A text field displayed in the mod UI +#credits="" #optional +# A text field displayed in the mod UI +authors="${mod_authors}" #optional +credits="BluSunrize, Damien Hazard, malte0811, et al., the Forge Smiths. And of course wilechaote, the original author." +# Display Test controls the display for your mod in the server connection screen +# MATCH_VERSION means that your mod will cause a red X if the versions on client and server differ. This is the default behaviour and should be what you choose if you have server and client elements to your mod. +# IGNORE_SERVER_VERSION means that your mod will not cause a red X if it's present on the server but not on the client. This is what you should use if you're a server only mod. +# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component. +# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value. +# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself. +#displayTest="MATCH_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional) -[[dependencies.engineersdecor]] - modId="forge" - mandatory=true - versionRange="[43.0.16,)" - ordering="NONE" - side="BOTH" +# The description text for the mod (multi line!) (#mandatory) +description='''${mod_description}''' +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.${mod_id}]] #optional +# the modid of the dependency +modId="forge" #mandatory +# Does this dependency have to exist - if not, ordering below must be specified +mandatory=true #mandatory +# The version range of the dependency +versionRange="${neo_version_range}" #mandatory +# An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory +# BEFORE - This mod is loaded BEFORE the dependency +# AFTER - This mod is loaded AFTER the dependency +ordering="NONE" +# Side this dependency is applied on - BOTH, CLIENT, or SERVER +side="BOTH" +# Here's another dependency +[[dependencies.${mod_id}]] +modId="minecraft" +mandatory=true +# This version range declares a minimum of the current minecraft version up to but not including the next major version +versionRange="${minecraft_version_range}" +ordering="NONE" +side="BOTH" -[[dependencies.engineersdecor]] - modId="minecraft" - mandatory=true - versionRange="[1.19.2]" - ordering="NONE" - side="BOTH" +[[dependencies.${mod_id}]] +modId="libzontreck" +mandatory=true +versionRange="[1201.11,1201.12)" +ordering="NONE" +side="BOTH" +# Features are specific properties of the game environment, that you may want to declare you require. This example declares +# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't +# stop your mod loading on the server for example. +#[features.${mod_id}] +#openGLVersion="[3.2,)" diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index d28d739..69e7a59 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,8 +1,8 @@ { "pack": { - "description": "engineersdecor resources", - "pack_format": 9, - "forge:resource_pack_format": 9, - "forge:data_pack_format": 10 + "description": { + "text": "${mod_id} resources" + }, + "pack_format": 15 } }