From 232e2c9cd7e99d321c8e71d15142ef1189022e40 Mon Sep 17 00:00:00 2001 From: Up Date: Sun, 25 Feb 2024 03:31:37 +0100 Subject: [PATCH] add mod files --- .gitattributes | 5 + .gitignore | 28 +++ build.gradle | 206 ++++++++++++++++++ gradle.properties | 58 +++++ settings.gradle | 18 ++ .../dev/upcraft/coraltrees/CoralTreesMod.java | 38 ++++ .../coraltrees/block/CoroakFanBlock.java | 36 +++ .../coraltrees/block/CoroakWallFanBlock.java | 36 +++ .../block/WaterloggedSaplingBlock.java | 98 +++++++++ .../feature/CoralTreeConfiguration.java | 20 ++ .../coraltrees/feature/CoralTreeFeature.java | 62 ++++++ .../coraltrees/init/CoralTreeBlocks.java | 52 +++++ .../init/CoralTreeConfiguredFeatures.java | 19 ++ .../coraltrees/init/CoralTreeFeatures.java | 16 ++ .../coraltrees/init/CoralTreePlantTypes.java | 8 + .../CoralTreeStructureProcessorTypes.java | 15 ++ .../coraltrees/init/CoralTreeTags.java | 14 ++ .../coraltrees/structure/CoralTreeGrower.java | 37 ++++ .../structure/TreeGrowthProcessor.java | 40 ++++ .../structure/TreeStructureManager.java | 54 +++++ .../coraltrees/structure/TreeType.java | 21 ++ .../resources/META-INF/accesstransformer.cfg | 0 src/main/resources/META-INF/mods.toml | 69 ++++++ .../coraltrees/loot_tables/blocks/coroak.json | 135 ++++++++++++ .../loot_tables/blocks/coroak_fan.json | 30 +++ .../loot_tables/blocks/coroak_log.json | 20 ++ .../loot_tables/blocks/coroak_planks.json | 20 ++ .../loot_tables/blocks/coroak_sapling.json | 20 ++ .../loot_tables/blocks/coroak_wood.json | 20 ++ .../coraltrees/recipes/coroak_planks.json | 13 ++ .../coraltrees/tree/coroak/coroak_tree_1.nbt | Bin 0 -> 219 bytes .../coraltrees/tree/coroak/coroak_tree_2.nbt | Bin 0 -> 284 bytes .../coraltrees/tree/coroak/coroak_tree_3.nbt | Bin 0 -> 260 bytes .../coraltrees/tree/coroak/coroak_tree_4.nbt | Bin 0 -> 334 bytes .../coraltrees/tree/coroak/coroak_tree_5.nbt | Bin 0 -> 293 bytes .../coraltrees/tree/coroak/coroak_tree_6.nbt | Bin 0 -> 346 bytes .../coraltrees/tags/blocks/coral_blocks.json | 7 + .../coraltrees/tags/blocks/coroak_logs.json | 7 + .../tags/blocks/coroak_plantable.json | 10 + .../coraltrees/tags/items/coroak_logs.json | 7 + .../data/minecraft/tags/blocks/corals.json | 6 + .../data/minecraft/tags/blocks/leaves.json | 6 + .../minecraft/tags/blocks/logs_that_burn.json | 6 + .../minecraft/tags/blocks/mineable/hoe.json | 6 + .../tags/blocks/mineable/pickaxe.json | 6 + .../data/minecraft/tags/blocks/planks.json | 6 + .../data/minecraft/tags/blocks/saplings.json | 6 + .../tags/blocks/underwater_bonemeals.json | 6 + .../minecraft/tags/blocks/wall_corals.json | 6 + .../data/minecraft/tags/items/leaves.json | 6 + .../minecraft/tags/items/logs_that_burn.json | 6 + .../data/minecraft/tags/items/planks.json | 6 + .../data/minecraft/tags/items/saplings.json | 6 + src/main/resources/pack.mcmeta | 8 + 54 files changed, 1325 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 settings.gradle create mode 100644 src/main/java/dev/upcraft/coraltrees/CoralTreesMod.java create mode 100644 src/main/java/dev/upcraft/coraltrees/block/CoroakFanBlock.java create mode 100644 src/main/java/dev/upcraft/coraltrees/block/CoroakWallFanBlock.java create mode 100644 src/main/java/dev/upcraft/coraltrees/block/WaterloggedSaplingBlock.java create mode 100644 src/main/java/dev/upcraft/coraltrees/feature/CoralTreeConfiguration.java create mode 100644 src/main/java/dev/upcraft/coraltrees/feature/CoralTreeFeature.java create mode 100644 src/main/java/dev/upcraft/coraltrees/init/CoralTreeBlocks.java create mode 100644 src/main/java/dev/upcraft/coraltrees/init/CoralTreeConfiguredFeatures.java create mode 100644 src/main/java/dev/upcraft/coraltrees/init/CoralTreeFeatures.java create mode 100644 src/main/java/dev/upcraft/coraltrees/init/CoralTreePlantTypes.java create mode 100644 src/main/java/dev/upcraft/coraltrees/init/CoralTreeStructureProcessorTypes.java create mode 100644 src/main/java/dev/upcraft/coraltrees/init/CoralTreeTags.java create mode 100644 src/main/java/dev/upcraft/coraltrees/structure/CoralTreeGrower.java create mode 100644 src/main/java/dev/upcraft/coraltrees/structure/TreeGrowthProcessor.java create mode 100644 src/main/java/dev/upcraft/coraltrees/structure/TreeStructureManager.java create mode 100644 src/main/java/dev/upcraft/coraltrees/structure/TreeType.java create mode 100644 src/main/resources/META-INF/accesstransformer.cfg create mode 100644 src/main/resources/META-INF/mods.toml create mode 100644 src/main/resources/data/coraltrees/loot_tables/blocks/coroak.json create mode 100644 src/main/resources/data/coraltrees/loot_tables/blocks/coroak_fan.json create mode 100644 src/main/resources/data/coraltrees/loot_tables/blocks/coroak_log.json create mode 100644 src/main/resources/data/coraltrees/loot_tables/blocks/coroak_planks.json create mode 100644 src/main/resources/data/coraltrees/loot_tables/blocks/coroak_sapling.json create mode 100644 src/main/resources/data/coraltrees/loot_tables/blocks/coroak_wood.json create mode 100644 src/main/resources/data/coraltrees/recipes/coroak_planks.json create mode 100644 src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_1.nbt create mode 100644 src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_2.nbt create mode 100644 src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_3.nbt create mode 100644 src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_4.nbt create mode 100644 src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_5.nbt create mode 100644 src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_6.nbt create mode 100644 src/main/resources/data/coraltrees/tags/blocks/coral_blocks.json create mode 100644 src/main/resources/data/coraltrees/tags/blocks/coroak_logs.json create mode 100644 src/main/resources/data/coraltrees/tags/blocks/coroak_plantable.json create mode 100644 src/main/resources/data/coraltrees/tags/items/coroak_logs.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/corals.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/leaves.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/mineable/hoe.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/planks.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/saplings.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/underwater_bonemeals.json create mode 100644 src/main/resources/data/minecraft/tags/blocks/wall_corals.json create mode 100644 src/main/resources/data/minecraft/tags/items/leaves.json create mode 100644 src/main/resources/data/minecraft/tags/items/logs_that_burn.json create mode 100644 src/main/resources/data/minecraft/tags/items/planks.json create mode 100644 src/main/resources/data/minecraft/tags/items/saplings.json create mode 100644 src/main/resources/pack.mcmeta diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f811f6a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# Disable autocrlf on generated files, they always generate with LF +# Add any extra files or paths here to make git stop saying they +# are changed when only line endings change. +src/generated/**/.cache/cache text eol=lf +src/generated/**/*.json text eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..39bfcad --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +# gradle +build +.gradle + +# other +eclipse +run + +# Files from Forge MDK +forge*changelog.txt + +# Misc +Assets/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..28ab136 --- /dev/null +++ b/build.gradle @@ -0,0 +1,206 @@ +plugins { + id 'eclipse' + id 'idea' + id 'maven-publish' + id 'net.minecraftforge.gradle' version '[6.0,6.2)' + id 'org.parchmentmc.librarian.forgegradle' version '1.+' +} +def ENV = System.getenv() + +version = mod_version +group = mod_group_id +def artifactName = "${mod_name}-Forge-${minecraft_version}" + +base { + archivesName.set(artifactName) +} + +// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +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://github.com/ParchmentMC/Parchment/wiki/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.minecraftforge.net/en/latest/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') + + // 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' + + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', mod_id + + 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 + args '--nogui' + } + + // 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 { + // 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' + // } + + mavenCentral() +} + + +dependencies { + // 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.minecraftforge:forge:${minecraft_version}-${forge_version}" + +} +// This blocks 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.named('processResources', ProcessResources).configure { + var replaceProperties = [ + minecraft_version: minecraft_version, minecraft_version_range: minecraft_version_range, + forge_version: forge_version, forge_version_range: forge_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, + ] + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] + } +} + +// 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' +// } + +publishing { + publications { + register('mavenJava', MavenPublication) { + artifact jar + artifactId = artifactName + } + } + repositories { + if (ENV.MAVEN_UPLOAD_URL) { + maven { + url = ENV.MAVEN_UPLOAD_URL + credentials { + username = ENV.MAVEN_UPLOAD_USERNAME + password = ENV.MAVEN_UPLOAD_PASSWORD + } + } + } + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..2249e76 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,58 @@ +# 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 + +## Environment Properties + +# The Minecraft version must agree with the Forge version to get a valid artifact +minecraft_version=1.19.2 +# The Minecraft version range can use any release version of Minecraft as bounds. +# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly +# as they do not follow standard versioning conventions. +minecraft_version_range=[1.19.2] +# The Forge version must agree with the Minecraft version to get a valid artifact +forge_version=43.3.8 +# The Forge version range can use any version of Forge as bounds or match the loader version range +forge_version_range=[43,) +# The loader version range can only use the major version of Forge/FML as bounds +loader_version_range=[43,) +# 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=parchment +# The mapping version to query from the mapping channel. +# This must match the format required by the mapping channel. +mapping_version=2022.11.27-1.19.2 + + +## 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=coraltrees +# The human-readable display name for the mod. +mod_name=CoralTrees +# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. +mod_license=All Rights Reserved +# The mod version. See https://semver.org/ +mod_version=1.0.0 +# 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.upcraft.commissions.2024.02 +# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. +mod_authors=Up +# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. +mod_description=Underwater trees made of coral. diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..2f831f3 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = 'MinecraftForge' + url = 'https://maven.minecraftforge.net/' + } + maven { + url = 'https://maven.parchmentmc.org' + } + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} + +rootProject.name = 'CoralTrees' diff --git a/src/main/java/dev/upcraft/coraltrees/CoralTreesMod.java b/src/main/java/dev/upcraft/coraltrees/CoralTreesMod.java new file mode 100644 index 0000000..c4ac01b --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/CoralTreesMod.java @@ -0,0 +1,38 @@ +package dev.upcraft.coraltrees; + +import dev.upcraft.coraltrees.init.CoralTreeBlocks; +import dev.upcraft.coraltrees.init.CoralTreeConfiguredFeatures; +import dev.upcraft.coraltrees.init.CoralTreeFeatures; +import dev.upcraft.coraltrees.init.CoralTreeStructureProcessorTypes; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; + +@Mod(CoralTreesMod.MODID) +public class CoralTreesMod { + + public static final String MODID = "coraltrees"; + + public static final CreativeModeTab CREATIVE_TAB = new CreativeModeTab(MODID) { + @Override + public ItemStack makeIcon() { + return new ItemStack(CoralTreeBlocks.COROAK_SAPLING.get()); + } + }; + + public CoralTreesMod() { + var bus = FMLJavaModLoadingContext.get().getModEventBus(); + + CoralTreeBlocks.BLOCKS.register(bus); + CoralTreeBlocks.ITEMS.register(bus); + CoralTreeFeatures.FEATURES.register(bus); + CoralTreeConfiguredFeatures.FEATURES.register(bus); + CoralTreeStructureProcessorTypes.PROCESSOR_TYPES.register(bus); + } + + public static ResourceLocation id(String path) { + return new ResourceLocation(MODID, path); + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/block/CoroakFanBlock.java b/src/main/java/dev/upcraft/coraltrees/block/CoroakFanBlock.java new file mode 100644 index 0000000..7a463df --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/block/CoroakFanBlock.java @@ -0,0 +1,36 @@ +package dev.upcraft.coraltrees.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.BaseCoralFanBlock; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; + +public class CoroakFanBlock extends BaseCoralFanBlock { + + public CoroakFanBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) { + this.tryScheduleDieTick(pState, pLevel, pPos); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos) { + if (pFacing == Direction.DOWN && !pState.canSurvive(pLevel, pCurrentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { + this.tryScheduleDieTick(pState, pLevel, pCurrentPos); + if (pState.getValue(WATERLOGGED)) { + pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); + } + + return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/block/CoroakWallFanBlock.java b/src/main/java/dev/upcraft/coraltrees/block/CoroakWallFanBlock.java new file mode 100644 index 0000000..734a783 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/block/CoroakWallFanBlock.java @@ -0,0 +1,36 @@ +package dev.upcraft.coraltrees.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.BaseCoralWallFanBlock; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; + +public class CoroakWallFanBlock extends BaseCoralWallFanBlock { + + public CoroakWallFanBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) { + this.tryScheduleDieTick(pState, pLevel, pPos); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos) { + if (pFacing.getOpposite() == pState.getValue(FACING) && !pState.canSurvive(pLevel, pCurrentPos)) { + return Blocks.AIR.defaultBlockState(); + } else { + if (pState.getValue(WATERLOGGED)) { + pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); + } + + this.tryScheduleDieTick(pState, pLevel, pCurrentPos); + return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/block/WaterloggedSaplingBlock.java b/src/main/java/dev/upcraft/coraltrees/block/WaterloggedSaplingBlock.java new file mode 100644 index 0000000..b986e40 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/block/WaterloggedSaplingBlock.java @@ -0,0 +1,98 @@ +package dev.upcraft.coraltrees.block; + +import dev.upcraft.coraltrees.init.CoralTreePlantTypes; +import dev.upcraft.coraltrees.init.CoralTreeTags; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.RandomSource; +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.SaplingBlock; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.block.grower.AbstractTreeGrower; +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.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraftforge.common.PlantType; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.Nullable; + +public class WaterloggedSaplingBlock extends SaplingBlock implements SimpleWaterloggedBlock { + + private static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; + + public WaterloggedSaplingBlock(AbstractTreeGrower pTreeGrower, Properties pProperties) { + super(pTreeGrower, pProperties); + this.registerDefaultState(this.stateDefinition.any().setValue(STAGE, 0).setValue(WATERLOGGED, false)); + } + + @Override + protected boolean mayPlaceOn(BlockState pState, BlockGetter pLevel, BlockPos pPos) { + return pState.is(CoralTreeTags.Blocks.COROAK_PLANTABLE); + } + + @Override + public void randomTick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + // only grow if waterlogged, but ignore light level + if (pState.getValue(WATERLOGGED) && pRandom.nextFloat() < 0.14) { + this.advanceTree(pLevel, pPos, pState, pRandom); + } + } + + @Override + public boolean canBeReplaced(BlockState pState, Fluid pFluid) { + return !ForgeRegistries.FLUIDS.tags().getTag(FluidTags.WATER).contains(pFluid); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder pBuilder) { + super.createBlockStateDefinition(pBuilder); + pBuilder.add(WATERLOGGED); + } + + @Override + public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { + BlockPos blockpos = pPos.below(); + return pLevel.getBlockState(blockpos).isFaceSturdy(pLevel, blockpos, Direction.UP); + } + + @Nullable + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + FluidState fluidstate = pContext.getLevel().getFluidState(pContext.getClickedPos()); + return super.getStateForPlacement(pContext).setValue(WATERLOGGED, fluidstate.is(FluidTags.WATER)); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pFacingPos) { + if (pState.getValue(WATERLOGGED)) { + pLevel.scheduleTick(pCurrentPos, Fluids.WATER, Fluids.WATER.getTickDelay(pLevel)); + } + + return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return pState.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(pState); + } + + @Override + public PlantType getPlantType(BlockGetter level, BlockPos pos) { + return CoralTreePlantTypes.CORAL; + } + + @Override + public boolean isValidBonemealTarget(BlockGetter pLevel, BlockPos pPos, BlockState pState, boolean pIsClient) { + return pState.getValue(WATERLOGGED); + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/feature/CoralTreeConfiguration.java b/src/main/java/dev/upcraft/coraltrees/feature/CoralTreeConfiguration.java new file mode 100644 index 0000000..4f7eaa5 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/feature/CoralTreeConfiguration.java @@ -0,0 +1,20 @@ +package dev.upcraft.coraltrees.feature; + +import com.mojang.serialization.Codec; +import dev.upcraft.coraltrees.structure.TreeType; +import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; + +public class CoralTreeConfiguration implements FeatureConfiguration { + + private final TreeType type; + + public static final Codec CODEC = TreeType.CODEC.fieldOf("type").xmap(CoralTreeConfiguration::new, CoralTreeConfiguration::getTreeType).codec(); + + public CoralTreeConfiguration(TreeType type) { + this.type = type; + } + + public TreeType getTreeType() { + return type; + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/feature/CoralTreeFeature.java b/src/main/java/dev/upcraft/coraltrees/feature/CoralTreeFeature.java new file mode 100644 index 0000000..015c34d --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/feature/CoralTreeFeature.java @@ -0,0 +1,62 @@ +package dev.upcraft.coraltrees.feature; + +import com.mojang.logging.LogUtils; +import com.mojang.serialization.Codec; +import dev.upcraft.coraltrees.structure.TreeGrowthProcessor; +import dev.upcraft.coraltrees.structure.TreeStructureManager; +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import org.slf4j.Logger; + +public class CoralTreeFeature extends Feature { + + private static final Logger LOGGER = LogUtils.getLogger(); + + // copied from TreeFeature + private static final int BLOCK_UPDATE_FLAGS = 19; + + public CoralTreeFeature(Codec pCodec) { + super(pCodec); + } + + @Override + public boolean place(FeaturePlaceContext ctx) { + var treeType = ctx.config().getTreeType(); + + var structures = TreeStructureManager.getInstance().getStructures(treeType); + if (structures.isEmpty()) { + LOGGER.warn("No structures found for tree type {}!", treeType); + return false; + } + + var randomId = structures.get(ctx.random().nextInt(structures.size())); + var template = ctx.level().getLevel().getStructureManager().getOrCreate(randomId); + + var size = template.getSize(); + // integer division is fine here because it is 0-indexed and the templates are usually odd-sized + var centerRelative = new BlockPos(size.getX() / 2, 0, size.getZ() / 2); + + var placementSettings = new StructurePlaceSettings() + .setRandom(ctx.random()) + .setKeepLiquids(true) + .setRotationPivot(centerRelative) + .setRotation(Rotation.getRandom(ctx.random())) + .addProcessor(new TreeGrowthProcessor()); + + var templateOrigin = ctx.origin().offset(-centerRelative.getX(), 0, -centerRelative.getZ()); + + var result = template.placeInWorld(ctx.level(), templateOrigin, templateOrigin, placementSettings, ctx.random(), BLOCK_UPDATE_FLAGS); + if(!result) { + LOGGER.error("Failed to place structure at [{}, {}, {}]", ctx.origin().getX(), ctx.origin().getY(), ctx.origin().getZ()); + } + else { + ctx.level().playSound(null, ctx.origin(), SoundEvents.CORAL_BLOCK_PLACE, SoundSource.BLOCKS, 0.8F + (float) (ctx.level().getRandom().nextGaussian() * 0.5D), 0.7F + (float) (ctx.level().getRandom().nextGaussian() * 0.5D)); + } + return result; + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/init/CoralTreeBlocks.java b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeBlocks.java new file mode 100644 index 0000000..e90bef0 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeBlocks.java @@ -0,0 +1,52 @@ +package dev.upcraft.coraltrees.init; + +import dev.upcraft.coraltrees.CoralTreesMod; +import dev.upcraft.coraltrees.block.CoroakFanBlock; +import dev.upcraft.coraltrees.block.CoroakWallFanBlock; +import dev.upcraft.coraltrees.block.WaterloggedSaplingBlock; +import dev.upcraft.coraltrees.structure.CoralTreeGrower; +import dev.upcraft.coraltrees.structure.TreeType; +import net.minecraft.core.Direction; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.StandingAndWallBlockItem; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.RotatedPillarBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +import java.util.function.Supplier; + +public class CoralTreeBlocks { + + public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, CoralTreesMod.MODID); + public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, CoralTreesMod.MODID); + + private static RegistryObject register(String name, Supplier factory) { + return register(name, factory, true); + } + + private static RegistryObject register(String name, Supplier factory, boolean registerItem) { + var obj = BLOCKS.register(name, factory); + if (registerItem) { + ITEMS.register(name, () -> new BlockItem(obj.get(), new Item.Properties().tab(CoralTreesMod.CREATIVE_TAB))); + } + return obj; + } + + public static final RegistryObject COROAK_SAPLING = register("coroak_sapling", () -> new WaterloggedSaplingBlock(new CoralTreeGrower(TreeType.COROAK), BlockBehaviour.Properties.copy(Blocks.OAK_SAPLING))); + public static final RegistryObject COROAK_LOG = register("coroak_log", () -> new RotatedPillarBlock(BlockBehaviour.Properties.of(Material.WOOD, (state) -> state.getValue(RotatedPillarBlock.AXIS) == Direction.Axis.Y ? MaterialColor.WOOD : MaterialColor.TERRACOTTA_BROWN).strength(2.0F).sound(SoundType.CORAL_BLOCK))); + public static final RegistryObject COROAK_WOOD = register("coroak_wood", () -> new RotatedPillarBlock(BlockBehaviour.Properties.of(Material.WOOD, MaterialColor.WOOD).strength(2.0F).sound(SoundType.CORAL_BLOCK)), true); + public static final RegistryObject COROAK_LEAVES = register("coroak", () -> new Block(BlockBehaviour.Properties.of(Material.STONE, MaterialColor.TERRACOTTA_BROWN).strength(0.2F).isSuffocating((pState, pLevel, pPos) -> false).sound(SoundType.CORAL_BLOCK))); + public static final RegistryObject COROAK_PLANKS = register("coroak_planks", () -> new Block(BlockBehaviour.Properties.copy(Blocks.OAK_PLANKS).sound(SoundType.CORAL_BLOCK))); + public static final RegistryObject COROAK_FAN = register("coroak_fan", () -> new CoroakFanBlock(Block.Properties.copy(Blocks.BUBBLE_CORAL_FAN)), false); + public static final RegistryObject COROAK_WALL_FAN = register("coroak_wall_fan", () -> new CoroakWallFanBlock(Block.Properties.copy(Blocks.BUBBLE_CORAL_WALL_FAN).lootFrom(COROAK_FAN)), false); + + public static final RegistryObject COROAK_FAN_ITEM = ITEMS.register("coroak_fan", () -> new StandingAndWallBlockItem(COROAK_FAN.get(), COROAK_WALL_FAN.get(), new Item.Properties().tab(CoralTreesMod.CREATIVE_TAB))); +} diff --git a/src/main/java/dev/upcraft/coraltrees/init/CoralTreeConfiguredFeatures.java b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeConfiguredFeatures.java new file mode 100644 index 0000000..dd49933 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeConfiguredFeatures.java @@ -0,0 +1,19 @@ +package dev.upcraft.coraltrees.init; + +import dev.upcraft.coraltrees.CoralTreesMod; +import dev.upcraft.coraltrees.feature.CoralTreeConfiguration; +import dev.upcraft.coraltrees.structure.TreeType; +import net.minecraft.core.Registry; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraftforge.registries.DeferredRegister; + +public class CoralTreeConfiguredFeatures { + + public static final DeferredRegister> FEATURES = DeferredRegister.create(Registry.CONFIGURED_FEATURE_REGISTRY, CoralTreesMod.MODID); + + static { + for (var type : TreeType.values()) { + FEATURES.register("tree/" + type.getSerializedName(), () -> new ConfiguredFeature<>(CoralTreeFeatures.CORAL_TREE.get(), new CoralTreeConfiguration(type))); + } + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/init/CoralTreeFeatures.java b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeFeatures.java new file mode 100644 index 0000000..07e5d71 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeFeatures.java @@ -0,0 +1,16 @@ +package dev.upcraft.coraltrees.init; + +import dev.upcraft.coraltrees.CoralTreesMod; +import dev.upcraft.coraltrees.feature.CoralTreeConfiguration; +import dev.upcraft.coraltrees.feature.CoralTreeFeature; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class CoralTreeFeatures { + + public static final DeferredRegister> FEATURES = DeferredRegister.create(ForgeRegistries.FEATURES, CoralTreesMod.MODID); + + public static final RegistryObject CORAL_TREE = FEATURES.register("coral_tree", () -> new CoralTreeFeature(CoralTreeConfiguration.CODEC)); +} diff --git a/src/main/java/dev/upcraft/coraltrees/init/CoralTreePlantTypes.java b/src/main/java/dev/upcraft/coraltrees/init/CoralTreePlantTypes.java new file mode 100644 index 0000000..d066164 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/init/CoralTreePlantTypes.java @@ -0,0 +1,8 @@ +package dev.upcraft.coraltrees.init; + +import net.minecraftforge.common.PlantType; + +public class CoralTreePlantTypes { + + public static final PlantType CORAL = PlantType.get("coral"); +} diff --git a/src/main/java/dev/upcraft/coraltrees/init/CoralTreeStructureProcessorTypes.java b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeStructureProcessorTypes.java new file mode 100644 index 0000000..62d3f68 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeStructureProcessorTypes.java @@ -0,0 +1,15 @@ +package dev.upcraft.coraltrees.init; + +import dev.upcraft.coraltrees.CoralTreesMod; +import dev.upcraft.coraltrees.structure.TreeGrowthProcessor; +import net.minecraft.core.Registry; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.RegistryObject; + +public class CoralTreeStructureProcessorTypes { + + public static final DeferredRegister> PROCESSOR_TYPES = DeferredRegister.create(Registry.STRUCTURE_PROCESSOR_REGISTRY, CoralTreesMod.MODID); + + public static final RegistryObject> TREE_GROWTH_PROCESSOR = PROCESSOR_TYPES.register("tree_growth_processor", () -> () -> TreeGrowthProcessor.CODEC); +} diff --git a/src/main/java/dev/upcraft/coraltrees/init/CoralTreeTags.java b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeTags.java new file mode 100644 index 0000000..473ba7b --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/init/CoralTreeTags.java @@ -0,0 +1,14 @@ +package dev.upcraft.coraltrees.init; + +import dev.upcraft.coraltrees.CoralTreesMod; +import net.minecraft.core.Registry; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; + +public class CoralTreeTags { + + public static class Blocks { + + public static final TagKey COROAK_PLANTABLE = TagKey.create(Registry.BLOCK_REGISTRY, CoralTreesMod.id("coroak_plantable")); + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/structure/CoralTreeGrower.java b/src/main/java/dev/upcraft/coraltrees/structure/CoralTreeGrower.java new file mode 100644 index 0000000..d5f8348 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/structure/CoralTreeGrower.java @@ -0,0 +1,37 @@ +package dev.upcraft.coraltrees.structure; + +import dev.upcraft.coraltrees.CoralTreesMod; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.grower.AbstractTreeGrower; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import org.jetbrains.annotations.Nullable; + +public class CoralTreeGrower extends AbstractTreeGrower { + + private final TreeType type; + + public CoralTreeGrower(TreeType type) { + this.type = type; + } + + @Nullable + @Override + protected Holder> getConfiguredFeature(ServerLevel level, ChunkGenerator chunkGenerator, BlockPos pos, BlockState state, RandomSource random, boolean hasFlowers) { + var id = CoralTreesMod.id("tree/" + type.getSerializedName()); + var key = ResourceKey.create(Registry.CONFIGURED_FEATURE_REGISTRY, id); + return level.registryAccess().registryOrThrow(Registry.CONFIGURED_FEATURE_REGISTRY).getHolder(key).orElse(null); + } + + @Nullable + @Override + protected Holder> getConfiguredFeature(RandomSource pRandom, boolean pLargeHive) { + return null; + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/structure/TreeGrowthProcessor.java b/src/main/java/dev/upcraft/coraltrees/structure/TreeGrowthProcessor.java new file mode 100644 index 0000000..bf5ab54 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/structure/TreeGrowthProcessor.java @@ -0,0 +1,40 @@ +package dev.upcraft.coraltrees.structure; + +import com.mojang.serialization.Codec; +import dev.upcraft.coraltrees.init.CoralTreeStructureProcessorTypes; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.level.material.Material; +import org.jetbrains.annotations.Nullable; + +public class TreeGrowthProcessor extends StructureProcessor { + + public static Codec CODEC = Codec.unit(TreeGrowthProcessor::new); + + @Nullable + @Override + public StructureTemplate.StructureBlockInfo process(LevelReader level, BlockPos p_74141_, BlockPos p_74142_, StructureTemplate.StructureBlockInfo p_74143_, StructureTemplate.StructureBlockInfo absoluteBlockInfo, StructurePlaceSettings placeSettings, @Nullable StructureTemplate template) { + var existingState = level.getBlockState(absoluteBlockInfo.pos); + + if (existingState.isAir()) { + return absoluteBlockInfo; + } + + var material = existingState.getMaterial(); + + if (material.isReplaceable() || material == Material.AIR || material == Material.REPLACEABLE_PLANT || material == Material.REPLACEABLE_WATER_PLANT || material == Material.REPLACEABLE_FIREPROOF_PLANT) { + return absoluteBlockInfo; + } + + return null; + } + + @Override + protected StructureProcessorType getType() { + return CoralTreeStructureProcessorTypes.TREE_GROWTH_PROCESSOR.get(); + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/structure/TreeStructureManager.java b/src/main/java/dev/upcraft/coraltrees/structure/TreeStructureManager.java new file mode 100644 index 0000000..13364c5 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/structure/TreeStructureManager.java @@ -0,0 +1,54 @@ +package dev.upcraft.coraltrees.structure; + +import dev.upcraft.coraltrees.CoralTreesMod; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimplePreparableReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraftforge.event.AddReloadListenerEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +@Mod.EventBusSubscriber(modid = CoralTreesMod.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) +public class TreeStructureManager extends SimplePreparableReloadListener>> { + + private static final TreeStructureManager INSTANCE = new TreeStructureManager(); + private static final String RESOURCE_PATH = String.format("structures/%s/tree/", CoralTreesMod.MODID); + + private Map> treeStructures = Map.of(); + + @Override + protected Map> prepare(ResourceManager resourceManager, ProfilerFiller profiler) { + var map = new EnumMap>(TreeType.class); + + for (TreeType treeType : TreeType.values()) { + var treePath = RESOURCE_PATH + treeType.getSerializedName(); + var treeFiles = resourceManager.listResources(treePath, path -> path.getPath().endsWith(".nbt")).keySet(); + map.put(treeType, treeFiles.stream().map(loc -> new ResourceLocation(loc.getNamespace(), loc.getPath().substring("structures/".length(), loc.getPath().length() - ".nbt".length()))).toList()); + } + + return map; + } + + @Override + protected void apply(Map> data, ResourceManager resourceManager, ProfilerFiller profiler) { + treeStructures = data; + } + + public List getStructures(TreeType treeType) { + return treeStructures.get(treeType); + } + + public static TreeStructureManager getInstance() { + return INSTANCE; + } + + @SubscribeEvent + public static void onRegisterReloadListeners(AddReloadListenerEvent event) { + event.addListener(INSTANCE); + } +} diff --git a/src/main/java/dev/upcraft/coraltrees/structure/TreeType.java b/src/main/java/dev/upcraft/coraltrees/structure/TreeType.java new file mode 100644 index 0000000..6711ca0 --- /dev/null +++ b/src/main/java/dev/upcraft/coraltrees/structure/TreeType.java @@ -0,0 +1,21 @@ +package dev.upcraft.coraltrees.structure; + +import com.mojang.serialization.Codec; +import net.minecraft.util.StringRepresentable; + +public enum TreeType implements StringRepresentable { + COROAK("coroak"); + + private final String name; + + TreeType(String name) { + this.name = name; + } + + @Override + public String getSerializedName() { + return name; + } + + public static final Codec CODEC = StringRepresentable.fromEnum(TreeType::values); +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..eea1c42 --- /dev/null +++ b/src/main/resources/META-INF/mods.toml @@ -0,0 +1,69 @@ +# 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://mods.upcraft.dev/discord" #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="examplemod.png" #optional +# A text field displayed in the mod UI +#credits="" #optional +# A text field displayed in the mod UI +authors="${mod_authors}" #optional +# 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="IGNORE_SERVER_VERSION" # MATCH_VERSION is the default if nothing is specified (#optional) + +# The description text for the mod (multi line!) (#mandatory) +description=''' +${mod_description} + +For mod commissions contact Up on discord at https://mods.upcraft.dev/discord +''' + +# 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="${forge_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" diff --git a/src/main/resources/data/coraltrees/loot_tables/blocks/coroak.json b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak.json new file mode 100644 index 0000000..606158b --- /dev/null +++ b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak.json @@ -0,0 +1,135 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:alternative", + "terms": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "items": [ + "minecraft:shears" + ] + } + }, + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ] + } + ], + "name": "coraltrees:coroak" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:survives_explosion" + }, + { + "chances": [ + 0.05, + 0.0625, + 0.083333336, + 0.1 + ], + "condition": "minecraft:table_bonus", + "enchantment": "minecraft:fortune" + } + ], + "name": "coraltrees:coroak_sapling" + } + ] + } + ], + "rolls": 1.0 + }, + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:inverted", + "term": { + "condition": "minecraft:alternative", + "terms": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "items": [ + "minecraft:shears" + ] + } + }, + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "conditions": [ + { + "chances": [ + 0.02, + 0.022222223, + 0.025, + 0.033333335, + 0.1 + ], + "condition": "minecraft:table_bonus", + "enchantment": "minecraft:fortune" + } + ], + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 2.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + }, + { + "function": "minecraft:explosion_decay" + } + ], + "name": "minecraft:stick" + } + ], + "rolls": 1.0 + } + ] +} diff --git a/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_fan.json b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_fan.json new file mode 100644 index 0000000..7957c63 --- /dev/null +++ b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_fan.json @@ -0,0 +1,30 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "coraltrees:coroak_fan" + } + ], + "rolls": 1.0 + } + ] +} diff --git a/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_log.json b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_log.json new file mode 100644 index 0000000..86a0b7f --- /dev/null +++ b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_log.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "coraltrees:coroak_log" + } + ], + "rolls": 1.0 + } + ] +} diff --git a/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_planks.json b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_planks.json new file mode 100644 index 0000000..00fb30c --- /dev/null +++ b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_planks.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "coraltrees:coroak_planks" + } + ], + "rolls": 1.0 + } + ] +} diff --git a/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_sapling.json b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_sapling.json new file mode 100644 index 0000000..4364432 --- /dev/null +++ b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_sapling.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "coraltrees:coroak_sapling" + } + ], + "rolls": 1.0 + } + ] +} diff --git a/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_wood.json b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_wood.json new file mode 100644 index 0000000..53f41d8 --- /dev/null +++ b/src/main/resources/data/coraltrees/loot_tables/blocks/coroak_wood.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "coraltrees:coroak_wood" + } + ], + "rolls": 1.0 + } + ] +} diff --git a/src/main/resources/data/coraltrees/recipes/coroak_planks.json b/src/main/resources/data/coraltrees/recipes/coroak_planks.json new file mode 100644 index 0000000..e71eb78 --- /dev/null +++ b/src/main/resources/data/coraltrees/recipes/coroak_planks.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "group": "planks", + "ingredients": [ + { + "tag": "coraltrees:coroak_logs" + } + ], + "result": { + "count": 4, + "item": "coraltrees:coroak_planks" + } +} diff --git a/src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_1.nbt b/src/main/resources/data/coraltrees/structures/coraltrees/tree/coroak/coroak_tree_1.nbt new file mode 100644 index 0000000000000000000000000000000000000000..23c09c66b1609ebee232bf1192b1f9cc017fcb26 GIT binary patch literal 219 zcmV<103`n(iwFP!00000|BaGO3&JoAhTpE8Zc`8s{twTdJ&Px=Qb&;DTu0l3`s;0V z6Y*nfAS5MEk~h!-$RVt{5eE=F^)5opkx}iGQ)Ce=$LLV$@?;DDnC0M&wp~+#rzISz zb<$DW@yW0OhPB)~!+y+p%!*)!^aSTUb9jUvbX*U^x){Oq=}Ees5sVnPYe)}|&?Elb zK5k@1&QbU(Nr7T(bVDY5r3^w|lm)xOryF@DEJ|%;p1v`QmL9dD=Mq!X(=+lQb2Ua}rlz?tH9cKsYV#^g&BM|g7|hV{u%$;a z^z;mW3RClExG;;&qGt+$(v#Iqn4X+n$fYN33#CuSLwq1^AN4!oc5j`YgCp_}aclMA iWwvj>$2b3uW9h4%4*Hp#H}(iz-{T9{a0+>an z^AG~c2OVg>amla-hF2J#*$a7*Fn3_)tS;!+Bd|2iR44;{jGyg}Pl5_TE4NR?u zmp)51Z1qu{)$ER-|b%l4c=?x zlQ{k_&XF4{t(r2HnrsZ_VxeKU<*+M=)+{;Mh9*nU#5{`x&)F1|=PaQX#bI7c_~AjV zEzOd{H#9lXS6D0Tizj#%E1b|z?tMi#`5l~?pCVxnXWx4fc;4$lc6Lz8yp4}q9=5!&0QA8O7`j^@7_HoRMn*nC=kq;Ss z4`a~9UyKVH)vR>o9Iw4c@%uKCzEzr^{T5JDTOUnp6m(e%;FeAxR^P`ST z?Y@}l8~thJ(SkfiP`eS-W&h~UW^ps6MCA$9BgV(z7YgNx-NL%}DMEc9PaoVH;d_l)`;Y9gLX?}=VSre!d-*+7O4GISI} zM=^9XqlTHO)i5*L8tU0hHUt}gd18R!WpT4z;xDlSX-=bu=DaprKATSq_j|XPDJ<6d sr}fd9!`tLOF57p1wxO(eq7(((>`XAPcJZS-0^B~pH+HH$j>rc903zL|;Q#;t literal 0 HcmV?d00001 diff --git a/src/main/resources/data/coraltrees/tags/blocks/coral_blocks.json b/src/main/resources/data/coraltrees/tags/blocks/coral_blocks.json new file mode 100644 index 0000000..8b95752 --- /dev/null +++ b/src/main/resources/data/coraltrees/tags/blocks/coral_blocks.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_fan", + "coraltrees:coroak_wall_fan" + ] +} diff --git a/src/main/resources/data/coraltrees/tags/blocks/coroak_logs.json b/src/main/resources/data/coraltrees/tags/blocks/coroak_logs.json new file mode 100644 index 0000000..97da372 --- /dev/null +++ b/src/main/resources/data/coraltrees/tags/blocks/coroak_logs.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_log", + "coraltrees:coroak_wood" + ] +} diff --git a/src/main/resources/data/coraltrees/tags/blocks/coroak_plantable.json b/src/main/resources/data/coraltrees/tags/blocks/coroak_plantable.json new file mode 100644 index 0000000..1431d59 --- /dev/null +++ b/src/main/resources/data/coraltrees/tags/blocks/coroak_plantable.json @@ -0,0 +1,10 @@ +{ + "replace": false, + "values": [ + "#minecraft:dirt", + "#minecraft:sand", + "#minecraft:coral_blocks", + "#forge:gravel", + "minecraft:grass_block" + ] +} diff --git a/src/main/resources/data/coraltrees/tags/items/coroak_logs.json b/src/main/resources/data/coraltrees/tags/items/coroak_logs.json new file mode 100644 index 0000000..97da372 --- /dev/null +++ b/src/main/resources/data/coraltrees/tags/items/coroak_logs.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_log", + "coraltrees:coroak_wood" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/corals.json b/src/main/resources/data/minecraft/tags/blocks/corals.json new file mode 100644 index 0000000..6b13f39 --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/corals.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_fan" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/leaves.json b/src/main/resources/data/minecraft/tags/blocks/leaves.json new file mode 100644 index 0000000..29eb7ba --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/leaves.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json b/src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json new file mode 100644 index 0000000..1fded97 --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/logs_that_burn.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#coraltrees:coroak_logs" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/hoe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/hoe.json new file mode 100644 index 0000000..29eb7ba --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/mineable/hoe.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json new file mode 100644 index 0000000..2db54ce --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#coraltrees:coral_blocks" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/planks.json b/src/main/resources/data/minecraft/tags/blocks/planks.json new file mode 100644 index 0000000..f91803f --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/planks.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_planks" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/saplings.json b/src/main/resources/data/minecraft/tags/blocks/saplings.json new file mode 100644 index 0000000..298841b --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/saplings.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_sapling" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/underwater_bonemeals.json b/src/main/resources/data/minecraft/tags/blocks/underwater_bonemeals.json new file mode 100644 index 0000000..298841b --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/underwater_bonemeals.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_sapling" + ] +} diff --git a/src/main/resources/data/minecraft/tags/blocks/wall_corals.json b/src/main/resources/data/minecraft/tags/blocks/wall_corals.json new file mode 100644 index 0000000..0a66c02 --- /dev/null +++ b/src/main/resources/data/minecraft/tags/blocks/wall_corals.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_wall_fan" + ] +} diff --git a/src/main/resources/data/minecraft/tags/items/leaves.json b/src/main/resources/data/minecraft/tags/items/leaves.json new file mode 100644 index 0000000..29eb7ba --- /dev/null +++ b/src/main/resources/data/minecraft/tags/items/leaves.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak" + ] +} diff --git a/src/main/resources/data/minecraft/tags/items/logs_that_burn.json b/src/main/resources/data/minecraft/tags/items/logs_that_burn.json new file mode 100644 index 0000000..1fded97 --- /dev/null +++ b/src/main/resources/data/minecraft/tags/items/logs_that_burn.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "#coraltrees:coroak_logs" + ] +} diff --git a/src/main/resources/data/minecraft/tags/items/planks.json b/src/main/resources/data/minecraft/tags/items/planks.json new file mode 100644 index 0000000..f91803f --- /dev/null +++ b/src/main/resources/data/minecraft/tags/items/planks.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_planks" + ] +} diff --git a/src/main/resources/data/minecraft/tags/items/saplings.json b/src/main/resources/data/minecraft/tags/items/saplings.json new file mode 100644 index 0000000..298841b --- /dev/null +++ b/src/main/resources/data/minecraft/tags/items/saplings.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + "coraltrees:coroak_sapling" + ] +} diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..81a429d --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,8 @@ +{ + "pack": { + "description": "${mod_id} resources", + "pack_format": 9, + "forge:resource_pack_format": 9, + "forge:data_pack_format": 10 + } +}