Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import net.coderbot.iris.Iris;
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.init.Blocks;
Expand Down Expand Up @@ -39,8 +41,16 @@ public static Map<Block, BlockRenderLayer> createBlockTypeMap(Map<NamespacedId,
Map<Block, BlockRenderLayer> blockTypeIds = new Reference2ReferenceOpenHashMap<>();

blockPropertiesMap.forEach((id, blockType) -> {
final ResourceLocation resourceLocation = new ResourceLocation(id.getNamespace(), id.getName());
final Block block = Block.getBlockFromName(resourceLocation.toString());
Block block = resolveBlock(id);

// Try flattening map for modern names
if ((block == null || block == Blocks.air) && "minecraft".equals(id.getNamespace())) {
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 = resolveBlock(legacyEntries.getFirst().getId());
}
}

if (block == null || block == Blocks.air) {
return;
Expand Down Expand Up @@ -73,19 +83,32 @@ private static BlockRenderLayer convertBlockToRenderLayer(BlockRenderType type)
* Based on Iris's addBlockStates method, adapted for 1.7.10 metadata system.
*/
private static void addBlockMetas(BlockEntry entry, Reference2ObjectMap<Block, Int2IntMap> idMap, int intId) {
final NamespacedId id = entry.getId();
final ResourceLocation resourceLocation = new ResourceLocation(id.getNamespace(), id.getName());

final Block block = (Block) Block.blockRegistry.getObject(resourceLocation.toString());
NamespacedId id = entry.getId();
String name = id.getName();
boolean hasStateProps = !entry.getStateProperties().isEmpty();
boolean hasExplicitMetas = !entry.getMetas().isEmpty();

if ("minecraft".equals(id.getNamespace()) && (hasStateProps || !hasExplicitMetas)) {
List<BlockEntry> legacyEntries = FlatteningMap.toLegacy(name, entry.getStateProperties());
if (legacyEntries != null) {
for (BlockEntry legacy : legacyEntries) {
applyMetas(resolveBlock(legacy.getId()), legacy.getMetas(), idMap, intId);
}
return;
}
}

// If the block doesn't exist, by default the registry will return AIR. That probably isn't what we want.
// TODO: Assuming that Registry.BLOCK.getDefaultId() == "minecraft:air" here
// Fall back to registry with the entry's own metas
Block block = resolveBlock(id);
applyMetas(block, entry.getMetas(), idMap, intId);
}
// If the block doesn't exist, by default the registry will return AIR. That probably isn't what we want.
// TODO: Assuming that Registry.BLOCK.getDefaultId() == "minecraft:air" here
private static void applyMetas(Block block, Set<Integer> metas, Reference2ObjectMap<Block, Int2IntMap> idMap, int intId) {
if (block == null || block == Blocks.air) {
return;
}

Set<Integer> metas = entry.getMetas();

Int2IntMap metaMap = idMap.get(block);
if (metaMap == null) {
metaMap = new Int2IntOpenHashMap();
Expand All @@ -94,15 +117,18 @@ private static void addBlockMetas(BlockEntry entry, Reference2ObjectMap<Block, I
}

if (metas.isEmpty()) {
// Add all metadata values (0-15) if there aren't any specific ones
for (int meta = 0; meta < 16; meta++) {
metaMap.putIfAbsent(meta, intId);
}
} else {
// Add only specific metadata values
for (int meta : metas) {
metaMap.putIfAbsent(meta, intId);
}
}
}

private static Block resolveBlock(NamespacedId id) {
final ResourceLocation resourceLocation = new ResourceLocation(id.getNamespace(), id.getName());
return (Block) Block.blockRegistry.getObject(resourceLocation.toString());
}
}
66 changes: 41 additions & 25 deletions src/main/java/net/coderbot/iris/shaderpack/IdMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.Getter;
import net.coderbot.iris.Iris;
import net.coderbot.iris.shaderpack.materialmap.BlockEntry;
import net.coderbot.iris.shaderpack.materialmap.EntityFlatteningMap;
import net.coderbot.iris.shaderpack.materialmap.BlockRenderType;
import net.coderbot.iris.shaderpack.materialmap.NamespacedId;
import net.coderbot.iris.shaderpack.option.ShaderPackOptions;
Expand Down Expand Up @@ -56,7 +58,8 @@ public class IdMap {
/**
* A set of render type overrides for specific blocks. Allows shader packs to move blocks to different render types.
*/
private Map<NamespacedId, BlockRenderType> blockRenderTypeMap;
@Getter
private Map<NamespacedId, BlockRenderType> blockRenderTypeMap;

IdMap(Path shaderPath, ShaderPackOptions shaderPackOptions, Iterable<StringPair> environmentDefines) {
// Check if block.properties has a dedicated 1.7.10 section
Expand All @@ -69,8 +72,8 @@ public class IdMap {
// Pack has a 1.7.10 section
resolvedDefines = environmentDefines;
loadProperties(shaderPath, "block.properties", shaderPackOptions, environmentDefines).ifPresent(blockProperties -> {
blockPropertiesMap = parseBlockMap(blockProperties, "block.", "block.properties");
blockRenderTypeMap = parseRenderTypeMap(blockProperties, "layer.", "block.properties");
blockPropertiesMap = parseBlockMap(blockProperties);
blockRenderTypeMap = parseRenderTypeMap(blockProperties);
});
} else {
// No 1.7.10 section, use modern MC_VERSION and convert entries
Expand All @@ -87,8 +90,8 @@ public class IdMap {
resolvedDefines = modernDefines;

loadProperties(shaderPath, "block.properties", shaderPackOptions, modernDefines).ifPresent(blockProperties -> {
blockPropertiesMap = parseBlockMap(blockProperties, "block.", "block.properties");
blockRenderTypeMap = parseRenderTypeMap(blockProperties, "layer.", "block.properties");
blockPropertiesMap = parseBlockMap(blockProperties);
blockRenderTypeMap = parseRenderTypeMap(blockProperties);
blockPropertiesMap = LegacyIdMap.convertModernBlockEntries(blockPropertiesMap);
});
}
Expand Down Expand Up @@ -141,7 +144,7 @@ private static Optional<Properties> loadProperties(Path shaderPath, String name,
private static String readProperties(Path shaderPath, String name) {
try {
// ID maps should be encoded in ISO_8859_1.
return new String(Files.readAllBytes(shaderPath.resolve(name)), StandardCharsets.ISO_8859_1);
return Files.readString(shaderPath.resolve(name), StandardCharsets.ISO_8859_1);
} catch (NoSuchFileException e) {
Iris.logger.debug("An " + name + " file was not found in the current shaderpack");

Expand All @@ -158,7 +161,24 @@ private static Object2IntMap<NamespacedId> parseItemIdMap(Properties properties)
}

private static Object2IntMap<NamespacedId> parseEntityIdMap(Properties properties) {
return parseIdMap(properties, "entity.", "entity.properties");
Object2IntMap<NamespacedId> idMap = parseIdMap(properties, "entity.", "entity.properties");

// For modern shader packs: translate modern entity names to 1.7.10 names
// so runtime lookups match EntityList's registered names directly.
Object2IntMap<NamespacedId> augmented = new Object2IntOpenHashMap<>(idMap);
augmented.defaultReturnValue(-1);

for (Object2IntMap.Entry<NamespacedId> entry : idMap.object2IntEntrySet()) {
NamespacedId id = entry.getKey();
if ("minecraft".equals(id.getNamespace())) {
String legacyName = EntityFlatteningMap.toLegacy(id.getName());
if (legacyName != null) {
augmented.putIfAbsent(new NamespacedId(legacyName), entry.getIntValue());
}
}
}

return Object2IntMaps.unmodifiable(augmented);
}

/**
Expand Down Expand Up @@ -210,7 +230,7 @@ static List<String> parseIdentifierList(String value, String fileName, String ke
} else if (c == '"') {
inQuotes = !inQuotes;
} else if (Character.isWhitespace(c) && !inQuotes) {
if (current.length() > 0) {
if (!current.isEmpty()) {
result.add(current.toString());
current.setLength(0);
}
Expand All @@ -230,7 +250,7 @@ static List<String> parseIdentifierList(String value, String fileName, String ke
}

// Add final token
if (current.length() > 0) {
if (!current.isEmpty()) {
result.add(current.toString());
}

Expand Down Expand Up @@ -280,25 +300,25 @@ private static Object2IntMap<NamespacedId> parseIdMap(Properties properties, Str
return Object2IntMaps.unmodifiable(idMap);
}

private static Int2ObjectMap<List<BlockEntry>> parseBlockMap(Properties properties, String keyPrefix, String fileName) {
private static Int2ObjectMap<List<BlockEntry>> parseBlockMap(Properties properties) {
Int2ObjectMap<List<BlockEntry>> entriesById = new Int2ObjectOpenHashMap<>();

properties.forEach((keyObject, valueObject) -> {
final String key = (String) keyObject;
StringBuilder value = new StringBuilder((String) valueObject);

if (!key.startsWith(keyPrefix)) {
if (!key.startsWith("block.")) {
// Not a valid line, ignore it
return;
}

final int intId;

try {
intId = Integer.parseInt(key.substring(keyPrefix.length()));
intId = Integer.parseInt(key.substring("block.".length()));
} catch (NumberFormatException e) {
// Not a valid property line
Iris.logger.warn("Failed to parse line in " + fileName + ": invalid key " + key);
Iris.logger.warn("Failed to parse line in " + "block.properties" + ": invalid key " + key);
return;
}

Expand All @@ -315,15 +335,15 @@ private static Int2ObjectMap<List<BlockEntry>> parseBlockMap(Properties properti
}

// Parse identifiers
for (String part : parseIdentifierList(value.toString(), fileName, key)) {
for (String part : parseIdentifierList(value.toString(), "block.properties", key)) {
if (part.isEmpty()) {
continue;
}

try {
entries.add(BlockEntry.parse(part));
} catch (Exception e) {
Iris.logger.warn("Unexpected error while parsing an entry from " + fileName + " for the key " + key + ":", e);
Iris.logger.warn("Unexpected error while parsing an entry from " + "block.properties" + " for the key " + key + ":", e);
}
}

Expand All @@ -338,29 +358,29 @@ private static Int2ObjectMap<List<BlockEntry>> parseBlockMap(Properties properti
*
* This feature is used by Chocapic v9 and Wisdom Shaders. Otherwise, it is a rarely-used feature.
*/
private static Map<NamespacedId, BlockRenderType> parseRenderTypeMap(Properties properties, String keyPrefix, String fileName) {
private static Map<NamespacedId, BlockRenderType> parseRenderTypeMap(Properties properties) {
Map<NamespacedId, BlockRenderType> overrides = new HashMap<>();

properties.forEach((keyObject, valueObject) -> {
String key = (String) keyObject;
String value = (String) valueObject;

if (!key.startsWith(keyPrefix)) {
if (!key.startsWith("layer.")) {
// Not a valid line, ignore it
return;
}

// Note: We have to remove the prefix "layer." because fromString expects "cutout", not "layer.cutout".
String keyWithoutPrefix = key.substring(keyPrefix.length());
String keyWithoutPrefix = key.substring("layer.".length());

BlockRenderType renderType = BlockRenderType.fromString(keyWithoutPrefix).orElse(null);

if (renderType == null) {
Iris.logger.warn("Failed to parse line in " + fileName + ": invalid block render type: " + key);
Iris.logger.warn("Failed to parse line in " + "block.properties" + ": invalid block render type: " + key);
return;
}

for (String part : parseIdentifierList(value, fileName, key)) {
for (String part : parseIdentifierList(value, "block.properties", key)) {
// Note: NamespacedId performs no validation on the content. That will need to be done by whatever is
// converting these things to ResourceLocations.
overrides.put(new NamespacedId(part), renderType);
Expand All @@ -382,11 +402,7 @@ public Object2IntFunction<NamespacedId> getEntityIdMap() {
return entityIdMap;
}

public Map<NamespacedId, BlockRenderType> getBlockRenderTypeMap() {
return blockRenderTypeMap;
}

@Override
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
Expand Down
Loading
Loading