Pattern Rendering and other Rendering
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@ yarn_mappings=1.16.1+build.19
|
||||
loader_version=0.8.9+build.203
|
||||
|
||||
#Fabric api
|
||||
fabric_version=0.14.1+build.372-1.16
|
||||
fabric_version=0.15.0+local-indigo-flat-lighting-fix
|
||||
|
||||
loom_version=0.4-SNAPSHOT
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package appeng.block;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import appeng.block.networking.WirelessBlock;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.item.TooltipContext;
|
||||
@@ -84,7 +85,7 @@ public class AEBaseBlockItem extends BlockItem {
|
||||
} else {
|
||||
forward = Direction.UP;
|
||||
}
|
||||
} else if (/* FIXME FABRIC this.blockType instanceof WirelessBlock || */ this.blockType instanceof SkyCompassBlock) {
|
||||
} else if (this.blockType instanceof WirelessBlock || this.blockType instanceof SkyCompassBlock) {
|
||||
forward = side;
|
||||
if (forward == Direction.UP || forward == Direction.DOWN) {
|
||||
up = Direction.SOUTH;
|
||||
|
||||
@@ -152,7 +152,7 @@ public class SkyCompassBlock extends AEBaseTileBlock<SkyCompassBlockEntity> {
|
||||
|
||||
@Override
|
||||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.ENTITYBLOCK_ANIMATED;
|
||||
return BlockRenderType.MODEL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+69
-39
@@ -1,34 +1,38 @@
|
||||
|
||||
package appeng.block.qnb;
|
||||
|
||||
import java.util.Collections;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import appeng.core.Api;
|
||||
import appeng.core.AppEng;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import appeng.core.Api;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.tile.qnb.QuantumBridgeBlockEntity;
|
||||
|
||||
class QnbFormedBakedModel implements IDynamicBakedModel {
|
||||
class QnbFormedBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
private static final SpriteIdentifier TEXTURE_LINK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "block/quantum_link"));
|
||||
@@ -75,23 +79,46 @@ class QnbFormedBakedModel implements IDynamicBakedModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
|
||||
IModelData modelData) {
|
||||
QnbFormedState formedState = modelData.getData(QuantumBridgeBlockEntity.FORMED_STATE);
|
||||
|
||||
if (formedState == null) {
|
||||
return this.baseModel.getQuads(state, side, rand);
|
||||
}
|
||||
|
||||
if (side != null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return this.getQuads(formedState, state);
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<BakedQuad> getQuads(QnbFormedState formedState, BlockState state) {
|
||||
CubeBuilder builder = new CubeBuilder();
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
QnbFormedState formedState = getState(blockView, pos);
|
||||
|
||||
if (formedState == null) {
|
||||
context.fallbackConsumer().accept(this.baseModel);
|
||||
return;
|
||||
}
|
||||
|
||||
buildQuads(context.getEmitter(), formedState, state);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
|
||||
return baseModel.getQuads(state, face, random);
|
||||
}
|
||||
|
||||
private static QnbFormedState getState(BlockRenderView view, BlockPos pos) {
|
||||
if (!(view instanceof RenderAttachedBlockView)) {
|
||||
return null;
|
||||
}
|
||||
Object attachment = ((RenderAttachedBlockView) view).getBlockEntityRenderAttachment(pos);
|
||||
if (attachment instanceof QnbFormedState) {
|
||||
return (QnbFormedState) attachment;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void buildQuads(QuadEmitter emitter, QnbFormedState formedState, BlockState state) {
|
||||
CubeBuilder builder = new CubeBuilder(emitter);
|
||||
|
||||
if (state.getBlock() == this.linkBlock) {
|
||||
Set<Direction> sides = formedState.getAdjacentQuantumBridges();
|
||||
@@ -155,8 +182,6 @@ class QnbFormedBakedModel implements IDynamicBakedModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.getOutput();
|
||||
}
|
||||
|
||||
private void renderCableAt(CubeBuilder builder, float thickness, Sprite texture, float pull,
|
||||
@@ -188,6 +213,11 @@ class QnbFormedBakedModel implements IDynamicBakedModel {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return ModelTransformation.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return this.baseModel.useAmbientOcclusion();
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
package appeng.block.qnb;
|
||||
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
import appeng.core.AppEng;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class QnbFormedModel implements BasicUnbakedModel {
|
||||
|
||||
private static final Identifier MODEL_RING = new Identifier(AppEng.MOD_ID, "block/qnb/ring");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
BakedModel ringModel = loader.bake(MODEL_RING, rotationContainer);
|
||||
return new QnbFormedBakedModel(ringModel, textureGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Identifier> getModelDependencies() {
|
||||
return ImmutableSet.of(MODEL_RING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return QnbFormedBakedModel.getRequiredTextures().stream();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package appeng.client;
|
||||
|
||||
import appeng.api.parts.CableRenderMode;
|
||||
import appeng.block.crafting.AbstractCraftingUnitBlock;
|
||||
import appeng.block.paint.PaintSplotchesModel;
|
||||
import appeng.block.qnb.QnbFormedModel;
|
||||
import appeng.bootstrap.ModelsReloadCallback;
|
||||
import appeng.bootstrap.components.IClientSetupComponent;
|
||||
import appeng.bootstrap.components.IItemColorRegistrationComponent;
|
||||
@@ -8,9 +11,9 @@ import appeng.bootstrap.components.IModelBakeComponent;
|
||||
import appeng.client.gui.implementations.*;
|
||||
import appeng.client.render.SimpleModelLoader;
|
||||
import appeng.client.render.cablebus.CableBusModelLoader;
|
||||
import appeng.client.render.crafting.CraftingCubeModel;
|
||||
import appeng.client.render.effects.*;
|
||||
import appeng.client.render.model.DriveModel;
|
||||
import appeng.client.render.model.SkyCompassModel;
|
||||
import appeng.client.render.model.*;
|
||||
import appeng.client.render.spatial.SpatialPylonModel;
|
||||
import appeng.client.render.tesr.InscriberTESR;
|
||||
import appeng.client.render.tesr.SkyChestTESR;
|
||||
@@ -239,28 +242,29 @@ public final class AppEngClient extends AppEngBase {
|
||||
|
||||
ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> new CableBusModelLoader((PartModels) Api.INSTANCE.registries().partModels()));
|
||||
|
||||
// FIXME FABRIC addBuiltInModel("glass", GlassModel::new);
|
||||
addBuiltInModel("block/quartz_glass", GlassModel::new);
|
||||
addBuiltInModel("block/sky_compass", SkyCompassModel::new);
|
||||
addBuiltInModel("item/sky_compass", SkyCompassModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("item/dummy_fluid_item", DummyFluidItemModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("memory_card", MemoryCardModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("biometric_card", BiometricCardModel::new);
|
||||
addBuiltInModel("item/memory_card", MemoryCardModel::new);
|
||||
addBuiltInModel("item/biometric_card", BiometricCardModel::new);
|
||||
addBuiltInModel("block/drive", DriveModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("color_applicator", ColorApplicatorModel::new);
|
||||
addBuiltInModel("color_applicator", ColorApplicatorModel::new); // FIXME need to wire this up
|
||||
addBuiltInModel("block/spatial_pylon", SpatialPylonModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("paint_splotches", PaintSplotchesModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("quantum_bridge_formed", QnbFormedModel::new);
|
||||
addBuiltInModel("block/paint", PaintSplotchesModel::new);
|
||||
addBuiltInModel("block/qnb/qnb_formed", QnbFormedModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("p2p_tunnel_frequency", P2PTunnelFrequencyModel::new);
|
||||
// FIXME FABRIC addBuiltInModel("facade", FacadeItemModel::new);
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "encoded_pattern"),
|
||||
// FIXME FABRIC EncodedPatternModelLoader.INSTANCE);
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "part_plane"),
|
||||
// FIXME FABRIC PlaneModelLoader.INSTANCE);
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "crafting_cube"),
|
||||
// FIXME FABRIC CraftingCubeModelLoader.INSTANCE);
|
||||
addBuiltInModel("block/crafting/1k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_1K));
|
||||
addBuiltInModel("block/crafting/4k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_4K));
|
||||
addBuiltInModel("block/crafting/16k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_16K));
|
||||
addBuiltInModel("block/crafting/64k_storage_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.STORAGE_64K));
|
||||
addBuiltInModel("block/crafting/accelerator_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.ACCELERATOR));
|
||||
addBuiltInModel("block/crafting/monitor_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.MONITOR));
|
||||
addBuiltInModel("block/crafting/unit_formed", () -> new CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType.UNIT));
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "uvlightmap"), UVLModelLoader.INSTANCE);
|
||||
// FIXME FABRIC ModelLoaderRegistry.registerLoader(new Identifier(AppEng.MOD_ID, "cable_bus"),
|
||||
// FIXME FABRIC new CableBusModelLoader());
|
||||
}
|
||||
|
||||
private static <T extends UnbakedModel> void addBuiltInModel(String id, Supplier<T> modelFactory) {
|
||||
|
||||
+85
-62
@@ -18,21 +18,27 @@
|
||||
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
@@ -45,7 +51,7 @@ import appeng.util.Platform;
|
||||
* the "ring" that frames the multi-block structure and delegates rendering of
|
||||
* the "inner" part of each block to the subclasses of this class.
|
||||
*/
|
||||
abstract class CraftingCubeBakedModel implements IDynamicBakedModel {
|
||||
abstract class CraftingCubeBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
private final Sprite ringCorner;
|
||||
|
||||
@@ -59,61 +65,75 @@ abstract class CraftingCubeBakedModel implements IDynamicBakedModel {
|
||||
this.ringVer = ringVer;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
|
||||
@Nonnull IModelData extraData) {
|
||||
if (side == null) {
|
||||
return Collections.emptyList(); // No generic quads for this model
|
||||
}
|
||||
|
||||
EnumSet<Direction> connections = getConnections(extraData);
|
||||
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
CubeBuilder builder = new CubeBuilder(quads);
|
||||
|
||||
builder.setDrawFaces(EnumSet.of(side));
|
||||
|
||||
// Add the quads for the ring that frames the entire multi-block structure
|
||||
this.addRing(builder, side, connections);
|
||||
|
||||
// Calculate the bounds of the "inner" block that is framed by the border drawn
|
||||
// above
|
||||
float x2 = connections.contains(Direction.EAST) ? 16 : 13.01f;
|
||||
float x1 = connections.contains(Direction.WEST) ? 0 : 2.99f;
|
||||
|
||||
float y2 = connections.contains(Direction.UP) ? 16 : 13.01f;
|
||||
float y1 = connections.contains(Direction.DOWN) ? 0 : 2.99f;
|
||||
|
||||
float z2 = connections.contains(Direction.SOUTH) ? 16 : 13.01f;
|
||||
float z1 = connections.contains(Direction.NORTH) ? 0 : 2.99f;
|
||||
|
||||
// On the axis of the side that we're currently drawing, extend the dimensions
|
||||
// out to the outer face of the block
|
||||
switch (side) {
|
||||
case DOWN:
|
||||
case UP:
|
||||
y1 = 0;
|
||||
y2 = 16;
|
||||
break;
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
z1 = 0;
|
||||
z2 = 16;
|
||||
break;
|
||||
case WEST:
|
||||
case EAST:
|
||||
x1 = 0;
|
||||
x2 = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
this.addInnerCube(side, state, extraData, builder, x1, y1, z1, x2, y2, z2);
|
||||
|
||||
return quads;
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addRing(CubeBuilder builder, @Nullable Direction side, EnumSet<Direction> connections) {
|
||||
@Override
|
||||
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
CraftingCubeModelData modelData = getModelData(blockView, pos);
|
||||
EnumSet<Direction> connections = modelData.getConnections();
|
||||
|
||||
CubeBuilder builder = new CubeBuilder(context.getEmitter());
|
||||
|
||||
for (Direction side : Direction.values()) {
|
||||
builder.setDrawFaces(EnumSet.of(side));
|
||||
|
||||
// Add the quads for the ring that frames the entire multi-block structure
|
||||
this.addRing(builder, side, connections);
|
||||
|
||||
// Calculate the bounds of the "inner" block that is framed by the border drawn
|
||||
// above
|
||||
float x2 = connections.contains(Direction.EAST) ? 16 : 13.01f;
|
||||
float x1 = connections.contains(Direction.WEST) ? 0 : 2.99f;
|
||||
|
||||
float y2 = connections.contains(Direction.UP) ? 16 : 13.01f;
|
||||
float y1 = connections.contains(Direction.DOWN) ? 0 : 2.99f;
|
||||
|
||||
float z2 = connections.contains(Direction.SOUTH) ? 16 : 13.01f;
|
||||
float z1 = connections.contains(Direction.NORTH) ? 0 : 2.99f;
|
||||
|
||||
// On the axis of the side that we're currently drawing, extend the dimensions
|
||||
// out to the outer face of the block
|
||||
switch (side) {
|
||||
case DOWN:
|
||||
case UP:
|
||||
y1 = 0;
|
||||
y2 = 16;
|
||||
break;
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
z1 = 0;
|
||||
z2 = 16;
|
||||
break;
|
||||
case WEST:
|
||||
case EAST:
|
||||
x1 = 0;
|
||||
x2 = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
this.addInnerCube(side, state, modelData, builder, x1, y1, z1, x2, y2, z2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return ModelTransformation.NONE;
|
||||
}
|
||||
|
||||
private void addRing(CubeBuilder builder, Direction side, EnumSet<Direction> connections) {
|
||||
// Fill in the corners
|
||||
builder.setTexture(this.ringCorner);
|
||||
this.addCornerCap(builder, connections, side, Direction.UP, Direction.EAST, Direction.NORTH);
|
||||
@@ -244,15 +264,18 @@ abstract class CraftingCubeBakedModel implements IDynamicBakedModel {
|
||||
|
||||
// Retrieve the cube connection state from the block state
|
||||
// If none is present, just assume there are no adjacent crafting cube blocks
|
||||
private static EnumSet<Direction> getConnections(IModelData modelData) {
|
||||
if (!(modelData instanceof CraftingCubeModelData)) {
|
||||
return EnumSet.noneOf(Direction.class);
|
||||
private static CraftingCubeModelData getModelData(BlockRenderView blockRenderView, BlockPos pos) {
|
||||
if (!(blockRenderView instanceof RenderAttachedBlockView)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((CraftingCubeModelData) modelData).getConnections();
|
||||
Object attached = ((RenderAttachedBlockView) blockRenderView).getBlockEntityRenderAttachment(pos);
|
||||
if (attached instanceof CraftingCubeModelData) {
|
||||
return (CraftingCubeModelData) attached;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract void addInnerCube(Direction facing, BlockState state, IModelData modelData, CubeBuilder builder,
|
||||
protected abstract void addInnerCube(Direction facing, BlockState state, CraftingCubeModelData modelData, CubeBuilder builder,
|
||||
float x1, float y1, float z1, float x2, float y2, float z2);
|
||||
|
||||
@Override
|
||||
+27
-36
@@ -18,32 +18,25 @@
|
||||
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.block.crafting.AbstractCraftingUnitBlock;
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The built-in model for the connected texture crafting cube.
|
||||
*/
|
||||
class CraftingCubeModel implements IModelGeometry<CraftingCubeModel> {
|
||||
public class CraftingCubeModel implements BasicUnbakedModel {
|
||||
|
||||
private final static SpriteIdentifier RING_CORNER = texture("ring_corner");
|
||||
private final static SpriteIdentifier RING_SIDE_HOR = texture("ring_side_hor");
|
||||
@@ -62,41 +55,39 @@ class CraftingCubeModel implements IModelGeometry<CraftingCubeModel> {
|
||||
|
||||
private final AbstractCraftingUnitBlock.CraftingUnitType type;
|
||||
|
||||
CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType type) {
|
||||
public CraftingCubeModel(AbstractCraftingUnitBlock.CraftingUnitType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return ImmutableList.of(RING_CORNER, RING_SIDE_HOR, RING_SIDE_VER, UNIT_BASE, LIGHT_BASE, ACCELERATOR_LIGHT,
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return Stream.of(RING_CORNER, RING_SIDE_HOR, RING_SIDE_VER, UNIT_BASE, LIGHT_BASE, ACCELERATOR_LIGHT,
|
||||
STORAGE_1K_LIGHT, STORAGE_4K_LIGHT, STORAGE_16K_LIGHT, STORAGE_64K_LIGHT, MONITOR_BASE,
|
||||
MONITOR_LIGHT_DARK, MONITOR_LIGHT_MEDIUM, MONITOR_LIGHT_BRIGHT);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
|
||||
ModelOverrideList overrides, Identifier modelLocation) {
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
// Retrieve our textures and pass them on to the baked model
|
||||
Sprite ringCorner = spriteGetter.apply(RING_CORNER);
|
||||
Sprite ringSideHor = spriteGetter.apply(RING_SIDE_HOR);
|
||||
Sprite ringSideVer = spriteGetter.apply(RING_SIDE_VER);
|
||||
Sprite ringCorner = textureGetter.apply(RING_CORNER);
|
||||
Sprite ringSideHor = textureGetter.apply(RING_SIDE_HOR);
|
||||
Sprite ringSideVer = textureGetter.apply(RING_SIDE_VER);
|
||||
|
||||
switch (this.type) {
|
||||
case UNIT:
|
||||
return new UnitBakedModel(ringCorner, ringSideHor, ringSideVer, spriteGetter.apply(UNIT_BASE));
|
||||
return new UnitBakedModel(ringCorner, ringSideHor, ringSideVer, textureGetter.apply(UNIT_BASE));
|
||||
case ACCELERATOR:
|
||||
case STORAGE_1K:
|
||||
case STORAGE_4K:
|
||||
case STORAGE_16K:
|
||||
case STORAGE_64K:
|
||||
return new LightBakedModel(ringCorner, ringSideHor, ringSideVer, spriteGetter.apply(LIGHT_BASE),
|
||||
getLightTexture(spriteGetter, this.type));
|
||||
return new LightBakedModel(ringCorner, ringSideHor, ringSideVer, textureGetter.apply(LIGHT_BASE),
|
||||
getLightTexture(textureGetter, this.type));
|
||||
case MONITOR:
|
||||
return new MonitorBakedModel(ringCorner, ringSideHor, ringSideVer, spriteGetter.apply(UNIT_BASE),
|
||||
spriteGetter.apply(MONITOR_BASE), spriteGetter.apply(MONITOR_LIGHT_DARK),
|
||||
spriteGetter.apply(MONITOR_LIGHT_MEDIUM), spriteGetter.apply(MONITOR_LIGHT_BRIGHT));
|
||||
return new MonitorBakedModel(ringCorner, ringSideHor, ringSideVer, textureGetter.apply(UNIT_BASE),
|
||||
textureGetter.apply(MONITOR_BASE), textureGetter.apply(MONITOR_LIGHT_DARK),
|
||||
textureGetter.apply(MONITOR_LIGHT_MEDIUM), textureGetter.apply(MONITOR_LIGHT_BRIGHT));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported crafting unit type: " + this.type);
|
||||
}
|
||||
+3
-2
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import appeng.tile.crafting.CraftingCubeModelData;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.Direction;
|
||||
@@ -45,8 +46,8 @@ class LightBakedModel extends CraftingCubeBakedModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addInnerCube(Direction facing, BlockState state, IModelData modelData, CubeBuilder builder, float x1,
|
||||
float y1, float z1, float x2, float y2, float z2) {
|
||||
protected void addInnerCube(Direction facing, BlockState state, CraftingCubeModelData modelData, CubeBuilder builder, float x1,
|
||||
float y1, float z1, float x2, float y2, float z2) {
|
||||
builder.setTexture(this.baseTexture);
|
||||
builder.addCube(x1, y1, z1, x2, y2, z2);
|
||||
|
||||
+5
-11
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import appeng.tile.crafting.CraftingCubeModelData;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.Direction;
|
||||
@@ -26,7 +27,6 @@ import net.minecraft.util.math.Direction;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.block.crafting.CraftingMonitorBlock;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import appeng.client.render.model.AEModelData;
|
||||
import appeng.tile.crafting.CraftingMonitorModelData;
|
||||
|
||||
/**
|
||||
@@ -60,9 +60,9 @@ public class MonitorBakedModel extends CraftingCubeBakedModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addInnerCube(Direction side, BlockState state, IModelData modelData, CubeBuilder builder, float x1,
|
||||
float y1, float z1, float x2, float y2, float z2) {
|
||||
Direction forward = getForward(modelData);
|
||||
protected void addInnerCube(Direction side, BlockState state, CraftingCubeModelData modelData, CubeBuilder builder, float x1,
|
||||
float y1, float z1, float x2, float y2, float z2) {
|
||||
Direction forward = modelData.getForward();
|
||||
|
||||
// For sides other than the front, use the chassis texture
|
||||
if (side != forward) {
|
||||
@@ -94,17 +94,11 @@ public class MonitorBakedModel extends CraftingCubeBakedModel {
|
||||
|
||||
}
|
||||
|
||||
private static AEColor getColor(IModelData modelData) {
|
||||
private static AEColor getColor(CraftingCubeModelData modelData) {
|
||||
if (modelData instanceof CraftingMonitorModelData) {
|
||||
return ((CraftingMonitorModelData) modelData).getColor();
|
||||
}
|
||||
return AEColor.TRANSPARENT;
|
||||
}
|
||||
|
||||
private static Direction getForward(IModelData modelData) {
|
||||
if (modelData instanceof AEModelData) {
|
||||
return ((AEModelData) modelData).getForward();
|
||||
}
|
||||
return Direction.NORTH;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import appeng.tile.crafting.CraftingCubeModelData;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.math.Direction;
|
||||
@@ -39,8 +40,8 @@ class UnitBakedModel extends CraftingCubeBakedModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addInnerCube(Direction facing, BlockState state, IModelData modelData, CubeBuilder builder, float x1,
|
||||
float y1, float z1, float x2, float y2, float z2) {
|
||||
protected void addInnerCube(Direction facing, BlockState state, CraftingCubeModelData modelData, CubeBuilder builder, float x1,
|
||||
float y1, float z1, float x2, float y2, float z2) {
|
||||
builder.setTexture(this.unitTexture);
|
||||
builder.addCube(x1, y1, z1, x2, y2, z2);
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import appeng.api.implementations.items.IBiometricCard;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class BiometricCardBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
private final BakedModel baseModel;
|
||||
|
||||
private final Sprite texture;
|
||||
|
||||
BiometricCardBakedModel(BakedModel baseModel, Sprite texture) {
|
||||
this.baseModel = baseModel;
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
// Not intended as a block
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
context.fallbackConsumer().accept(this.baseModel);
|
||||
|
||||
// Get the player's name hash from the card
|
||||
int hash = getHash(stack);
|
||||
|
||||
emitColorCode(context.getEmitter(), hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
return this.baseModel.getQuads(state, side, rand);
|
||||
}
|
||||
|
||||
private void emitColorCode(QuadEmitter emitter, int hash) {
|
||||
CubeBuilder builder = new CubeBuilder(emitter);
|
||||
|
||||
builder.setTexture(this.texture);
|
||||
|
||||
AEColor col = AEColor.values()[Math.abs(3 + hash) % AEColor.values().length];
|
||||
if (hash == 0) {
|
||||
col = AEColor.BLACK;
|
||||
}
|
||||
|
||||
for (int x = 0; x < 8; x++) {
|
||||
for (int y = 0; y < 6; y++) {
|
||||
final boolean isLit;
|
||||
|
||||
// This makes the border always use the darker color
|
||||
if (x == 0 || y == 0 || x == 7 || y == 5) {
|
||||
isLit = false;
|
||||
} else {
|
||||
isLit = (hash & (1 << x)) != 0 || (hash & (1 << y)) != 0;
|
||||
}
|
||||
|
||||
if (isLit) {
|
||||
builder.setColorRGB(col.mediumVariant);
|
||||
} else {
|
||||
final float scale = 0.3f / 255.0f;
|
||||
builder.setColorRGB(((col.blackVariant >> 16) & 0xff) * scale,
|
||||
((col.blackVariant >> 8) & 0xff) * scale, (col.blackVariant & 0xff) * scale);
|
||||
}
|
||||
|
||||
builder.addCube(4 + x, 6 + y, 7.5f, 4 + x + 1, 6 + y + 1, 8.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return this.baseModel.useAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return this.baseModel.hasDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false; // This is an item model
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return this.baseModel.isBuiltin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.baseModel.getSprite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return this.baseModel.getTransformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return ModelOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
private static int getHash(ItemStack stack) {
|
||||
String username = "";
|
||||
if (stack.getItem() instanceof IBiometricCard) {
|
||||
final GameProfile gp = ((IBiometricCard) stack.getItem()).getProfile(stack);
|
||||
if (gp != null) {
|
||||
if (gp.getId() != null) {
|
||||
username = gp.getId().toString();
|
||||
} else {
|
||||
username = gp.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !username.isEmpty() ? username.hashCode() : 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Model wrapper for the biometric card item model, which combines a base card
|
||||
* layer with a "visual hash" of the player name
|
||||
*/
|
||||
public class BiometricCardModel implements BasicUnbakedModel {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/biometric_card_base");
|
||||
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/biometric_card_hash"));
|
||||
|
||||
@Override
|
||||
public Collection<Identifier> getModelDependencies() {
|
||||
return Collections.singleton(MODEL_BASE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return Stream.of(TEXTURE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
Sprite texture = textureGetter.apply(TEXTURE);
|
||||
|
||||
BakedModel baseModel = loader.bake(MODEL_BASE, rotationContainer);
|
||||
|
||||
return new BiometricCardBakedModel(baseModel, texture);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.mixins.BakedQuadAccessor;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
/**
|
||||
* This baked model will take the generated item model for the colored color applicator,
|
||||
* and associate tint indices with the added layers that correspond to the light/medium/dark
|
||||
* variants of the {@link appeng.api.util.AEColor}.
|
||||
* <p>
|
||||
* Using the color provider registered in {@link appeng.items.tools.powered.ColorApplicatorItemRendering},
|
||||
* this results in the right color being multiplied with the corresponding layer.
|
||||
*/
|
||||
class ColorApplicatorBakedModel extends ForwardingBakedModel {
|
||||
|
||||
private final EnumMap<Direction, List<BakedQuad>> quadsBySide;
|
||||
|
||||
private final List<BakedQuad> generalQuads;
|
||||
|
||||
ColorApplicatorBakedModel(BakedModel baseModel, Sprite texDark,
|
||||
Sprite texMedium, Sprite texBright) {
|
||||
this.wrapped = baseModel;
|
||||
|
||||
// Put the tint indices in... Since this is an item model, we are ignoring rand
|
||||
this.generalQuads = this.fixQuadTint(null, texDark, texMedium, texBright);
|
||||
this.quadsBySide = new EnumMap<>(Direction.class);
|
||||
for (Direction facing : Direction.values()) {
|
||||
this.quadsBySide.put(facing, this.fixQuadTint(facing, texDark, texMedium, texBright));
|
||||
}
|
||||
}
|
||||
|
||||
private Sprite getSprite(BakedQuad quad) {
|
||||
return ((BakedQuadAccessor) quad).getSprite();
|
||||
}
|
||||
|
||||
private List<BakedQuad> fixQuadTint(Direction facing, Sprite texDark, Sprite texMedium,
|
||||
Sprite texBright) {
|
||||
List<BakedQuad> quads = this.wrapped.getQuads(null, facing, new Random(0));
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size());
|
||||
for (BakedQuad quad : quads) {
|
||||
int tint;
|
||||
|
||||
if (getSprite(quad) == texDark) {
|
||||
tint = 1;
|
||||
} else if (getSprite(quad) == texMedium) {
|
||||
tint = 2;
|
||||
} else if (getSprite(quad) == texBright) {
|
||||
tint = 3;
|
||||
} else {
|
||||
result.add(quad);
|
||||
continue;
|
||||
}
|
||||
|
||||
BakedQuad newQuad = new BakedQuad(quad.getVertexData(), tint, quad.getFace(), getSprite(quad),
|
||||
quad.hasShade());
|
||||
result.add(newQuad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
if (side == null) {
|
||||
return this.generalQuads;
|
||||
}
|
||||
return this.quadsBySide.get(side);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A color applicator uses the base model, and extends it with additional layers
|
||||
* that are colored according to the selected color of the applicator.
|
||||
*/
|
||||
public class ColorApplicatorModel implements BasicUnbakedModel {
|
||||
|
||||
private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID,
|
||||
"item/color_applicator_colored");
|
||||
|
||||
private static final SpriteIdentifier TEXTURE_DARK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_dark"));
|
||||
private static final SpriteIdentifier TEXTURE_MEDIUM = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_medium"));
|
||||
private static final SpriteIdentifier TEXTURE_BRIGHT = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_bright"));
|
||||
|
||||
@Override
|
||||
public Collection<Identifier> getModelDependencies() {
|
||||
return Collections.singleton(MODEL_BASE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return Stream.of(TEXTURE_DARK, TEXTURE_MEDIUM, TEXTURE_DARK);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
BakedModel baseModel = loader.bake(MODEL_BASE, rotationContainer);
|
||||
|
||||
Sprite texDark = textureGetter.apply(TEXTURE_DARK);
|
||||
Sprite texMedium = textureGetter.apply(TEXTURE_MEDIUM);
|
||||
Sprite texBright = textureGetter.apply(TEXTURE_BRIGHT);
|
||||
|
||||
return new ColorApplicatorBakedModel(baseModel, texDark, texMedium, texBright);
|
||||
}
|
||||
}
|
||||
+96
-123
@@ -18,48 +18,43 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import appeng.decorative.solid.GlassState;
|
||||
import appeng.decorative.solid.QuartzGlassBlock;
|
||||
import com.google.common.base.Strings;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.BlockView;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.VertexFormat;
|
||||
import net.minecraft.client.render.VertexFormatElement;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.BlockRenderView;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
|
||||
import appeng.decorative.solid.GlassState;
|
||||
import appeng.decorative.solid.QuartzGlassBlock;
|
||||
|
||||
class GlassBakedModel implements IDynamicBakedModel {
|
||||
|
||||
// This unlisted property is used to determine the actual block that should be
|
||||
// rendered
|
||||
public static final ModelProperty<GlassState> GLASS_STATE = new ModelProperty<>();
|
||||
class GlassBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
private static final byte[][][] OFFSETS = generateOffsets();
|
||||
|
||||
@@ -75,6 +70,12 @@ class GlassBakedModel implements IDynamicBakedModel {
|
||||
|
||||
// Frame texture
|
||||
static final SpriteIdentifier[] TEXTURES_FRAME = generateTexturesFrame();
|
||||
private final RenderMaterial material = RendererAccess.INSTANCE.getRenderer().materialFinder()
|
||||
.disableDiffuse(0, true)
|
||||
.disableAo(0, true)
|
||||
.disableColorIndex(0, true)
|
||||
.blendMode(0, BlendMode.TRANSLUCENT)
|
||||
.find();
|
||||
|
||||
// Generates the required textures for the frame
|
||||
private static SpriteIdentifier[] generateTexturesFrame() {
|
||||
@@ -101,17 +102,13 @@ class GlassBakedModel implements IDynamicBakedModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
|
||||
IModelData extraData) {
|
||||
if (side == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
final GlassState glassState = extraData.getData(GLASS_STATE);
|
||||
|
||||
if (glassState == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@Override
|
||||
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
final GlassState glassState = getGlassState(blockView, pos);
|
||||
|
||||
// TODO: This could just use the Random instance we're given...
|
||||
final int cx = Math.abs(glassState.getX() % 10);
|
||||
@@ -130,36 +127,51 @@ class GlassBakedModel implements IDynamicBakedModel {
|
||||
|
||||
final Sprite glassTexture = this.glassTextures[texIdx];
|
||||
|
||||
QuadEmitter emitter = context.getEmitter();
|
||||
|
||||
// Render the glass side
|
||||
final List<BakedQuad> quads = new ArrayList<>(5); // At most 5
|
||||
for (Direction side : Direction.values()) {
|
||||
final List<Vector3f> corners = RenderHelper.getFaceCorners(side);
|
||||
this.emitQuad(emitter, side, corners, glassTexture, u, v);
|
||||
|
||||
final List<Vec3d> corners = RenderHelper.getFaceCorners(side);
|
||||
quads.add(this.createQuad(side, corners, glassTexture, u, v));
|
||||
/*
|
||||
* This needs some explanation: The bit-field contains 4-bits, one for each
|
||||
* direction that a frame may be drawn. Converted to a number, the bit-field is
|
||||
* then used as an index into the list of frame textures, which have been
|
||||
* created in such a way that their filenames indicate, in which directions they
|
||||
* contain borders. i.e. bitmask = 0101 means a border should be drawn up and
|
||||
* down (in terms of u,v space). Converted to a number, this bitmask is 5. So
|
||||
* the texture at index 5 is used. That texture had "0101" in its filename to
|
||||
* indicate this.
|
||||
*/
|
||||
final int edgeBitmask = makeBitmask(glassState, side);
|
||||
final Sprite sideSprite = this.frameTextures[edgeBitmask];
|
||||
|
||||
/*
|
||||
* This needs some explanation: The bit-field contains 4-bits, one for each
|
||||
* direction that a frame may be drawn. Converted to a number, the bit-field is
|
||||
* then used as an index into the list of frame textures, which have been
|
||||
* created in such a way that their filenames indicate, in which directions they
|
||||
* contain borders. i.e. bitmask = 0101 means a border should be drawn up and
|
||||
* down (in terms of u,v space). Converted to a number, this bitmask is 5. So
|
||||
* the texture at index 5 is used. That texture had "0101" in its filename to
|
||||
* indicate this.
|
||||
*/
|
||||
final int edgeBitmask = makeBitmask(glassState, side);
|
||||
final Sprite sideSprite = this.frameTextures[edgeBitmask];
|
||||
|
||||
if (sideSprite != null) {
|
||||
quads.add(this.createQuad(side, corners, sideSprite, 0, 0));
|
||||
if (sideSprite != null) {
|
||||
this.emitQuad(emitter, side, corners, sideSprite, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return ModelTransformation.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
// TODO: Forge: Auto-generated method stub
|
||||
return false;
|
||||
return false; // Irrelvant because not used as item model
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,65 +216,31 @@ class GlassBakedModel implements IDynamicBakedModel {
|
||||
return bitmask;
|
||||
}
|
||||
|
||||
private BakedQuad createQuad(Direction side, List<Vec3d> corners, Sprite sprite, float uOffset,
|
||||
private void emitQuad(QuadEmitter emitter, Direction side, List<Vector3f> corners, Sprite sprite, float uOffset,
|
||||
float vOffset) {
|
||||
return this.createQuad(side, corners.get(0), corners.get(1), corners.get(2), corners.get(3), sprite, uOffset,
|
||||
this.emitQuad(emitter, side, corners.get(0), corners.get(1), corners.get(2), corners.get(3), sprite, uOffset,
|
||||
vOffset);
|
||||
}
|
||||
|
||||
private BakedQuad createQuad(Direction side, Vec3d c1, Vec3d c2, Vec3d c3, Vec3d c4, Sprite sprite,
|
||||
private void emitQuad(QuadEmitter emitter, Direction side, Vector3f c1, Vector3f c2, Vector3f c3, Vector3f c4, Sprite sprite,
|
||||
float uOffset, float vOffset) {
|
||||
Vec3d normal = new Vec3d(side.getVector());
|
||||
|
||||
// Apply the u,v shift.
|
||||
// This mirrors the logic from OffsetIcon from 1.7
|
||||
float u1 = MathHelper.clamp(0 - uOffset, 0, 16);
|
||||
float u2 = MathHelper.clamp(16 - uOffset, 0, 16);
|
||||
float v1 = MathHelper.clamp(0 - vOffset, 0, 16);
|
||||
float v2 = MathHelper.clamp(16 - vOffset, 0, 16);
|
||||
float u1 = sprite.getFrameU(MathHelper.clamp(0 - uOffset, 0, 16));
|
||||
float u2 = sprite.getFrameU(MathHelper.clamp(16 - uOffset, 0, 16));
|
||||
float v1 = sprite.getFrameV(MathHelper.clamp(0 - vOffset, 0, 16));
|
||||
float v2 = sprite.getFrameV(MathHelper.clamp(16 - vOffset, 0, 16));
|
||||
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
|
||||
builder.setQuadOrientation(side);
|
||||
this.putVertex(builder, normal, c1.x, c1.y, c1.z, sprite, u1, v1);
|
||||
this.putVertex(builder, normal, c2.x, c2.y, c2.z, sprite, u1, v2);
|
||||
this.putVertex(builder, normal, c3.x, c3.y, c3.z, sprite, u2, v2);
|
||||
this.putVertex(builder, normal, c4.x, c4.y, c4.z, sprite, u2, v1);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is as complicated as it is, because the order in which we push
|
||||
* data into the vertexbuffer actually has to be precisely the order in which
|
||||
* the vertex elements had been declared in the vertex format.
|
||||
*/
|
||||
private void putVertex(BakedQuadBuilder builder, Vec3d normal, double x, double y, double z,
|
||||
Sprite sprite, float u, float v) {
|
||||
VertexFormat vertexFormat = builder.getVertexFormat();
|
||||
for (int e = 0; e < vertexFormat.getElements().size(); e++) {
|
||||
VertexFormatElement el = vertexFormat.getElements().get(e);
|
||||
switch (el.getType()) {
|
||||
case POSITION:
|
||||
builder.put(e, (float) x, (float) y, (float) z, 1.0f);
|
||||
break;
|
||||
case COLOR:
|
||||
builder.put(e, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
break;
|
||||
case NORMAL:
|
||||
builder.put(e, (float) normal.x, (float) normal.y, (float) normal.z, 0f);
|
||||
break;
|
||||
case UV:
|
||||
if (el.getIndex() == 0) {
|
||||
u = sprite.getFrameU(u);
|
||||
v = sprite.getFrameV(v);
|
||||
builder.put(e, u, v, 0f, 1f);
|
||||
break;
|
||||
}
|
||||
// Important: Fall through for getIndex() != 0
|
||||
default:
|
||||
builder.put(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
emitter.nominalFace(side);
|
||||
emitter.cullFace(side);
|
||||
emitter.material(material);
|
||||
emitter.pos(0, c1).sprite(0, 0, u1, v1);
|
||||
emitter.pos(1, c2).sprite(1, 0, u1, v2);
|
||||
emitter.pos(2, c3).sprite(2, 0, u2, v2);
|
||||
emitter.pos(3, c4).sprite(3, 0, u2, v1);
|
||||
emitter.spriteColor(0, -1, -1, -1, -1);
|
||||
emitter.emit();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -304,10 +282,7 @@ class GlassBakedModel implements IDynamicBakedModel {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData(@Nonnull BlockRenderView world, @Nonnull BlockPos pos, @Nonnull BlockState state,
|
||||
@Nonnull IModelData tileData) {
|
||||
|
||||
private static GlassState getGlassState(BlockRenderView world, BlockPos pos) {
|
||||
EnumSet<Direction> flushWith = EnumSet.noneOf(Direction.class);
|
||||
// Test every direction for another glass block
|
||||
for (Direction facing : Direction.values()) {
|
||||
@@ -316,9 +291,7 @@ class GlassBakedModel implements IDynamicBakedModel {
|
||||
}
|
||||
}
|
||||
|
||||
GlassState glassState = new GlassState(pos.getX(), pos.getY(), pos.getZ(), flushWith);
|
||||
return new ModelDataMap.Builder().withInitial(GLASS_STATE, glassState).build();
|
||||
|
||||
return new GlassState(pos.getX(), pos.getY(), pos.getZ(), flushWith);
|
||||
}
|
||||
|
||||
private static boolean isGlassBlock(BlockView world, BlockPos pos, Direction facing) {
|
||||
+13
-20
@@ -18,43 +18,36 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Model class for the connected texture glass model.
|
||||
*/
|
||||
public class GlassModel implements IModelGeometry<GlassModel> {
|
||||
public class GlassModel implements BasicUnbakedModel {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
|
||||
ModelOverrideList overrides, Identifier modelLocation) {
|
||||
return new GlassBakedModel(spriteGetter);
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
return new GlassBakedModel(textureGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return ImmutableSet
|
||||
.<SpriteIdentifier>builder().add(GlassBakedModel.TEXTURE_A, GlassBakedModel.TEXTURE_B,
|
||||
GlassBakedModel.TEXTURE_C, GlassBakedModel.TEXTURE_D)
|
||||
.add(GlassBakedModel.TEXTURES_FRAME).build();
|
||||
.add(GlassBakedModel.TEXTURES_FRAME).build().stream();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import appeng.api.implementations.items.IMemoryCard;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class MemoryCardBakedModel extends ForwardingBakedModel implements FabricBakedModel {
|
||||
private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] { AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
AEColor.TRANSPARENT, };
|
||||
|
||||
private final Sprite texture;
|
||||
|
||||
public MemoryCardBakedModel(BakedModel baseModel, Sprite texture) {
|
||||
this.wrapped = baseModel;
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVanillaAdapter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
|
||||
context.fallbackConsumer().accept(wrapped);
|
||||
|
||||
AEColor[] colorCode = getColorCode(stack);
|
||||
|
||||
CubeBuilder builder = new CubeBuilder(context.getEmitter());
|
||||
|
||||
builder.setTexture(this.texture);
|
||||
|
||||
for (int x = 0; x < 4; x++) {
|
||||
for (int y = 0; y < 2; y++) {
|
||||
final AEColor color = colorCode[x + y * 4];
|
||||
|
||||
builder.setColorRGB(color.mediumVariant);
|
||||
builder.addCube(7 + x, 8 + (1 - y), 7.5f, 7 + x + 1, 8 + (1 - y) + 1, 8.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static AEColor[] getColorCode(ItemStack stack) {
|
||||
if (stack.getItem() instanceof IMemoryCard) {
|
||||
final IMemoryCard memoryCard = (IMemoryCard) stack.getItem();
|
||||
return memoryCard.getColorCode(stack);
|
||||
}
|
||||
|
||||
return DEFAULT_COLOR_CODE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import appeng.client.render.BasicUnbakedModel;
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.ModelBakeSettings;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Model wrapper for the memory card item model, which combines a base card
|
||||
* layer with a "visual hash" of the part/tile.
|
||||
*/
|
||||
public class MemoryCardModel implements BasicUnbakedModel {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/memory_card_base");
|
||||
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/memory_card_hash"));
|
||||
|
||||
@Override
|
||||
public Collection<Identifier> getModelDependencies() {
|
||||
return Collections.singleton(MODEL_BASE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
|
||||
Sprite texture = textureGetter.apply(TEXTURE);
|
||||
|
||||
BakedModel baseModel = loader.bake(MODEL_BASE, rotationContainer);
|
||||
|
||||
return new MemoryCardBakedModel(baseModel, texture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<SpriteIdentifier> getAdditionalTextures() {
|
||||
return Stream.of(TEXTURE);
|
||||
}
|
||||
}
|
||||
+14
-13
@@ -24,47 +24,48 @@ import java.util.List;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
// TODO: Investigate use of CubeBuilder instead
|
||||
final class RenderHelper {
|
||||
|
||||
private static EnumMap<Direction, List<Vec3d>> cornersForFacing = generateCornersForFacings();
|
||||
private static EnumMap<Direction, List<Vector3f>> cornersForFacing = generateCornersForFacings();
|
||||
|
||||
private RenderHelper() {
|
||||
|
||||
}
|
||||
|
||||
static List<Vec3d> getFaceCorners(Direction side) {
|
||||
static List<Vector3f> getFaceCorners(Direction side) {
|
||||
return cornersForFacing.get(side);
|
||||
}
|
||||
|
||||
private static EnumMap<Direction, List<Vec3d>> generateCornersForFacings() {
|
||||
EnumMap<Direction, List<Vec3d>> result = new EnumMap<>(Direction.class);
|
||||
private static EnumMap<Direction, List<Vector3f>> generateCornersForFacings() {
|
||||
EnumMap<Direction, List<Vector3f>> result = new EnumMap<>(Direction.class);
|
||||
|
||||
for (Direction facing : Direction.values()) {
|
||||
List<Vec3d> corners;
|
||||
List<Vector3f> corners;
|
||||
|
||||
float offset = (facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ? 0 : 1;
|
||||
float offset = (facing.getDirection() == Direction.AxisDirection.NEGATIVE) ? 0 : 1;
|
||||
|
||||
switch (facing.getAxis()) {
|
||||
default:
|
||||
case X:
|
||||
corners = Lists.newArrayList(new Vec3d(offset, 1, 1), new Vec3d(offset, 0, 1),
|
||||
new Vec3d(offset, 0, 0), new Vec3d(offset, 1, 0));
|
||||
corners = Lists.newArrayList(new Vector3f(offset, 1, 1), new Vector3f(offset, 0, 1),
|
||||
new Vector3f(offset, 0, 0), new Vector3f(offset, 1, 0));
|
||||
break;
|
||||
case Y:
|
||||
corners = Lists.newArrayList(new Vec3d(1, offset, 1), new Vec3d(1, offset, 0),
|
||||
new Vec3d(0, offset, 0), new Vec3d(0, offset, 1));
|
||||
corners = Lists.newArrayList(new Vector3f(1, offset, 1), new Vector3f(1, offset, 0),
|
||||
new Vector3f(0, offset, 0), new Vector3f(0, offset, 1));
|
||||
break;
|
||||
case Z:
|
||||
corners = Lists.newArrayList(new Vec3d(0, 1, offset), new Vec3d(0, 0, offset),
|
||||
new Vec3d(1, 0, offset), new Vec3d(1, 1, offset));
|
||||
corners = Lists.newArrayList(new Vector3f(0, 1, offset), new Vector3f(0, 0, offset),
|
||||
new Vector3f(1, 0, offset), new Vector3f(1, 1, offset));
|
||||
break;
|
||||
}
|
||||
|
||||
if (facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) {
|
||||
if (facing.getDirection() == Direction.AxisDirection.NEGATIVE) {
|
||||
corners = Lists.reverse(corners);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,6 @@ package appeng.client.render.model;
|
||||
|
||||
import appeng.hooks.CompassManager;
|
||||
import appeng.hooks.CompassResult;
|
||||
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.minecraft.block.BlockState;
|
||||
@@ -47,7 +43,6 @@ import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@@ -85,30 +80,18 @@ public class SkyCompassBakedModel implements BakedModel, FabricBakedModel {
|
||||
|
||||
@Override
|
||||
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
|
||||
MeshBuilder mb = RendererAccess.INSTANCE.getRenderer().meshBuilder();
|
||||
mb.getEmitter().square(Direction.UP, 0, 0, 1, 1, 0).emit();
|
||||
Mesh build = mb.build();
|
||||
context.meshConsumer().accept(build);
|
||||
|
||||
float rotation = getAnimatedRotation(pos, false);
|
||||
emitQuads(context, rotation);
|
||||
// Pre-compute the quad count to avoid list resizes
|
||||
context.fallbackConsumer().accept(this.base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
// This is used to render a compass pointing in a specific direction when being
|
||||
// held in hand
|
||||
emitQuads(context, this.fallbackRotation);
|
||||
}
|
||||
|
||||
private void emitQuads(RenderContext context, float rotation) {
|
||||
// Pre-compute the quad count to avoid list resizes
|
||||
context.fallbackConsumer().accept(this.base);
|
||||
context.fallbackConsumer().accept(base);
|
||||
|
||||
// This is used to render a compass pointing in a specific direction when being held in hand
|
||||
// Set up the rotation around the Y-axis for the pointer
|
||||
context.pushTransform(quad -> {
|
||||
Quaternion quaternion = new Quaternion(0, rotation, 0, false);
|
||||
Quaternion quaternion = new Quaternion(0, this.fallbackRotation, 0, false);
|
||||
Vector3f pos = new Vector3f();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
quad.copyPos(i, pos);
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ItemRenderable<T extends BlockEntity> implements Renderable<T> {
|
||||
if (pair != null && pair.getLeft() != null) {
|
||||
matrixStack.push();
|
||||
if (pair.getRight() != null) {
|
||||
pair.getRight().apply(true, matrixStack); // FIXME: check left handed
|
||||
pair.getRight().apply(false, matrixStack); // FIXME: check left handed
|
||||
}
|
||||
MinecraftClient.getInstance().getItemRenderer().renderItem(pair.getLeft(),
|
||||
ModelTransformation.Mode.GROUND, combinedLight, combinedOverlay, matrixStack, buffers);
|
||||
|
||||
@@ -67,7 +67,6 @@ public class SkyCompassTESR extends BlockEntityRenderer<SkyCompassBlockEntity> {
|
||||
return;
|
||||
}
|
||||
|
||||
BakedModel baseModel = skyCompassModel.getBase();
|
||||
BakedModel pointerModel = skyCompassModel.getPointer();
|
||||
|
||||
Direction forward = te.getForward();
|
||||
@@ -78,17 +77,14 @@ public class SkyCompassTESR extends BlockEntityRenderer<SkyCompassBlockEntity> {
|
||||
if (forward == Direction.UP || forward == Direction.DOWN) {
|
||||
up = Direction.NORTH;
|
||||
}
|
||||
// Flip forward/up for rendering, the base model is facing up without any
|
||||
// rotation
|
||||
ms.push();
|
||||
|
||||
VertexConsumer buffer = buffers.getBuffer(RenderLayer.getSolid());
|
||||
|
||||
modelRenderer.render(te.getWorld(), model, blockState, te.getPos(), ms, buffer, false, new Random(), 42L, combinedOverlayIn);
|
||||
// modelRenderer.render(ms.peek(), buffer, null, baseModel, 1, 1, 1, combinedLightIn, combinedOverlayIn);
|
||||
|
||||
float rotation = getRotation(te);
|
||||
ms.translate(0.5D, 0.5D, 0.5D);
|
||||
// Flip forward/up for rendering, the base model
|
||||
// is facing up without any rotation
|
||||
FacingToRotation.get(up, forward).push(ms);
|
||||
ms.multiply(new Quaternion(0, rotation, 0, false));
|
||||
ms.translate(-0.5D, -0.5D, -0.5D);
|
||||
|
||||
@@ -43,6 +43,8 @@ import static appeng.block.crafting.AbstractCraftingUnitBlock.CraftingUnitType;
|
||||
import appeng.bootstrap.components.IInitComponent;
|
||||
import appeng.bootstrap.definitions.TileEntityDefinition;
|
||||
import appeng.client.render.crafting.CraftingCubeRendering;
|
||||
import appeng.client.render.crafting.CraftingMonitorTESR;
|
||||
import appeng.client.render.crafting.MonitorBakedModel;
|
||||
import appeng.client.render.model.AutoRotatingBakedModel;
|
||||
import appeng.client.render.spatial.SpatialPylonRendering;
|
||||
import appeng.client.render.tesr.ChestTileEntityRenderer;
|
||||
@@ -465,7 +467,7 @@ public final class ApiBlocks implements IBlocks {
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Override
|
||||
public void customize(TileEntityRendering<CraftingMonitorBlockEntity> rendering) {
|
||||
// FIXME FABRIC rendering.tileEntityRenderer(CraftingMonitorTESR::new);
|
||||
rendering.tileEntityRenderer(CraftingMonitorTESR::new);
|
||||
}
|
||||
}).build())
|
||||
.rendering(new BlockRenderingCustomizer() {
|
||||
@@ -475,9 +477,9 @@ public final class ApiBlocks implements IBlocks {
|
||||
rendering.renderType(RenderLayer.getCutout());
|
||||
rendering.modelCustomizer((path, model) -> {
|
||||
// The formed model handles rotations itself, the unformed one does not
|
||||
// FIXME FABRIC if (model instanceof MonitorBakedModel) {
|
||||
// FIXME FABRIC return model;
|
||||
// FIXME FABRIC }
|
||||
if (model instanceof MonitorBakedModel) {
|
||||
return model;
|
||||
}
|
||||
return new AutoRotatingBakedModel(model);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public final class BlockToolDispenseItemBehavior extends ItemDispenserBehavior {
|
||||
if (w instanceof ServerWorld) {
|
||||
ItemUsageContext context = new AutomaticItemPlacementContext(w, dispenser.getBlockPos().offset(direction),
|
||||
direction, dispensedItem, direction.getOpposite());
|
||||
tm.onItemUse(context);
|
||||
tm.useOnBlock(context);
|
||||
}
|
||||
}
|
||||
return dispensedItem;
|
||||
|
||||
@@ -23,6 +23,6 @@ import net.minecraft.util.ActionResult;
|
||||
|
||||
public interface IBlockTool {
|
||||
// Workaround for dispenser logic.
|
||||
ActionResult onItemUse(ItemUsageContext itemUseContext);
|
||||
ActionResult useOnBlock(ItemUsageContext itemUseContext);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package appeng.hooks;
|
||||
|
||||
import appeng.items.misc.EncodedPatternItem;
|
||||
import appeng.mixins.ItemRendererAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public final class ItemRendererHooks {
|
||||
|
||||
// Prevents recursion in the hook below
|
||||
private static final ThreadLocal<ItemStack> OVERRIDING_FOR = new ThreadLocal<>();
|
||||
|
||||
private ItemRendererHooks() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook will exchange the rendered item model for encoded patterns to the item being crafted by them
|
||||
* if shift is held.
|
||||
*/
|
||||
public static boolean onRenderGuiItemModel(ItemRenderer renderer, ItemStack stack, int x, int y, BakedModel model) {
|
||||
if (stack.getItem() instanceof EncodedPatternItem && OVERRIDING_FOR.get() != stack) {
|
||||
boolean shiftHeld = Screen.hasShiftDown();
|
||||
ClientWorld world = MinecraftClient.getInstance().world;
|
||||
if (shiftHeld && world != null) {
|
||||
EncodedPatternItem iep = (EncodedPatternItem) stack.getItem();
|
||||
ItemStack output = iep.getOutput(world, stack);
|
||||
if (!output.isEmpty()) {
|
||||
BakedModel realModel = MinecraftClient.getInstance().getItemRenderer().getModels()
|
||||
.getModel(output);
|
||||
ItemRendererAccessor self = (ItemRendererAccessor) renderer;
|
||||
OVERRIDING_FOR.set(stack);
|
||||
try {
|
||||
self.callRenderGuiItemModel(stack, x, y, realModel);
|
||||
} finally {
|
||||
OVERRIDING_FOR.remove();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,7 +35,6 @@ import appeng.api.util.DimensionalCoord;
|
||||
import appeng.block.networking.CableBusBlock;
|
||||
import appeng.block.paint.PaintSplotchesBlock;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.core.Api;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.helpers.IMouseWheelItem;
|
||||
@@ -118,7 +117,7 @@ public class ColorApplicatorItem extends AEBasePoweredItem
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult onItemUse(ItemUsageContext context) {
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
World w = context.getWorld();
|
||||
BlockPos pos = context.getBlockPos();
|
||||
ItemStack is = context.getStack();
|
||||
|
||||
@@ -219,7 +219,7 @@ public class EntropyManipulatorItem extends AEBasePoweredItem implements IBlockT
|
||||
if (state.getMaterial() == Material.LAVA || state.getMaterial() == Material.WATER) {
|
||||
if (Platform.hasPermissions(new DimensionalCoord(w, pos), p)) {
|
||||
ItemUsageContext context = new ItemUsageContext(p, hand, target);
|
||||
this.onItemUse(context);
|
||||
this.useOnBlock(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,7 +228,7 @@ public class EntropyManipulatorItem extends AEBasePoweredItem implements IBlockT
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult onItemUse(ItemUsageContext context) {
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
World w = context.getWorld();
|
||||
ItemStack item = context.getStack();
|
||||
BlockPos pos = context.getBlockPos();
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package appeng.mixins;
|
||||
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(BakedQuad.class)
|
||||
public interface BakedQuadAccessor {
|
||||
|
||||
@Accessor
|
||||
Sprite getSprite();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package appeng.mixins;
|
||||
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(ItemRenderer.class)
|
||||
public interface ItemRendererAccessor {
|
||||
|
||||
@Invoker
|
||||
void callRenderGuiItemModel(ItemStack stack, int x, int y, BakedModel model);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package appeng.mixins;
|
||||
|
||||
import appeng.hooks.ItemRendererHooks;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* This mixin specifically targets rendering of items in the user interface to allow us to
|
||||
* customize _only_ the UI representation of an item, and none of the others (held items, in-world, etc.)
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class RenderEncodedPatternMixin {
|
||||
|
||||
@Inject(method = "renderGuiItemModel", at = @At("HEAD"), cancellable = true)
|
||||
protected void renderGuiItemModel(ItemStack stack, int x, int y, BakedModel model, CallbackInfo ci) {
|
||||
if (ItemRendererHooks.onRenderGuiItemModel((ItemRenderer) (Object) this, stack, x, y, model)) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,9 @@
|
||||
package appeng.tile.inventory;
|
||||
|
||||
import alexiil.mc.lib.attributes.Simulation;
|
||||
import alexiil.mc.lib.attributes.item.FixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.LimitedFixedItemInv;
|
||||
import alexiil.mc.lib.attributes.item.compat.FixedInventoryVanillaWrapper;
|
||||
import alexiil.mc.lib.attributes.item.filter.ConstantItemFilter;
|
||||
import alexiil.mc.lib.attributes.item.filter.ItemFilter;
|
||||
import alexiil.mc.lib.attributes.item.impl.DirectFixedItemInv;
|
||||
@@ -61,6 +64,29 @@ public class AppEngInternalInventory extends DirectFixedItemInv implements Itera
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public FixedItemInv createFiltered(IAEItemFilter filter) {
|
||||
LimitedFixedItemInv limitedFixedInv = this.createLimitedFixedInv();
|
||||
for (int i = 0; i < getSlotCount(); i++) {
|
||||
final int slot = i;
|
||||
limitedFixedInv.getRule(i)
|
||||
.filterExtracts(stack -> filter.allowExtract(this, slot, stack.getCount()));
|
||||
limitedFixedInv.getRule(i)
|
||||
.filterInserts(stack -> {
|
||||
if (stack.isEmpty()) {
|
||||
ItemStack current = this.getInvStack(slot);
|
||||
if (current.isEmpty()) {
|
||||
return true; // Replacing empty with empty... okay
|
||||
}
|
||||
return filter.allowExtract(this, slot, current.getCount());
|
||||
} else {
|
||||
return filter.allowInsert(this, slot, stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return limitedFixedInv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmount(int slot, ItemStack stack) {
|
||||
return Math.min(maxStack[slot], super.getMaxAmount(slot, stack));
|
||||
|
||||
@@ -61,7 +61,9 @@ public class ChargerBlockEntity extends AENetworkPowerBlockEntity implements ICr
|
||||
private static final int POWER_THRESHOLD = POWER_MAXIMUM_AMOUNT - 1;
|
||||
private static final int POWER_PER_CRANK_TURN = 160;
|
||||
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 1, 1, new ChargerInvFilter());
|
||||
private final AppEngInternalInventory inv = new AppEngInternalInventory(this, 1, 1);
|
||||
|
||||
private final FixedItemInv externalInv = inv.createFiltered(new ChargerInvFilter());
|
||||
|
||||
public ChargerBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
|
||||
super(tileEntityTypeIn);
|
||||
@@ -134,7 +136,7 @@ public class ChargerBlockEntity extends AENetworkPowerBlockEntity implements ICr
|
||||
|
||||
@Override
|
||||
public FixedItemInv getInternalInventory() {
|
||||
return this.inv;
|
||||
return externalInv;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.tile.misc;
|
||||
|
||||
import appeng.client.render.model.AEModelData;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
|
||||
import appeng.tile.AEBaseBlockEntity;
|
||||
@@ -28,4 +29,9 @@ public class SkyCompassBlockEntity extends AEBaseBlockEntity {
|
||||
super(tileEntityTypeIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderAttachmentData() {
|
||||
// For compasses, the forward/up are flipped
|
||||
return new AEModelData(getForward(), getUp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ import net.minecraft.util.math.Direction;
|
||||
*/
|
||||
public abstract class InventoryAdaptor implements Iterable<ItemSlot> {
|
||||
public static InventoryAdaptor getAdaptor(final BlockEntity te, final Direction d) {
|
||||
FixedItemInv inv = ItemAttributes.FIXED_INV.get(te.getWorld(), te.getPos().offset(d), SearchOptions.inDirection(d.getOpposite()));
|
||||
FixedItemInv inv = ItemAttributes.FIXED_INV.get(te.getWorld(), te.getPos(), SearchOptions.inDirection(d.getOpposite()));
|
||||
|
||||
if (inv == ItemAttributes.FIXED_INV.defaultValue) {
|
||||
return null;
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
"client": [
|
||||
"ModelsReloadMixin",
|
||||
"RenderPhaseMixin",
|
||||
"BakedModelManagerAccessor"
|
||||
"BakedModelManagerAccessor",
|
||||
"RenderEncodedPatternMixin",
|
||||
"ItemRendererAccessor"
|
||||
],
|
||||
"server": [],
|
||||
"injectors": {
|
||||
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:crafting_cube",
|
||||
"type": "storage_16k"
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:crafting_cube",
|
||||
"type": "storage_1k"
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:crafting_cube",
|
||||
"type": "storage_4k"
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:crafting_cube",
|
||||
"type": "storage_64k"
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:crafting_cube",
|
||||
"type": "accelerator"
|
||||
}
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:crafting_cube",
|
||||
"type": "monitor"
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:crafting_cube",
|
||||
"type": "unit"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:paint_splotches"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:quantum_bridge_formed"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:glass"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:biometric_card"
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:encoded_pattern",
|
||||
"baseModel": "appliedenergistics2:item/encoded_pattern_base"
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "appliedenergistics2:item/encoded_pattern"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "appliedenergistics2:item/encoded_pattern"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"loader": "appliedenergistics2:memory_card"
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
{
|
||||
"parent": "appliedenergistics2:block/paint"
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
|
||||
package appeng.block.qnb;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
public class QnbFormedModel implements IModelGeometry<QnbFormedModel> {
|
||||
|
||||
private static final Identifier MODEL_RING = new Identifier(AppEng.MOD_ID, "block/qnb/ring");
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
|
||||
ModelOverrideList overrides, Identifier modelLocation) {
|
||||
BakedModel ringModel = bakery.getBakedModel(MODEL_RING, modelTransform, spriteGetter);
|
||||
return new QnbFormedBakedModel(ringModel, spriteGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return QnbFormedBakedModel.getRequiredTextures();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,7 +42,7 @@ import appeng.core.AppEng;
|
||||
* The model class for facades. Since facades wrap existing models, they don't
|
||||
* declare any dependencies here other than the cable anchor.
|
||||
*/
|
||||
public class DummyFluidItemModel implements IModelGeometry<DummyFluidItemModel> {
|
||||
public class DummyFluidItemModel implements BasicUnbakedModel {
|
||||
// We use this to get the default item transforms and make our lives easier
|
||||
private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID,
|
||||
"item/dummy_fluid_item_base");
|
||||
|
||||
@@ -39,7 +39,7 @@ import appeng.core.AppEng;
|
||||
* The model class for facades. Since facades wrap existing models, they don't
|
||||
* declare any dependencies here other than the cable anchor.
|
||||
*/
|
||||
public class FacadeItemModel implements IModelGeometry<FacadeItemModel> {
|
||||
public class FacadeItemModel implements BasicUnbakedModel {
|
||||
|
||||
// We use this to get the default item transforms and make our lives easier
|
||||
private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/facade_base");
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
public class P2PTunnelFrequencyModel implements IModelGeometry<P2PTunnelFrequencyModel> {
|
||||
public class P2PTunnelFrequencyModel implements BasicUnbakedModel {
|
||||
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "parts/p2p_tunnel_frequency"));
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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.crafting;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraftforge.client.model.IModelLoader;
|
||||
|
||||
import appeng.block.crafting.AbstractCraftingUnitBlock;
|
||||
|
||||
/**
|
||||
* Loader that allows access to the built-in crafting cube model from
|
||||
* block-model JSONs.
|
||||
*/
|
||||
public class CraftingCubeModelLoader implements IModelLoader<CraftingCubeModel> {
|
||||
|
||||
public static final CraftingCubeModelLoader INSTANCE = new CraftingCubeModelLoader();
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftingCubeModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
|
||||
AbstractCraftingUnitBlock.CraftingUnitType unitType = null;
|
||||
|
||||
JsonElement typeEl = modelContents.get("type");
|
||||
if (typeEl != null) {
|
||||
String typeName = deserializationContext.deserialize(typeEl, String.class);
|
||||
if (typeName != null) {
|
||||
unitType = AbstractCraftingUnitBlock.CraftingUnitType.valueOf(typeName.toUpperCase());
|
||||
}
|
||||
}
|
||||
if (unitType == null) {
|
||||
throw new JsonParseException("type property is missing");
|
||||
}
|
||||
|
||||
return new CraftingCubeModel(unitType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.util.math.AffineTransformation;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.model.PerspectiveMapWrapper;
|
||||
|
||||
import appeng.client.render.DelegateBakedModel;
|
||||
import appeng.items.misc.EncodedPatternItem;
|
||||
|
||||
/**
|
||||
* This model is used to substitute the crafting result's item model for our
|
||||
* encoded pattern model if these two conditions are met: - The player is
|
||||
* holding shift - The itemstack is being rendered in the UI (not on the ground,
|
||||
* etc.)
|
||||
*
|
||||
* We do this by abusing a custom {@link ModelOverrideList} since it will be
|
||||
* called each frame with the itemstack that is about to be rendered. We return
|
||||
* a custom IBakedModel ({@link ShiftHoldingModelWrapper} if the player is
|
||||
* holding down shift from the override list. This custom baked model implements
|
||||
* {@link #doesHandlePerspectives()} and returns the crafting result model if
|
||||
* the model for {@link ModelTransformation.Mode#GUI} is requested.
|
||||
*/
|
||||
public class EncodedPatternBakedModel extends DelegateBakedModel {
|
||||
|
||||
private final CustomOverrideList overrides;
|
||||
|
||||
EncodedPatternBakedModel(BakedModel baseModel) {
|
||||
super(baseModel);
|
||||
this.overrides = new CustomOverrideList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return this.overrides;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the ItemOverrideList handling comes before handling the perspective
|
||||
* awareness (which is the first place where we know how we are being rendered)
|
||||
* we need to remember the model of the crafting output, and make the decision
|
||||
* on which to render later on. Sadly, Forge is pretty inconsistent when it will
|
||||
* call the handlePerspective method, so some methods are called even on this
|
||||
* interim-model. Usually those methods only matter for rendering on the ground
|
||||
* and other cases, where we wouldn't render the crafting output model anyway,
|
||||
* so in those cases we delegate to the model of the encoded pattern.
|
||||
*/
|
||||
private static class ShiftHoldingModelWrapper extends DelegateBakedModel {
|
||||
|
||||
private final BakedModel outputModel;
|
||||
|
||||
private ShiftHoldingModelWrapper(BakedModel patternModel, BakedModel outputModel) {
|
||||
super(patternModel);
|
||||
this.outputModel = outputModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesHandlePerspectives() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel handlePerspective(ModelTransformation.Mode cameraTransformType, MatrixStack mat) {
|
||||
// No need to re-check for shift being held since this model is only handed out
|
||||
// in that case
|
||||
if (cameraTransformType == ModelTransformation.Mode.GUI) {
|
||||
ImmutableMap<ModelTransformation.Mode, AffineTransformation> transforms = PerspectiveMapWrapper
|
||||
.getTransforms(outputModel.getTransformation());
|
||||
return PerspectiveMapWrapper.handlePerspective(this.outputModel, transforms, cameraTransformType, mat);
|
||||
} else {
|
||||
return getBaseModel().handlePerspective(cameraTransformType, mat);
|
||||
}
|
||||
}
|
||||
|
||||
// This determines diffuse lighting in the UI, and since we want to render
|
||||
// the outputModel in the UI, we need to use it's setting here
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return outputModel.isSideLit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesHandlePerspectives() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel handlePerspective(ModelTransformation.Mode cameraTransformType, MatrixStack mat) {
|
||||
return getBaseModel().handlePerspective(cameraTransformType, mat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Item Override Lists are the only point during item rendering where we can
|
||||
* access the item stack that is being rendered. So this is the point where we
|
||||
* actually check if shift is being held, and if so, determine the crafting
|
||||
* output model.
|
||||
*/
|
||||
private class CustomOverrideList extends ModelOverrideList {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel getModelWithOverrides(BakedModel originalModel, ItemStack stack, @Nullable World world,
|
||||
@Nullable LivingEntity entity) {
|
||||
boolean shiftHeld = Screen.hasShiftDown();
|
||||
if (shiftHeld && world != null) {
|
||||
EncodedPatternItem iep = (EncodedPatternItem) stack.getItem();
|
||||
ItemStack output = iep.getOutput(world, stack);
|
||||
if (!output.isEmpty()) {
|
||||
BakedModel realModel = MinecraftClient.getInstance().getItemRenderer().getItemModelMesher()
|
||||
.getItemModel(output);
|
||||
// Give the item model a chance to handle the overrides as well
|
||||
realModel = realModel.getOverrides().getModelWithOverrides(realModel, output, world, entity);
|
||||
return new ShiftHoldingModelWrapper(getBaseModel(), realModel);
|
||||
}
|
||||
}
|
||||
|
||||
return getBaseModel().getOverrides().getModelWithOverrides(originalModel, stack, world, entity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
/**
|
||||
* This model is used to provide the {@link EncodedPatternBakedModel}.
|
||||
*/
|
||||
public class EncodedPatternModel implements IModelGeometry<EncodedPatternModel> {
|
||||
|
||||
private final Identifier baseModel;
|
||||
|
||||
public EncodedPatternModel(Identifier baseModel) {
|
||||
this.baseModel = baseModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return modelGetter.apply(baseModel).getTextures(modelGetter, missingTextureErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
|
||||
ModelOverrideList overrides, Identifier modelLocation) {
|
||||
BakedModel baseModel = bakery.getBakedModel(this.baseModel, modelTransform, spriteGetter);
|
||||
return new EncodedPatternBakedModel(baseModel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package appeng.client.render.crafting;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraftforge.client.model.IModelLoader;
|
||||
|
||||
/**
|
||||
* Provides our custom {@link EncodedPatternBakedModel encoded pattern item
|
||||
* model}.
|
||||
*/
|
||||
public class EncodedPatternModelLoader implements IModelLoader<EncodedPatternModel> {
|
||||
|
||||
public static final EncodedPatternModelLoader INSTANCE = new EncodedPatternModelLoader();
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EncodedPatternModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
|
||||
modelContents.remove("loader"); // Avoid recursion
|
||||
Identifier baseModel = new Identifier(JsonHelper.getString(modelContents, "baseModel"));
|
||||
return new EncodedPatternModel(baseModel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
import appeng.api.implementations.items.IBiometricCard;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import appeng.core.AELog;
|
||||
|
||||
class BiometricCardBakedModel implements BakedModel {
|
||||
|
||||
private final BakedModel baseModel;
|
||||
|
||||
private final Sprite texture;
|
||||
|
||||
private final int hash;
|
||||
|
||||
private final Cache<Integer, BiometricCardBakedModel> modelCache;
|
||||
|
||||
private final ImmutableList<BakedQuad> generalQuads;
|
||||
|
||||
BiometricCardBakedModel(BakedModel baseModel, Sprite texture) {
|
||||
this(baseModel, texture, 0, createCache());
|
||||
}
|
||||
|
||||
private BiometricCardBakedModel(BakedModel baseModel, Sprite texture, int hash,
|
||||
Cache<Integer, BiometricCardBakedModel> modelCache) {
|
||||
this.baseModel = baseModel;
|
||||
this.texture = texture;
|
||||
this.hash = hash;
|
||||
this.generalQuads = ImmutableList.copyOf(this.buildGeneralQuads());
|
||||
this.modelCache = modelCache;
|
||||
}
|
||||
|
||||
private static Cache<Integer, BiometricCardBakedModel> createCache() {
|
||||
return CacheBuilder.newBuilder().maximumSize(100).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
|
||||
List<BakedQuad> quads = this.baseModel.getQuads(state, side, rand, EmptyModelData.INSTANCE);
|
||||
|
||||
if (side != null) {
|
||||
return quads;
|
||||
}
|
||||
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size() + this.generalQuads.size());
|
||||
result.addAll(quads);
|
||||
result.addAll(this.generalQuads);
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<BakedQuad> buildGeneralQuads() {
|
||||
CubeBuilder builder = new CubeBuilder();
|
||||
|
||||
builder.setTexture(this.texture);
|
||||
|
||||
AEColor col = AEColor.values()[Math.abs(3 + this.hash) % AEColor.values().length];
|
||||
if (this.hash == 0) {
|
||||
col = AEColor.BLACK;
|
||||
}
|
||||
|
||||
for (int x = 0; x < 8; x++) {
|
||||
for (int y = 0; y < 6; y++) {
|
||||
final boolean isLit;
|
||||
|
||||
// This makes the border always use the darker color
|
||||
if (x == 0 || y == 0 || x == 7 || y == 5) {
|
||||
isLit = false;
|
||||
} else {
|
||||
isLit = (this.hash & (1 << x)) != 0 || (this.hash & (1 << y)) != 0;
|
||||
}
|
||||
|
||||
if (isLit) {
|
||||
builder.setColorRGB(col.mediumVariant);
|
||||
} else {
|
||||
final float scale = 0.3f / 255.0f;
|
||||
builder.setColorRGB(((col.blackVariant >> 16) & 0xff) * scale,
|
||||
((col.blackVariant >> 8) & 0xff) * scale, (col.blackVariant & 0xff) * scale);
|
||||
}
|
||||
|
||||
builder.addCube(4 + x, 6 + y, 7.5f, 4 + x + 1, 6 + y + 1, 8.5f);
|
||||
}
|
||||
}
|
||||
return builder.getOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return this.baseModel.useAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return this.baseModel.hasDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return this.baseModel.isBuiltin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.baseModel.getSprite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return this.baseModel.getTransformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return new ModelOverrideList() {
|
||||
@Override
|
||||
public BakedModel getModelWithOverrides(BakedModel originalModel, ItemStack stack, World world,
|
||||
LivingEntity entity) {
|
||||
String username = "";
|
||||
if (stack.getItem() instanceof IBiometricCard) {
|
||||
final GameProfile gp = ((IBiometricCard) stack.getItem()).getProfile(stack);
|
||||
if (gp != null) {
|
||||
if (gp.getId() != null) {
|
||||
username = gp.getId().toString();
|
||||
} else {
|
||||
username = gp.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
final int hash = !username.isEmpty() ? username.hashCode() : 0;
|
||||
|
||||
// Get hash
|
||||
if (hash == 0) {
|
||||
return BiometricCardBakedModel.this;
|
||||
}
|
||||
|
||||
try {
|
||||
return BiometricCardBakedModel.this.modelCache.get(hash,
|
||||
() -> new BiometricCardBakedModel(BiometricCardBakedModel.this.baseModel,
|
||||
BiometricCardBakedModel.this.texture, hash,
|
||||
BiometricCardBakedModel.this.modelCache));
|
||||
} catch (ExecutionException e) {
|
||||
AELog.error(e);
|
||||
return BiometricCardBakedModel.this;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesHandlePerspectives() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel handlePerspective(ModelTransformation.Mode cameraTransformType, MatrixStack mat) {
|
||||
baseModel.handlePerspective(cameraTransformType, mat);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* Model wrapper for the biometric card item model, which combines a base card
|
||||
* layer with a "visual hash" of the player name
|
||||
*/
|
||||
public class BiometricCardModel implements IModelGeometry<BiometricCardModel> {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/biometric_card_base");
|
||||
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/biometric_card_hash"));
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.singleton(TEXTURE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform transformIn,
|
||||
ModelOverrideList overrides, Identifier locationIn) {
|
||||
Sprite texture = spriteGetter.apply(TEXTURE);
|
||||
|
||||
BakedModel baseModel = bakery.getBakedModel(MODEL_BASE, transformIn, spriteGetter);
|
||||
|
||||
return new BiometricCardBakedModel(baseModel, texture);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraftforge.client.model.PerspectiveMapWrapper;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
class ColorApplicatorBakedModel implements BakedModel {
|
||||
|
||||
private final BakedModel baseModel;
|
||||
|
||||
private final IModelTransform transforms;
|
||||
|
||||
private final EnumMap<Direction, List<BakedQuad>> quadsBySide;
|
||||
|
||||
private final List<BakedQuad> generalQuads;
|
||||
|
||||
ColorApplicatorBakedModel(BakedModel baseModel, IModelTransform transforms, Sprite texDark,
|
||||
Sprite texMedium, Sprite texBright) {
|
||||
this.baseModel = baseModel;
|
||||
this.transforms = transforms;
|
||||
|
||||
// Put the tint indices in... Since this is an item model, we are ignoring rand
|
||||
this.generalQuads = this.fixQuadTint(null, texDark, texMedium, texBright);
|
||||
this.quadsBySide = new EnumMap<>(Direction.class);
|
||||
for (Direction facing : Direction.values()) {
|
||||
this.quadsBySide.put(facing, this.fixQuadTint(facing, texDark, texMedium, texBright));
|
||||
}
|
||||
}
|
||||
|
||||
private List<BakedQuad> fixQuadTint(Direction facing, Sprite texDark, Sprite texMedium,
|
||||
Sprite texBright) {
|
||||
List<BakedQuad> quads = this.baseModel.getQuads(null, facing, new Random(0), EmptyModelData.INSTANCE);
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size());
|
||||
for (BakedQuad quad : quads) {
|
||||
int tint;
|
||||
|
||||
if (quad.func_187508_a() == texDark) {
|
||||
tint = 1;
|
||||
} else if (quad.func_187508_a() == texMedium) {
|
||||
tint = 2;
|
||||
} else if (quad.func_187508_a() == texBright) {
|
||||
tint = 3;
|
||||
} else {
|
||||
result.add(quad);
|
||||
continue;
|
||||
}
|
||||
|
||||
BakedQuad newQuad = new BakedQuad(quad.getVertexData(), tint, quad.getFace(), quad.func_187508_a(),
|
||||
quad.shouldApplyDiffuseLighting());
|
||||
result.add(newQuad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
if (side == null) {
|
||||
return this.generalQuads;
|
||||
}
|
||||
return this.quadsBySide.get(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return this.baseModel.useAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return this.baseModel.hasDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return this.baseModel.isBuiltin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.baseModel.getSprite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return this.baseModel.getTransformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return this.baseModel.getOverrides();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel handlePerspective(ModelTransformation.Mode cameraTransformType, MatrixStack mat) {
|
||||
return PerspectiveMapWrapper.handlePerspective(this, transforms, cameraTransformType, mat);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* A color applicator uses the base model, and extends it with additional layers
|
||||
* that are colored according to the selected color of the applicator.
|
||||
*/
|
||||
public class ColorApplicatorModel implements IModelGeometry<ColorApplicatorModel> {
|
||||
|
||||
private static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID,
|
||||
"item/color_applicator_colored");
|
||||
|
||||
private static final SpriteIdentifier TEXTURE_DARK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_dark"));
|
||||
private static final SpriteIdentifier TEXTURE_MEDIUM = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_medium"));
|
||||
private static final SpriteIdentifier TEXTURE_BRIGHT = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/color_applicator_tip_bright"));
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Arrays.asList(TEXTURE_DARK, TEXTURE_MEDIUM, TEXTURE_DARK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
|
||||
ModelOverrideList overrides, Identifier modelLocation) {
|
||||
BakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
|
||||
|
||||
Sprite texDark = spriteGetter.apply(TEXTURE_DARK);
|
||||
Sprite texMedium = spriteGetter.apply(TEXTURE_MEDIUM);
|
||||
Sprite texBright = spriteGetter.apply(TEXTURE_BRIGHT);
|
||||
|
||||
return new ColorApplicatorBakedModel(baseModel, modelTransform, texDark, texMedium, texBright);
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
import appeng.api.implementations.items.IMemoryCard;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import appeng.core.AELog;
|
||||
|
||||
class MemoryCardBakedModel implements BakedModel {
|
||||
private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] { AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
AEColor.TRANSPARENT, };
|
||||
|
||||
private final BakedModel baseModel;
|
||||
|
||||
private final Sprite texture;
|
||||
|
||||
private final AEColor[] colorCode;
|
||||
|
||||
private final Cache<CacheKey, MemoryCardBakedModel> modelCache;
|
||||
|
||||
private final ImmutableList<BakedQuad> generalQuads;
|
||||
|
||||
MemoryCardBakedModel(BakedModel baseModel, Sprite texture) {
|
||||
this(baseModel, texture, DEFAULT_COLOR_CODE, createCache());
|
||||
}
|
||||
|
||||
private MemoryCardBakedModel(BakedModel baseModel, Sprite texture, AEColor[] hash,
|
||||
Cache<CacheKey, MemoryCardBakedModel> modelCache) {
|
||||
this.baseModel = baseModel;
|
||||
this.texture = texture;
|
||||
this.colorCode = hash;
|
||||
this.generalQuads = ImmutableList.copyOf(this.buildGeneralQuads());
|
||||
this.modelCache = modelCache;
|
||||
}
|
||||
|
||||
private static Cache<CacheKey, MemoryCardBakedModel> createCache() {
|
||||
return CacheBuilder.newBuilder().maximumSize(100).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
|
||||
List<BakedQuad> quads = this.baseModel.getQuads(state, side, rand, EmptyModelData.INSTANCE);
|
||||
|
||||
if (side != null) {
|
||||
return quads;
|
||||
}
|
||||
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size() + this.generalQuads.size());
|
||||
result.addAll(quads);
|
||||
result.addAll(this.generalQuads);
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<BakedQuad> buildGeneralQuads() {
|
||||
CubeBuilder builder = new CubeBuilder();
|
||||
|
||||
builder.setTexture(this.texture);
|
||||
|
||||
for (int x = 0; x < 4; x++) {
|
||||
for (int y = 0; y < 2; y++) {
|
||||
final AEColor color = this.colorCode[x + y * 4];
|
||||
|
||||
builder.setColorRGB(color.mediumVariant);
|
||||
builder.addCube(7 + x, 8 + (1 - y), 7.5f, 7 + x + 1, 8 + (1 - y) + 1, 8.5f);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.getOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion() {
|
||||
return this.baseModel.useAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth() {
|
||||
return this.baseModel.hasDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin() {
|
||||
return this.baseModel.isBuiltin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sprite getSprite() {
|
||||
return this.baseModel.getSprite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelTransformation getTransformation() {
|
||||
return this.baseModel.getTransformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelOverrideList getOverrides() {
|
||||
return new ModelOverrideList() {
|
||||
@Override
|
||||
public BakedModel getModelWithOverrides(BakedModel originalModel, ItemStack stack, World world,
|
||||
LivingEntity entity) {
|
||||
try {
|
||||
if (stack.getItem() instanceof IMemoryCard) {
|
||||
final IMemoryCard memoryCard = (IMemoryCard) stack.getItem();
|
||||
final AEColor[] colors = memoryCard.getColorCode(stack);
|
||||
|
||||
return MemoryCardBakedModel.this.modelCache.get(new CacheKey(colors),
|
||||
() -> new MemoryCardBakedModel(MemoryCardBakedModel.this.baseModel,
|
||||
MemoryCardBakedModel.this.texture, colors,
|
||||
MemoryCardBakedModel.this.modelCache));
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
AELog.error(e);
|
||||
}
|
||||
|
||||
return MemoryCardBakedModel.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel handlePerspective(ModelTransformation.Mode cameraTransformType, MatrixStack mat) {
|
||||
baseModel.handlePerspective(cameraTransformType, mat);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static class CacheKey {
|
||||
private final AEColor[] key;
|
||||
|
||||
CacheKey(AEColor[] key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(this.key);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
CacheKey other = (CacheKey) obj;
|
||||
return Arrays.equals(this.key, other.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.IModelTransform;
|
||||
import net.minecraft.client.render.model.IUnbakedModel;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.util.SpriteIdentifier;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.texture.SpriteAtlasTexture;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* Model wrapper for the memory card item model, which combines a base card
|
||||
* layer with a "visual hash" of the part/tile.
|
||||
*/
|
||||
public class MemoryCardModel implements IModelGeometry<MemoryCardModel> {
|
||||
|
||||
public static final Identifier MODEL_BASE = new Identifier(AppEng.MOD_ID, "item/memory_card_base");
|
||||
private static final SpriteIdentifier TEXTURE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
|
||||
new Identifier(AppEng.MOD_ID, "item/memory_card_hash"));
|
||||
|
||||
@Override
|
||||
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
|
||||
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.singleton(TEXTURE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
|
||||
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
|
||||
ModelOverrideList overrides, Identifier modelLocation) {
|
||||
Sprite texture = spriteGetter.apply(TEXTURE);
|
||||
|
||||
BakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
|
||||
|
||||
return new MemoryCardBakedModel(baseModel, texture);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public class UVLModelLoader implements IModelLoader<UVLModelLoader.UVLModelWrapp
|
||||
}
|
||||
}
|
||||
|
||||
public static class UVLModelWrapper implements IModelGeometry<UVLModelWrapper> {
|
||||
public static class UVLModelWrapper implements BasicUnbakedModel {
|
||||
private final BlockModel parent;
|
||||
|
||||
public UVLModelWrapper(BlockModel parent) {
|
||||
|
||||
@@ -40,7 +40,7 @@ import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
/**
|
||||
* Built-in model for annihilation planes that supports connected textures.
|
||||
*/
|
||||
public class PlaneModel implements IModelGeometry<PlaneModel> {
|
||||
public class PlaneModel implements BasicUnbakedModel {
|
||||
|
||||
private final SpriteIdentifier frontTexture;
|
||||
private final SpriteIdentifier sidesTexture;
|
||||
|
||||
Reference in New Issue
Block a user