Move dummy item creation to the load complete event.

This commit is contained in:
Guillaume Mercier committed 2026-01-20 13:07:23 -05:00
1 parent 36de68e5ab
commit 5d4b657868
6 files changed
+167 -89

No files matched your search

+1
View File
@@ -4,4 +4,5 @@ dependencies {
compileOnly('com.github.GTNewHorizons:NotEnoughIds:2.1.10:dev')
compileOnly('com.falsepattern:chunkapi-mc1.7.10:0.6.0:dev')
compileOnly('com.falsepattern:endlessids-mc1.7.10:1.6.0:dev')
compileOnly("com.github.GTNewHorizons:NotEnoughItems:2.8.48-GTNH:dev") { transitive = false }
}
@@ -3,10 +3,10 @@ package com.gtnewhorizons.postea;
import static com.gtnewhorizons.postea.api.BlockReplacementManager.blockReplacementMap;
import static com.gtnewhorizons.postea.api.BlockReplacementManager.posteaMarkedIDs;
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
import net.minecraft.block.Block;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
import cpw.mods.fml.common.event.FMLMissingMappingsEvent;
import cpw.mods.fml.common.event.FMLModIdMappingEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
@@ -44,6 +44,7 @@ public class Postea {
PosteaMissingMappingHandler.onMissingMapping(event);
}
@Mod.EventHandler
public void onLoadCompleted(FMLLoadCompleteEvent event) {
PosteaMissingMappingHandler.onLoadCompleted();
}
@@ -1,92 +1,46 @@
package com.gtnewhorizons.postea;
import java.util.HashMap;
import java.util.HashSet;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.Map;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import com.gtnewhorizons.postea.compat.Compat;
import cpw.mods.fml.common.event.FMLMissingMappingsEvent;
import cpw.mods.fml.common.registry.GameRegistry;
public abstract class PosteaMissingMappingHandler {
private static final HashMap<String, Item> missingItemMappings = new HashMap<>();
private static final HashMap<String, Block> missingBlockMappings = new HashMap<>();
private static final HashMap<String, String> remappedBlocks = new HashMap<>();
private static final HashSet<String> remappedItems = new HashSet<>();
enum MappingType {
/** Tells the mapping logic to register an Item. */
Item,
/** Tells the mapping logic to register a Block (and ItemBlock). */
Block
}
private static final String DUMMY_ID_PREFIX_START = Postea.MODID + ":";
private static final String DUMMY_ID_PREFIX_END = "d.";
private static final String DUMMY_ID_PREFIX = DUMMY_ID_PREFIX_START + DUMMY_ID_PREFIX_END;
static class DummyMapping {
public static String createDummyBlockIfNeeded(String originalId) {
if (remappedItems.contains(originalId))
throw new IllegalArgumentException("block mappings must be declared before the item remapping");
String newId = onMappingAdded(
originalId,
GameRegistry::findBlock,
missingBlockMappings,
DummyBlock::new,
GameRegistry::registerBlock);
// don't let it register an item jic
if (!newId.equals(originalId)) {
remappedBlocks.put(originalId, newId);
/** The type of thing that should be registered for this dummy */
public MappingType type;
/** The id under which the dummy should be registered */
public String registerAs;
/** The full id of the dummy, including mod prefix */
public String id;
public DummyMapping(MappingType type, String registerAs, String id) {
this.type = type;
this.registerAs = registerAs;
this.id = id;
}
return newId;
}
public static String createDummyItemIfNeeded(String originalId) {
if (remappedBlocks.containsKey(originalId)) return remappedBlocks.get(originalId);
String newId = onMappingAdded(
originalId,
GameRegistry::findItem,
missingItemMappings,
DummyItem::new,
GameRegistry::registerItem);
if (!newId.equals(originalId)) remappedItems.add(newId);
return newId;
}
private static <T> String onMappingAdded(String originalId, BiFunction<String, String, T> registryCheck,
HashMap<String, T> dummyLookup, Supplier<T> dummySupplier, BiConsumer<T, String> registryConsumer) {
// split name into parts
int pos = originalId.indexOf(':');
if (pos < 1) return originalId;
final String modId = originalId.substring(0, pos);
final String name = originalId.substring(pos + 1);
// check if it exists
if (registryCheck.apply(modId, name) != null) return originalId;
// else register a fake item
final String registerAs = DUMMY_ID_PREFIX_END + modId + "." + name;
final String dummyFullId = DUMMY_ID_PREFIX_START + registerAs;
// abort early if we've already registered a dummy handler for this item.
if (dummyLookup.containsKey(dummyFullId)) return dummyFullId;
T dummy = dummySupplier.get();
dummyLookup.put(dummyFullId, dummy);
dummyLookup.put(originalId, dummy);
registryConsumer.accept(dummy, registerAs);
return dummyFullId;
}
public static boolean isDummyItem(Item item) {
return item instanceof DummyItem || item instanceof ItemBlock ib && ib.field_150939_a instanceof DummyBlock;
}
public static boolean isDummyBlock(Block block) {
return block instanceof DummyBlock;
}
public static void onLoadCompleted() {
for (
}
// we're using reflection to identify dummies quickly.
// because we're using reflection to quickly identify our stuff at runtime.
public static class DummyBlock extends Block {
public DummyBlock() {
@@ -94,10 +48,56 @@ public abstract class PosteaMissingMappingHandler {
}
}
// because we're using reflection to quickly identify our items
public static class DummyItem extends Item {
}
public static class DummyItemBlock extends ItemBlock {
public DummyItemBlock(Block p_i45328_1_) {
super(p_i45328_1_);
}
}
private static final HashMap<String, Item> MISSING_ITEM_MAPPINGS = new HashMap<>();
private static final HashMap<String, Block> MISSING_BLOCK_MAPPINGS = new HashMap<>();
private static final HashMap<String, DummyMapping> DUMMY_TARGET_TYPES = new HashMap<>();
private static final HashMap<String, String> REVERSE_DUMMY_ID_LOOKUP = new HashMap<>();
private static final String DUMMY_ID_PREFIX_START = Postea.MODID + ":";
private static final String DUMMY_ID_PREFIX_END = "d.";
private static final String DUMMY_ID_PREFIX = DUMMY_ID_PREFIX_START + DUMMY_ID_PREFIX_END;
static void onLoadCompleted() {
for (Map.Entry<String, DummyMapping> kv : DUMMY_TARGET_TYPES.entrySet()) {
DummyMapping mapping = kv.getValue();
String originalId = kv.getKey();
// split the original id into parts to query for the original's existance.
String[] splitId = splitItemId(originalId);
if (splitId == null) continue;
// ensure nothing else is registered under that id.
if (GameRegistry.findBlock(splitId[0], splitId[1]) != null) continue;
if (GameRegistry.findItem(splitId[0], splitId[1]) != null) continue;
// remap if not found
if (mapping.type == MappingType.Block) {
// check if the block was since registered.
Block dummy = new DummyBlock();
GameRegistry.registerBlock(dummy, DummyItemBlock.class, mapping.registerAs);
// register both for when we're remapping from ourselves to ourselves because something wasn't loaded
// and transformed.
MISSING_BLOCK_MAPPINGS.put(originalId, dummy);
Compat.hideItemFromNEI(Item.getItemFromBlock(dummy));
} else {
Item dummy = new DummyItem();
GameRegistry.registerItem(dummy, mapping.registerAs);
MISSING_ITEM_MAPPINGS.put(originalId, dummy);
Compat.hideItemFromNEI(dummy);
}
REVERSE_DUMMY_ID_LOOKUP.put(mapping.id, originalId);
}
// no longer needed free what ever used to be in there
DUMMY_TARGET_TYPES.clear();
}
static void onMissingMapping(FMLMissingMappingsEvent event) {
for (FMLMissingMappingsEvent.MissingMapping mapping : event.getAll()) {
if (mapping.name.startsWith(DUMMY_ID_PREFIX)) {
@@ -107,23 +107,76 @@ public abstract class PosteaMissingMappingHandler {
}
if (mapping.type == GameRegistry.Type.BLOCK) {
Block remappedBlock = missingBlockMappings.get(mapping.name);
Block remappedBlock = MISSING_BLOCK_MAPPINGS.get(mapping.name);
if (remappedBlock != null) {
mapping.remap(remappedBlock);
continue;
}
} else if (mapping.type == GameRegistry.Type.ITEM) {
Block remappedBlock = missingBlockMappings.get(mapping.name);
Block remappedBlock = MISSING_BLOCK_MAPPINGS.get(mapping.name);
if (remappedBlock != null) {
mapping.remap(Item.getItemFromBlock(remappedBlock));
continue;
}
Item remappedItem = missingItemMappings.get(mapping.name);
Item remappedItem = MISSING_ITEM_MAPPINGS.get(mapping.name);
if (remappedItem != null) {
mapping.remap(missingItemMappings.get(mapping.name));
mapping.remap(MISSING_ITEM_MAPPINGS.get(mapping.name));
continue;
}
}
}
// no longer needed free what ever used to be in there
MISSING_BLOCK_MAPPINGS.clear();
MISSING_ITEM_MAPPINGS.clear();
}
private static void onMappingAdded(String originalId, MappingType mappingType) {
// split name into parts
String[] splitId = splitItemId(originalId);
if (splitId == null) return;
// else register a fake item
final String registerAs = DUMMY_ID_PREFIX_END + splitId[0] + "." + splitId[1];
final String dummyFullId = DUMMY_ID_PREFIX_START + registerAs;
if (mappingType == MappingType.Item) {
DUMMY_TARGET_TYPES.putIfAbsent(originalId, new DummyMapping(mappingType, registerAs, dummyFullId));
} else {
DummyMapping existing = DUMMY_TARGET_TYPES.getOrDefault(originalId, null);
if (existing != null) {
existing.type = mappingType;
} else {
DUMMY_TARGET_TYPES.put(originalId, new DummyMapping(mappingType, registerAs, dummyFullId));
}
}
}
public static void createDummyBlockIfNeeded(String originalId) {
DummyMapping existing = DUMMY_TARGET_TYPES.get(originalId);
// item mappings should be over-written
if (existing != null && existing.type == MappingType.Block) return;
onMappingAdded(originalId, MappingType.Block);
}
public static void createDummyItemIfNeeded(String originalId) {
DummyMapping existing = DUMMY_TARGET_TYPES.get(originalId);
if (existing != null) return;
onMappingAdded(originalId, MappingType.Item);
}
public static String getOriginalIDIfIDIsDummyID(String originalId) {
return REVERSE_DUMMY_ID_LOOKUP.getOrDefault(originalId, originalId);
}
private static @Nullable String[] splitItemId(String itemId) {
int pos = itemId.indexOf(':');
if (pos < 1) return null;
return new String[] { itemId.substring(0, pos), itemId.substring(pos + 1) };
}
public static boolean isDummyItem(Item item) {
return item instanceof DummyItem || item instanceof DummyItemBlock;
}
public static boolean isDummyBlock(Block block) {
return block instanceof DummyBlock;
}
}
@@ -1,6 +1,5 @@
package com.gtnewhorizons.postea.api;
import java.util.HashMap;
import java.util.function.BiFunction;
import net.minecraft.world.World;
@@ -13,7 +12,6 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
public class BlockReplacementManager {
private static final HashMap<String, String> dummyMap = new HashMap<>();
public static final LinkedListMultimap<String, BiFunction<BlockConversionInfo, World, BlockConversionInfo>> blockReplacementMap = LinkedListMultimap
.create();
public static final IntOpenHashSet posteaMarkedIDs = new IntOpenHashSet();
@@ -21,19 +19,15 @@ public class BlockReplacementManager {
@SuppressWarnings("unused")
public static void addBlockReplacement(String blockNameIn,
BiFunction<BlockConversionInfo, World, BlockConversionInfo> transformer) {
String newName = PosteaMissingMappingHandler.createDummyBlockIfNeeded(blockNameIn);
if (!newName.equals(blockNameIn)) {
dummyMap.put(newName, blockNameIn);
}
blockReplacementMap.put(newName, transformer);
PosteaMissingMappingHandler.createDummyBlockIfNeeded(blockNameIn);
blockReplacementMap.put(blockNameIn, transformer);
}
public static BlockConversionInfo getBlockReplacement(BlockConversionInfo blockConversionInfo, World world) {
// auto change the value in case a handler check it, we can't do anything about the block id
// but hopefully that's never going to be an issue
String originalName = blockConversionInfo.blockName;
blockConversionInfo.blockName = dummyMap
.getOrDefault(blockConversionInfo.blockName, blockConversionInfo.blockName);
String originalName = PosteaMissingMappingHandler.getOriginalIDIfIDIsDummyID(blockConversionInfo.blockName);
blockConversionInfo.blockName = originalName;
for (BiFunction<BlockConversionInfo, World, BlockConversionInfo> transformer : blockReplacementMap
.get(originalName)) {
BlockConversionInfo result = transformer.apply(blockConversionInfo, world);
@@ -17,12 +17,12 @@ public class ItemStackReplacementManager {
@SuppressWarnings("unused")
public static void addItemReplacement(String itemName, Function<NBTTagCompound, NBTTagCompound> transformer) {
replacementMap.put(PosteaMissingMappingHandler.createDummyItemIfNeeded(itemName), transformer);
PosteaMissingMappingHandler.createDummyItemIfNeeded(itemName);
replacementMap.put(itemName, transformer);
}
@SuppressWarnings("unused")
public static Collection<Function<NBTTagCompound, NBTTagCompound>> getItemReplacement(String itemNameInternal) {
return replacementMap.get(itemNameInternal);
return replacementMap.get(PosteaMissingMappingHandler.getOriginalIDIfIDIsDummyID(itemNameInternal));
}
}
@@ -1,17 +1,23 @@
package com.gtnewhorizons.postea.compat;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraftforge.oredict.OreDictionary;
import com.falsepattern.endlessids.mixin.helpers.SubChunkBlockHook;
import com.gtnewhorizons.neid.mixins.interfaces.IExtendedBlockStorageMixin;
import codechicken.nei.api.API;
public class Compat {
private static Boolean chunkapi = null;
private static Boolean endlessids = null;
private static Boolean neid = null;
private static Boolean nei = null;
public static boolean chunkapiPresent() {
if (chunkapi == null) {
@@ -47,6 +53,17 @@ public class Compat {
return neid;
}
public static boolean neiPresent() {
if (nei == null) {
boolean present = false;
try {
present = Launch.classLoader.getClassBytes("codechicken.nei.api.API") != null;
} catch (Throwable ignored) {}
nei = present;
}
return nei;
}
public static SubChunkAccess getSubChunkAccess(ExtendedBlockStorage subChunk) {
if (endlessidsPresent()) {
return EndlessIDSCompat.getSubChunkAccess(subChunk);
@@ -162,6 +179,18 @@ public class Compat {
}
}
public static void hideItemFromNEI(Item item) {
if (!neiPresent()) return;
NEICompat.hideItem(item);
}
private static class NEICompat {
public static void hideItem(Item item) {
API.hideItem(new ItemStack(item, 1, OreDictionary.WILDCARD_VALUE));
}
}
private static int toIndex(int x, int y, int z) {
return y << 8 | z << 4 | x;
}