Update models to use gt base texture
1
.gitignore
vendored
@@ -25,3 +25,4 @@ src/generated/resources/.cache/
|
||||
*.DS_Store
|
||||
|
||||
.factorypath
|
||||
run-data
|
||||
|
||||
1
models/lathe.bbmodel
Normal file
BIN
src/generated/resources/assets/ibg/textures/block/ev_lathe.png
Normal file
|
After Width: | Height: | Size: 929 B |
BIN
src/generated/resources/assets/ibg/textures/block/hv_lathe.png
Normal file
|
After Width: | Height: | Size: 932 B |
BIN
src/generated/resources/assets/ibg/textures/block/iv_lathe.png
Normal file
|
After Width: | Height: | Size: 889 B |
BIN
src/generated/resources/assets/ibg/textures/block/luv_lathe.png
Normal file
|
After Width: | Height: | Size: 896 B |
BIN
src/generated/resources/assets/ibg/textures/block/lv_lathe.png
Normal file
|
After Width: | Height: | Size: 804 B |
BIN
src/generated/resources/assets/ibg/textures/block/max_lathe.png
Normal file
|
After Width: | Height: | Size: 854 B |
BIN
src/generated/resources/assets/ibg/textures/block/mv_lathe.png
Normal file
|
After Width: | Height: | Size: 843 B |
BIN
src/generated/resources/assets/ibg/textures/block/opv_lathe.png
Normal file
|
After Width: | Height: | Size: 965 B |
BIN
src/generated/resources/assets/ibg/textures/block/uev_lathe.png
Normal file
|
After Width: | Height: | Size: 961 B |
BIN
src/generated/resources/assets/ibg/textures/block/uhv_lathe.png
Normal file
|
After Width: | Height: | Size: 883 B |
BIN
src/generated/resources/assets/ibg/textures/block/uiv_lathe.png
Normal file
|
After Width: | Height: | Size: 922 B |
BIN
src/generated/resources/assets/ibg/textures/block/uv_lathe.png
Normal file
|
After Width: | Height: | Size: 981 B |
BIN
src/generated/resources/assets/ibg/textures/block/uxv_lathe.png
Normal file
|
After Width: | Height: | Size: 970 B |
BIN
src/generated/resources/assets/ibg/textures/block/zpm_lathe.png
Normal file
|
After Width: | Height: | Size: 968 B |
@@ -4,6 +4,7 @@ import com.imbgt.ibg.block.MachineSets;
|
||||
import com.imbgt.ibg.block.ModBlocks;
|
||||
import com.imbgt.ibg.block.entity.ModBlockEntities;
|
||||
import com.imbgt.ibg.block.entity.client.AnimatedBlockRenderer;
|
||||
import com.imbgt.ibg.datagen.TierTextureBakeProvider;
|
||||
|
||||
import com.gregtechceu.gtceu.api.machine.MachineDefinition;
|
||||
import com.gregtechceu.gtceu.api.registry.GTRegistries;
|
||||
@@ -11,6 +12,7 @@ import com.gregtechceu.gtceu.api.registry.GTRegistries;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.data.event.GatherDataEvent;
|
||||
import net.minecraftforge.event.server.ServerStartingEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -61,4 +63,15 @@ public class IBG {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Mod.EventBusSubscriber(modid = IBG.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public final class DataGenHook {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void gather(GatherDataEvent e) {
|
||||
var out = e.getGenerator().getPackOutput();
|
||||
var ef = e.getExistingFileHelper();
|
||||
e.getGenerator().addProvider(e.includeClient(), new TierTextureBakeProvider(out, ef));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.List;
|
||||
@UtilityClass
|
||||
public final class MachineSets {
|
||||
|
||||
public static final String NS = "gtceu";
|
||||
public final String NS = "gtceu";
|
||||
|
||||
public record Definition(String suffix, FootprintSpec spec) {
|
||||
|
||||
@@ -21,7 +21,7 @@ public final class MachineSets {
|
||||
}
|
||||
}
|
||||
|
||||
public static final List<Definition> DEFINITIONS = List.of(
|
||||
public final List<Definition> DEFINITIONS = List.of(
|
||||
new Definition(
|
||||
"lathe",
|
||||
FootprintSpec.builder()
|
||||
@@ -31,17 +31,17 @@ public final class MachineSets {
|
||||
.build()));
|
||||
|
||||
/** Does this machine belong to any configured family? */
|
||||
public static boolean matches(ResourceLocation id) {
|
||||
public boolean matches(ResourceLocation id) {
|
||||
return DEFINITIONS.stream().anyMatch(f -> f.matches(id));
|
||||
}
|
||||
|
||||
/** The footprint spec for this machine, or null. */
|
||||
public static FootprintSpec getSpec(ResourceLocation id) {
|
||||
public FootprintSpec getSpec(ResourceLocation id) {
|
||||
return DEFINITIONS.stream().filter(f -> f.matches(id)).map(Definition::spec).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/** Asset key (filename stem) for this machine, or fallback to last segment. */
|
||||
public static String assetKeyFor(ResourceLocation id) {
|
||||
public String assetKeyFor(ResourceLocation id) {
|
||||
return DEFINITIONS.stream().filter(f -> f.matches(id)).map(Definition::suffix).findFirst()
|
||||
.orElseGet(() -> {
|
||||
var p = id.getPath();
|
||||
|
||||
@@ -28,8 +28,11 @@ public class AnimatedBlockModel<T extends GeoAnimatable> extends GeoModel<T> {
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureResource(T anim) {
|
||||
String key = keyFrom(anim);
|
||||
return new ResourceLocation(IBG.MOD_ID, "textures/block/" + key + ".png");
|
||||
if (anim instanceof MetaMachineBlockEntity mme) {
|
||||
var id = mme.getMetaMachine().getDefinition().getId();
|
||||
return new ResourceLocation(IBG.MOD_ID, "textures/block/" + id.getPath() + ".png");
|
||||
}
|
||||
return new ResourceLocation("ibg", "textures/block/fallback.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
232
src/main/java/com/imbgt/ibg/datagen/TierTextureBakeProvider.java
Normal file
@@ -0,0 +1,232 @@
|
||||
// src/main/java/com/imbgt/ibg/datagen/TierTextureBakeProvider.java
|
||||
package com.imbgt.ibg.datagen;
|
||||
|
||||
import com.imbgt.ibg.block.MachineSets;
|
||||
|
||||
import com.gregtechceu.gtceu.api.GTValues;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
|
||||
import com.google.common.hash.HashCode;
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.gson.*;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public final class TierTextureBakeProvider implements DataProvider {
|
||||
|
||||
private record TierTiles(BufferedImage side, BufferedImage top, BufferedImage bottom) {}
|
||||
|
||||
private final PackOutput out;
|
||||
private final ExistingFileHelper ef;
|
||||
|
||||
public TierTextureBakeProvider(PackOutput out, ExistingFileHelper ef) {
|
||||
this.out = out;
|
||||
this.ef = ef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "IBG tier texture baker";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<?> run(CachedOutput cache) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
for (var def : MachineSets.DEFINITIONS) {
|
||||
String key = def.suffix();
|
||||
for (int tierId = GTValues.LV; tierId <= GTValues.MAX; tierId++) {
|
||||
String tier = GTValues.VN[tierId].toLowerCase(Locale.ROOT);
|
||||
|
||||
JsonObject geo = readJson("ibg", "geo/" + key + ".geo.json");
|
||||
|
||||
JsonObject geometry0 = geo.getAsJsonArray("minecraft:geometry").get(0).getAsJsonObject();
|
||||
JsonObject description = geometry0.getAsJsonObject("description");
|
||||
int atlasW = description.get("texture_width").getAsInt();
|
||||
int atlasH = description.get("texture_height").getAsInt();
|
||||
|
||||
BufferedImage atlas = new BufferedImage(atlasW, atlasH, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = atlas.createGraphics();
|
||||
|
||||
TierTiles tiles = loadTierTiles("gtceu", tier)
|
||||
.orElseThrow(
|
||||
() -> new FileNotFoundException("Missing GTCEu casing tiles for tier " + tier));
|
||||
|
||||
paintCasingFromGeo(g, tiles, geo);
|
||||
|
||||
BufferedImage overlay = tryReadPng("ibg", "textures/block/" + key + ".png");
|
||||
if (overlay != null)
|
||||
g.drawImage(overlay, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(atlas, "PNG", baos);
|
||||
byte[] bytes = baos.toByteArray();
|
||||
HashCode hash = Hashing.sha256().hashBytes(bytes);
|
||||
|
||||
Path dst = out.getOutputFolder()
|
||||
.resolve("assets/ibg/textures/block/" + tier + "_" +
|
||||
key + ".png");
|
||||
|
||||
// No need to create directories manually; writeIfNeeded will.
|
||||
cache.writeIfNeeded(dst, bytes, hash);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}, Util.backgroundExecutor());
|
||||
}
|
||||
|
||||
// ---------- resource helpers ----------
|
||||
private JsonObject readJson(String ns, String path) throws IOException {
|
||||
try (InputStream is = open(ns, path).orElseThrow(() -> new FileNotFoundException(ns + ":" + path))) {
|
||||
return JsonParser.parseReader(new InputStreamReader(is)).getAsJsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage tryReadPng(String ns, String path) throws IOException {
|
||||
var opt = open(ns, path);
|
||||
if (opt.isEmpty())
|
||||
return null;
|
||||
try (InputStream is = opt.get()) {
|
||||
return ImageIO.read(is);
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<TierTiles> loadTierTiles(String ns, String tier) throws IOException {
|
||||
String base = "textures/block/casings/voltage/" + tier + "/";
|
||||
BufferedImage side = tryReadPng(ns, base + "side.png");
|
||||
BufferedImage top = tryReadPng(ns, base + "top.png");
|
||||
BufferedImage bot = tryReadPng(ns, base + "bottom.png");
|
||||
if (side != null && top != null && bot != null)
|
||||
return Optional.of(new TierTiles(side, top, bot));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<InputStream> open(String ns, String path) throws IOException {
|
||||
try {
|
||||
var rl = new ResourceLocation(ns, path);
|
||||
var res = ef.getResource(rl, PackType.CLIENT_RESOURCES);
|
||||
if (res != null)
|
||||
return Optional.of(res.open());
|
||||
} catch (FileNotFoundException e) {
|
||||
String cpPath = "assets/" + ns + "/" + path;
|
||||
var cl = Thread.currentThread().getContextClassLoader();
|
||||
InputStream is = cl.getResourceAsStream(cpPath);
|
||||
return Optional.ofNullable(is);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// ---------- painting ----------
|
||||
private static void paintTile(Graphics2D g, BufferedImage tile, int x, int y, int w, int h) {
|
||||
int tw0 = tile.getWidth();
|
||||
int th0 = tile.getHeight();
|
||||
for (int yy = 0; yy < h; yy += th0) {
|
||||
for (int xx = 0; xx < w; xx += tw0) {
|
||||
int tw = Math.min(tw0, w - xx);
|
||||
int th = Math.min(th0, h - yy);
|
||||
g.drawImage(tile, x + xx, y + yy, x + xx + tw, y + yy + th, 0, 0, tw, th, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void paintFace(Graphics2D g, BufferedImage tile, int atlasW, int atlasH,
|
||||
int u, int v, int us, int vs) {
|
||||
int x0 = us >= 0 ? u : u + us;
|
||||
int y0 = vs >= 0 ? v : v + vs;
|
||||
int w = Math.abs(us);
|
||||
int h = Math.abs(vs);
|
||||
// clamp to atlas
|
||||
if (x0 < 0) {
|
||||
w += x0;
|
||||
x0 = 0;
|
||||
}
|
||||
if (y0 < 0) {
|
||||
h += y0;
|
||||
y0 = 0;
|
||||
}
|
||||
if (x0 >= atlasW || y0 >= atlasH || w <= 0 || h <= 0)
|
||||
return;
|
||||
if (x0 + w > atlasW)
|
||||
w = atlasW - x0;
|
||||
if (y0 + h > atlasH)
|
||||
h = atlasH - y0;
|
||||
|
||||
paintTile(g, tile, x0, y0, w, h);
|
||||
}
|
||||
|
||||
private void paintCasingFromGeo(Graphics2D g, TierTiles tiles, JsonObject geo) {
|
||||
var geos = geo.getAsJsonArray("minecraft:geometry");
|
||||
if (geos == null)
|
||||
return;
|
||||
|
||||
// atlas size from description
|
||||
JsonObject description = geos.get(0).getAsJsonObject().getAsJsonObject("description");
|
||||
int atlasW = description.get("texture_width").getAsInt();
|
||||
int atlasH = description.get("texture_height").getAsInt();
|
||||
|
||||
for (var ge : geos) {
|
||||
var bones = ge.getAsJsonObject().getAsJsonArray("bones");
|
||||
if (bones == null)
|
||||
continue;
|
||||
|
||||
for (var bEl : bones) {
|
||||
var cubes = bEl.getAsJsonObject().getAsJsonArray("cubes");
|
||||
if (cubes == null || !bEl.getAsJsonObject().get("name").getAsString().equals("bone"))
|
||||
continue;
|
||||
|
||||
for (var cEl : cubes) {
|
||||
var cube = cEl.getAsJsonObject();
|
||||
|
||||
if (cube.has("uv") && cube.get("uv").isJsonObject()) {
|
||||
var uv = cube.getAsJsonObject("uv");
|
||||
for (var e : uv.entrySet()) {
|
||||
String face = e.getKey(); // north/east/south/west/up/down
|
||||
var f = e.getValue().getAsJsonObject();
|
||||
int u = f.getAsJsonArray("uv").get(0).getAsInt();
|
||||
int v = f.getAsJsonArray("uv").get(1).getAsInt();
|
||||
int us = f.getAsJsonArray("uv_size").get(0).getAsInt();
|
||||
int vs = f.getAsJsonArray("uv_size").get(1).getAsInt();
|
||||
|
||||
BufferedImage tile = switch (face) {
|
||||
case "up" -> tiles.top();
|
||||
case "down" -> tiles.bottom();
|
||||
default -> tiles.side();
|
||||
};
|
||||
paintFace(g, tile, atlasW, atlasH, u, v, us, vs);
|
||||
}
|
||||
} else if (cube.has("uv") && cube.get("uv").isJsonArray() && cube.has("size")) {
|
||||
// Better fallback: use cube sizes per face like Bedrock layout
|
||||
var size = cube.getAsJsonArray("size");
|
||||
int sx = size.get(0).getAsInt();
|
||||
int sy = size.get(1).getAsInt();
|
||||
int sz = size.get(2).getAsInt();
|
||||
|
||||
int u = cube.getAsJsonArray("uv").get(0).getAsInt();
|
||||
int v = cube.getAsJsonArray("uv").get(1).getAsInt();
|
||||
|
||||
// Minimal conservative mapping: fill a sx×sy area with side tile at (u,v)
|
||||
paintFace(g, tiles.side(), atlasW, atlasH, u, v, sx, sy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import com.gregtechceu.gtceu.api.capability.IWorkable;
|
||||
import com.gregtechceu.gtceu.api.capability.forge.GTCapability;
|
||||
import com.gregtechceu.gtceu.api.machine.MetaMachine;
|
||||
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
@@ -41,16 +39,13 @@ public abstract class MetaMachineBlockEntityGeoMixin implements GeoBlockEntity {
|
||||
|
||||
@Unique
|
||||
private static boolean ibg$isActuallyRunning(MetaMachine m) {
|
||||
// Manually enabled?
|
||||
boolean enabled = MetaMachineBlockEntity.getCapability(m, GTCapability.CAPABILITY_CONTROLLABLE, null)
|
||||
.map(IControllable::isWorkingEnabled).orElse(true);
|
||||
|
||||
|
||||
boolean active = MetaMachineBlockEntity.getCapability(m, GTCapability.CAPABILITY_WORKABLE, null)
|
||||
.map(IWorkable::isActive).orElse(false);
|
||||
|
||||
return enabled && active;
|
||||
|
||||
}
|
||||
|
||||
@Unique
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"variants": {
|
||||
"": { "model": "ibg:block/animated_block" }
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,27 @@
|
||||
"bones": [
|
||||
{
|
||||
"name": "bone",
|
||||
"pivot": [17, 18, 0],
|
||||
"pivot": [7, 6, 0],
|
||||
"cubes": [
|
||||
{"origin": [-7, 1, -7], "size": [30, 12, 14], "inflate": 1, "uv": [0, 0]}
|
||||
{
|
||||
"origin": [-8, 0, -8],
|
||||
"size": [32, 14, 16],
|
||||
"uv": {
|
||||
"north": {"uv": [16, 16], "uv_size": [32, 14]},
|
||||
"east": {"uv": [0, 16], "uv_size": [16, 14]},
|
||||
"south": {"uv": [64, 16], "uv_size": [32, 14]},
|
||||
"west": {"uv": [48, 16], "uv_size": [16, 14]},
|
||||
"up": {"uv": [16, 0], "uv_size": [32, 16]},
|
||||
"down": {"uv": [48, 16], "uv_size": [32, -16]}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bone2",
|
||||
"parent": "bone",
|
||||
"pivot": [17, 18, 0],
|
||||
"cubes": [
|
||||
{"origin": [-8, 7, -1], "size": [2, 11, 2], "pivot": [-7, 18, 0], "rotation": [-90, -90, 0], "uv": [0, 26]}
|
||||
{"origin": [-8, 7, -1], "size": [2, 11, 2], "pivot": [-7, 18, 0], "rotation": [-90, -90, 0], "uv": [0, 30]}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 271 B |
BIN
src/main/resources/assets/ibg/textures/block/lathe_overlay.png
Normal file
|
After Width: | Height: | Size: 504 B |