Added various levels of detection and recovery for missing blocks.

Such blueprints should not be loaded in survival, as there may be
inconsistencies, but it's ok to load in creative, in particular for repair if
needed.
Close #1779
This commit is contained in:
SpaceToad 2014-05-11 13:19:06 +02:00
parent a7fe30f38a
commit f1d9aee0b8
15 changed files with 157 additions and 37 deletions

View file

@ -0,0 +1,15 @@
/**
* Copyright (c) 2011-2014, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.api.blueprints;
public class MappingNotFoundException extends Exception {
public MappingNotFoundException(String msg) {
super(msg);
}
}

View file

@ -10,6 +10,7 @@ package buildcraft.api.blueprints;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
@ -21,6 +22,8 @@ import net.minecraft.nbt.NBTTagShort;
import net.minecraftforge.common.util.Constants;
import buildcraft.api.core.BCLog;
public class MappingRegistry {
public HashMap<Block, Integer> blockToId = new HashMap<Block, Integer>();
@ -53,12 +56,18 @@ public class MappingRegistry {
}
}
public Item getItemForId(int id) {
public Item getItemForId(int id) throws MappingNotFoundException {
if (id >= idToItem.size()) {
return null;
throw new MappingNotFoundException("no item mapping at position " + id);
}
return idToItem.get(id);
Item result = idToItem.get(id);
if (result == null) {
throw new MappingNotFoundException("no item mapping at position " + id);
} else {
return result;
}
}
public int getIdForItem(Item item) {
@ -75,18 +84,24 @@ public class MappingRegistry {
return getIdForItem(item);
}
public int itemIdToWorld(int id) {
public int itemIdToWorld(int id) throws MappingNotFoundException {
Item item = getItemForId(id);
return Item.getIdFromItem(item);
}
public Block getBlockForId(int id) {
public Block getBlockForId(int id) throws MappingNotFoundException {
if (id >= idToBlock.size()) {
return null;
throw new MappingNotFoundException("no block mapping at position " + id);
}
return idToBlock.get(id);
Block result = idToBlock.get(id);
if (result == null) {
throw new MappingNotFoundException("no block mapping at position " + id);
} else {
return result;
}
}
public int getIdForBlock(Block block) {
@ -103,18 +118,24 @@ public class MappingRegistry {
return getIdForBlock(block);
}
public int blockIdToWorld(int id) {
public int blockIdToWorld(int id) throws MappingNotFoundException {
Block block = getBlockForId(id);
return Block.getIdFromBlock(block);
}
public Class<? extends Entity> getEntityForId(int id) {
public Class<? extends Entity> getEntityForId(int id) throws MappingNotFoundException {
if (id >= idToEntity.size()) {
return null;
throw new MappingNotFoundException("no entity mapping at position " + id);
}
return idToEntity.get(id);
Class<? extends Entity> result = idToEntity.get(id);
if (result == null) {
throw new MappingNotFoundException("no entity mapping at position " + id);
} else {
return result;
}
}
public int getIdForEntity(Class<? extends Entity> entity) {
@ -138,7 +159,7 @@ public class MappingRegistry {
* Relocates a stack nbt from the registry referential to the world
* referential.
*/
public void stackToWorld(NBTTagCompound nbt) {
public void stackToWorld(NBTTagCompound nbt) throws MappingNotFoundException {
Item item = getItemForId(nbt.getShort("id"));
nbt.setShort("id", (short) Item.getIdFromItem(item));
}
@ -180,7 +201,7 @@ public class MappingRegistry {
}
}
public void scanAndTranslateStacksToWorld(NBTTagCompound nbt) {
public void scanAndTranslateStacksToWorld(NBTTagCompound nbt) throws MappingNotFoundException {
// First, check if this nbt is itself a stack
if (isStackLayout(nbt)) {
@ -193,15 +214,23 @@ public class MappingRegistry {
String key = (String) keyO;
if (nbt.getTag(key) instanceof NBTTagCompound) {
scanAndTranslateStacksToWorld(nbt.getCompoundTag(key));
try {
scanAndTranslateStacksToWorld(nbt.getCompoundTag(key));
} catch (MappingNotFoundException e) {
nbt.removeTag(key);
}
}
if (nbt.getTag(key) instanceof NBTTagList) {
NBTTagList list = (NBTTagList) nbt.getTag(key);
if (list.func_150303_d() == Constants.NBT.TAG_COMPOUND) {
for (int i = 0; i < list.tagCount(); ++i) {
scanAndTranslateStacksToWorld(list.getCompoundTagAt(i));
for (int i = list.tagCount() - 1; i >= 0; --i) {
try {
scanAndTranslateStacksToWorld(list.getCompoundTagAt(i));
} catch (MappingNotFoundException e) {
list.removeTag(i);
}
}
}
}
@ -250,7 +279,14 @@ public class MappingRegistry {
NBTTagCompound sub = blocksMapping.getCompoundTagAt(i);
String name = sub.getString("name");
Block b = (Block) Block.blockRegistry.getObject(name);
registerBlock (b);
if (b != null) {
registerBlock(b);
} else {
// Keeping the order correct
idToBlock.add(null);
BCLog.logger.log(Level.WARNING, "Can't load block " + name);
}
}
NBTTagList itemsMapping = nbt.getTagList("itemsMapping",
@ -260,7 +296,14 @@ public class MappingRegistry {
NBTTagCompound sub = itemsMapping.getCompoundTagAt(i);
String name = sub.getString("name");
Item item = (Item) Item.itemRegistry.getObject(name);
registerItem (item);
if (item != null) {
registerItem(item);
} else {
// Keeping the order correct
idToItem.add(null);
BCLog.logger.log(Level.WARNING, "Can't load item " + name);
}
}
NBTTagList entitiesMapping = nbt.getTagList("entitiesMapping",
@ -277,7 +320,13 @@ public class MappingRegistry {
e1.printStackTrace();
}
registerEntity (e);
if (e != null) {
registerEntity(e);
} else {
// Keeping the order correct
idToEntity.add(null);
BCLog.logger.log(Level.WARNING, "Can't load entity " + name);
}
}
}
}

View file

@ -109,7 +109,14 @@ public class SchematicBlock extends SchematicBlockBase {
public void readFromNBT(NBTTagCompound nbt, MappingRegistry registry) {
super.readFromNBT(nbt, registry);
block = registry.getBlockForId(nbt.getInteger("blockId"));
try {
block = registry.getBlockForId(nbt.getInteger("blockId"));
} catch (MappingNotFoundException e) {
defaultPermission = BuildingPermission.CREATIVE_ONLY;
return;
}
meta = nbt.getInteger("blockMeta");
if (nbt.hasKey("rq")) {
@ -127,6 +134,8 @@ public class SchematicBlock extends SchematicBlockBase {
} else {
defaultPermission = BuildingPermission.CREATIVE_ONLY;
}
} catch (MappingNotFoundException e) {
defaultPermission = BuildingPermission.CREATIVE_ONLY;
} catch (Throwable t) {
t.printStackTrace();
defaultPermission = BuildingPermission.CREATIVE_ONLY;

View file

@ -82,7 +82,11 @@ public class SchematicEntity extends Schematic {
@Override
public void idsToWorld(MappingRegistry registry) {
registry.scanAndTranslateStacksToWorld(cpt);
try {
registry.scanAndTranslateStacksToWorld(cpt);
} catch (MappingNotFoundException e) {
cpt = new NBTTagCompound();
}
}
@Override

View file

@ -18,13 +18,15 @@ public abstract class SchematicFactory<S extends Schematic> {
private static final HashMap<Class<? extends Schematic>, SchematicFactory> schematicToFactory = new HashMap<Class<? extends Schematic>, SchematicFactory>();
protected abstract S loadSchematicFromWorldNBT (NBTTagCompound nbt, MappingRegistry registry);
protected abstract S loadSchematicFromWorldNBT(NBTTagCompound nbt, MappingRegistry registry)
throws MappingNotFoundException;
public void saveSchematicToWorldNBT (NBTTagCompound nbt, S object, MappingRegistry registry) {
nbt.setString("factoryID", getClass().getCanonicalName());
}
public static Schematic createSchematicFromWorldNBT (NBTTagCompound nbt, MappingRegistry registry) {
public static Schematic createSchematicFromWorldNBT(NBTTagCompound nbt, MappingRegistry registry)
throws MappingNotFoundException {
String factoryName = nbt.getString("factoryID");
if (factories.containsKey(factoryName)) {

View file

@ -35,7 +35,11 @@ public class SchematicTile extends SchematicBlock {
@Override
public void idsToWorld(MappingRegistry registry) {
registry.scanAndTranslateStacksToWorld(cpt);
try {
registry.scanAndTranslateStacksToWorld(cpt);
} catch (MappingNotFoundException e) {
cpt = new NBTTagCompound();
}
}
/**

View file

@ -20,6 +20,7 @@ import net.minecraftforge.common.util.Constants;
import buildcraft.BuildCraftBuilders;
import buildcraft.api.blueprints.IBuilderContext;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.MappingRegistry;
import buildcraft.api.core.NetworkData;
import buildcraft.api.core.Position;
@ -255,7 +256,7 @@ public class BuildingItem implements IBuilder {
nbt.setTag("slotToBuild", slotNBT);
}
public void readFromNBT (NBTTagCompound nbt) {
public void readFromNBT(NBTTagCompound nbt) throws MappingNotFoundException {
origin = new Position(nbt.getCompoundTag("origin"));
destination = new Position (nbt.getCompoundTag("destination"));
lifetime = nbt.getDouble("lifetime");

View file

@ -12,6 +12,7 @@ import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.MappingRegistry;
import buildcraft.api.blueprints.SchematicBlock;
import buildcraft.api.blueprints.SchematicFactory;
@ -20,7 +21,8 @@ import buildcraft.api.blueprints.SchematicRegistry;
public class SchematicFactoryBlock extends SchematicFactory<SchematicBlock> {
@Override
protected SchematicBlock loadSchematicFromWorldNBT (NBTTagCompound nbt, MappingRegistry registry) {
protected SchematicBlock loadSchematicFromWorldNBT(NBTTagCompound nbt, MappingRegistry registry)
throws MappingNotFoundException {
int blockId = nbt.getInteger("blockId");
Block b = registry.getBlockForId(blockId);

View file

@ -10,6 +10,7 @@ package buildcraft.builders.schematics;
import net.minecraft.nbt.NBTTagCompound;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.MappingRegistry;
import buildcraft.api.blueprints.SchematicEntity;
import buildcraft.api.blueprints.SchematicFactory;
@ -18,7 +19,8 @@ import buildcraft.api.blueprints.SchematicRegistry;
public class SchematicFactoryEntity extends SchematicFactory<SchematicEntity> {
@Override
protected SchematicEntity loadSchematicFromWorldNBT (NBTTagCompound nbt, MappingRegistry registry) {
protected SchematicEntity loadSchematicFromWorldNBT(NBTTagCompound nbt, MappingRegistry registry)
throws MappingNotFoundException {
int entityId = nbt.getInteger("entityId");
SchematicEntity s = SchematicRegistry.newSchematicEntity(registry.getEntityForId(entityId));

View file

@ -22,6 +22,7 @@ import net.minecraftforge.common.util.Constants;
import buildcraft.BuildCraftBuilders;
import buildcraft.api.blueprints.BuildingPermission;
import buildcraft.api.blueprints.IBuilderContext;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.SchematicBlock;
import buildcraft.api.blueprints.SchematicEntity;
import buildcraft.api.blueprints.SchematicRegistry;
@ -205,7 +206,14 @@ public class Blueprint extends BlueprintBase {
index++;
if (cpt.hasKey("blockId")) {
Block block = mapping.getBlockForId(cpt.getInteger("blockId"));
Block block;
try {
block = mapping.getBlockForId(cpt.getInteger("blockId"));
} catch (MappingNotFoundException e) {
block = null;
buildingPermission = BuildingPermission.CREATIVE_ONLY;
}
if (block != null) {
contents[x][y][z] = SchematicRegistry.newSchematicBlock(block);
@ -242,7 +250,14 @@ public class Blueprint extends BlueprintBase {
NBTTagCompound cpt = entitiesNBT.getCompoundTagAt(i);
if (cpt.hasKey("entityId")) {
Class<? extends Entity> entity = mapping.getEntityForId(cpt.getInteger("entityId"));
Class<? extends Entity> entity;
try {
entity = mapping.getEntityForId(cpt.getInteger("entityId"));
} catch (MappingNotFoundException e) {
entity = null;
buildingPermission = BuildingPermission.CREATIVE_ONLY;
}
if (entity != null) {
SchematicEntity s = SchematicRegistry.newSchematicEntity(entity);

View file

@ -11,6 +11,7 @@ package buildcraft.core.blueprints;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.TreeSet;
import java.util.logging.Level;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@ -22,7 +23,9 @@ import net.minecraftforge.common.util.Constants;
import buildcraft.BuildCraftBuilders;
import buildcraft.api.blueprints.IBuilderContext;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.SchematicRegistry;
import buildcraft.api.core.BCLog;
import buildcraft.api.core.IAreaProvider;
import buildcraft.api.core.Position;
import buildcraft.builders.BuildingItem;
@ -220,9 +223,14 @@ public abstract class BptBuilderBase implements IAreaProvider {
for (int i = 0; i < buildingList.tagCount(); ++i) {
BuildingItem item = new BuildingItem();
item.readFromNBT(buildingList.getCompoundTagAt(i));
item.context = getContext();
builder.buildersInAction.add(item);
try {
item.readFromNBT(buildingList.getCompoundTagAt(i));
item.context = getContext();
builder.buildersInAction.add(item);
} catch (MappingNotFoundException e) {
BCLog.logger.log(Level.WARNING, "can't load building item", e);
}
}
}
}

View file

@ -14,6 +14,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import buildcraft.api.blueprints.IBuilderContext;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.MappingRegistry;
import buildcraft.api.blueprints.Schematic;
import buildcraft.api.core.Position;
@ -58,7 +59,7 @@ public abstract class BuildingSlot {
public abstract void writeToNBT (NBTTagCompound nbt, MappingRegistry registry);
public abstract void readFromNBT (NBTTagCompound nbt, MappingRegistry registry);
public abstract void readFromNBT(NBTTagCompound nbt, MappingRegistry registry) throws MappingNotFoundException;
public abstract double getEnergyRequirement();
}

View file

@ -18,6 +18,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.Constants;
import buildcraft.api.blueprints.IBuilderContext;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.MappingRegistry;
import buildcraft.api.blueprints.SchematicBlockBase;
import buildcraft.api.blueprints.SchematicFactory;
@ -137,7 +138,7 @@ public class BuildingSlotBlock extends BuildingSlot {
}
@Override
public void readFromNBT (NBTTagCompound nbt, MappingRegistry registry) {
public void readFromNBT(NBTTagCompound nbt, MappingRegistry registry) throws MappingNotFoundException {
mode = Mode.values() [nbt.getByte("mode")];
x = nbt.getInteger("x");
y = nbt.getInteger("y");

View file

@ -13,7 +13,9 @@ import java.util.LinkedList;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import buildcraft.api.blueprints.IBuilderContext;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.MappingRegistry;
import buildcraft.api.blueprints.SchematicEntity;
import buildcraft.api.blueprints.SchematicFactory;
@ -74,7 +76,7 @@ public class BuildingSlotEntity extends BuildingSlot {
}
@Override
public void readFromNBT (NBTTagCompound nbt, MappingRegistry registry) {
public void readFromNBT(NBTTagCompound nbt, MappingRegistry registry) throws MappingNotFoundException {
schematic = (SchematicEntity) SchematicFactory
.createSchematicFromWorldNBT(nbt.getCompoundTag("schematic"), registry);
}

View file

@ -20,6 +20,7 @@ import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.blueprints.BuildingPermission;
import buildcraft.api.blueprints.IBuilderContext;
import buildcraft.api.blueprints.MappingNotFoundException;
import buildcraft.api.blueprints.MappingRegistry;
import buildcraft.api.blueprints.SchematicTile;
import buildcraft.api.gates.ActionManager;
@ -157,9 +158,13 @@ public class SchematicPipe extends SchematicTile {
super.idsToWorld(registry);
if (cpt.hasKey("pipeId")) {
Item item = registry.getItemForId(cpt.getInteger("pipeId"));
try {
Item item = registry.getItemForId(cpt.getInteger("pipeId"));
cpt.setInteger("pipeId", Item.getIdFromItem(item));
cpt.setInteger("pipeId", Item.getIdFromItem(item));
} catch (MappingNotFoundException e) {
cpt.removeTag("pipeId");
}
}
}