Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/com/ruling_0/materiallib/api/IconPather.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ruling_0.materiallib.api;

/// Overrides the icon path a block or fluid [Shape] registers for one material, ahead of that material's
/// [TextureSet]-driven lookup.
/// [TextureSet]-driven lookup and behind any resource-pack override.
///
/// Set through [BlockShapeBuilder#iconPath] or [FluidShapeBuilder#iconPath]. Fluid textures live on the block
/// atlas.
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/com/ruling_0/materiallib/api/IconSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import cpw.mods.fml.relauncher.SideOnly;

/// A named per-material icon binding on one texture atlas, with no backing item or block: the icon resolution of a
/// shape (texture-set chain, fallbacks, unification alternatives, `_OVERLAY` convention) for art a mod composites
/// in its own renderers, e.g. tool parts drawn by the material read from a stack's NBT, or an extra face icon of a
/// block the mod already owns.
/// shape (resource-pack overrides, texture-set chain, fallbacks, unification alternatives, `_OVERLAY` convention) for
/// art a mod composites in its own renderers, e.g. tool parts drawn by the material read from a stack's NBT, or an
/// extra face icon of a block the mod already owns.
///
/// Created through [MaterialLibClient#newIconSet] before the first texture stitch. Icons bind for every registered
/// material -- an icon set has no served set, since no material generates one -- when the chosen atlas stitches, and
Expand Down Expand Up @@ -65,6 +65,11 @@ public IIcon getOverlayIcon(Material material) {
return icons.getOverlayOrNull(material.getIndex());
}

/// Whether `material`'s icon bound from the resource-pack override location; see [ShapeItem#hasOverrideIcon].
public boolean hasOverrideIcon(Material material) {
return icons.isOverride(material.getIndex());
}

void bind(IIconRegister register, Material[] materials) {
icons.bind(register, materials, name);
}
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/com/ruling_0/materiallib/api/ShapeBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,12 @@ public IIcon getMaterialOverlayIcon(Material material) {
return icons.getOverlayOrNull(material.getIndex());
}

/// Whether `material`'s icon bound from the resource-pack override location; see [ShapeItem#hasOverrideIcon].
@SideOnly(Side.CLIENT)
public boolean hasOverrideIcon(Material material) {
return icons.isOverride(material.getIndex());
}

@Override
@SideOnly(Side.CLIENT)
public int getRenderColor(int meta) {
Expand All @@ -285,9 +291,11 @@ public int colorMultiplier(IBlockAccess world, int x, int y, int z) {
/// The RGB tint of the material at the given metadata, or white when the metadata maps to no live material:
/// [StandardProperties#BLOCK_OVERLAY_TINT] for a [#hasBaseTexture] composite's overlay layer,
/// [StandardProperties#BLOCK_TINT] for a plain block, [StandardProperties#TINT] when the specific property is
/// unset. Block render colors carry no alpha, so the resolved ARGB value is masked to its low 24 bits.
/// unset. An icon bound from the resource-pack override location is white as well; see [#hasOverrideIcon].
/// Block render colors carry no alpha, so the resolved ARGB value is masked to its low 24 bits.
@SideOnly(Side.CLIENT)
int tintFor(int meta) {
if (icons.isOverride(meta)) return 0xFFFFFF;
Material material = MaterialRegistry.instance().getMaterialByIndex(meta);
if (material == null) return 0xFFFFFF;
Integer override = material.getProperty(
Expand Down
46 changes: 32 additions & 14 deletions src/main/java/com/ruling_0/materiallib/api/ShapeFluid.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

import net.minecraft.client.renderer.texture.IIconRegister;

Expand All @@ -24,14 +25,15 @@
/// A fluid shape is not a [BackedShape], as fluids are registered by name and not numeric ID. Materials declare it
/// through [MaterialBuilder#generateShape]; the registry registers one fluid per material at resolve, configures
/// newly registered fluids through this shape's [FluidConfigurer], and, on the client, binds each fluid's still and
/// flowing icons from this shape's [IconPather] when it names an existing file (see
/// [FluidShapeBuilder#iconPath]), and otherwise from the material's texture sets -- the same chain [ShapeIcons]
/// flowing icons from a resource-pack override, then from this shape's [IconPather] when it names an existing file
/// (see [FluidShapeBuilder#iconPath]), and otherwise from the material's texture sets -- the same chain [ShapeIcons]
/// walks for an item or block icon.
///
/// A bare fluid has no item form, so its material tooltip is carried by its container item (see
/// [ShapeFluidInContainer]). Each fluid takes its display name from the shape's format and its color from the
/// material's [StandardProperties#FLUID_TINT], or [StandardProperties#TINT] when unset, so tank and GUI renderers
/// show the right name and tint without a custom fluid block.
/// show the right name and tint without a custom fluid block. A fluid whose icon came from the resource-pack
/// override location is untinted; see [ShapeItem#hasOverrideIcon].
public class ShapeFluid implements ServedShape {

private static final List<String> NO_OREDICTS = List.of();
Expand All @@ -49,6 +51,7 @@ public class ShapeFluid implements ServedShape {

private final Int2ObjectMap<Fluid> fluidsByIndex = new Int2ObjectOpenHashMap<>();
private final Set<Material> warnedMissingIcon = new ReferenceOpenHashSet<>();
private final Set<Material> overrideIcons = new ReferenceOpenHashSet<>();

/// Creates a fluid shape. `displayNameFormat` is applied to the material name to build the fluid's display
/// name, e.g. `"Molten %s"`. Identifiers must be non-empty and free of ':' and whitespace.
Expand Down Expand Up @@ -198,17 +201,19 @@ void registerIcons(IIconRegister register) {
}
}

/// The icon path to register for `material`'s fluid: this shape's [IconPather] when set and it names an
/// existing file, otherwise the first name `material`'s texture-set chain resolves (see [ShapeIcons#resolve]),
/// or the [ShapeIcons#EMPTY_ICON] placeholder when neither does. Never null.
/// The icon path to register for `material`'s fluid, or the [ShapeIcons#EMPTY_ICON] placeholder when no source
/// carries one; see [ShapeIcons#resolvePath] for the order. Never null.
String resolveIconPath(Material material) {
if (iconPather != null) {
String path = iconPather.iconPath(this, material);
if (path != null && blockTextureExists(path)) return path;
}
ShapeIcons.ResolvedTexture resolved = ShapeIcons.resolve(material, List.of(name),
ShapeFluid::blockTextureExists);
if (resolved != null) return resolved.set().iconPath(resolved.shapeName());
return resolveIconPath(material, ShapeFluid::blockTextureExists);
}

/// As [#resolveIconPath(Material)], with `exists` deciding whether an icon path names a file on the block
/// atlas.
String resolveIconPath(Material material, Predicate<String> exists) {
String path = ShapeIcons.resolvePath(material, List.of(name), this::patherPath, exists);
if (path != null && path.startsWith(ShapeIcons.OVERRIDE_ROOT)) overrideIcons.add(material);
else overrideIcons.remove(material);
if (path != null) return path;
if (warnedMissingIcon.add(material)) {
MaterialLib.LOG.warn(
"Fluid shape {} of {} resolved no icon; it will render the transparent placeholder",
Expand All @@ -218,6 +223,16 @@ String resolveIconPath(Material material) {
return ShapeIcons.EMPTY_ICON;
}

/// Whether `material`'s fluid icon resolved from the resource-pack override location; see
/// [ShapeItem#hasOverrideIcon].
boolean hasOverrideIcon(Material material) {
return overrideIcons.contains(material);
}

private String patherPath(Material material) {
return iconPather != null ? iconPather.iconPath(this, material) : null;
}

private static boolean blockTextureExists(String path) {
return ResourceUtil.resourceExists(ResourceUtil.getCompleteBlockTextureResourceLocation(path));
}
Expand All @@ -241,7 +256,10 @@ public String getLocalizedName(FluidStack stack) {
}

@Override
public int getColor() { return tintOf(material) & 0xFFFFFF; }
public int getColor() {
if (hasOverrideIcon(material)) return 0xFFFFFF;
return tintOf(material) & 0xFFFFFF;
}
}

/// The ARGB fill tint for `material`'s fluid: [StandardProperties#FLUID_TINT] when set, or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,14 @@ public IIcon getIconFromDamage(int damage) {
return emptyIcon;
}

/// White for the untinted container base in pass 0, the fill tint (see the class doc) for every later pass.
/// White for the untinted container base in pass 0, the fill tint (see the class doc) for every later pass. An
/// override-bound fill icon is white as well; see [ShapeItem#hasOverrideIcon].
@Override
@SideOnly(Side.CLIENT)
public int getColorFromItemStack(ItemStack stack, int renderPass) {
if (renderPass == 0) return 0xFFFFFFFF;
Material material = ShapeText.materialFor(stack);
if (material == null) return 0xFFFFFFFF;
if (material == null || hasOverrideIcon(material)) return 0xFFFFFFFF;
Integer cellTint = material.getProperty(StandardProperties.CELL_TINT);
return cellTint != null ? cellTint : ShapeFluid.tintOf(material);
}
Expand Down
Loading