aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/gregtech/api/enums/Dyes.java17
-rw-r--r--src/main/java/gregtech/api/enums/SoundResource.java4
-rw-r--r--src/main/java/gregtech/api/interfaces/IItemBehaviour.java34
-rw-r--r--src/main/java/gregtech/api/items/GTGenericItem.java6
-rw-r--r--src/main/java/gregtech/api/items/MetaBaseItem.java16
-rw-r--r--src/main/java/gregtech/api/items/MetaGeneratedItem.java6
-rw-r--r--src/main/java/gregtech/api/net/GTPacketInfiniteSpraycan.java121
-rw-r--r--src/main/java/gregtech/api/util/ColoredBlockContainer.java348
-rw-r--r--src/main/java/gregtech/client/GTMouseEventHandler.java4
-rw-r--r--src/main/java/gregtech/common/GTClient.java4
-rw-r--r--src/main/java/gregtech/common/blocks/BlockMachines.java20
-rw-r--r--src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java13
-rw-r--r--src/main/java/gregtech/common/items/MetaGeneratedItem01.java5
-rw-r--r--src/main/java/gregtech/common/items/behaviors/BehaviourSprayColor.java74
-rw-r--r--src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorInfinite.java282
-rw-r--r--src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorRemover.java34
-rw-r--r--src/main/java/gregtech/common/render/items/DataStickRenderer.java11
-rw-r--r--src/main/java/gregtech/common/render/items/InfiniteSprayCanRenderer.java83
-rw-r--r--src/main/java/gregtech/common/render/items/MetaGeneratedItemRenderer.java60
-rw-r--r--src/main/resources/assets/gregtech/lang/en_US.lang11
-rw-r--r--src/main/resources/assets/gregtech/sounds.json40
-rw-r--r--src/main/resources/assets/gregtech/sounds/spraycan_lock.oggbin0 -> 10151 bytes
-rw-r--r--src/main/resources/assets/gregtech/sounds/spraycan_shake.ogg (renamed from src/main/resources/assets/gregtech/sounds/spraycan.ogg)bin20679 -> 20679 bytes
-rw-r--r--src/main/resources/assets/gregtech/sounds/spraycan_unlock.oggbin0 -> 10358 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/1.pngbin0 -> 4583 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/2.pngbin0 -> 4450 bytes
-rw-r--r--src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/3.pngbin0 -> 4456 bytes
27 files changed, 1018 insertions, 175 deletions
diff --git a/src/main/java/gregtech/api/enums/Dyes.java b/src/main/java/gregtech/api/enums/Dyes.java
index 1dedcb6af0..72113b554a 100644
--- a/src/main/java/gregtech/api/enums/Dyes.java
+++ b/src/main/java/gregtech/api/enums/Dyes.java
@@ -6,6 +6,8 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.Contract;
+
import gregtech.api.interfaces.IColorModulationContainer;
import gregtech.api.objects.GTArrayList;
import gregtech.api.util.GTUtility;
@@ -123,4 +125,19 @@ public enum Dyes implements IColorModulationContainer {
public static Dyes getDyeFromIndex(short index) {
return index != -1 ? Dyes.get(index) : Dyes.MACHINE_METAL;
}
+
+ /**
+ * Transforms a dye index between the GT index for this color and the vanilla index for this color.
+ *
+ * @param color an integer between 0 and 15
+ * @return the transformed color
+ */
+ @Contract(pure = true)
+ public static int transformDyeIndex(final int color) {
+ if (color < 0 || color > 15) {
+ throw new IllegalArgumentException("Color passed to transformColor must be between 0 and 15");
+ }
+
+ return (~(byte) color) & 0xF;
+ }
}
diff --git a/src/main/java/gregtech/api/enums/SoundResource.java b/src/main/java/gregtech/api/enums/SoundResource.java
index f6ca0485dc..eea2cf477e 100644
--- a/src/main/java/gregtech/api/enums/SoundResource.java
+++ b/src/main/java/gregtech/api/enums/SoundResource.java
@@ -74,7 +74,9 @@ public enum SoundResource {
GT_MACHINES_MULTI_LATHE_LOOP(241, GregTech.ID, "machines.MultiLatheLoop"),
GT_MACHINES_MULTI_AUTOCLAVE_LOOP(242, GregTech.ID, "machines.MultiAutoclaveLoop"),
- GT_SPRAYCAN_SHAKE(243, GregTech.ID, "items.spraycan"),
+ GT_SPRAYCAN_SHAKE(243, GregTech.ID, "items.spraycan_shake"),
+ GT_SPRAYCAN_LOCK(244, GregTech.ID, "items.spraycan_lock"),
+ GT_SPRAYCAN_UNLOCK(245, GregTech.ID, "items.spraycan_unlock"),
GUI_BUTTON_DOWN(-1, GregTech.ID, "gui.buttonDown"),
GUI_BUTTON_UP(-1, GregTech.ID, "gui.buttonUp"),
diff --git a/src/main/java/gregtech/api/interfaces/IItemBehaviour.java b/src/main/java/gregtech/api/interfaces/IItemBehaviour.java
index 8c5dad6dc2..1f728025a7 100644
--- a/src/main/java/gregtech/api/interfaces/IItemBehaviour.java
+++ b/src/main/java/gregtech/api/interfaces/IItemBehaviour.java
@@ -9,9 +9,12 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
+import com.google.common.collect.ImmutableList;
+
import gregtech.api.enums.SubTag;
import gregtech.api.items.MetaBaseItem;
@@ -21,6 +24,33 @@ public interface IItemBehaviour<E extends Item> {
return false;
}
+ default boolean onMiddleClick(E aItem, ItemStack aStack, EntityPlayer aPlayer) {
+ return false;
+ }
+
+ /**
+ * Suppresses standard block activation for a {@link gregtech.common.blocks.BlockMachines GT machine block}. Put
+ * your item's right click activation in
+ * {@link #onItemUse(Item, ItemStack, EntityPlayer, World, int, int, int, int, float, float, float) onItemUse}
+ * for best results.
+ * <p>
+ * Typically used when the item needs support for the Ring of Loki (from Botania.) If you don't care about that,
+ * using
+ * {@link #onItemUseFirst(Item, ItemStack, EntityPlayer, World, int, int, int, ForgeDirection, float, float, float)
+ * onItemUseFirst}
+ * instead of {@link #onItemUse(Item, ItemStack, EntityPlayer, World, int, int, int, int, float, float, float)
+ * onItemUse}
+ * will act before block activation with a little less overhead.
+ *
+ * @param player the player making the request
+ * @param tileEntity the tile entity that is attempting to be activated
+ * @param side the side of the tile entity that the player clicked on
+ * @return true if standard block activation should be suppressed
+ */
+ default boolean shouldInterruptBlockActivation(EntityPlayer player, TileEntity tileEntity, ForgeDirection side) {
+ return false;
+ }
+
boolean onLeftClickEntity(E aItem, ItemStack aStack, EntityPlayer aPlayer, Entity aEntity);
boolean onItemUse(E aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ,
@@ -33,6 +63,10 @@ public interface IItemBehaviour<E extends Item> {
List<String> getAdditionalToolTips(E aItem, List<String> aList, ItemStack aStack);
+ default List<String> getAdditionalToolTipsWhileSneaking(E aItem, List<String> aList, ItemStack aStack) {
+ return ImmutableList.of();
+ }
+
void onUpdate(E aItem, ItemStack aStack, World aWorld, Entity aPlayer, int aTimer, boolean aIsInHand);
boolean isItemStackUsable(E aItem, ItemStack aStack);
diff --git a/src/main/java/gregtech/api/items/GTGenericItem.java b/src/main/java/gregtech/api/items/GTGenericItem.java
index 4f0994bb12..5febfcc173 100644
--- a/src/main/java/gregtech/api/items/GTGenericItem.java
+++ b/src/main/java/gregtech/api/items/GTGenericItem.java
@@ -151,7 +151,11 @@ public class GTGenericItem extends Item implements IProjectileItem {
@Override
public ItemStack dispenseStack(IBlockSource aSource, ItemStack aStack) {
- return ((GTGenericItem) aStack.getItem()).onDispense(aSource, aStack);
+ final GTGenericItem item = (GTGenericItem) aStack.getItem();
+ if (item != null) {
+ return item.onDispense(aSource, aStack);
+ }
+ return aStack;
}
@Override
diff --git a/src/main/java/gregtech/api/items/MetaBaseItem.java b/src/main/java/gregtech/api/items/MetaBaseItem.java
index 32e4bba392..fa47043fcc 100644
--- a/src/main/java/gregtech/api/items/MetaBaseItem.java
+++ b/src/main/java/gregtech/api/items/MetaBaseItem.java
@@ -24,6 +24,8 @@ import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidContainerItem;
+import com.gtnewhorizons.modularui.api.KeyboardUtil;
+
import gregtech.api.enums.SubTag;
import gregtech.api.interfaces.IItemBehaviour;
import gregtech.api.util.GTLanguageManager;
@@ -123,6 +125,10 @@ public abstract class MetaBaseItem extends GTGenericItem
return forEachBehavior(aStack, behavior -> behavior.onLeftClick(this, aStack, aPlayer));
}
+ public boolean onMiddleClick(ItemStack aStack, EntityPlayer aPlayer) {
+ return forEachBehavior(aStack, behavior -> behavior.onMiddleClick(this, aStack, aPlayer));
+ }
+
@Override
public boolean onLeftClickEntity(ItemStack aStack, EntityPlayer aPlayer, Entity aEntity) {
use(aStack, 0, aPlayer);
@@ -260,9 +266,13 @@ public abstract class MetaBaseItem extends GTGenericItem
"" + formatNumbers(tStats[0])) + EnumChatFormatting.GRAY);
}
- ArrayList<IItemBehaviour<MetaBaseItem>> tList = mItemBehaviors.get((short) getDamage(aStack));
- if (tList != null) for (IItemBehaviour<MetaBaseItem> tBehavior : tList)
- aList = tBehavior.getAdditionalToolTips(this, aList, aStack);
+ ArrayList<IItemBehaviour<MetaBaseItem>> behaviours = mItemBehaviors.get((short) getDamage(aStack));
+ if (behaviours != null) {
+ for (IItemBehaviour<MetaBaseItem> behavior : behaviours) {
+ aList = !KeyboardUtil.isShiftKeyDown() ? behavior.getAdditionalToolTips(this, aList, aStack)
+ : behavior.getAdditionalToolTipsWhileSneaking(this, aList, aStack);
+ }
+ }
addAdditionalToolTips(aList, aStack, aPlayer);
}
diff --git a/src/main/java/gregtech/api/items/MetaGeneratedItem.java b/src/main/java/gregtech/api/items/MetaGeneratedItem.java
index 449b1ced24..0d8c1f1b32 100644
--- a/src/main/java/gregtech/api/items/MetaGeneratedItem.java
+++ b/src/main/java/gregtech/api/items/MetaGeneratedItem.java
@@ -244,6 +244,12 @@ public abstract class MetaGeneratedItem extends MetaBaseItem implements IGT_Item
return this;
}
+ @SuppressWarnings("UnusedReturnValue")
+ public final MetaGeneratedItem setSubIcons(int metaValue, int length) {
+ mIconList[metaValue] = Arrays.copyOf(mIconList[metaValue], length + 1);
+ return this;
+ }
+
/**
*
* @param aMetaValue the Meta Value of the Item you want to set it to. [0 - 32765]
diff --git a/src/main/java/gregtech/api/net/GTPacketInfiniteSpraycan.java b/src/main/java/gregtech/api/net/GTPacketInfiniteSpraycan.java
index 66ad89590f..302937f6ba 100644
--- a/src/main/java/gregtech/api/net/GTPacketInfiniteSpraycan.java
+++ b/src/main/java/gregtech/api/net/GTPacketInfiniteSpraycan.java
@@ -1,5 +1,7 @@
package gregtech.api.net;
+import java.nio.charset.StandardCharsets;
+
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.network.INetHandler;
@@ -16,16 +18,24 @@ import io.netty.buffer.ByteBuf;
public class GTPacketInfiniteSpraycan extends GTPacketNew {
- private boolean wasSneaking;
+ private Action action;
+ private int newColor;
private EntityPlayerMP player;
public GTPacketInfiniteSpraycan() {
super(true);
}
- public GTPacketInfiniteSpraycan(boolean wasSneaking) {
+ public GTPacketInfiniteSpraycan(Action action) {
+ super(false);
+ this.action = action;
+ this.newColor = -1;
+ }
+
+ public GTPacketInfiniteSpraycan(Action action, int newColor) {
super(false);
- this.wasSneaking = wasSneaking;
+ this.action = action;
+ this.newColor = newColor;
}
@Override
@@ -35,12 +45,21 @@ public class GTPacketInfiniteSpraycan extends GTPacketNew {
@Override
public void encode(final ByteBuf aOut) {
- aOut.writeBoolean(wasSneaking);
+ final byte[] name = action.name()
+ .getBytes(StandardCharsets.UTF_8);
+ aOut.writeInt(newColor);
+ aOut.writeInt(name.length);
+ aOut.writeBytes(name);
}
@Override
public GTPacketNew decode(final ByteArrayDataInput aData) {
- return new GTPacketInfiniteSpraycan(aData.readBoolean());
+ final int newColor = aData.readInt();
+ final int length = aData.readInt();
+ final byte[] name = new byte[length];
+ aData.readFully(name, 0, length);
+
+ return new GTPacketInfiniteSpraycan(Action.valueOf(new String(name, StandardCharsets.UTF_8)), newColor);
}
@Override
@@ -53,24 +72,94 @@ public class GTPacketInfiniteSpraycan extends GTPacketNew {
ItemStack currentItemStack = player.inventory.getCurrentItem();
if (currentItemStack != null && currentItemStack.getItem() instanceof MetaBaseItem item) {
item.forEachBehavior(currentItemStack, behavior -> {
- if (behavior instanceof BehaviourSprayColorInfinite spraycanBehavior) {
- spraycanBehavior.setNewColor(currentItemStack, wasSneaking);
+ if (behavior instanceof BehaviourSprayColorInfinite spraycanBehavior
+ && action.execute(spraycanBehavior, currentItemStack, player, newColor)) {
player.sendSlotContents(player.inventoryContainer, player.inventory.currentItem, currentItemStack);
+ return true;
+ }
+
+ return false;
+ });
+ }
+ }
+
+ public enum Action {
- GTUtility.sendSoundToPlayers(
- player.worldObj,
- SoundResource.GT_SPRAYCAN_SHAKE,
- 1.0F,
- 1,
- (int) player.posX,
- (int) player.posY,
- (int) player.posZ);
+ INCREMENT_COLOR {
+
+ @Override
+ boolean execute(final BehaviourSprayColorInfinite behaviour, final ItemStack itemStack,
+ final EntityPlayerMP player, final int newColor) {
+ if (!behaviour.isLocked(itemStack)) {
+ behaviour.incrementColor(itemStack, player.isSneaking());
+ playShakeSound(player);
return true;
}
+ return false;
+ }
+ },
+ LOCK_CAN {
+
+ @Override
+ boolean execute(final BehaviourSprayColorInfinite behavior, final ItemStack itemStack,
+ final EntityPlayerMP player, final int newColor) {
+ if (behavior.toggleLock(itemStack)) {
+ Action.playLockSound(player);
+ } else {
+ Action.playUnlockSound(player);
+ }
+ return true;
+ }
+ },
+ SET_COLOR {
+ @Override
+ boolean execute(final BehaviourSprayColorInfinite behavior, final ItemStack itemStack,
+ final EntityPlayerMP player, final int newColor) {
+ if (newColor != -1) {
+ behavior.setColor(itemStack, (byte) newColor);
+ Action.playShakeSound(player);
+ return true;
+ }
return false;
- });
+ }
+ };
+
+ private static void playShakeSound(final EntityPlayerMP player) {
+ GTUtility.sendSoundToPlayers(
+ player.worldObj,
+ SoundResource.GT_SPRAYCAN_SHAKE,
+ 1.0F,
+ 1,
+ (int) player.posX,
+ (int) player.posY,
+ (int) player.posZ);
+ }
+
+ private static void playLockSound(final EntityPlayerMP player) {
+ GTUtility.sendSoundToPlayers(
+ player.worldObj,
+ SoundResource.GT_SPRAYCAN_LOCK,
+ 1.0F,
+ 1,
+ (int) player.posX,
+ (int) player.posY,
+ (int) player.posZ);
}
+
+ private static void playUnlockSound(final EntityPlayerMP player) {
+ GTUtility.sendSoundToPlayers(
+ player.worldObj,
+ SoundResource.GT_SPRAYCAN_UNLOCK,
+ 1.0F,
+ 1,
+ (int) player.posX,
+ (int) player.posY,
+ (int) player.posZ);
+ }
+
+ abstract boolean execute(final BehaviourSprayColorInfinite behavior, ItemStack itemStack, EntityPlayerMP player,
+ final int newColor);
}
}
diff --git a/src/main/java/gregtech/api/util/ColoredBlockContainer.java b/src/main/java/gregtech/api/util/ColoredBlockContainer.java
new file mode 100644
index 0000000000..82956ff0c0
--- /dev/null
+++ b/src/main/java/gregtech/api/util/ColoredBlockContainer.java
@@ -0,0 +1,348 @@
+package gregtech.api.util;
+
+import java.util.Optional;
+import java.util.Set;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockColored;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableSet;
+
+import appeng.api.implementations.tiles.IColorableTile;
+import appeng.api.util.AEColor;
+import appeng.block.networking.BlockCableBus;
+import appeng.integration.IntegrationRegistry;
+import appeng.integration.IntegrationType;
+import appeng.integration.abstraction.IFMP;
+import appeng.tile.networking.TileCableBus;
+import gregtech.api.enums.Dyes;
+import gregtech.api.interfaces.tileentity.IColoredTileEntity;
+
+/**
+ * Used to provide a consistent interface for dealing with colors of blocks for the various spray can items.
+ * <p>
+ * Call {@link #getInstance(EntityPlayer, MovingObjectPosition)} or
+ * {@link #getInstance(World, int, int, int, ForgeDirection, EntityPlayer)}
+ * to acquire an instance of this class.
+ */
+public abstract class ColoredBlockContainer {
+
+ private final static ColoredBlockContainer NULL_INSTANCE = new NullContainer();
+
+ /**
+ * Sets the color of the block.
+ *
+ * @param newColor a color from 0-15
+ * @return true if the block was changed
+ */
+ public abstract boolean setColor(int newColor);
+
+ /**
+ * Removes the color of the block.
+ *
+ * @return true if color was removed
+ */
+ public abstract boolean removeColor();
+
+ /**
+ * Returns if the requested block is colorable.
+ *
+ * @return true if the block is colorable
+ */
+ public boolean isValid() {
+ return true;
+ }
+
+ /**
+ * Get the color of the block.
+ *
+ * @return an Optional with the color of the block inside, or {@link Optional#empty()} if the block is uncolored
+ * or invalid
+ */
+ public abstract Optional<Integer> getColor();
+
+ private ColoredBlockContainer() {}
+
+ public static ColoredBlockContainer getInstance(EntityPlayer player, MovingObjectPosition position) {
+ if (position == null || position.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) {
+ return NULL_INSTANCE;
+ }
+ return getInstance(
+ player.worldObj,
+ position.blockX,
+ position.blockY,
+ position.blockZ,
+ ForgeDirection.getOrientation(position.sideHit),
+ player);
+ }
+
+ public static ColoredBlockContainer getInstance(EntityPlayer player, TileEntity tileEntity, ForgeDirection side) {
+ if (tileEntity == null) {
+ return NULL_INSTANCE;
+ }
+
+ return getInstance(player.worldObj, tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord, side, player);
+ }
+
+ public static ColoredBlockContainer getInstance(World world, int x, int y, int z, ForgeDirection side,
+ EntityPlayer player) {
+ final Block block = world.getBlock(x, y, z);
+
+ // The vanilla method returns Blocks.air instead of null for a negative result
+ if (block != Blocks.air) {
+ if (VanillaBlockContainer.ALLOWED_VANILLA_BLOCKS.contains(block) || block instanceof BlockColored) {
+ return new VanillaBlockContainer(block, world, x, y, z, side);
+ } else if (block instanceof final BlockCableBus bus) {
+ return new AE2BlockCableBusContainer(bus, world, x, y, z, side, player);
+ } else {
+ final TileEntity tileEntity = world.getTileEntity(x, y, z);
+
+ if (tileEntity instanceof final IColorableTile colorableTile) {
+ return new AE2ColorableTileContainer(colorableTile, side, player);
+ } else if (tileEntity instanceof final IColoredTileEntity coloredTileEntity) {
+ return new GTColoredBlockContainer(coloredTileEntity);
+ }
+ }
+ }
+ return NULL_INSTANCE;
+ }
+
+ /**
+ * Provides functionality for various types of vanilla blocks that use their metadata value for color. Also performs
+ * some transformations of blocks, e.g. glass is transformed to stained glass when sprayed.
+ */
+ private static class VanillaBlockContainer extends ColoredBlockContainer {
+
+ private static final Set<Block> ALLOWED_VANILLA_BLOCKS = ImmutableSet.of(
+ Blocks.glass,
+ Blocks.glass_pane,
+ Blocks.stained_glass,
+ Blocks.stained_glass_pane,
+ Blocks.carpet,
+ Blocks.hardened_clay,
+ Blocks.stained_hardened_clay);
+ private static final BiMap<Block, Block> TRANSFORMATIONS = ImmutableBiMap.of(
+ Blocks.glass,
+ Blocks.stained_glass,
+ Blocks.glass_pane,
+ Blocks.stained_glass_pane,
+ Blocks.hardened_clay,
+ Blocks.stained_hardened_clay);
+
+ private final int originalColor;
+ private final World world;
+ private final int x;
+ private final int y;
+ private final int z;
+ private final Block block;
+ private final ForgeDirection side;
+
+ public VanillaBlockContainer(final Block block, final World world, final int x, final int y, final int z,
+ final ForgeDirection side) {
+ this.world = world;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.block = block;
+ this.side = side;
+ originalColor = world.getBlockMetadata(x, y, z);
+ }
+
+ @Override
+ public Optional<Integer> getColor() {
+ return Optional.of(Dyes.transformDyeIndex(originalColor));
+ }
+
+ @Override
+ public boolean setColor(final int newColor) {
+ final int transformedColor = Dyes.transformDyeIndex(newColor);
+
+ if (TRANSFORMATIONS.containsKey(block)) {
+ world.setBlock(x, y, z, TRANSFORMATIONS.get(block), transformedColor, 3);
+ return true;
+ } else {
+ if (originalColor != transformedColor) {
+ if (block instanceof BlockColored) {
+ return block.recolourBlock(world, x, y, z, side, transformedColor);
+ }
+ return world.setBlockMetadataWithNotify(x, y, z, transformedColor, 3);
+ }
+ }
+
+ return block.recolourBlock(world, x, y, z, side, transformedColor);
+ }
+
+ @Override
+ public boolean removeColor() {
+ if (TRANSFORMATIONS.containsValue(block)) {
+ world.setBlock(
+ x,
+ y,
+ z,
+ TRANSFORMATIONS.inverse()
+ .get(block),
+ 0,
+ 3);
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Provides functionality for full AE2 blocks like the ME Chest and Security Terminal.
+ */
+ private static class AE2ColorableTileContainer extends ColoredBlockContainer {
+
+ private final IColorableTile colorableTile;
+ private final ForgeDirection side;
+ private final EntityPlayer player;
+
+ public AE2ColorableTileContainer(final IColorableTile colorableTile, final ForgeDirection side,
+ final EntityPlayer player) {
+ this.colorableTile = colorableTile;
+ this.side = side;
+ this.player = player;
+ }
+
+ @Override
+ public Optional<Integer> getColor() {
+ return Optional.of(
+ Dyes.transformDyeIndex(
+ colorableTile.getColor()
+ .ordinal()));
+ }
+
+ @Override
+ public boolean setColor(final int newColor) {
+ return colorableTile.recolourBlock(side, AEColor.values()[Dyes.transformDyeIndex(newColor)], player);
+ }
+
+ @Override
+ public boolean removeColor() {
+ return colorableTile.recolourBlock(side, AEColor.Transparent, player);
+ }
+ }
+
+ /**
+ * Provides functionality for AE2 cables and other multipart things that go on cables.
+ */
+ private static class AE2BlockCableBusContainer extends ColoredBlockContainer {
+
+ private final BlockCableBus bus;
+ private final World world;
+ private final int x;
+ private final int y;
+ private final int z;
+ private final ForgeDirection side;
+ private final EntityPlayer player;
+
+ public AE2BlockCableBusContainer(final BlockCableBus bus, final World world, final int x, final int y,
+ final int z, final ForgeDirection side, final EntityPlayer player) {
+ this.bus = bus;
+ this.world = world;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.side = side;
+ this.player = player;
+ }
+
+ @Override
+ public boolean setColor(final int newColor) {
+ return bus.recolourBlock(world, x, y, z, side, Dyes.transformDyeIndex(newColor), player);
+ }
+
+ @Override
+ public boolean removeColor() {
+ return bus.recolourBlock(world, x, y, z, side, AEColor.Transparent.ordinal(), player);
+ }
+
+ @Override
+ public Optional<Integer> getColor() {
+ final TileEntity te = world.getTileEntity(x, y, z);
+ AEColor aeColor = null;
+
+ // Code stolen from an AE2 private method.
+ if (te instanceof final TileCableBus cableBus) {
+ aeColor = cableBus.getCableBus().getColor();
+ } else if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.FMP)) {
+ aeColor = ((IFMP) IntegrationRegistry.INSTANCE.getInstance(IntegrationType.FMP)).getCableContainer(te).getColor();
+ }
+
+ return aeColor == null ? Optional.empty() : Optional.of(Dyes.transformDyeIndex(aeColor.ordinal()));
+ }
+ }
+
+ /**
+ * Provides functionality for GT machines, cables, pipes, etc.
+ */
+ private static class GTColoredBlockContainer extends ColoredBlockContainer {
+
+ private final IColoredTileEntity coloredTileEntity;
+
+ public GTColoredBlockContainer(final IColoredTileEntity coloredTileEntity) {
+ this.coloredTileEntity = coloredTileEntity;
+ }
+
+ @Override
+ public boolean setColor(final int newColor) {
+ coloredTileEntity.setColorization((byte) newColor);
+ return true;
+ }
+
+ @Override
+ public boolean removeColor() {
+ if (coloredTileEntity.getColorization() > -1) {
+ coloredTileEntity.setColorization((byte) -1);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Optional<Integer> getColor() {
+ final int colorization = coloredTileEntity.getColorization();
+ if (colorization == -1) {
+ return Optional.empty();
+ }
+ return Optional.of(colorization);
+ }
+ }
+
+ /**
+ * Returned when the block is invalid or otherwise has no color functionality. Calling {@link #setColor(int)} does
+ * nothing, so it's safe to call without verifying the exact instance of the returned {@link ColoredBlockContainer}.
+ */
+ private static class NullContainer extends ColoredBlockContainer {
+
+ @Override
+ public boolean setColor(final int newColor) {
+ return false;
+ }
+
+ @Override
+ public boolean removeColor() {
+ return false;
+ }
+
+ @Override
+ public Optional<Integer> getColor() {
+ return Optional.empty();
+ }
+
+ @Override
+ public boolean isValid() {
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/client/GTMouseEventHandler.java b/src/main/java/gregtech/client/GTMouseEventHandler.java
index 15112b2888..7225faebc2 100644
--- a/src/main/java/gregtech/client/GTMouseEventHandler.java
+++ b/src/main/java/gregtech/client/GTMouseEventHandler.java
@@ -30,5 +30,9 @@ public class GTMouseEventHandler {
if (event.button == 0 && event.buttonstate && heldItem.getItem() instanceof MetaBaseItem mbItem) {
event.setCanceled(mbItem.onLeftClick(heldItem, player));
}
+
+ if (event.button == 2 && event.buttonstate && heldItem.getItem() instanceof MetaBaseItem mbItem) {
+ event.setCanceled(mbItem.onMiddleClick(heldItem, player));
+ }
}
}
diff --git a/src/main/java/gregtech/common/GTClient.java b/src/main/java/gregtech/common/GTClient.java
index 07d11fe214..844731e82f 100644
--- a/src/main/java/gregtech/common/GTClient.java
+++ b/src/main/java/gregtech/common/GTClient.java
@@ -103,6 +103,8 @@ import gregtech.common.render.MetaGeneratedToolRenderer;
import gregtech.common.render.MultiTileRenderer;
import gregtech.common.render.PollutionRenderer;
import gregtech.common.render.WormholeRenderer;
+import gregtech.common.render.items.DataStickRenderer;
+import gregtech.common.render.items.InfiniteSprayCanRenderer;
import gregtech.common.render.items.MetaGeneratedItemRenderer;
import gregtech.common.tileentities.debug.MTEAdvDebugStructureWriter;
import gregtech.loaders.ExtraIcons;
@@ -645,6 +647,8 @@ public class GTClient extends GTProxy implements Runnable {
new MetaGeneratedToolRenderer();
new FlaskRenderer();
new FluidDisplayStackRenderer();
+ new DataStickRenderer();
+ new InfiniteSprayCanRenderer();
MinecraftForge.EVENT_BUS.register(new NEIGTConfig());
MinecraftForge.EVENT_BUS.register(new GTMouseEventHandler());
}
diff --git a/src/main/java/gregtech/common/blocks/BlockMachines.java b/src/main/java/gregtech/common/blocks/BlockMachines.java
index 1db6f51730..4c392f8cf5 100644
--- a/src/main/java/gregtech/common/blocks/BlockMachines.java
+++ b/src/main/java/gregtech/common/blocks/BlockMachines.java
@@ -42,6 +42,7 @@ import gregtech.api.interfaces.tileentity.ICoverable;
import gregtech.api.interfaces.tileentity.IDebugableTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.items.GTGenericBlock;
+import gregtech.api.items.MetaBaseItem;
import gregtech.api.metatileentity.BaseMetaPipeEntity;
import gregtech.api.metatileentity.BaseMetaTileEntity;
import gregtech.api.metatileentity.BaseTileEntity;
@@ -358,14 +359,28 @@ public class BlockMachines extends GTGenericBlock implements IDebugableBlock, IT
if (tTileEntity == null) {
return false;
}
+
+ final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+
if (aPlayer.isSneaking()) {
- final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
if (tCurrentItem != null && !GTUtility.isStackInList(tCurrentItem, GregTechAPI.sScrewdriverList)
&& !GTUtility.isStackInList(tCurrentItem, GregTechAPI.sWrenchList)
&& !GTUtility.isStackInList(tCurrentItem, GregTechAPI.sWireCutterList)
&& !GTUtility.isStackInList(tCurrentItem, GregTechAPI.sSolderingToolList)
&& !GTUtility.isStackInList(tCurrentItem, GregTechAPI.sJackhammerList)) return false;
}
+
+ final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
+
+ // Used for Ring of Loki support
+ if (tCurrentItem != null && tCurrentItem.getItem() instanceof MetaBaseItem mbItem) {
+ if (mbItem.forEachBehavior(
+ tCurrentItem,
+ behavior -> behavior.shouldInterruptBlockActivation(aPlayer, tTileEntity, side))) {
+ return false;
+ }
+ }
+
if (tTileEntity instanceof IGregTechTileEntity gtTE) {
if (gtTE.getTimer() < 1L) {
return false;
@@ -373,8 +388,7 @@ public class BlockMachines extends GTGenericBlock implements IDebugableBlock, IT
if ((!aWorld.isRemote) && !gtTE.isUseableByPlayer(aPlayer)) {
return true;
}
- return ((IGregTechTileEntity) tTileEntity)
- .onRightclick(aPlayer, ForgeDirection.getOrientation(ordinalSide), aOffsetX, aOffsetY, aOffsetZ);
+ return ((IGregTechTileEntity) tTileEntity).onRightclick(aPlayer, side, aOffsetX, aOffsetY, aOffsetZ);
}
return false;
}
diff --git a/src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java b/src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java
index 0163c6fb7b..535263dd00 100644
--- a/src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java
+++ b/src/main/java/gregtech/common/gui/modularui/uifactory/SelectItemUIFactory.java
@@ -18,6 +18,7 @@ import com.gtnewhorizons.modularui.api.drawable.ItemDrawable;
import com.gtnewhorizons.modularui.api.drawable.Text;
import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.api.widget.Widget;
import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
import com.gtnewhorizons.modularui.common.widget.TextWidget;
@@ -167,14 +168,14 @@ public class SelectItemUIFactory {
}
}.setOnClick((clickData, widget) -> {
if (clickData.mouseButton == 0) {
- setSelected(index);
+ setSelected(index, widget);
} else {
- setSelected(UNSELECTED);
+ setSelected(UNSELECTED, widget);
}
selectedCallback.accept(getCandidate(getSelected()));
})
.setSynced(false, false)
- .dynamicTooltip(() -> GuiHelper.getItemTooltip(stacks.get(index)))
+ .dynamicTooltip(() -> getItemTooltips(index))
.setUpdateTooltipEveryTick(true)
.setBackground(
() -> new IDrawable[] {
@@ -207,7 +208,7 @@ public class SelectItemUIFactory {
return selected;
}
- public void setSelected(int selected) {
+ public void setSelected(int selected, Widget widget) {
if (selected == this.selected) return;
int newSelected = GTUtility.clamp(selected, UNSELECTED, stacks.size() - 1);
if (noDeselect && newSelected == UNSELECTED) return;
@@ -215,6 +216,10 @@ public class SelectItemUIFactory {
this.selected = newSelected;
}
+ protected List<String> getItemTooltips(final int index) {
+ return GuiHelper.getItemTooltip(stacks.get(index));
+ }
+
private ItemStack getCandidate(int listIndex) {
return listIndex < 0 || listIndex >= stacks.size() ? null : stacks.get(listIndex);
}
diff --git a/src/main/java/gregtech/common/items/MetaGeneratedItem01.java b/src/main/java/gregtech/common/items/MetaGeneratedItem01.java
index 9afdb22673..68eea152a6 100644
--- a/src/main/java/gregtech/common/items/MetaGeneratedItem01.java
+++ b/src/main/java/gregtech/common/items/MetaGeneratedItem01.java
@@ -3462,6 +3462,7 @@ public class MetaGeneratedItem01 extends MetaGeneratedItemX32 {
setAllFluidContainerStats();
setAllElectricStats();
registerTieredTooltips();
+ registerSubIcons();
craftingShapedRecipes();
craftingShapelessRecipes();
@@ -4634,6 +4635,10 @@ public class MetaGeneratedItem01 extends MetaGeneratedItemX32 {
setElectricStats(32000 + BatteryHull_UxV_Full.ID, 1677721600000L, GTValues.V[13], 13L, -3L, true);
}
+ private void registerSubIcons() {
+ setSubIcons(Spray_Color_Infinite.ID, 3);
+ }
+
private void registerTieredTooltips() {
registerTieredTooltip(ItemList.Battery_RE_ULV_Tantalum.get(1), ULV);
registerTieredTooltip(ItemList.Battery_SU_LV_SulfuricAcid.get(1), LV);
diff --git a/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColor.java b/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColor.java
index 8c655907f2..60b586335f 100644
--- a/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColor.java
+++ b/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColor.java
@@ -1,13 +1,9 @@
package gregtech.common.items.behaviors;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
import net.minecraft.block.Block;
-import net.minecraft.block.BlockColored;
import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -16,13 +12,11 @@ import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
-import appeng.api.implementations.tiles.IColorableTile;
-import appeng.api.util.AEColor;
-import appeng.block.networking.BlockCableBus;
import gregtech.api.enums.Dyes;
import gregtech.api.enums.SoundResource;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.items.MetaBaseItem;
+import gregtech.api.util.ColoredBlockContainer;
import gregtech.api.util.GTLanguageManager;
import gregtech.api.util.GTUtility;
import gregtech.common.config.Other;
@@ -34,13 +28,6 @@ public class BehaviourSprayColor extends BehaviourNone {
private final ItemStack mFull;
private final long mUses;
private final byte mColor;
- private final Collection<Block> mAllowedVanillaBlocks = Arrays.asList(
- Blocks.glass,
- Blocks.glass_pane,
- Blocks.stained_glass,
- Blocks.stained_glass_pane,
- Blocks.carpet,
- Blocks.hardened_clay);
protected String mTooltip;
private final String mTooltipUses = GTLanguageManager
.addStringLocalization("gt.behaviour.paintspray.uses", "Remaining Uses:");
@@ -75,6 +62,21 @@ public class BehaviourSprayColor extends BehaviourNone {
}
@Override
+ // Included for Ring of Loki support.
+ public boolean onItemUse(final MetaBaseItem aItem, final ItemStack aStack, final EntityPlayer aPlayer,
+ final World aWorld, final int aX, final int aY, final int aZ, final int ordinalSide, final float hitX,
+ final float hitY, final float hitZ) {
+ final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
+
+ if (ColoredBlockContainer.getInstance(aWorld, aX, aY, aZ, side, aPlayer)
+ .isValid()) {
+ return onItemUseFirst(aItem, aStack, aPlayer, aWorld, aX, aY, aZ, side, hitX, hitY, hitZ);
+ }
+
+ return false;
+ }
+
+ @Override
public boolean onItemUseFirst(MetaBaseItem aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
if ((aWorld.isRemote) || (aStack.stackSize != 1)) {
@@ -130,8 +132,8 @@ public class BehaviourSprayColor extends BehaviourNone {
if (aWorld.getBlockMetadata(aX, aY, aZ) != initialBlockMeta) break;
/*
- * Check if the initial block had a TE and if the next one does, check if its the same kind.
- * else one does and the other doesnt, thus stop checking.
+ * Check if the initial block had a TE and if the next one does, check if it's the same kind.
+ * else one does and the other doesn't, thus stop checking.
*/
TileEntity targetTE = aWorld.getTileEntity(aX, aY, aZ);
if (initialTE == null ^ targetTE == null) break;
@@ -149,6 +151,13 @@ public class BehaviourSprayColor extends BehaviourNone {
return rOutput;
}
+ @Override
+ public boolean shouldInterruptBlockActivation(final EntityPlayer player, final TileEntity tileEntity,
+ final ForgeDirection side) {
+ return ColoredBlockContainer.getInstance(player, tileEntity, side)
+ .isValid();
+ }
+
protected long getUses(ItemStack aStack, NBTTagCompound tNBT) {
long tUses = tNBT.getLong("GT.RemainingPaint");
if (GTUtility.areStacksEqual(aStack, this.mFull, true)) {
@@ -180,37 +189,8 @@ public class BehaviourSprayColor extends BehaviourNone {
}
protected boolean colorize(World aWorld, int aX, int aY, int aZ, ForgeDirection side, EntityPlayer player) {
- final Block aBlock = aWorld.getBlock(aX, aY, aZ);
- if (aBlock != Blocks.air) {
- if (this.mAllowedVanillaBlocks.contains(aBlock) || aBlock instanceof BlockColored) {
- if (aBlock == Blocks.hardened_clay) {
- aWorld.setBlock(aX, aY, aZ, Blocks.stained_hardened_clay, (~getColor()) & 0xF, 3);
- return true;
- }
- if (aBlock == Blocks.glass_pane) {
- aWorld.setBlock(aX, aY, aZ, Blocks.stained_glass_pane, (~getColor()) & 0xF, 3);
- return true;
- }
- if (aBlock == Blocks.glass) {
- aWorld.setBlock(aX, aY, aZ, Blocks.stained_glass, (~getColor()) & 0xF, 3);
- return true;
- }
- if (aWorld.getBlockMetadata(aX, aY, aZ) == ((~getColor()) & 0xF)) {
- return false;
- }
- aWorld.setBlockMetadataWithNotify(aX, aY, aZ, (~getColor()) & 0xF, 3);
- return true;
- }
-
- if (aBlock instanceof IColorableTile) {
- return ((IColorableTile) aBlock).recolourBlock(side, AEColor.values()[(~getColor()) & 0xF], player);
- }
-
- if (aBlock instanceof BlockCableBus) {
- return ((BlockCableBus) aBlock).recolourBlock(aWorld, aX, aY, aZ, side, (~getColor()) & 0xF, player);
- }
- }
- return aBlock.recolourBlock(aWorld, aX, aY, aZ, side, (~getColor()) & 0xF);
+ return ColoredBlockContainer.getInstance(aWorld, aX, aY, aZ, side, player)
+ .setColor(getColor());
}
protected byte getColor() {
diff --git a/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorInfinite.java b/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorInfinite.java
index 6f7d99fe3a..ad22dcb958 100644
--- a/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorInfinite.java
+++ b/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorInfinite.java
@@ -1,49 +1,71 @@
package gregtech.common.items.behaviors;
import static gregtech.api.enums.GTValues.AuthorQuerns;
+import static net.minecraft.util.MovingObjectPosition.MovingObjectType.BLOCK;
import java.util.List;
+import java.util.function.Consumer;
import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizon.gtnhlib.GTNHLib;
+import com.gtnewhorizons.modularui.api.UIInfos;
+import com.gtnewhorizons.modularui.api.widget.Widget;
+
import gregtech.api.enums.Dyes;
import gregtech.api.enums.GTValues;
+import gregtech.api.enums.ItemList;
import gregtech.api.items.MetaBaseItem;
import gregtech.api.net.GTPacketInfiniteSpraycan;
-import gregtech.api.util.GTLanguageManager;
+import gregtech.api.util.ColoredBlockContainer;
+import gregtech.api.util.GTUtility;
import gregtech.common.config.Other;
+import gregtech.common.gui.modularui.uifactory.SelectItemUIFactory;
public class BehaviourSprayColorInfinite extends BehaviourSprayColor {
private static final byte REMOVE_COLOR = (byte) Dyes.VALUES.length;
- private static final String COLOR_NBT_TAG = "current_color";
- private final String tooltipInfinite = GTLanguageManager
- .addStringLocalization("gt.behaviour.paintspray.infinite.tooltip", "Infinite uses");
- private final String tooltipSwitchHint = GTLanguageManager.addStringLocalization(
- "gt.behaviour.paintspray.infinite.hint.tooltip",
- "Left click to change color (sneak to reverse direction)");
+ private static final List<ItemStack> COLOR_SELECTIONS;
+ public static final String COLOR_NBT_TAG = "current_color";
+ public static final String LOCK_NBT_TAG = "is_locked";
+ public static final String SEPARATOR = "-----------------------------------------";
private byte mCurrentColor;
+ static {
+ final ImmutableList.Builder<ItemStack> builder = ImmutableList.builder();
+
+ for (int i = 0; i < 16; i++) {
+ builder.add(new ItemStack(Items.dye, 1, i));
+ }
+
+ builder.add(ItemList.Spray_Color_Remover.get(1));
+ COLOR_SELECTIONS = builder.build();
+ }
+
public BehaviourSprayColorInfinite(ItemStack sprayCan) {
super(sprayCan, sprayCan, sprayCan, Other.sprayCanChainRange, 0);
this.mTooltip = "";
mCurrentColor = 0;
}
+ // region Base Method Overrides
@Override
- protected long getUses(ItemStack aStack, NBTTagCompound tNBT) {
+ protected long getUses(ItemStack itemStack, NBTTagCompound tNBT) {
return Other.sprayCanChainRange;
}
@Override
- protected void setRemainingUses(ItemStack aStack, NBTTagCompound tNBT, long tUses) {
+ protected void setRemainingUses(ItemStack itemStack, NBTTagCompound tNBT, long tUses) {
// Infinite spray can; do nothing
}
@@ -56,87 +78,243 @@ public class BehaviourSprayColorInfinite extends BehaviourSprayColor {
}
@Override
- public boolean onItemUseFirst(MetaBaseItem aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX,
+ public boolean onItemUseFirst(MetaBaseItem aItem, ItemStack itemStack, EntityPlayer aPlayer, World aWorld, int aX,
int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) {
- if ((aWorld.isRemote) || (aStack.stackSize != 1)) {
+ if ((aWorld.isRemote) || (itemStack.stackSize != 1)) {
return false;
}
- if (aStack.hasTagCompound()) {
- final NBTTagCompound tag = aStack.getTagCompound();
+ if (itemStack.hasTagCompound()) {
+ final NBTTagCompound tag = itemStack.getTagCompound();
if (tag.hasKey(COLOR_NBT_TAG)) {
mCurrentColor = tag.getByte(COLOR_NBT_TAG);
}
}
- return super.onItemUseFirst(aItem, aStack, aPlayer, aWorld, aX, aY, aZ, side, hitX, hitY, hitZ);
+ return super.onItemUseFirst(aItem, itemStack, aPlayer, aWorld, aX, aY, aZ, side, hitX, hitY, hitZ);
}
@Override
protected boolean colorize(World aWorld, int aX, int aY, int aZ, ForgeDirection side, EntityPlayer player) {
+ ColoredBlockContainer block = ColoredBlockContainer.getInstance(aWorld, aX, aY, aZ, side, player);
if (mCurrentColor == REMOVE_COLOR) {
- return BehaviourSprayColorRemover.removeColor(aWorld, aX, aY, aZ, side, player);
+ return block.removeColor();
+ }
+ return block.setColor(getColor());
+ }
+
+ @Override
+ public List<String> getAdditionalToolTips(final MetaBaseItem aItem, final List<String> aList,
+ final ItemStack itemStack) {
+ aList.add(StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.tooltip.infinite"));
+ aList.add(mTooltipChain);
+ aList.add(SEPARATOR);
+ aList.add(StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.tooltip.more_info"));
+ aList.add(SEPARATOR);
+ aList.add(AuthorQuerns);
+
+ return aList;
+ }
+
+ @Override
+ public List<String> getAdditionalToolTipsWhileSneaking(final MetaBaseItem aItem, final List<String> aList,
+ final ItemStack aStack) {
+ aList.add(SEPARATOR);
+ aList.add(StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.tooltip.switch"));
+ aList.add(StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.tooltip.gui"));
+ aList.add(StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.tooltip.pick"));
+ aList.add(StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.tooltip.lock"));
+ aList.add(SEPARATOR);
+ aList.add(AuthorQuerns);
+
+ return aList;
+ }
+ // endregion
+
+ // region Raw Mouse Event Handlers
+ @Override
+ public boolean onLeftClick(MetaBaseItem item, ItemStack itemStack, EntityPlayer aPlayer) {
+ if (isLocked(itemStack)) {
+ displayLockedMessage();
+ } else {
+ sendPacket(GTPacketInfiniteSpraycan.Action.INCREMENT_COLOR);
}
- return super.colorize(aWorld, aX, aY, aZ, side, player);
+ return true;
}
- public boolean onLeftClick(MetaBaseItem item, ItemStack aStack, EntityPlayer aPlayer) {
- GTValues.NW.sendToServer(new GTPacketInfiniteSpraycan(aPlayer.isSneaking()));
+ @Override
+ public boolean onMiddleClick(final MetaBaseItem item, final ItemStack itemStack, final EntityPlayer player) {
+ if (player.isSneaking()) {
+ sendPacket(GTPacketInfiniteSpraycan.Action.LOCK_CAN);
+ } else if (isLocked(itemStack)) {
+ displayLockedMessage();
+ } else {
+ final MovingObjectPosition position = GTUtility.getPlayerLookingTarget(player);
+
+ if (position != null && position.typeOfHit == BLOCK) {
+ final ColoredBlockContainer block = ColoredBlockContainer.getInstance(player, position);
+ if (block.getColor()
+ .isPresent()) {
+ sendPacket(
+ GTPacketInfiniteSpraycan.Action.SET_COLOR,
+ block.getColor()
+ .get());
+ return true;
+ }
+ }
+
+ openGUI(player, itemStack);
+ }
return true;
}
+ // endregion
- private static byte clampColor(byte newColor) {
- if (newColor > REMOVE_COLOR) {
- newColor = 0;
- } else if (newColor < 0) {
- newColor = REMOVE_COLOR;
+ // region GUI
+ private void openGUI(final EntityPlayer player, final ItemStack itemStack) {
+ UIInfos.openClientUI(
+ player,
+ buildContext -> new DyeSelectGUI(
+ StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.gui.header"),
+ itemStack,
+ selectedStack -> sendPacket(
+ GTPacketInfiniteSpraycan.Action.SET_COLOR,
+ selectedStack.getItem() == Items.dye ? selectedStack.getItemDamage() : REMOVE_COLOR),
+ COLOR_SELECTIONS,
+ getColor(itemStack),
+ true).createWindow(buildContext));
+ }
+
+ private byte getColor(ItemStack sprayCan) {
+ if (sprayCan.hasTagCompound()) {
+ final NBTTagCompound tag = sprayCan.getTagCompound();
+ if (tag.hasKey(COLOR_NBT_TAG)) {
+ return tag.getByte(COLOR_NBT_TAG);
+ }
}
- return newColor;
+
+ return REMOVE_COLOR;
+ }
+
+ private static void displayLockedMessage() {
+ GTNHLib.proxy.printMessageAboveHotbar(
+ StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.gui.lock_error"),
+ 120,
+ true,
+ true);
}
+ // endregion
- public void setNewColor(final ItemStack aStack, final boolean wasSneaking) {
- final NBTTagCompound tag = aStack.hasTagCompound() ? aStack.getTagCompound() : new NBTTagCompound();
+ // region Networking
+ private static void sendPacket(GTPacketInfiniteSpraycan.Action action) {
+ GTValues.NW.sendToServer(new GTPacketInfiniteSpraycan(action));
+ }
+
+ private static void sendPacket(@SuppressWarnings("SameParameterValue") GTPacketInfiniteSpraycan.Action action,
+ int newColor) {
+ GTValues.NW.sendToServer(new GTPacketInfiniteSpraycan(action, newColor));
+ }
+ // endregion
+
+ // region Server Actions
+ public void incrementColor(final ItemStack itemStack, final boolean wasSneaking) {
+ if (isLocked(itemStack)) {
+ return;
+ }
+
+ final NBTTagCompound tag = itemStack.hasTagCompound() ? itemStack.getTagCompound() : new NBTTagCompound();
byte color = 0;
if (tag.hasKey(COLOR_NBT_TAG)) {
color = tag.getByte(COLOR_NBT_TAG);
}
- color = clampColor((byte) (color + (wasSneaking ? -1 : 1)));
+ byte newColor = (byte) (color + (wasSneaking ? -1 : 1));
+ if (newColor > REMOVE_COLOR) {
+ newColor = 0;
+ } else if (newColor < 0) {
+ newColor = REMOVE_COLOR;
+ }
+ color = newColor;
+
+ setColor(itemStack, color);
+ }
+
+ public void setColor(final ItemStack itemStack, final byte color) {
+ if (isLocked(itemStack)) {
+ return;
+ }
+
+ final NBTTagCompound tag = itemStack.hasTagCompound() ? itemStack.getTagCompound() : new NBTTagCompound();
tag.setByte(COLOR_NBT_TAG, color);
mCurrentColor = color;
- aStack.setTagCompound(tag);
+ itemStack.setTagCompound(tag);
+
+ setItemStackName(itemStack);
+ }
+
+ public boolean toggleLock(final ItemStack itemStack) {
+ final NBTTagCompound tag = itemStack.hasTagCompound() ? itemStack.getTagCompound() : new NBTTagCompound();
+ final boolean newLockStatus = !tag.getBoolean(LOCK_NBT_TAG);
+
+ tag.setBoolean(LOCK_NBT_TAG, newLockStatus);
+ itemStack.setTagCompound(tag);
+ setItemStackName(itemStack);
+
+ return newLockStatus;
+ }
+
+ private void setItemStackName(final ItemStack itemStack) {
+ final boolean isLocked = isLocked(itemStack);
+ final char lBracket = isLocked ? '[' : '(';
+ final char rBracket = isLocked ? ']' : ')';
if (mCurrentColor == REMOVE_COLOR) {
- aStack.setStackDisplayName("Infinite Spray Can (Solvent)");
+ itemStack.setStackDisplayName(String.format("Infinite Spray Can %cSolvent%c", lBracket, rBracket));
} else {
- aStack.setStackDisplayName("Infinite Spray Can (" + Dyes.get(mCurrentColor).mName + ")");
+ itemStack.setStackDisplayName(
+ String.format("Infinite Spray Can %c" + Dyes.get(mCurrentColor).mName + "%c", lBracket, rBracket));
}
}
+ // endregion
- @Override
- public List<String> getAdditionalToolTips(final MetaBaseItem aItem, final List<String> aList,
- final ItemStack aStack) {
- if (mCurrentColor == REMOVE_COLOR) {
- aList.add(
- GTLanguageManager.addStringLocalization(
- "gt.behavior.paintspray.infinite.remover.tooltip",
- "Current color: Solvent (clears color)"));
- } else {
- final Dyes currentDye = Dyes.get(mCurrentColor);
- final String diamondSymbol = " " + currentDye.formatting + "♦" + EnumChatFormatting.RESET + " ";
- aList.add(
- GTLanguageManager.addStringLocalization(
- "gt.behaviour.paintspray.infinite." + mCurrentColor + ".tooltip",
- "Current color:" + diamondSymbol + currentDye.mName + diamondSymbol));
- }
- aList.add(tooltipInfinite);
- aList.add(tooltipSwitchHint);
- aList.add(mTooltipChain);
- aList.add(AuthorQuerns);
+ public static Dyes getDye(ItemStack itemStack) {
+ if (itemStack.hasTagCompound()) {
+ final byte color = itemStack.getTagCompound()
+ .getByte(COLOR_NBT_TAG);
+ if (color != REMOVE_COLOR) {
+ return Dyes.getDyeFromIndex(color);
+ }
+ }
- return aList;
+ return Dyes.MACHINE_METAL;
+ }
+
+ public boolean isLocked(final ItemStack itemStack) {
+ return itemStack.hasTagCompound() && itemStack.getTagCompound()
+ .getBoolean(LOCK_NBT_TAG);
+ }
+
+ private static class DyeSelectGUI extends SelectItemUIFactory {
+
+ public DyeSelectGUI(final String header, final ItemStack headerItem, final Consumer<ItemStack> selectedCallback,
+ final List<ItemStack> stacks, final int selected, final boolean noDeselect) {
+ super(header, headerItem, selectedCallback, stacks, selected, noDeselect);
+ }
+
+ @Override
+ public void setSelected(final int selected, Widget widget) {
+ super.setSelected(selected, widget);
+ widget.getWindow()
+ .closeWindow();
+ }
+
+ @Override
+ protected List<String> getItemTooltips(final int index) {
+ return ImmutableList.of(
+ index == REMOVE_COLOR ? StatCollector.translateToLocal("gt.behaviour.paintspray.infinite.gui.solvent")
+ : Dyes.getDyeFromIndex((short) index).mName);
+ }
}
}
diff --git a/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorRemover.java b/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorRemover.java
index 1cf51f32fa..0a6d2095e1 100644
--- a/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorRemover.java
+++ b/src/main/java/gregtech/common/items/behaviors/BehaviourSprayColorRemover.java
@@ -1,17 +1,11 @@
package gregtech.common.items.behaviors;
-import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
-import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
-import appeng.api.implementations.tiles.IColorableTile;
-import appeng.api.util.AEColor;
-import appeng.block.networking.BlockCableBus;
-import gregtech.api.interfaces.tileentity.IColoredTileEntity;
+import gregtech.api.util.ColoredBlockContainer;
import gregtech.api.util.GTLanguageManager;
public class BehaviourSprayColorRemover extends BehaviourSprayColor {
@@ -24,29 +18,7 @@ public class BehaviourSprayColorRemover extends BehaviourSprayColor {
@Override
protected boolean colorize(World aWorld, int aX, int aY, int aZ, ForgeDirection side, EntityPlayer player) {
- return removeColor(aWorld, aX, aY, aZ, side, player);
- }
-
- public static boolean removeColor(World aWorld, int aX, int aY, int aZ, ForgeDirection side, EntityPlayer player) {
- final Block aBlock = aWorld.getBlock(aX, aY, aZ);
- if (aBlock != Blocks.air) {
- if (aBlock instanceof IColorableTile) {
- return ((IColorableTile) aBlock).recolourBlock(side, AEColor.Transparent, player);
- }
-
- if (aBlock instanceof BlockCableBus) {
- return ((BlockCableBus) aBlock)
- .recolourBlock(aWorld, aX, aY, aZ, side, AEColor.Transparent.ordinal(), player);
- }
-
- TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
- if (tTileEntity instanceof IColoredTileEntity gte) {
- if (gte.getColorization() >= 0) {
- gte.setColorization((byte) -1);
- return true;
- }
- }
- }
- return false;
+ return ColoredBlockContainer.getInstance(aWorld, aX, aY, aZ, side, player)
+ .removeColor();
}
}
diff --git a/src/main/java/gregtech/common/render/items/DataStickRenderer.java b/src/main/java/gregtech/common/render/items/DataStickRenderer.java
index 3411c24c83..02735e6aef 100644
--- a/src/main/java/gregtech/common/render/items/DataStickRenderer.java
+++ b/src/main/java/gregtech/common/render/items/DataStickRenderer.java
@@ -9,18 +9,25 @@ import net.minecraftforge.client.IItemRenderer;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
+import gregtech.api.enums.ItemList;
import gregtech.api.util.AssemblyLineUtils;
// borrow form ae2
-
public class DataStickRenderer implements IItemRenderer {
private final RenderItem ri = new RenderItem();
+ public DataStickRenderer() {
+ MetaGeneratedItemRenderer.registerSpecialRenderer(ItemList.Tool_DataStick, this);
+ }
+
@Override
public boolean handleRenderType(ItemStack item, ItemRenderType type) {
final boolean isShiftHeld = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
- return type == ItemRenderType.INVENTORY && isShiftHeld;
+ final boolean shouldSwitch = item.hasTagCompound() && item.getTagCompound()
+ .hasKey("output");
+
+ return type == ItemRenderType.INVENTORY && isShiftHeld && shouldSwitch;
}
@Override
diff --git a/src/main/java/gregtech/common/render/items/InfiniteSprayCanRenderer.java b/src/main/java/gregtech/common/render/items/InfiniteSprayCanRenderer.java
new file mode 100644
index 0000000000..4050eadd22
--- /dev/null
+++ b/src/main/java/gregtech/common/render/items/InfiniteSprayCanRenderer.java
@@ -0,0 +1,83 @@
+package gregtech.common.render.items;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
+import net.minecraftforge.client.IItemRenderer;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.ItemList;
+import gregtech.api.items.MetaGeneratedItem;
+import gregtech.common.items.behaviors.BehaviourSprayColorInfinite;
+import gregtech.common.render.GTRenderUtil;
+
+public class InfiniteSprayCanRenderer implements IItemRenderer {
+
+ public InfiniteSprayCanRenderer() {
+ MetaGeneratedItemRenderer.registerSpecialRenderer(ItemList.Spray_Color_Infinite, this);
+ }
+
+ @Override
+ public boolean handleRenderType(final ItemStack item, final ItemRenderType type) {
+ return type == ItemRenderType.EQUIPPED || type == ItemRenderType.EQUIPPED_FIRST_PERSON
+ || type == ItemRenderType.INVENTORY
+ || type == ItemRenderType.ENTITY;
+
+ }
+
+ @Override
+ public boolean shouldUseRenderHelper(final ItemRenderType type, final ItemStack item,
+ final ItemRendererHelper helper) {
+ return type == ItemRenderType.ENTITY && helper == ItemRendererHelper.ENTITY_BOBBING
+ || (helper == ItemRendererHelper.ENTITY_ROTATION && Minecraft.getMinecraft().gameSettings.fancyGraphics);
+
+ }
+
+ @Override
+ public void renderItem(final ItemRenderType type, final ItemStack item, final Object... data) {
+ final Dyes dye = BehaviourSprayColorInfinite.getDye(item);
+ final short[] modulation = dye.getRGBA();
+
+ if (!(item.getItem() instanceof final MetaGeneratedItem mgItem)) {
+ return;
+ }
+
+ final IIcon[] iconList = mgItem.mIconList[item.getItemDamage() - mgItem.mOffset];
+ if (iconList == null || iconList.length < 4) {
+ return;
+ }
+
+ final IIcon baseLayer = iconList[1];
+ final IIcon lockLayer = iconList[2];
+ final IIcon paintRegion = iconList[3];
+
+ if (baseLayer == null || paintRegion == null || lockLayer == null) {
+ return;
+ }
+
+ boolean locked = false;
+
+ if (item.hasTagCompound()) {
+ locked = item.getTagCompound()
+ .getBoolean(BehaviourSprayColorInfinite.LOCK_NBT_TAG);
+ }
+
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GL11.glEnable(GL11.GL_ALPHA_TEST);
+
+ GTRenderUtil.renderItem(type, baseLayer);
+
+ GL11.glColor4f(modulation[0] / 255.0F, modulation[1] / 255.0F, modulation[2] / 255.0F, 1);
+ GTRenderUtil.renderItem(type, paintRegion);
+ GL11.glColor4f(1, 1, 1, 1);
+
+ if (locked) {
+ GTRenderUtil.renderItem(type, lockLayer);
+ }
+
+ GL11.glDisable(GL11.GL_BLEND);
+ }
+}
diff --git a/src/main/java/gregtech/common/render/items/MetaGeneratedItemRenderer.java b/src/main/java/gregtech/common/render/items/MetaGeneratedItemRenderer.java
index 14d9b65e7f..f0a614e3e6 100644
--- a/src/main/java/gregtech/common/render/items/MetaGeneratedItemRenderer.java
+++ b/src/main/java/gregtech/common/render/items/MetaGeneratedItemRenderer.java
@@ -1,12 +1,16 @@
package gregtech.common.render.items;
+import java.util.HashMap;
+import java.util.Map;
+
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.client.IItemRenderer;
import net.minecraftforge.client.MinecraftForgeClient;
+import com.google.common.base.Objects;
+
import gregtech.api.enums.ItemList;
-import gregtech.api.enums.Materials;
import gregtech.api.interfaces.IGT_ItemWithMaterialRenderer;
import gregtech.api.objects.ItemData;
import gregtech.api.util.GTOreDictUnificator;
@@ -18,7 +22,7 @@ public class MetaGeneratedItemRenderer implements IItemRenderer {
private final IItemRenderer mItemRenderer = new GeneratedItemRenderer();
private final IItemRenderer mMaterialRenderer = new GeneratedMaterialRenderer();
- private final IItemRenderer mDataStickRenderer = new DataStickRenderer();
+ private static final Map<RendererKey, IItemRenderer> specialRenderers = new HashMap<>();
public MetaGeneratedItemRenderer() {}
@@ -26,6 +30,15 @@ public class MetaGeneratedItemRenderer implements IItemRenderer {
MinecraftForgeClient.registerItemRenderer(item, this);
}
+ public static void registerSpecialRenderer(ItemList item, IItemRenderer renderer) {
+ specialRenderers.put(
+ new RendererKey(
+ Item.getIdFromItem(item.getItem()),
+ (short) item.getInternalStack_unsafe()
+ .getItemDamage()),
+ renderer);
+ }
+
@Override
public boolean handleRenderType(ItemStack aStack, ItemRenderType aType) {
if ((GTUtility.isStackInvalid(aStack)) || (aStack.getItemDamage() < 0)
@@ -53,7 +66,13 @@ public class MetaGeneratedItemRenderer implements IItemRenderer {
}
private IItemRenderer getRendererForItemStack(ItemStack aStack) {
- short aMetaData = (short) aStack.getItemDamage();
+ final short aMetaData = (short) aStack.getItemDamage();
+ final RendererKey key = new RendererKey(Item.getIdFromItem(aStack.getItem()), aMetaData);
+
+ if (specialRenderers.containsKey(key)) {
+ return specialRenderers.get(key);
+ }
+
IGT_ItemWithMaterialRenderer aItem = (IGT_ItemWithMaterialRenderer) aStack.getItem();
if (aItem != null && aItem.allowMaterialRenderer(aMetaData)) {
@@ -63,9 +82,8 @@ public class MetaGeneratedItemRenderer implements IItemRenderer {
if (aMaterialRenderer == null) {
ItemData itemData = GTOreDictUnificator.getAssociation(aStack);
if (itemData != null) {
- Materials material = itemData.mMaterial.mMaterial;
- if (material.renderer != null) {
- aMaterialRenderer = material.renderer;
+ if (itemData.mMaterial != null && itemData.mMaterial.mMaterial.renderer != null) {
+ aMaterialRenderer = itemData.mMaterial.mMaterial.renderer;
}
}
}
@@ -73,13 +91,31 @@ public class MetaGeneratedItemRenderer implements IItemRenderer {
return aMaterialRenderer != null ? aMaterialRenderer : mMaterialRenderer;
}
- // handle data stick
- if (aStack.getItem() == ItemList.Tool_DataStick.getItem() && aStack.hasTagCompound()
- && aStack.getTagCompound()
- .hasKey("output")) {
- return mDataStickRenderer;
+ return mItemRenderer;
+ }
+
+ @SuppressWarnings("ClassCanBeRecord")
+ private static class RendererKey {
+
+ private final int id;
+ private final short metadata;
+
+ private RendererKey(final int id, final short metadata) {
+ this.id = id;
+ this.metadata = metadata;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final RendererKey that = (RendererKey) o;
+ return id == that.id && metadata == that.metadata;
}
- return mItemRenderer;
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, metadata);
+ }
}
}
diff --git a/src/main/resources/assets/gregtech/lang/en_US.lang b/src/main/resources/assets/gregtech/lang/en_US.lang
index c0d9a98e88..049bb66bc4 100644
--- a/src/main/resources/assets/gregtech/lang/en_US.lang
+++ b/src/main/resources/assets/gregtech/lang/en_US.lang
@@ -621,6 +621,17 @@ GT5U.item.cable.loss=Loss/Meter/Ampere
GT5U.item.cable.eu_volt=EU-Volt
GT5U.item.tank.locked_to=Content locked to %s
+gt.behaviour.paintspray.infinite.gui.header=Select a Color
+gt.behaviour.paintspray.infinite.gui.lock_error=§eSpray can is §clocked§e! §bSneak middle-click to unlock.
+gt.behaviour.paintspray.infinite.gui.solvent=Solvent
+
+gt.behaviour.paintspray.infinite.tooltip.infinite=Infinite uses
+gt.behaviour.paintspray.infinite.tooltip.more_info=Hold SHIFT for more information
+gt.behaviour.paintspray.infinite.tooltip.switch=Left Click: Change color (sneak to reverse direction)
+gt.behaviour.paintspray.infinite.tooltip.pick=Middle Click block: Copy color to spray can
+gt.behaviour.paintspray.infinite.tooltip.lock=Sneak Middle Click: Lock or unlock spray can
+gt.behaviour.paintspray.infinite.tooltip.gui=Middle Click: Open color choice GUI
+
GT5U.hatch.disableFilter.true=Input Filter §cOff§r
GT5U.hatch.disableFilter.false=Input Filter §aOn§r
GT5U.hatch.disableMultiStack.true=Multi Stack Input §cOff§r
diff --git a/src/main/resources/assets/gregtech/sounds.json b/src/main/resources/assets/gregtech/sounds.json
index ae25d2bb23..612ce93fc4 100644
--- a/src/main/resources/assets/gregtech/sounds.json
+++ b/src/main/resources/assets/gregtech/sounds.json
@@ -142,11 +142,45 @@
}
]
},
- "items.spraycan": {
+ "items.spraycan_shake": {
"category": "player",
"sounds": [
{
- "name": "spraycan",
+ "name": "spraycan_shake",
+ "stream": false,
+ "licensing": {
+ "sound_url": "https://freesound.org/people/J-La/sounds/38025/",
+ "sound_name": "spraycan.wav",
+ "author_url": "https://freesound.org/people/J-La/",
+ "author_name": "J-La",
+ "license_url": "https://creativecommons.org/licenses/by/3.0/",
+ "license_name": "Attribution 3.0"
+ }
+ }
+ ]
+ },
+ "items.spraycan_lock": {
+ "category": "player",
+ "sounds": [
+ {
+ "name": "spraycan_lock",
+ "stream": false,
+ "licensing": {
+ "sound_url": "https://freesound.org/people/J-La/sounds/38025/",
+ "sound_name": "spraycan.wav",
+ "author_url": "https://freesound.org/people/J-La/",
+ "author_name": "J-La",
+ "license_url": "https://creativecommons.org/licenses/by/3.0/",
+ "license_name": "Attribution 3.0"
+ }
+ }
+ ]
+ },
+ "items.spraycan_unlock": {
+ "category": "player",
+ "sounds": [
+ {
+ "name": "spraycan_unlock",
"stream": false,
"licensing": {
"sound_url": "https://freesound.org/people/J-La/sounds/38025/",
@@ -159,4 +193,4 @@
}
]
}
-} \ No newline at end of file
+}
diff --git a/src/main/resources/assets/gregtech/sounds/spraycan_lock.ogg b/src/main/resources/assets/gregtech/sounds/spraycan_lock.ogg
new file mode 100644
index 0000000000..d81e2991dc
--- /dev/null
+++ b/src/main/resources/assets/gregtech/sounds/spraycan_lock.ogg
Binary files differ
diff --git a/src/main/resources/assets/gregtech/sounds/spraycan.ogg b/src/main/resources/assets/gregtech/sounds/spraycan_shake.ogg
index 1d858c6268..1d858c6268 100644
--- a/src/main/resources/assets/gregtech/sounds/spraycan.ogg
+++ b/src/main/resources/assets/gregtech/sounds/spraycan_shake.ogg
Binary files differ
diff --git a/src/main/resources/assets/gregtech/sounds/spraycan_unlock.ogg b/src/main/resources/assets/gregtech/sounds/spraycan_unlock.ogg
new file mode 100644
index 0000000000..555051c57e
--- /dev/null
+++ b/src/main/resources/assets/gregtech/sounds/spraycan_unlock.ogg
Binary files differ
diff --git a/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/1.png b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/1.png
new file mode 100644
index 0000000000..31101e7fa3
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/1.png
Binary files differ
diff --git a/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/2.png b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/2.png
new file mode 100644
index 0000000000..3cf38a228f
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/2.png
Binary files differ
diff --git a/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/3.png b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/3.png
new file mode 100644
index 0000000000..ab642f8605
--- /dev/null
+++ b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/3.png
Binary files differ