mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 01:34:48 +00:00
194 lines
7.3 KiB
Java
194 lines
7.3 KiB
Java
package net.coderbot.iris.block_rendering;
|
|
|
|
import com.gtnewhorizons.angelica.compat.ModStatus;
|
|
import com.gtnewhorizons.angelica.rendering.celeritas.BlockRenderLayer;
|
|
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
|
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
|
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
|
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
|
import it.unimi.dsi.fastutil.objects.ReferenceSet;
|
|
import net.coderbot.iris.shaderpack.materialmap.BlockEntry;
|
|
import net.coderbot.iris.shaderpack.materialmap.BlockRenderType;
|
|
import net.coderbot.iris.shaderpack.materialmap.FlatteningMap;
|
|
import net.coderbot.iris.shaderpack.materialmap.NamespacedId;
|
|
import net.minecraft.block.Block;
|
|
import net.minecraft.block.BlockDoublePlant;
|
|
import net.minecraft.init.Blocks;
|
|
import net.minecraft.util.ResourceLocation;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
public class BlockMaterialMapping {
|
|
|
|
public record BlockIdMaps(Reference2ObjectMap<Block, Int2IntMap> blockMetaMap, NbtConditionalIdMap<Block> tileEntityMap) {}
|
|
|
|
// Meta-key bits OR'd in at runtime
|
|
public static final int SNOWY_META_BIT = 1 << 16;
|
|
|
|
public static final int DOUBLE_PLANT_TOP_BIT = 0x8;
|
|
|
|
public static final int WILDCARD_META_KEY = 1 << 30;
|
|
|
|
/**
|
|
* Creates the standard block meta ID map, the TileEntity NBT-conditional map, and registers
|
|
* snowy blocks on {@link BlockRenderingSettings}.
|
|
*/
|
|
public static BlockIdMaps createBlockIdMaps(Int2ObjectMap<List<BlockEntry>> blockPropertiesMap, boolean skipFlattening) {
|
|
final Reference2ObjectMap<Block, Int2IntMap> blockMatches = new Reference2ObjectOpenHashMap<>();
|
|
final NbtConditionalIdMap<Block> tileEntityMap = new NbtConditionalIdMap<>();
|
|
final ReferenceSet<Block> snowyBlocks = new ReferenceOpenHashSet<>();
|
|
|
|
blockPropertiesMap.forEach((intId, entries) -> {
|
|
for (BlockEntry entry : entries) {
|
|
if (entry.hasNbtProperties()) {
|
|
addTileEntityEntry(entry, tileEntityMap, intId);
|
|
} else {
|
|
addBlockMetas(entry, blockMatches, tileEntityMap, intId, skipFlattening, snowyBlocks);
|
|
}
|
|
}
|
|
});
|
|
|
|
BlockRenderingSettings.INSTANCE.setHasSnowyEntries(!snowyBlocks.isEmpty());
|
|
BlockRenderingSettings.INSTANCE.setSnowyBlocks(snowyBlocks);
|
|
return new BlockIdMaps(blockMatches, tileEntityMap);
|
|
}
|
|
|
|
public static Map<Block, BlockRenderLayer> createBlockTypeMap(Map<NamespacedId, BlockRenderType> blockPropertiesMap) {
|
|
final Map<Block, BlockRenderLayer> blockTypeIds = new Reference2ReferenceOpenHashMap<>();
|
|
|
|
blockPropertiesMap.forEach((id, blockType) -> {
|
|
Block block = resolveBlockOrNull(id);
|
|
|
|
// Modern names like "grass_block" don't exist in 1.7.10's registry; fall back to flattening.
|
|
if (block == null && "minecraft".equals(id.getNamespace())) {
|
|
final List<BlockEntry> legacyEntries = FlatteningMap.toLegacy(id.getName(), Map.of());
|
|
if (legacyEntries != null) {
|
|
// Use the first entry for render type (render type applies per-block)
|
|
block = resolveBlockOrNull(legacyEntries.getFirst().id());
|
|
}
|
|
}
|
|
|
|
if (block == null) return;
|
|
final BlockRenderLayer layer = convertBlockToRenderLayer(blockType);
|
|
if (layer != null) blockTypeIds.put(block, layer);
|
|
});
|
|
|
|
return blockTypeIds;
|
|
}
|
|
|
|
private static BlockRenderLayer convertBlockToRenderLayer(BlockRenderType type) {
|
|
if (type == null) {
|
|
return null;
|
|
}
|
|
|
|
return switch (type) {
|
|
case SOLID -> BlockRenderLayer.SOLID;
|
|
case CUTOUT -> BlockRenderLayer.CUTOUT;
|
|
case CUTOUT_MIPPED -> BlockRenderLayer.CUTOUT_MIPPED;
|
|
case TRANSLUCENT -> BlockRenderLayer.TRANSLUCENT;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates an NBT-conditional ID map keyed by NamespacedId, for items or entities.
|
|
*/
|
|
public static NbtConditionalIdMap<NamespacedId> createNamespacedNbtMap(Int2ObjectMap<List<BlockEntry>> nbtEntries) {
|
|
NbtConditionalIdMap<NamespacedId> map = new NbtConditionalIdMap<>();
|
|
|
|
nbtEntries.forEach((intId, entries) -> {
|
|
for (BlockEntry entry : entries) {
|
|
if (entry.hasNbtProperties()) {
|
|
map.addCondition(entry.id(), entry.nbtProperties(), intId);
|
|
}
|
|
}
|
|
});
|
|
|
|
return map;
|
|
}
|
|
|
|
private static void addTileEntityEntry(BlockEntry entry, NbtConditionalIdMap<Block> teMap, int intId) {
|
|
final NamespacedId id = entry.id();
|
|
final ResourceLocation resourceLocation = new ResourceLocation(id.getNamespace(), id.getName());
|
|
|
|
final Block block = (Block) Block.blockRegistry.getObject(resourceLocation.toString());
|
|
|
|
if (block == null || block == Blocks.air) {
|
|
return;
|
|
}
|
|
|
|
teMap.addCondition(block, entry.nbtProperties(), intId);
|
|
}
|
|
|
|
/**
|
|
* Adds block+metadata combinations to the material ID map.
|
|
* Based on Iris's addBlockStates method, adapted for 1.7.10 metadata system.
|
|
*/
|
|
private static void addBlockMetas(BlockEntry entry, Reference2ObjectMap<Block, Int2IntMap> idMap,
|
|
NbtConditionalIdMap<Block> tileEntityMap, int intId,
|
|
boolean skipFlattening, ReferenceSet<Block> snowyBlocks) {
|
|
final NamespacedId id = entry.id();
|
|
final Map<String, String> stateProps = entry.stateProperties();
|
|
final String snowy = stateProps.get("snowy");
|
|
final int snowyBit = "true".equals(snowy) ? SNOWY_META_BIT : 0;
|
|
final boolean wantsDoublePlantTop = "upper".equals(stateProps.get("half"));
|
|
|
|
// Vanilla modern names go through FlatteningMap; legacy-section packs and modded blocks
|
|
// resolve directly from the registry.
|
|
List<BlockEntry> targets = null;
|
|
if (!skipFlattening && "minecraft".equals(id.getNamespace()) && (!stateProps.isEmpty() || entry.metas().isEmpty())) {
|
|
targets = FlatteningMap.toLegacy(id.getName(), stateProps);
|
|
}
|
|
if (targets == null) targets = List.of(entry);
|
|
|
|
for (BlockEntry target : targets) {
|
|
if (target.hasNbtProperties()) {
|
|
addTileEntityEntry(target, tileEntityMap, intId);
|
|
continue;
|
|
}
|
|
final Block block = resolveBlockOrNull(target.id());
|
|
if (block == null) continue;
|
|
int extraBits = snowyBit;
|
|
if (wantsDoublePlantTop && block instanceof BlockDoublePlant) {
|
|
extraBits |= DOUBLE_PLANT_TOP_BIT;
|
|
}
|
|
applyMetas(block, target.metas(), idMap, intId, extraBits);
|
|
if (snowy != null) snowyBlocks.add(block);
|
|
}
|
|
}
|
|
|
|
private static void applyMetas(Block block, Set<Integer> metas, Reference2ObjectMap<Block, Int2IntMap> idMap, int intId, int extraBits) {
|
|
Int2IntMap metaMap = idMap.get(block);
|
|
if (metaMap == null) {
|
|
metaMap = new Int2IntOpenHashMap();
|
|
metaMap.defaultReturnValue(-1);
|
|
idMap.put(block, metaMap);
|
|
}
|
|
|
|
if (metas.isEmpty()) {
|
|
for (int meta = 0; meta < 16; meta++) metaMap.putIfAbsent(meta | extraBits, intId);
|
|
if (ModStatus.isMetadataExtended) metaMap.putIfAbsent(WILDCARD_META_KEY | extraBits, intId);
|
|
} else {
|
|
for (int meta : metas) metaMap.putIfAbsent(meta | extraBits, intId);
|
|
}
|
|
}
|
|
|
|
public static int resolveId(Int2IntMap metaMap, int metaKey) {
|
|
final int id = metaMap.get(metaKey);
|
|
return id != -1 ? id : metaMap.get(WILDCARD_META_KEY | (metaKey & SNOWY_META_BIT));
|
|
}
|
|
|
|
/**
|
|
* Returns the registered Block for an id, or null if unknown.
|
|
* The registry returns Blocks.air (its default) for missing keys, which we coerce to null.
|
|
*/
|
|
private static Block resolveBlockOrNull(NamespacedId id) {
|
|
final Block block = (Block) Block.blockRegistry.getObject(new ResourceLocation(id.getNamespace(), id.getName()).toString());
|
|
return block == Blocks.air ? null : block;
|
|
}
|
|
}
|