Private
Public Access
1
0

28 Commits

Author SHA1 Message Date
1424988938 Merge pull request 'Release 1.16.5-v1.0.0' (#44) from 1.16.5/dev into 1.16.5/main
Reviewed-on: #44
2026-05-25 21:41:14 +00:00
1ed918cf34 Merge pull request '1.16.5/feat/42-backport' (#43) from 1.16.5/feat/42-backport into 1.16.5/dev
Reviewed-on: #43
2026-05-25 21:39:14 +00:00
e96cf26948 Made common config into a variable. 2026-05-25 22:38:51 +01:00
5228bea7b9 Optimized imports. 2026-05-25 22:33:21 +01:00
6cd3a35ac3 Stopped registering common and server configs as they are unused. 2026-05-25 22:31:32 +01:00
6df0ee4b21 Updated mod version. 2026-05-25 22:10:41 +01:00
5c4ff6fd4c Fixed bonemealing for bush block. 2026-05-25 22:04:59 +01:00
db57036375 Removed old files. 2026-05-25 21:57:40 +01:00
ad4efdc0ac Ported world generation features. 2026-05-25 21:57:14 +01:00
dc4684404c Generated new data. 2026-05-25 21:56:22 +01:00
9c582b2faa Fixed rendering of firefly bush. (Extra note: Bonemealing does not work) 2026-05-25 18:12:36 +01:00
26b258af04 Ported data generation. Fixed proxy and main class. 2026-05-25 18:04:37 +01:00
cb44ecc59b Porting configured features. 2026-05-25 17:20:01 +01:00
901b968bec Ported wandering villager trade. 2026-05-25 17:08:33 +01:00
bf4a6c40fc Ported creative mod tab. 2026-05-25 17:07:36 +01:00
8b472c8a95 Ported sounds. 2026-05-25 16:57:35 +01:00
239a759e3c Ported config. Adjusted particle color logic. 2026-05-25 16:52:54 +01:00
d860061a56 Ported particles. 2026-05-25 16:43:07 +01:00
33412dcf93 Ported ModItems and ModBlocks. Partially ported FireflyBushBlock. 2026-05-25 15:38:21 +01:00
0fb17e6834 Partially ported proxy class, need to revisit particles and items. 2026-05-25 14:56:02 +01:00
748653618a Updated logger deps. 2026-05-25 14:49:13 +01:00
5a43ec8475 Updated versions. 2026-05-25 14:45:25 +01:00
c531147712 Merge pull request 'Implemented wanderer trade for firefly bush.' (#41) from 1.20.1-feat-39-implement_wandering_trader_trade into 1.20.1
Reviewed-on: #41
2026-05-02 14:50:27 +00:00
2ac6cc363b Implemented wanderer trade for firefly bush. 2026-05-02 15:49:42 +01:00
00ba9d1488 Merge pull request '1.20.1-feat-38-implement_composting' (#40) from 1.20.1-feat-38-implement_composting into 1.20.1
Reviewed-on: #40
2026-05-02 14:39:34 +00:00
38b91f2f29 Bumped mod version number. 2026-05-02 15:36:31 +01:00
6d46ec7671 Adding firefly bush to compostable items. 2026-05-02 15:35:21 +01:00
71ffddec33 Moved BlockItem registration into ModItems in order to keep references for registered items. 2026-05-02 15:34:13 +01:00
48 changed files with 592 additions and 1086 deletions

BIN
assets/images/web/logo.png (Stored with Git LFS)

Binary file not shown.

View File

@ -1,191 +1,134 @@
plugins { buildscript {
id 'java-library' repositories {
id 'maven-publish' // These repositories are only for Gradle plugins, put any other repositories in the repository block further below
id 'net.neoforged.moddev' version '2.0.137' maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
id 'idea' mavenCentral()
}
dependencies {
classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT'
}
} }
tasks.named('wrapper', Wrapper).configure { plugins {
// Define wrapper values here so as to not have to always do so when updating gradlew.properties. id 'eclipse'
// Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with id 'idea'
// documentation attached on cursor hover of gradle classes and methods. However, this comes with increased id 'net.minecraftforge.gradle' version '[6.0.16,6.2)'
// file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards. id 'org.parchmentmc.librarian.forgegradle' version '1.+'
// (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`)
distributionType = Wrapper.DistributionType.BIN
} }
apply plugin: 'org.spongepowered.mixin'
group = mod_group_id group = mod_group_id
version = mod_version version = mod_version
repositories {
// Add here additional repositories if required by some of the dependencies below.
}
base { base {
archivesName = "${mod_id}-${minecraft_version}" archivesName = "${mod_id}-${minecraft_version}"
} }
java { java {
toolchain.languageVersion = JavaLanguageVersion.of(21) toolchain.languageVersion = JavaLanguageVersion.of(8)
} }
neoForge { minecraft {
// Specify the version of NeoForge to use. mappings channel: mapping_channel, version: "$mapping_version-$minecraft_version"
version = project.neo_version
parchment { copyIdeResources = true
mappingsVersion = project.parchment_mappings_version // generateRunFolders = true
minecraftVersion = project.parchment_minecraft_version // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // https://docs.minecraftforge.net/en/latest/advanced/accesstransformers/
}
// This line is optional. Access Transformers are automatically detected
// accessTransformers = project.files('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs { runs {
client { // applies to all the run configs below
client() configureEach {
workingDirectory project.file('run')
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces. property 'forge.logging.markers', 'REGISTRIES'
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id property 'forge.logging.console.level', 'debug'
mods {
"${mod_id}" {
source sourceSets.main
}
}
}
client {
property 'forge.enabledGameTestNamespaces', mod_id
} }
server { server {
server() property 'forge.enabledGameTestNamespaces', mod_id
programArgument '--nogui' args '--nogui'
systemProperty 'neoforge.enabledGameTestNamespaces', project.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 { gameTestServer {
type = "gameTestServer" property 'forge.enabledGameTestNamespaces', mod_id
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
} }
data { data {
data() workingDirectory project.file('run-data')
args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
// gameDirectory = project.file('run-data')
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
// applies to all the run configs above
configureEach {
// 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.
systemProperty '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
logLevel = org.slf4j.event.Level.DEBUG
}
}
mods {
// define mod <-> source bindings
// these are used to tell the game which sources are for which mod
// multi mod projects should define one per mod
"${mod_id}" {
sourceSet(sourceSets.main)
} }
} }
} }
// Include resources generated by data generators. mixin {
add sourceSets.main, "${mod_id}.refmap.json"
config "${mod_id}.mixins.json"
}
sourceSets.main.resources { sourceSets.main.resources {
srcDir 'src/generated/resources' srcDir 'src/generated/resources'
} }
// Sets up a dependency configuration called 'localRuntime'. repositories {
// This configuration should be used instead of 'runtimeOnly' to declare exclusiveContent {
// a dependency that will be present for runtime testing but that is forRepository {
// "optional", meaning it will not be pulled by dependents of this mod. maven {
configurations { name = "Modrinth"
runtimeClasspath.extendsFrom localRuntime url = "https://api.modrinth.com/maven"
}
}
forRepositories(fg.repository) // Only add this if you're using ForgeGradle, otherwise remove this line
filter {
includeGroup "maven.modrinth"
}
}
} }
dependencies { dependencies {
// Example optional mod dependency with JEI minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
// compileOnly "mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}"
// We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it
// localRuntime "mezz.jei:jei-${mc_version}-neoforge:${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 "blank:coolmod-${mc_version}:${coolmod_version}"
// Example mod dependency using a file as dependency
// implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar")
// Example project dependency using a sister or child project:
// implementation project(":myproject")
// For more info:
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.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]
// 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
]
inputs.properties replaceProperties inputs.properties replaceProperties
filesMatching(['META-INF/neoforge.mods.toml']) { filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) {
expand replaceProperties expand replaceProperties + [project: project]
} }
} }
// Example configuration to allow publishing using the maven-publish plugin tasks.named('jar', Jar).configure {
publishing { manifest {
publications { attributes(["Specification-Title" : mod_id,
register('mavenJava', MavenPublication) { "Specification-Vendor" : mod_authors,
from components.java "Specification-Version" : "1",
} "Implementation-Title" : project.name,
} "Implementation-Version" : project.jar.archiveVersion,
repositories { "Implementation-Vendor" : mod_authors,
maven { "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")])
url "file://${project.projectDir}/repo"
}
} }
finalizedBy 'reobfJar'
} }
tasks.withType(JavaCompile).configureEach { tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation options.encoding = 'UTF-8'
}
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
idea {
module {
downloadSources = true
downloadJavadoc = true
}
} }

View File

@ -1,23 +1,20 @@
org.gradle.jvmargs=-Xmx3G org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=true org.gradle.daemon=false
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
mod_id=firefly_bush_backport mod_id=firefly_bush_backport
mod_name=Firefly Bush Backport mod_name=Firefly Bush Backport
mod_license=All Rights Reserved mod_license=All Rights Reserved
mod_version=1.1.1 mod_version=1.0.0
mod_group_id=dev.micle mod_group_id=dev.micle
mod_authors=Micle mod_authors=Micle
mod_description=Firefly bush backport from 1.21.5. mod_description=Firefly bush backport from 1.21.5.
minecraft_version=1.21.1 minecraft_version=1.16.5
minecraft_version_range=[1.21.1,1.22) minecraft_version_range=[1.16.5,1.17)
neo_version=21.1.228 forge_version=36.2.42
neo_version_range=[21.1.228,21.2) forge_version_range=[36,)
loader_version_range=[1,) loader_version_range=[36,)
parchment_minecraft_version=1.21.1 mapping_channel=parchment
parchment_mappings_version=2024.11.17 mapping_version=2022.03.06

View File

@ -1,7 +1 @@
distributionBase=GRADLE_USER_HOME distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -10,7 +10,7 @@ pluginManagement {
} }
plugins { plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0' id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
} }
rootProject.name = "${mod_id}-${minecraft_version}" rootProject.name = "${mod_id}-${minecraft_version}"

View File

