mirror of
https://github.com/Ellpeck/ActuallyAdditions.git
synced 2024-12-22 19:39:24 +01:00
Smashing! Although I think the break code is duping sounds
This commit is contained in:
parent
a94af5e247
commit
4f33a9fb2d
5 changed files with 276 additions and 24 deletions
|
@ -1,5 +1,10 @@
|
|||
package de.ellpeck.actuallyadditions.common.config;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static de.ellpeck.actuallyadditions.common.config.Config.COMMON_BUILDER;
|
||||
import static net.minecraftforge.common.ForgeConfigSpec.IntValue;
|
||||
|
||||
|
@ -7,6 +12,7 @@ public class ItemConfig {
|
|||
public final IntValue teleportStaffCost;
|
||||
public final IntValue teleportStaffMaxEnergy;
|
||||
public final IntValue drillMaxEnergy;
|
||||
public final ConfigValue<List<String>> drillSpecialBlockWhitelist;
|
||||
|
||||
public ItemConfig() {
|
||||
COMMON_BUILDER.comment("Item Config Options").push("items");
|
||||
|
@ -25,5 +31,9 @@ public class ItemConfig {
|
|||
drillMaxEnergy = COMMON_BUILDER
|
||||
.comment("The max energy amount for the drill")
|
||||
.defineInRange("Drill Max Energy", 250000, 0, 1000000);
|
||||
|
||||
drillSpecialBlockWhitelist = COMMON_BUILDER
|
||||
.comment("By default, the Drill can mine certain blocks. If there is one that it can't mine, but should be able to, put its REGISTRY NAME here. These are the actual registered Item Names, the ones you use, for example, when using the /give Command.")
|
||||
.define("Drill special block whitelist", ImmutableList.of("examplemod:block_one"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,14 @@ import net.minecraftforge.items.wrapper.InvWrapper;
|
|||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DrillContainer extends Container {
|
||||
private final ItemStackHandler handler;
|
||||
public static final int AUGMENT_SLOT_COUNT = 3;
|
||||
private final ItemStackHandler handler = new ItemStackHandler(AUGMENT_SLOT_COUNT) {
|
||||
@Override
|
||||
public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
|
||||
return stack.getItem() instanceof DrillAugmentItem;
|
||||
}
|
||||
};
|
||||
|
||||
private final PlayerInventory inv;
|
||||
private final ItemStack stack;
|
||||
|
||||
|
@ -34,15 +41,7 @@ public class DrillContainer extends Container {
|
|||
|
||||
ContainerHelper.setupPlayerInventory(new InvWrapper(inv), 0, ContainerHelper.DEFAULT_SLOTS_X, 116, this::addSlot);
|
||||
|
||||
this.handler = new ItemStackHandler(5) {
|
||||
@Override
|
||||
public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
|
||||
return stack.getItem() instanceof DrillAugmentItem;
|
||||
}
|
||||
};
|
||||
|
||||
this.handler.deserializeNBT(this.stack.getOrCreateChildTag("augments"));
|
||||
|
||||
this.handler.deserializeNBT(this.stack.getOrCreateChildTag(DrillItem.NBT_AUGMENT_TAG));
|
||||
this.addContainerSlots();
|
||||
}
|
||||
|
||||
|
@ -53,7 +52,7 @@ public class DrillContainer extends Container {
|
|||
}
|
||||
|
||||
protected void addContainerSlots() {
|
||||
for (int i = 0; i < 5; i ++) {
|
||||
for (int i = 0; i < AUGMENT_SLOT_COUNT; i ++) {
|
||||
addSlot(new SlotItemHandler(handler, i, 44 + (i * ContainerHelper.SLOT_SPACING), 19));
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +88,7 @@ public class DrillContainer extends Container {
|
|||
}
|
||||
} else {
|
||||
// Moves the item from the players inventory to the drill
|
||||
if (!this.mergeItemStack(fromStack, ContainerHelper.PLAYER_INVENTORY_END_SLOT + 1, ContainerHelper.PLAYER_INVENTORY_END_SLOT + 6, false)) {
|
||||
if (!this.mergeItemStack(fromStack, ContainerHelper.PLAYER_INVENTORY_END_SLOT + 1, ContainerHelper.PLAYER_INVENTORY_END_SLOT + (AUGMENT_SLOT_COUNT + 1), false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +100,6 @@ public class DrillContainer extends Container {
|
|||
public void onContainerClosed(@Nonnull PlayerEntity playerIn) {
|
||||
super.onContainerClosed(playerIn);
|
||||
|
||||
this.stack.getOrCreateTag().put("augments", this.handler.serializeNBT());
|
||||
this.stack.getOrCreateTag().put(DrillItem.NBT_AUGMENT_TAG, this.handler.serializeNBT());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import net.minecraft.world.World;
|
|||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.energy.CapabilityEnergy;
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
|
||||
|
@ -72,7 +73,7 @@ public abstract class CrystalFluxItem extends ActuallyItem {
|
|||
public void addInformation(ItemStack stack, @Nullable World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
|
||||
super.addInformation(stack, worldIn, tooltip, flagIn);
|
||||
|
||||
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(energy ->
|
||||
getCrystalFlux(stack).ifPresent(energy ->
|
||||
tooltip.add(this.getEnergyPretty(energy, Screen.hasShiftDown()).mergeStyle(TextFormatting.GRAY)));
|
||||
}
|
||||
|
||||
|
@ -120,8 +121,12 @@ public abstract class CrystalFluxItem extends ActuallyItem {
|
|||
|
||||
@Override
|
||||
public double getDurabilityForDisplay(ItemStack stack) {
|
||||
return stack.getCapability(CapabilityEnergy.ENERGY)
|
||||
return getCrystalFlux(stack)
|
||||
.map(energy -> 1D - (energy.getEnergyStored() / (double) energy.getMaxEnergyStored()))
|
||||
.orElse(0D);
|
||||
}
|
||||
|
||||
public LazyOptional<IEnergyStorage> getCrystalFlux(ItemStack stack) {
|
||||
return stack.getCapability(CapabilityEnergy.ENERGY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,14 +15,24 @@ public class DrillAugmentItem extends ActuallyItem {
|
|||
}
|
||||
|
||||
public enum AugmentType {
|
||||
SPEED_AUGMENT_I,
|
||||
SPEED_AUGMENT_II,
|
||||
SPEED_AUGMENT_III,
|
||||
SILK_TOUCH_AUGMENT,
|
||||
FORTUNE_AUGMENT_I,
|
||||
FORTUNE_AUGMENT_II,
|
||||
MINING_AUGMENT_I,
|
||||
MINING_AUGMENT_II,
|
||||
BLOCK_PLACING_AUGMENT
|
||||
SPEED_AUGMENT_I(50),
|
||||
SPEED_AUGMENT_II(75),
|
||||
SPEED_AUGMENT_III(175),
|
||||
SILK_TOUCH_AUGMENT(100),
|
||||
FORTUNE_AUGMENT_I(40),
|
||||
FORTUNE_AUGMENT_II(80),
|
||||
MINING_AUGMENT_I(10),
|
||||
MINING_AUGMENT_II(30),
|
||||
BLOCK_PLACING_AUGMENT(0);
|
||||
|
||||
int energyCost;
|
||||
|
||||
AugmentType(int energyCost) {
|
||||
this.energyCost = energyCost;
|
||||
}
|
||||
|
||||
public int getEnergyCost() {
|
||||
return energyCost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,52 @@
|
|||
package de.ellpeck.actuallyadditions.common.items.useables;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
import de.ellpeck.actuallyadditions.common.config.Config;
|
||||
import de.ellpeck.actuallyadditions.common.container.DrillContainer;
|
||||
import de.ellpeck.actuallyadditions.common.items.CrystalFluxItem;
|
||||
import de.ellpeck.actuallyadditions.common.items.misc.DrillAugmentItem;
|
||||
import de.ellpeck.actuallyadditions.common.utilities.Help;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.enchantment.Enchantments;
|
||||
import net.minecraft.entity.ai.attributes.Attribute;
|
||||
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.EquipmentSlotType;
|
||||
import net.minecraft.inventory.container.SimpleNamedContainerProvider;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.ToolType;
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
import net.minecraftforge.fml.network.NetworkHooks;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static de.ellpeck.actuallyadditions.common.items.misc.DrillAugmentItem.AugmentType;
|
||||
|
||||
public class DrillItem extends CrystalFluxItem {
|
||||
public static final String NBT_AUGMENT_TAG = "augments";
|
||||
|
||||
private static final int BASE_ENERGY_USE = 100;
|
||||
|
||||
public DrillItem() {
|
||||
super(
|
||||
baseProps()
|
||||
|
@ -27,6 +59,117 @@ public class DrillItem extends CrystalFluxItem {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType equipmentSlot, ItemStack stack) {
|
||||
Multimap<Attribute, AttributeModifier> map = HashMultimap.create();
|
||||
|
||||
if (equipmentSlot == EquipmentSlotType.MAINHAND) {
|
||||
map.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Drill Modifier", getCrystalFlux(stack).map(IEnergyStorage::getEnergyStored).orElse(0) >= BASE_ENERGY_USE ? 8.0F : 0.1F, AttributeModifier.Operation.ADDITION));
|
||||
map.put(Attributes.ATTACK_SPEED, new AttributeModifier(ATTACK_SPEED_MODIFIER, "Tool Modifier", -2.5F, AttributeModifier.Operation.ADDITION));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBlockStartBreak(ItemStack stack, BlockPos posIn, PlayerEntity player) {
|
||||
int crystalFlux = getCrystalFlux(stack).map(IEnergyStorage::getEnergyStored).orElse(0);
|
||||
int fluxPerBlock = this.getFluxPerBlock(stack);
|
||||
|
||||
if (crystalFlux < fluxPerBlock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImmutableSet<AugmentType> augments = getAugments(stack);
|
||||
ItemStack drill = stack.copy(); // copy to apply enchants
|
||||
|
||||
// Apply enchants
|
||||
if (hasAugment(augments, AugmentType.SILK_TOUCH_AUGMENT)) {
|
||||
drill.addEnchantment(Enchantments.SILK_TOUCH, 1);
|
||||
}
|
||||
|
||||
if (hasAugment(augments, AugmentType.FORTUNE_AUGMENT_I) || hasAugment(augments, AugmentType.FORTUNE_AUGMENT_II)) {
|
||||
drill.addEnchantment(Enchantments.FORTUNE, hasAugment(augments, AugmentType.FORTUNE_AUGMENT_I) ? 1 : 3);
|
||||
}
|
||||
|
||||
if ((hasAugment(augments, AugmentType.MINING_AUGMENT_I) || hasAugment(augments, AugmentType.MINING_AUGMENT_II))) {
|
||||
return this.breakBlocksWithAoe(player, player.world, stack, drill, fluxPerBlock, hasAugment(augments, AugmentType.MINING_AUGMENT_I) ? 1 : 2);
|
||||
} else {
|
||||
return this.destroyBlock(posIn, player, player.world, stack, drill, fluxPerBlock);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean breakBlocksWithAoe(PlayerEntity player, World world, ItemStack drill, ItemStack drillEnchanted, int fluxPerBlock, int radius) {
|
||||
double distance = Objects.requireNonNull(player.getAttribute(ForgeMod.REACH_DISTANCE.get())).getValue();
|
||||
RayTraceResult trace = player.pick(player.isCreative() ? distance : distance - 0.5D, 1F, false);
|
||||
if (trace.getType() != RayTraceResult.Type.BLOCK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockRayTraceResult pick = (BlockRayTraceResult) trace;
|
||||
|
||||
BlockPos pos = pick.getPos();
|
||||
Direction.Axis axis = pick.getFace().getAxis();
|
||||
|
||||
Set<BlockPos> posSet = new HashSet<>();
|
||||
|
||||
// Uses the facing axis to move around the X,Y,Z to allow for multiple faces in 2 for loops
|
||||
int a = axis != Direction.Axis.X ? pos.getX() : pos.getY(); // Z & Y plane both use X
|
||||
int b = axis != Direction.Axis.Z ? pos.getZ() : pos.getY(); // X & Y plane both use Z
|
||||
|
||||
for (int i = (a - radius); i < (a + radius) + 1; i++) {
|
||||
for (int j = (b - radius); j < (b + radius) + 1; j++) {
|
||||
// Assign [a] and [b] to X, Y, or Z depending on the axis
|
||||
posSet.add(new BlockPos(
|
||||
axis != Direction.Axis.X ? i : pos.getX(),
|
||||
axis == Direction.Axis.X ? i : (axis == Direction.Axis.Z ? j : pos.getY()),
|
||||
axis != Direction.Axis.Z ? j : pos.getZ()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Set<BlockPos> failed = new HashSet<>();
|
||||
posSet.forEach(e -> {
|
||||
if (!destroyBlock(e, player, world, drill, drillEnchanted, fluxPerBlock)) {
|
||||
failed.add(e);
|
||||
}
|
||||
});
|
||||
|
||||
return failed.contains(pick.getPos());
|
||||
}
|
||||
|
||||
private boolean destroyBlock(BlockPos pos, PlayerEntity player, World world, ItemStack drill, ItemStack drillEnchanted, int fluxPerBlock) {
|
||||
BlockState state = world.getBlockState(pos);
|
||||
int flux = this.getCrystalFlux(drill).map(IEnergyStorage::getEnergyStored).orElse(0);
|
||||
|
||||
if (!ForgeHooks.canHarvestBlock(state, player, world, pos) || flux < fluxPerBlock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!world.isRemote) {
|
||||
int event = ForgeHooks.onBlockBreakEvent(world, ((ServerPlayerEntity) player).interactionManager.getGameType(), (ServerPlayerEntity) player, pos);
|
||||
if (event == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TileEntity tileEntity = world.getTileEntity(pos);
|
||||
state.getBlock().onPlayerDestroy(world, pos, state);
|
||||
state.getBlock().harvestBlock(world, player, pos, state, tileEntity, drillEnchanted);
|
||||
state.getBlock().dropXpOnBlockBreak((ServerWorld) world, pos, event);
|
||||
}
|
||||
|
||||
// Old Ell Code :cry:, I mean, it's perfect!
|
||||
// Client code
|
||||
world.playEvent(2001, pos, Block.getStateId(state));
|
||||
if (state.getBlock().removedByPlayer(state, world, pos, player, true, world.getFluidState(pos))) {
|
||||
state.getBlock().onPlayerDestroy(world, pos, state);
|
||||
}
|
||||
|
||||
// callback to the tool
|
||||
drill.onBlockDestroyed(world, state, pos, player);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity player, Hand handIn) {
|
||||
ItemStack stack = player.getHeldItem(handIn);
|
||||
|
@ -43,4 +186,89 @@ public class DrillItem extends CrystalFluxItem {
|
|||
|
||||
return ActionResult.resultSuccess(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDestroySpeed(ItemStack stack, BlockState state) {
|
||||
int flux = getCrystalFlux(stack).map(IEnergyStorage::getEnergyStored).orElse(0);
|
||||
|
||||
if (flux == 0 || flux <= this.getFluxPerBlock(stack))
|
||||
return 0.1f;
|
||||
|
||||
return blockIsPartOfSpecialWhitelist(state) || state.getHarvestTool() == null || this.getToolTypes(stack).contains(state.getHarvestTool())
|
||||
? this.getDestroySpeedFromUpgrades(stack)
|
||||
: 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the speed the drill can mine based on it's augments and it's reducer augments
|
||||
*
|
||||
* @return speed that the drill can mine
|
||||
*/
|
||||
private float getDestroySpeedFromUpgrades(ItemStack stack) {
|
||||
float speed = 8.0f;
|
||||
|
||||
ImmutableSet<AugmentType> augments = getAugments(stack);
|
||||
if (augments.size() == 0) {
|
||||
return speed;
|
||||
}
|
||||
|
||||
float reduction = hasAugment(augments, AugmentType.MINING_AUGMENT_I) ? (hasAugment(augments, AugmentType.MINING_AUGMENT_II) ? 0.5f : 0.35f) : 1f;
|
||||
float modifier = hasAugment(augments, AugmentType.SPEED_AUGMENT_I)
|
||||
? 8.0f
|
||||
: (hasAugment(augments, AugmentType.SPEED_AUGMENT_II)
|
||||
? 25.0f
|
||||
: (hasAugment(augments, AugmentType.SPEED_AUGMENT_III) ? 37.0f : 0f));
|
||||
|
||||
return (speed + modifier) * reduction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the cost to mine a block based on the items augments
|
||||
*
|
||||
* @return the cost per operation
|
||||
*/
|
||||
private int getFluxPerBlock(ItemStack stack) {
|
||||
return BASE_ENERGY_USE + getAugments(stack).stream().mapToInt(AugmentType::getEnergyCost).sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not a state can be mined even if the other operators fail
|
||||
*/
|
||||
private boolean blockIsPartOfSpecialWhitelist(BlockState state) {
|
||||
ResourceLocation location = state.getBlock().getRegistryName();
|
||||
if (location == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Config.ITEM_CONFIG.drillSpecialBlockWhitelist.get().contains(location.toString());
|
||||
}
|
||||
|
||||
private boolean hasAugment(ItemStack stack, AugmentType type) {
|
||||
return getAugments(stack).contains(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this in preference for {@link #hasAugment(ItemStack, AugmentType)} when doing multiple comparisons
|
||||
*/
|
||||
private boolean hasAugment(ImmutableSet<AugmentType> augments, AugmentType type) {
|
||||
return augments.contains(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of AugmentTypes attached to the item stack.
|
||||
*/
|
||||
private ImmutableSet<AugmentType> getAugments(ItemStack stack) {
|
||||
ItemStackHandler handler = new ItemStackHandler();
|
||||
handler.deserializeNBT(stack.getOrCreateChildTag(NBT_AUGMENT_TAG));
|
||||
|
||||
ImmutableSet.Builder<AugmentType> augments = ImmutableSet.builder();
|
||||
for (int i = 0; i < handler.getSlots(); i ++) {
|
||||
ItemStack stackInSlot = handler.getStackInSlot(i);
|
||||
if (!stackInSlot.isEmpty() && stackInSlot.getItem() instanceof DrillAugmentItem) {
|
||||
augments.add(((DrillAugmentItem) stackInSlot.getItem()).getType());
|
||||
}
|
||||
}
|
||||
|
||||
return augments.build();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue