review fixes

This commit is contained in:
danyadev committed 2026-10-11 12:52:19 +03:00
1 parent c1e8606629
commit 6eed99f030
10 files changed
+183 -37

No files matched your search

@@ -31,6 +31,7 @@ import team.chisel.ctmlib.ISubmapManager;
import team.chisel.ctmlib.RenderBlocksCTM;
import team.chisel.ctmlib.RenderBlocksColumn;
import team.chisel.ctmlib.TextureSubmap;
import team.chisel.ctmlib.TextureSubmapCTM;
/**
* Handles all default {@link ISubmapManager} behavior
@@ -197,8 +198,8 @@ public enum TextureType {
IIcon baseIcon = register.registerIcon(modName + ":" + texturePath);
return Triple.of(
baseIcon,
new TextureSubmap(register.registerIcon(modName + ":" + texturePath + "-ctm"), 4, 4),
new TextureSubmap(baseIcon, 2, 2)
new TextureSubmapCTM(register.registerIcon(modName + ":" + texturePath + "-ctm"), 4),
new TextureSubmapCTM(baseIcon, 2)
);
}
@@ -19,8 +19,8 @@ import team.chisel.ctmlib.TextureSubmapResource;
/**
* Provides generated resources for independently stitched CTM submap sprites.
* <p>
* For example, a request for chisel:textures/blocks/__chisel_submap/4x4/2_1/foo.png is resolved from
* chisel:textures/blocks/foo.png and cropped to the requested cell. This lets Minecraft and other mods treat each
* For example, a request for chisel:textures/blocks/__chisel_submap/2x2/1_0/foo.png is resolved from
* chisel:textures/blocks/foo.png and cropped to its top-right tile. This lets Minecraft and other mods treat each
* submap sprite like an ordinary texture resource.
*/
@Mixin(FallbackResourceManager.class)
@@ -54,6 +54,7 @@ public abstract class MixinFallbackResourceManager {
List<IResource> resources = new ArrayList<>(sources.size());
for (IResource source : sources) {
// Different resource packs may provide different images for the same location, so we can't cache them
resources.add(new TextureSubmapResource(source, submap, false));
}
@@ -16,6 +16,7 @@ import cpw.mods.fml.relauncher.SideOnly;
import team.chisel.ctmlib.Drawing;
import team.chisel.ctmlib.RenderBlocksCTM;
import team.chisel.ctmlib.TextureSubmap;
import team.chisel.ctmlib.TextureSubmapCTM;
import team.chisel.init.ChiselBlocks;
public class SubmapManagerAntiblock extends SubmapManagerBase {
@@ -93,8 +94,8 @@ public class SubmapManagerAntiblock extends SubmapManagerBase {
@Override
@SideOnly(Side.CLIENT)
public void registerIcons(String modName, Block block, IIconRegister register) {
submap = new TextureSubmap(register.registerIcon(modName + ":antiblock/" + color + "-antiBlock-ctm"), 4, 4);
submapSmall = new TextureSubmap(register.registerIcon(modName + ":antiblock/" + color + "-antiBlock"), 2, 2);
submap = new TextureSubmapCTM(register.registerIcon(modName + ":antiblock/" + color + "-antiBlock-ctm"), 4);
submapSmall = new TextureSubmapCTM(register.registerIcon(modName + ":antiblock/" + color + "-antiBlock"), 2);
}
@Override
@@ -11,6 +11,7 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import team.chisel.ctmlib.RenderBlocksCTM;
import team.chisel.ctmlib.TextureSubmap;
import team.chisel.ctmlib.TextureSubmapCTM;
public class SubmapManagerCarpetFloor extends SubmapManagerBase {
@@ -39,8 +40,8 @@ public class SubmapManagerCarpetFloor extends SubmapManagerBase {
@SideOnly(Side.CLIENT)
public void registerIcons(String modName, Block block, IIconRegister register) {
String path = modName + ":carpet/" + color;
submap = new TextureSubmap(register.registerIcon(path + "-ctm"), 4, 4);
submapSmall = new TextureSubmap(register.registerIcon(path), 2, 2);
submap = new TextureSubmapCTM(register.registerIcon(path + "-ctm"), 4);
submapSmall = new TextureSubmapCTM(register.registerIcon(path), 2);
}
@Override
@@ -13,6 +13,7 @@ import cpw.mods.fml.relauncher.SideOnly;
import team.chisel.ctmlib.ISubmapManager;
import team.chisel.ctmlib.RenderBlocksCTM;
import team.chisel.ctmlib.TextureSubmap;
import team.chisel.ctmlib.TextureSubmapCTM;
public class SubmapManagerSlab implements ISubmapManager {
@@ -42,8 +43,8 @@ public class SubmapManagerSlab implements ISubmapManager {
@SideOnly(Side.CLIENT)
public void registerIcons(String modName, Block block, IIconRegister register) {
String path = modName + ":" + texture;
submap = new TextureSubmap(register.registerIcon(path + "-ctm"), 4, 4);
submapSmall = new TextureSubmap(register.registerIcon(path), 2, 2);
submap = new TextureSubmapCTM(register.registerIcon(path + "-ctm"), 4);
submapSmall = new TextureSubmapCTM(register.registerIcon(path), 2);
sideTexture = register.registerIcon(path + "-side");
}
@@ -11,6 +11,7 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import team.chisel.ctmlib.RenderBlocksCTM;
import team.chisel.ctmlib.TextureSubmap;
import team.chisel.ctmlib.TextureSubmapCTM;
public class SubmapManagerSpecialMaterial extends SubmapManagerBase {
@@ -71,8 +72,8 @@ public class SubmapManagerSpecialMaterial extends SubmapManagerBase {
public void registerIcons(String modName, Block block, IIconRegister register) {
String materialName = materialType.name()
.toLowerCase();
submap = new TextureSubmap(register.registerIcon(modName + ":" + materialName + "/" + color + "-ctm"), 4, 4);
submapSmall = new TextureSubmap(register.registerIcon(modName + ":" + materialName + "/" + color), 2, 2);
submap = new TextureSubmapCTM(register.registerIcon(modName + ":" + materialName + "/" + color + "-ctm"), 4);
submapSmall = new TextureSubmapCTM(register.registerIcon(modName + ":" + materialName + "/" + color), 2);
}
@Override
@@ -48,8 +48,8 @@ public class SubmapManagerCTM implements ISubmapManager {
@Override
@SideOnly(Side.CLIENT)
public void registerIcons(String modName, Block block, IIconRegister register) {
submap = new TextureSubmap(register.registerIcon(modName + ":" + textureName + "-ctm"), 4, 4);
submapSmall = new TextureSubmap(register.registerIcon(modName + ":" + textureName), 2, 2);
submap = new TextureSubmapCTM(register.registerIcon(modName + ":" + textureName + "-ctm"), 4);
submapSmall = new TextureSubmapCTM(register.registerIcon(modName + ":" + textureName), 2);
}
@Override
@@ -16,7 +16,7 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import lombok.experimental.Delegate;
/**
* Splits a texture sheet into independently stitched sub-icons used for CTM and other texture manipulation.
* Represents a grid of individually accessible texture regions.
*/
public class TextureSubmap implements IIcon, ISubmap {
@@ -29,17 +29,11 @@ public class TextureSubmap implements IIcon, ISubmap {
protected final IIcon[][] icons;
/**
* Construct a new square submap.
*
* @param baseIcon The IIcon to submap.
* @param width The width of the map, in icons.
* @param height The height of the map, in icons. Must equal {@code width}.
* @param height The height of the map, in icons.
*/
public TextureSubmap(IIcon baseIcon, int width, int height) {
if (width != height) {
throw new IllegalArgumentException("TextureSubmap must be square: " + width + "x" + height);
}
this.baseIcon = baseIcon;
this.width = width;
this.height = height;
@@ -47,9 +41,6 @@ public class TextureSubmap implements IIcon, ISubmap {
submaps.add(this);
}
/**
* The large "base" icon used for the submap.
*/
public IIcon getBaseIcon() {
return baseIcon;
}
@@ -114,20 +105,138 @@ public class TextureSubmap implements IIcon, ISubmap {
}
}
/**
* Register the real sprites backing this submap.
*/
public void registerSubIcons(TextureMap textureMap) {
registerSpriteGrid(textureMap, width, height);
}
/**
* Splits the texture into a grid of atlas sprites and assigns sub-icons to them.
* <p>
* The number of sub-icons is determined by the submap's width and height,
* while spriteColumns and spriteRows determine how many separate atlas sprites
* are used. Each sprite can contain one or more sub-icons.
* <p>
* For example, a 4x4 submap backed by a 2x2 sprite grid uses four atlas sprites,
* each containing a 2x2 group of sub-icons.
*/
protected final void registerSpriteGrid(TextureMap textureMap, int spriteColumns, int spriteRows) {
if (baseIcon == null || width <= 0 || height <= 0) {
return;
}
if (spriteColumns <= 0 || spriteRows <= 0 || width % spriteColumns != 0 || height % spriteRows != 0) {
throw new IllegalArgumentException(
"Logical submap " + width
+ "x"
+ height
+ " cannot be backed by sprite grid "
+ spriteColumns
+ "x"
+ spriteRows);
}
ResourceLocation sourceLocation = new ResourceLocation(baseIcon.getIconName());
IIcon[][] sprites = new IIcon[spriteColumns][spriteRows];
for (int spriteX = 0; spriteX < spriteColumns; spriteX++) {
for (int spriteY = 0; spriteY < spriteRows; spriteY++) {
sprites[spriteX][spriteY] = getBackingSprite(
textureMap,
sourceLocation,
spriteColumns,
spriteRows,
spriteX,
spriteY);
}
}
int cellsPerSpriteX = width / spriteColumns;
int cellsPerSpriteY = height / spriteRows;
boolean wholeSprite = cellsPerSpriteX == 1 && cellsPerSpriteY == 1;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
String name = TextureSubmapResource.getSubIconName(sourceLocation, width, height, x, y);
icons[x][y] = textureMap.registerIcon(name);
IIcon sprite = sprites[x / cellsPerSpriteX][y / cellsPerSpriteY];
icons[x][y] = wholeSprite ? sprite
: new TextureRegion(
sprite,
cellsPerSpriteX,
cellsPerSpriteY,
x % cellsPerSpriteX,
y % cellsPerSpriteY);
}
}
}
private IIcon getBackingSprite(TextureMap textureMap, ResourceLocation sourceLocation, int columns, int rows, int x,
int y) {
if (columns == 1 && rows == 1) {
return baseIcon;
}
String name = TextureSubmapResource.getSubIconName(sourceLocation, columns, rows, x, y);
return textureMap.registerIcon(name);
}
private static final class TextureRegion implements IIcon {
private final IIcon parent;
private final int columns;
private final int rows;
private final int x;
private final int y;
private TextureRegion(IIcon parent, int columns, int rows, int x, int y) {
this.parent = parent;
this.columns = columns;
this.rows = rows;
this.x = x;
this.y = y;
}
@Override
public float getMinU() {
return getInterpolatedU(0);
}
@Override
public float getMaxU() {
return getInterpolatedU(16);
}
@Override
public float getInterpolatedU(double u) {
return parent.getInterpolatedU((16.0 * x + u) / columns);
}
@Override
public float getMinV() {
return getInterpolatedV(0);
}
@Override
public float getMaxV() {
return getInterpolatedV(16);
}
@Override
public float getInterpolatedV(double v) {
return parent.getInterpolatedV((16.0 * y + v) / rows);
}
@Override
public String getIconName() {
return parent.getIconName();
}
@Override
public int getIconWidth() {
return parent.getIconWidth() / columns;
}
@Override
public int getIconHeight() {
return parent.getIconHeight() / rows;
}
}
}
@@ -0,0 +1,27 @@
package team.chisel.ctmlib;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.util.IIcon;
/**
* A CTM submap that keeps each tile in one atlas sprite while exposing its four quadrants as sub-icons.
*/
public final class TextureSubmapCTM extends TextureSubmap {
/**
* @param baseIcon The registered texture sheet.
* @param size The number of logical quadrants per axis: 4 for the CTM sheet, 2 for the normal texture.
*/
public TextureSubmapCTM(IIcon baseIcon, int size) {
super(baseIcon, size, size);
if (size <= 0 || (size & 1) != 0) {
throw new IllegalArgumentException("CTM submap size must be a positive even number: " + size);
}
}
@Override
public void registerSubIcons(TextureMap textureMap) {
registerSpriteGrid(textureMap, getWidth() / 2, getHeight() / 2);
}
}
@@ -6,9 +6,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nullable;
import javax.imageio.IIOImage;
@@ -35,7 +35,7 @@ public final class TextureSubmapResource implements IResource {
private record SubmapCacheKey(ResourceLocation source, int columns, int rows) {}
@Nullable
private static HashMap<SubmapCacheKey, byte[][]> imageCache;
private static volatile ConcurrentHashMap<SubmapCacheKey, byte[][]> imageCache;
private static final String PREFIX = "__chisel_submap/";
@@ -103,7 +103,7 @@ public final class TextureSubmapResource implements IResource {
}
public static void beginTextureStitch() {
imageCache = new HashMap<>();
imageCache = new ConcurrentHashMap<>();
}
public static void endTextureStitch() {
@@ -124,15 +124,19 @@ public final class TextureSubmapResource implements IResource {
}
private byte[] getCachedImageData(IResource resource, SubmapLocation submap) throws IOException {
if (!cacheable || imageCache == null) {
ConcurrentHashMap<SubmapCacheKey, byte[][]> cache = imageCache;
if (!cacheable || cache == null) {
return generateCell(resource, submap);
}
SubmapCacheKey key = new SubmapCacheKey(submap.source(), submap.columns(), submap.rows());
byte[][] cells = imageCache.get(key);
byte[][] cells = cache.get(key);
if (cells == null) {
cells = generateSubmap(resource, submap);
imageCache.put(key, cells);
byte[][] existing = cache.putIfAbsent(key, cells);
if (existing != null) {
cells = existing;
}
}
return cells[submap.cellX() * submap.rows() + submap.cellY()];
@@ -176,7 +180,7 @@ public final class TextureSubmapResource implements IResource {
ImageWriteParam param = writer.getDefaultWriteParam();
if (param.canWriteCompressed()) {
// disable compression so we don't spend time on compressing and decompressing to just get the image bytes
// Disable compression to avoid wasting time compressing images that will immediately be decoded again
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(1.0f);
}