Jank Control

- More blocks now support the new belt system
- Fixed the extractor models
- Prepared the funnel model for filtering
- Items now look 80% better on belts
This commit is contained in:
simibubi 2019-11-14 13:00:55 +01:00
parent 25cac1fe8e
commit e5c78fbd04
25 changed files with 1312 additions and 996 deletions

View file

@ -0,0 +1,94 @@
package com.simibubi.create.foundation.utility;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IWorldReader;
/**
* Stolen from EntityRenderer
*/
public class IndependentShadowRenderer {
private static final ResourceLocation SHADOW_TEXTURES = new ResourceLocation("textures/misc/shadow.png");
public static void renderShadow(double x, double y, double z, float shadowAlpha, float size) {
GlStateManager.enableBlend();
GlStateManager.enableAlphaTest();
GlStateManager.blendFunc(GlStateManager.SourceFactor.DST_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
Minecraft.getInstance().getTextureManager().bindTexture(SHADOW_TEXTURES);
IWorldReader iworldreader = Minecraft.getInstance().world;
GlStateManager.depthMask(false);
int i = MathHelper.floor(x - size);
int j = MathHelper.floor(x + size);
int k = MathHelper.floor(y - size);
int l = MathHelper.floor(y);
int i1 = MathHelper.floor(z - size);
int j1 = MathHelper.floor(z + size);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
for (BlockPos blockpos : BlockPos.getAllInBoxMutable(new BlockPos(i, k, i1), new BlockPos(j, l, j1))) {
BlockPos blockpos1 = blockpos.down();
BlockState blockstate = iworldreader.getBlockState(blockpos1);
if (blockstate.getRenderType() != BlockRenderType.INVISIBLE && iworldreader.getLight(blockpos) > 3) {
func_217759_a(blockstate, iworldreader, blockpos1, 0, 0, 0, blockpos, shadowAlpha, size, -x, -y, -z);
}
}
tessellator.draw();
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableBlend();
GlStateManager.depthMask(true);
}
private static void func_217759_a(BlockState p_217759_1_, IWorldReader p_217759_2_, BlockPos p_217759_3_,
double p_217759_4_, double p_217759_6_, double p_217759_8_, BlockPos p_217759_10_, float p_217759_11_,
float p_217759_12_, double p_217759_13_, double p_217759_15_, double p_217759_17_) {
ClientWorld world = Minecraft.getInstance().world;
VoxelShape voxelshape = p_217759_1_.getShape(world, p_217759_10_.down());
if (!voxelshape.isEmpty()) {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
double d0 = ((double) p_217759_11_ - (p_217759_6_ - ((double) p_217759_10_.getY() + p_217759_15_)) / 2.0D)
* 0.5D * (double) world.getBrightness(p_217759_10_);
if (!(d0 < 0.0D)) {
if (d0 > 1.0D) {
d0 = 1.0D;
}
AxisAlignedBB axisalignedbb = voxelshape.getBoundingBox();
double d1 = (double) p_217759_10_.getX() + axisalignedbb.minX + p_217759_13_;
double d2 = (double) p_217759_10_.getX() + axisalignedbb.maxX + p_217759_13_;
double d3 = (double) p_217759_10_.getY() + axisalignedbb.minY + p_217759_15_ + 0.015625D;
double d4 = (double) p_217759_10_.getZ() + axisalignedbb.minZ + p_217759_17_;
double d5 = (double) p_217759_10_.getZ() + axisalignedbb.maxZ + p_217759_17_;
float f = (float) ((p_217759_4_ - d1) / 2.0D / (double) p_217759_12_ + 0.5D);
float f1 = (float) ((p_217759_4_ - d2) / 2.0D / (double) p_217759_12_ + 0.5D);
float f2 = (float) ((p_217759_8_ - d4) / 2.0D / (double) p_217759_12_ + 0.5D);
float f3 = (float) ((p_217759_8_ - d5) / 2.0D / (double) p_217759_12_ + 0.5D);
bufferbuilder.pos(d1, d3, d4).tex((double) f, (double) f2).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
bufferbuilder.pos(d1, d3, d5).tex((double) f, (double) f3).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
bufferbuilder.pos(d2, d3, d5).tex((double) f1, (double) f3).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
bufferbuilder.pos(d2, d3, d4).tex((double) f1, (double) f2).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
}
}
}
}

View file

@ -16,24 +16,23 @@ import net.minecraft.util.math.Vec3d;
public class TessellatorHelper {
public static final float fontScale = 1/512f;
public static final float fontScale = 1 / 512f;
public static void prepareForDrawing() {
Minecraft mc = Minecraft.getInstance();
GlStateManager.pushMatrix();
GlStateManager.pushLightingAttributes();
GlStateManager.enableBlend();
GlStateManager.enableAlphaTest();
GlStateManager.color4f(1, 1, 1, 1);
public static void prepareForDrawing() {
Minecraft mc = Minecraft.getInstance();
GlStateManager.pushMatrix();
GlStateManager.pushLightingAttributes();
GlStateManager.enableBlend();
GlStateManager.enableAlphaTest();
GlStateManager.color4f(1, 1, 1, 1);
ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo();
Vec3d view = renderInfo.getProjectedView();
GlStateManager.translated(-view.x, -view.y, -view.z);
}
ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo();
Vec3d view = renderInfo.getProjectedView();
GlStateManager.translated(-view.x, -view.y, -view.z);
}
public static void prepareFastRender() {
Minecraft.getInstance().textureManager
.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
Minecraft.getInstance().textureManager.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.enableBlend();
@ -43,35 +42,35 @@ public class TessellatorHelper {
GlStateManager.shadeModel(GL11.GL_SMOOTH);
else
GlStateManager.shadeModel(GL11.GL_FLAT);
GlStateManager.color3f(1, 1, 1);
}
public static void begin() {
begin(DefaultVertexFormats.POSITION_TEX);
}
public static void begin(VertexFormat format) {
Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, format);
}
public static void begin() {
begin(DefaultVertexFormats.POSITION_TEX);
}
public static void draw() {
Tessellator.getInstance().draw();
}
public static void begin(VertexFormat format) {
Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, format);
}
public static void cleanUpAfterDrawing() {
GlStateManager.disableAlphaTest();
GlStateManager.disableBlend();
GlStateManager.popAttributes();
GlStateManager.popMatrix();
}
public static void draw() {
Tessellator.getInstance().draw();
}
public static void cleanUpAfterDrawing() {
GlStateManager.disableAlphaTest();
GlStateManager.disableBlend();
GlStateManager.popAttributes();
GlStateManager.popMatrix();
}
public static void drawString(String str, float x, float y, float z, boolean scalesUp, boolean hasDepth) {
Minecraft mc = Minecraft.getInstance();
float pitch = mc.getRenderManager().playerViewX;
float yaw = mc.getRenderManager().playerViewY;
boolean isThirdPersonFrontal = mc.gameSettings.thirdPersonView == 2;
GlStateManager.pushMatrix();
GlStateManager.pushLightingAttributes();
GlStateManager.translatef(x, y, z);
@ -82,9 +81,9 @@ public class TessellatorHelper {
GlStateManager.disableLighting();
if (!hasDepth) {
GlStateManager.depthMask(false);
GlStateManager.disableDepthTest();
GlStateManager.disableDepthTest();
}
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA,
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE,
@ -98,21 +97,21 @@ public class TessellatorHelper {
bufferbuilder.pos((double) (-i - 3), (double) (10), 0.0D).color(1F, 1F, 1F, .5F).endVertex();
bufferbuilder.pos((double) (i + 3), (double) (10), 0.0D).color(1F, 1F, 1F, .5F).endVertex();
bufferbuilder.pos((double) (i + 3), (double) (-3), 0.0D).color(1F, 1F, 1F, .5F).endVertex();
if (scalesUp) {
double distance = mc.player.getEyePosition(mc.getRenderPartialTicks()).squareDistanceTo(x, y, z);
double scale = distance * fontScale;
GlStateManager.scaled(2 + scale, 2 + scale, 2 + scale);
GlStateManager.scaled(2 + scale, 2 + scale, 2 + scale);
}
tessellator.draw();
GlStateManager.enableTexture();
if (hasDepth) {
GlStateManager.translatef(0, 0, -0.125f);
}
mc.fontRenderer.drawString(str, -mc.fontRenderer.getStringWidth(str) / 2, 0, 0);
GlStateManager.enableDepthTest();
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.depthMask(true);
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA,
@ -121,118 +120,124 @@ public class TessellatorHelper {
GlStateManager.popMatrix();
GlStateManager.popAttributes();
}
public static void cube(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale,
boolean scaleVertical, boolean doubleFaces) {
TessellatorHelper.walls(bufferBuilder, pos, size, scale, scaleVertical, doubleFaces);
int w = size.getX();
int h = size.getY();
int l = size.getZ();
if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical, false);
} else {
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical, false, false);
}
}
public static void cube(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale,
boolean scaleVertical, boolean doubleFaces) {
TessellatorHelper.walls(bufferBuilder, pos, size, scale, scaleVertical, doubleFaces);
int w = size.getX();
int h = size.getY();
int l = size.getZ();
public static void walls(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale,
boolean scaleVertical, boolean doubleFaces) {
int w = size.getX();
int h = size.getY();
int l = size.getZ();
if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true,
scaleVertical, false);
} else {
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical,
false, false);
}
}
if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false);
} else {
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false, false);
}
}
public static void walls(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale,
boolean scaleVertical, boolean doubleFaces) {
int w = size.getX();
int h = size.getY();
int l = size.getZ();
public static void doubleFace(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift,
boolean stretch, boolean shiftVertical, boolean mirrorTexture) {
TessellatorHelper.face(bufferBuilder, pos, size, shift, stretch, shiftVertical, false, mirrorTexture);
TessellatorHelper.face(bufferBuilder, pos.add(size.getX(), 0, (size.getY() == 0) ? 0 : size.getZ()),
new BlockPos(-size.getX(), size.getY(), (size.getY() == 0) ? size.getZ() : -size.getZ()), -shift,
stretch, shiftVertical, true, mirrorTexture);
}
if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true,
scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true,
scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false);
} else {
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true,
scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true,
scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false, false);
}
}
public static void face(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift, boolean stretch,
boolean shiftVertical, boolean shiftBackwards, boolean mirrorTexture) {
int w = size.getX();
int h = size.getY();
int l = size.getZ();
if (shiftBackwards)
shift = -shift;
public static void doubleFace(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift,
boolean stretch, boolean shiftVertical, boolean mirrorTexture) {
TessellatorHelper.face(bufferBuilder, pos, size, shift, stretch, shiftVertical, false, mirrorTexture);
TessellatorHelper.face(bufferBuilder, pos.add(size.getX(), 0, (size.getY() == 0) ? 0 : size.getZ()),
new BlockPos(-size.getX(), size.getY(), (size.getY() == 0) ? size.getZ() : -size.getZ()), -shift,
stretch, shiftVertical, true, mirrorTexture);
}
if (w == 0) { // YZ plane -> H has to be positive
public static void face(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift, boolean stretch,
boolean shiftVertical, boolean shiftBackwards, boolean mirrorTexture) {
int w = size.getX();
int h = size.getY();
int l = size.getZ();
if (shiftBackwards)
shift = -shift;
double xs = (l < 0) ? shift : -shift;
if (shiftBackwards)
xs = -xs;
double ys1 = shiftVertical ? shift : 0;
double zs1 = l < 0 ? -shift : shift;
if (!stretch && (l > 0 ^ mirrorTexture))
zs1 = -zs1;
double ys2 = stretch ? -ys1 : ys1;
double zs2 = stretch ? -zs1 : zs1;
double u1 = (mirrorTexture) ? l : 0;
double u2 = (mirrorTexture) ? 0 : l;
if (w == 0) { // YZ plane -> H has to be positive
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs1), pos.south(l), u2, h);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys1, zs1), pos.south(l).up(h), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys1, zs2), pos.up(h), u1, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs2), pos, u1, h);
double xs = (l < 0) ? shift : -shift;
if (shiftBackwards)
xs = -xs;
double ys1 = shiftVertical ? shift : 0;
double zs1 = l < 0 ? -shift : shift;
if (!stretch && (l > 0 ^ mirrorTexture))
zs1 = -zs1;
double ys2 = stretch ? -ys1 : ys1;
double zs2 = stretch ? -zs1 : zs1;
double u1 = (mirrorTexture) ? l : 0;
double u2 = (mirrorTexture) ? 0 : l;
} else if (h == 0) { // XZ plane -> L has to be positive
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs1), pos.south(l), u2, h);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys1, zs1), pos.south(l).up(h), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys1, zs2), pos.up(h), u1, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs2), pos, u1, h);
double ys = w < 0 ? shift : -shift;
if (shiftBackwards)
ys = -ys;
double xs1 = w < 0 ? -shift : shift;
double zs1 = shift;
double xs2 = stretch ? -xs1 : xs1;
double zs2 = stretch ? -zs1 : zs1;
double u1 = (mirrorTexture) ? w : 0;
double u2 = (mirrorTexture) ? 0 : w;
} else if (h == 0) { // XZ plane -> L has to be positive
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys, zs1), pos.south(l), u1, l);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys, zs2), pos, u1, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs2), pos.east(w), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs1), pos.east(w).south(l), u2, l);
double ys = w < 0 ? shift : -shift;
if (shiftBackwards)
ys = -ys;
double xs1 = w < 0 ? -shift : shift;
double zs1 = shift;
double xs2 = stretch ? -xs1 : xs1;
double zs2 = stretch ? -zs1 : zs1;
double u1 = (mirrorTexture) ? w : 0;
double u2 = (mirrorTexture) ? 0 : w;
} else if (l == 0) { // XY plane -> H has to be positive
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys, zs1), pos.south(l), u1, l);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys, zs2), pos, u1, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs2), pos.east(w), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs1), pos.east(w).south(l), u2, l);
double zs = w < 0 ? shift : -shift;
if (shiftBackwards)
zs = -zs;
double ys1 = shiftVertical ? shift : 0;
double xs1 = w < 0 ? -shift : shift;
if (!stretch && (w > 0 ^ mirrorTexture))
xs1 = -xs1;
double ys2 = stretch ? -ys1 : ys1;
double xs2 = stretch ? -xs1 : xs1;
double u1 = (mirrorTexture) ? w : 0;
double u2 = (mirrorTexture) ? 0 : w;
} else if (l == 0) { // XY plane -> H has to be positive
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys2, zs), pos, u1, h);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys1, zs), pos.up(h), u1, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys1, zs), pos.east(w).up(h), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys2, zs), pos.east(w), u2, h);
double zs = w < 0 ? shift : -shift;
if (shiftBackwards)
zs = -zs;
double ys1 = shiftVertical ? shift : 0;
double xs1 = w < 0 ? -shift : shift;
if (!stretch && (w > 0 ^ mirrorTexture))
xs1 = -xs1;
double ys2 = stretch ? -ys1 : ys1;
double xs2 = stretch ? -xs1 : xs1;
double u1 = (mirrorTexture) ? w : 0;
double u2 = (mirrorTexture) ? 0 : w;
}
}
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys2, zs), pos, u1, h);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys1, zs), pos.up(h), u1, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys1, zs), pos.east(w).up(h), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys2, zs), pos.east(w), u2, h);
private static void posTexShift(BufferBuilder bufferBuilder, Vec3d shift, BlockPos pos, double u, double v) {
bufferBuilder.pos(shift.x + pos.getX(), shift.y + pos.getY(), shift.z + pos.getZ()).tex(u, v).endVertex();
}
}
}
private static void posTexShift(BufferBuilder bufferBuilder, Vec3d shift, BlockPos pos, double u, double v) {
bufferBuilder.pos(shift.x + pos.getX(), shift.y + pos.getY(), shift.z + pos.getZ()).tex(u, v).endVertex();
}
}

