Implemented drive models. Fixed issues with the UVL model loader using a null model loader (and thus crashing).

This commit is contained in:
Sebastian Hartte 2016-08-26 13:46:52 +02:00
parent 576923a2f2
commit f3e10b1851
27 changed files with 810 additions and 39 deletions

View File

@ -22,13 +22,19 @@ package appeng.block.storage;
import javax.annotation.Nullable;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import appeng.api.util.AEPartLocation;
import appeng.block.AEBaseTileBlock;
@ -40,6 +46,8 @@ import appeng.util.Platform;
public class BlockDrive extends AEBaseTileBlock
{
public static final DriveSlotsStateProperty SLOTS_STATE = new DriveSlotsStateProperty();
public BlockDrive()
{
super( Material.IRON );
@ -52,6 +60,29 @@ public class BlockDrive extends AEBaseTileBlock
return BlockRenderLayer.CUTOUT;
}
@Override
protected BlockStateContainer createBlockState()
{
return new ExtendedBlockState( this, getAEStates(), new IUnlistedProperty[] {
SLOTS_STATE,
FORWARD,
UP
} );
}
@Override
public IBlockState getExtendedState( IBlockState state, IBlockAccess world, BlockPos pos )
{
TileDrive te = getTileEntity( world, pos );
if( te == null )
{
return super.getExtendedState( state, world, pos );
}
IExtendedBlockState extState = (IExtendedBlockState) super.getExtendedState( state, world, pos );
return extState.withProperty( SLOTS_STATE, DriveSlotsState.fromChestOrDrive( te ) );
}
@Override
public boolean onActivated( final World w, final BlockPos pos, final EntityPlayer p, final EnumHand hand, final @Nullable ItemStack heldItem, final EnumFacing side, final float hitX, final float hitY, final float hitZ )
{

View File

@ -0,0 +1,17 @@
package appeng.block.storage;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
import appeng.client.render.model.DriveModel;
public class DriveRendering extends BlockRenderingCustomizer
{
@Override
public void customize( IBlockRendering rendering, IItemRendering itemRendering )
{
rendering.builtInModel( "models/block/builtin/drive", new DriveModel() );
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
/**
* Describes the different states a single slot of a BlockDrive can be in in terms of rendering.
*/
public enum DriveSlotState
{
// No cell in slot
EMPTY,
// Cell in slot, but unpowered
OFFLINE,
// Online and free space
ONLINE,
// Types full, space left
TYPES_FULL,
// Completely full
FULL
}

View File

@ -0,0 +1,93 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import appeng.api.implementations.tiles.IChestOrDrive;
/**
* Contains the full information about what the state of the slots in a BlockDrive is.
*/
public class DriveSlotsState
{
private final DriveSlotState[] slots;
private DriveSlotsState( DriveSlotState[] slots )
{
this.slots = slots;
}
public DriveSlotState getState( int index )
{
if( index >= slots.length )
{
return DriveSlotState.EMPTY;
}
return slots[index];
}
public int getSlotCount()
{
return slots.length;
}
/**
* Retrieve an array that describes the state of each slot in this drive or chest.
*/
public static DriveSlotsState fromChestOrDrive( IChestOrDrive chestOrDrive )
{
DriveSlotState[] slots = new DriveSlotState[chestOrDrive.getCellCount()];
for( int i = 0; i < chestOrDrive.getCellCount(); i++ )
{
if( !chestOrDrive.isPowered() )
{
if( chestOrDrive.getCellStatus( i ) != 0 )
{
slots[i] = DriveSlotState.OFFLINE;
}
else
{
slots[i] = DriveSlotState.EMPTY;
}
}
else
{
switch( chestOrDrive.getCellStatus( i ) )
{
default:
case 0:
slots[i] = DriveSlotState.EMPTY;
break;
case 1:
slots[i] = DriveSlotState.ONLINE;
break;
case 2:
slots[i] = DriveSlotState.TYPES_FULL;
break;
case 3:
slots[i] = DriveSlotState.FULL;
break;
}
}
}
return new DriveSlotsState( slots );
}
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import net.minecraftforge.common.property.IUnlistedProperty;
public class DriveSlotsStateProperty implements IUnlistedProperty<DriveSlotsState>
{
@Override
public String getName()
{
return "drive_slots_state";
}
@Override
public boolean isValid( DriveSlotsState value )
{
return value != null;
}
@Override
public Class<DriveSlotsState> getType()
{
return DriveSlotsState.class;
}
@Override
public String valueToString( DriveSlotsState value )
{
return value.toString();
}
}

View File

@ -41,7 +41,6 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderLivingEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
@ -356,12 +355,6 @@ public class ClientHelper extends ServerHelper
Minecraft.getMinecraft().effectRenderer.addEffect( fx );
}
@SubscribeEvent
public void onModelBakeEvent( final ModelBakeEvent event )
{
UVLModelLoader.INSTANCE.setLoader( event.getModelLoader() );
}
@SubscribeEvent
public void wheelEvent( final MouseEvent me )
{

View File

@ -0,0 +1,136 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector3f;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import net.minecraftforge.common.property.IExtendedBlockState;
import appeng.block.storage.BlockDrive;
import appeng.block.storage.DriveSlotState;
import appeng.block.storage.DriveSlotsState;
public class DriveBakedModel implements IBakedModel
{
private final IBakedModel bakedBase;
private final Map<DriveSlotState, IBakedModel> bakedCells;
public DriveBakedModel( IBakedModel bakedBase, Map<DriveSlotState, IBakedModel> bakedCells )
{
this.bakedBase = bakedBase;
this.bakedCells = bakedCells;
}
@Override
public List<BakedQuad> getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand )
{
List<BakedQuad> result = new ArrayList<>();
result.addAll( bakedBase.getQuads( state, side, rand ) );
if( side == null && state instanceof IExtendedBlockState )
{
IExtendedBlockState extState = (IExtendedBlockState) state;
DriveSlotsState slotsState = extState.getValue( BlockDrive.SLOTS_STATE );
for( int row = 0; row < 5; row++ )
{
for( int col = 0; col < 2; col++ )
{
DriveSlotState slotState = slotsState.getState( row * 2 + col );
IBakedModel bakedCell = bakedCells.get( slotState );
Matrix4f transform = new Matrix4f();
transform.setIdentity();
// Position this drive model copy at the correct slot. The transform is based on the
// cell-model being in slot 0,0 at the top left of the drive.
float xOffset = -col * 7 / 16.0f;
float yOffset = -row * 3 / 16.0f;
transform.setTranslation( new Vector3f( xOffset, yOffset, 0 ) );
MatrixVertexTransformer transformer = new MatrixVertexTransformer( transform );
for( BakedQuad bakedQuad : bakedCell.getQuads( state, null, rand ) )
{
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( bakedQuad.getFormat() );
transformer.setParent( builder );
transformer.setVertexFormat( builder.getVertexFormat() );
bakedQuad.pipe( transformer );
result.add( builder.build() );
}
}
}
}
return result;
}
@Override
public boolean isAmbientOcclusion()
{
return bakedBase.isAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return bakedBase.isGui3d();
}
@Override
public boolean isBuiltInRenderer()
{
return bakedBase.isGui3d();
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return bakedBase.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return bakedBase.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides()
{
return bakedBase.getOverrides();
}
}

View File

@ -0,0 +1,97 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.model;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import appeng.block.storage.DriveSlotState;
public class DriveModel implements IModel
{
private static final ResourceLocation MODEL_BASE = new ResourceLocation( "appliedenergistics2:block/drive_base" );
private static final Map<DriveSlotState, ResourceLocation> MODELS_CELLS = ImmutableMap.of(
DriveSlotState.EMPTY, new ResourceLocation( "appliedenergistics2:block/drive_cell_empty" ),
DriveSlotState.OFFLINE, new ResourceLocation( "appliedenergistics2:block/drive_cell_off" ),
DriveSlotState.ONLINE, new ResourceLocation( "appliedenergistics2:block/drive_cell_on" ),
DriveSlotState.TYPES_FULL, new ResourceLocation( "appliedenergistics2:block/drive_cell_types_full" ),
DriveSlotState.FULL, new ResourceLocation( "appliedenergistics2:block/drive_cell_full" )
);
@Override
public Collection<ResourceLocation> getDependencies()
{
return ImmutableList.<ResourceLocation>builder().add( MODEL_BASE ).addAll( MODELS_CELLS.values() ).build();
}
@Override
public Collection<ResourceLocation> getTextures()
{
return Collections.emptyList();
}
@Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
EnumMap<DriveSlotState, IBakedModel> cellModels = new EnumMap<>( DriveSlotState.class );
// Load the base model and the model for each cell state.
IModel baseModel;
try
{
baseModel = ModelLoaderRegistry.getModel( MODEL_BASE );
for( DriveSlotState slotState : MODELS_CELLS.keySet() )
{
IModel model = ModelLoaderRegistry.getModel( MODELS_CELLS.get( slotState ) );
cellModels.put( slotState, model.bake( state, format, bakedTextureGetter ) );
}
}
catch( Exception e )
{
throw new RuntimeException( e );
}
IBakedModel bakedBase = baseModel.bake( state, format, bakedTextureGetter );
return new DriveBakedModel( bakedBase, cellModels );
}
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
}
}

View File

@ -55,7 +55,7 @@ final class MatrixVertexTransformer extends QuadGatheringTransformer
VertexFormatElement element = format.getElement( e );
if( element.getUsage() == VertexFormatElement.EnumUsage.POSITION )
{
parent.put( e, transform( quadData[e][v] ) );
parent.put( e, transform( quadData[e][v], element.getElementCount() ) );
}
else if( element.getUsage() == VertexFormatElement.EnumUsage.NORMAL )
{
@ -93,7 +93,7 @@ final class MatrixVertexTransformer extends QuadGatheringTransformer
parent.setTexture( texture );
}
private float[] transform( float[] fs )
private float[] transform( float[] fs, int elemCount )
{
switch( fs.length )
{
@ -113,6 +113,10 @@ final class MatrixVertexTransformer extends QuadGatheringTransformer
};
case 4:
Vector4f vecc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
// Otherwise all translation is lost
if (elemCount == 3) {
vecc.w = 1;
}
vecc.x -= 0.5f;
vecc.y -= 0.5f;
vecc.z -= 0.5f;

View File

@ -6,6 +6,8 @@ import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@ -13,7 +15,6 @@ import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.base.Charsets;
@ -72,6 +73,8 @@ public enum UVLModelLoader implements ICustomModelLoader
private static final Constructor<? extends IModel> vanillaModelWrapper;
private static final Field faceBakery;
private static final Object vanillaLoader;
private static final MethodHandle loaderGetter;
static
{
@ -86,6 +89,14 @@ public enum UVLModelLoader implements ICustomModelLoader
Class clas = Class.forName( ModelLoader.class.getName() + "$VanillaModelWrapper" );
vanillaModelWrapper = clas.getDeclaredConstructor( ModelLoader.class, ResourceLocation.class, ModelBlock.class, boolean.class, ModelBlockAnimation.class );
vanillaModelWrapper.setAccessible( true );
Class<?> vanillaLoaderClass = Class.forName( ModelLoader.class.getName() + "$VanillaLoader" );
Field instanceField = vanillaLoaderClass.getField( "INSTANCE" );
// Static field
vanillaLoader = instanceField.get( null );
Field loaderField = vanillaLoaderClass.getDeclaredField( "loader" );
loaderField.setAccessible( true );
loaderGetter = MethodHandles.lookup().unreflectGetter( loaderField );
}
catch( Exception e )
{
@ -133,16 +144,17 @@ public enum UVLModelLoader implements ICustomModelLoader
}
private IResourceManager resourceManager;
private ModelLoader loader;
public ModelLoader getLoader()
{
return loader;
}
public void setLoader( ModelLoader loader )
{
this.loader = loader;
try
{
return (ModelLoader) loaderGetter.invoke( vanillaLoader );
}
catch( Throwable throwable )
{
throw new RuntimeException( throwable );
}
}
@Override

View File

@ -73,6 +73,7 @@ import appeng.block.storage.BlockDrive;
import appeng.block.storage.BlockIOPort;
import appeng.block.storage.BlockSkyChest;
import appeng.block.storage.BlockSkyChest.SkyChestType;
import appeng.block.storage.DriveRendering;
import appeng.block.storage.SkyChestRenderingCustomizer;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.FeatureFactory;
@ -270,7 +271,11 @@ public final class ApiBlocks implements IBlocks
this.spatialPylon = registry.block( "spatial_pylon", BlockSpatialPylon::new ).features( AEFeature.SpatialIO ).build();
this.spatialIOPort = registry.block( "spatial_ioport", BlockSpatialIOPort::new ).features( AEFeature.SpatialIO ).build();
this.controller = registry.block( "controller", BlockController::new ).features( AEFeature.Channels ).build();
this.drive = registry.block( "drive", BlockDrive::new ).features( AEFeature.StorageCells, AEFeature.MEDrive ).build();
this.drive = registry.block( "drive", BlockDrive::new )
.features( AEFeature.StorageCells, AEFeature.MEDrive )
.useCustomItemModel()
.rendering( new DriveRendering() )
.build();
this.chest = registry.block( "chest", BlockChest::new ).features( AEFeature.StorageCells, AEFeature.MEChest ).build();
this.iface = registry.block( "interface", BlockInterface::new ).build();
this.cellWorkbench = registry.block( "cell_workbench", BlockCellWorkbench::new ).features( AEFeature.StorageCells ).build();

View File

@ -1,20 +1,5 @@
{
"variants": {
"facing=east": {
"model": "appliedenergistics2:drive",
"y": 270
},
"facing=north": {
"model": "appliedenergistics2:drive",
"y": 180
},
"facing=south": {
"model": "appliedenergistics2:drive",
"y": 0
},
"facing=west": {
"model": "appliedenergistics2:drive",
"y": 90
}
}
"variants": {
"normal": { "model": "appliedenergistics2:builtin/drive" }
}
}

View File

@ -693,8 +693,8 @@
}
],
"textures": {
"0": "blocks/BlockDriveSide",
"1": "blocks/BlockDriveFront",
"2": "blocks/BlockDrive"
"0": "blocks/drive_side",
"1": "blocks/drive_front",
"2": "blocks/drive_top"
}
}

View File

@ -0,0 +1,77 @@
{
"parent": "block/block",
"textures": {
"side": "appliedenergistics2:blocks/drive_side",
"bottom": "appliedenergistics2:blocks/drive_bottom",
"top": "appliedenergistics2:blocks/drive_top",
"front": "appliedenergistics2:blocks/drive_front",
"inner": "appliedenergistics2:blocks/drive_bottom"
},
"elements": [
{
"name": "Right Side Panel",
"from": [ 0.0, 1.0, 0.0 ],
"to": [ 2.0, 15.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#inner" },
"south": { "texture": "#side" },
"west": { "texture": "#side" }
}
},
{
"name": "Left Side Panel",
"from": [ 14.0, 1.0, 0.0 ],
"to": [ 16.0, 15.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inner" }
}
},
{
"name": "Back Panel",
"from": [ 2.0, 1.0, 8.0 ],
"to": [ 14.0, 15.0, 16.0 ],
"faces": {
"north": { "texture": "#inner" },
"south": { "texture": "#side" }
}
},
{
"name": "Bottom Panel",
"from": [ 0.0, 0.0, 0.0 ],
"to": [ 16.0, 1.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#side" },
"up": { "texture": "#inner" },
"down": { "texture": "#bottom" }
}
},
{
"name": "Top Panel",
"from": [ 0.0, 15.0, 0.0 ],
"to": [ 16.0, 16.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#side" },
"up": { "texture": "#top" },
"down": { "texture": "#inner" }
}
},
{
"name": "Front Panel",
"from": [ 2.0, 1.0, 0.0 ],
"to": [ 14.0, 15.0, 8.0 ],
"faces": {
"north": { "texture": "#front" }
}
}
]
}

View File

@ -0,0 +1,119 @@
{
"parent": "block/block",
"textures": {
"side": "appliedenergistics2:blocks/drive_side",
"bottom": "appliedenergistics2:blocks/drive_bottom",
"top": "appliedenergistics2:blocks/drive_top",
"front": "appliedenergistics2:blocks/drive_front",
"inner": "appliedenergistics2:blocks/drive_bottom"
},
"elements": [
{
"name": "Right Side Panel",
"from": [ 0.0, 1.0, 0.0 ],
"to": [ 2.0, 15.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#inner" },
"south": { "texture": "#side" },
"west": { "texture": "#side" }
}
},
{
"name": "Left Side Panel",
"from": [ 14.0, 1.0, 0.0 ],
"to": [ 16.0, 15.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#inner" }
}
},
{
"name": "Back Panel",
"from": [ 2.0, 1.0, 8.0 ],
"to": [ 14.0, 15.0, 16.0 ],
"faces": {
"north": { "texture": "#inner" },
"south": { "texture": "#side" }
}
},
{
"name": "Bottom Panel",
"from": [ 0.0, 0.0, 0.0 ],
"to": [ 16.0, 1.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#side" },
"up": { "texture": "#inner" },
"down": { "texture": "#bottom" }
}
},
{
"name": "Top Panel",
"from": [ 0.0, 15.0, 0.0 ],
"to": [ 16.0, 16.0, 16.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#side" },
"south": { "texture": "#side" },
"west": { "texture": "#side" },
"up": { "texture": "#top" },
"down": { "texture": "#inner" }
}
},
{
"name": "Middle Strut",
"from": [ 7.0, 1.0, 0.0 ],
"to": [ 9.0, 15.0, 8.0 ],
"faces": {
"north": { "texture": "#front" },
"east": { "texture": "#inner" },
"west": { "texture": "#inner" }
}
},
{
"name": "Separator",
"from": [ 2.0, 3.0, 1.0 ],
"to": [ 14.0, 4.0, 8.0 ],
"faces": {
"north": { "texture": "#front" },
"up": { "texture": "#inner" },
"down": { "texture": "#inner" }
}
},
{
"name": "Separator",
"from": [ 2.0, 6.0, 1.0 ],
"to": [ 14.0, 7.0, 8.0 ],
"faces": {
"north": { "texture": "#front" },
"up": { "texture": "#inner" },
"down": { "texture": "#inner" }
}
},
{
"name": "Separator",
"from": [ 2.0, 9.0, 1.0 ],
"to": [ 14.0, 10.0, 8.0 ],
"faces": {
"north": { "texture": "#front" },
"up": { "texture": "#inner" },
"down": { "texture": "#inner" }
}
},
{
"name": "Separator",
"from": [ 2.0, 12.0, 1.0 ],
"to": [ 14.0, 13.0, 8.0 ],
"faces": {
"north": { "texture": "#front" },
"up": { "texture": "#inner" },
"down": { "texture": "#inner" }
}
}
]
}

View File

@ -0,0 +1,16 @@
{
"uvlMarker": true,
"textures": {
"front": "appliedenergistics2:blocks/drive_cell_states"
},
"elements": [
{
"name": "Cell Backdrop",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 10, 5, 12] }
}
}
]
}

