From 0c71ea88d95c10d78af9b34de2b8804f469fd4f8 Mon Sep 17 00:00:00 2001 From: Michael Hillcox Date: Mon, 30 Oct 2023 21:45:50 +0000 Subject: [PATCH] feat: rewrites :D --- CHANGELOG.md | 14 ++ .../java/dev/wuffs/squatgrow/SquatAction.java | 127 +++++++++--------- .../java/dev/wuffs/squatgrow/SquatGrow.java | 66 +-------- .../dev/wuffs/squatgrow/actions/Action.java | 26 ++++ .../squatgrow/actions/ActionContext.java | 16 +++ .../dev/wuffs/squatgrow/actions/Actions.java | 60 +++++++++ .../squatgrow/actions/BoneMealAction.java | 32 +++++ .../squatgrow/actions/GrowCropAction.java | 30 +++++ .../actions/RandomTickableAction.java | 42 ++++++ .../actions/integrations/AE2Action.java | 32 +++++ .../actions/integrations/MysticalAction.java | 27 ++++ .../actions/special/DirtToGrassAction.java | 31 +++++ .../squatgrow/config/SquatGrowConfig.java | 19 ++- forge/build.gradle | 6 + gradle.properties | 2 +- 15 files changed, 399 insertions(+), 131 deletions(-) create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/Action.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/ActionContext.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/Actions.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/BoneMealAction.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/GrowCropAction.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/RandomTickableAction.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/integrations/AE2Action.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/integrations/MysticalAction.java create mode 100644 common/src/main/java/dev/wuffs/squatgrow/actions/special/DirtToGrassAction.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 341ba73..973bb13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ # Changelog All notable changes to this project will be documented in this file. +## [5.2.0] + +### Added + +- An new action that allows the player to hold a grass block in their offhand to quickly squat to convert dirt to grass + +### Fixed + +- Fixed another crash causing clients to be disconnected from the server or crash in single player due to poor validation + +### Changed + +- Rewrote most of the mod to be more robust and extendable + ## [5.1.1] ### Fixed diff --git a/common/src/main/java/dev/wuffs/squatgrow/SquatAction.java b/common/src/main/java/dev/wuffs/squatgrow/SquatAction.java index 2df7314..c50b1db 100644 --- a/common/src/main/java/dev/wuffs/squatgrow/SquatAction.java +++ b/common/src/main/java/dev/wuffs/squatgrow/SquatAction.java @@ -1,34 +1,29 @@ package dev.wuffs.squatgrow; +import dev.wuffs.squatgrow.actions.Action; +import dev.wuffs.squatgrow.actions.ActionContext; +import dev.wuffs.squatgrow.actions.Actions; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.tags.ItemTags; -import net.minecraft.tags.TagKey; +import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BoneMealItem; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; +import java.util.Set; + import static dev.wuffs.squatgrow.SquatGrow.config; public class SquatAction { - private static final TagKey MYSTICAL_TAG = TagKey.create(Registries.BLOCK, new ResourceLocation("mysticalagriculture", "crops")); - private static final TagKey AE2_TAG = TagKey.create(Registries.BLOCK, new ResourceLocation("ae2", "growth_acceleratable")); - - public static boolean isMysticalLoaded = false; - public static boolean isAE2Loaded = false; - public static void performAction(Level level, Player player) { if (level.isClientSide) return; if (!config.allowAdventureTwerking && ((ServerPlayer) player).gameMode.getGameModeForPlayer() == GameType.ADVENTURE) return; @@ -44,55 +39,54 @@ public static void grow(Level level, ServerPlayer player) { var r = level.random; + // Actions + Set actions = Actions.get().getActions(); + for (int x = -config.range; x <= config.range; x++) { for (int z = -config.range; z <= config.range; z++) { for (int y = -1; y <= 1; y++) { - double randomValue = 0 + (1 - 0) * r.nextDouble(); - if (config.debug) { - SquatGrow.getLogger().debug("Rand value:" + randomValue); + double randomValue = 0 + 1 * r.nextDouble(); + if (randomValue < config.chance) { + continue; } - if (config.chance >= randomValue) { - boolean didGrow = false; - BlockPos blockPos = new BlockPos(pos.getX() + x, pos.getY() + y, pos.getZ() + z); - BlockState blockState = level.getBlockState(blockPos); - Block block = blockState.getBlock(); - if (isMysticalLoaded && block.builtInRegistryHolder().tags().toList().contains(MYSTICAL_TAG) && config.enableMysticalCrops) { - ((CropBlock) block).growCrops(level, blockPos, level.getBlockState(blockPos)); - didGrow = true; - } else if (isAE2Loaded && block.builtInRegistryHolder().tags().toList().contains(AE2_TAG) && config.enableMysticalCrops) { - SquatGrow.getLogger().debug("Ticking ae2 block: " + level.getBlockState(blockPos).getBlock().arch$registryName().toString() + " " + config.ae2Multiplier + " times"); - for (int i = 0; i < config.sugarcaneMultiplier; i++) { - block.randomTick(level.getBlockState(blockPos), ((ServerLevel) level), blockPos, level.random); - } - didGrow = true; + + boolean didGrow = false; + BlockPos offsetLocation = pos.offset(x, y, z); + BlockState offsetState = level.getBlockState(offsetLocation); + + if (offsetState.isAir() || !SquatGrow.allowTwerk(offsetState)) { + continue; + } + + ActionContext context = new ActionContext( + level, + offsetLocation, + offsetState, + player.getMainHandItem(), + player.getOffhandItem(), + player + ); + + for (Action action : actions) { + if (!action.canApply(context)) { + continue; } - if ((block instanceof BonemealableBlock || block instanceof SugarCaneBlock) && SquatGrow.allowTwerk(blockState)) { - if (block instanceof SugarCaneBlock) { - // Todo make this a loop with a config option for the multiplier - SquatGrow.getLogger().debug("Ticking sugarcane block: " + config.sugarcaneMultiplier + " times"); - for (int i = 0; i < config.sugarcaneMultiplier; i++) { - block.randomTick(blockState, ((ServerLevel) level), blockPos, level.random); - } - didGrow = true; - } else { - - BoneMealItem.growCrop(new ItemStack(Items.BONE_MEAL), level, blockPos); - didGrow = true; + + didGrow = action.execute(context); + } + + if (didGrow) { + if (config.requireHoe && config.hoeTakesDamage) { + ItemStack hoe = player.getMainHandItem(); + if (!hoe.is(ItemTags.HOES)) { + hoe = player.getOffhandItem(); } -// ((ServerWorld) level).sendParticles((ServerPlayerEntity) player, ParticleTypes.HAPPY_VILLAGER, false, blockPos.getX() + 0.5D, blockPos.getY() + 0.5D, blockPos.getZ() + 0.1D, 10, 0.5, 0.5, 0.5, 3); - } -// - if (didGrow) { - addGrowthParticles((ServerLevel) level, blockPos, player); - } - if (config.debug) { - SquatGrow.getLogger().debug("===================================================="); -// SquatGrow.getLogger().debug("Block: " + Registry.BLOCK.getKey(block).toString()); - SquatGrow.getLogger().debug("Tags: " + block.builtInRegistryHolder().tags().toList().toString()); - SquatGrow.getLogger().debug("Pos: " + blockPos); - SquatGrow.getLogger().debug("===================================================="); + hoe.hurtAndBreak(1, player, (playerEntity) -> { + playerEntity.broadcastBreakEvent(player.getUsedItemHand()); + }); } + addGrowthParticles((ServerLevel) level, offsetLocation, player); } } } @@ -105,7 +99,7 @@ private static void addGrowthParticles(ServerLevel level, BlockPos pos, ServerPl BlockState blockstate = level.getBlockState(pos); if (!blockstate.isAir()) { - double d0 = 0.5D; + double d0 = 0.5D; // Gaz what was this for? double d1; if (blockstate.is(Blocks.WATER)) { numParticles *= 3; @@ -119,25 +113,30 @@ private static void addGrowthParticles(ServerLevel level, BlockPos pos, ServerPl } else { d1 = blockstate.getShape(level, pos).max(Direction.Axis.Y); } - level.sendParticles(player, ParticleTypes.HAPPY_VILLAGER, false, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, numParticles, 0.0D, 0.0D, 0.5, 0.5); + + var randomPartialCount = random.nextInt(1, numParticles); // Something can cause this to mutate BlockPos immutablePos = pos.immutable(); - for (int i = 0; i < numParticles; ++i) { - double d2 = random.nextGaussian() * 0.02D; - double d3 = random.nextGaussian() * 0.02D; - double d4 = random.nextGaussian() * 0.02D; - double d5 = 0.5D - d0; - double x = immutablePos.getX() + d5 + random.nextInt() * d0 * 2; - double y = immutablePos.getY() + random.nextInt() * d1; - double z = immutablePos.getZ() + d5 + random.nextInt() * d0 * 2; + for (int i = 0; i < randomPartialCount; ++i) { + double d2 = random.nextGaussian() * 0.2D; + double d3 = random.nextGaussian() * 0.2D; + double d4 = random.nextGaussian() * 0.2D; + + var randomY = Mth.clamp(random.nextDouble(), 0.1, 0.5); + + // Randomly place a particle somewhere within the blocks x and z + double x = immutablePos.getX() + Mth.clamp(random.nextDouble(), -1D, 1D); + double y = (immutablePos.getY() - .95D) + (d1 + randomY); + double z = immutablePos.getZ() + Mth.clamp(random.nextDouble(), -1D, 1D); BlockState state = level.getBlockState(immutablePos); if (!state.isAir()) { level.sendParticles(player, ParticleTypes.HAPPY_VILLAGER, false, x, y, z, numParticles, d2, d3, d4, 0.5); - level.playSound(null, immutablePos, SoundEvents.BONE_MEAL_USE, SoundSource.MASTER, 0.5F, 1.0F); } } + + level.playSound(null, immutablePos, SoundEvents.BONE_MEAL_USE, SoundSource.MASTER, 0.5F, 1.0F); } } } diff --git a/common/src/main/java/dev/wuffs/squatgrow/SquatGrow.java b/common/src/main/java/dev/wuffs/squatgrow/SquatGrow.java index 7187719..4298616 100644 --- a/common/src/main/java/dev/wuffs/squatgrow/SquatGrow.java +++ b/common/src/main/java/dev/wuffs/squatgrow/SquatGrow.java @@ -1,9 +1,8 @@ package dev.wuffs.squatgrow; import dev.architectury.event.events.common.LifecycleEvent; -import dev.architectury.event.events.common.TickEvent; -import dev.architectury.platform.Platform; import dev.architectury.registry.ReloadListenerRegistry; +import dev.wuffs.squatgrow.actions.Actions; import dev.wuffs.squatgrow.config.SquatGrowConfig; import me.shedaniel.autoconfig.AutoConfig; import me.shedaniel.autoconfig.ConfigHolder; @@ -17,8 +16,8 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.Set; @@ -26,10 +25,7 @@ public class SquatGrow { public static final String MOD_ID = "squatgrow"; - private static final Logger LOGGER = LogManager.getLogger(); - public static Logger getLogger() { - return LOGGER; - } + private static final Logger LOGGER = LoggerFactory.getLogger(SquatGrow.class); public static SquatGrowConfig config; public static ConfigHolder configHolder; @@ -58,8 +54,8 @@ public void onResourceManagerReload(ResourceManager manager) { } private static void onSetup() { - SquatAction.isMysticalLoaded = Platform.isModLoaded("mysticalagriculture"); - SquatAction.isAE2Loaded = Platform.isModLoaded("ae2"); + LOGGER.debug("Starting setup"); + Actions.get().setup(); } /** @@ -87,56 +83,6 @@ private static InteractionResult onConfigChanged(ConfigHolder h public static Boolean allowTwerk(BlockState state) { return config.useWhitelist == isBlockInIgnoreList(state); -// ResourceLocation resourceLocation = state.getBlock().arch$registryName(); -// if (wildcardCache.contains(resourceLocation.getNamespace())) { -// -// } -// var regName = Registry.BLOCK.getKey(state.getBlock()).toString(); -// var rawTags = state.getBlock().builtInRegistryHolder().tags().toList(); -// if (config.useWhitelist) { -// if (config.ignorelist.contains(regName)) { -// if (config.debug) { -// LOGGER.debug("Whitelist contains reg: " + regName); -// } -// return true; -// } -// if (rawTags.size() > 0) { -// for (TagKey tag : rawTags) { -// if (config.ignorelist.contains("#" + tag.location().toString())) { -// if (config.debug) { -// LOGGER.debug("Whitelist contains tag: " + "#" + tag.location()); -// } -// return true; -// } -// } -// } -// if (config.debug) { -// LOGGER.debug("Whitelist does NOT contain: " + regName); -// } -// return false; -// } -// -// if (config.ignorelist.contains(regName)) { -// if (config.debug) { -// LOGGER.debug("Blacklist contains reg: " + regName); -// } -// return false; -// } -// -// if (rawTags.size() > 0) { -// for (TagKey tag : rawTags) { -// if (config.ignorelist.contains("#" + tag.location().toString())) { -// return false; -// } -// if (config.debug) { -// LOGGER.debug("Blacklist does NOT contain tag: " + "#" + tag.location()); -// } -// } -// } -// if (config.debug) { -// LOGGER.debug("Nothing contains: " + regName); -// } -// return true; } private static boolean isBlockInIgnoreList(BlockState state) { diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/Action.java b/common/src/main/java/dev/wuffs/squatgrow/actions/Action.java new file mode 100644 index 0000000..1274066 --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/Action.java @@ -0,0 +1,26 @@ +package dev.wuffs.squatgrow.actions; + +import java.util.function.BooleanSupplier; + +public interface Action { + BooleanSupplier TRUE = () -> true; + BooleanSupplier FALSE = () -> false; + + /** + * Only called once upon initial creation of the available actions list. + * This is loaded after game setup and thus is safe to use mod loaded checking. + *