@ -1,6 +1,5 @@
{ {
"parent": "firefly_bush_backport:block/cross_emissive", "parent": "firefly_bush_backport:block/cross_emissive",
"render_type": "minecraft:cutout",
"textures": { "textures": {
"cross": "firefly_bush_backport:block/firefly_bush", "cross": "firefly_bush_backport:block/firefly_bush",
"cross_emissive": "firefly_bush_backport:block/firefly_bush_emissive" "cross_emissive": "firefly_bush_backport:block/firefly_bush_emissive"

View File

@ -1,5 +1,6 @@
{ {
"block.firefly_bush.idle": { "block.firefly_bush.idle": {
"subtitle": "sound.firefly_bush_backport.block.firefly_bush.idle",
"sounds": [ "sounds": [
{ {
"name": "firefly_bush_backport:block/firefly_bush/firefly_bush1", "name": "firefly_bush_backport:block/firefly_bush/firefly_bush1",
@ -49,7 +50,6 @@
"name": "firefly_bush_backport:block/firefly_bush/firefly_bush11", "name": "firefly_bush_backport:block/firefly_bush/firefly_bush11",
"volume": 4.0 "volume": 4.0
} }
], ]
"subtitle": "sound.firefly_bush_backport.block.firefly_bush.idle"
} }
} }

View File

@ -2,20 +2,18 @@
"type": "minecraft:block", "type": "minecraft:block",
"pools": [ "pools": [
{ {
"bonus_rolls": 0.0, "rolls": 1,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [ "entries": [
{ {
"type": "minecraft:item", "type": "minecraft:item",
"name": "firefly_bush_backport:firefly_bush" "name": "firefly_bush_backport:firefly_bush"
} }
], ],
"rolls": 1.0 "conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
} }
], ]
"random_sequence": "firefly_bush_backport:blocks/firefly_bush"
} }

View File

@ -1,6 +0,0 @@
{
"type": "neoforge:add_features",
"biomes": "#minecraft:is_overworld",
"features": "firefly_bush_backport:patch_firefly_bush_near_water",
"step": "vegetal_decoration"
}

View File

@ -1,6 +0,0 @@
{
"type": "neoforge:add_features",
"biomes": "#c:is_swamp",
"features": "firefly_bush_backport:patch_firefly_bush_near_water_swamp",
"step": "vegetal_decoration"
}

View File

@ -1,6 +0,0 @@
{
"type": "neoforge:add_features",
"biomes": "#c:is_swamp",
"features": "firefly_bush_backport:patch_firefly_bush_swamp",
"step": "vegetal_decoration"
}

View File

@ -1,6 +0,0 @@
{
"type": "neoforge:remove_features",
"biomes": "#c:is_swamp",
"features": "firefly_bush_backport:patch_firefly_bush_near_water",
"steps": "vegetal_decoration"
}

View File

@ -1,30 +0,0 @@
{
"type": "minecraft:random_patch",
"config": {
"feature": {
"feature": {
"type": "minecraft:simple_block",
"config": {
"to_place": {
"type": "minecraft:simple_state_provider",
"state": {
"Name": "firefly_bush_backport:firefly_bush"
}
}
}
},
"placement": [
{
"type": "minecraft:block_predicate_filter",
"predicate": {
"type": "minecraft:matching_blocks",
"blocks": "minecraft:air"
}
}
]
},
"tries": 20,
"xz_spread": 4,
"y_spread": 3
}
}

View File

@ -1,90 +0,0 @@
{
"feature": "firefly_bush_backport:patch_firefly_bush",
"placement": [
{
"type": "minecraft:count",
"count": 2
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:heightmap",
"heightmap": "MOTION_BLOCKING_NO_LEAVES"
},
{
"type": "minecraft:biome"
},
{
"type": "minecraft:block_predicate_filter",
"predicate": {
"type": "minecraft:all_of",
"predicates": [
{
"type": "minecraft:matching_blocks",
"blocks": "minecraft:air"
},
{
"type": "minecraft:would_survive",
"state": {
"Name": "firefly_bush_backport:firefly_bush"
}
},
{
"type": "minecraft:any_of",
"predicates": [
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
1,
-1,
0
]
},
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
-1,
-1,
0
]
},
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
0,
-1,
1
]
},
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
0,
-1,
-1
]
}
]
}
]
}
}
]
}

View File

@ -1,90 +0,0 @@
{
"feature": "firefly_bush_backport:patch_firefly_bush",
"placement": [
{
"type": "minecraft:count",
"count": 3
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:heightmap",
"heightmap": "MOTION_BLOCKING"
},
{
"type": "minecraft:biome"
},
{
"type": "minecraft:block_predicate_filter",
"predicate": {
"type": "minecraft:all_of",
"predicates": [
{
"type": "minecraft:matching_blocks",
"blocks": "minecraft:air"
},
{
"type": "minecraft:would_survive",
"state": {
"Name": "firefly_bush_backport:firefly_bush"
}
},
{
"type": "minecraft:any_of",
"predicates": [
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
1,
-1,
0
]
},
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
-1,
-1,
0
]
},
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
0,
-1,
1
]
},
{
"type": "minecraft:matching_fluids",
"fluids": [
"minecraft:water",
"minecraft:flowing_water"
],
"offset": [
0,
-1,
-1
]
}
]
}
]
}
}
]
}

View File

@ -1,19 +0,0 @@
{
"feature": "firefly_bush_backport:patch_firefly_bush",
"placement": [
{
"type": "minecraft:rarity_filter",
"chance": 8
},
{
"type": "minecraft:in_square"
},
{
"type": "minecraft:heightmap",
"heightmap": "MOTION_BLOCKING"
},
{
"type": "minecraft:biome"
}
]
}

View File

@ -1,5 +0,0 @@
{
"values": [
"firefly_bush_backport:firefly_bush"
]
}

View File

@ -1,7 +0,0 @@
{
"values": {
"firefly_bush_backport:firefly_bush": {
"chance": 0.3
}
}
}

View File

@ -1,48 +1,24 @@
package dev.micle.firefly_bush_backport; package dev.micle.firefly_bush_backport;
import com.mojang.logging.LogUtils;
import dev.micle.firefly_bush_backport.proxy.IProxy; import dev.micle.firefly_bush_backport.proxy.IProxy;
import dev.micle.firefly_bush_backport.proxy.Proxy; import dev.micle.firefly_bush_backport.proxy.Proxy;
import net.minecraft.resources.ResourceLocation; import net.minecraftforge.fml.DistExecutor;
import net.neoforged.api.distmarker.Dist; import net.minecraftforge.fml.common.Mod;
import net.neoforged.bus.api.IEventBus; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.neoforged.fml.ModContainer; import org.apache.logging.log4j.LogManager;
import net.neoforged.fml.ModList; import org.apache.logging.log4j.Logger;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLEnvironment;
import org.slf4j.Logger;
import java.util.Optional;
@Mod(FireflyBushBackport.MOD_ID) @Mod(FireflyBushBackport.MOD_ID)
public class FireflyBushBackport { public class FireflyBushBackport {
public static final String MOD_ID = "firefly_bush_backport"; public static final String MOD_ID = "firefly_bush_backport";
public static final Logger LOGGER = LogUtils.getLogger(); public static final Logger LOGGER = LogManager.getLogger(MOD_ID);
private static FMLJavaModLoadingContext fmlJavaModLoadingContext;
private static IProxy proxy; private static IProxy proxy;
public FireflyBushBackport(IEventBus modEventBus, ModContainer modContainer) { public FireflyBushBackport() {
proxy = FMLEnvironment.dist == Dist.CLIENT proxy = DistExecutor.safeRunForDist(
? new Proxy.Client(modEventBus, modContainer) () -> Proxy.Client::new,
: new Proxy.Server(modEventBus, modContainer); () -> Proxy.Server::new
} );
public static ResourceLocation createResourceLocation(String name) {
if (name.contains(":")) {
throw new IllegalArgumentException("Name contains namespace");
}
return ResourceLocation.fromNamespaceAndPath(MOD_ID, name);
}
public static String getVersion() {
Optional<? extends ModContainer> optional = ModList.get().getModContainerById(MOD_ID);
if (optional.isPresent()) {
return optional.get().getModInfo().getVersion().toString();
}
return "0.0.0";
}
public static IProxy getProxy() {
return proxy;
} }
} }

View File

@ -1,48 +1,42 @@
package dev.micle.firefly_bush_backport.block; package dev.micle.firefly_bush_backport.block;
import com.mojang.serialization.MapCodec;
import dev.micle.firefly_bush_backport.config.Config; import dev.micle.firefly_bush_backport.config.Config;
import dev.micle.firefly_bush_backport.particle.ModParticles; import dev.micle.firefly_bush_backport.particle.ModParticles;
import dev.micle.firefly_bush_backport.sound.ModSounds; import dev.micle.firefly_bush_backport.sound.ModSounds;
import net.minecraft.core.BlockPos; import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.core.Direction; import net.minecraft.block.BlockState;
import net.minecraft.server.level.ServerLevel; import net.minecraft.block.Blocks;
import net.minecraft.sounds.SoundSource; import net.minecraft.block.BushBlock;
import net.minecraft.util.RandomSource; import net.minecraft.block.IGrowable;
import net.minecraft.world.level.Level; import net.minecraft.util.Direction;
import net.minecraft.world.level.LevelReader; import net.minecraft.util.SoundCategory;
import net.minecraft.world.level.block.BonemealableBlock; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.BushBlock; import net.minecraft.world.IBlockReader;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.IWorldReader;
import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.World;
import org.jetbrains.annotations.NotNull; import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.server.ServerWorld;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;
public class FireflyBushBlock extends BushBlock implements BonemealableBlock { public class FireflyBushBlock extends BushBlock implements IGrowable {
public static final MapCodec<FireflyBushBlock> CODEC = simpleCodec(FireflyBushBlock::new);
public FireflyBushBlock(Properties properties) { public FireflyBushBlock(Properties properties) {
super(properties); super(properties);
} }
@Override
@NotNull
protected MapCodec<? extends BushBlock> codec() {
return CODEC;
}
@Override @Override
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public void animateTick(BlockState blockState, Level level, BlockPos blockPos, RandomSource randomSource) { public void animateTick(BlockState blockState, World level, BlockPos blockPos, Random randomSource) {
if (randomSource.nextInt(Config.Client.bushFireflyAmbientSoundChanceOneIn.get()) == 0 && ( if (randomSource.nextInt(Config.Client.bushFireflyAmbientSoundChanceOneIn.get()) == 0 && (
Config.Client.bushExtraAlwaysPlayAmbientSound.get() || Config.Client.bushExtraAlwaysPlayAmbientSound.get() ||
(isMoonVisible(level) && level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos.getX(), blockPos.getZ()) <= blockPos.getY()) (isMoonVisible(level) && level.getHeight(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, blockPos.getX(), blockPos.getZ()) <= blockPos.getY())
)) { )) {
level.playLocalSound( level.playLocalSound(
blockPos, ModSounds.FIREFLY_BUSH_IDLE.get(), SoundSource.AMBIENT, 1.0F, 1.0F, false blockPos.getX(), blockPos.getY(), blockPos.getZ(), ModSounds.FIREFLY_BUSH_IDLE.get(), SoundCategory.AMBIENT, 1.0F, 1.0F, false
); );
} }
@ -57,7 +51,7 @@ public class FireflyBushBlock extends BushBlock implements BonemealableBlock {
} }
} }
public boolean isMoonVisible(Level level) { public boolean isMoonVisible(World level) {
if (!level.dimensionType().natural()) { if (!level.dimensionType().natural()) {
return false; return false;
} else { } else {
@ -68,37 +62,47 @@ public class FireflyBushBlock extends BushBlock implements BonemealableBlock {
@Override @Override
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public boolean isValidBonemealTarget(LevelReader level, BlockPos blockPos, BlockState blockState) { public boolean isValidBonemealTarget(IBlockReader level, BlockPos blockPos, BlockState blockState, boolean isClient) {
return hasSpreadableNeighbourPos(level, blockPos, blockState); return hasSpreadableNeighbourPos(level, blockPos, blockState);
} }
@Override @Override
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public boolean isBonemealSuccess(Level level, RandomSource randomSource, BlockPos blockPos, BlockState blockState) { public boolean isBonemealSuccess(World level, Random randomSource, BlockPos blockPos, BlockState blockState) {
return true; return true;
} }
@Override @Override
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public void performBonemeal(ServerLevel level, RandomSource randomSource, BlockPos blockPos, BlockState blockState) { public void performBonemeal(ServerWorld level, Random randomSource, BlockPos blockPos, BlockState blockState) {
findSpreadableNeighbourPos(level, blockPos, blockState).ifPresent(x -> level.setBlockAndUpdate(x, this.defaultBlockState())); findSpreadableNeighbourPos(level, blockPos, blockState).ifPresent(x -> level.setBlockAndUpdate(x, this.defaultBlockState()));
} }
static boolean hasSpreadableNeighbourPos(LevelReader levelReader, BlockPos blockPos, BlockState blockState) { private static boolean hasSpreadableNeighbourPos(IBlockReader levelReader, BlockPos blockPos, BlockState blockState) {
return getSpreadableNeighbourPos(Direction.Plane.HORIZONTAL.stream().toList(), levelReader, blockPos, blockState).isPresent(); return getSpreadableNeighbourPos(Direction.Plane.HORIZONTAL.stream().collect(Collectors.toList()), levelReader, blockPos, blockState).isPresent();
} }
static Optional<BlockPos> findSpreadableNeighbourPos(Level level, BlockPos blockPos, BlockState blockState) { private static Optional<BlockPos> findSpreadableNeighbourPos(World level, BlockPos blockPos, BlockState blockState) {
return getSpreadableNeighbourPos(Direction.Plane.HORIZONTAL.shuffledCopy(level.random), level, blockPos, blockState); return getSpreadableNeighbourPos(shuffledCopy(Direction.Plane.HORIZONTAL.stream().toArray(Direction[]::new), level.random), level, blockPos, blockState);
} }
static Optional<BlockPos> getSpreadableNeighbourPos(List<Direction> directions, LevelReader levelReader, BlockPos blockPos, BlockState blockState) { private static Optional<BlockPos> getSpreadableNeighbourPos(List<Direction> directions, IBlockReader levelReader, BlockPos blockPos, BlockState blockState) {
for (Direction direction : directions) { for (Direction direction : directions) {
BlockPos blockPosDirection = blockPos.relative(direction); BlockPos blockPosDirection = blockPos.relative(direction);
if (levelReader.isEmptyBlock(blockPosDirection) && blockState.canSurvive(levelReader, blockPosDirection)) { if (levelReader.getBlockState(blockPosDirection).is(Blocks.AIR) && blockState.canSurvive((IWorldReader) levelReader, blockPosDirection)) {
return Optional.of(blockPosDirection); return Optional.of(blockPosDirection);
} }
} }
return Optional.empty(); return Optional.empty();
} }
private static <T> List<T> shuffledCopy(T[] array, Random random) {
ObjectArrayList<T> objectArrayList = new ObjectArrayList<>(array);
int i = objectArrayList.size();
for (int j = i; j > 1; --j) {
int k = random.nextInt(j);
objectArrayList.set(j - 1, objectArrayList.set(k, objectArrayList.get(j - 1)));
}
return objectArrayList;
}
} }

View File

@ -1,27 +1,25 @@
package dev.micle.firefly_bush_backport.block; package dev.micle.firefly_bush_backport.block;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.world.level.block.Block; import net.minecraft.block.AbstractBlock;
import net.minecraft.world.level.block.SoundType; import net.minecraft.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.block.SoundType;
import net.minecraft.world.level.material.MapColor; import net.minecraft.block.material.Material;
import net.minecraft.world.level.material.PushReaction; import net.minecraft.block.material.MaterialColor;
import net.neoforged.bus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredHolder; import net.minecraftforge.fml.RegistryObject;
import net.neoforged.neoforge.registries.DeferredRegister; import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
public class ModBlocks { public class ModBlocks {
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.createBlocks(FireflyBushBackport.MOD_ID); public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, FireflyBushBackport.MOD_ID);
public static DeferredHolder<Block, FireflyBushBlock> FIREFLY_BUSH = BLOCKS.register("firefly_bush", public static RegistryObject<Block> FIREFLY_BUSH = BLOCKS.register("firefly_bush",
() -> new FireflyBushBlock(BlockBehaviour.Properties.of() () -> new FireflyBushBlock(AbstractBlock.Properties.of(Material.PLANT, MaterialColor.PLANT)
.mapColor(MapColor.PLANT)
.ignitedByLava()
.lightLevel(blockState -> 2) .lightLevel(blockState -> 2)
.noCollission() .noCollission()
.instabreak() .instabreak()
.sound(SoundType.SWEET_BERRY_BUSH) .sound(SoundType.SWEET_BERRY_BUSH))
.pushReaction(PushReaction.DESTROY))
); );
public static void register(IEventBus modEventBus) { public static void register(IEventBus modEventBus) {

View File

@ -1,50 +1,48 @@
package dev.micle.firefly_bush_backport.config; package dev.micle.firefly_bush_backport.config;
import net.minecraft.util.random.SimpleWeightedRandomList; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.world.level.Level; import net.minecraft.util.WeightedList;
import net.neoforged.bus.api.IEventBus; import net.minecraftforge.common.ForgeConfigSpec;
import net.neoforged.bus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer; import net.minecraftforge.fml.ModLoadingContext;
import net.neoforged.fml.config.ModConfig; import net.minecraftforge.fml.common.Mod;
import net.neoforged.fml.event.config.ModConfigEvent; import net.minecraftforge.fml.config.ModConfig;
import net.neoforged.neoforge.common.ModConfigSpec;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.awt.*; import java.awt.*;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Mod.EventBusSubscriber(modid = FireflyBushBackport.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public final class Config { public final class Config {
public static final Client CLIENT; public static final Client CLIENT;
public static final ModConfigSpec CLIENT_SPEC; public static final ForgeConfigSpec CLIENT_SPEC;
public static final Common COMMON; public static final Common COMMON;
public static final ModConfigSpec COMMON_SPEC; public static final ForgeConfigSpec COMMON_SPEC;
public static final Server SERVER; public static final Server SERVER;
public static final ModConfigSpec SERVER_SPEC; public static final ForgeConfigSpec SERVER_SPEC;
static { static {
Pair<Client, ModConfigSpec> clientSpecPair = new ModConfigSpec.Builder().configure(Client::new); Pair<Client, ForgeConfigSpec> clientSpecPair = new ForgeConfigSpec.Builder().configure(Client::new);
CLIENT = clientSpecPair.getLeft(); CLIENT = clientSpecPair.getLeft();
CLIENT_SPEC = clientSpecPair.getRight(); CLIENT_SPEC = clientSpecPair.getRight();
Pair<Common, ModConfigSpec> commonSpecPair = new ModConfigSpec.Builder().configure(Common::new); Pair<Common, ForgeConfigSpec> commonSpecPair = new ForgeConfigSpec.Builder().configure(Common::new);
COMMON = commonSpecPair.getLeft(); COMMON = commonSpecPair.getLeft();
COMMON_SPEC = commonSpecPair.getRight(); COMMON_SPEC = commonSpecPair.getRight();
Pair<Server, ModConfigSpec> serverSpecPair = new ModConfigSpec.Builder().configure(Server::new); Pair<Server, ForgeConfigSpec> serverSpecPair = new ForgeConfigSpec.Builder().configure(Server::new);
SERVER = serverSpecPair.getLeft(); SERVER = serverSpecPair.getLeft();
SERVER_SPEC = serverSpecPair.getRight(); SERVER_SPEC = serverSpecPair.getRight();
} }
public static void register(IEventBus modEventBus, ModContainer modContainer) { public static void register() {
modContainer.registerConfig(ModConfig.Type.CLIENT, CLIENT_SPEC); ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, CLIENT_SPEC);
modContainer.registerConfig(ModConfig.Type.COMMON, COMMON_SPEC);
modContainer.registerConfig(ModConfig.Type.SERVER, SERVER_SPEC);
modEventBus.addListener(Config::onConfigReloadEvent);
} }
@SubscribeEvent @SubscribeEvent
public static void onConfigReloadEvent(ModConfigEvent event) { public static void onConfigReloadEvent(ModConfig.ModConfigEvent event) {
if (event.getConfig().getSpec() == CLIENT_SPEC) { if (event.getConfig().getSpec() == CLIENT_SPEC) {
Client.onConfigReload(); Client.onConfigReload();
} else if (event.getConfig().getSpec() == COMMON_SPEC) { } else if (event.getConfig().getSpec() == COMMON_SPEC) {
@ -55,29 +53,29 @@ public final class Config {
} }
public static class Client { public static class Client {
public static ModConfigSpec.DoubleValue bushFireflyChancePerTick; public static ForgeConfigSpec.DoubleValue bushFireflyChancePerTick;
public static ModConfigSpec.DoubleValue bushFireflyHorizontalRange; public static ForgeConfigSpec.DoubleValue bushFireflyHorizontalRange;
public static ModConfigSpec.DoubleValue bushFireflyVerticalRange; public static ForgeConfigSpec.DoubleValue bushFireflyVerticalRange;
public static ModConfigSpec.IntValue bushFireflySpawnMaxBrightnessLevel; public static ForgeConfigSpec.IntValue bushFireflySpawnMaxBrightnessLevel;
public static ModConfigSpec.IntValue bushFireflyAmbientSoundChanceOneIn; public static ForgeConfigSpec.IntValue bushFireflyAmbientSoundChanceOneIn;
public static ModConfigSpec.BooleanValue bushExtraAlwaysPlayAmbientSound; public static ForgeConfigSpec.BooleanValue bushExtraAlwaysPlayAmbientSound;
public static ModConfigSpec.BooleanValue bushExtraAlwaysSpawnParticles; public static ForgeConfigSpec.BooleanValue bushExtraAlwaysSpawnParticles;
public static ModConfigSpec.DoubleValue particleFadeOutLightTime; public static ForgeConfigSpec.DoubleValue particleFadeOutLightTime;
public static ModConfigSpec.DoubleValue particleFadeInLightTime; public static ForgeConfigSpec.DoubleValue particleFadeInLightTime;
public static ModConfigSpec.DoubleValue particleFadeOutAlphaTime; public static ForgeConfigSpec.DoubleValue particleFadeOutAlphaTime;
public static ModConfigSpec.DoubleValue particleFadeInAlphaTime; public static ForgeConfigSpec.DoubleValue particleFadeInAlphaTime;
public static ModConfigSpec.IntValue particleMinLifetime; public static ForgeConfigSpec.IntValue particleMinLifetime;
public static ModConfigSpec.IntValue particleMaxLifetime; public static ForgeConfigSpec.IntValue particleMaxLifetime;
public static ModConfigSpec.DoubleValue particleExtraFriction; public static ForgeConfigSpec.DoubleValue particleExtraFriction;
public static ModConfigSpec.DoubleValue particleExtraScale; public static ForgeConfigSpec.DoubleValue particleExtraScale;
public static ModConfigSpec.DoubleValue particleExtraBrightness; public static ForgeConfigSpec.DoubleValue particleExtraBrightness;
private static ModConfigSpec.ConfigValue<List<? extends String>> particleExtraColors; private static ForgeConfigSpec.ConfigValue<List<? extends String>> particleExtraColors;
public static SimpleWeightedRandomList<Color> particleExtraColorsWeightedList; public static WeightedList<Color> particleExtraColorsWeightedList;
Client(ModConfigSpec.Builder builder) { Client(ForgeConfigSpec.Builder builder) {
builder.comment("Settings for the firefly bush.").push("bush"); builder.comment("Settings for the firefly bush.").push("bush");
bushFireflyChancePerTick = builder bushFireflyChancePerTick = builder
.defineInRange("bushFireflyChancePerTick", 0.7, 0, 1); .defineInRange("bushFireflyChancePerTick", 0.7, 0, 1);
@ -86,7 +84,7 @@ public final class Config {
bushFireflyVerticalRange = builder bushFireflyVerticalRange = builder
.defineInRange("bushFireflyVerticalRange", 5.0, 0, Double.MAX_VALUE); .defineInRange("bushFireflyVerticalRange", 5.0, 0, Double.MAX_VALUE);
bushFireflySpawnMaxBrightnessLevel = builder bushFireflySpawnMaxBrightnessLevel = builder
.defineInRange("bushFireflySpawnMaxBrightnessLevel", 13, 0, Level.MAX_BRIGHTNESS); .defineInRange("bushFireflySpawnMaxBrightnessLevel", 13, 0, 15);
bushFireflyAmbientSoundChanceOneIn = builder bushFireflyAmbientSoundChanceOneIn = builder
.defineInRange("bushFireflyAmbientSoundChanceOneIn", 30, 0, Integer.MAX_VALUE); .defineInRange("bushFireflyAmbientSoundChanceOneIn", 30, 0, Integer.MAX_VALUE);
@ -121,37 +119,32 @@ public final class Config {
.defineInRange("particleExtraBrightness", 255.0, 0, 255); .defineInRange("particleExtraBrightness", 255.0, 0, 255);
particleExtraColors = builder particleExtraColors = builder
.comment("List of color hex values and their weight. Format: '<color_hex>,<weight>'") .comment("List of color hex values and their weight. Format: '<color_hex>,<weight>'")
.defineList("particleExtraColors", List.of(getDefaultColorEntry()), Client::getDefaultColorEntry, Client::isValidColorEntry); .defineList("particleExtraColors", Stream.of("#ffffff,1").collect(Collectors.toList()), Client::isValidColorEntry);
builder.pop(); builder.pop();
builder.pop(); builder.pop();
} }
private static void onConfigReload() { private static void onConfigReload() {
SimpleWeightedRandomList.Builder<Color> particleExtraColorsWeightedListBuilder = SimpleWeightedRandomList.builder(); particleExtraColorsWeightedList = new WeightedList<>();
for (String entry : particleExtraColors.get()) { for (String entry : particleExtraColors.get()) {
String[] splitEntry = entry.split(","); String[] splitEntry = entry.split(",");
particleExtraColorsWeightedListBuilder.add(Color.decode(splitEntry[0]), Integer.parseInt(splitEntry[1])); particleExtraColorsWeightedList.add(Color.decode(splitEntry[0]), Integer.parseInt(splitEntry[1]));
} }
particleExtraColorsWeightedList = particleExtraColorsWeightedListBuilder.build();
} }
private static boolean isValidColorEntry(Object entry) { private static boolean isValidColorEntry(Object entry) {
return entry instanceof String && ((String) entry).matches("#\\w{6},\\d+$"); return entry instanceof String && ((String) entry).matches("#\\w{6},\\d+$");
} }
private static String getDefaultColorEntry() {
return "#ffffff,1";
}
} }
public static class Common { public static class Common {
Common(ModConfigSpec.Builder builder) {} Common(ForgeConfigSpec.Builder builder) {}
private static void onConfigReload() {} private static void onConfigReload() {}
} }
public static class Server { public static class Server {
Server(ModConfigSpec.Builder builder) {} Server(ForgeConfigSpec.Builder builder) {}
private static void onConfigReload() {} private static void onConfigReload() {}
} }

View File

@ -1,36 +1,27 @@
package dev.micle.firefly_bush_backport.data; package dev.micle.firefly_bush_backport.data;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.data.client.ModBlockStateProvider; import dev.micle.firefly_bush_backport.data.client.ModBlockStateProvider;
import dev.micle.firefly_bush_backport.data.client.ModDataMapProvider;
import dev.micle.firefly_bush_backport.data.client.ModItemModelProvider; import dev.micle.firefly_bush_backport.data.client.ModItemModelProvider;
import dev.micle.firefly_bush_backport.data.client.ModSoundDefinitionsProvider; import dev.micle.firefly_bush_backport.data.client.ModSoundDefinitionsProvider;
import dev.micle.firefly_bush_backport.data.server.ModBlockTagsProvider; import dev.micle.firefly_bush_backport.data.loot.ModLootTableProvider;
import dev.micle.firefly_bush_backport.data.server.ModLootTableProvider;
import dev.micle.firefly_bush_backport.data.server.ModWorldGenProvider;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.neoforged.bus.api.SubscribeEvent; import net.minecraftforge.common.data.ExistingFileHelper;
import net.neoforged.fml.common.EventBusSubscriber; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.neoforged.neoforge.common.data.ExistingFileHelper; import net.minecraftforge.fml.common.Mod;
import net.neoforged.neoforge.data.event.GatherDataEvent; import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import java.util.concurrent.CompletableFuture; @Mod.EventBusSubscriber(modid = FireflyBushBackport.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
@EventBusSubscriber
public class DataGenerators { public class DataGenerators {
@SubscribeEvent @SubscribeEvent
public static void gatherData(GatherDataEvent event) { public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator(); DataGenerator generator = event.getGenerator();
ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
CompletableFuture<HolderLookup.Provider> lookupProvider = event.getLookupProvider();
generator.addProvider(event.includeClient(), new ModBlockStateProvider(generator, existingFileHelper)); generator.addProvider(new ModBlockStateProvider(generator, existingFileHelper));
generator.addProvider(event.includeClient(), new ModItemModelProvider(generator, existingFileHelper)); generator.addProvider(new ModItemModelProvider(generator, existingFileHelper));
generator.addProvider(event.includeClient(), new ModSoundDefinitionsProvider(generator, existingFileHelper)); generator.addProvider(new ModSoundDefinitionsProvider(generator, existingFileHelper));
generator.addProvider(event.includeClient(), new ModDataMapProvider(generator, lookupProvider));
generator.addProvider(event.includeServer(), new ModBlockTagsProvider(generator, lookupProvider, existingFileHelper)); generator.addProvider(new ModLootTableProvider(generator));
generator.addProvider(event.includeServer(), new ModLootTableProvider(generator, lookupProvider));
generator.addProvider(event.includeServer(), new ModWorldGenProvider(generator, lookupProvider));
} }
} }

View File

@ -2,18 +2,18 @@ package dev.micle.firefly_bush_backport.data.client;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks; import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.block.Block;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.level.block.Block; import net.minecraftforge.client.model.generators.BlockStateProvider;
import net.neoforged.neoforge.client.model.generators.BlockStateProvider; import net.minecraftforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.common.data.ExistingFileHelper; import net.minecraftforge.fml.RegistryObject;
import net.neoforged.neoforge.registries.DeferredHolder;
import java.util.Objects; import java.util.Objects;
public class ModBlockStateProvider extends BlockStateProvider { public class ModBlockStateProvider extends BlockStateProvider {
public ModBlockStateProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) { public ModBlockStateProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) {
super(generator.getPackOutput(), FireflyBushBackport.MOD_ID, existingFileHelper); super(generator, FireflyBushBackport.MOD_ID, existingFileHelper);
} }
@Override @Override
@ -21,13 +21,12 @@ public class ModBlockStateProvider extends BlockStateProvider {
crossEmissiveBlock(ModBlocks.FIREFLY_BUSH); crossEmissiveBlock(ModBlocks.FIREFLY_BUSH);
} }
private void crossEmissiveBlock(DeferredHolder<Block, ? extends Block> block) { private void crossEmissiveBlock(RegistryObject<Block> block) {
String name = Objects.requireNonNull(block.getId()).getPath(); String name = Objects.requireNonNull(block.getId()).getPath();
simpleBlock(block.get(), models() simpleBlock(block.get(), models()
.withExistingParent(name, ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/cross_emissive")) .withExistingParent(name, new ResourceLocation(FireflyBushBackport.MOD_ID, "block/cross_emissive"))
.texture("cross", "block/" + name) .texture("cross", "block/" + name)
.texture("cross_emissive", "block/" + name + "_emissive") .texture("cross_emissive", "block/" + name + "_emissive")
.renderType("cutout")
); );
} }
} }

View File

@ -1,24 +0,0 @@
package dev.micle.firefly_bush_backport.data.client;
import dev.micle.firefly_bush_backport.item.ModItems;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator;
import net.neoforged.neoforge.common.data.DataMapProvider;
import net.neoforged.neoforge.registries.datamaps.builtin.Compostable;
import net.neoforged.neoforge.registries.datamaps.builtin.NeoForgeDataMaps;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.concurrent.CompletableFuture;
public class ModDataMapProvider extends DataMapProvider {
public ModDataMapProvider(DataGenerator generator, CompletableFuture<HolderLookup.Provider> lookupProvider) {
super(generator.getPackOutput(), lookupProvider);
}
@Override
@ParametersAreNonnullByDefault
protected void gather(HolderLookup.Provider provider) {
this.builder(NeoForgeDataMaps.COMPOSTABLES)
.add(ModItems.FIREFLY_BUSH, new Compostable(0.3F), false);
}
}

View File

@ -2,30 +2,30 @@ package dev.micle.firefly_bush_backport.data.client;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks; import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.block.Block;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.world.item.Items; import net.minecraft.item.Items;
import net.minecraft.world.level.block.Block; import net.minecraftforge.client.model.generators.ItemModelBuilder;
import net.neoforged.neoforge.client.model.generators.ItemModelBuilder; import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.neoforged.neoforge.client.model.generators.ItemModelProvider; import net.minecraftforge.client.model.generators.ModelFile;
import net.neoforged.neoforge.client.model.generators.ModelFile; import net.minecraftforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.common.data.ExistingFileHelper; import net.minecraftforge.fml.RegistryObject;
import net.neoforged.neoforge.registries.DeferredHolder; import net.minecraftforge.registries.ForgeRegistries;
import java.util.Objects; import java.util.Objects;
public class ModItemModelProvider extends ItemModelProvider { public class ModItemModelProvider extends ItemModelProvider {
public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) { public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) {
super(generator.getPackOutput(), FireflyBushBackport.MOD_ID, existingFileHelper); super(generator, FireflyBushBackport.MOD_ID, existingFileHelper);
} }
@Override @Override
protected void registerModels() { protected void registerModels() {
ModBlocks.BLOCKS.getEntries().stream().map(DeferredHolder::get).forEach(this::blockItemModel); ModBlocks.BLOCKS.getEntries().stream().map(RegistryObject::get).forEach(this::blockItemModel);
} }
private void blockItemModel(Block block) { private void blockItemModel(Block block) {
String name = Objects.requireNonNull(BuiltInRegistries.BLOCK.getKey(block)).getPath(); String name = Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(block)).getPath();
if (block == ModBlocks.FIREFLY_BUSH.get()) { if (block == ModBlocks.FIREFLY_BUSH.get()) {
builder(getExistingFile(mcLoc("item/generated")), name); builder(getExistingFile(mcLoc("item/generated")), name);

View File

@ -3,13 +3,13 @@ package dev.micle.firefly_bush_backport.data.client;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.sound.ModSounds; import dev.micle.firefly_bush_backport.sound.ModSounds;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.neoforged.neoforge.common.data.ExistingFileHelper; import net.minecraftforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.common.data.SoundDefinitionsProvider; import net.minecraftforge.common.data.SoundDefinitionsProvider;
public class ModSoundDefinitionsProvider extends SoundDefinitionsProvider { public class ModSoundDefinitionsProvider extends SoundDefinitionsProvider {
public ModSoundDefinitionsProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) { public ModSoundDefinitionsProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) {
super(generator.getPackOutput(), FireflyBushBackport.MOD_ID, existingFileHelper); super(generator, FireflyBushBackport.MOD_ID, existingFileHelper);
} }
@Override @Override
@ -17,31 +17,31 @@ public class ModSoundDefinitionsProvider extends SoundDefinitionsProvider {
add(ModSounds.FIREFLY_BUSH_IDLE, definition() add(ModSounds.FIREFLY_BUSH_IDLE, definition()
.subtitle("sound." + FireflyBushBackport.MOD_ID + ".block.firefly_bush.idle") .subtitle("sound." + FireflyBushBackport.MOD_ID + ".block.firefly_bush.idle")
.with( .with(
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush1")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush1"))
.volume(4), .volume(4),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush2")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush2"))
.volume(4), .volume(4),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush3")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush3"))
.volume(4), .volume(4),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush4")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush4"))
.volume(4), .volume(4),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush5")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush5"))
.volume(4), .volume(4),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush6")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush6"))
.volume(4), .volume(4),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush7")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush7"))
.volume(4) .volume(4)
.weight(2), .weight(2),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush8")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush8"))
.volume(4) .volume(4)
.weight(2), .weight(2),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush9")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush9"))
.volume(4) .volume(4)
.weight(2), .weight(2),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush10")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush10"))
.volume(4) .volume(4)
.weight(2), .weight(2),
sound(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush11")) sound(new ResourceLocation(FireflyBushBackport.MOD_ID, "block/firefly_bush/firefly_bush11"))
.volume(4) .volume(4)
) )
); );