View file

@ -4,7 +4,6 @@ import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
import com.simibubi.create.modules.contraptions.relays.belt.FastItemRenderer;
import net.minecraft.client.resources.ReloadListener;
import net.minecraft.profiler.IProfiler;
@ -23,7 +22,6 @@ public class CachedBufferReloader extends ReloadListener<String> {
ContraptionRenderer.invalidateCache();
MechanicalBearingTileEntityRenderer.invalidateCache();
ColoredIndicatorRenderer.invalidateCache();
FastItemRenderer.invalidateCache();
}

View file

@ -2,7 +2,6 @@ package com.simibubi.create.modules.contraptions;
import static com.simibubi.create.AllBlocks.BELT;
import static com.simibubi.create.AllBlocks.COGWHEEL;
import static com.simibubi.create.AllBlocks.ENCASED_FAN;
import static com.simibubi.create.AllBlocks.LARGE_COGWHEEL;
import static com.simibubi.create.CreateConfig.parameters;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;

View file

@ -7,21 +7,22 @@ import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.utility.ItemHelper;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
@ -99,8 +100,8 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
}
@Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) {
return Arrays.asList(te.getPos().up(2));
public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
return Arrays.asList(pos.up(2));
}
@Override
@ -112,15 +113,35 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
}
@Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) {
BlockState blockState = world.getBlockState(pos.down(2));
if (!AllBlocks.BELT.typeOf(blockState) || blockState.get(BeltBlock.SLOPE) != Slope.HORIZONTAL)
return Optional.empty();
return Optional.of(pos.down(2));
public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
return pos.down(2);
}
@Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos,
BlockState attachmentState, BlockState beltState) {
return AllBlocks.BELT.typeOf(beltState) && beltState.get(BeltBlock.SLOPE) == Slope.HORIZONTAL;
}
@Override
public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
MechanicalPressTileEntity pressTe = (MechanicalPressTileEntity) te.getWorld()
.getTileEntity(state.attachmentPos);
if (pressTe == null || pressTe.getSpeed() == 0)
return false;
if (pressTe.running)
return false;
if (!pressTe.getRecipe(transported.stack).isPresent())
return false;
state.processingDuration = 1;
pressTe.start(true);
return true;
}
@Override
public boolean processItem(BeltTileEntity te, TransportedItemStack transportedStack, BeltAttachmentState state) {
MechanicalPressTileEntity pressTe = (MechanicalPressTileEntity) te.getWorld()
.getTileEntity(state.attachmentPos);
@ -128,42 +149,23 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
if (pressTe == null || pressTe.getSpeed() == 0)
return false;
// Not an Item
if (!(entity instanceof ItemEntity))
return false;
// Running
if (pressTe.running) {
double distanceTo = entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos()));
if (distanceTo < .32f)
return true;
if (distanceTo < .4f) {
entity.setPosition(te.getPos().getX() + .5f, entity.posY, te.getPos().getZ() + .5f);
return true;
if (pressTe.runningTicks == 30) {
Optional<PressingRecipe> recipe = pressTe.getRecipe(transportedStack.stack);
if (!recipe.isPresent())
return false;
ItemStack out = recipe.get().getRecipeOutput().copy();
List<ItemStack> multipliedOutput = ItemHelper.multipliedOutput(transportedStack.stack, out);
if (multipliedOutput.isEmpty())
transportedStack.stack = ItemStack.EMPTY;
transportedStack.stack = multipliedOutput.get(0);
TileEntity controllerTE = te.getWorld().getTileEntity(te.getController());
if (controllerTE != null && controllerTE instanceof BeltTileEntity)
((SyncedTileEntity) controllerTE).sendData();
}
return false;
}
// Start process
if (state.processingEntity != entity) {
state.processingEntity = entity;
if (!pressTe.getRecipe((ItemEntity) entity).isPresent()) {
state.processingDuration = -1;
} else {
state.processingDuration = 1;
pressTe.start(true);
}
return false;
}
// Already processed
if (state.processingDuration == -1)
return false;
// Just Finished
if (pressTe.finished) {
state.processingDuration = -1;
return false;
return true;
}
return false;

View file

