Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ dependencies {
compileOnly('com.github.GTNewHorizons:Angelica:1.0.0-beta68a:dev')
compileOnly("com.github.GTNewHorizons:FindIt:1.4.0:dev")
compileOnly('com.github.GTNewHorizons:TinkersConstruct:1.14.14-GTNH:dev')
compileOnly("com.github.GTNewHorizons:Backhand:1.8.2:dev")
compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.296:dev')


devOnlyNonPublishable("com.github.GTNewHorizons:Baubles-Expanded:2.2.4-GTNH:dev")
Expand All @@ -57,4 +59,8 @@ dependencies {
// For testing glove
// runtimeOnlyNonPublishable("com.github.GTNewHorizons:Translocators:1.4.0:dev")
// runtimeOnlyNonPublishable("com.github.GTNewHorizons:Backhand:1.8.2:dev")

// For testing trowel + wand
// runtimeOnlyNonPublishable("com.github.GTNewHorizons:Backhand:1.8.2:dev")
// runtimeOnlyNonPublishable('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.296:dev')
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.fouristhenumber.utilitiesinexcess.common.items;

import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils.getItemStackToPlace;

import java.util.List;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MovingObjectPosition;
Expand All @@ -19,8 +17,11 @@
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;

import org.jetbrains.annotations.NotNull;

import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess;
import com.fouristhenumber.utilitiesinexcess.common.renderers.WireframeRenderer;
import com.fouristhenumber.utilitiesinexcess.utils.ArchitectsSelection;
import com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils;
import com.gtnewhorizon.gtnhlib.api.ITranslucentItem;
import com.gtnewhorizon.gtnhlib.blockpos.BlockPos;
Expand Down Expand Up @@ -85,24 +86,51 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool
}

// 4. Target block to place
ItemStack itemStackToPlace = getItemStackToPlace(world, target, movingObjectPosition, player);
if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) {
WireframeRenderer.clearCandidatePositions();
return;
}
ArchitectsSelection selection = new ArchitectsSelection(player, world, movingObjectPosition);
List<ItemStack> itemStackToPlace = selection.blockToPlace(player);

// 3. Total amount to place
int placeCount = player.capabilities.isCreativeMode ? this.buildLimit
: Math.min(ArchitectsWandUtils.countItemInInventory(player, itemStackToPlace), this.buildLimit);

Set<BlockPos> blocksToPlace = ArchitectsWandUtils
.findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, movingObjectPosition, player);
int placeCount = selection.maxPlaceCount(player, buildLimit);

Set<BlockPos> blocksToPlace = ArchitectsWandUtils.findAdjacentBlocks(
world,
itemStackToPlace,
placeCount,
forgeSide,
target,
movingObjectPosition,
player,
selection);
WireframeRenderer.clearCandidatePositions();
for (BlockPos pos : blocksToPlace) {
WireframeRenderer.addCandidatePosition(pos.offset(forgeSide.offsetX, forgeSide.offsetY, forgeSide.offsetZ));
}
}

private void placeBlock(World world, EntityPlayer player, @NotNull ItemStack itemStack, BlockPos pos, int side,
float hitX, float hitY, float hitZ, ForgeDirection forgeSide) {
// This block is here because some mods want to use TEs to
ItemStack itemCopy = itemStack.copy();
itemCopy.stackSize = 1;
Block comparisonBlock = world.getBlock(pos.x, pos.y, pos.z);
int comparisonMeta = world.getBlockMetadata(pos.x, pos.y, pos.z);
ItemStack comparisonItemStack = new ItemStack(comparisonBlock, 1, comparisonMeta);

boolean useCompatPlacement = !ItemStack.areItemStacksEqual(itemCopy, comparisonItemStack);
if (useCompatPlacement) {
itemStack.getItem()
.onItemUse(itemCopy, player, world, pos.x, pos.y, pos.z, side, hitX, hitY, hitZ);
} else {
world.setBlock(
pos.x + forgeSide.offsetX,
pos.y + forgeSide.offsetY,
pos.z + forgeSide.offsetZ,
Block.getBlockFromItem(itemCopy.getItem()),
comparisonMeta,
3);
}
}

@Override
public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side,
float hitX, float hitY, float hitZ) {
Expand All @@ -116,42 +144,28 @@ public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world,

BlockPos target = new BlockPos(x, y, z);
MovingObjectPosition mop = new MovingObjectPosition(x, y, z, side, Vec3.createVectorHelper(hitX, hitY, hitZ));
ItemStack itemStackToPlace = getItemStackToPlace(world, target, mop, player);
if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) return false;
ArchitectsSelection selection = new ArchitectsSelection(player, world, mop);

// This block is here because some mods want to use TEs to
Block comparisonBlock = world.getBlock(x, y, z);
int comparisonMeta = world.getBlockMetadata(x, y, z);
ItemStack comparisonItemStack = new ItemStack(comparisonBlock, 1, comparisonMeta);

boolean useCompatPlacement = !ItemStack.areItemStacksEqual(itemStackToPlace, comparisonItemStack);
List<ItemStack> itemStackToPlace = selection.blockToPlace(player);

int inventoryBlockCount = ArchitectsWandUtils.countItemInInventory(player, itemStackToPlace);
if (!player.capabilities.isCreativeMode && inventoryBlockCount == 0) return false;
int placeCount = player.capabilities.isCreativeMode ? this.buildLimit
: Math.min(inventoryBlockCount, this.buildLimit);
int placeCount = selection.maxPlaceCount(player, buildLimit);

Set<BlockPos> blocksToPlace = ArchitectsWandUtils
.findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player);
itemStackToPlace.stackSize = blocksToPlace.size(); // Since now, we actually create a stack we have to set the
// size. Strange kinda...
.findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player, selection);