View File

@ -1,26 +1,23 @@
package dev.micle.firefly_bush_backport.data.loot; package dev.micle.firefly_bush_backport.data.loot;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks; import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.HolderLookup; import net.minecraft.block.Block;
import net.minecraft.data.loot.BlockLootSubProvider; import net.minecraft.data.loot.BlockLootTables;
import net.minecraft.world.flag.FeatureFlags; import net.minecraftforge.registries.ForgeRegistries;
import net.minecraft.world.level.block.Block;
import org.jetbrains.annotations.NotNull;
import java.util.Set; import java.util.stream.Collectors;
public class ModBlockLootTableProvider extends BlockLootSubProvider { public class ModBlockLootTableProvider extends BlockLootTables {
public ModBlockLootTableProvider(HolderLookup.Provider provider) { @Override
super(Set.of(), FeatureFlags.REGISTRY.allFlags(), provider); protected void addTables() {
dropSelf(ModBlocks.FIREFLY_BUSH.get());
} }
@Override @Override
protected void generate() { protected Iterable<Block> getKnownBlocks() {
this.dropSelf(ModBlocks.FIREFLY_BUSH.get()); return ForgeRegistries.BLOCKS.getValues().stream()
} .filter(block -> FireflyBushBackport.MOD_ID.equals(block.getRegistryName().getNamespace()))
.collect(Collectors.toSet());
@Override
protected @NotNull Iterable<Block> getKnownBlocks() {
return ModBlocks.BLOCKS.getEntries().stream().map(x -> (Block)x.value())::iterator;
} }
} }

