Skip to content

Commit

Permalink
DispenserItemBehavior for flint and brick.
Browse files Browse the repository at this point in the history
  • Loading branch information
Waterpicker committed Nov 26, 2022
1 parent 9207c88 commit 6b61c38
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.gson.JsonObject;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockSource;
import net.minecraft.core.Direction;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
Expand Down Expand Up @@ -969,6 +970,18 @@ public void onEquip(IToolStackView tool, int level, EquipmentChangeContext conte
*/
public void onEquipmentChange(IToolStackView tool, int level, EquipmentChangeContext context, EquipmentSlot slotType) {}

/**
* Called when a stack is being used within a dispenser.
* <br>
* @param tool Tool instance
* @param level Modifier level
* @param source Block source
* @param stack Stack being dispensed
* @return True if dispenser action was taken
*/
public boolean onDispenserUse(IToolStackView tool, int level, BlockSource source, ItemStack stack) {
return false;
}

/* Display */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ public Iterable<BlockPos> getBlocks(IToolStackView tool, ItemStack stack, Player
* @return List of block positions
*/
public static Iterable<BlockPos> calculate(IToolStackView tool, ItemStack stack, Level world, Player player, BlockPos origin, Direction sideHit, int diameter, boolean is3D, AOEMatchType matchType) {
return calculate(tool, stack, world, player.getDirection(), origin, sideHit, diameter, is3D, matchType);
}

/**
*
* @param tool Tool used for harvest
* @param stack Item stack used for harvest (for vanilla hooks)
* @param world World containing the block
* @param harvestDirection Player harvesting
* @param origin Center of harvest
* @param sideHit Block side hit
* @param diameter Circle diameter
* @param matchType Type of harvest being performed
* @return List of block positions
*/
public static Iterable<BlockPos> calculate(IToolStackView tool, ItemStack stack, Level world, Direction harvestDirection, BlockPos origin, Direction sideHit, int diameter, boolean is3D, AOEMatchType matchType) {
// skip if no work
if (diameter == 1) {
return Collections.emptyList();
Expand All @@ -67,11 +83,27 @@ public static Iterable<BlockPos> calculate(IToolStackView tool, ItemStack stack,
// math works out that we can leave this an integer and get the radius working still
int radiusSq = diameter * diameter / 4;
Predicate<BlockPos> posPredicate = IAreaOfEffectIterator.defaultBlockPredicate(tool, stack, world, origin, matchType);
ExpansionDirections directions = IBoxExpansion.SIDE_HIT.getDirections(player, sideHit);
ExpansionDirections directions = getDirections(harvestDirection, sideHit);
// max needs to be an odd number
return () -> new CircleIterator(origin, directions.width(), directions.height(), directions.traverseDown(), directions.depth(), radiusSq, diameter / 2, is3D, posPredicate);
}

private static ExpansionDirections getDirections(Direction harvestDirection, Direction sideHit) {
// depth is always direction into the block
Direction depth = sideHit.getOpposite();
Direction width, height;
// for Y, direction is based on facing
if (sideHit.getAxis() == Direction.Axis.Y) {
height = harvestDirection;
width = height.getClockWise();
} else {
// for X and Z, just rotate from side hit
width = sideHit.getCounterClockWise();
height = Direction.UP;
}
return new ExpansionDirections(width, height, depth, true);
}

/** Iterator used for getting the blocks, secret is a circle is a rectangle */
private static class CircleIterator extends RectangleIterator {
/* Diameter of the area to mine, circular */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.common.collect.Multimap;
import lombok.Getter;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockSource;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
Expand Down Expand Up @@ -31,8 +32,10 @@
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.ToolAction;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import slimeknights.mantle.client.SafeClientAccess;
Expand Down Expand Up @@ -585,4 +588,8 @@ public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStac
public static BlockHitResult blockRayTrace(Level worldIn, Player player, ClipContext.Fluid fluidMode) {
return Item.getPlayerPOVHitResult(worldIn, player, fluidMode);
}

public static UseOnContext contextFromBlockSource(BlockSource source, ItemStack stack) {
return new UseOnContext(source.getLevel(), null, InteractionHand.MAIN_HAND, stack, Util.createTraceResult(source.getPos().relative(source.getBlockState().getValue(DispenserBlock.FACING)), source.getBlockState().getValue(DispenserBlock.FACING), false));
}
}
23 changes: 23 additions & 0 deletions src/main/java/slimeknights/tconstruct/tools/TinkerTools.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package slimeknights.tconstruct.tools;

import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.core.BlockSource;
import net.minecraft.core.Registry;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.core.particles.SimpleParticleType;
import net.minecraft.data.DataGenerator;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.event.RegistryEvent;
Expand All @@ -29,6 +33,7 @@
import slimeknights.tconstruct.library.client.data.material.MaterialPartTextureGenerator;
import slimeknights.tconstruct.library.json.AddToolDataFunction;
import slimeknights.tconstruct.library.json.RandomMaterial;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.IndestructibleItemEntity;
import slimeknights.tconstruct.library.tools.SlotType;
import slimeknights.tconstruct.library.tools.ToolPredicate;
Expand All @@ -52,6 +57,7 @@
import slimeknights.tconstruct.library.tools.helper.ModifierLootingHandler;
import slimeknights.tconstruct.library.tools.item.ModifiableArmorItem;
import slimeknights.tconstruct.library.tools.item.ModifiableItem;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import slimeknights.tconstruct.library.utils.BlockSideHitListener;
import slimeknights.tconstruct.tools.data.StationSlotLayoutProvider;
import slimeknights.tconstruct.tools.data.ToolDefinitionDataProvider;
Expand Down Expand Up @@ -147,6 +153,23 @@ void commonSetup(FMLCommonSetupEvent event) {
EquipmentChangeWatcher.register();
ToolCapabilityProvider.register(ToolFluidCapability.Provider::new);
ToolCapabilityProvider.register(ToolInventoryCapability.Provider::new);

event.enqueueWork(() -> {
DispenseItemBehavior behavior = (source, stack) -> {
ToolStack tool = ToolStack.from(stack);

for (ModifierEntry entry : tool.getModifierList()) {
if (entry.getModifier().onDispenserUse(tool, entry.getLevel(), source, stack)) break;
}

return stack;
};

DispenserBlock.registerBehavior(TinkerTools.flintAndBrick, behavior);
DispenserBlock.registerBehavior(TinkerTools.mattock, behavior);
DispenserBlock.registerBehavior(TinkerTools.handAxe, behavior);
});

for (ConfigurableAction action : Config.COMMON.damageSourceTweaks) {
event.enqueueWork(action);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockSource;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
Expand All @@ -19,6 +20,7 @@
import slimeknights.tconstruct.library.modifiers.impl.InteractionModifier;
import slimeknights.tconstruct.library.tools.definition.aoe.IAreaOfEffectIterator;
import slimeknights.tconstruct.library.tools.helper.ToolDamageUtil;
import slimeknights.tconstruct.library.tools.item.ModifiableItem;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.utils.MutableUseOnContext;

Expand Down Expand Up @@ -127,6 +129,80 @@ public InteractionResult afterBlockUse(IToolStackView tool, int level, UseOnCont
return didTransform ? InteractionResult.sidedSuccess(world.isClientSide) : InteractionResult.PASS;
}

@Override
public boolean onDispenserUse(IToolStackView tool, int level, BlockSource source, ItemStack stack) {
// tool must not be broken
if (tool.isBroken()) {
return false;
}

UseOnContext context = ModifiableItem.contextFromBlockSource(source, stack);

// for hoes and shovels, must have nothing but plants above
if (requireGround && context.getClickedFace() == Direction.DOWN) {
return true;
}

// must actually transform
Level world = context.getLevel();
BlockPos pos = context.getClickedPos();
BlockState original = world.getBlockState(pos);

boolean didTransform = transform(context, original, true);

// if we made a successful transform, client can stop early
if (didTransform) {
if (world.isClientSide) {
return true;
}

// if the tool breaks or it was a campfire, we are done
if (ToolDamageUtil.damage(tool, 1, null, null)) {
return true;
}
}

// AOE transforming, run even if we did not transform the center
// note we consider anything effective, as hoes are not effective on all tillable blocks
// if (player != null && !tool.isBroken()) {
// int totalTransformed = 0;
// Iterator<BlockPos> aoePos = tool.getDefinition().getData().getAOE().getBlocks(tool, stack, player, original, world, pos, context.getClickedFace(), IAreaOfEffectIterator.AOEMatchType.TRANSFORM).iterator();
// if (aoePos.hasNext()) {
// MutableUseOnContext offsetContext = new MutableUseOnContext(context);
// do {
// BlockPos newPos = aoePos.next();
// if (pos.equals(newPos)) {
// continue;
// }
//
// // try interacting with the new position
// offsetContext.setOffsetPos(newPos);
//
// BlockState newTarget = world.getBlockState(newPos);
//
// // limit to playing 40 sounds, that's more than enough for most transforms
// if (transform(offsetContext, newTarget, totalTransformed < 40)) {
// totalTransformed++;
// didTransform = true;
//
// // stop if the tool broke
// if (world.isClientSide || ToolDamageUtil.damageAnimated(tool, 1, player, slotType)) {
// break;
// }
// }
// } while (aoePos.hasNext());
//
// // sweep attack if we transformed any
// if (totalTransformed > 0) {
// player.sweepAttack();
// }
// }
// }

// if anything happened, return success
return didTransform;
}

/** Transforms the given block */
protected boolean transform(UseOnContext context, BlockState original, boolean playSound) {
Level level = context.getLevel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockSource;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
Expand All @@ -21,6 +22,7 @@
import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.CandleBlock;
import net.minecraft.world.level.block.CandleCakeBlock;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.level.block.TntBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
Expand All @@ -31,6 +33,8 @@
import slimeknights.tconstruct.library.tools.definition.aoe.IAreaOfEffectIterator;
import slimeknights.tconstruct.library.tools.helper.ToolDamageUtil;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import slimeknights.tconstruct.library.utils.Util;
import slimeknights.tconstruct.tools.TinkerModifiers;

import javax.annotation.Nullable;
Expand Down Expand Up @@ -161,4 +165,64 @@ public InteractionResult afterBlockUse(IToolStackView tool, int level, UseOnCont
}
return didIgnite ? InteractionResult.sidedSuccess(world.isClientSide) : InteractionResult.PASS;
}

/** Ignites the given block */
private static boolean igniteDispenser(IToolStackView tool, Level world, BlockPos pos, BlockState state, Direction sideHit, Direction horizontalFacing) {
// campfires first
if (CampfireBlock.canLight(state) || CandleBlock.canLight(state) || CandleCakeBlock.canLight(state)) {
world.playSound(null, pos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, RANDOM.nextFloat() * 0.4F + 0.8F);
world.setBlock(pos, state.setValue(BlockStateProperties.LIT, true), 11);
world.gameEvent(null, GameEvent.BLOCK_PLACE, pos);
return true;
}

// ignite the TNT
if (state.getBlock() instanceof TntBlock tnt) {
tnt.onCaughtFire(state, world, pos, sideHit, null);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11);
return true;
}

// fire starting
BlockPos offset = pos.relative(sideHit);
if (BaseFireBlock.canBePlacedAt(world, offset, horizontalFacing)) {
world.playSound(null, offset, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, RANDOM.nextFloat() * 0.4F + 0.8F);
world.setBlock(offset, BaseFireBlock.getState(world, offset), 11);
return true;
}
return false;
}


@Override
public boolean onDispenserUse(IToolStackView tool, int level, BlockSource source, ItemStack stack) {

if (tool.isBroken()) {
return false;
}

Level world = source.getLevel();

Direction interactionDirection = source.getBlockState().getValue(DispenserBlock.FACING);
Direction sideHit = interactionDirection.getOpposite();
BlockPos pos = source.getPos().relative(interactionDirection);
BlockState state = world.getBlockState(pos);


// if targeting fire, offset to behind the fire
boolean targetingFire = state.is(BlockTags.FIRE);

// burn it all in AOE
Direction horizontalFacing = interactionDirection.getAxis() != Direction.Axis.Y ? interactionDirection : Direction.NORTH;
// first burn the center, unless we already know its fire
boolean didIgnite = false;
if (!targetingFire) {
didIgnite = igniteDispenser(tool, world, pos, state, sideHit, horizontalFacing);
if (didIgnite && ToolDamageUtil.damage(tool, 1, null, stack)) {
return true;
}
}

return didIgnite;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package slimeknights.tconstruct.tools.modifiers.ability.tool;

import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockSource;
import net.minecraft.core.Direction;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DispenserBlock;
import slimeknights.tconstruct.library.modifiers.impl.InteractionModifier.NoLevels;
import slimeknights.tconstruct.library.tools.helper.ToolDamageUtil;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import slimeknights.tconstruct.shared.TinkerCommons;

public class GlowingModifier extends NoLevels {
Expand Down Expand Up @@ -39,4 +44,21 @@ public InteractionResult afterBlockUse(IToolStackView tool, int level, UseOnCont
}
return InteractionResult.PASS;
}

@Override
public boolean onDispenserUse(IToolStackView tool, int level, BlockSource source, ItemStack stack) {

if(tool.getCurrentDurability() >= 10) {
Level world = source.getLevel();

Direction facing = source.getBlockState().getValue(DispenserBlock.FACING);
if(TinkerCommons.glow.get().addGlow(world, source.getPos().relative(facing), facing)) {
ToolDamageUtil.damage(tool, 10, null, stack);
world.playSound(null, source.getPos(), source.getBlockState().getSoundType(world, source.getPos(), null).getPlaceSound(), SoundSource.BLOCKS, 1.0f, 10.f);
}
return true;
}

return false;
}
}

0 comments on commit 6b61c38

Please sign in to comment.