add dummy item auto-creation

This commit is contained in:
Guillaume Mercier committed 2026-01-20 11:00:33 -05:00
1 parent 4d2c1ba3fc
commit 36de68e5ab
6 files changed
+182 -9

No files matched your search

@@ -3,9 +3,11 @@ 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.FMLMissingMappingsEvent;
import cpw.mods.fml.common.event.FMLModIdMappingEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
@@ -37,6 +39,15 @@ public class Postea {
}
}
@Mod.EventHandler
public void onMissingMapping(FMLMissingMappingsEvent event) {
PosteaMissingMappingHandler.onMissingMapping(event);
}
public void onLoadCompleted(FMLLoadCompleteEvent event) {
PosteaMissingMappingHandler.onLoadCompleted();
}
@Mod.EventHandler
public void onServerStopping(FMLServerStoppingEvent event) {
posteaMarkedIDs.clear();
@@ -0,0 +1,129 @@
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 net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
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<>();
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;
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);
}
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.
public static class DummyBlock extends Block {
public DummyBlock() {
super(Material.ground);
}
}
// because we're using reflection to quickly identify our items
public static class DummyItem extends Item {
}
static void onMissingMapping(FMLMissingMappingsEvent event) {
for (FMLMissingMappingsEvent.MissingMapping mapping : event.getAll()) {
if (mapping.name.startsWith(DUMMY_ID_PREFIX)) {
// for when a migrator ceases being registered, likely due to a removal.
mapping.ignore();
continue;
}
if (mapping.type == GameRegistry.Type.BLOCK) {
Block remappedBlock = missingBlockMappings.get(mapping.name);
if (remappedBlock != null) {
mapping.remap(remappedBlock);
continue;
}
} else if (mapping.type == GameRegistry.Type.ITEM) {
Block remappedBlock = missingBlockMappings.get(mapping.name);
if (remappedBlock != null) {
mapping.remap(Item.getItemFromBlock(remappedBlock));
continue;
}
Item remappedItem = missingItemMappings.get(mapping.name);
if (remappedItem != null) {
mapping.remap(missingItemMappings.get(mapping.name));
continue;
}
}
}
}
}
@@ -1,16 +1,19 @@
package com.gtnewhorizons.postea.api;
import java.util.HashMap;
import java.util.function.BiFunction;
import net.minecraft.world.World;
import com.google.common.collect.LinkedListMultimap;
import com.gtnewhorizons.postea.PosteaMissingMappingHandler;
import com.gtnewhorizons.postea.utility.BlockConversionInfo;
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();
@@ -18,12 +21,21 @@ public class BlockReplacementManager {
@SuppressWarnings("unused")
public static void addBlockReplacement(String blockNameIn,
BiFunction<BlockConversionInfo, World, BlockConversionInfo> transformer) {
blockReplacementMap.put(blockNameIn, transformer);
String newName = PosteaMissingMappingHandler.createDummyBlockIfNeeded(blockNameIn);
if (!newName.equals(blockNameIn)) {
dummyMap.put(newName, blockNameIn);
}
blockReplacementMap.put(newName, 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);
for (BiFunction<BlockConversionInfo, World, BlockConversionInfo> transformer : blockReplacementMap
.get(blockConversionInfo.blockName)) {
.get(originalName)) {
BlockConversionInfo result = transformer.apply(blockConversionInfo, world);
if (result != null) return result;
}
@@ -34,5 +46,4 @@ public class BlockReplacementManager {
public static boolean blockNotConvertible(int blockID) {
return !posteaMarkedIDs.contains(blockID);
}
}
@@ -6,6 +6,7 @@ import java.util.function.Function;
import net.minecraft.nbt.NBTTagCompound;
import com.google.common.collect.LinkedListMultimap;
import com.gtnewhorizons.postea.PosteaMissingMappingHandler;
public class ItemStackReplacementManager {
@@ -16,11 +17,12 @@ public class ItemStackReplacementManager {
@SuppressWarnings("unused")
public static void addItemReplacement(String itemName, Function<NBTTagCompound, NBTTagCompound> transformer) {
replacementMap.put(itemName, transformer);
replacementMap.put(PosteaMissingMappingHandler.createDummyItemIfNeeded(itemName), transformer);
}
@SuppressWarnings("unused")
public static Collection<Function<NBTTagCompound, NBTTagCompound>> getItemReplacement(String itemNameInternal) {
return replacementMap.get(itemNameInternal);
}
}
@@ -15,6 +15,7 @@ import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import com.gtnewhorizons.postea.PosteaMissingMappingHandler;
import com.gtnewhorizons.postea.api.BlockReplacementManager;
import com.gtnewhorizons.postea.api.TileEntityReplacementManager;
import com.gtnewhorizons.postea.api.TriFunction;
@@ -76,6 +77,10 @@ public class ChunkFixerUtility {
if (output != null) {
access.setBlockId(x, y, z, output.blockID);
access.setMeta(x, y, z, output.metadata);
} else if (PosteaMissingMappingHandler.isDummyBlock(block)) {
// clear out the slot if this is an unhandled dummy item.
access.setBlockId(x, y, z, 0);
access.setMeta(x, y, z, 0);
}
}
}
@@ -1,10 +1,12 @@
package com.gtnewhorizons.postea.utility;
import java.util.Collection;
import java.util.function.Function;
import net.minecraft.item.Item;
import net.minecraft.nbt.NBTTagCompound;
import com.gtnewhorizons.postea.PosteaMissingMappingHandler;
import com.gtnewhorizons.postea.api.IDExtenderCompat;
import com.gtnewhorizons.postea.api.ItemStackReplacementManager;
@@ -20,12 +22,25 @@ public abstract class ItemFixerUtility {
int id = IDExtenderCompat.getItemStackID(tag);
Item item = Item.getItemById(id);
if (item == null) return;
String itemNameInternal = GameRegistry.findUniqueIdentifierFor(item).modId + ":"
+ GameRegistry.findUniqueIdentifierFor(item).name;
GameRegistry.UniqueIdentifier uuid = GameRegistry.findUniqueIdentifierFor(item);
String itemNameInternal = uuid.modId + ":" + uuid.name;
for (Function<NBTTagCompound, NBTTagCompound> transformer : ItemStackReplacementManager
.getItemReplacement(itemNameInternal)) {
if (transformer.apply(tag) != null) break;
// abort early if no handlers
Collection<Function<NBTTagCompound, NBTTagCompound>> handlers = ItemStackReplacementManager
.getItemReplacement(itemNameInternal);
if (handlers.isEmpty()) return;
// apply handlers
for (Function<NBTTagCompound, NBTTagCompound> transformer : handlers) {
if (transformer.apply(tag) != null) {
return;
}
}
// if no handler overwrote anything on this stack, and it's a dummy, delete the stack.
if (PosteaMissingMappingHandler.isDummyItem(item)) {
tag.removeTag("id");
tag.removeTag("idExt");
}
}
}