diff --git a/README.md b/README.md index f8f9b8d..7243e4c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,3 @@ - -

- fabric-api -

- Unkindled makes furnaces no longer smelt items automatically. Instead, players need to use a flint and steel (any tool in `c:tools/igniter`) or a fire charge to ignite the furnace (while sneaking). diff --git a/build.gradle b/build.gradle index cf701da..db30848 100644 --- a/build.gradle +++ b/build.gradle @@ -1,99 +1,229 @@ plugins { - id 'fabric-loom' version '1.7-SNAPSHOT' + id 'java-library' id 'maven-publish' - id "com.modrinth.minotaur" version "2.+" + id 'net.neoforged.moddev' version '1.0.20' + id "me.modmuss50.mod-publish-plugin" version "0.7.4" +} + +tasks.named('wrapper', Wrapper).configure { + // Define wrapper values here so as to not have to always do so when updating gradlew.properties. + // Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with + // documentation attached on cursor hover of gradle classes and methods. However, this comes with increased + // file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards. + // (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`) + distributionType = Wrapper.DistributionType.BIN } version = "${project.mod_version}+${project.minecraft_version}" -group = project.maven_group +group = mod_group_id -base { - archivesName = project.archives_base_name +repositories { + mavenLocal() } -repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. +base { + archivesName = mod_id } -dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" +// Mojang ships Java 21 to end users starting in 1.20.5, so mods should target Java 21. +java.toolchain.languageVersion = JavaLanguageVersion.of(21) - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" +neoForge { + // Specify the version of NeoForge to use. + version = project.neo_version -} + parchment { + mappingsVersion = project.parchment_mappings_version + minecraftVersion = project.parchment_minecraft_version + } + + // 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 { + client { + client() -processResources { - inputs.property "version", project.version + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + + server { + server() + programArgument '--nogui' + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } - filesMatching("fabric.mod.json") { - expand "version": project.version + // 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 { + type = "gameTestServer" + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + + data { + data() + + // 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 + } } -} -tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + mods { + // define mod <-> source bindings + // these are used to tell the game which sources are for which mod + // mostly optional in a single mod project + // but multi mod projects should define one per mod + "${mod_id}" { + sourceSet(sourceSets.main) + } + } } -java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 +// Sets up a dependency configuration called 'localRuntime'. +// This configuration should be used instead of 'runtimeOnly' to declare +// a dependency that will be present for runtime testing but that is +// "optional", meaning it will not be pulled by dependents of this mod. +configurations { + runtimeClasspath.extendsFrom localRuntime } -jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}"} - } +dependencies { + // Example optional mod dependency with JEI + // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime + // 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 } -// configure the maven publication +// 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. +var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) { + 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 + expand replaceProperties + from "src/main/templates" + into "build/generated/sources/modMetadata" +} +// Include the output of "generateModMetadata" as an input directory for the build +// this works with both building through Gradle and the IDE. +sourceSets.main.resources.srcDir generateModMetadata +// To avoid having to run "generateModMetadata" manually, make it run on every project reload +neoForge.ideSyncTask generateModMetadata + +// Example configuration to allow publishing using the maven-publish plugin publishing { publications { - create("mavenJava", MavenPublication) { - artifactId = project.archives_base_name + register('mavenJava', MavenPublication) { from components.java } } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. + maven { + url "file://${project.projectDir}/repo" + } } } -modrinth { - token = System.getenv("MODRINTH_TOKEN") - projectId = project.archives_base_name - versionName = "Unkindled " + project.mod_version - versionNumber = project.version.toString() - versionType = "release" - uploadFile = remapJar - gameVersions = project.version_range.split(",").collect { it.trim() } - loaders = ["fabric"] - dependencies { - required.project "fabric-api" +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} + +// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior. +idea { + module { + downloadSources = true + downloadJavadoc = true } - syncBodyFrom = rootProject.file("README.md").text +} + +java { + withSourcesJar() +} + +jar { + from("LICENSE") +} + +static def addMinecraftVersions(versionsContainer) { + versionsContainer.add("1.21") + versionsContainer.add("1.21.1") +} + +publishMods { def versionAsNumber = project.mod_version.replaceAll("\\.", "") changelog = "Check the changelog on [GitHub](https://github.com/Reimaden-Modding/unkindled/blob/HEAD/CHANGELOG.md#" + versionAsNumber + ")" - additionalFiles = [ - remapSourcesJar - ] -} + type = STABLE + file = jar.archiveFile + modLoaders.add("neoforge") + version = project.version + displayName = "Unkindled " + project.mod_version + additionalFiles.from(sourcesJar.archiveFile) + + modrinth { + accessToken = providers.environmentVariable("MODRINTH_TOKEN") + projectId = "ozHCnpcZ" + addMinecraftVersions(minecraftVersions) + projectDescription = providers.fileContents(layout.projectDirectory.file("README.md")).asText + } -tasks.modrinth.dependsOn(tasks.modrinthSyncBody) \ No newline at end of file + curseforge { + accessToken = providers.environmentVariable("CURSEFORGE_TOKEN") + projectId = "1118464" + addMinecraftVersions(minecraftVersions) + clientRequired = false + serverRequired = true + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 77c3b79..6abfdae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,23 @@ -# Done to increase the memory available to gradle. +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. org.gradle.jvmargs=-Xmx1G +org.gradle.daemon=true org.gradle.parallel=true +org.gradle.caching=true -# Fabric Properties -# check these on https://fabricmc.net/develop +# Environment Properties +parchment_minecraft_version=1.21 +parchment_mappings_version=2024.07.28 minecraft_version=1.21.1 -yarn_mappings=1.21.1+build.3 -loader_version=0.16.5 +minecraft_version_range=[1.21, 1.22) +neo_version=21.1.66 +neo_version_range=[21.1.0,) +loader_version_range=[4,) # Mod Properties +mod_id=unkindled +mod_name=Unkindled +mod_license=MIT mod_version=1.2.0 -maven_group=net.reimaden -archives_base_name=unkindled -version_range=1.21,1.21.1 - -# Dependencies -fabric_version=0.105.0+1.21.1 \ No newline at end of file +mod_group_id=net.reimaden +mod_authors=Maxmani +mod_description=Makes furnaces require manual ignition to work, and campfires are placed unlit. \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 75c4d72..fd1434c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,11 @@ pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - mavenCentral() - gradlePluginPortal() - } + repositories { + mavenLocal() + gradlePluginPortal() + maven { url = 'https://maven.neoforged.net/releases' } + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } \ No newline at end of file diff --git a/src/main/java/net/reimaden/unkindled/Unkindled.java b/src/main/java/net/reimaden/unkindled/Unkindled.java index ff5a0c6..e6d437d 100644 --- a/src/main/java/net/reimaden/unkindled/Unkindled.java +++ b/src/main/java/net/reimaden/unkindled/Unkindled.java @@ -1,76 +1,85 @@ package net.reimaden.unkindled; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; -import net.minecraft.block.AbstractFurnaceBlock; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.AbstractFurnaceBlockEntity; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.registry.tag.TagKey; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; -import net.minecraft.sound.SoundEvents; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.random.Random; -import net.minecraft.world.event.GameEvent; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.ItemTags; +import net.minecraft.tags.TagKey; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.AbstractFurnaceBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.gameevent.GameEvent; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.common.Tags; +import net.neoforged.neoforge.event.entity.player.UseItemOnBlockEvent; import net.reimaden.unkindled.util.FurnaceUtil; import net.reimaden.unkindled.util.Igniter; -public class Unkindled implements ModInitializer { +@Mod(Unkindled.MOD_ID) +public class Unkindled { public static final String MOD_ID = "unkindled"; - public static final TagKey NEEDS_IGNITING = TagKey.of(RegistryKeys.BLOCK, id("needs_igniting")); - public static final TagKey SELF_IGNITING_FUEL = TagKey.of(RegistryKeys.ITEM, id("self_igniting_fuel")); + public static final TagKey NEEDS_IGNITING = BlockTags.create(id("needs_igniting")); + public static final TagKey SELF_IGNITING_FUEL = ItemTags.create(id("self_igniting_fuel")); - @Override - public void onInitialize() { + public Unkindled() { + NeoForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onUseItemOnBlock(UseItemOnBlockEvent event) { // Event to allow lighting furnaces with any igniter tool // "c:tools/igniter" - UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> { - final BlockPos pos = hitResult.getBlockPos(); - final BlockState state = world.getBlockState(pos); - if (!FurnaceUtil.canBeLit(state) || !player.isSneaking() || player.isSpectator()) return ActionResult.PASS; + final BlockPos pos = event.getPos(); + final Level level = event.getLevel(); + final BlockState state = level.getBlockState(pos); + final Player player = event.getPlayer(); - final ItemStack stack = player.getStackInHand(hand); - final boolean isFireCharge = stack.isOf(Items.FIRE_CHARGE); + if (player == null || !FurnaceUtil.canBeLit(state) || !player.isShiftKeyDown()) return; - if (stack.isIn(ConventionalItemTags.IGNITER_TOOLS) || isFireCharge) { - final Random random = world.getRandom(); - final SoundEvent sound = isFireCharge ? SoundEvents.ITEM_FIRECHARGE_USE : SoundEvents.ITEM_FLINTANDSTEEL_USE; - float pitch = isFireCharge ? (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F : random.nextFloat() * 0.4F + 0.8F; + final InteractionHand hand = event.getHand(); + final ItemStack stack = player.getItemInHand(hand); + final boolean isFireCharge = stack.is(Items.FIRE_CHARGE); - world.playSound(player, pos, sound, SoundCategory.BLOCKS, 1.0F, pitch); - world.setBlockState(pos, state.with(AbstractFurnaceBlock.LIT, true), Block.NOTIFY_ALL_AND_REDRAW); - world.emitGameEvent(player, GameEvent.BLOCK_CHANGE, pos); + if (stack.is(Tags.Items.TOOLS_IGNITER) || isFireCharge) { + final RandomSource random = level.getRandom(); + final SoundEvent sound = isFireCharge ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; + final float pitch = isFireCharge ? (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F : random.nextFloat() * 0.4F + 0.8F; - final BlockEntity blockEntity = world.getBlockEntity(pos); - // Sanity check - if (blockEntity instanceof AbstractFurnaceBlockEntity furnace) { - ((Igniter) furnace).unkindled$setIgnited(true); - } + level.playSound(player, pos, sound, SoundSource.BLOCKS, 1.0F, pitch); + level.setBlock(pos, state.setValue(AbstractFurnaceBlock.LIT, true), Block.UPDATE_ALL_IMMEDIATE); + level.gameEvent(player, GameEvent.BLOCK_CHANGE, pos); - if (isFireCharge) { - stack.decrementUnlessCreative(1, player); - } else { - stack.damage(1, player, LivingEntity.getSlotForHand(hand)); - } + // Sanity check + if (level.getBlockEntity(pos) instanceof AbstractFurnaceBlockEntity furnace) { + ((Igniter) furnace).unkindled$setIgnited(true); + } - return ActionResult.success(world.isClient()); + if (isFireCharge) { + stack.consume(1, player); + } else { + stack.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand)); } - return ActionResult.PASS; - }); + event.cancelWithResult(ItemInteractionResult.sidedSuccess(level.isClientSide())); + } } - public static Identifier id(String path) { - return Identifier.of(MOD_ID, path); + public static ResourceLocation id(String path) { + return ResourceLocation.fromNamespaceAndPath(MOD_ID, path); } } diff --git a/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityAccessor.java b/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityAccessor.java index 2fd5eb1..07e19c5 100644 --- a/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityAccessor.java +++ b/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityAccessor.java @@ -1,15 +1,15 @@ package net.reimaden.unkindled.mixin; -import net.minecraft.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(AbstractFurnaceBlockEntity.class) public interface AbstractFurnaceBlockEntityAccessor { - @Accessor("cookTime") - int unkindled$cookTime(); + @Accessor("cookingProgress") + int unkindled$cookingProgress(); - @Invoker("isBurning") - boolean unkindled$isBurning(); + @Invoker("isLit") + boolean unkindled$isLit(); } diff --git a/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityMixin.java b/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityMixin.java index d4bc8c9..e4f4c6f 100644 --- a/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityMixin.java +++ b/src/main/java/net/reimaden/unkindled/mixin/AbstractFurnaceBlockEntityMixin.java @@ -2,15 +2,14 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.block.AbstractFurnaceBlock; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.AbstractFurnaceBlockEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.registry.RegistryWrapper; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.AbstractFurnaceBlock; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.world.level.block.state.BlockState; import net.reimaden.unkindled.Unkindled; import net.reimaden.unkindled.util.Igniter; import org.spongepowered.asm.mixin.Mixin; @@ -36,56 +35,56 @@ public abstract class AbstractFurnaceBlockEntityMixin implements Igniter { @SuppressWarnings("UnresolvedMixinReference") @ModifyExpressionValue( - method = "tick", + method = "serverTick", at = @At( value = "INVOKE:FIRST", - target = "Lnet/minecraft/block/entity/AbstractFurnaceBlockEntity;canAcceptRecipeOutput(Lnet/minecraft/registry/DynamicRegistryManager;Lnet/minecraft/recipe/RecipeEntry;Lnet/minecraft/util/collection/DefaultedList;I)Z" + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/core/NonNullList;ILnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;)Z" ) ) - private static boolean unkindled$requiresIgniting(boolean original, World world, BlockPos pos, BlockState state, + private static boolean unkindled$requiresIgniting(boolean original, Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity blockEntity, @Local(ordinal = 0) ItemStack stack) { - if (!state.isIn(Unkindled.NEEDS_IGNITING) || stack.isIn(Unkindled.SELF_IGNITING_FUEL)) { + if (!state.is(Unkindled.NEEDS_IGNITING) || stack.is(Unkindled.SELF_IGNITING_FUEL)) { return original; } return original && ((Igniter) blockEntity).unkindled$isIgnited(); } @Inject( - method = "tick", + method = "serverTick", at = @At( "TAIL" ) ) - private static void unkindled$setUnignited(World world, BlockPos pos, BlockState state, + private static void unkindled$setUnignited(Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity blockEntity, CallbackInfo ci) { - if (!state.get(AbstractFurnaceBlock.LIT)) { - if (((AbstractFurnaceBlockEntityAccessor) blockEntity).unkindled$cookTime() > 0) { + if (!state.getValue(AbstractFurnaceBlock.LIT)) { + if (((AbstractFurnaceBlockEntityAccessor) blockEntity).unkindled$cookingProgress() > 0) { return; } ((Igniter) blockEntity).unkindled$setIgnited(false); - } else if (!((AbstractFurnaceBlockEntityAccessor) blockEntity).unkindled$isBurning()) { - state = state.with(AbstractFurnaceBlock.LIT, false); - world.setBlockState(pos, state, Block.NOTIFY_ALL); + } else if (!((AbstractFurnaceBlockEntityAccessor) blockEntity).unkindled$isLit()) { + state = state.setValue(AbstractFurnaceBlock.LIT, false); + level.setBlockAndUpdate(pos, state); } } @Inject( - method = "readNbt", + method = "loadAdditional", at = @At( "TAIL" ) ) - private void unkindled$readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup, CallbackInfo ci) { - this.unkindled$ignited = nbt.getBoolean("Ignited"); + private void unkindled$readNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { + this.unkindled$ignited = tag.getBoolean("Ignited"); } @Inject( - method = "writeNbt", + method = "saveAdditional", at = @At( "TAIL" ) ) - private void unkindled$writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup, CallbackInfo ci) { - nbt.putBoolean("Ignited", this.unkindled$ignited); + private void unkindled$writeNbt(CompoundTag tag, HolderLookup.Provider registries, CallbackInfo ci) { + tag.putBoolean("Ignited", this.unkindled$ignited); } } diff --git a/src/main/java/net/reimaden/unkindled/mixin/CampfireBlockMixin.java b/src/main/java/net/reimaden/unkindled/mixin/CampfireBlockMixin.java index 98aeaee..10d35d4 100644 --- a/src/main/java/net/reimaden/unkindled/mixin/CampfireBlockMixin.java +++ b/src/main/java/net/reimaden/unkindled/mixin/CampfireBlockMixin.java @@ -1,27 +1,27 @@ package net.reimaden.unkindled.mixin; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import net.minecraft.block.BlockWithEntity; -import net.minecraft.block.CampfireBlock; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.CampfireBlock; import net.reimaden.unkindled.Unkindled; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @Mixin(CampfireBlock.class) -public abstract class CampfireBlockMixin extends BlockWithEntity { - protected CampfireBlockMixin(Settings settings) { - super(settings); +public abstract class CampfireBlockMixin extends BaseEntityBlock { + protected CampfireBlockMixin(Properties properties) { + super(properties); } @SuppressWarnings("UnresolvedMixinReference") @ModifyExpressionValue( - method = "getPlacementState", + method = "getStateForPlacement", at = @At( value = "INVOKE:LAST", target = "Ljava/lang/Boolean;valueOf(Z)Ljava/lang/Boolean;" ) ) private Boolean unkindled$isUnlitByDefault(Boolean original) { - return original && !this.getDefaultState().isIn(Unkindled.NEEDS_IGNITING); + return original && !this.defaultBlockState().is(Unkindled.NEEDS_IGNITING); } } diff --git a/src/main/java/net/reimaden/unkindled/mixin/FlintAndSteelDispenserBehaviorMixin.java b/src/main/java/net/reimaden/unkindled/mixin/FlintAndSteelDispenserBehaviorMixin.java index b29f02a..ae8245d 100644 --- a/src/main/java/net/reimaden/unkindled/mixin/FlintAndSteelDispenserBehaviorMixin.java +++ b/src/main/java/net/reimaden/unkindled/mixin/FlintAndSteelDispenserBehaviorMixin.java @@ -1,13 +1,14 @@ package net.reimaden.unkindled.mixin; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.AbstractFurnaceBlockEntity; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; +import net.minecraft.core.BlockPos; +import net.minecraft.core.dispenser.OptionalDispenseItemBehavior; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.AbstractFurnaceBlock; +import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.gameevent.GameEvent; import net.reimaden.unkindled.util.FurnaceUtil; import net.reimaden.unkindled.util.Igniter; import org.spongepowered.asm.mixin.Mixin; @@ -15,30 +16,23 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(targets = "net.minecraft.block.dispenser.DispenserBehavior$17") -public abstract class FlintAndSteelDispenserBehaviorMixin { - @ModifyExpressionValue( - method = "dispenseSilently", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/block/CandleCakeBlock;canBeLit(Lnet/minecraft/block/BlockState;)Z" - ) - ) - private boolean unkindled$allowUsingOnFurnaces(boolean original, @Local BlockState state) { - return original || FurnaceUtil.canBeLit(state); - } - +@Mixin(targets = "net.minecraft.core.dispenser.DispenseItemBehavior$8") +public abstract class FlintAndSteelDispenserBehaviorMixin extends OptionalDispenseItemBehavior { @Inject( - method = "dispenseSilently", + method = "execute", at = @At( - value = "FIELD", - target = "Lnet/minecraft/world/event/GameEvent;BLOCK_CHANGE:Lnet/minecraft/registry/entry/RegistryEntry$Reference;" + value = "INVOKE", + target = "Lnet/minecraft/core/dispenser/DispenseItemBehavior$8;isSuccess()Z" ) ) - private void unkindled$setIgnited(CallbackInfoReturnable cir, @Local ServerWorld world, @Local BlockPos pos) { - BlockEntity blockEntity = world.getBlockEntity(pos); - if (blockEntity instanceof AbstractFurnaceBlockEntity furnace) { + private void unkindled$useOnFurnaces(CallbackInfoReturnable cir, @Local(ordinal = 0) BlockState state, + @Local(ordinal = 0) ServerLevel level, @Local(ordinal = 0) BlockPos pos) { + if (FurnaceUtil.canBeLit(state) && level.getBlockEntity(pos) instanceof AbstractFurnaceBlockEntity furnace) { + level.setBlockAndUpdate(pos, state.setValue(AbstractFurnaceBlock.LIT, true)); + level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos); ((Igniter) furnace).unkindled$setIgnited(true); + + this.setSuccess(true); } } } diff --git a/src/main/java/net/reimaden/unkindled/util/FurnaceUtil.java b/src/main/java/net/reimaden/unkindled/util/FurnaceUtil.java index 8a2db35..c00370b 100644 --- a/src/main/java/net/reimaden/unkindled/util/FurnaceUtil.java +++ b/src/main/java/net/reimaden/unkindled/util/FurnaceUtil.java @@ -1,11 +1,11 @@ package net.reimaden.unkindled.util; -import net.minecraft.block.AbstractFurnaceBlock; -import net.minecraft.block.BlockState; +import net.minecraft.world.level.block.AbstractFurnaceBlock; +import net.minecraft.world.level.block.state.BlockState; import net.reimaden.unkindled.Unkindled; public class FurnaceUtil { public static boolean canBeLit(BlockState state) { - return state.isIn(Unkindled.NEEDS_IGNITING, s -> s.contains(AbstractFurnaceBlock.LIT) && !state.get(AbstractFurnaceBlock.LIT)); + return state.is(Unkindled.NEEDS_IGNITING, s -> s.hasProperty(AbstractFurnaceBlock.LIT) && !state.getValue(AbstractFurnaceBlock.LIT)); } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json deleted file mode 100644 index 4fe21f1..0000000 --- a/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "schemaVersion": 1, - "id": "unkindled", - "version": "${version}", - "name": "Unkindled", - "description": "Makes furnaces require manual ignition to work, and campfires are placed unlit.", - "authors": [ - "Maxmani" - ], - "contact": { - "homepage": "https://modrinth.com/mod/unkindled", - "sources": "https://github.com/Reimaden-Modding/unkindled", - "issues": "https://github.com/Reimaden-Modding/unkindled/issues" - }, - "license": "MIT", - "icon": "assets/unkindled/icon.png", - "environment": "*", - "entrypoints": { - "main": [ - "net.reimaden.unkindled.Unkindled" - ] - }, - "mixins": [ - "unkindled.mixins.json" - ], - "depends": { - "fabricloader": "*", - "minecraft": "~1.21", - "java": ">=21", - "fabric-api": "*" - } -} \ No newline at end of file diff --git a/src/main/templates/META-INF/neoforge.mods.toml b/src/main/templates/META-INF/neoforge.mods.toml new file mode 100644 index 0000000..cf9f355 --- /dev/null +++ b/src/main/templates/META-INF/neoforge.mods.toml @@ -0,0 +1,31 @@ +modLoader="javafml" +loaderVersion="${loader_version_range}" +license="${mod_license}" +issueTrackerURL="https://github.com/Reimaden-Modding/unkindled/issues" + +[[mods]] +modId="${mod_id}" +version="${mod_version}" +displayName="${mod_name}" +displayURL="https://modrinth.com/mod/unkindled" +logoFile="assets/${mod_id}/icon.png" +#credits="" +authors="${mod_authors}" +description='''${mod_description}''' + +[[mixins]] +config="${mod_id}.mixins.json" + +[[dependencies.${mod_id}]] #optional + modId="neoforge" + type="required" + versionRange="${neo_version_range}" + ordering="NONE" + side="BOTH" + +[[dependencies.${mod_id}]] + modId="minecraft" + type="required" + versionRange="${minecraft_version_range}" + ordering="NONE" + side="BOTH" \ No newline at end of file