Skip to content
Closed
Show file tree
Hide file tree
Changes from 10 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: 3 additions & 3 deletions src/main/java/gregtech/common/items/MetaItem1.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
import gregtech.common.creativetab.GTCreativeTabs;
import gregtech.common.entities.GTBoatEntity.GTBoatType;
import gregtech.common.items.behaviors.ClipboardBehavior;
import gregtech.common.items.behaviors.ColorSprayBehaviour;
import gregtech.common.items.behaviors.ColorSprayBehavior;
import gregtech.common.items.behaviors.DataItemBehavior;
import gregtech.common.items.behaviors.DoorBehavior;
import gregtech.common.items.behaviors.DynamiteBehaviour;
Expand Down Expand Up @@ -180,13 +180,13 @@ public void registerSubItems() {

// out of registry order so it can reference the Empty Spray Can
SPRAY_SOLVENT = addItem(60, "spray.solvent").setMaxStackSize(1)
.addComponents(new ColorSprayBehaviour(SPRAY_EMPTY.getStackForm(), 1024, -1))
.addComponents(new ColorSprayBehavior(SPRAY_EMPTY.getStackForm(), 1024, -1))
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);

for (int i = 0; i < EnumDyeColor.values().length; i++) {
SPRAY_CAN_DYES[i] = addItem(62 + i, "spray.can.dyes." + EnumDyeColor.values()[i].getName())
.setMaxStackSize(1)
.addComponents(new ColorSprayBehaviour(SPRAY_EMPTY.getStackForm(), 512, i))
.addComponents(new ColorSprayBehavior(SPRAY_EMPTY.getStackForm(), 512, i))
.setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package gregtech.common.items.behaviors;

import gregtech.api.cover.CoverRayTracer;
import gregtech.api.items.metaitem.stats.IItemDurabilityManager;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.interfaces.IGregTechTileEntity;
import gregtech.api.pipenet.tile.IPipeTile;
import gregtech.api.util.GradientUtil;
import gregtech.api.util.Mods;
import gregtech.common.pipelike.PipeCollectorWalker;
import gregtech.core.sound.GTSoundEvents;

import net.minecraft.block.Block;
Expand All @@ -22,23 +24,26 @@
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;

import appeng.api.util.AEColor;
import appeng.tile.networking.TileCableBus;
import codechicken.lib.raytracer.RayTracer;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;

import java.awt.*;
import java.util.List;

public class ColorSprayBehaviour extends AbstractUsableBehaviour implements IItemDurabilityManager {
public class ColorSprayBehavior extends AbstractUsableBehaviour implements IItemDurabilityManager {

private final ItemStack empty;
private final EnumDyeColor color;
private final Pair<Color, Color> durabilityBarColors;
private static final int MAX_PIPE_TRAVERSAL_LENGTH = 256;

public ColorSprayBehaviour(ItemStack empty, int totalUses, int color) {
public ColorSprayBehavior(ItemStack empty, int totalUses, int color) {
super(totalUses);
this.empty = empty;
EnumDyeColor[] colors = EnumDyeColor.values();
Expand All @@ -55,7 +60,7 @@ public ActionResult<ItemStack> onItemUse(EntityPlayer player, World world, Block
if (!player.canPlayerEdit(pos, facing, stack)) {
return ActionResult.newResult(EnumActionResult.FAIL, player.getHeldItem(hand));
}
if (!tryPaintBlock(player, world, pos, facing)) {
if (!tryPaintBlock(player, world, pos, facing, hand)) {
return ActionResult.newResult(EnumActionResult.PASS, player.getHeldItem(hand));
}
useItemDurability(player, hand, stack, empty.copy());
Expand All @@ -64,16 +69,17 @@ public ActionResult<ItemStack> onItemUse(EntityPlayer player, World world, Block
return ActionResult.newResult(EnumActionResult.SUCCESS, player.getHeldItem(hand));
}

private boolean tryPaintBlock(EntityPlayer player, World world, BlockPos pos, EnumFacing side) {
private boolean tryPaintBlock(EntityPlayer player, World world, BlockPos pos, EnumFacing side, EnumHand hand) {
IBlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
if (color == null) {
return tryStripBlockColor(player, world, pos, block, side);
return tryStripBlockColor(player, world, pos, block, side, hand);
}
return block.recolorBlock(world, pos, side, this.color) || tryPaintSpecialBlock(player, world, pos, block);
return tryPaintSpecialBlock(player, world, pos, block, hand) ||
block.recolorBlock(world, pos, side, this.color);
}

private boolean tryPaintSpecialBlock(EntityPlayer player, World world, BlockPos pos, Block block) {
private boolean tryPaintSpecialBlock(EntityPlayer player, World world, BlockPos pos, Block block, EnumHand hand) {
if (block == Blocks.GLASS) {
IBlockState newBlockState = Blocks.STAINED_GLASS.getDefaultState()
.withProperty(BlockStainedGlass.COLOR, this.color);
Expand All @@ -92,10 +98,27 @@ private boolean tryPaintSpecialBlock(EntityPlayer player, World world, BlockPos
world.setBlockState(pos, newBlockState);
return true;
}
TileEntity te = world.getTileEntity(pos);
if (player.isSneaking() && te instanceof IPipeTile<?, ?>mainPipe) {
RayTraceResult hitResult = RayTracer.retraceBlock(world, player, pos);
if (hitResult != null) {
EnumFacing facing = CoverRayTracer.determineGridSideHit(hitResult);
if (facing != null && mainPipe.isConnected(facing)) {
boolean paintedOthers = traversePipes(player, world, hand, pos, facing);
if (mainPipe.getPaintingColor() != this.color.colorValue) {
mainPipe.setPaintingColor(this.color.colorValue);
// Account for traversePipes having the durability used off by one
if (paintedOthers) {
ItemStack heldItem = player.getHeldItem(hand);
useItemDurability(player, hand, heldItem, empty.copy());
}
return true;
} else return paintedOthers;
}
}
}
if (Mods.AppliedEnergistics2.isModLoaded()) {
TileEntity te = world.getTileEntity(pos);
if (te instanceof TileCableBus) {
TileCableBus cable = (TileCableBus) te;
if (te instanceof TileCableBus cable) {
// do not try to recolor if it already is this color
if (cable.getColor().ordinal() != color.ordinal()) {
cable.recolourBlock(null, AEColor.values()[color.ordinal()], player);
Expand All @@ -106,9 +129,41 @@ private boolean tryPaintSpecialBlock(EntityPlayer player, World world, BlockPos
return false;
}

// note: automatically uses durability from recolouring pipes, apart from the last use, as this allows for proper
// animation of the item's use
private boolean traversePipes(EntityPlayer player, World world, EnumHand hand, BlockPos startPos,
EnumFacing facing) {
startPos = startPos.offset(facing);
TileEntity connectedTe = world.getTileEntity(startPos);
boolean painted = false;
ItemStack heldItem = player.getHeldItem(hand);
if (connectedTe instanceof IPipeTile<?, ?>startPipe) {
List<IPipeTile<?, ?>> pipes = PipeCollectorWalker.collectPipeNet(world, startPos, startPipe,
Math.min(MAX_PIPE_TRAVERSAL_LENGTH, getUsesLeft(heldItem)));
int colour = this.color == null ? -1 : this.color.colorValue;
for (IPipeTile<?, ?> pipe : pipes) {
if (pipe.getPaintingColor() != colour) {
pipe.setPaintingColor(colour);
pipe.scheduleRenderUpdate();
if (getUsesLeft(heldItem) == 1) {
useItemDurability(player, hand, heldItem, empty.copy());
return true;
}
// Off by one durability as the final use is handled by onItemUse, along with the use animation
if (painted) {
useItemDurability(player, hand, heldItem, empty.copy());
}
painted = true;
}
}

}
return painted;
}

@SuppressWarnings("unchecked, rawtypes")
private static boolean tryStripBlockColor(EntityPlayer player, World world, BlockPos pos, Block block,
EnumFacing side) {
private boolean tryStripBlockColor(EntityPlayer player, World world, BlockPos pos, Block block,
EnumFacing side, EnumHand hand) {
// MC special cases
if (block == Blocks.STAINED_GLASS) {
world.setBlockState(pos, Blocks.GLASS.getDefaultState());
Expand Down Expand Up @@ -136,18 +191,32 @@ private static boolean tryStripBlockColor(EntityPlayer player, World world, Bloc
}

// TileEntityPipeBase special case
if (te instanceof IPipeTile) {
IPipeTile<?, ?> pipe = (IPipeTile<?, ?>) te;
if (pipe.isPainted()) {
if (te instanceof IPipeTile<?, ?>pipe) {
if (player.isSneaking()) {
RayTraceResult hitResult = RayTracer.retraceBlock(world, player, pos);
if (hitResult != null) {
EnumFacing facing = CoverRayTracer.determineGridSideHit(hitResult);
if (facing != null && pipe.isConnected(facing)) {
boolean paintedOthers = traversePipes(player, world, hand, pos, facing);
if (pipe.isPainted()) {
pipe.setPaintingColor(-1);
if (paintedOthers) {
ItemStack heldItem = player.getHeldItem(hand);
useItemDurability(player, hand, heldItem, empty.copy());
}
return true;
} else return paintedOthers;
}
}
} else if (pipe.isPainted()) {
pipe.setPaintingColor(-1);
return true;
} else return false;
}

// AE2 cable special case
if (Mods.AppliedEnergistics2.isModLoaded()) {
if (te instanceof TileCableBus) {
TileCableBus cable = (TileCableBus) te;
if (te instanceof TileCableBus cable) {
// do not try to strip color if it is already colorless
if (cable.getColor() != AEColor.TRANSPARENT) {
cable.recolourBlock(null, AEColor.TRANSPARENT, player);
Expand Down Expand Up @@ -189,6 +258,7 @@ public void addInformation(ItemStack itemStack, List<String> lines) {
}
lines.add(I18n.format("behaviour.paintspray.uses", remainingUses));
lines.add(I18n.format("behaviour.paintspray.offhand"));
lines.add(I18n.format("behaviour.paintspray.crouch"));
}

@Override
Expand Down
67 changes: 67 additions & 0 deletions src/main/java/gregtech/common/pipelike/PipeCollectorWalker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package gregtech.common.pipelike;

import gregtech.api.pipenet.PipeNetWalker;
import gregtech.api.pipenet.tile.IPipeTile;

import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class PipeCollectorWalker<T extends IPipeTile<?, ?>> extends PipeNetWalker<T> {

@NotNull
public static List<IPipeTile<?, ?>> collectPipeNet(World world, BlockPos sourcePipe, IPipeTile<?, ?> pipe,
int limit) {
PipeCollectorWalker<? extends IPipeTile<?, ?>> walker = (PipeCollectorWalker<? extends IPipeTile<?, ?>>) new PipeCollectorWalker<>(
world, sourcePipe, 0, pipe.getClass());
walker.traversePipeNet(limit);
Comment thread
htmlcsjs marked this conversation as resolved.
Outdated
return walker.isFailed() ? Collections.emptyList() : Collections.unmodifiableList(walker.pipes);
}

public static List<IPipeTile<?, ?>> collectPipeNet(World world, BlockPos sourcePipe, IPipeTile<?, ?> pipe) {
// Default limit for a pipenet walker
return collectPipeNet(world, sourcePipe, pipe, 32768);
}

// I love type erasure
private final Class<T> basePipeClass;
private List<T> pipes = new ArrayList<>();
private BlockPos sourcePipe;

protected PipeCollectorWalker(World world, BlockPos sourcePipe, int walkedBlocks, Class<T> basePipeClass) {
super(world, sourcePipe, walkedBlocks);
this.sourcePipe = sourcePipe;
this.basePipeClass = basePipeClass;
}

@Override
protected PipeNetWalker<T> createSubWalker(World world, EnumFacing facingToNextPos, BlockPos nextPos,
int walkedBlocks) {
PipeCollectorWalker<T> walker = new PipeCollectorWalker<>(world, nextPos, walkedBlocks, this.basePipeClass);
walker.pipes = pipes;
walker.sourcePipe = sourcePipe;
return walker;
}

@Override
protected void checkPipe(T pipeTile, BlockPos pos) {
this.pipes.add(pipeTile);
}

@Override
protected void checkNeighbour(T pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour,
@Nullable TileEntity neighbourTile) {}

@Override
protected Class<T> getBasePipeClass() {
return basePipeClass;
}
}
1 change: 1 addition & 0 deletions src/main/resources/assets/gregtech/lang/en_us.lang
Original file line number Diff line number Diff line change
Expand Up @@ -4717,6 +4717,7 @@ behaviour.paintspray.red.tooltip=Can paint things in Red
behaviour.paintspray.black.tooltip=Can paint things in Black
behaviour.paintspray.uses=Remaining Uses: %,d
behaviour.paintspray.offhand=Hold in offhand to color while placing blocks
behaviour.paintspray.crouch=Crouch to spray connected pipes
behaviour.prospecting=Usable for Prospecting

# Multiblock machine controllers
Expand Down