mirror of
https://github.com/GTNewHorizons/Postea.git
synced 2026-11-12 08:27:33 +00:00
350 lines
16 KiB
Java
350 lines
16 KiB
Java
package com.gtnewhorizons.postea;
|
|||
|
|
|
||
|
|
import net.minecraft.block.Block;
|
||
|
|
import net.minecraft.block.material.Material;
|
||
|
|
import net.minecraft.init.Blocks;
|
||
|
|
import net.minecraft.init.Items;
|
||
|
|
import net.minecraft.item.Item;
|
||
|
|
import net.minecraft.item.ItemStack;
|
||
|
|
import net.minecraft.nbt.NBTTagCompound;
|
||
|
|
import net.minecraft.nbt.NBTTagList;
|
||
|
|
import net.minecraft.world.World;
|
||
|
|
import net.minecraft.world.chunk.Chunk;
|
||
|
|
import net.minecraftforge.oredict.OreDictionary;
|
||
|
|
|
||
|
|
import com.gtnewhorizons.postea.api.BlockAccessCompat;
|
||
|
|
import com.gtnewhorizons.postea.api.BlockReplacementManager;
|
||
|
|
import com.gtnewhorizons.postea.api.IDExtenderCompat;
|
||
|
|
import com.gtnewhorizons.postea.api.ItemStackReplacementManager;
|
||
|
|
import com.gtnewhorizons.postea.api.TileEntityReplacementManager;
|
||
|
|
import com.gtnewhorizons.postea.utility.BlockConversionInfo;
|
||
|
|
import com.gtnewhorizons.postea.utility.BlockInfo;
|
||
|
|
|
||
|
|
import cpw.mods.fml.common.registry.GameRegistry;
|
||
|
|
|
||
|
|
abstract class ExampleMigrators {
|
||
|
|
|
||
|
|
static void postLoad() {
|
||
|
|
TEToBlockExample.postLoad();
|
||
|
|
TEModifyExample.postLoad();
|
||
|
|
TEFullReplacementExample.postLoad();
|
||
|
|
SimpleTransformationExample.postLoad();
|
||
|
|
ComplexBlockTransformer.postLoad();
|
||
|
|
ComplexItemTransformer.postLoad();
|
||
|
|
FMLReMappingExample.postLoad();
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class TEToBlockExample {
|
||
|
|
|
||
|
|
public static void postLoad() {
|
||
|
|
// it's with great shame that we do admit that gregtech ores used to be tile entities.
|
||
|
|
TileEntityReplacementManager.tileEntityTransformer("GT_TileEntity_Ores", (tag, world, chunk) -> {
|
||
|
|
if (world.provider.dimensionId == -1) {
|
||
|
|
// nether gets orange wool
|
||
|
|
return new BlockInfo(Blocks.wool, 1);
|
||
|
|
}
|
||
|
|
if (world.provider.dimensionId == 1) {
|
||
|
|
// the end gets magenta wool
|
||
|
|
return new BlockInfo(Blocks.wool, 2);
|
||
|
|
}
|
||
|
|
// all other dimensions get light blue wool
|
||
|
|
return new BlockInfo(Blocks.wool, 3);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class TEModifyExample {
|
||
|
|
|
||
|
|
private static int reedsId = -1;
|
||
|
|
private static int diamondId = -1;
|
||
|
|
private static int stoneId = -1;
|
||
|
|
private static int record11Id = -1;
|
||
|
|
|
||
|
|
public static void postLoad() {
|
||
|
|
// pre caching ids like this will lead to faster transformers
|
||
|
|
ItemStackReplacementManager.registerIDResolver("minecraft:reeds", i -> reedsId = i);
|
||
|
|
ItemStackReplacementManager.registerIDResolver("minecraft:diamond", i -> diamondId = i);
|
||
|
|
ItemStackReplacementManager.registerIDResolver("minecraft:stone", i -> stoneId = i);
|
||
|
|
TileEntityReplacementManager.tileEntityTransformer("Chest", (tag, world, chunk) -> {
|
||
|
|
// This transformer replaces all sugar cane stacks inside a chest with
|
||
|
|
// stone, unless it's in the 13th slot at which point it's replaced with
|
||
|
|
// diamonds. All transformations are done without affecting the stack size.
|
||
|
|
NBTTagList slots = tag.getTagList("Items", 10);
|
||
|
|
for (int i = 0; i < slots.tagCount(); i++) {
|
||
|
|
NBTTagCompound slot = slots.getCompoundTagAt(i);
|
||
|
|
// only target the removed item
|
||
|
|
if (IDExtenderCompat.getItemStackID(slot) != reedsId) continue;
|
||
|
|
if (slot.getByte("Slot") == 13) {
|
||
|
|
// replace it with diamonds if it's in slot 13
|
||
|
|
IDExtenderCompat.setItemStackID(slot, diamondId);
|
||
|
|
} else {
|
||
|
|
// else replace it with stone.
|
||
|
|
IDExtenderCompat.setItemStackID(slot, stoneId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
});
|
||
|
|
|
||
|
|
// this tile entity transformer also executes because the other transformer returned null
|
||
|
|
ItemStackReplacementManager.registerIDResolver("minecraft:record_11", i -> record11Id = i);
|
||
|
|
byte targetSLot = (byte) 12;
|
||
|
|
TileEntityReplacementManager.tileEntityTransformer("Chest", (tag, world, chunk) -> {
|
||
|
|
// This transformer looks for the 12th slot of the chest and replaces
|
||
|
|
// or sets it's content to a new stack of record 11 with a stack size of 1.
|
||
|
|
NBTTagList slots = tag.getTagList("Items", 10);
|
||
|
|
NBTTagCompound toEdit = null;
|
||
|
|
for (int i = 0; i < slots.tagCount(); i++) {
|
||
|
|
NBTTagCompound slot = slots.getCompoundTagAt(i);
|
||
|
|
if (slot.getByte("Slot") != targetSLot) continue;
|
||
|
|
toEdit = slot;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (toEdit == null) {
|
||
|
|
toEdit = new NBTTagCompound();
|
||
|
|
toEdit.setByte("Slot", targetSLot);
|
||
|
|
slots.appendTag(toEdit);
|
||
|
|
}
|
||
|
|
toEdit.setByte("Count", (byte) 1);
|
||
|
|
toEdit.setShort("Damage", (short) 0);
|
||
|
|
IDExtenderCompat.setItemStackID(toEdit, record11Id);
|
||
|
|
return null;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class TEFullReplacementExample {
|
||
|
|
|
||
|
|
public static int litFurnaceId = -1;
|
||
|
|
public static int unlitFurnaceId = -1;
|
||
|
|
public static int fireChargeId = -1;
|
||
|
|
|
||
|
|
public static void postLoad() {
|
||
|
|
BlockReplacementManager.registerIDResolver("minecraft:lit_furnace", i -> litFurnaceId = i);
|
||
|
|
BlockReplacementManager.registerIDResolver("minecraft:furnace", i -> unlitFurnaceId = i);
|
||
|
|
ItemStackReplacementManager.registerIDResolver("minecraft:fire_charge", i -> fireChargeId = i);
|
||
|
|
TileEntityReplacementManager.tileEntityTransformer("Furnace", TEFullReplacementExample::transformFurnace);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* This transformer transforms a furnace into a chest, and adds a fire charge in the 4th slot of the chest if
|
||
|
|
* the block where the tile entity once stood was a lit furnace. If it's not either a lit or unlit furnace,
|
||
|
|
* the block is simply transformed into air.
|
||
|
|
*
|
||
|
|
* @param tag The NBT data of the tile entity being transformed.
|
||
|
|
* @param world The world in which the tile entity is located.
|
||
|
|
* @param chunk The chunk in which the tile entity is located.
|
||
|
|
* @return Null if we didn't update the block, else a BlockInfo with the transformation data you wish to
|
||
|
|
* execute.
|
||
|
|
*/
|
||
|
|
private static BlockInfo transformFurnace(NBTTagCompound tag, World world, Chunk chunk) {
|
||
|
|
int[] blockIdAndMeta = BlockAccessCompat.getBlockIDAndMetaAtTE(tag, chunk);
|
||
|
|
int blockId = blockIdAndMeta[0];
|
||
|
|
int meta = blockIdAndMeta[1];
|
||
|
|
// we return a value this time because we are actually replacing the block and tile entity.
|
||
|
|
// we copy the meta value since that preserves the orientation for these blocks.
|
||
|
|
return new BlockInfo(Blocks.chest, meta, oldTag -> transformFurnaceNBT(oldTag, blockId));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Moves the content of the furnace to the chest and adds a fire charge in the 4th slot if the furnace was lit.
|
||
|
|
*
|
||
|
|
* @param oldTag The current NBT data ofthe tile entity being transformed.
|
||
|
|
* @return null if we want the tile entity to be erased.
|
||
|
|
*/
|
||
|
|
private static NBTTagCompound transformFurnaceNBT(NBTTagCompound oldTag, int blockId) {
|
||
|
|
// if the block wasn't a furnace, clear the current tile entity and let the chest spawn a new one.
|
||
|
|
if (blockId != litFurnaceId && blockId != unlitFurnaceId) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
// use this function to create a new tile entity tag with the same positional data as the old one.
|
||
|
|
NBTTagCompound newTag = TileEntityReplacementManager.createTETagAtSamePosition("Chest", oldTag);
|
||
|
|
NBTTagList newSlots = (NBTTagList) oldTag.getTagList("Items", 10)
|
||
|
|
.copy();
|
||
|
|
// if the block used to be a lit furnace add a fire charge in the 4th slot.
|
||
|
|
if (blockId == litFurnaceId) {
|
||
|
|
NBTTagCompound fireChargeStack = new NBTTagCompound();
|
||
|
|
IDExtenderCompat.setItemStackID(fireChargeStack, fireChargeId);
|
||
|
|
fireChargeStack.setByte("Slot", (byte) 4);
|
||
|
|
fireChargeStack.setByte("Count", (byte) 1);
|
||
|
|
fireChargeStack.setShort("Damage", (short) 0);
|
||
|
|
newSlots.appendTag(fireChargeStack);
|
||
|
|
}
|
||
|
|
newTag.setTag("Items", newSlots);
|
||
|
|
return newTag;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class SimpleTransformationExample {
|
||
|
|
|
||
|
|
public static void postLoad() {
|
||
|
|
// item/block -> item/block, preserving the Meta/Damage value.
|
||
|
|
//
|
||
|
|
// remap all block and items of colored stone blocks with wool of the same color
|
||
|
|
BlockReplacementManager.addSimpleReplacement("ExtraUtilities:colorStoneBrick", Blocks.wool);
|
||
|
|
|
||
|
|
// Item/Block with meta -> Item/Block, meta preserved
|
||
|
|
//
|
||
|
|
// angel ring:3 to disk 11
|
||
|
|
ItemStackReplacementManager
|
||
|
|
.addSimpleReplacement("ExtraUtilities:angelRing", 3, new ItemStack(Items.record_11));
|
||
|
|
ItemStackReplacementManager
|
||
|
|
.addSimpleReplacement("ExtraUtilities:angelRing", 4, new ItemStack(Items.record_13));
|
||
|
|
|
||
|
|
// Item/Block with meta -> Item/Block with specific meta
|
||
|
|
//
|
||
|
|
// remap all compressed cobble to oak planks
|
||
|
|
//
|
||
|
|
// When using a stack as a target the passed stack size is ignored, only the contained item and meta value
|
||
|
|
// are kept.
|
||
|
|
ItemStackReplacementManager
|
||
|
|
.addSimpleReplacement("ExtraUtilities:cobblestone_compressed", 0, new ItemStack(Blocks.planks, 0, 0));
|
||
|
|
|
||
|
|
// block only with meta -> block with specific meta value.
|
||
|
|
//
|
||
|
|
// remap blocks of double compressed cobble to cobble.
|
||
|
|
BlockReplacementManager
|
||
|
|
.addSimpleReplacement("ExtraUtilities:cobblestone_compressed", 1, Blocks.cobblestone, 0, true);
|
||
|
|
// item only with damage -> item only with specific damage value.
|
||
|
|
//
|
||
|
|
// remap stacks of double compressed cobble to oak saplings.
|
||
|
|
ItemStackReplacementManager.addSimpleReplacement(
|
||
|
|
"ExtraUtilities:cobblestone_compressed",
|
||
|
|
1,
|
||
|
|
new ItemStack(Blocks.sapling, 1, 0),
|
||
|
|
true);
|
||
|
|
|
||
|
|
// Block/Item with any Meta/Damage -> Block/Item with specific Meta/Damage value.
|
||
|
|
//
|
||
|
|
// Using OreDictionary.WILDCARD_VALUE will tell postea to use this mapping as a fallback when there is no
|
||
|
|
// transformer targeting the specific meta/damage value of the block/item.
|
||
|
|
//
|
||
|
|
// remap all other instances of compressed blocks to endstone
|
||
|
|
BlockReplacementManager.addSimpleReplacement(
|
||
|
|
"ExtraUtilities:cobblestone_compressed",
|
||
|
|
OreDictionary.WILDCARD_VALUE,
|
||
|
|
Blocks.end_stone,
|
||
|
|
0);
|
||
|
|
|
||
|
|
// Block/Item with any Meta/Damage -> Block/Item, preserving the Meta/Damage value.
|
||
|
|
//
|
||
|
|
// When passing OreDictionary.WILDCARD_VALUE as the target Meta/Damage value, Postea will preserve any
|
||
|
|
// existing
|
||
|
|
// Meta/Damage value. This is also the default value when you don't specify a target meta value.
|
||
|
|
//
|
||
|
|
// remap all other instances of compressed blocks to endstone
|
||
|
|
BlockReplacementManager.addSimpleReplacement(
|
||
|
|
"ExtraUtilities:cobblestone_compressed",
|
||
|
|
OreDictionary.WILDCARD_VALUE,
|
||
|
|
Blocks.end_stone,
|
||
|
|
OreDictionary.WILDCARD_VALUE);
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class ComplexBlockTransformer {
|
||
|
|
|
||
|
|
private static int woolId = -1;
|
||
|
|
|
||
|
|
public static void postLoad() {
|
||
|
|
// This transformer replaces all grass blocks with even x-coordinates with orange wool.
|
||
|
|
BlockReplacementManager.registerIDResolver("minecraft:wool", i -> woolId = i);
|
||
|
|
BlockReplacementManager
|
||
|
|
.addTransformationHandler("minecraft:grass", ComplexBlockTransformer::transformGrass);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static boolean transformGrass(BlockConversionInfo info) {
|
||
|
|
// only affect blocks that are on even x coordinates
|
||
|
|
if (info.x % 2 != 0) return false;
|
||
|
|
// transform all these blocks into orange wool.
|
||
|
|
info.blockID = woolId;
|
||
|
|
info.metadata = 1;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class ComplexItemTransformer {
|
||
|
|
|
||
|
|
private static int writableBookId = -1;
|
||
|
|
private static int woolId = -1;
|
||
|
|
|
||
|
|
private static void postLoad() {
|
||
|
|
ItemStackReplacementManager.registerIDResolver("minecraft:writable_book", i -> writableBookId = i);
|
||
|
|
ItemStackReplacementManager.registerIDResolver("minecraft:wool", i -> woolId = i);
|
||
|
|
ItemStackReplacementManager
|
||
|
|
.addTransformationHandler("minecraft:written_book", ComplexItemTransformer::unsignBook);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* This transformer transforms a written book into either an unsigned book or orange wool depending on it's
|
||
|
|
* title.
|
||
|
|
*
|
||
|
|
* @param name The name of the item being transformed, even if that item doesn't exist anymore.
|
||
|
|
* @param nbt The NBT data of the stack item being transformed.
|
||
|
|
* @return True if we've actually transformed the item.
|
||
|
|
*/
|
||
|
|
private static boolean unsignBook(String name, NBTTagCompound nbt) {
|
||
|
|
// check if the book has a title.
|
||
|
|
if (!nbt.hasKey("tag", 10)) return false;
|
||
|
|
NBTTagCompound tag = nbt.getCompoundTag("tag");
|
||
|
|
if (!tag.hasKey("title", 8)) return false;
|
||
|
|
String title = tag.getString("title");
|
||
|
|
if (title.equalsIgnoreCase("unsign me")) {
|
||
|
|
// unsign the book
|
||
|
|
IDExtenderCompat.setItemStackID(nbt, writableBookId);
|
||
|
|
nbt.setShort("Damage", (short) 0);
|
||
|
|
nbt.setByte("Count", (byte) 1);
|
||
|
|
// clear the signed book nbt
|
||
|
|
tag.removeTag("title");
|
||
|
|
tag.removeTag("author");
|
||
|
|
return true;
|
||
|
|
} else if (title.equalsIgnoreCase("orange wool")) {
|
||
|
|
// Transform it into orange wool.
|
||
|
|
IDExtenderCompat.setItemStackID(nbt, woolId);
|
||
|
|
nbt.setShort("Damage", (short) 1);
|
||
|
|
nbt.setByte("Count", (byte) 1);
|
||
|
|
// removes the NBT tag from the stack.
|
||
|
|
nbt.removeTag("tag");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class FMLReMappingExample {
|
||
|
|
|
||
|
|
// You have to make your own block class since the block constructor is protected.
|
||
|
|
public static class MyBlock extends Block {
|
||
|
|
|
||
|
|
protected MyBlock() {
|
||
|
|
super(Material.ground);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static void postLoad() {
|
||
|
|
// this only works when the thing you're replacing with has never been registered to a world's
|
||
|
|
// id map. If you try to run this with a block that already exists (eg good old dirt), FML error out and
|
||
|
|
// you that your world is corrupted beyond repair, and advise you to undo what ever you just did.
|
||
|
|
//
|
||
|
|
// Postea Simple Transformers don't have that issue and are more lag friendly in the long term. Consider
|
||
|
|
// using them when ever possible, instead of FML mappings.
|
||
|
|
Item item = new Item();
|
||
|
|
GameRegistry.registerItem(item, "my_item");
|
||
|
|
ItemStackReplacementManager.replaceMissingMapping("IC2:itemFertilizer", item);
|
||
|
|
|
||
|
|
Block block = new MyBlock();
|
||
|
|
GameRegistry.registerBlock(block, "my_block");
|
||
|
|
BlockReplacementManager.replaceMissingMapping("IC2:blockCrop", block);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public static abstract class FMLIgnoreMissingMappingExample {
|
||
|
|
|
||
|
|
public static void postLoad() {
|
||
|
|
// It doesn't really matter which one you use, they both do the same thing under the hood.
|
||
|
|
ItemStackReplacementManager.ignoreMissingMapping("IC2:itemFertilizer");
|
||
|
|
BlockReplacementManager.ignoreMissingMapping("IC2:blockCrop");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|