View File

@ -0,0 +1,38 @@
package dev.micle.firefly_bush_backport.data.loot;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Pair;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.LootTableProvider;
import net.minecraft.loot.*;
import net.minecraft.util.ResourceLocation;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class ModLootTableProvider extends LootTableProvider {
public ModLootTableProvider(DataGenerator generator) {
super(generator);
}
@Override
public String getName() {
return new ResourceLocation(FireflyBushBackport.MOD_ID, "loot_tables").toString();
}
@Override
protected List<Pair<Supplier<Consumer<BiConsumer<ResourceLocation, LootTable.Builder>>>, LootParameterSet>> getTables() {
return ImmutableList.of(
Pair.of(ModBlockLootTableProvider::new, LootParameterSets.BLOCK)
);
}
@Override
protected void validate(Map<ResourceLocation, LootTable> map, ValidationTracker validationTracker) {
map.forEach((id, table) -> LootTableManager.validate(validationTracker, id, table));
}
}

View File

@ -1,25 +0,0 @@
package dev.micle.firefly_bush_backport.data.server;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator;
import net.minecraft.tags.BlockTags;
import net.neoforged.neoforge.common.data.BlockTagsProvider;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.concurrent.CompletableFuture;
public class ModBlockTagsProvider extends BlockTagsProvider {
public ModBlockTagsProvider(DataGenerator generator, CompletableFuture<HolderLookup.Provider> lookupProvider, ExistingFileHelper existingFileHelper) {
super(generator.getPackOutput(), lookupProvider, FireflyBushBackport.MOD_ID, existingFileHelper);
}
@Override
@ParametersAreNonnullByDefault
protected void addTags(HolderLookup.Provider provider) {
this.tag(BlockTags.REPLACEABLE_BY_TREES)
.add(ModBlocks.FIREFLY_BUSH.get());
}
}

View File

@ -1,19 +0,0 @@
package dev.micle.firefly_bush_backport.data.server;
import dev.micle.firefly_bush_backport.data.loot.ModBlockLootTableProvider;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class ModLootTableProvider extends LootTableProvider {
public ModLootTableProvider(DataGenerator generator, CompletableFuture<HolderLookup.Provider> registries) {
super(generator.getPackOutput(), Set.of(), List.of(
new LootTableProvider.SubProviderEntry(ModBlockLootTableProvider::new, LootContextParamSets.BLOCK)
), registries);
}
}

View File

@ -1,26 +0,0 @@
package dev.micle.firefly_bush_backport.data.server;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.worldgen.ModBiomeModifiers;
import dev.micle.firefly_bush_backport.worldgen.ModConfiguredFeatures;
import dev.micle.firefly_bush_backport.worldgen.ModPlacedFeatures;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.DataGenerator;
import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class ModWorldGenProvider extends DatapackBuiltinEntriesProvider {
public static final RegistrySetBuilder BUILDER = new RegistrySetBuilder()
.add(Registries.CONFIGURED_FEATURE, ModConfiguredFeatures::bootstrap)
.add(Registries.PLACED_FEATURE, ModPlacedFeatures::bootstrap)
.add(NeoForgeRegistries.Keys.BIOME_MODIFIERS, ModBiomeModifiers::bootstrap);
public ModWorldGenProvider(DataGenerator generator, CompletableFuture<HolderLookup.Provider> registries) {
super(generator.getPackOutput(), registries, BUILDER, Set.of(FireflyBushBackport.MOD_ID));
}
}

View File

@ -0,0 +1,19 @@
package dev.micle.firefly_bush_backport.event;
import dev.micle.firefly_bush_backport.worldgen.ModConfiguredFeatures;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStage;
import net.minecraftforge.event.world.BiomeLoadingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
public class OnBiomeLoadingEventHandler {
@SubscribeEvent
public void onBiomeLoadingEvent(final BiomeLoadingEvent event) {
if (event.getCategory() == Biome.Category.SWAMP) {
event.getGeneration().addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, ModConfiguredFeatures.PLACED_PATCH_FIREFLY_BUSH_SWAMP);
event.getGeneration().addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, ModConfiguredFeatures.PLACED_PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP);
} else if (event.getCategory() != Biome.Category.THEEND && event.getCategory() != Biome.Category.NETHER) {
event.getGeneration().addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, ModConfiguredFeatures.PLACED_PATCH_FIREFLY_BUSH_NEAR_WATER);
}
}
}

View File

@ -1,14 +1,14 @@
package dev.micle.firefly_bush_backport.event; package dev.micle.firefly_bush_backport.event;
import dev.micle.firefly_bush_backport.item.ModItems; import dev.micle.firefly_bush_backport.item.ModItems;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
import net.neoforged.bus.api.SubscribeEvent; import net.minecraftforge.common.BasicTrade;
import net.neoforged.neoforge.common.BasicItemListing; import net.minecraftforge.event.village.WandererTradesEvent;
import net.neoforged.neoforge.event.village.WandererTradesEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
public class OnWandererTradesEventHandler { public class OnWandererTradesEventHandler {
@SubscribeEvent @SubscribeEvent
public void onWandererTradesEvent(WandererTradesEvent event) { public void onWandererTradesEvent(WandererTradesEvent event) {
event.getGenericTrades().add(new BasicItemListing(3, new ItemStack(ModItems.FIREFLY_BUSH, 1), 12, 1)); event.getGenericTrades().add(new BasicTrade(3, new ItemStack(ModItems.FIREFLY_BUSH.get(), 1), 12, 1));
} }
} }

View File

@ -2,25 +2,27 @@ package dev.micle.firefly_bush_backport.item;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks; import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.world.item.BlockItem; import dev.micle.firefly_bush_backport.tab.ModCreativeModeTabs;
import net.minecraft.world.item.Item; import net.minecraft.block.Block;
import net.minecraft.world.level.block.Block; import net.minecraft.item.BlockItem;
import net.neoforged.bus.api.IEventBus; import net.minecraft.item.Item;
import net.neoforged.neoforge.registries.DeferredHolder; import net.minecraftforge.eventbus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister; import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.Objects; import java.util.Objects;
public class ModItems { public class ModItems {
public static final DeferredRegister<Item> ITEMS = DeferredRegister.createItems(FireflyBushBackport.MOD_ID); public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, FireflyBushBackport.MOD_ID);
public static final DeferredHolder<Item, BlockItem> FIREFLY_BUSH = registerBlock(ModBlocks.FIREFLY_BUSH); public static final RegistryObject<BlockItem> FIREFLY_BUSH = registerBlock(ModBlocks.FIREFLY_BUSH);
public static void register(IEventBus modEventBus) { public static void register(IEventBus modEventBus) {
ITEMS.register(modEventBus); ITEMS.register(modEventBus);
} }
private static <T extends Block> DeferredHolder<Item, BlockItem> registerBlock(DeferredHolder<Block, T> block) { private static RegistryObject<BlockItem> registerBlock(RegistryObject<Block> block) {
return ITEMS.register(Objects.requireNonNull(block.getId()).getPath(), () -> new BlockItem(block.get(), new Item.Properties())); return ITEMS.register(Objects.requireNonNull(block.getId()).getPath(), () -> new BlockItem(block.get(), new Item.Properties().tab(ModCreativeModeTabs.MAIN_TAB)));
} }
} }

View File