@ -6,13 +6,17 @@ import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
@ -85,31 +89,45 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
@Override
public void tick() {
super.tick();
if (!running)
return;
if (runningTicks == 30) {
AxisAlignedBB bb = new AxisAlignedBB(pos.down(beltMode ? 2 : 1));
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
if (!(entity instanceof ItemEntity))
continue;
ItemEntity itemEntity = (ItemEntity) entity;
if (world.isRemote) {
for (int i = 0; i < 20; i++) {
Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .25f).mul(1, 0, 1);
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, itemEntity.getItem()), entity.posX,
entity.posY, entity.posZ, motion.x, motion.y, motion.z);
if (!beltMode) {
AxisAlignedBB bb = new AxisAlignedBB(pos.down(beltMode ? 2 : 1));
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
if (!(entity instanceof ItemEntity))
continue;
ItemEntity itemEntity = (ItemEntity) entity;
makeParticleEffect(entity.getPositionVec(), itemEntity.getItem());
if (!world.isRemote) {
Optional<PressingRecipe> recipe = getRecipe(itemEntity.getItem());
if (recipe.isPresent())
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
}
}
}
if (beltMode && world.isRemote) {
TileEntity te = world.getTileEntity(pos.down(2));
if (te != null && te instanceof BeltTileEntity) {
BeltTileEntity beltTE = (BeltTileEntity) te;
TileEntity controller = world.getTileEntity(beltTE.getController());
if (controller != null && controller instanceof BeltTileEntity) {
TransportedItemStack stackAtOffset = ((BeltTileEntity) controller).getInventory()
.getStackAtOffset(beltTE.index);
if (stackAtOffset != null)
makeParticleEffect(VecHelper.getCenterOf(pos.down(2)).add(0, 5 / 16f, 0),
stackAtOffset.stack);
}
}
if (!world.isRemote) {
Optional<PressingRecipe> recipe = getRecipe(itemEntity);
if (recipe.isPresent())
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
}
}
if (!world.isRemote) {
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, .5f, 1f);
world.playSound(null, getPos(), SoundEvents.BLOCK_ANVIL_LAND, SoundCategory.BLOCKS, .125f, 1f);
@ -128,8 +146,18 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
runningTicks++;
}
public Optional<PressingRecipe> getRecipe(ItemEntity itemEntity) {
pressingInv.setInventorySlotContents(0, itemEntity.getItem());
public void makeParticleEffect(Vec3d pos, ItemStack stack) {
if (world.isRemote) {
for (int i = 0; i < 20; i++) {
Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .25f).mul(1, 0, 1);
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y, pos.z, motion.x,
motion.y, motion.z);
}
}
}
public Optional<PressingRecipe> getRecipe(ItemStack item) {
pressingInv.setInventorySlotContents(0, item);
Optional<PressingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.PRESSING, pressingInv,
world);
return recipe;

View file

@ -4,10 +4,11 @@ import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.NonNullList;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper;
public class ProcessingInventory extends RecipeWrapper {
public class ProcessingInventory extends RecipeWrapper implements IItemHandler {
protected int remainingTime;
protected int recipeDuration;
protected boolean appliedRecipe;
@ -50,8 +51,40 @@ public class ProcessingInventory extends RecipeWrapper {
return inventory;
}
@Override
public int getInventoryStackLimit() {
return 64;
}
public ItemStackHandler getItems() {
return (ItemStackHandler) inv;
}
@Override
public int getSlots() {
return 9;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (!isItemValid(slot, stack))
return stack;
return inv.insertItem(slot, stack, simulate);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
}
@Override
public int getSlotLimit(int slot) {
return 64;
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return slot == 0 && isEmpty();
}
}

View file

@ -7,10 +7,12 @@ import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import net.minecraft.entity.item.ItemEntity;
@ -24,15 +26,23 @@ import net.minecraft.particles.BlockParticleData;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
public ProcessingInventory inventory;
private int recipeIndex;
private ItemStack filter;
private LazyOptional<IItemHandler> invProvider = LazyOptional.empty();
public SawTileEntity() {
super(AllTileEntities.SAW.type);
@ -40,6 +50,7 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
inventory.remainingTime = -1;
filter = ItemStack.EMPTY;
recipeIndex = 0;
invProvider = LazyOptional.of(() -> inventory);
}
@Override
@ -78,12 +89,17 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return;
if (getSpeed() == 0)
return;
if (inventory.remainingTime == -1)
if (inventory.remainingTime == -1) {
if (!inventory.isEmpty() && !inventory.appliedRecipe)
start();
return;
}
float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 32, 1, 128);
inventory.remainingTime -= processingSpeed;
spawnParticles(inventory.getStackInSlot(0));
if (inventory.remainingTime > 0)
spawnParticles(inventory.getStackInSlot(0));
if (world.isRemote)
return;
@ -95,10 +111,69 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return;
}
Vec3d outPos = VecHelper.getCenterOf(pos).add(getItemMovementVec().scale(.5f).add(0, .5, 0));
Vec3d outMotion = getItemMovementVec().scale(.0625).add(0, .125, 0);
Vec3d itemMovement = getItemMovementVec();
Direction itemMovementFacing = Direction.getFacingFromVector(itemMovement.x, itemMovement.y, itemMovement.z);
Vec3d outPos = VecHelper.getCenterOf(pos).add(itemMovement.scale(.5f).add(0, .5, 0));
Vec3d outMotion = itemMovement.scale(.0625).add(0, .125, 0);
if (inventory.remainingTime <= 0) {
// Try moving items onto the belt
BlockPos nextPos = pos.add(itemMovement.x, itemMovement.y, itemMovement.z);
if (AllBlocks.BELT.typeOf(world.getBlockState(nextPos))) {
TileEntity te = world.getTileEntity(nextPos);
if (te != null && te instanceof BeltTileEntity) {
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
if (itemMovementFacing.getAxis() == Axis.Z)
itemMovementFacing = itemMovementFacing.getOpposite();
if (((BeltTileEntity) te).tryInsertingFromSide(itemMovementFacing, stack, false))
inventory.setInventorySlotContents(slot, ItemStack.EMPTY);
else {
inventory.remainingTime = 0;
return;
}
}
inventory.clear();
inventory.remainingTime = -1;
sendData();
}
}
// Try moving items onto next saw
if (AllBlocks.SAW.typeOf(world.getBlockState(nextPos))) {
TileEntity te = world.getTileEntity(nextPos);
if (te != null && te instanceof SawTileEntity) {
SawTileEntity sawTileEntity = (SawTileEntity) te;
Vec3d otherMovement = sawTileEntity.getItemMovementVec();
if (Direction.getFacingFromVector(otherMovement.x, otherMovement.y,
otherMovement.z) != itemMovementFacing.getOpposite()) {
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ProcessingInventory sawInv = sawTileEntity.inventory;
if (sawInv.isEmpty()) {
sawInv.insertItem(0, stack, false);
inventory.setInventorySlotContents(slot, ItemStack.EMPTY);
} else {
inventory.remainingTime = 0;
return;
}
}
inventory.clear();
inventory.remainingTime = -1;
sendData();
}
}
}
// Eject Items
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
@ -108,6 +183,7 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
world.addEntity(entityIn);
}
inventory.clear();
world.updateComparatorOutputLevel(pos, getBlockState().getBlock());
inventory.remainingTime = -1;
sendData();
return;
@ -116,6 +192,19 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return;
}
@Override
public void remove() {
super.remove();
invProvider.invalidate();
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return invProvider.cast();
return super.getCapability(cap, side);
}
protected void spawnParticles(ItemStack stack) {
if (stack == null || stack.isEmpty())
return;
@ -198,6 +287,17 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
inventory.clear();
inventory.setInventorySlotContents(0, entity.getItem().copy());
entity.remove();
start();
}
public void start() {
if (!canProcess())
return;
if (inventory.isEmpty())
return;
if (world.isRemote)
return;
List<IRecipe<?>> recipes = getRecipes();
boolean valid = !recipes.isEmpty();
@ -206,7 +306,6 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
if (recipes.isEmpty()) {
inventory.remainingTime = inventory.recipeDuration = 10;
inventory.appliedRecipe = false;
entity.remove();
sendData();
return;
}
@ -222,11 +321,9 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
time = ((CuttingRecipe) recipe).getProcessingDuration();
}
inventory.remainingTime = time * Math.max(1, (entity.getItem().getCount() / 5));
inventory.remainingTime = time * Math.max(1, (inventory.getStackInSlot(0).getCount() / 5));
inventory.recipeDuration = inventory.remainingTime;
inventory.appliedRecipe = false;
entity.remove();
sendData();
}

View file

@ -24,16 +24,17 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
@SuppressWarnings("deprecation")
public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
FilteredTileEntityRenderer filterRenderer;
public SawTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override
public void render(SawTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(te, x, y, z, partialTicks, destroyStage);
@ -43,9 +44,11 @@ public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE);
GlStateManager.pushMatrix();
float offset = te.inventory.recipeDuration != 0
? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration
: 0;
boolean moving = te.inventory.recipeDuration != 0;
float offset = moving ? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration : 0;
if (moving)
offset = MathHelper.clamp(offset + (-partialTicks + .5f) / te.inventory.recipeDuration, 0, 1);
if (te.getSpeed() == 0)
offset = .5f;
if (te.getSpeed() < 0 ^ alongZ)
@ -69,7 +72,7 @@ public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
// Filter
filterRenderer.render(te, x, y, z, partialTicks, destroyStage);
// Kinetic renders
final BlockState state = getRenderedBlockState(te);
KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new);

View file