View File

@ -0,0 +1,24 @@
{
"uvlMarker": true,
"textures": {
"front": "appliedenergistics2:blocks/drive_cell_states"
},
"elements": [
{
"name": "Cell Backdrop",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 8, 5, 10] }
}
},
{
"name": "Cell Light",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 6, 5, 8], "uvlightmap": { "sky": 0.007, "block": 0.007 } }
}
}
]
}

View File

@ -0,0 +1,15 @@
{
"textures": {
"front": "appliedenergistics2:blocks/drive_cell_states"
},
"elements": [
{
"name": "Cell",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 0, 5, 2] }
}
}
]
}

View File

@ -0,0 +1,24 @@
{
"uvlMarker": true,
"textures": {
"front": "appliedenergistics2:blocks/drive_cell_states"
},
"elements": [
{
"name": "Cell Backdrop",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 8, 5, 10] }
}
},
{
"name": "Cell Light",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 2, 5, 4], "uvlightmap": { "sky": 0.007, "block": 0.007 } }
}
}
]
}

View File

@ -0,0 +1,24 @@
{
"uvlMarker": true,
"textures": {
"front": "appliedenergistics2:blocks/drive_cell_states"
},
"elements": [
{
"name": "Cell Backdrop",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 8, 5, 10] }
}
},
{
"name": "Cell Light",
"from": [ 9.0, 13.0, 0.0 ],
"to": [ 14.0, 15.0, 1.0 ],
"faces": {
"north": { "texture": "#front", "uv": [0, 4, 5, 6], "uvlightmap": { "sky": 0.007, "block": 0.007 } }
}
}
]
}

View File

@ -0,0 +1,6 @@
{
"parent": "appliedenergistics2:block/drive_base",
"textures": {
"front": "appliedenergistics2:blocks/drive_front_flat"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B