@ -1,22 +1,32 @@
package dev.micle.firefly_bush_backport.particle; package dev.micle.firefly_bush_backport.particle;
import dev.micle.firefly_bush_backport.config.Config; import dev.micle.firefly_bush_backport.config.Config;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.block.Blocks;
import net.minecraft.client.particle.*; import net.minecraft.client.particle.*;
import net.minecraft.core.BlockPos; import net.minecraft.client.world.ClientWorld;
import net.minecraft.core.particles.SimpleParticleType; import net.minecraft.entity.Entity;
import net.minecraft.util.Mth; import net.minecraft.particles.BasicParticleType;
import net.neoforged.api.distmarker.Dist; import net.minecraft.util.ReuseableStream;
import net.neoforged.api.distmarker.OnlyIn; import net.minecraft.util.math.BlockPos;
import org.jetbrains.annotations.NotNull; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import java.awt.*; import java.awt.*;
import java.util.Optional; import java.util.Random;
import java.util.stream.Stream;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class FireflyParticle extends TextureSheetParticle { public class FireflyParticle extends SpriteTexturedParticle {
protected FireflyParticle(ClientLevel clientLevel, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { private static final double MAXIMUM_COLLISION_VELOCITY_SQUARED = MathHelper.square(100.00F);
private boolean stoppedByCollision;
private final float friction;
private final boolean speedUpWhenYMotionIsBlocked;
protected FireflyParticle(ClientWorld clientLevel, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
super(clientLevel, x, y, z, xSpeed, ySpeed, zSpeed); super(clientLevel, x, y, z, xSpeed, ySpeed, zSpeed);
this.speedUpWhenYMotionIsBlocked = true; this.speedUpWhenYMotionIsBlocked = true;
this.friction = Config.Client.particleExtraFriction.get().floatValue(); this.friction = Config.Client.particleExtraFriction.get().floatValue();
@ -27,8 +37,8 @@ public class FireflyParticle extends TextureSheetParticle {
} }
@Override @Override
public @NotNull ParticleRenderType getRenderType() { public IParticleRenderType getRenderType() {
return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; return IParticleRenderType.PARTICLE_SHEET_TRANSLUCENT;
} }
@Override @Override
@ -49,13 +59,34 @@ public class FireflyParticle extends TextureSheetParticle {
} }
private float getLifetimeProgress(float age) { private float getLifetimeProgress(float age) {
return Mth.clamp(age / this.lifetime, 0.0F, 1.0F); return MathHelper.clamp(age / this.lifetime, 0.0F, 1.0F);
} }
@Override @Override
public void tick() { public void tick() {
super.tick(); this.xo = this.x;
if (!this.level.getBlockState(BlockPos.containing(this.x, this.y, this.z)).isAir()) { this.yo = this.y;
this.zo = this.z;
if (this.age++ >= this.lifetime) {
this.remove();
} else {
this.yd -= 0.04D * (double) this.gravity;
this.move(this.xd, this.yd, this.zd);
if (this.speedUpWhenYMotionIsBlocked && this.y == this.yd) {
this.xd *= 1.1D;
this.zd *= 1.1D;
}
this.xd *= this.friction;
this.yd *= this.friction;
this.zd *= this.friction;
if (this.onGround) {
this.xd *= 0.7F;
this.zd *= 0.7F;
}
}
if (!this.level.getBlockState(new BlockPos(this.x, this.y, this.z)).is(Blocks.AIR)) {
this.remove(); this.remove();
} else { } else {
this.setAlpha(getFadeAmount(this.getLifetimeProgress(this.age), this.setAlpha(getFadeAmount(this.getLifetimeProgress(this.age),
@ -68,18 +99,57 @@ public class FireflyParticle extends TextureSheetParticle {
} }
} }
@OnlyIn(Dist.CLIENT) @Override
public static class FireflyProvider implements ParticleProvider<SimpleParticleType> { public void move(double pX, double pY, double pZ) {
private final SpriteSet sprite; if (!this.stoppedByCollision) {
double d0 = pX;
double d1 = pY;
double d2 = pZ;
if (this.hasPhysics && (pX != 0.0D || pY != 0.0D || pZ != 0.0D) && pX * pX + pY * pY + pZ * pZ < MAXIMUM_COLLISION_VELOCITY_SQUARED) {
Vector3d vec3 = Entity.collideBoundingBoxHeuristically((Entity) null, new Vector3d(pX, pY, pZ), this.getBoundingBox(), this.level, ISelectionContext.empty(), new ReuseableStream<>(Stream.empty()));
pX = vec3.x;
pY = vec3.y;
pZ = vec3.z;
}
public FireflyProvider(SpriteSet spriteSet) { if (pX != 0.0D || pY != 0.0D || pZ != 0.0D) {
this.setBoundingBox(this.getBoundingBox().move(pX, pY, pZ));
this.setLocationFromBoundingbox();
}
if (Math.abs(d1) >= (double) 1.0E-5F && Math.abs(pY) < (double) 1.0E-5F) {
this.stoppedByCollision = true;
}
this.onGround = d1 != pY && d1 < 0.00;
if (d0 != pX) {
this.xd = 0.0D;
}
if (d2 != pZ) {
this.zd = 0.0D;
}
}
}
private void setParticleSpeed(double xd, double yd, double zd) {
this.xd = xd;
this.yd = yd;
this.zd = zd;
}
@OnlyIn(Dist.CLIENT)
public static class FireflyProvider implements IParticleFactory<BasicParticleType> {
private final IAnimatedSprite sprite;
public FireflyProvider(IAnimatedSprite spriteSet) {
this.sprite = spriteSet; this.sprite = spriteSet;
} }
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public Particle createParticle( public Particle createParticle(
SimpleParticleType simpleParticleType, BasicParticleType simpleParticleType,
ClientLevel clientLevel, ClientWorld clientLevel,
double x, double x,
double y, double y,
double z, double z,
@ -96,19 +166,21 @@ public class FireflyParticle extends TextureSheetParticle {
clientLevel.random.nextBoolean() ? ySpeed : -ySpeed, clientLevel.random.nextBoolean() ? ySpeed : -ySpeed,
0.5 - clientLevel.random.nextDouble() 0.5 - clientLevel.random.nextDouble()
); );
fireflyParticle.setLifetime(clientLevel.random.nextIntBetweenInclusive( fireflyParticle.setLifetime(nextIntBetweenInclusive(
Config.Client.particleMinLifetime.get(), Config.Client.particleMaxLifetime.get() clientLevel.random, Config.Client.particleMinLifetime.get(), Config.Client.particleMaxLifetime.get()
)); ));
fireflyParticle.scale(1.5F); fireflyParticle.scale(1.5F);
fireflyParticle.pickSprite(this.sprite); fireflyParticle.pickSprite(this.sprite);
fireflyParticle.setAlpha(0.0F); fireflyParticle.setAlpha(0.0F);
Optional<Color> optionalColor = Config.Client.particleExtraColorsWeightedList.getRandomValue(clientLevel.random); Color color = Config.Client.particleExtraColorsWeightedList.getOne(clientLevel.random);
optionalColor.ifPresent(color -> fireflyParticle.setColor(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F);
fireflyParticle.setColor(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F)
);
return fireflyParticle; return fireflyParticle;
} }
private int nextIntBetweenInclusive(Random random, int low, int high) {
return random.nextInt(high - low + 1) + low;
}
} }
} }

View File

@ -1,18 +1,18 @@
package dev.micle.firefly_bush_backport.particle; package dev.micle.firefly_bush_backport.particle;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.core.particles.ParticleType; import net.minecraft.particles.BasicParticleType;
import net.minecraft.core.particles.SimpleParticleType; import net.minecraft.particles.ParticleType;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraftforge.eventbus.api.IEventBus;
import net.neoforged.bus.api.IEventBus; import net.minecraftforge.fml.RegistryObject;
import net.neoforged.neoforge.registries.DeferredHolder; import net.minecraftforge.registries.DeferredRegister;
import net.neoforged.neoforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries;
public class ModParticles { public class ModParticles {
public static final DeferredRegister<ParticleType<?>> PARTICLE_TYPES = DeferredRegister.create(BuiltInRegistries.PARTICLE_TYPE, FireflyBushBackport.MOD_ID); public static final DeferredRegister<ParticleType<?>> PARTICLE_TYPES = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, FireflyBushBackport.MOD_ID);
public static final DeferredHolder<ParticleType<?>, SimpleParticleType> FIREFLY = PARTICLE_TYPES.register("firefly", public static final RegistryObject<BasicParticleType> FIREFLY = PARTICLE_TYPES.register("firefly",
() -> new SimpleParticleType(false)); () -> new BasicParticleType(false));
public static void register(IEventBus modEventBus) { public static void register(IEventBus modEventBus) {
PARTICLE_TYPES.register(modEventBus); PARTICLE_TYPES.register(modEventBus);

View File

@ -1,18 +1,11 @@
package dev.micle.firefly_bush_backport.proxy; package dev.micle.firefly_bush_backport.proxy;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import javax.annotation.Nullable;
public interface IProxy { public interface IProxy {
@Nullable
MinecraftServer getServer(); MinecraftServer getServer();
PlayerEntity getClientPlayer();
@Nullable ClientWorld getClientLevel();
Player getClientPlayer();
@Nullable
Level getClientLevel();
} }

View File

@ -2,36 +2,42 @@ package dev.micle.firefly_bush_backport.proxy;
import dev.micle.firefly_bush_backport.block.ModBlocks; import dev.micle.firefly_bush_backport.block.ModBlocks;
import dev.micle.firefly_bush_backport.config.Config; import dev.micle.firefly_bush_backport.config.Config;
import dev.micle.firefly_bush_backport.event.OnBiomeLoadingEventHandler;
import dev.micle.firefly_bush_backport.event.OnWandererTradesEventHandler; import dev.micle.firefly_bush_backport.event.OnWandererTradesEventHandler;
import dev.micle.firefly_bush_backport.tab.ModCreativeModeTabs;
import dev.micle.firefly_bush_backport.item.ModItems; import dev.micle.firefly_bush_backport.item.ModItems;
import dev.micle.firefly_bush_backport.particle.FireflyParticle; import dev.micle.firefly_bush_backport.particle.FireflyParticle;
import dev.micle.firefly_bush_backport.particle.ModParticles; import dev.micle.firefly_bush_backport.particle.ModParticles;
import dev.micle.firefly_bush_backport.sound.ModSounds; import dev.micle.firefly_bush_backport.sound.ModSounds;
import dev.micle.firefly_bush_backport.tab.ModCreativeModeTabs;
import net.minecraft.block.ComposterBlock;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player; import net.minecraftforge.api.distmarker.Dist;
import net.minecraft.world.level.Level; import net.minecraftforge.api.distmarker.OnlyIn;
import net.neoforged.api.distmarker.Dist; import net.minecraftforge.client.event.ParticleFactoryRegisterEvent;
import net.neoforged.api.distmarker.OnlyIn; import net.minecraftforge.common.MinecraftForge;
import net.neoforged.bus.api.IEventBus; import net.minecraftforge.event.AddReloadListenerEvent;
import net.neoforged.fml.ModContainer; import net.minecraftforge.eventbus.api.IEventBus;
import net.neoforged.fml.event.lifecycle.*; import net.minecraftforge.fml.event.lifecycle.*;
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.neoforged.neoforge.common.NeoForge; import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.neoforged.neoforge.event.AddReloadListenerEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.neoforged.neoforge.event.server.ServerStartedEvent;
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
public class Proxy implements IProxy { public class Proxy implements IProxy {
private static MinecraftServer server = null; private static MinecraftServer server = null;
// Common setup // Common setup
public Proxy(IEventBus modEventBus, ModContainer modContainer) { public Proxy() {
Config.register(modEventBus, modContainer); IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
Config.register();
ModBlocks.register(modEventBus); ModBlocks.register(modEventBus);
ModItems.register(modEventBus); ModItems.register(modEventBus);
ModCreativeModeTabs.register(modEventBus); ModCreativeModeTabs.register();
ModSounds.register(modEventBus); ModSounds.register(modEventBus);
ModParticles.register(modEventBus); ModParticles.register(modEventBus);
@ -41,15 +47,18 @@ public class Proxy implements IProxy {
modEventBus.addListener(Proxy::imcProcess); modEventBus.addListener(Proxy::imcProcess);
// Register event bus listeners // Register event bus listeners
NeoForge.EVENT_BUS.addListener(Proxy::onAddReloadListeners); MinecraftForge.EVENT_BUS.addListener(Proxy::onAddReloadListeners);
NeoForge.EVENT_BUS.addListener(Proxy::serverStarted); MinecraftForge.EVENT_BUS.addListener(Proxy::serverStarted);
NeoForge.EVENT_BUS.addListener(Proxy::serverStopping); MinecraftForge.EVENT_BUS.addListener(Proxy::serverStopping);
// Register event handlers // Register event handlers
NeoForge.EVENT_BUS.register(new OnWandererTradesEventHandler()); MinecraftForge.EVENT_BUS.register(new OnWandererTradesEventHandler());
MinecraftForge.EVENT_BUS.register(new OnBiomeLoadingEventHandler());
} }
private static void setup(FMLCommonSetupEvent event) {} private static void setup(FMLCommonSetupEvent event) {
ComposterBlock.COMPOSTABLES.put(ModItems.FIREFLY_BUSH.get().asItem(), 0.3F);
}
private static void imcEnqueue(InterModEnqueueEvent event) {} private static void imcEnqueue(InterModEnqueueEvent event) {}
@ -57,11 +66,11 @@ public class Proxy implements IProxy {
private static void onAddReloadListeners(AddReloadListenerEvent event) {} private static void onAddReloadListeners(AddReloadListenerEvent event) {}
private static void serverStarted(ServerStartedEvent event) { private static void serverStarted(FMLServerStartedEvent event) {
server = event.getServer(); server = event.getServer();
} }
private static void serverStopping(ServerStoppingEvent event) { private static void serverStopping(FMLServerStoppingEvent event) {
server = null; server = null;
} }
@ -71,19 +80,19 @@ public class Proxy implements IProxy {
} }
@Override @Override
public Player getClientPlayer() { public PlayerEntity getClientPlayer() {
return null; return null;
} }
@Override @Override
public Level getClientLevel() { public ClientWorld getClientLevel() {
return null; return null;
} }
// Client setup // Client setup
public static class Client extends Proxy { public static class Client extends Proxy {
public Client(IEventBus modEventBus, ModContainer modContainer) { public Client() {
super(modEventBus, modContainer); IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
// Register mod event bus listeners // Register mod event bus listeners
modEventBus.addListener(Client::setup); modEventBus.addListener(Client::setup);
@ -91,33 +100,34 @@ public class Proxy implements IProxy {
modEventBus.addListener(Client::registerParticleFactories); modEventBus.addListener(Client::registerParticleFactories);
} }
private static void setup(FMLClientSetupEvent event) {} private static void setup(FMLClientSetupEvent event) {
RenderTypeLookup.setRenderLayer(ModBlocks.FIREFLY_BUSH.get(), RenderType.cutout());
}
private static void postSetup(FMLLoadCompleteEvent event) {} private static void postSetup(FMLLoadCompleteEvent event) {}
private static void registerParticleFactories(RegisterParticleProvidersEvent event) { private static void registerParticleFactories(ParticleFactoryRegisterEvent event) {
event.registerSpriteSet(ModParticles.FIREFLY.get(), FireflyParticle.FireflyProvider::new); Minecraft.getInstance().particleEngine.register(ModParticles.FIREFLY.get(), FireflyParticle.FireflyProvider::new);
} }
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public Player getClientPlayer() { public PlayerEntity getClientPlayer() {
return Minecraft.getInstance().player; return Minecraft.getInstance().player;
} }
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public Level getClientLevel() { public ClientWorld getClientLevel() {
return Minecraft.getInstance().level; return Minecraft.getInstance().level;
} }
} }
// Server setup // Server setup
public static class Server extends Proxy { public static class Server extends Proxy {
public Server(IEventBus modEventBus, ModContainer modContainer) { public Server() {
super(modEventBus, modContainer);
// Register mod event bus listeners // Register mod event bus listeners
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(Server::setup); modEventBus.addListener(Server::setup);
} }

View File

@ -1,23 +1,23 @@
package dev.micle.firefly_bush_backport.sound; package dev.micle.firefly_bush_backport.sound;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.util.ResourceLocation;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.SoundEvent;
import net.minecraft.sounds.SoundEvent; import net.minecraftforge.eventbus.api.IEventBus;
import net.neoforged.bus.api.IEventBus; import net.minecraftforge.fml.RegistryObject;
import net.neoforged.neoforge.registries.DeferredHolder; import net.minecraftforge.registries.DeferredRegister;
import net.neoforged.neoforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries;
public class ModSounds { public class ModSounds {
public static final DeferredRegister<SoundEvent> SOUND_EVENTS = DeferredRegister.create(BuiltInRegistries.SOUND_EVENT, FireflyBushBackport.MOD_ID); public static final DeferredRegister<SoundEvent> SOUND_EVENTS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, FireflyBushBackport.MOD_ID);
public static final DeferredHolder<SoundEvent, SoundEvent> FIREFLY_BUSH_IDLE = registerSoundEvent("block.firefly_bush.idle"); public static final RegistryObject<SoundEvent> FIREFLY_BUSH_IDLE = registerSoundEvent("block.firefly_bush.idle");
public static void register(IEventBus modEventBus) { public static void register(IEventBus modEventBus) {
SOUND_EVENTS.register(modEventBus); SOUND_EVENTS.register(modEventBus);
} }
private static DeferredHolder<SoundEvent, SoundEvent> registerSoundEvent(String name) { private static RegistryObject<SoundEvent> registerSoundEvent(String name) {
return SOUND_EVENTS.register(name, () -> SoundEvent.createVariableRangeEvent(ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, name))); return SOUND_EVENTS.register(name, () -> new SoundEvent(new ResourceLocation(FireflyBushBackport.MOD_ID, name)));
} }
} }

View File

@ -2,27 +2,24 @@ package dev.micle.firefly_bush_backport.tab;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks; import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.item.ItemGroup;
import net.minecraft.network.chat.Component; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.util.ResourceLocation;
import net.neoforged.bus.api.IEventBus; import net.minecraft.util.text.ITextComponent;
import net.neoforged.neoforge.registries.DeferredHolder; import net.minecraft.util.text.TranslationTextComponent;
import net.neoforged.neoforge.registries.DeferredRegister;
public class ModCreativeModeTabs { public class ModCreativeModeTabs {
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(BuiltInRegistries.CREATIVE_MODE_TAB, FireflyBushBackport.MOD_ID); public static final ItemGroup MAIN_TAB = new ItemGroup(new ResourceLocation(FireflyBushBackport.MOD_ID, "main").toString()) {
@Override
public ItemStack makeIcon() {
return ModBlocks.FIREFLY_BUSH.get().asItem().getDefaultInstance();
}
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> MAIN_TAB = CREATIVE_MODE_TABS.register( "main", @Override
() -> CreativeModeTab.builder() public ITextComponent getDisplayName() {
.title(Component.translatable(String.format("itemGroup.%s.main", FireflyBushBackport.MOD_ID))) return new TranslationTextComponent(String.format("itemGroup.%s.main", FireflyBushBackport.MOD_ID));
.icon(ModBlocks.FIREFLY_BUSH.get().asItem()::getDefaultInstance) }
.displayItems((itemDisplayParams, output) -> { };
output.accept(ModBlocks.FIREFLY_BUSH.get());
})
.build()
);
public static void register(IEventBus modEventBus) { public static void register() {}
CREATIVE_MODE_TABS.register(modEventBus);
}
} }

View File

@ -1,59 +0,0 @@
package dev.micle.firefly_bush_backport.worldgen;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.HolderSet;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BiomeTags;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.neoforged.neoforge.common.Tags;
import net.neoforged.neoforge.common.world.BiomeModifier;
import net.neoforged.neoforge.common.world.BiomeModifiers;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
import java.util.Set;
public class ModBiomeModifiers {
public static final ResourceKey<BiomeModifier> ADD_PATCH_FIREFLY_BUSH_SWAMP = registerKey("add_patch_firefly_bush_swamp");
public static final ResourceKey<BiomeModifier> ADD_PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP = registerKey("add_patch_firefly_bush_near_water_swamp");
public static final ResourceKey<BiomeModifier> ADD_PATCH_FIREFLY_BUSH_NEAR_WATER = registerKey("add_patch_firefly_bush_near_water");
public static final ResourceKey<BiomeModifier> REMOVE_PATCH_FIREFLY_BUSH_NEAR_WATER = registerKey("remove_patch_firefly_bush_near_water");
public static void bootstrap(BootstrapContext<BiomeModifier> context) {
HolderGetter<PlacedFeature> placedFeatures = context.lookup(Registries.PLACED_FEATURE);
HolderGetter<Biome> biomes = context.lookup(Registries.BIOME);
context.register(ADD_PATCH_FIREFLY_BUSH_SWAMP, new BiomeModifiers.AddFeaturesBiomeModifier(
biomes.getOrThrow(Tags.Biomes.IS_SWAMP),
HolderSet.direct(placedFeatures.getOrThrow(ModPlacedFeatures.PATCH_FIREFLY_BUSH_SWAMP_PLACED_KEY)),
GenerationStep.Decoration.VEGETAL_DECORATION
));
context.register(ADD_PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP, new BiomeModifiers.AddFeaturesBiomeModifier(
biomes.getOrThrow(Tags.Biomes.IS_SWAMP),
HolderSet.direct(placedFeatures.getOrThrow(ModPlacedFeatures.PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP_PLACED_KEY)),
GenerationStep.Decoration.VEGETAL_DECORATION
));
context.register(ADD_PATCH_FIREFLY_BUSH_NEAR_WATER, new BiomeModifiers.AddFeaturesBiomeModifier(
biomes.getOrThrow(BiomeTags.IS_OVERWORLD),
HolderSet.direct(placedFeatures.getOrThrow(ModPlacedFeatures.PATCH_FIREFLY_BUSH_NEAR_WATER_PLACED_KEY)),
GenerationStep.Decoration.VEGETAL_DECORATION
));
context.register(REMOVE_PATCH_FIREFLY_BUSH_NEAR_WATER, new BiomeModifiers.RemoveFeaturesBiomeModifier(
biomes.getOrThrow(Tags.Biomes.IS_SWAMP),
HolderSet.direct(placedFeatures.getOrThrow(ModPlacedFeatures.PATCH_FIREFLY_BUSH_NEAR_WATER_PLACED_KEY)),
Set.of(GenerationStep.Decoration.VEGETAL_DECORATION)
));
}
private static ResourceKey<BiomeModifier> registerKey(String name) {
return ResourceKey.create(NeoForgeRegistries.Keys.BIOME_MODIFIERS, ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, name));
}
}

View File

@ -2,43 +2,43 @@ package dev.micle.firefly_bush_backport.worldgen;
import dev.micle.firefly_bush_backport.FireflyBushBackport; import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks; import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.registries.Registries; import net.minecraft.util.ResourceLocation;
import net.minecraft.data.worldgen.BootstrapContext; import net.minecraft.util.registry.Registry;
import net.minecraft.data.worldgen.placement.PlacementUtils; import net.minecraft.util.registry.WorldGenRegistries;
import net.minecraft.resources.ResourceKey; import net.minecraft.world.gen.blockplacer.SimpleBlockPlacer;
import net.minecraft.resources.ResourceLocation; import net.minecraft.world.gen.blockstateprovider.SimpleBlockStateProvider;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.gen.feature.*;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.RandomPatchConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConfiguration;
import net.minecraft.world.level.levelgen.feature.stateproviders.SimpleStateProvider;
public class ModConfiguredFeatures { public class ModConfiguredFeatures {
public static final ResourceKey<ConfiguredFeature<?, ?>> PATCH_FIREFLY_BUSH_KEY = registerKey("patch_firefly_bush"); private static final BlockClusterFeatureConfig.Builder CONFIG_PATCH_FIREFLY_BUSH = new BlockClusterFeatureConfig.Builder(
new SimpleBlockStateProvider(ModBlocks.FIREFLY_BUSH.get().defaultBlockState()), new SimpleBlockPlacer()
).tries(20).xspread(4).yspread(3).zspread(4);
public static void bootstrap(BootstrapContext<ConfiguredFeature<?, ?>> context) { public static final ConfiguredFeature<?, ?> CONFIGURED_PATCH_FIREFLY_BUSH = create("patch_firefly_bush", Feature.RANDOM_PATCH.configured(
register(context, PATCH_FIREFLY_BUSH_KEY, Feature.RANDOM_PATCH, new RandomPatchConfiguration( CONFIG_PATCH_FIREFLY_BUSH.build()
20, ));
4,
3,
PlacementUtils.onlyWhenEmpty(
Feature.SIMPLE_BLOCK,
new SimpleBlockConfiguration(
SimpleStateProvider.simple(ModBlocks.FIREFLY_BUSH.get())
)
)
));
}
public static ResourceKey<ConfiguredFeature<?, ?>> registerKey(String name) { public static final ConfiguredFeature<?, ?> CONFIGURED_PATCH_FIREFLY_BUSH_NEAR_WATER = create("patch_firefly_bush", Feature.RANDOM_PATCH.configured(
return ResourceKey.create(Registries.CONFIGURED_FEATURE, ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, name)); CONFIG_PATCH_FIREFLY_BUSH.needWater().build()
} ));
private static <FC extends FeatureConfiguration, F extends Feature<FC>> void register( public static final ConfiguredFeature<?, ?> PLACED_PATCH_FIREFLY_BUSH_SWAMP = create("patch_firefly_bush_swamp", CONFIGURED_PATCH_FIREFLY_BUSH
BootstrapContext<ConfiguredFeature<?, ?>> context, .chance(8)
ResourceKey<ConfiguredFeature<?, ?>> key, F feature, FC configuration .decorated(Features.Placements.HEIGHTMAP_SQUARE)
) { );
context.register(key, new ConfiguredFeature<>(feature, configuration));
public static final ConfiguredFeature<?, ?> PLACED_PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP = create("patch_firefly_bush_near_water_swamp", CONFIGURED_PATCH_FIREFLY_BUSH_NEAR_WATER
.count(3)
.decorated(Features.Placements.HEIGHTMAP_SQUARE)
);
public static final ConfiguredFeature<?, ?> PLACED_PATCH_FIREFLY_BUSH_NEAR_WATER = create("patch_firefly_bush_near_water", CONFIGURED_PATCH_FIREFLY_BUSH_NEAR_WATER
.count(2)
.decorated(Features.Placements.TOP_SOLID_HEIGHTMAP_SQUARE)
);
private static <FC extends IFeatureConfig, F extends Feature<FC>, CF extends ConfiguredFeature<FC, F>> CF create(String id, CF configuredFeature) {
Registry.register(WorldGenRegistries.CONFIGURED_FEATURE, new ResourceLocation(FireflyBushBackport.MOD_ID, id), configuredFeature);
return configuredFeature;
} }
} }

View File

@ -1,79 +0,0 @@
package dev.micle.firefly_bush_backport.worldgen;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.Vec3i;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.placement.*;
import net.minecraft.world.level.material.Fluids;
import java.util.List;
public class ModPlacedFeatures {
public static final ResourceKey<PlacedFeature> PATCH_FIREFLY_BUSH_SWAMP_PLACED_KEY = registerKey("patch_firefly_bush_swamp");
public static final ResourceKey<PlacedFeature> PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP_PLACED_KEY = registerKey("patch_firefly_bush_near_water_swamp");
public static final ResourceKey<PlacedFeature> PATCH_FIREFLY_BUSH_NEAR_WATER_PLACED_KEY = registerKey("patch_firefly_bush_near_water");
public static void bootstrap(BootstrapContext<PlacedFeature> context) {
HolderGetter<ConfiguredFeature<?, ?>> configuredFeatures = context.lookup(Registries.CONFIGURED_FEATURE);
register(context, PATCH_FIREFLY_BUSH_SWAMP_PLACED_KEY, configuredFeatures.getOrThrow(ModConfiguredFeatures.PATCH_FIREFLY_BUSH_KEY), List.of(
RarityFilter.onAverageOnceEvery(8),
InSquarePlacement.spread(),
PlacementUtils.HEIGHTMAP,
BiomeFilter.biome()
));
register(context, PATCH_FIREFLY_BUSH_NEAR_WATER_SWAMP_PLACED_KEY, configuredFeatures.getOrThrow(ModConfiguredFeatures.PATCH_FIREFLY_BUSH_KEY), List.of(
CountPlacement.of(3),
InSquarePlacement.spread(),
PlacementUtils.HEIGHTMAP,
BiomeFilter.biome(),
BlockPredicateFilter.forPredicate(BlockPredicate.allOf(
BlockPredicate.matchesBlocks(Blocks.AIR),
BlockPredicate.wouldSurvive(ModBlocks.FIREFLY_BUSH.get().defaultBlockState(), Vec3i.ZERO),
BlockPredicate.anyOf(
BlockPredicate.matchesFluids(new Vec3i(1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
BlockPredicate.matchesFluids(new Vec3i(-1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
BlockPredicate.matchesFluids(new Vec3i(0, -1, 1), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
BlockPredicate.matchesFluids(new Vec3i(0, -1, -1), List.of(Fluids.WATER, Fluids.FLOWING_WATER))
)
))
));
register(context, PATCH_FIREFLY_BUSH_NEAR_WATER_PLACED_KEY, configuredFeatures.getOrThrow(ModConfiguredFeatures.PATCH_FIREFLY_BUSH_KEY), List.of(
CountPlacement.of(2),
InSquarePlacement.spread(),
HeightmapPlacement.onHeightmap(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES),
BiomeFilter.biome(),
BlockPredicateFilter.forPredicate(BlockPredicate.allOf(
BlockPredicate.matchesBlocks(Blocks.AIR),
BlockPredicate.wouldSurvive(ModBlocks.FIREFLY_BUSH.get().defaultBlockState(), Vec3i.ZERO),
BlockPredicate.anyOf(
BlockPredicate.matchesFluids(new Vec3i(1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
BlockPredicate.matchesFluids(new Vec3i(-1, -1, 0), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
BlockPredicate.matchesFluids(new Vec3i(0, -1, 1), List.of(Fluids.WATER, Fluids.FLOWING_WATER)),
BlockPredicate.matchesFluids(new Vec3i(0, -1, -1), List.of(Fluids.WATER, Fluids.FLOWING_WATER))
)
))
));
}
private static ResourceKey<PlacedFeature> registerKey(String name) {
return ResourceKey.create(Registries.PLACED_FEATURE, ResourceLocation.fromNamespaceAndPath(FireflyBushBackport.MOD_ID, name));
}
private static void register(BootstrapContext<PlacedFeature> context, ResourceKey<PlacedFeature> key, Holder<ConfiguredFeature<?, ?>> configuration, List<PlacementModifier> modifiers) {
context.register(key, new PlacedFeature(configuration, List.copyOf(modifiers)));
}
}

View File

@ -0,0 +1,30 @@
modLoader = "javafml"
loaderVersion = "${loader_version_range}"
license = "${mod_license}"
issueTrackerURL="https://gitea.micle.dev/minecraft-mods/firefly_bush_backport/issues"
[[mods]]
modId = "${mod_id}"
version = "${mod_version}"
displayName = "${mod_name}"
#updateJSONURL="https://change.me.example.invalid/updates.json" # https://docs.minecraftforge.net/en/latest/misc/updatechecker/
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/"
logoFile="logo.jpg"
#credits=""
authors = "${mod_authors}"
displayTest="MATCH_VERSION" # MATCH_VERSION, IGNORE_SERVER_VERSION (server only), IGNORE_ALL_VERSION (client only), NONE (IExtensionPoint.DisplayTest)
description = '''${mod_description}'''
[[dependencies."${mod_id}"]]
modId = "forge"
mandatory = true
versionRange = "${forge_version_range}"
ordering = "NONE" # BEFORE, AFTER, NONE
side = "BOTH" # BOTH, CLIENT, SERVER
[[dependencies."${mod_id}"]]
modId = "minecraft"
mandatory = true
versionRange = "${minecraft_version_range}"
ordering = "NONE"
side = "BOTH"

View File

@ -1,44 +0,0 @@
modLoader = "javafml"
loaderVersion = "${loader_version_range}"
license = "${mod_license}"
issueTrackerURL="https://gitea.micle.dev/minecraft-mods/firefly_bush_backport/issues"
[[mods]]
modId = "${mod_id}"
version = "${mod_version}"
displayName = "${mod_name}"
#updateJSONURL="https://change.me.example.invalid/updates.json" # https://docs.minecraftforge.net/en/latest/misc/updatechecker/
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/"
logoFile="logo.png"
#credits=""
authors = "${mod_authors}"
description = '''${mod_description}'''
#[[mixins]]
#config = "${mod_id}.mixins.json"
#[[accessTransformers]]
#file = "META-INF/accesstransformer.cfg"
[[dependencies."${mod_id}"]]
modId = "neoforge"
# The type of the dependency. Can be one of "required", "optional", "incompatible" or "discouraged" (case insensitive).
# 'required' requires the mod to exist, 'optional' does not
# 'incompatible' will prevent the game from loading when the mod exists, and 'discouraged' will show a warning"
type = "required"
versionRange = "${neo_version_range}"
ordering = "NONE" # BEFORE, AFTER, NONE
side = "BOTH" # BOTH, CLIENT, SERVER
[[dependencies."${mod_id}"]]
modId = "minecraft"
type = "required"
versionRange = "${minecraft_version_range}"
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,)"

BIN
src/main/resources/logo.jpg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
src/main/resources/logo.png (Stored with Git LFS)

Binary file not shown.