@ -2,11 +2,11 @@ package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
@ -33,32 +34,52 @@ public enum AllBeltAttachments {
}
public interface IBeltAttachment {
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te);
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state);
public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState);
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state);
public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state);
default boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos, BlockState attachmentState,
BlockState beltState) {
return true;
}
default boolean processEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
return false;
}
default boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
return false;
}
default boolean processItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
return false;
}
default void onAttachmentPlaced(IWorld world, BlockPos pos, BlockState state) {
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state);
if (!beltPos.isPresent())
BlockPos beltPos = getBeltPositionForAttachment(world, pos, state);
TileEntity te = world.getTileEntity(beltPos);
if (te == null || !(te instanceof BeltTileEntity))
return;
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get());
if (te == null)
BeltTileEntity belt = (BeltTileEntity) te;
if (!isAttachedCorrectly(world, pos, belt.getPos(), state, belt.getBlockState()))
return;
te.attachmentTracker.addAttachment(world, pos);
te.sendData();
belt.attachmentTracker.addAttachment(world, pos);
belt.markDirty();
belt.sendData();
}
default void onAttachmentRemoved(IWorld world, BlockPos pos, BlockState state) {
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state);
if (!beltPos.isPresent())
BlockPos beltPos = getBeltPositionForAttachment(world, pos, state);
TileEntity te = world.getTileEntity(beltPos);
if (te == null || !(te instanceof BeltTileEntity))
return;
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get());
if (te == null)
BeltTileEntity belt = (BeltTileEntity) te;
if (!isAttachedCorrectly(world, pos, belt.getPos(), state, belt.getBlockState()))
return;
te.attachmentTracker.removeAttachment(pos);
te.sendData();
belt.attachmentTracker.removeAttachment(pos);
belt.markDirty();
belt.sendData();
}
}
@ -67,6 +88,7 @@ public enum AllBeltAttachments {
public BlockPos attachmentPos;
public int processingDuration;
public Entity processingEntity;
public TransportedItemStack processingStack;
public BeltAttachmentState(IBeltAttachment attachment, BlockPos attachmentPos) {
this.attachment = attachment;
@ -86,19 +108,25 @@ public enum AllBeltAttachments {
public void findAttachments(BeltTileEntity belt) {
for (AllBeltAttachments ba : AllBeltAttachments.values()) {
List<BlockPos> attachmentPositions = ba.attachment.getPotentialAttachmentLocations(belt);
World world = belt.getWorld();
BlockPos beltPos = belt.getPos();
BlockState beltState = belt.getBlockState();
List<BlockPos> attachmentPositions = ba.attachment.getPotentialAttachmentPositions(world, beltPos,
beltState);
for (BlockPos potentialPos : attachmentPositions) {
if (!world.isBlockPresent(potentialPos))
continue;
BlockState state = world.getBlockState(potentialPos);
if (!(state.getBlock() instanceof IBeltAttachment))
if (!(state.getBlock() instanceof IBeltAttachment))
continue;
Optional<BlockPos> validBeltPos = ((IBeltAttachment) state.getBlock()).getValidBeltPositionFor(world, potentialPos, state);
if (!validBeltPos.isPresent())
IBeltAttachment attachment = (IBeltAttachment) state.getBlock();
if (!attachment.getBeltPositionForAttachment(world, potentialPos, state).equals(beltPos))
continue;
if (validBeltPos.get().equals(belt.getPos()))
addAttachment(world, potentialPos);
if (!attachment.isAttachedCorrectly(world, potentialPos, beltPos, state, beltState))
continue;
addAttachment(world, potentialPos);
}
}
}

View file

@ -9,6 +9,7 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.block.IWithoutBlockItem;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.Block;
@ -38,7 +39,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.Tags;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.IItemHandler;
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> {
@ -99,10 +100,14 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
if (entityIn instanceof ItemEntity && entityIn.isAlive()) {
if (worldIn.isRemote)
return;
if (entityIn.getMotion().y > 0)
return;
withTileEntityDo(worldIn, pos, te -> {
ItemEntity itemEntity = (ItemEntity) entityIn;
ItemStack remainder = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
.orElseGet(() -> new ItemStackHandler(0)).insertItem(0, itemEntity.getItem().copy(), false);
IItemHandler handler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
if (handler == null)
return;
ItemStack remainder = handler.insertItem(0, itemEntity.getItem().copy(), false);
if (remainder.isEmpty())
itemEntity.remove();
});
@ -133,19 +138,42 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
if (player.isSneaking() || !player.isAllowEdit())
return false;
ItemStack heldItem = player.getHeldItem(handIn);
if (!Tags.Items.DYES.contains(heldItem.getItem()))
return false;
if (worldIn.isRemote)
boolean isShaft = heldItem.getItem() == AllBlocks.SHAFT.get().asItem();
boolean isDye = Tags.Items.DYES.contains(heldItem.getItem());
if (isShaft) {
TileEntity te = worldIn.getTileEntity(pos);
if (te == null || !(te instanceof BeltTileEntity))
return false;
BeltTileEntity belt = (BeltTileEntity) te;
if (belt.hasPulley())
return false;
if (worldIn.isRemote)
return true;
if (!player.isCreative())
heldItem.shrink(1);
belt.hasPulley = true;
belt.markDirty();
belt.sendData();
belt.attachKinetics();
return true;
withTileEntityDo(worldIn, pos, te -> {
DyeColor dyeColor = DyeColor.getColor(heldItem);
if (dyeColor == null)
return;
te.applyColor(dyeColor);
});
if (!player.isCreative())
heldItem.shrink(1);
return true;
}
if (isDye) {
if (worldIn.isRemote)
return true;
withTileEntityDo(worldIn, pos, te -> {
DyeColor dyeColor = DyeColor.getColor(heldItem);
if (dyeColor == null)
return;
te.applyColor(dyeColor);
});
if (!player.isCreative())
heldItem.shrink(1);
return true;
}
return false;
}
@Override
@ -177,8 +205,15 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
@Override
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
withTileEntityDo(worldIn, pos, te -> {
if (te.hasPulley())
if (worldIn.isRemote)
return;
if (te.hasPulley() && (player == null || !player.isCreative()))
Block.spawnDrops(AllBlocks.SHAFT.get().getDefaultState(), worldIn, pos);
if (te.isController()) {
BeltInventory inv = te.getInventory();
for (TransportedItemStack stack : inv.items)
inv.eject(stack);
}
});
super.onBlockHarvested(worldIn, pos, state, player);
}
@ -211,16 +246,20 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
break;
BeltTileEntity te = (BeltTileEntity) worldIn.getTileEntity(toDestroy);
boolean hasPulley = te.hasPulley();
if (te.isController()) {
BeltInventory inv = te.getInventory();
for (TransportedItemStack stack : inv.items)
inv.eject(stack);
}
te.setSource(null);
te.remove();
if (hasPulley) {
if (te.hasPulley())
worldIn.setBlockState(toDestroy, AllBlocks.SHAFT.get().getDefaultState()
.with(BlockStateProperties.AXIS, getRotationAxis(destroyedBlock)), 3);
} else {
else
worldIn.destroyBlock(toDestroy, false);
}
if (destroyedBlock.get(PART) == Part.END)
break;

View file

@ -4,9 +4,11 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -21,7 +23,10 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public class BeltInventory {
@ -36,7 +41,7 @@ public class BeltInventory {
}
public void tick() {
// Reverse item collection if belt just reversed
if (beltMovementPositive != movingPositive()) {
beltMovementPositive = movingPositive();
@ -49,12 +54,15 @@ public class BeltInventory {
TransportedItemStack stackInFront = null;
TransportedItemStack current = null;
Iterator<TransportedItemStack> iterator = items.iterator();
float beltSpeed = belt.getBeltMovementSpeed();
float beltSpeed = belt.getDirectionAwareBeltMovementSpeed();
float spacing = 1;
while (iterator.hasNext()) {
Items: while (iterator.hasNext()) {
stackInFront = current;
current = iterator.next();
current.prevBeltPosition = current.beltPosition;
current.prevSideOffset = current.sideOffset;
if (current.stack.isEmpty()) {
iterator.remove();
@ -64,6 +72,11 @@ public class BeltInventory {
float movement = beltSpeed;
// Don't move if locked
boolean onClient = belt.getWorld().isRemote;
if (onClient && current.locked)
continue;
// Don't move if other items are waiting in front
float currentPos = current.beltPosition;
if (stackInFront != null) {
@ -74,18 +87,60 @@ public class BeltInventory {
: Math.max(movement, diff + spacing);
}
float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos;
float limitedMovement = beltMovementPositive ? Math.min(movement, diffToEnd)
: Math.max(movement, diffToEnd);
// Determine current segment
int segmentBefore = (int) currentPos;
float min = segmentBefore + .5f - (SEGMENT_WINDOW / 2);
float max = segmentBefore + .5f + (SEGMENT_WINDOW / 2);
if (currentPos < min || currentPos > max)
segmentBefore = -1;
current.beltPosition += limitedMovement;
// Don't move beyond the edge
float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos;
float limitedMovement = beltMovementPositive ? Math.min(movement, diffToEnd)
: Math.max(movement, diffToEnd);
if (!onClient) {
// Don't move if belt attachments want to continue processing
if (segmentBefore != -1 && current.locked) {
BeltTileEntity beltSegment = getBeltSegment(segmentBefore);
if (beltSegment != null) {
current.locked = false;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
if (attachmentState.attachment.processItem(beltSegment, current, attachmentState))
current.locked = true;
}
if (!current.locked || current.stack.isEmpty())
belt.sendData();
continue;
}
}
// See if any new belt processing catches the item
int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f));
for (int segment = upcomingSegment; beltMovementPositive
? segment <= current.beltPosition + limitedMovement
: segment >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1 : -1) {
BeltTileEntity beltSegment = getBeltSegment(segmentBefore);
if (beltSegment == null)
break;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
if (attachmentState.attachment.startProcessingItem(beltSegment, current, attachmentState)) {
current.beltPosition += (segment + .5f) - current.beltPosition;
current.locked = true;
belt.sendData();
continue Items;
}
}
}
}
// Apply Movement
current.beltPosition += limitedMovement;
current.sideOffset += (current.getTargetSideOffset() - current.sideOffset) * Math.abs(limitedMovement) * 2f;
currentPos = current.beltPosition;
// Determine segment after movement
int segmentAfter = (int) currentPos;
min = segmentAfter + .5f - (SEGMENT_WINDOW / 2);
max = segmentAfter + .5f + (SEGMENT_WINDOW / 2);
@ -113,12 +168,38 @@ public class BeltInventory {
BlockState state = world.getBlockState(nextPosition);
Direction movementFacing = belt.getMovementFacing();
// next block is a basin or a saw
if (AllBlocks.BASIN.typeOf(state) || AllBlocks.SAW.typeOf(state)) {
TileEntity te = world.getTileEntity(nextPosition);
if (te != null) {
LazyOptional<IItemHandler> optional = te
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP);
if (optional.isPresent()) {
IItemHandler itemHandler = optional.orElse(null);
ItemStack remainder = ItemHandlerHelper.insertItemStacked(itemHandler, current.stack.copy(),
false);
if (remainder.equals(current.stack, false))
continue;
current.stack = remainder;
if (remainder.isEmpty()) {
iterator.remove();
current = null;
}
belt.sendData();
}
}
continue;
}
// next block is not a belt
if (!AllBlocks.BELT.typeOf(state)) {
if (!Block.hasSolidSide(state, world, nextPosition, movementFacing.getOpposite())) {
eject(current);
iterator.remove();
current = null;
belt.sendData();
}
continue;
}
@ -135,25 +216,12 @@ public class BeltInventory {
continue;
// Inserting into other belt
BlockPos controller = nextBelt.getController();
if (!world.isBlockPresent(controller))
continue;
te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
continue;
BeltTileEntity nextBeltController = (BeltTileEntity) te;
BeltInventory nextInventory = nextBeltController.getInventory();
if (nextBelt.tryInsertingFromSide(movementFacing, current, false)) {
iterator.remove();
current = null;
belt.sendData();
}
if (!nextInventory.canInsertAt(nextBelt.index))
continue;
current.beltPosition = nextBelt.index + .5f;
current.insertedAt = nextBelt.index;
nextInventory.insert(current);
iterator.remove();
current = null;
belt.sendData();
nextBeltController.sendData();
}
}
@ -164,10 +232,23 @@ public class BeltInventory {
public ItemStack stack;
public float beltPosition;
public float sideOffset;
public int angle;
public int insertedAt;
public Direction insertedFrom;
public boolean locked;
public float prevBeltPosition;
public float prevSideOffset;
public TransportedItemStack(ItemStack stack) {
this.stack = stack;
angle = new Random().nextInt(360);
sideOffset = prevSideOffset = getTargetSideOffset();
insertedFrom = Direction.UP;
}
public float getTargetSideOffset() {
return (angle - 180) / (360 * 3f);
}
@Override
@ -179,22 +260,36 @@ public class BeltInventory {
CompoundNBT nbt = new CompoundNBT();
nbt.put("Item", stack.serializeNBT());
nbt.putFloat("Pos", beltPosition);
nbt.putFloat("PrevPos", prevBeltPosition);
nbt.putFloat("Offset", sideOffset);
nbt.putFloat("PrevOffset", prevSideOffset);
nbt.putInt("InSegment", insertedAt);
nbt.putInt("Angle", angle);
nbt.putInt("InDirection", insertedFrom.getIndex());
nbt.putBoolean("Locked", locked);
return nbt;
}
public static TransportedItemStack read(CompoundNBT nbt) {
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
stack.beltPosition = nbt.getFloat("Pos");
stack.prevBeltPosition = nbt.getFloat("PrevPos");
stack.sideOffset = nbt.getFloat("Offset");
stack.prevSideOffset = nbt.getFloat("PrevOffset");
stack.insertedAt = nbt.getInt("InSegment");
stack.angle = nbt.getInt("Angle");
stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection"));
stack.locked = nbt.getBoolean("Locked");
return stack;
}
}
public boolean canInsertAt(int segment) {
return canInsertFrom(segment, Direction.UP);
}
public boolean canInsertFrom(int segment, Direction side) {
float min = segment + .5f - (SEGMENT_WINDOW / 2);
float max = segment + .5f + (SEGMENT_WINDOW / 2);
@ -211,7 +306,8 @@ public class BeltInventory {
// Items on the belt get prioritized if the previous item was inserted on the
// same segment
if (stack.insertedAt == segment && currentPos <= segment + 1)
if (stack.insertedAt == segment && stack.insertedFrom == side
&& (beltMovementPositive ? currentPos <= segment + 1.5 : currentPos - 1.5 >= segment))
return false;
}
@ -219,20 +315,23 @@ public class BeltInventory {
}
protected void insert(TransportedItemStack newStack) {
int index = 0;
if (items.isEmpty())
items.add(newStack);
for (TransportedItemStack stack : items) {
if (stack.compareTo(newStack) > 0 == beltMovementPositive)
break;
index++;
else {
int index = 0;
for (TransportedItemStack stack : items) {
if (stack.compareTo(newStack) > 0 == beltMovementPositive)
break;
index++;
}
items.add(index, newStack);
}
items.add(index, newStack);
belt.markDirty();
belt.sendData();
}
protected TransportedItemStack getStackAtOffset(int offset) {
public TransportedItemStack getStackAtOffset(int offset) {
float min = offset + .5f - (SEGMENT_WINDOW / 2);
float max = offset + .5f + (SEGMENT_WINDOW / 2);
for (TransportedItemStack stack : items) {
@ -260,28 +359,40 @@ public class BeltInventory {
return nbt;
}
private void eject(TransportedItemStack stack) {
public void eject(TransportedItemStack stack) {
ItemStack ejected = stack.stack;
Vec3d outPos = getVectorForOffset(stack.beltPosition);
ItemEntity entity = new ItemEntity(belt.getWorld(), outPos.x, outPos.y, outPos.z, ejected);
entity.setMotion(new Vec3d(belt.getBeltChainDirection()).scale(Math.abs(belt.getBeltMovementSpeed())));
Vec3d outMotion = new Vec3d(belt.getBeltChainDirection()).scale(Math.abs(belt.getBeltMovementSpeed())).add(0,
1 / 8f, 0);
outPos.add(outMotion.normalize());
ItemEntity entity = new ItemEntity(belt.getWorld(), outPos.x, outPos.y + 6 / 16f, outPos.z, ejected);
entity.setMotion(outMotion);
entity.velocityChanged = true;
belt.getWorld().addEntity(entity);
}
private Vec3d getVectorForOffset(float offset) {
Vec3d vec = VecHelper.getCenterOf(belt.getPos());
vec.add(new Vec3d(belt.getBeltChainDirection()).scale(offset));
vec = vec.add(new Vec3d(belt.getBeltFacing().getDirectionVec()).scale(offset - .5f));
return vec;
}
private BeltTileEntity getBeltSegment(int segment) {
BlockPos pos = getPositionForOffset(segment);
TileEntity te = belt.getWorld().getTileEntity(pos);
if (te == null || !(te instanceof BeltTileEntity))
return null;
return (BeltTileEntity) te;
}
private BlockPos getPositionForOffset(int offset) {
BlockPos pos = belt.getPos();
Vec3i vec = belt.getBeltChainDirection();
Vec3i vec = belt.getBeltFacing().getDirectionVec();
return pos.add(offset * vec.getX(), offset * vec.getY(), offset * vec.getZ());
}
private boolean movingPositive() {
return belt.getBeltMovementSpeed() > 0;
return belt.getDirectionAwareBeltMovementSpeed() > 0;
}
public class ItemHandlerSegment implements IItemHandler {
@ -311,6 +422,7 @@ public class BeltInventory {
TransportedItemStack newStack = new TransportedItemStack(stack);
newStack.insertedAt = offset;
newStack.beltPosition = offset + .5f;
newStack.prevBeltPosition = newStack.beltPosition;
insert(newStack);
}
return ItemStack.EMPTY;

View file

@ -93,7 +93,7 @@ public class BeltMovementHandler {
// Attachment pauses movement
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
if (state.attachment.handleEntity(belt, entityIn, state)) {
if (state.attachment.processEntity(belt, entityIn, state)) {
info.ticksSinceLastCollision--;
return;
}

View file

@ -20,11 +20,13 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties;
@ -197,6 +199,13 @@ public class BeltTileEntity extends KineticTileEntity {
return getSpeed() / 1600f;
}
public float getDirectionAwareBeltMovementSpeed() {
int offset = getBeltFacing().getAxisDirection().getOffset();
if (getBeltFacing().getAxis() == Axis.X)
offset *= -1;
return getSpeed() / 1600f * offset;
}
public boolean hasPulley() {
if (!AllBlocks.BELT.typeOf(getBlockState()))
return false;
@ -270,4 +279,44 @@ public class BeltTileEntity extends KineticTileEntity {
return inventory;
}
public boolean tryInsertingFromSide(Direction side, ItemStack stack, boolean simulate) {
return tryInsertingFromSide(side, new TransportedItemStack(stack), simulate);
}
public boolean tryInsertingFromSide(Direction side, TransportedItemStack transportedStack, boolean simulate) {
BlockPos controller = getController();
if (!world.isBlockPresent(controller))
return false;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return false;
BeltTileEntity nextBeltController = (BeltTileEntity) te;
BeltInventory nextInventory = nextBeltController.getInventory();
if (!nextInventory.canInsertFrom(index, side))
return false;
if (simulate)
return true;
transportedStack.beltPosition = index + .5f;
Direction movementFacing = getMovementFacing();
if (!side.getAxis().isVertical()) {
if (movementFacing != side)
transportedStack.sideOffset = side.getAxisDirection().getOffset() * .35f;
else
transportedStack.beltPosition = getDirectionAwareBeltMovementSpeed() > 0 ? index : index + 1;
if (side.getAxis() == Axis.X ^ movementFacing.getAxis() == Axis.X)
transportedStack.sideOffset *= -1;
}
transportedStack.prevSideOffset = transportedStack.sideOffset;
transportedStack.insertedAt = index;
transportedStack.insertedFrom = side;
transportedStack.prevBeltPosition = transportedStack.beltPosition;
nextInventory.insert(transportedStack);
nextBeltController.sendData();
return true;
}
}

View file

@ -2,6 +2,7 @@ package com.simibubi.create.modules.contraptions.relays.belt;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.IndependentShadowRenderer;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
@ -12,6 +13,8 @@ import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.Transp
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
@ -19,6 +22,7 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
@ -28,27 +32,66 @@ public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
@Override
public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(te, x, y, z, partialTicks, destroyStage);
if (te.isController()) {
GlStateManager.pushMatrix();
GlStateManager.translated(x + .5, y + 13 / 16f + .25, z + .5);
for (TransportedItemStack transported : te.getInventory().items) {
GlStateManager.pushMatrix();
Vec3i direction = te.getBeltChainDirection();
float offset = transported.beltPosition;
Vec3d offsetVec = new Vec3d(direction).scale(offset);
GlStateManager.translated(offsetVec.x, offsetVec.y, offsetVec.z);
Minecraft.getInstance().getItemRenderer().renderItem(transported.stack, TransformType.FIXED);
GlStateManager.popMatrix();
}
GlStateManager.popMatrix();
}
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw();
if (te.isController()) {
GlStateManager.pushMatrix();
Vec3i directionVec = te.getBeltFacing().getDirectionVec();
Vec3d beltStartOffset = new Vec3d(directionVec).scale(-.5).add(.5, 13 / 16f + .125f, .5);
GlStateManager.translated(x + beltStartOffset.x, y + beltStartOffset.y, z + beltStartOffset.z);
for (TransportedItemStack transported : te.getInventory().items) {
GlStateManager.pushMatrix();
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
Vec3d offsetVec = new Vec3d(directionVec).scale(offset);
GlStateManager.translated(offsetVec.x, offsetVec.y, offsetVec.z);
boolean alongX = te.getBeltFacing().rotateY().getAxis() == Axis.X;
if (!alongX)
sideOffset *= -1;
GlStateManager.translated(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset);
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
boolean blockItem = itemRenderer.getModelWithOverrides(transported.stack).isGui3d();
if (Minecraft.getInstance().gameSettings.fancyGraphics) {
Vec3d shadowPos = new Vec3d(te.getPos()).add(beltStartOffset.scale(1).add(offsetVec)
.add(alongX ? sideOffset : 0, .39, alongX ? 0 : sideOffset));
IndependentShadowRenderer.renderShadow(shadowPos.x, shadowPos.y, shadowPos.z, .75f,
blockItem ? .2f : .2f);
}
RenderHelper.enableStandardItemLighting();
int count = (int) (MathHelper.log2((int) (transported.stack.getCount()))) / 2;
for (int i = 0; i <= count; i++) {
GlStateManager.pushMatrix();
GlStateManager.rotated(transported.angle, 0, 1, 0);
if (!blockItem) {
GlStateManager.translated(0, -.09375, 0);
GlStateManager.rotated(90, 1, 0, 0);
}
GlStateManager.scaled(.5, .5, .5);
itemRenderer.renderItem(transported.stack, TransformType.FIXED);
GlStateManager.popMatrix();
GlStateManager.rotated(10, 0, 1, 0);
GlStateManager.translated(0, 1/16d, 0);
}
RenderHelper.disableStandardItemLighting();
GlStateManager.popMatrix();
}
GlStateManager.popMatrix();
}
}
@Override

View file

@ -1,120 +0,0 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.nio.ByteBuffer;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.simibubi.create.foundation.utility.BufferManipulator;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.client.model.data.EmptyModelData;
public class FastItemRenderer extends BufferManipulator {
public FastItemRenderer(ByteBuffer original) {
super(original);
}
public ByteBuffer getTranslatedAndRotated(World world, float x, float y, float z, float yaw, float pitch) {
original.rewind();
mutable.rewind();
float cosYaw = MathHelper.cos(yaw);
float sinYaw = MathHelper.sin(yaw);
float cosPitch = MathHelper.cos(pitch);
float sinPitch = MathHelper.sin(pitch);
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
float xL = getX(original, vertex); // - (float) rotationOffset.x;
float yL = getY(original, vertex); // - (float) rotationOffset.y;
float zL = getZ(original, vertex); // - (float) rotationOffset.z;
float xL2 = rotateX(xL, yL, zL, sinPitch, cosPitch, Axis.X);
float yL2 = rotateY(xL, yL, zL, sinPitch, cosPitch, Axis.X);
float zL2 = rotateZ(xL, yL, zL, sinPitch, cosPitch, Axis.X);
//
xL = rotateX(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
yL = rotateY(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
zL = rotateZ(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
float xPos = xL + x; // + (float) (offset.x + rotationOffset.x);
float yPos = yL + y; // + (float) (offset.y + rotationOffset.y);
float zPos = zL + z; // + (float) (offset.z + rotationOffset.z);
putPos(mutable, vertex, xPos, yPos, zPos);
BlockPos pos = new BlockPos(xPos + .5f, yPos + .5f, zPos + .5f);
putLight(mutable, vertex, world.getCombinedLight(pos, 15));
}
return mutable;
}
protected static Cache<Item, FastItemRenderer> cachedItems;
public static void renderItem(BufferBuilder buffer, World world, ItemStack stack, float x, float y, float z,
float yaw, float pitch) {
if (stack.isEmpty())
return;
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
IBakedModel model = itemRenderer.getModelWithOverrides(stack);
if (model.isBuiltInRenderer()) {
renderItemIntoBuffer(stack, itemRenderer, model, 0, buffer);
return;
}
cacheIfMissing(stack);
FastItemRenderer renderer = cachedItems.getIfPresent(stack.getItem());
if (renderer == null)
return;
buffer.putBulkData(renderer.getTranslatedAndRotated(world, x, y +1, z, yaw, pitch));
}
protected static void cacheIfMissing(ItemStack stack) {
if (cachedItems == null)
cachedItems = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.SECONDS).build();
if (cachedItems.getIfPresent(stack.getItem()) != null)
return;
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
IBakedModel model = itemRenderer.getModelWithOverrides(stack);
int color = 0;
BufferBuilder bufferbuilder = new BufferBuilder(0);
bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
renderItemIntoBuffer(stack, itemRenderer, model, color, bufferbuilder);
bufferbuilder.finishDrawing();
cachedItems.put(stack.getItem(), new FastItemRenderer(bufferbuilder.getByteBuffer()));
}
protected static void renderItemIntoBuffer(ItemStack stack, ItemRenderer itemRenderer, IBakedModel model, int color,
BufferBuilder bufferbuilder) {
Random random = new Random(42L);
for (Direction direction : Direction.values())
itemRenderer.renderQuads(bufferbuilder, model.getQuads(null, direction, random, EmptyModelData.INSTANCE),
color, stack);
itemRenderer.renderQuads(bufferbuilder, model.getQuads(null, null, random, EmptyModelData.INSTANCE), color,
stack);
}
public static void invalidateCache() {
if (cachedItems != null)
cachedItems.invalidateAll();
}
}

View file

@ -2,8 +2,10 @@ package com.simibubi.create.modules.logistics.block;
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.item.CardboardBoxItem;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
@ -11,10 +13,12 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
@ -126,6 +130,8 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
IItemHandler inv = getInventory().orElse(null);
ItemStack extracting = ItemStack.EMPTY;
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY;
World world = getWorld();
BlockPos pos = getPos();
int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get()
: filterItem.getCount();
boolean checkHasEnoughItems = !filterItem.isEmpty();
@ -171,18 +177,26 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
break Extraction;
} while (true);
if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) {
TileEntity te = world.getTileEntity(pos.down());
if (te != null && te instanceof BeltTileEntity && !extracting.isEmpty()) {
if (((BeltTileEntity) te).tryInsertingFromSide(Direction.UP, extracting.copy(), simulate))
return extracting;
return ItemStack.EMPTY;
}
}
if (!simulate && hasEnoughItems) {
World world = getWorld();
Vec3d pos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Vec3d entityPos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Entity entityIn = null;
if (extracting.getItem() instanceof CardboardBoxItem) {
Direction face = getWorld().getBlockState(getPos()).get(HORIZONTAL_FACING).getOpposite();
entityIn = new CardboardBoxEntity(world, pos, extracting, face);
entityIn = new CardboardBoxEntity(world, entityPos, extracting, face);
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .25f, .05f);
} else {
entityIn = new ItemEntity(world, pos.x, pos.y, pos.z, extracting);
entityIn = new ItemEntity(world, entityPos.x, entityPos.y, entityPos.z, extracting);
entityIn.setMotion(Vec3d.ZERO);
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, .1f);
}

View file

@ -2,31 +2,24 @@ package com.simibubi.create.modules.logistics.block.belts;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
@ -49,7 +42,7 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
@ -79,7 +72,7 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
BlockState neighbour = worldIn.getBlockState(neighbourPos);
return !neighbour.getShape(worldIn, pos).isEmpty();
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = getDefaultState();
@ -138,33 +131,32 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
}
@Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) {
return Arrays.asList(te.getPos().up());
public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
return Arrays.asList(pos.up());
}
@Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) {
BlockPos validPos = pos.down();
BlockState blockState = world.getBlockState(validPos);
if (!AllBlocks.BELT.typeOf(blockState)
|| blockState.get(HORIZONTAL_FACING).getAxis() != state.get(HORIZONTAL_FACING).getAxis())
return Optional.empty();
return Optional.of(validPos);
public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
return pos.down();
}
@Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
boolean isItem = entity instanceof ItemEntity;
if (!isItem && !(entity instanceof CardboardBoxEntity))
return false;
boolean slope = te.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
if (isItem && entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > (slope ? .6f : .4f))
return false;
entity.setMotion(Vec3d.ZERO);
withTileEntityDo(te.getWorld(), state.attachmentPos, funnelTE -> {
funnelTE.tryToInsert(entity);
});
public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
return process(te, transported, state);
}
@Override
public boolean processItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
return process(te, transported, state);
}
public boolean process(BeltTileEntity belt, TransportedItemStack transported, BeltAttachmentState state) {
TileEntity te = belt.getWorld().getTileEntity(state.attachmentPos);
if (te == null || !(te instanceof BeltFunnelTileEntity))
return false;
BeltFunnelTileEntity funnel = (BeltFunnelTileEntity) te;
ItemStack stack = funnel.tryToInsert(transported.stack);
transported.stack = stack;
return true;
}

View file

@ -2,11 +2,10 @@ package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.ItemHandlerSegment;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData;
@ -16,6 +15,7 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
@ -27,6 +27,8 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
protected boolean waitingForInventorySpace;
private boolean initialize;
private ItemStack justEaten;
public BeltFunnelTileEntity() {
super(AllTileEntities.BELT_FUNNEL.type);
inventory = LazyOptional.empty();
@ -38,22 +40,33 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
super.read(compound);
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Waiting", waitingForInventorySpace);
return super.write(compound);
}
@Override
public void onLoad() {
initialize = true;
}
@Override
public CompoundNBT writeToClient(CompoundNBT tag) {
if (justEaten != null) {
tag.put("Nom", justEaten.serializeNBT());
justEaten = null;
}
return super.writeToClient(tag);
}
@Override
public void readClientUpdate(CompoundNBT tag) {
super.readClientUpdate(tag);
if (!waitingForInventorySpace)
neighborChanged();
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Waiting", waitingForInventorySpace);
return super.write(compound);
if (tag.contains("Nom"))
justEaten = ItemStack.read(tag.getCompound("Nom"));
}
@Override
@ -72,6 +85,10 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
neighborChanged();
initialize = false;
}
if (world.isRemote && justEaten != null) {
spawnParticles(justEaten);
justEaten = null;
}
}
@Override
@ -87,42 +104,34 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
sendData();
}
public void tryToInsert(Entity entity) {
public ItemStack tryToInsert(ItemStack stack) {
if (!inventory.isPresent())
return;
if (waitingForInventorySpace)
return;
ItemStack stack = null;
if (entity instanceof ItemEntity)
stack = ((ItemEntity) entity).getItem().copy();
if (entity instanceof CardboardBoxEntity)
stack = ((CardboardBoxEntity) entity).getBox().copy();
return stack;
if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerSegment))
return stack;
IItemHandler inv = inventory.orElse(null);
stack = ItemHandlerHelper.insertItemStacked(inv, stack, false);
if (stack.isEmpty()) {
if (!world.isRemote) {
entity.remove();
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, stack.copy(), false);
if (remainder.isEmpty()) {
if (!world.isRemote)
world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f);
} else {
Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec();
float xSpeed = directionVec.getX() * 1 / 8f;
float zSpeed = directionVec.getZ() * 1 / 8f;
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), entity.posX,
entity.posY, entity.posZ, xSpeed, 1 / 6f, zSpeed);
}
return;
justEaten = stack;
} else {
waitingForInventorySpace = true;
}
waitingForInventorySpace = true;
sendData();
return remainder;
}
if (entity instanceof ItemEntity)
if (!stack.equals(((ItemEntity) entity).getItem(), false))
((ItemEntity) entity).setItem(stack);
public void spawnParticles(ItemStack stack) {
Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec();
float xSpeed = directionVec.getX() * 1 / 8f;
float zSpeed = directionVec.getZ() * 1 / 8f;
Vec3d vec = VecHelper.getCenterOf(pos);
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), vec.x, vec.y - 9 / 16f, vec.z, xSpeed,
1 / 6f, zSpeed);
}
}

