211 lines
7.4 KiB
Java
211 lines
7.4 KiB
Java
/**
|
|
* Copyright (c) 2011-2015, 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.core.blueprints;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import net.minecraft.block.Block;
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraftforge.common.config.Configuration;
|
|
import net.minecraftforge.common.config.Property;
|
|
import buildcraft.api.blueprints.ISchematicRegistry;
|
|
import buildcraft.api.blueprints.Schematic;
|
|
import buildcraft.api.blueprints.SchematicBlock;
|
|
import buildcraft.api.blueprints.SchematicEntity;
|
|
import buildcraft.api.core.BCLog;
|
|
import buildcraft.api.core.JavaTools;
|
|
|
|
public final class SchematicRegistry implements ISchematicRegistry {
|
|
|
|
public static SchematicRegistry INSTANCE = new SchematicRegistry();
|
|
private static final HashMap<Class<? extends Schematic>, Constructor<?>> emptyConstructorMap = new HashMap<Class<? extends Schematic>, Constructor<?>>();
|
|
|
|
public final HashMap<String, SchematicConstructor> schematicBlocks =
|
|
new HashMap<String, SchematicConstructor>();
|
|
|
|
public final HashMap<Class<? extends Entity>, SchematicConstructor> schematicEntities = new HashMap<Class<? extends Entity>, SchematicConstructor>();
|
|
|
|
private final HashSet<String> modsForbidden = new HashSet<String>();
|
|
private final HashSet<String> blocksForbidden = new HashSet<String>();
|
|
|
|
private SchematicRegistry() {
|
|
}
|
|
|
|
public class SchematicConstructor {
|
|
public final Class<? extends Schematic> clazz;
|
|
public final Object[] params;
|
|
|
|
private final Constructor<?> constructor;
|
|
|
|
SchematicConstructor(Class<? extends Schematic> clazz, Object[] params) throws IllegalArgumentException {
|
|
this.clazz = clazz;
|
|
this.params = params;
|
|
this.constructor = findConstructor();
|
|
}
|
|
|
|
public Schematic newInstance() throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
|
return (Schematic) constructor.newInstance(params);
|
|
}
|
|
|
|
private Constructor<?> findConstructor() throws IllegalArgumentException {
|
|
if (params.length == 0 && emptyConstructorMap.containsKey(clazz)) {
|
|
return emptyConstructorMap.get(clazz);
|
|
}
|
|
|
|
for (Constructor<?> c : clazz.getConstructors()) {
|
|
Class<?>[] typesSignature = c.getParameterTypes();
|
|
if (typesSignature.length != params.length) {
|
|
// non-matching constructor count arguments, skip
|
|
continue;
|
|
}
|
|
boolean valid = true;
|
|
for (int i = 0; i < params.length; i++) {
|
|
if (params[i] == null) {
|
|
// skip checking for null parameters
|
|
continue;
|
|
}
|
|
Class<?> paramClass = params[i].getClass();
|
|
if (!(typesSignature[i].isAssignableFrom(paramClass)
|
|
|| (typesSignature[i] == int.class && paramClass == Integer.class)
|
|
|| (typesSignature[i] == double.class && paramClass == Double.class)
|
|
|| (typesSignature[i] == boolean.class && paramClass == Boolean.class))) {
|
|
// constructor has non assignable parameters skip constructor...
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!valid) {
|
|
continue;
|
|
}
|
|
if (c != null && params.length == 0) {
|
|
emptyConstructorMap.put(clazz, c);
|
|
}
|
|
return c;
|
|
}
|
|
throw new IllegalArgumentException("Builder: Could not find matching constructor for class " + clazz);
|
|
}
|
|
}
|
|
|
|
public void registerSchematicBlock(Block block, Class<? extends Schematic> clazz, Object... params) {
|
|
for (int i = 0; i < 16; i++) {
|
|
registerSchematicBlock(block, i, clazz, params);
|
|
}
|
|
}
|
|
|
|
public void registerSchematicBlock(Block block, int meta, Class<? extends Schematic> clazz, Object... params) {
|
|
if (block == null || Block.blockRegistry.getNameForObject(block) == null || "null".equals(Block.blockRegistry.getNameForObject(block))) {
|
|
BCLog.logger.warn("Builder: Mod tried to register block '" + (block != null ? block.getClass().getName() : "null") + "' schematic with a null name! Ignoring.");
|
|
return;
|
|
}
|
|
if (schematicBlocks.containsKey(toStringKey(block, meta))) {
|
|
throw new RuntimeException("Builder: Block " + Block.blockRegistry.getNameForObject(block) + " is already associated with a schematic.");
|
|
}
|
|
|
|
schematicBlocks.put(toStringKey(block, meta), new SchematicConstructor(clazz, params));
|
|
}
|
|
|
|
public void registerSchematicEntity(
|
|
Class<? extends Entity> entityClass,
|
|
Class<? extends SchematicEntity> schematicClass, Object... params) {
|
|
if (schematicEntities.containsKey(entityClass)) {
|
|
throw new RuntimeException("Builder: Entity " + entityClass.getName() + " is already associated with a schematic.");
|
|
}
|
|
schematicEntities.put(entityClass, new SchematicConstructor(schematicClass, params));
|
|
}
|
|
|
|
public SchematicBlock createSchematicBlock(Block block, int metadata) {
|
|
if (block == null || metadata < 0 || metadata >= 16) {
|
|
return null;
|
|
}
|
|
|
|
SchematicConstructor c = schematicBlocks.get(toStringKey(block, metadata));
|
|
|
|
if (c == null) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
SchematicBlock s = (SchematicBlock) c.newInstance();
|
|
s.block = block;
|
|
return s;
|
|
} catch (IllegalAccessException e) {
|
|
e.printStackTrace();
|
|
} catch (IllegalArgumentException e) {
|
|
e.printStackTrace();
|
|
} catch (InvocationTargetException e) {
|
|
e.printStackTrace();
|
|
} catch (InstantiationException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public SchematicEntity createSchematicEntity(Class<? extends Entity> entityClass) {
|
|
if (!schematicEntities.containsKey(entityClass)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
SchematicConstructor c = schematicEntities.get(entityClass);
|
|
SchematicEntity s = (SchematicEntity) c.newInstance();
|
|
s.entity = entityClass;
|
|
return s;
|
|
} catch (IllegalAccessException e) {
|
|
e.printStackTrace();
|
|
} catch (IllegalArgumentException e) {
|
|
e.printStackTrace();
|
|
} catch (InvocationTargetException e) {
|
|
e.printStackTrace();
|
|
} catch (InstantiationException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public boolean isSupported(Block block, int metadata) {
|
|
return schematicBlocks.containsKey(toStringKey(block, metadata));
|
|
}
|
|
|
|
public boolean isAllowedForBuilding(Block block, int metadata) {
|
|
String name = Block.blockRegistry.getNameForObject(block);
|
|
return isSupported(block, metadata) && !blocksForbidden.contains(name) && !modsForbidden.contains(name.split(":", 2)[0]);
|
|
}
|
|
|
|
public void readConfiguration(Configuration conf) {
|
|
Property excludedMods = conf.get("blueprints", "excludedMods", new String[0],
|
|
"mods that should be excluded from the builder.").setLanguageKey("config.blueprints.excludedMods").setRequiresMcRestart(true);
|
|
Property excludedBlocks = conf.get("blueprints", "excludedBlocks", new String[0],
|
|
"blocks that should be excluded from the builder.").setLanguageKey("config.blueprints.excludedBlocks").setRequiresMcRestart(true);
|
|
|
|
for (String id : excludedMods.getStringList()) {
|
|
String strippedId = JavaTools.stripSurroundingQuotes(id.trim());
|
|
|
|
if (strippedId.length() > 0) {
|
|
modsForbidden.add(strippedId);
|
|
}
|
|
}
|
|
|
|
for (String id : excludedBlocks.getStringList()) {
|
|
String strippedId = JavaTools.stripSurroundingQuotes(id.trim());
|
|
|
|
if (strippedId.length() > 0) {
|
|
blocksForbidden.add(strippedId);
|
|
}
|
|
}
|
|
}
|
|
|
|
private String toStringKey(Block block, int meta) {
|
|
return Block.blockRegistry.getNameForObject(block) + ":" + meta;
|
|
}
|
|
}
|