Skip to content
Open
1 change: 1 addition & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies {
compileOnly("com.github.GTNewHorizons:TinkersConstruct:1.14.93-GTNH:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:ForgeMultipart:1.7.10:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:Backhand:1.8.11:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:ArchitectureCraft:1.11.6:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:waila:1.19.30:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:Postea:1.2.5:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:SimpleSkinBackport:1.0.2-GTNH:dev") {transitive = false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import com.fouristhenumber.utilitiesinexcess.common.worldgen.WorldGenEnderLotus;
import com.fouristhenumber.utilitiesinexcess.compat.ForgeMultipart.FMPCompat;
import com.fouristhenumber.utilitiesinexcess.compat.ForgeMultipart.FMPItems;
import com.fouristhenumber.utilitiesinexcess.compat.ForgeMultipart.MultipartBWCellHandler;
import com.fouristhenumber.utilitiesinexcess.compat.ForgeMultipart.multipart.Content;
import com.fouristhenumber.utilitiesinexcess.compat.Mods;
import com.fouristhenumber.utilitiesinexcess.compat.architecturecraft.ArchitectureCraftBWCellHandler;
import com.fouristhenumber.utilitiesinexcess.compat.crafttweaker.EnderLocusCraftTweakerSupport;
import com.fouristhenumber.utilitiesinexcess.compat.exu.ExuWorldConversionWarning;
import com.fouristhenumber.utilitiesinexcess.compat.exu.PosteaTransforms;
Expand All @@ -31,6 +33,7 @@
import com.fouristhenumber.utilitiesinexcess.utils.PinkFuelHelper;
import com.fouristhenumber.utilitiesinexcess.utils.SoundVolumeChecks;
import com.fouristhenumber.utilitiesinexcess.utils.TEChunkLoadingCallback;
import com.fouristhenumber.utilitiesinexcess.utils.bw.BWCellHandlers;
import com.gtnewhorizon.gtnhlib.api.gui.WorldConversionWarningManager;
import com.gtnewhorizon.gtnhlib.blockstate.registry.BlockPropertyRegistry;
import com.gtnewhorizon.gtnhlib.datastructs.space.ArrayProximityCheck4D;
Expand Down Expand Up @@ -99,6 +102,11 @@ public void preInit(FMLPreInitializationEvent event) {
FMPItems.init();
new Content().init();
FMPCompat.init();
BWCellHandlers.register(new MultipartBWCellHandler());
}

if (Mods.ArchitectureCraft.isLoaded()) {
BWCellHandlers.register(new ArchitectureCraftBWCellHandler());
}

if (ColoredBlocksConfig.INSTANCE.enableColoredBlocks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.fouristhenumber.utilitiesinexcess.common.items.ItemMobJar;
import com.fouristhenumber.utilitiesinexcess.common.items.ItemPaintRoller;
import com.fouristhenumber.utilitiesinexcess.common.items.ItemPseudoReversionSigil;
import com.fouristhenumber.utilitiesinexcess.common.items.ItemScribe;
import com.fouristhenumber.utilitiesinexcess.common.items.ItemWateringCan;
import com.fouristhenumber.utilitiesinexcess.common.items.ItemXRayGlasses;
import com.fouristhenumber.utilitiesinexcess.common.items.tools.ItemAntiGravityShovel;
Expand Down Expand Up @@ -83,6 +84,7 @@ public enum ModItems {
CHUNCHUNMARU(ChunchunmaruConfig.INSTANCE.enable, new ItemChunchunmaru(), "chunchunmaru"),
CAPACITY_UPGRADE(BlockConfig.filingCabinets.enableFilingCabinets, new ItemCapacityUpgrade(), "capacity_upgrade"),
PAINT_ROLLER(ColoredBlocksConfig.INSTANCE.enablePaintRoller, new ItemPaintRoller(), "paint_roller"),
SCRIBE(BuildersWandsConfig.INSTANCE.enableScribe, new ItemScribe(), "scribe"),
; // leave trailing semicolon
// spotless:on

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.fouristhenumber.utilitiesinexcess.common.blocks.BlockColored;
import com.fouristhenumber.utilitiesinexcess.compat.Mods;
import com.fouristhenumber.utilitiesinexcess.config.blocks.ColoredBlocksConfig;
import com.fouristhenumber.utilitiesinexcess.config.items.BuildersWandsConfig;
import com.fouristhenumber.utilitiesinexcess.config.items.InversionConfig;
import com.fouristhenumber.utilitiesinexcess.mixins.early.minecraft.accessors.AccessorBlock;

Expand Down Expand Up @@ -77,6 +78,9 @@ public static void IMCSender() {
if (Mods.GregTech.isLoaded()) sendInfoPage(
"<utilitiesinexcess:builders_wand>,<utilitiesinexcess:super_builders_wand>",
"uie.nei.infopage.builders_wand.3");
if (BuildersWandsConfig.INSTANCE.enableScribe) sendInfoPage(
"<utilitiesinexcess:builders_wand>,<utilitiesinexcess:super_builders_wand>",
"uie.nei.infopage.builders_wand.4");
}
sendInfoPage("<utilitiesinexcess:mob_jar>", "uie.nei.infopage.mob_jar.1");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package com.fouristhenumber.utilitiesinexcess.common.items;

import static com.fouristhenumber.utilitiesinexcess.utils.BuildersWandUtils.damageBackhand;

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;
Expand All @@ -19,14 +15,16 @@
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.config.items.BuildersWandsConfig;
import com.fouristhenumber.utilitiesinexcess.utils.BuildersSelection;
import com.fouristhenumber.utilitiesinexcess.utils.BuildersWandUtils;
import com.fouristhenumber.utilitiesinexcess.utils.BuildersWandUtils.WandAxisMode;
import com.fouristhenumber.utilitiesinexcess.utils.ChickenLibRayTracer;
import com.fouristhenumber.utilitiesinexcess.utils.InventoryBudget;
import com.fouristhenumber.utilitiesinexcess.utils.MovingObjectPositionUtil;
import com.fouristhenumber.utilitiesinexcess.utils.bw.BWCellHandlers;
import com.fouristhenumber.utilitiesinexcess.utils.bw.BWContext;
import com.fouristhenumber.utilitiesinexcess.utils.bw.BWMode;
import com.fouristhenumber.utilitiesinexcess.utils.bw.BWRegion;
import com.fouristhenumber.utilitiesinexcess.utils.bw.BWRegion.WandAxisLock;
import com.gtnewhorizon.gtnhlib.api.ITranslucentItem;
import com.gtnewhorizon.gtnhlib.blockpos.BlockPos;

Expand All @@ -35,7 +33,7 @@

public class ItemBuildersWand extends Item implements ITranslucentItem {

public int buildLimit;
private final int buildLimit;

public ItemBuildersWand(int buildLimit) {
super();
Expand All @@ -56,15 +54,16 @@ public void addInformation(ItemStack stack, EntityPlayer player, List<String> to
@SideOnly(Side.CLIENT)
@Override
public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean isSelected) {
if (!world.isRemote || !(entity instanceof EntityPlayer player)) {
return;
}
if (!world.isRemote || !(entity instanceof EntityPlayer player)) return;

if (!isSelected) return;

if (!isSelected) {
// adventure mode
if (!player.capabilities.allowEdit) {
WireframeRenderer.clearCandidatePositions();
return;
}

// I'm pretty sure this will never determine whether we render or not but I'm not certain
MovingObjectPosition movingObjectPosition = Minecraft.getMinecraft().objectMouseOver;

// Check if player is looking at a block.
Expand All @@ -74,146 +73,82 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool
return;
}

// 1. Target block location
BlockPos target = new BlockPos(
movingObjectPosition.blockX,
movingObjectPosition.blockY,
movingObjectPosition.blockZ);
ForgeDirection forgeSide = ForgeDirection.getOrientation(movingObjectPosition.sideHit);

// 2. Side
int side = movingObjectPosition.sideHit;
ForgeDirection forgeSide = ForgeDirection.getOrientation(side);
if (forgeSide == ForgeDirection.UNKNOWN) {
UtilitiesInExcess.LOG
.warn("Builder's wand onUpdate was called with invalid facing direction: {}", forgeSide);
return;
}

WandAxisMode axisMode;
if (UtilitiesInExcess.proxy.BUILDERS_KEYBIND_H.isKeyDown(player)) {
axisMode = WandAxisMode.HORIZONTAL;
} else if (UtilitiesInExcess.proxy.BUILDERS_KEYBIND_V.isKeyDown(player)) {
axisMode = WandAxisMode.VERTICAL;
} else {
axisMode = WandAxisMode.FREE;
}

// 4. Target block to place
BuildersSelection selection = new BuildersSelection(player, world, movingObjectPosition);
List<ItemStack> itemStackToPlace = selection.blockToPlace(player);

// 3. Total amount to place
int placeCount = selection.maxPlaceCount(player, buildLimit);

Set<BlockPos> blocksToPlace = BuildersWandUtils.findAdjacentBlocks(
world,
itemStackToPlace,
placeCount,
forgeSide,
target,
WandAxisLock axisLock = axisLock(player);
Set<BlockPos> blocksToPlace = BWRegion.findAdjacentBlocksToBuildOn(
newContext(world, player, movingObjectPosition),
buildLimit,
movingObjectPosition,
player,
selection,
axisMode);
axisLock);

WireframeRenderer.clearCandidatePositions();
for (BlockPos pos : blocksToPlace) {
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 {
Block block = Block.getBlockFromItem(itemCopy.getItem());
world.setBlock(
pos.x + forgeSide.offsetX,
pos.y + forgeSide.offsetY,
pos.z + forgeSide.offsetZ,
block,
comparisonMeta,
3);

world.playSoundEffect(
pos.x + forgeSide.offsetX,
pos.y + forgeSide.offsetY,
pos.z + forgeSide.offsetZ,
block.stepSound.func_150496_b(),
(block.stepSound.getVolume() + 1.0F) / 2.0F,
block.stepSound.getPitch() * 0.8F);
}
}

@Override
public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side,
float hitX, float hitY, float hitZ) {
if (world.isRemote) return true;
if (!player.capabilities.allowEdit) return false;

// TODO: Prevent player from placing blocks into themself / other entities?
MovingObjectPosition mop = new MovingObjectPosition(
x,
y,
z,
side,
Vec3.createVectorHelper((double) x + hitX, (double) y + hitY, (double) z + hitZ));

// Sanity check
ForgeDirection forgeSide = ForgeDirection.getOrientation(side);
if (forgeSide == ForgeDirection.UNKNOWN) {
UtilitiesInExcess.LOG
.warn("Builder's wand onItemUse was called with invalid facing direction: {}", forgeSide);
return false;
UtilitiesInExcess.LOG.warn("Builder's wand onItemUse was called with invalid facing direction: {}", side);
return true;
}

BlockPos target = new BlockPos(x, y, z);
MovingObjectPosition mop = new MovingObjectPosition(x, y, z, side, Vec3.createVectorHelper(hitX, hitY, hitZ));
BuildersSelection selection = new BuildersSelection(player, world, mop);
WandAxisLock axisLock = axisLock(player);

List<ItemStack> itemStackToPlace = selection.blockToPlace(player);
// the scan pass spends the budget working out what fits, so placement starts from a fresh one
BWContext scanCtx = newContext(world, player, mop);
Set<BlockPos> blocksToPlace = BWRegion.findAdjacentBlocksToBuildOn(scanCtx, buildLimit, mop, axisLock);

WandAxisMode axisMode;
if (UtilitiesInExcess.proxy.BUILDERS_KEYBIND_H.isKeyDown(player)) {
axisMode = WandAxisMode.HORIZONTAL;
} else if (UtilitiesInExcess.proxy.BUILDERS_KEYBIND_V.isKeyDown(player)) {
axisMode = WandAxisMode.VERTICAL;
} else {
axisMode = WandAxisMode.FREE;
// every cell is protection-checked on its own, Forge recording the whole use at once would muddle that
boolean capturing = world.captureBlockSnapshots;
world.captureBlockSnapshots = false;
try {
BWContext buildCtx = newContext(world, player, mop);
for (BlockPos srcPos : blocksToPlace) {
MovingObjectPositionUtil.TranslateMovingObjectPositionToLocation(mop, srcPos);
BWCellHandlers.build(buildCtx, mop, true);
}
} finally {
world.captureBlockSnapshots = capturing;
}
player.inventoryContainer.detectAndSendChanges();
return true;
}

int placeCount = selection.maxPlaceCount(player, buildLimit);
/** Mode, budget and picker for one pass over the fill, seeded from the clicked cell. */
private static BWContext newContext(World world, EntityPlayer player, MovingObjectPosition mop) {
var budget = new InventoryBudget(player.inventory, player.capabilities.isCreativeMode);

Set<BlockPos> blocksToPlace = BuildersWandUtils.findAdjacentBlocks(
// null when the ray misses the clicked block, then handlers just get the plain position
MovingObjectPosition tracedMop = ChickenLibRayTracer
.retraceBlock(world, player, mop.blockX, mop.blockY, mop.blockZ);
return new BWContext(
world,
itemStackToPlace,
placeCount,
forgeSide,
target,
mop,
tracedMop != null ? tracedMop : MovingObjectPositionUtil.copy(mop),
player,
selection,
axisMode);

ItemStack nowPlacing;
for (BlockPos pos : blocksToPlace) {
List<ItemStack> candidates = selection.blockToPlace(player);
if (candidates.size() == 1) {
nowPlacing = candidates.get(0);
} else {
nowPlacing = candidates.get(
ThreadLocalRandom.current()
.nextInt(candidates.size()));
}
BWMode.of(player),
budget);
}

if (player.capabilities.isCreativeMode || (BuildersWandUtils.decreaseFromInventory(player, nowPlacing)
&& damageBackhand(BuildersWandsConfig.INSTANCE.damageTrowelWithBuildersWand, player))) {
placeBlock(world, player, nowPlacing, pos, side, hitX, hitY, hitZ, forgeSide);
}
}
player.inventoryContainer.detectAndSendChanges();
return true;
private static WandAxisLock axisLock(EntityPlayer player) {
if (UtilitiesInExcess.proxy.BUILDERS_KEYBIND_H.isKeyDown(player)) return WandAxisLock.HORIZONTAL;
if (UtilitiesInExcess.proxy.BUILDERS_KEYBIND_V.isKeyDown(player)) return WandAxisLock.VERTICAL;

return WandAxisLock.FREE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.fouristhenumber.utilitiesinexcess.common.items;

import java.util.List;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;

public class ItemScribe extends Item {

public ItemScribe() {
setMaxStackSize(1);
setMaxDamage(0);
setUnlocalizedName("scribe");
setTextureName("utilitiesinexcess:scribe");
}

@Override
public void addInformation(ItemStack stack, EntityPlayer player, List<String> tooltip, boolean advanced) {
tooltip.add(EnumChatFormatting.AQUA + StatCollector.translateToLocal("uie.desc.item.scribe.1"));
super.addInformation(stack, player, tooltip, advanced);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,10 @@ private static void loadInversionRecipes() {
's',
ModItems.BUILDERS_WAND);

// Scribe
if (RecipeConfig.enableScribeRecipe)
addShapedRecipe(ModItems.SCRIBE, "np", "np", "np", 'n', Items.gold_nugget, 'p', Items.paper);

// Inverted Ingot -> Block
if (RecipeConfig.enableInvertedBlockRecipe) addShapedRecipe(
ModBlocks.INVERTED_BLOCK,
Expand Down
Loading