Reimplemented cable and parts rendering.
This commit is contained in:
@@ -29,6 +29,7 @@ import appeng.api.storage.IStorageHelper;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
import appeng.core.api.ApiPart;
|
||||
import appeng.core.api.ApiStorage;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import appeng.core.features.registries.RegistryContainer;
|
||||
import appeng.me.GridConnection;
|
||||
import appeng.me.GridNode;
|
||||
@@ -51,7 +52,7 @@ public final class Api implements IAppEngApi
|
||||
this.storageHelper = new ApiStorage();
|
||||
this.registryContainer = new RegistryContainer();
|
||||
this.partHelper = new ApiPart();
|
||||
this.definitions = new ApiDefinitions( this.partHelper );
|
||||
this.definitions = new ApiDefinitions( (PartModels) this.registryContainer.partModels() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,12 +20,12 @@ package appeng.core;
|
||||
|
||||
|
||||
import appeng.api.definitions.IDefinitions;
|
||||
import appeng.api.parts.IPartHelper;
|
||||
import appeng.bootstrap.FeatureFactory;
|
||||
import appeng.core.api.definitions.ApiBlocks;
|
||||
import appeng.core.api.definitions.ApiItems;
|
||||
import appeng.core.api.definitions.ApiMaterials;
|
||||
import appeng.core.api.definitions.ApiParts;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,12 +40,12 @@ public final class ApiDefinitions implements IDefinitions
|
||||
|
||||
private final FeatureFactory registry = new FeatureFactory();
|
||||
|
||||
public ApiDefinitions( final IPartHelper partHelper )
|
||||
public ApiDefinitions( final PartModels partModels )
|
||||
{
|
||||
this.blocks = new ApiBlocks( registry );
|
||||
this.blocks = new ApiBlocks( registry, partModels );
|
||||
this.items = new ApiItems( registry );
|
||||
this.materials = new ApiMaterials( registry );
|
||||
this.parts = new ApiParts( registry, partHelper );
|
||||
this.parts = new ApiParts( registry, partModels );
|
||||
}
|
||||
|
||||
public FeatureFactory getRegistry()
|
||||
|
||||
@@ -20,11 +20,12 @@ package appeng.core;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
@@ -41,6 +42,7 @@ import net.minecraftforge.fml.common.event.FMLServerStoppedEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.core.crash.CrashInfo;
|
||||
import appeng.core.crash.IntegrationCrashEnhancement;
|
||||
import appeng.core.crash.ModCrashEnhancement;
|
||||
@@ -169,6 +171,12 @@ public final class AppEng
|
||||
}
|
||||
|
||||
AELog.info( "Pre Initialization ( ended after " + watch.elapsed( TimeUnit.MILLISECONDS ) + "ms )" );
|
||||
|
||||
// Instantiate all Plugins
|
||||
List<Object> injectables = Lists.newArrayList(
|
||||
AEApi.instance()
|
||||
);
|
||||
new PluginLoader().loadPlugins( injectables, event.getAsmData() );
|
||||
}
|
||||
|
||||
private void startService( final String serviceName, final Thread thread )
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.Random;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.SidedProxy;
|
||||
@@ -60,7 +59,7 @@ public abstract class CommonHelper
|
||||
|
||||
public abstract RayTraceResult getRTR();
|
||||
|
||||
public abstract void doRenderItem( ItemStack itemstack, World w );
|
||||
public abstract void doRenderItem( ItemStack itemstack );
|
||||
|
||||
public abstract void postInit();
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package appeng.core;
|
||||
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable;
|
||||
|
||||
import appeng.api.AEInjectable;
|
||||
import appeng.api.AEPlugin;
|
||||
import appeng.api.exceptions.AppEngException;
|
||||
|
||||
|
||||
/**
|
||||
* Loads AE plugins on startup and provides them with access to various components of the AE API.
|
||||
*/
|
||||
class PluginLoader
|
||||
{
|
||||
|
||||
public void loadPlugins( Collection<Object> injectables, ASMDataTable asmDataTable )
|
||||
{
|
||||
Map<Class<?>, Object> injectableMap = mapInjectables( injectables );
|
||||
findAndInstantiatePlugins( asmDataTable, injectableMap );
|
||||
}
|
||||
|
||||
private static void findAndInstantiatePlugins( ASMDataTable dataTable, Map<Class<?>, Object> injectableMap )
|
||||
{
|
||||
Set<ASMDataTable.ASMData> allAnnotated = dataTable.getAll( AEPlugin.class.getCanonicalName() );
|
||||
|
||||
for( ASMDataTable.ASMData candidate : allAnnotated )
|
||||
{
|
||||
|
||||
Class<?> aClass;
|
||||
try
|
||||
{
|
||||
aClass = Class.forName( candidate.getClassName() );
|
||||
}
|
||||
catch( ClassNotFoundException e )
|
||||
{
|
||||
AELog.error( e, "Couldn't find annotated AE plugin class " + candidate.getClassName() );
|
||||
throw new RuntimeException( "Couldn't find annotated AE plugin class " + candidate.getClassName(), e );
|
||||
}
|
||||
|
||||
// Try instantiating the plugin
|
||||
try
|
||||
{
|
||||
Object plugin = instantiatePlugin( aClass, injectableMap );
|
||||
AELog.info( "Loaded AE2 Plugin {}", plugin.getClass() );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
AELog.error( e, "Unable to instantiate AE plugin " + candidate.getClassName() );
|
||||
throw new RuntimeException( "Unable to instantiate AE plugin " + candidate.getClassName(), e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Object instantiatePlugin( Class<?> aClass, Map<Class<?>, Object> injectableMap ) throws Exception
|
||||
{
|
||||
|
||||
Constructor<?>[] constructors = aClass.getDeclaredConstructors();
|
||||
|
||||
if( constructors.length == 0 )
|
||||
{
|
||||
// This is the default no-arg constructor, although it seems pointless to instantiate anything but not take any AE dependencies as parameters
|
||||
return aClass.newInstance();
|
||||
}
|
||||
else if( constructors.length != 1 )
|
||||
{
|
||||
throw new IllegalArgumentException( "Expected a single constructor, but found: " + constructors.length );
|
||||
}
|
||||
|
||||
Constructor<?> constructor = constructors[0];
|
||||
constructor.setAccessible( true );
|
||||
|
||||
Object[] args = findInjectables( constructor, injectableMap );
|
||||
|
||||
return constructor.newInstance( args );
|
||||
}
|
||||
|
||||
private static Object[] findInjectables( Constructor<?> constructor, Map<Class<?>, Object> injectableMap )
|
||||
{
|
||||
|
||||
Class<?>[] types = constructor.getParameterTypes();
|
||||
Object[] args = new Object[types.length];
|
||||
|
||||
for( int i = 0; i < types.length; i++ )
|
||||
{
|
||||
args[i] = injectableMap.get( types[i] );
|
||||
if( args[i] == null )
|
||||
{
|
||||
throw new IllegalArgumentException( "Constructor has parameter of type " + types[i] + " which is not an injectable type."
|
||||
+ " Please see the documentation for @AEPlugin." );
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
private static Map<Class<?>, Object> mapInjectables( Collection<Object> injectables )
|
||||
{
|
||||
ImmutableMap.Builder<Class<?>, Object> builder = ImmutableMap.builder();
|
||||
|
||||
for( Object injectable : injectables )
|
||||
{
|
||||
// Get all super-interfaces that were annotated with @AEInjectable
|
||||
Set<Class<?>> injectableIfs = getInjectableInterfaces( injectable.getClass() );
|
||||
for( Class<?> injectableIf : injectableIfs )
|
||||
{
|
||||
builder.put( injectableIf, injectable );
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static Set<Class<?>> getInjectableInterfaces( Class<?> aClass )
|
||||
{
|
||||
Set<Class<?>> hierarchy = new HashSet<>();
|
||||
getFullHierarchy( aClass, hierarchy );
|
||||
|
||||
return hierarchy.stream()
|
||||
.filter( c -> c.getAnnotation( AEInjectable.class ) != null )
|
||||
.collect( Collectors.toSet() );
|
||||
}
|
||||
|
||||
// Recursively gather all superclasses and superinterfaces of the given class and put them into the given collection
|
||||
private static void getFullHierarchy( Class<?> aClass, Set<Class<?>> classes )
|
||||
{
|
||||
classes.add( aClass );
|
||||
for( Class<?> anIf : aClass.getInterfaces() )
|
||||
{
|
||||
getFullHierarchy( anIf, classes );
|
||||
}
|
||||
if( aClass.getSuperclass() != null )
|
||||
{
|
||||
getFullHierarchy( aClass.getSuperclass(), classes );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,6 @@ import appeng.api.networking.spatial.ISpatialCache;
|
||||
import appeng.api.networking.storage.IStorageGrid;
|
||||
import appeng.api.networking.ticking.ITickManager;
|
||||
import appeng.api.parts.IPartHelper;
|
||||
import appeng.block.networking.BlockCableBus;
|
||||
import appeng.core.features.AEFeature;
|
||||
import appeng.core.features.registries.P2PTunnelRegistry;
|
||||
import appeng.core.features.registries.entries.BasicCellHandler;
|
||||
@@ -145,7 +144,6 @@ public final class Registration
|
||||
|
||||
// Register all detected handlers and features (items, blocks) in pre-init
|
||||
definitions.getRegistry().getBootstrapComponents().forEach( b -> b.preInitialize( event.getSide() ) );
|
||||
|
||||
}
|
||||
|
||||
private void registerSpatial( final boolean force )
|
||||
@@ -342,7 +340,6 @@ public final class Registration
|
||||
GuiText.values();
|
||||
|
||||
Api.INSTANCE.partHelper().initFMPSupport();
|
||||
blocks.multiPart().maybeBlock().ifPresent( block -> ( (BlockCableBus) block ).setupTile() );
|
||||
|
||||
definitions.getRegistry().getBootstrapComponents().forEach( b -> b.postInitialize( event.getSide() ) );
|
||||
|
||||
|
||||
@@ -57,13 +57,14 @@ import appeng.integration.IntegrationRegistry;
|
||||
import appeng.integration.IntegrationType;
|
||||
import appeng.integration.abstraction.IFMP;
|
||||
import appeng.parts.PartPlacement;
|
||||
import appeng.tile.AEBaseTile;
|
||||
import appeng.tile.networking.TileCableBus;
|
||||
|
||||
|
||||
public class ApiPart implements IPartHelper
|
||||
{
|
||||
|
||||
private final Map<String, Class> tileImplementations = new HashMap<String, Class>();
|
||||
private final Map<String, Class<? extends AEBaseTile>> tileImplementations = new HashMap<>();
|
||||
private final Map<Class<?>, String> interfaces2Layer = new HashMap<Class<?>, String>();
|
||||
private final Map<String, Class> roots = new HashMap<String, Class>();
|
||||
private final List<String> desc = new LinkedList<String>();
|
||||
@@ -79,18 +80,13 @@ public class ApiPart implements IPartHelper
|
||||
}
|
||||
}
|
||||
|
||||
public Class getCombinedInstance( final String base )
|
||||
public Class<? extends AEBaseTile> getCombinedInstance( final Class<? extends AEBaseTile> baseClass )
|
||||
{
|
||||
String base = baseClass.getName();
|
||||
|
||||
if( this.desc.isEmpty() )
|
||||
{
|
||||
try
|
||||
{
|
||||
return Class.forName( base );
|
||||
}
|
||||
catch( final ClassNotFoundException e )
|
||||
{
|
||||
throw new IllegalStateException( e );
|
||||
}
|
||||
return baseClass;
|
||||
}
|
||||
|
||||
final String description = base + ':' + Joiner.on( ";" ).skipNulls().join( this.desc.iterator() );
|
||||
@@ -101,25 +97,8 @@ public class ApiPart implements IPartHelper
|
||||
}
|
||||
|
||||
String f = base;// TileCableBus.class.getName();
|
||||
String Addendum = "";
|
||||
try
|
||||
{
|
||||
Addendum = Class.forName( base ).getSimpleName();
|
||||
}
|
||||
catch( final ClassNotFoundException e )
|
||||
{
|
||||
AELog.debug( e );
|
||||
}
|
||||
Class myCLass;
|
||||
|
||||
try
|
||||
{
|
||||
myCLass = Class.forName( f );
|
||||
}
|
||||
catch( final ClassNotFoundException e )
|
||||
{
|
||||
throw new IllegalStateException( e );
|
||||
}
|
||||
String Addendum = baseClass.getSimpleName();
|
||||
Class<? extends AEBaseTile> myClass = baseClass;
|
||||
|
||||
String path = f;
|
||||
|
||||
@@ -128,21 +107,20 @@ public class ApiPart implements IPartHelper
|
||||
try
|
||||
{
|
||||
final String newPath = path + ';' + name;
|
||||
myCLass = this.getClassByDesc( Addendum, newPath, f, this.interfaces2Layer.get( Class.forName( name ) ) );
|
||||
myClass = this.getClassByDesc( baseClass.getSimpleName(), newPath, f, this.interfaces2Layer.get( Class.forName( name ) ) );
|
||||
path = newPath;
|
||||
}
|
||||
catch( final Throwable t )
|
||||
{
|
||||
AELog.warn( "Error loading " + name );
|
||||
AELog.debug( t );
|
||||
// throw new RuntimeException( t );
|
||||
}
|
||||
f = myCLass.getName();
|
||||
f = myClass.getName();
|
||||
}
|
||||
|
||||
this.tileImplementations.put( description, myCLass );
|
||||
this.tileImplementations.put( description, myClass );
|
||||
|
||||
return myCLass;
|
||||
return myClass;
|
||||
}
|
||||
|
||||
private Class getClassByDesc( final String addendum, final String fullPath, final String root, final String next )
|
||||
|
||||
@@ -23,6 +23,7 @@ import net.minecraft.block.BlockDispenser;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.client.registry.ClientRegistry;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
@@ -85,6 +86,7 @@ import appeng.bootstrap.IItemRendering;
|
||||
import appeng.client.render.model.GlassModel;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.features.AEFeature;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import appeng.debug.BlockChunkloader;
|
||||
import appeng.debug.BlockCubeGenerator;
|
||||
import appeng.debug.BlockItemGen;
|
||||
@@ -101,6 +103,8 @@ import appeng.decorative.solid.BlockSkyStone;
|
||||
import appeng.decorative.solid.BlockSkyStone.SkystoneType;
|
||||
import appeng.decorative.stair.BlockStairCommon;
|
||||
import appeng.hooks.DispenserBehaviorTinyTNT;
|
||||
import appeng.tile.networking.CableBusTESR;
|
||||
import appeng.util.Platform;
|
||||
|
||||
|
||||
/**
|
||||
@@ -184,7 +188,7 @@ public final class ApiBlocks implements IBlocks
|
||||
private final IBlockDefinition phantomNode;
|
||||
private final IBlockDefinition cubeGenerator;
|
||||
|
||||
public ApiBlocks( FeatureFactory registry )
|
||||
public ApiBlocks( FeatureFactory registry, PartModels partModels )
|
||||
{
|
||||
// this.quartzOre = new BlockDefinition( "ore.quartz", new OreQuartz() );
|
||||
this.quartzOre = registry.block( "quartz_ore", BlockQuartzOre::new )
|
||||
@@ -357,8 +361,15 @@ public final class ApiBlocks implements IBlocks
|
||||
this.chiseledQuartzStairs = makeStairs( "chiseled_quartz_stairs", registry, this.chiseledQuartzBlock() );
|
||||
this.quartzPillarStairs = makeStairs( "quartz_pillar_stairs", registry, this.quartzPillar() );
|
||||
|
||||
this.multiPart = registry.block( "multipart_block", BlockCableBus::new )
|
||||
.rendering( new CableBusRendering() )
|
||||
this.multiPart = registry.block( "cable_bus", BlockCableBus::new )
|
||||
.rendering( new CableBusRendering( partModels ) )
|
||||
.postInit( (block, item) -> {
|
||||
( (BlockCableBus) block ).setupTile();
|
||||
if( Platform.isClient() )
|
||||
{
|
||||
ClientRegistry.bindTileEntitySpecialRenderer( BlockCableBus.getTesrTile(), new CableBusTESR() );
|
||||
}
|
||||
} )
|
||||
.build();
|
||||
|
||||
// TODO Re-Add Slabs...
|
||||
|
||||
@@ -22,13 +22,13 @@ package appeng.core.api.definitions;
|
||||
import appeng.api.definitions.IItemDefinition;
|
||||
import appeng.api.definitions.IParts;
|
||||
import appeng.api.exceptions.MissingDefinition;
|
||||
import appeng.api.parts.IPartHelper;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.api.util.AEColoredItemDefinition;
|
||||
import appeng.bootstrap.FeatureFactory;
|
||||
import appeng.core.features.ColoredItemDefinition;
|
||||
import appeng.core.features.DamagedItemDefinition;
|
||||
import appeng.core.features.ItemStackSrc;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import appeng.items.parts.ItemMultiPart;
|
||||
import appeng.items.parts.ItemMultipartRendering;
|
||||
import appeng.items.parts.PartType;
|
||||
@@ -78,13 +78,19 @@ public final class ApiParts implements IParts
|
||||
private final IItemDefinition storageMonitor;
|
||||
private final IItemDefinition conversionMonitor;
|
||||
|
||||
public ApiParts( FeatureFactory registry, IPartHelper partHelper )
|
||||
public ApiParts( FeatureFactory registry, PartModels partModels )
|
||||
{
|
||||
final ItemMultiPart itemMultiPart = new ItemMultiPart( partHelper );
|
||||
final ItemMultiPart itemMultiPart = new ItemMultiPart();
|
||||
registry.item( "multipart", () -> itemMultiPart )
|
||||
.rendering( new ItemMultipartRendering( itemMultiPart ) )
|
||||
.rendering( new ItemMultipartRendering( partModels, itemMultiPart ) )
|
||||
.build();
|
||||
|
||||
// Register all part models
|
||||
for( PartType partType : PartType.values() )
|
||||
{
|
||||
partModels.registerModels( partType.getModels() );
|
||||
}
|
||||
|
||||
this.cableSmart = constructColoredDefinition( itemMultiPart, PartType.CableSmart );
|
||||
this.cableCovered = constructColoredDefinition( itemMultiPart, PartType.CableCovered );
|
||||
this.cableGlass = constructColoredDefinition( itemMultiPart, PartType.CableGlass );
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package appeng.core.features.registries;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import appeng.api.parts.IPartModels;
|
||||
|
||||
|
||||
public class PartModels implements IPartModels
|
||||
{
|
||||
|
||||
private final Set<ResourceLocation> models = new HashSet<>();
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
@Override
|
||||
public void registerModels( Collection<ResourceLocation> partModels )
|
||||
{
|
||||
if( initialized )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot register models after the pre-initialization phase!" );
|
||||
}
|
||||
|
||||
models.addAll( partModels );
|
||||
}
|
||||
|
||||
public Set<ResourceLocation> getModels()
|
||||
{
|
||||
return models;
|
||||
}
|
||||
|
||||
public void setInitialized( boolean initialized )
|
||||
{
|
||||
this.initialized = initialized;
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import appeng.api.features.IWirelessTermRegistry;
|
||||
import appeng.api.features.IWorldGen;
|
||||
import appeng.api.movable.IMovableRegistry;
|
||||
import appeng.api.networking.IGridCacheRegistry;
|
||||
import appeng.api.parts.IPartModels;
|
||||
import appeng.api.storage.ICellRegistry;
|
||||
import appeng.api.storage.IExternalStorageRegistry;
|
||||
|
||||
@@ -59,6 +60,7 @@ public class RegistryContainer implements IRegistryContainer
|
||||
private final IMatterCannonAmmoRegistry matterCannonReg = new MatterCannonAmmoRegistry();
|
||||
private final IPlayerRegistry playerRegistry = new PlayerRegistry();
|
||||
private final IRecipeHandlerRegistry recipeReg = new RecipeHandlerRegistry();
|
||||
private final IPartModels partModels = new PartModels();
|
||||
|
||||
@Override
|
||||
public IMovableRegistry movable()
|
||||
@@ -143,4 +145,11 @@ public class RegistryContainer implements IRegistryContainer
|
||||
{
|
||||
return WorldGenRegistry.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPartModels partModels()
|
||||
{
|
||||
return partModels;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user