diff options
Diffstat (limited to 'src/main')
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 Binary files differnew file mode 100644 index 0000000000..d81e2991dc --- /dev/null +++ b/src/main/resources/assets/gregtech/sounds/spraycan_lock.ogg diff --git a/src/main/resources/assets/gregtech/sounds/spraycan.ogg b/src/main/resources/assets/gregtech/sounds/spraycan_shake.ogg Binary files differindex 1d858c6268..1d858c6268 100644 --- a/src/main/resources/assets/gregtech/sounds/spraycan.ogg +++ b/src/main/resources/assets/gregtech/sounds/spraycan_shake.ogg diff --git a/src/main/resources/assets/gregtech/sounds/spraycan_unlock.ogg b/src/main/resources/assets/gregtech/sounds/spraycan_unlock.ogg Binary files differnew file mode 100644 index 0000000000..555051c57e --- /dev/null +++ b/src/main/resources/assets/gregtech/sounds/spraycan_unlock.ogg 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 Binary files differnew file mode 100644 index 0000000000..31101e7fa3 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/1.png 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 Binary files differnew file mode 100644 index 0000000000..3cf38a228f --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/2.png 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 Binary files differnew file mode 100644 index 0000000000..ab642f8605 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/items/gt.metaitem.01/468/3.png |