ItemStack nowPlacing;

for (BlockPos pos : blocksToPlace) {
// TODO: Group these by a bigger number instead of decreasing by 1 every time.
if (player.capabilities.isCreativeMode
|| ArchitectsWandUtils.decreaseFromInventory(player, itemStackToPlace)) {
if (useCompatPlacement) {
itemStackToPlace.getItem()
.onItemUse(itemStackToPlace, player, world, pos.x, pos.y, pos.z, side, hitX, hitY, hitZ);
} else {
world.setBlock(
pos.x + forgeSide.offsetX,
pos.y + forgeSide.offsetY,
pos.z + forgeSide.offsetZ,
comparisonBlock,
comparisonMeta,
3);
}
List<ItemStack> candidates = selection.blockToPlace(player);
if (candidates.size() == 1) {
nowPlacing = candidates.get(0);
} else {
nowPlacing = candidates.get(
ThreadLocalRandom.current()
.nextInt(candidates.size()));
}
if (player.capabilities.isCreativeMode || ArchitectsWandUtils.decreaseFromInventory(player, nowPlacing)) {
placeBlock(world, player, nowPlacing, pos, side, hitX, hitY, hitZ, forgeSide);
}
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ public enum Mods {
NEI("NotEnoughItems"),
CraftTweaker("MineTweaker3"),
FindIt("findit"),
Tinkers("TConstruct")
Tinkers("TConstruct"),
Backhand("backhand"),
GT("gregtech")
;
// spotless:on

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package com.fouristhenumber.utilitiesinexcess.utils;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;

import org.jetbrains.annotations.Nullable;

import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess;
import com.fouristhenumber.utilitiesinexcess.compat.Mods;
import com.gtnewhorizon.gtnhlib.blockpos.BlockPos;

import gregtech.api.items.MetaGeneratedTool;
import gregtech.common.tools.ToolTrowel;
import xonin.backhand.api.core.BackhandUtils;

public class ArchitectsSelection {

private final Set<ItemStack> validBlocks;
private final ItemStack backhand;
private final ItemStack lookAtBlock;

public ArchitectsSelection(EntityPlayer player, World world, MovingObjectPosition movingObjectPosition) {
this.validBlocks = new HashSet<>();
backhand = Mods.Backhand.isLoaded() ? BackhandUtils.getOffhandItem(player) : null;
lookAtBlock = getBlockByLocation(world, movingObjectPosition, player);

// No logic is executed if we don't look at any block, no need to bother checking other cases
if (lookAtBlock == null) {
return;
}

this.validBlocks.add(lookAtBlock); // Clicked block is always valid

if (backhand == null) {
return;
}
if (isValidBlock(backhand)) {
this.validBlocks.add(backhand.copy());
return;
}
if (isTrowel(backhand)) {
this.validBlocks.addAll(hotbarBlocks(player));
}
}

/**
*
* @param player
* @return Always a valid block list or null
*/
public List<ItemStack> blockToPlace(EntityPlayer player) {
boolean isCreative = player.capabilities.isCreativeMode;

if (backhand == null) {
return Collections.singletonList((lookAtBlock));
}
if (isValidBlock(backhand)) {
return Collections.singletonList(backhand);
}
if (isTrowel(backhand)) {
return hotbarBlocks(player);
}
UtilitiesInExcess.LOG.warn("Could not determent a block to place.");
return null;
}

public int maxPlaceCount(EntityPlayer player, int wandLimit) {
if (player.capabilities.isCreativeMode) return wandLimit;
int count = 0;
for (ItemStack block : blockToPlace(player)) {
count += ArchitectsWandUtils.countItemInInventory(player, block);
}
return Math.min(count, wandLimit);
}

public boolean matches(ItemStack other) {
if (other == null) return false;
return this.validBlocks.stream()
.anyMatch(
validBlock -> validBlock.getItem() == other.getItem()
&& ItemStack.areItemStackTagsEqual(validBlock, other));
}

private static boolean isTrowel(@Nullable ItemStack stack) {
if (stack == null) {
return false;
}
if (stack.getItem() instanceof MetaGeneratedTool metaGeneratedTool) {
return metaGeneratedTool.getToolStats(stack) instanceof ToolTrowel;
}
return false;
}

private static boolean isValidBlock(@Nullable ItemStack stack) {
return (stack != null && stack.getItem() instanceof ItemBlock);
}

private static List<ItemStack> hotbarBlocks(EntityPlayer player) {
List<ItemStack> candidates = new ArrayList<>();

for (int i = 0; i < 9; i++) {
if (i == player.inventory.currentItem) {
continue;
}
ItemStack item = player.inventory.mainInventory[i];
if (!isValidBlock(item)) {
continue;
}
candidates.add(item);
}
return candidates;
}

private static ItemStack randomHotbarBlock(EntityPlayer player) {
List<ItemStack> candidates = hotbarBlocks(player);
if (candidates.isEmpty()) {
return null;
}
return candidates.get(
ThreadLocalRandom.current()
.nextInt(candidates.size()));
}

public static ItemStack getBlockByLocation(World world, MovingObjectPosition movingObjectPosition,
EntityPlayer player) {

BlockPos blockPos = new BlockPos(
movingObjectPosition.blockX,
movingObjectPosition.blockY,
movingObjectPosition.blockZ);

Block block = world.getBlock(blockPos.x, blockPos.y, blockPos.z);
if (block == null) {
return null;
}
return block.getPickBlock(movingObjectPosition, world, blockPos.x, blockPos.y, blockPos.z, player);
}
}
Loading
Loading