+ * Running modded code here is not recommended unless you register your action only + * when your mod is present. + */ + BooleanSupplier isAvailable(); + + /** + * Called upon the action being available and the block is about to be actioned upon. + * + * @return if we should continue to apply the action. + */ + boolean canApply(ActionContext context); + + boolean execute(ActionContext context); +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/ActionContext.java b/common/src/main/java/dev/wuffs/squatgrow/actions/ActionContext.java new file mode 100644 index 0000000..60ac1ce --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/ActionContext.java @@ -0,0 +1,16 @@ +package dev.wuffs.squatgrow.actions; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +public record ActionContext( + Level level, + BlockPos pos, + BlockState state, + ItemStack mainHand, + ItemStack offhand, + Player player +) {} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/Actions.java b/common/src/main/java/dev/wuffs/squatgrow/actions/Actions.java new file mode 100644 index 0000000..8bfbc3e --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/Actions.java @@ -0,0 +1,60 @@ +package dev.wuffs.squatgrow.actions; + +import com.google.common.collect.ImmutableSet; +import dev.wuffs.squatgrow.actions.integrations.MysticalAction; +import dev.wuffs.squatgrow.actions.integrations.AE2Action; +import dev.wuffs.squatgrow.actions.special.DirtToGrassAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Supplier; + +public enum Actions { + INSTANCE; + + private static final Logger LOGGER = LoggerFactory.getLogger(Actions.class); + + ImmutableSet actions; + final Set> possibleActions = new HashSet<>(); + + Actions() { + register(RandomTickableAction::new); + register(BoneMealAction::new); + + // Special actions + register(DirtToGrassAction::new); + + // Register integrations + register(MysticalAction::new); + register(AE2Action::new); + } + + public void register(Supplier action) { + this.possibleActions.add(action); + } + + public void setup() { + Set actions = new HashSet<>(); + for (Supplier action : this.possibleActions) { + // Lazy load the action + Action actualAction = action.get(); + if (actualAction.isAvailable().getAsBoolean()) { + actions.add(actualAction); + LOGGER.info("Registered action: {}", action.getClass().getSimpleName()); + } + } + + // Create an immutable set + this.actions = ImmutableSet.copyOf(actions); + } + + public static Actions get() { + return INSTANCE; + } + + public ImmutableSet getActions() { + return actions; + } +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/BoneMealAction.java b/common/src/main/java/dev/wuffs/squatgrow/actions/BoneMealAction.java new file mode 100644 index 0000000..f3c246f --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/BoneMealAction.java @@ -0,0 +1,32 @@ +package dev.wuffs.squatgrow.actions; + +import net.minecraft.world.item.BoneMealItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BonemealableBlock; +import net.minecraft.world.level.block.StemBlock; + +import java.util.function.BooleanSupplier; + +public class BoneMealAction implements Action { + @Override + public BooleanSupplier isAvailable() { + return TRUE; + } + + @Override + public boolean canApply(ActionContext context) { + Block block = context.state().getBlock(); + + return (block instanceof BonemealableBlock && !(block instanceof StemBlock)) || ( + // StemBlocks can't be bone mealed when they're fully grown + block instanceof StemBlock && context.state().getValue(StemBlock.AGE) != 7 + ); + } + + @Override + public boolean execute(ActionContext context) { + return BoneMealItem.growCrop(new ItemStack(Items.BONE_MEAL), context.level(), context.pos()); + } +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/GrowCropAction.java b/common/src/main/java/dev/wuffs/squatgrow/actions/GrowCropAction.java new file mode 100644 index 0000000..90a5e80 --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/GrowCropAction.java @@ -0,0 +1,30 @@ +package dev.wuffs.squatgrow.actions; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.CropBlock; + +import java.util.function.BooleanSupplier; + +public class GrowCropAction implements Action { + /** + * Not used by our mod but is likely helpful for others + */ + @Override + public BooleanSupplier isAvailable() { + return FALSE; + } + + @Override + public boolean canApply(ActionContext context) { + return context.state().getBlock() instanceof CropBlock; + } + + @Override + public boolean execute(ActionContext context) { + Block block = context.state().getBlock(); + CropBlock crop = (CropBlock) block; + + crop.growCrops(context.level(), context.pos(), context.state()); + return true; + } +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/RandomTickableAction.java b/common/src/main/java/dev/wuffs/squatgrow/actions/RandomTickableAction.java new file mode 100644 index 0000000..053d585 --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/RandomTickableAction.java @@ -0,0 +1,42 @@ +package dev.wuffs.squatgrow.actions; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.CactusBlock; +import net.minecraft.world.level.block.StemBlock; +import net.minecraft.world.level.block.SugarCaneBlock; + +import java.util.function.BooleanSupplier; + +import static dev.wuffs.squatgrow.SquatGrow.config; + +public class RandomTickableAction implements Action { + @Override + public BooleanSupplier isAvailable() { + return TRUE; + } + + @Override + public boolean canApply(ActionContext context) { + Block block = context.state().getBlock(); + return block instanceof SugarCaneBlock || block instanceof CactusBlock || ( + // StemBlocks can't be random ticked when they're not fully grown but can be when they are + block instanceof StemBlock && context.state().getValue(StemBlock.AGE) == 7 + ); + } + + @Override + public boolean execute(ActionContext context) { + for (int i = 0; i < this.getMultiplier(context); i++) { + context.state() + .randomTick(((ServerLevel) context.level()), context.pos(), context.level().getRandom()); + } + + return true; + } + + public int getMultiplier(ActionContext context) { + // If the old legacy config is using the default value of 4, use the new randomTickMultiplier + return config.sugarcaneMultiplier == 4 ? config.randomTickMultiplier : config.sugarcaneMultiplier; + } +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/integrations/AE2Action.java b/common/src/main/java/dev/wuffs/squatgrow/actions/integrations/AE2Action.java new file mode 100644 index 0000000..8c630b5 --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/integrations/AE2Action.java @@ -0,0 +1,32 @@ +package dev.wuffs.squatgrow.actions.integrations; + +import dev.architectury.platform.Platform; +import dev.wuffs.squatgrow.actions.ActionContext; +import dev.wuffs.squatgrow.actions.RandomTickableAction; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; + +import java.util.function.BooleanSupplier; + +import static dev.wuffs.squatgrow.SquatGrow.config; + +public class AE2Action extends RandomTickableAction { + private static final TagKey AE2_TAG = TagKey.create(Registries.BLOCK, new ResourceLocation("ae2", "growth_acceleratable")); + + @Override + public BooleanSupplier isAvailable() { + return () -> Platform.isModLoaded("ae2") && config.enableAE2Accelerator; + } + + @Override + public boolean canApply(ActionContext context) { + return context.state().is(AE2_TAG); + } + + @Override + public int getMultiplier(ActionContext context) { + return config.ae2Multiplier; + } +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/integrations/MysticalAction.java b/common/src/main/java/dev/wuffs/squatgrow/actions/integrations/MysticalAction.java new file mode 100644 index 0000000..2f86394 --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/integrations/MysticalAction.java @@ -0,0 +1,27 @@ +package dev.wuffs.squatgrow.actions.integrations; + +import dev.architectury.platform.Platform; +import dev.wuffs.squatgrow.actions.ActionContext; +import dev.wuffs.squatgrow.actions.GrowCropAction; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; + +import java.util.function.BooleanSupplier; + +import static dev.wuffs.squatgrow.SquatGrow.config; + +public class MysticalAction extends GrowCropAction { + private static final TagKey MYSTICAL_TAG = TagKey.create(Registries.BLOCK, new ResourceLocation("mysticalagriculture", "crops")); + + @Override + public BooleanSupplier isAvailable() { + return () -> Platform.isModLoaded("mysticalagriculture") && config.enableMysticalCrops; + } + + @Override + public boolean canApply(ActionContext context) { + return super.canApply(context) && context.state().is(MYSTICAL_TAG); + } +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/actions/special/DirtToGrassAction.java b/common/src/main/java/dev/wuffs/squatgrow/actions/special/DirtToGrassAction.java new file mode 100644 index 0000000..e34e299 --- /dev/null +++ b/common/src/main/java/dev/wuffs/squatgrow/actions/special/DirtToGrassAction.java @@ -0,0 +1,31 @@ +package dev.wuffs.squatgrow.actions.special; + +import dev.wuffs.squatgrow.actions.Action; +import dev.wuffs.squatgrow.actions.ActionContext; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; + +import static dev.wuffs.squatgrow.SquatGrow.config; +import java.util.function.BooleanSupplier; + +/** + * Special action that will allow you to grow grass when standing on dirt + * if the player has a grass block in their offhand. + */ +public class DirtToGrassAction implements Action { + @Override + public BooleanSupplier isAvailable() { + return () -> config.enableDirtToGrass; + } + + @Override + public boolean canApply(ActionContext context) { + return context.offhand().is(Items.GRASS_BLOCK) && context.state().is(Blocks.DIRT); + } + + @Override + public boolean execute(ActionContext context) { + context.level().setBlockAndUpdate(context.pos(), Blocks.GRASS_BLOCK.defaultBlockState()); + return true; + } +} diff --git a/common/src/main/java/dev/wuffs/squatgrow/config/SquatGrowConfig.java b/common/src/main/java/dev/wuffs/squatgrow/config/SquatGrowConfig.java index fcb7f80..d05a27b 100644 --- a/common/src/main/java/dev/wuffs/squatgrow/config/SquatGrowConfig.java +++ b/common/src/main/java/dev/wuffs/squatgrow/config/SquatGrowConfig.java @@ -12,30 +12,33 @@ @Config(name = SquatGrow.MOD_ID + "-common") public class SquatGrowConfig implements ConfigData { - @Comment("Enable debug logging") public boolean debug = false; @Comment("Require hoe to allow growth") public boolean requireHoe = false; -// @Comment("Hoe takes damage on growth") -// public boolean hoeTakesDamage = true; + @Comment("Hoe takes damage on growth") + public boolean hoeTakesDamage = false; @Comment("Use whitelist instead of blacklist, default false") public boolean useWhitelist = false; - @Comment("Range of effect") + @Comment("Range of effect, warning: this can cause lag if set too high") @ConfigEntry.BoundedDiscrete(min = 0, max = 16) public int range = 3; @Comment("Growth chance") public double chance = 0.5; - @Comment("Sugarcane multiplier") + @Comment("Don't use! Use randomTickMultiplier instead, this is here for backwards compatibility") @ConfigEntry.BoundedDiscrete(min = 1, max = 16) public int sugarcaneMultiplier = 4; + @Comment("Random tick multiplier, this is the amount of times the mod will call the randomTick method on the block for each block in the range") + @ConfigEntry.BoundedDiscrete(min = 1, max = 16) + public int randomTickMultiplier = 4; + @Comment("List of blocks to blacklist/whitelist from twerking, Tags can be used by using #minecraft: or #modid:") public List ignoreList = new ArrayList<>(Arrays.asList( "minecraft:grass_block", @@ -45,6 +48,7 @@ public class SquatGrowConfig implements ConfigData { "minecraft:warped_nylium", "minecraft:crimson_nylium" )); + @Comment("Allow twerking in adventure mode, default true") public boolean allowAdventureTwerking = true; @@ -54,7 +58,10 @@ public class SquatGrowConfig implements ConfigData { @Comment("Enable AE2 accelerator") public boolean enableAE2Accelerator = true; - @Comment("AE2 growth multiplier") + @Comment("AE2 growth multiplier, only available if AE2 is present") @ConfigEntry.BoundedDiscrete(min = 1, max = 16) public int ae2Multiplier = 4; + + @Comment("When the player is holding a grass block in their offhand, they will be able to randomly convert dirt into grass") + public boolean enableDirtToGrass = true; } diff --git a/forge/build.gradle b/forge/build.gradle index 41dbf9e..4280f5f 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -46,6 +46,12 @@ dependencies { modApi("me.shedaniel.cloth:cloth-config-forge:${rootProject.cloth_config_version}") // modRuntimeOnly("curse.maven:canary-665658:4668137") +// modRuntimeOnly("curse.maven:applied-energistics-2-223794:4783930") +// modRuntimeOnly("curse.maven:mystical-agriculture-246640:4802036") +// modRuntimeOnly("curse.maven:cucumber-272335:4825638") +// modRuntimeOnly("curse.maven:apotheosis-313970:4724390") +// modRuntimeOnly("curse.maven:placebo-283644:4723708") +// modRuntimeOnly("curse.maven:apothic-attributes-898963:4731488") common(project(path: ":common", configuration: "namedElements")) { transitive false } shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false } diff --git a/gradle.properties b/gradle.properties index fcb2022..13be800 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ minecraft_version=1.20.1 enabled_platforms=fabric,forge archives_base_name=squatgrow -mod_version=5.1.1 +mod_version=5.2.0 maven_group=dev.wuffs architectury_version=9.1.12