View file

@ -3,7 +3,6 @@ package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import com.simibubi.create.AllBlocks;
@ -129,16 +128,20 @@ public class EntityDetectorBlock extends HorizontalBlock
}
@Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) {
Direction side = te.getBlockState().get(BeltBlock.HORIZONTAL_FACING).rotateY();
return Arrays.asList(te.getPos().offset(side), te.getPos().offset(side.getOpposite()));
public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
Direction side = beltState.get(BeltBlock.HORIZONTAL_FACING).rotateY();
return Arrays.asList(pos.offset(side), pos.offset(side.getOpposite()));
}
@Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) {
if (!state.get(BELT))
return Optional.empty();
return Optional.of(pos.offset(state.get(HORIZONTAL_FACING)));
public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
return pos.offset(state.get(HORIZONTAL_FACING));
}
@Override
public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos, BlockState attachmentState,
BlockState beltState) {
return attachmentState.get(BELT);
}
@Override
@ -178,11 +181,11 @@ public class EntityDetectorBlock extends HorizontalBlock
}
@Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
public boolean processEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
if (te.getWorld().isRemote)
return false;
if (state.processingEntity != entity) {
state.processingEntity = entity;
state.processingDuration = 0;

View file

@ -1,95 +1,140 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"textures": {
"particle": "create:block/belt_funnel",
"belt_funnel": "create:block/belt_funnel",
"brass_casing": "create:block/brass_casing"
},
"elements": [
{
"name": "Bottom",
"from": [ 3, -4.1, -1 ],
"to": [ 13, -3.1, 5 ],
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] },
"east": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ] },
"south": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ], "rotation": 180 },
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 },
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 }
}
},
{
"name": "Top",
"from": [ 3, 7, -1 ],
"to": [ 13, 8, 5 ],
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
"east": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 1 ] },
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 1 ], "rotation": 180 },
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 },
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 }
}
},
{
"name": "Side",
"from": [ 3, -3.1, -1 ],
"to": [ 4, 7, 5 ],
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] },
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] },
"south": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] }
}
},
{
"name": "Center",
"from": [ 4, -3.1, -1 ],
"to": [ 12, 7, 4 ],
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 4, 3, 12, 13.1 ] },
"east": { "texture": "#belt_funnel", "uv": [ 9, 3, 10, 9 ], "rotation": 90 },
"south": { "texture": "#belt_funnel", "uv": [ 1, 1, 9, 11.1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 0, 2, 1, 8 ], "rotation": 90 }
}
},
{
"name": "Top",
"from": [ 4, 6, 0 ],
"to": [ 12, 8, 4.8 ],
"rotation": { "origin": [ 8, 8, 0 ], "axis": "x", "angle": -22.5 },
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 1, 7, 9, 9 ], "rotation": 180 },
"east": { "texture": "#belt_funnel", "uv": [ 11, 4.6, 16, 6.6 ], "rotation": 180 },
"south": { "texture": "#belt_funnel", "uv": [ 9, 2, 11, 10 ], "rotation": 90 },
"west": { "texture": "#belt_funnel", "uv": [ 10, 5, 15, 7.4 ], "rotation": 180 },
"up": { "texture": "#belt_funnel", "uv": [ 11, 2, 16, 9.4 ], "rotation": 90 },
"down": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.8 ] }
}
},
{
"name": "Ramp",
"from": [ 4, -4, -8 ],
"to": [ 12, 3, -1 ],
"rotation": { "origin": [ 8, -4, -1 ], "axis": "x", "angle": 45.0 },
"faces": {
"north": { "texture": "#brass_casing", "uv": [ 4, 5, 12, 12 ] },
"east": { "texture": "#brass_casing", "uv": [ 4, 9, 11, 16 ], "rotation": 90 },
"west": { "texture": "#brass_casing", "uv": [ 5, 9, 12, 16 ], "rotation": 270 },
"down": { "texture": "#brass_casing", "uv": [ 4, 0, 12, 7 ] }
}
},
{
"name": "Side",
"from": [ 12, -3.1, -1 ],
"to": [ 13, 7, 5 ],
"faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] },
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ], "rotation": 180 },
"south": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] },
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] }
}
}
]
"credit": "Made with Blockbench",
"textures": {
"belt_funnel": "create:block/belt_funnel",
"particle": "create:block/belt_funnel",
"brass_casing": "create:block/brass_casing"
},
"elements": [
{
"name": "Bottom",
"from": [3, -4.1, -1],
"to": [13, -3.1, 5],
"faces": {
"north": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"east": {"uv": [10, 11, 16, 12], "texture": "#belt_funnel"},
"south": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"west": {"uv": [10, 11, 16, 12], "rotation": 180, "texture": "#belt_funnel"},
"up": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Top",
"from": [3, 7, -1],
"to": [13, 8, 5],
"faces": {
"north": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"east": {"uv": [10, 0, 16, 1], "texture": "#belt_funnel"},
"south": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"west": {"uv": [10, 0, 16, 1], "rotation": 180, "texture": "#belt_funnel"},
"up": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Side",
"from": [3, -3.1, -1],
"to": [4, 7, 5],
"faces": {
"north": {"uv": [9, 1, 10, 11.1], "texture": "#belt_funnel"},
"east": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"},
"south": {"uv": [0, 1, 1, 11.1], "texture": "#belt_funnel"},
"west": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"}
}
},
{
"name": "Center",
"from": [4, -3.1, -1],
"to": [12, 7, 4],
"faces": {
"north": {"uv": [4, 3, 12, 13.1], "texture": "#brass_casing"},
"east": {"uv": [9, 3, 10, 9], "rotation": 90, "texture": "#belt_funnel"},
"south": {"uv": [1, 1, 9, 11.1], "texture": "#belt_funnel"},
"west": {"uv": [0, 2, 1, 8], "rotation": 90, "texture": "#belt_funnel"}
}
},
{
"name": "Top",
"from": [4, 9, -1],
"to": [12, 10, 4.25],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"faces": {
"north": {"uv": [1, 12, 9, 13], "rotation": 180, "texture": "#belt_funnel"},
"east": {"uv": [10, 5, 16, 6], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [9, 2, 11, 10], "rotation": 90, "texture": "#belt_funnel"},
"west": {"uv": [10, 5, 16, 6], "texture": "#belt_funnel"},
"up": {"uv": [10, 2, 16, 10], "rotation": 90, "texture": "#belt_funnel"},
"down": {"uv": [1, 8, 9, 12.8], "texture": "#belt_funnel"}
}
},
{
"name": "Top",
"from": [4, 7, -1],
"to": [12, 9, 2.5],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"faces": {
"north": {"uv": [1, 11, 9, 13], "texture": "#belt_funnel"},
"east": {"uv": [10, 5, 14, 7], "rotation": 180, "texture": "#belt_funnel"},
"west": {"uv": [10, 5, 14, 6], "texture": "#belt_funnel"}
}
},
{
"name": "Ramp",
"from": [4, -4, -8],
"to": [12, 3, -1],
"rotation": {"angle": 45, "axis": "x", "origin": [8, -4, -1]},
"faces": {
"north": {"uv": [4, 5, 12, 12], "texture": "#brass_casing"},
"east": {"uv": [4, 9, 11, 16], "rotation": 90, "texture": "#brass_casing"},
"west": {"uv": [5, 9, 12, 16], "rotation": 270, "texture": "#brass_casing"},
"down": {"uv": [4, 0, 12, 7], "texture": "#brass_casing"}
}
},
{
"name": "Side",
"from": [12, -3.1, -1],
"to": [13, 7, 5],
"faces": {
"north": {"uv": [0, 1, 1, 11.1], "texture": "#belt_funnel"},
"east": {"uv": [10, 1, 16, 11], "rotation": 180, "texture": "#belt_funnel"},
"south": {"uv": [9, 1, 10, 11.1], "texture": "#belt_funnel"},
"west": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [-0.5, 3.25, 2.25],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [-0.5, 3.25, 2.25],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 0, 2.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.5, 1.75, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 3.5, -4.5],
"scale": [0.5, 0.5, 0.5]
}
}
}

View file

@ -1,75 +1,115 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"extractor": "create:block/extractor",
"textures": {
"1": "create:block/brass_casing",
"extractor": "create:block/extractor",
"particle": "create:block/extractor"
},
"elements": [
{
"name": "Bottom",
"from": [ 4, 2, -1 ],
"to": [ 12, 3, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 }
}
},
{
"name": "Top",
"from": [ 4, 9, -1 ],
"to": [ 12, 10, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 4, 3, -1 ],
"to": [ 5, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] },
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] }
}
},
{
"name": "Side",
"from": [ 11, 3, -1 ],
"to": [ 12, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] },
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] }
}
},
{
"name": "Center",
"from": [ 5, 3, 3 ],
"to": [ 11, 9, 4 ],
"faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] }
}
},
{
"name": "FilterSpot",
"from": [ 5, 10, -0.6 ],
"to": [ 11, 12, 4 ],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 },
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 },
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 }
}
}
]
},
"elements": [
{
"name": "Bottom",
"from": [4, 2, -1],
"to": [12, 3, 5],
"faces": {
"north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [4, 9, -1],
"to": [12, 10, 5],
"faces": {
"north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [4, 3, -1],
"to": [5, 9, 5],
"faces": {
"north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [11, 3, -1],
"to": [12, 9, 5],
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
},
{
"name": "Center",
"from": [5, 3, 0],
"to": [11, 9, 4],
"faces": {
"north": {"uv": [5, 5, 11, 11], "texture": "#1"},
"south": {"uv": [7, 1, 13, 7], "texture": "#extractor"}
}
},
{
"name": "FilterSpot",
"from": [5, 10, -0.6],
"to": [11, 12, 4],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8, 11, -1]},
"faces": {
"north": {"uv": [13, 1, 15, 7], "rotation": 90, "texture": "#extractor"},
"east": {"uv": [0.1, 0, 4.7, 2], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [4, 1, 5, 7], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [0.1, 0, 4.7, 2], "texture": "#extractor"},
"up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 1, 1.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.5, -0.5, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 1.75, -4.5],
"scale": [0.5, 0.5, 0.5]
}
}
}

View file

@ -1,112 +1,118 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"parent": "block/block",
"textures": {
"redstone_antenna": "create:block/redstone_antenna",
"extractor": "create:block/extractor",
"credit": "Made with Blockbench",
"parent": "create:block/extractor",
"textures": {
"2": "create:block/brass_casing",
"redstone_antenna": "create:block/redstone_antenna",
"extractor": "create:block/extractor",
"particle": "create:block/extractor"
},
"elements": [
{
"name": "Bottom",
"from": [ 4, 2, -1 ],
"to": [ 12, 3, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 }
}
},
{
"name": "Top",
"from": [ 4, 9, -1 ],
"to": [ 12, 10, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 4, 3, -1 ],
"to": [ 5, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] },
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] }
}
},
{
"name": "Side",
"from": [ 11, 3, -1 ],
"to": [ 12, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] },
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] }
}
},
{
"name": "Center",
"from": [ 5, 3, 3 ],
"to": [ 11, 9, 4 ],
"faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] }
}
},
{
"name": "FilterSpot",
"from": [ 5, 10, -0.6 ],
"to": [ 11, 12, 4 ],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 },
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 },
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 }
}
},
{
"name": "AntennaX",
"from": [ 11, 7, 2 ],
"to": [ 14, 17, 3 ],
"faces": {
"north": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"south": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"down": { "texture": "#redstone_antenna", "uv": [ 0, 9, 3, 10 ] }
}
},
{
"name": "AntennaZ",
"from": [ 12, 7, 1 ],
"to": [ 13, 17, 4 ],
"faces": {
"east": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"west": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }
}
},
{
"name": "AntennaTop",
"from": [ 12, 15, 2 ],
"to": [ 13, 16, 3 ],
"faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 1, 1, 2, 2 ] }
}
},
{
"name": "AntennaDish",
"from": [ 10, 13, 0 ],
"to": [ 15, 13, 5 ],
"faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] },
"down": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] }
}
}
]
},
"elements": [
{
"name": "Bottom",
"from": [4, 2, -1],
"to": [12, 3, 5],
"faces": {
"north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Top",
"from": [4, 9, -1],
"to": [12, 10, 5],
"faces": {
"north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [4, 3, -1],
"to": [5, 9, 5],
"faces": {
"north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
},
{
"name": "Side",
"from": [11, 3, -1],
"to": [12, 9, 5],
"faces": {
"north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
}
},
{
"name": "Center",
"from": [5, 3, 0],
"to": [11, 9, 4],
"faces": {
"north": {"uv": [5, 5, 11, 11], "texture": "#2"},
"south": {"uv": [7, 1, 13, 7], "texture": "#extractor"}
}
},
{
"name": "FilterSpot",
"from": [5, 10, -0.6],
"to": [11, 12, 4],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8, 11, -1]},
"faces": {
"north": {"uv": [13, 1, 15, 7], "rotation": 90, "texture": "#extractor"},
"east": {"uv": [0.1, 0, 4.7, 2], "rotation": 180, "texture": "#extractor"},
"south": {"uv": [4, 1, 5, 7], "rotation": 270, "texture": "#extractor"},
"west": {"uv": [0.1, 0, 4.7, 2], "texture": "#extractor"},
"up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"}
}
},
{
"name": "AntennaX",
"from": [11, 7, 2],
"to": [14, 17, 3],
"faces": {
"north": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"south": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaZ",
"from": [12, 7, 1],
"to": [13, 17, 4],
"faces": {
"east": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"west": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaTop",
"from": [12, 15, 2],
"to": [13, 16, 3],
"faces": {
"up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"}
}
},
{
"name": "AntennaDish",
"from": [10, 13, 0],
"to": [15, 13, 5],
"faces": {
"up": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"},
"down": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"}
}
}
]
}

