Reimplemented cable and parts rendering.
This commit is contained in:
@@ -46,7 +46,6 @@ import net.minecraft.world.World;
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.implementations.items.IItemGroup;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.parts.IPartHelper;
|
||||
import appeng.api.parts.IPartItem;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.core.AEConfig;
|
||||
@@ -67,10 +66,8 @@ public final class ItemMultiPart extends AEBaseItem implements IPartItem, IItemG
|
||||
public static ItemMultiPart instance;
|
||||
private final Map<Integer, PartTypeWithVariant> registered;
|
||||
|
||||
public ItemMultiPart( final IPartHelper partHelper )
|
||||
public ItemMultiPart()
|
||||
{
|
||||
Preconditions.checkNotNull( partHelper );
|
||||
|
||||
this.registered = new HashMap<>( INITIAL_REGISTERED_CAPACITY );
|
||||
|
||||
this.setHasSubtypes( true );
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
package appeng.items.parts;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.bootstrap.IItemRendering;
|
||||
import appeng.bootstrap.ItemRenderingCustomizer;
|
||||
import appeng.client.render.StaticItemColor;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import appeng.parts.automation.PlaneConnections;
|
||||
import appeng.parts.automation.PlaneModel;
|
||||
|
||||
|
||||
public class ItemMultipartRendering extends ItemRenderingCustomizer
|
||||
{
|
||||
|
||||
private final PartModels partModels;
|
||||
|
||||
private final ItemMultiPart item;
|
||||
|
||||
public ItemMultipartRendering( ItemMultiPart item )
|
||||
public ItemMultipartRendering( PartModels partModels, ItemMultiPart item )
|
||||
{
|
||||
this.partModels = partModels;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@@ -35,6 +45,52 @@ public class ItemMultipartRendering extends ItemRenderingCustomizer
|
||||
rendering.variants( Arrays.stream( PartType.values() )
|
||||
.flatMap( part -> part.getItemModels().stream() )
|
||||
.collect( Collectors.toList() ) );
|
||||
|
||||
// TODO All of this has to go somewhere else! (I.e. when the part is registered)
|
||||
// Register the built-in models for annihilation planes
|
||||
ResourceLocation annihilationPlaneTexture = new ResourceLocation( AppEng.MOD_ID, "items/part/annihilation_plane" );
|
||||
ResourceLocation annihilationPlaneOnTexture = new ResourceLocation( AppEng.MOD_ID, "parts/annihilation_plane_on" );
|
||||
ResourceLocation identityAnnihilationPlaneTexture = new ResourceLocation( AppEng.MOD_ID, "items/part/identity_annihilation_plane" );
|
||||
ResourceLocation identityAnnihilationPlaneOnTexture = new ResourceLocation( AppEng.MOD_ID, "parts/identity_annihilation_plane_on" );
|
||||
ResourceLocation formationPlaneTexture = new ResourceLocation( AppEng.MOD_ID, "items/part/formation_plane" );
|
||||
ResourceLocation formationPlaneOnTexture = new ResourceLocation( AppEng.MOD_ID, "parts/formation_plane_on" );
|
||||
ResourceLocation sidesTexture = new ResourceLocation( AppEng.MOD_ID, "parts/plane_sides" );
|
||||
ResourceLocation backTexture = new ResourceLocation( AppEng.MOD_ID, "parts/transition_plane_back" );
|
||||
|
||||
List<String> modelNames = new ArrayList<>();
|
||||
|
||||
for( PlaneConnections connection : PlaneConnections.PERMUTATIONS )
|
||||
{
|
||||
PlaneModel model = new PlaneModel( annihilationPlaneTexture, sidesTexture, backTexture, connection );
|
||||
rendering.builtInModel( "models/part/annihilation_plane_" + connection.getFilenameSuffix(), model );
|
||||
modelNames.add( "part/annihilation_plane_" + connection.getFilenameSuffix() );
|
||||
|
||||
model = new PlaneModel( annihilationPlaneOnTexture, sidesTexture, backTexture, connection );
|
||||
rendering.builtInModel( "models/part/annihilation_plane_on_" + connection.getFilenameSuffix(), model );
|
||||
modelNames.add( "part/annihilation_plane_on_" + connection.getFilenameSuffix() );
|
||||
|
||||
model = new PlaneModel( identityAnnihilationPlaneTexture, sidesTexture, backTexture, connection );
|
||||
rendering.builtInModel( "models/part/identity_annihilation_plane_" + connection.getFilenameSuffix(), model );
|
||||
modelNames.add( "part/identity_annihilation_plane_" + connection.getFilenameSuffix() );
|
||||
|
||||
model = new PlaneModel( identityAnnihilationPlaneOnTexture, sidesTexture, backTexture, connection );
|
||||
rendering.builtInModel( "models/part/identity_annihilation_plane_on_" + connection.getFilenameSuffix(), model );
|
||||
modelNames.add( "part/identity_annihilation_plane_on_" + connection.getFilenameSuffix() );
|
||||
|
||||
model = new PlaneModel( formationPlaneTexture, sidesTexture, backTexture, connection );
|
||||
rendering.builtInModel( "models/part/formation_plane_" + connection.getFilenameSuffix(), model );
|
||||
modelNames.add( "part/formation_plane_" + connection.getFilenameSuffix() );
|
||||
|
||||
model = new PlaneModel( formationPlaneOnTexture, sidesTexture, backTexture, connection );
|
||||
rendering.builtInModel( "models/part/formation_plane_on_" + connection.getFilenameSuffix(), model );
|
||||
modelNames.add( "part/formation_plane_on_" + connection.getFilenameSuffix() );
|
||||
|
||||
}
|
||||
|
||||
List<ResourceLocation> partResourceLocs = modelNames.stream()
|
||||
.map( name -> new ResourceLocation( AppEng.MOD_ID, name ) )
|
||||
.collect( Collectors.toList() );
|
||||
partModels.registerModels( partResourceLocs );
|
||||
}
|
||||
|
||||
private ModelResourceLocation getItemMeshDefinition( ItemStack is )
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package appeng.items.parts;
|
||||
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* This annotation is used to mark static fields or static methods that return/contain models used
|
||||
* for a part. They are automatically registered as part of the part item registration.
|
||||
*/
|
||||
@Retention( RetentionPolicy.RUNTIME )
|
||||
@Target( {
|
||||
ElementType.FIELD,
|
||||
ElementType.METHOD
|
||||
} )
|
||||
public @interface PartModels
|
||||
{
|
||||
}
|
||||
@@ -20,9 +20,16 @@ package appeng.items.parts;
|
||||
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -34,6 +41,7 @@ import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.features.AEFeature;
|
||||
import appeng.core.localization.GuiText;
|
||||
@@ -213,6 +221,7 @@ public enum PartType
|
||||
private final Class<? extends IPart> myPart;
|
||||
private final GuiText extraName;
|
||||
private final List<ModelResourceLocation> itemModels;
|
||||
private final Set<ResourceLocation> models;
|
||||
private Constructor<? extends IPart> constructor;
|
||||
|
||||
PartType( final int baseMetaValue, final String name, final Set<AEFeature> features, final Set<IntegrationType> integrations, final Class<? extends IPart> c )
|
||||
@@ -229,6 +238,14 @@ public enum PartType
|
||||
this.myPart = c;
|
||||
this.extraName = en;
|
||||
this.itemModels = createItemModels( name );
|
||||
if( c != null )
|
||||
{
|
||||
this.models = new HashSet<>( createModels( c ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.models = Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
protected List<ModelResourceLocation> createItemModels( String baseName )
|
||||
@@ -295,5 +312,125 @@ public enum PartType
|
||||
{
|
||||
return itemModels;
|
||||
}
|
||||
|
||||
|
||||
public Set<ResourceLocation> getModels()
|
||||
{
|
||||
return models;
|
||||
}
|
||||
|
||||
private List<ResourceLocation> createModels( Class<?> clazz )
|
||||
{
|
||||
List<ResourceLocation> locations = new ArrayList<>( );
|
||||
|
||||
// Check all static fields for used models
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
for( Field field : fields )
|
||||
{
|
||||
if( field.getAnnotation( PartModels.class ) == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if( !Modifier.isStatic( field.getModifiers() ) )
|
||||
{
|
||||
AELog.error( "The @PartModels annotation can only be used on static fields or methods. Was seen on: " + field );
|
||||
continue;
|
||||
}
|
||||
|
||||
Object value;
|
||||
try
|
||||
{
|
||||
field.setAccessible( true );
|
||||
value = field.get( null );
|
||||
}
|
||||
catch( IllegalAccessException e )
|
||||
{
|
||||
AELog.error( e, "Cannot access field annotated with @PartModels: " + field );
|
||||
continue;
|
||||
}
|
||||
|
||||
convertAndAddLocation( field, value, locations );
|
||||
}
|
||||
|
||||
// Check all static methods for the annotation
|
||||
for( Method method : clazz.getDeclaredMethods() )
|
||||
{
|
||||
if( method.getAnnotation( PartModels.class ) == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !Modifier.isStatic( method.getModifiers() ) )
|
||||
{
|
||||
AELog.error( "The @PartModels annotation can only be used on static fields or methods. Was seen on: " + method );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for parameter count
|
||||
if( method.getParameters().length != 0 )
|
||||
{
|
||||
AELog.error( "The @PartModels annotation can only be used on static methods without parameters. Was seen on: " + method );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure we can handle the return type
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if( !ResourceLocation.class.isAssignableFrom( returnType ) && !Collection.class.isAssignableFrom( returnType ) )
|
||||
{
|
||||
AELog.error( "The @PartModels annotation can only be used on static methods that return a ResourceLocation or Collection of "
|
||||
+ "ResourceLocations. Was seen on: " + method );
|
||||
continue;
|
||||
}
|
||||
|
||||
Object value = null;
|
||||
try
|
||||
{
|
||||
method.setAccessible( true );
|
||||
value = method.invoke( null );
|
||||
}
|
||||
catch( IllegalAccessException | InvocationTargetException e )
|
||||
{
|
||||
AELog.error( e, "Failed to invoke the @PartModels annotated method " + method );
|
||||
continue;
|
||||
}
|
||||
|
||||
convertAndAddLocation( method, value, locations );
|
||||
}
|
||||
|
||||
if( clazz.getSuperclass() != null )
|
||||
{
|
||||
locations.addAll( createModels( clazz.getSuperclass() ) );
|
||||
}
|
||||
|
||||
return locations;
|
||||
}
|
||||
|
||||
private void convertAndAddLocation( Object source, Object value, List<ResourceLocation> locations )
|
||||
{
|
||||
if( value == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( value instanceof ResourceLocation )
|
||||
{
|
||||
locations.add( (ResourceLocation) value );
|
||||
}
|
||||
else if( value instanceof Collection )
|
||||
{
|
||||
// Check that each object is a ResourceLocation
|
||||
Collection values = (Collection) value;
|
||||
for( Object candidate : values )
|
||||
{
|
||||
if ( !( candidate instanceof ResourceLocation )) {
|
||||
AELog.error( "List of locations obtained from {} contains a non resource location: {}", source, candidate );
|
||||
continue;
|
||||
}
|
||||
|
||||
locations.add( (ResourceLocation) candidate );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user