View file

@ -1,86 +1,3 @@
{
"parent": "block/block",
"display": {
"gui": {
"rotation": [ 30, 45, 0 ],
"translation": [ 0, 0, 0],
"scale":[ 0.625, 0.625, 0.625 ]
},
"fixed": {
"rotation": [ 0, 180, 0 ],
"translation": [ 0, 0, -3.5],
"scale":[ 0.5, 0.5, 0.5 ]
}
},
"textures": {
"extractor": "create:block/extractor",
"particle": "create:block/extractor"
},
"elements": [
{
"name": "Bottom",
"from": [ 4, 2, -1 ],
"to": [ 12, 3, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 }
}
},
{
"name": "Top",
"from": [ 4, 9, -1 ],
"to": [ 12, 10, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 4, 3, -1 ],
"to": [ 5, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] },
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] }
}
},
{
"name": "Side",
"from": [ 11, 3, -1 ],
"to": [ 12, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] },
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] }
}
},
{
"name": "Center",
"from": [ 5, 3, 3 ],
"to": [ 11, 9, 4 ],
"faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] }
}
},
{
"name": "FilterSpot",
"from": [ 5, 10, -0.6 ],
"to": [ 11, 12, 4 ],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 },
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 },
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 }
}
}
]
"parent": "create:block/extractor"
}

View file

@ -1,123 +1,3 @@
{
"parent": "block/block",
"display": {
"gui": {
"rotation": [ 30, 45, 0 ],
"translation": [ 0, 0, 0],
"scale":[ 0.625, 0.625, 0.625 ]
},
"fixed": {
"rotation": [ 0, 180, 0 ],
"translation": [ 0, 0, -3.5],
"scale":[ 0.5, 0.5, 0.5 ]
}
},
"textures": {
"redstone_antenna": "create:block/redstone_antenna",
"extractor": "create:block/extractor",
"particle": "create:block/extractor"
},
"elements": [
{
"name": "Bottom",
"from": [ 4, 2, -1 ],
"to": [ 12, 3, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 }
}
},
{
"name": "Top",
"from": [ 4, 9, -1 ],
"to": [ 12, 10, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 4, 3, -1 ],
"to": [ 5, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] },
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] }
}
},
{
"name": "Side",
"from": [ 11, 3, -1 ],
"to": [ 12, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] },
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] }
}
},
{
"name": "Center",
"from": [ 5, 3, 3 ],
"to": [ 11, 9, 4 ],
"faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] }
}
},
{
"name": "FilterSpot",
"from": [ 5, 10, -0.6 ],
"to": [ 11, 12, 4 ],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 },
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 },
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 }
}
},
{
"name": "AntennaX",
"from": [ 11, 7, 2 ],
"to": [ 14, 17, 3 ],
"faces": {
"north": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"south": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"down": { "texture": "#redstone_antenna", "uv": [ 0, 9, 3, 10 ] }
}
},
{
"name": "AntennaZ",
"from": [ 12, 7, 1 ],
"to": [ 13, 17, 4 ],
"faces": {
"east": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"west": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }
}
},
{
"name": "AntennaTop",
"from": [ 12, 15, 2 ],
"to": [ 13, 16, 3 ],
"faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 1, 1, 2, 2 ] }
}
},
{
"name": "AntennaDish",
"from": [ 10, 13, 0 ],
"to": [ 15, 13, 5 ],
"faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] },
"down": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] }
}
}
]
"parent": "create:block/extractor_wireless"
}