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 class TessellatorHelper {
public static final float fontScale = 1/512f; public static final float fontScale = 1 / 512f;
public static void prepareForDrawing() { public static void prepareForDrawing() {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
GlStateManager.pushLightingAttributes(); GlStateManager.pushLightingAttributes();
GlStateManager.enableBlend(); GlStateManager.enableBlend();
GlStateManager.enableAlphaTest(); GlStateManager.enableAlphaTest();
GlStateManager.color4f(1, 1, 1, 1); GlStateManager.color4f(1, 1, 1, 1);
ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo(); ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo();
Vec3d view = renderInfo.getProjectedView(); Vec3d view = renderInfo.getProjectedView();
GlStateManager.translated(-view.x, -view.y, -view.z); GlStateManager.translated(-view.x, -view.y, -view.z);
} }
public static void prepareFastRender() { public static void prepareFastRender() {
Minecraft.getInstance().textureManager Minecraft.getInstance().textureManager.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting(); net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.enableBlend(); GlStateManager.enableBlend();
@ -47,24 +46,24 @@ public class TessellatorHelper {
GlStateManager.color3f(1, 1, 1); GlStateManager.color3f(1, 1, 1);
} }
public static void begin() { public static void begin() {
begin(DefaultVertexFormats.POSITION_TEX); begin(DefaultVertexFormats.POSITION_TEX);
} }
public static void begin(VertexFormat format) { public static void begin(VertexFormat format) {
Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, format); Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, format);
} }
public static void draw() { public static void draw() {
Tessellator.getInstance().draw(); Tessellator.getInstance().draw();
} }
public static void cleanUpAfterDrawing() { public static void cleanUpAfterDrawing() {
GlStateManager.disableAlphaTest(); GlStateManager.disableAlphaTest();
GlStateManager.disableBlend(); GlStateManager.disableBlend();
GlStateManager.popAttributes(); GlStateManager.popAttributes();
GlStateManager.popMatrix(); GlStateManager.popMatrix();
} }
public static void drawString(String str, float x, float y, float z, boolean scalesUp, boolean hasDepth) { public static void drawString(String str, float x, float y, float z, boolean scalesUp, boolean hasDepth) {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
@ -122,117 +121,123 @@ public class TessellatorHelper {
GlStateManager.popAttributes(); GlStateManager.popAttributes();
} }
public static void cube(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale, public static void cube(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale,
boolean scaleVertical, boolean doubleFaces) { boolean scaleVertical, boolean doubleFaces) {
TessellatorHelper.walls(bufferBuilder, pos, size, scale, scaleVertical, doubleFaces); TessellatorHelper.walls(bufferBuilder, pos, size, scale, scaleVertical, doubleFaces);
int w = size.getX(); int w = size.getX();
int h = size.getY(); int h = size.getY();
int l = size.getZ(); int l = size.getZ();
if (doubleFaces) { if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false); 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); TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true,
} else { scaleVertical, false);
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false, false); } else {
TessellatorHelper.face(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical, false, false); 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 walls(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale, public static void walls(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale,
boolean scaleVertical, boolean doubleFaces) { boolean scaleVertical, boolean doubleFaces) {
int w = size.getX(); int w = size.getX();
int h = size.getY(); int h = size.getY();
int l = size.getZ(); int l = size.getZ();
if (doubleFaces) { if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false); 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(0, h, -l), scale, true,
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false); scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false); TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true,
} else { scaleVertical, false);
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false, false); TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true, scaleVertical, false, false); } else {
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false, false); TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(0, h, l), 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 doubleFace(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift, public static void doubleFace(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift,
boolean stretch, boolean shiftVertical, boolean mirrorTexture) { boolean stretch, boolean shiftVertical, boolean mirrorTexture) {
TessellatorHelper.face(bufferBuilder, pos, size, shift, stretch, shiftVertical, false, 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()), 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, new BlockPos(-size.getX(), size.getY(), (size.getY() == 0) ? size.getZ() : -size.getZ()), -shift,
stretch, shiftVertical, true, mirrorTexture); stretch, shiftVertical, true, mirrorTexture);
} }
public static void face(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift, boolean stretch, public static void face(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift, boolean stretch,
boolean shiftVertical, boolean shiftBackwards, boolean mirrorTexture) { boolean shiftVertical, boolean shiftBackwards, boolean mirrorTexture) {
int w = size.getX(); int w = size.getX();
int h = size.getY(); int h = size.getY();
int l = size.getZ(); int l = size.getZ();
if (shiftBackwards) if (shiftBackwards)
shift = -shift; shift = -shift;
if (w == 0) { // YZ plane -> H has to be positive if (w == 0) { // YZ plane -> H has to be positive
double xs = (l < 0) ? shift : -shift; double xs = (l < 0) ? shift : -shift;
if (shiftBackwards) if (shiftBackwards)
xs = -xs; xs = -xs;
double ys1 = shiftVertical ? shift : 0; double ys1 = shiftVertical ? shift : 0;
double zs1 = l < 0 ? -shift : shift; double zs1 = l < 0 ? -shift : shift;
if (!stretch && (l > 0 ^ mirrorTexture)) if (!stretch && (l > 0 ^ mirrorTexture))
zs1 = -zs1; zs1 = -zs1;
double ys2 = stretch ? -ys1 : ys1; double ys2 = stretch ? -ys1 : ys1;
double zs2 = stretch ? -zs1 : zs1; double zs2 = stretch ? -zs1 : zs1;
double u1 = (mirrorTexture) ? l : 0; double u1 = (mirrorTexture) ? l : 0;
double u2 = (mirrorTexture) ? 0 : l; double u2 = (mirrorTexture) ? 0 : l;
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs1), pos.south(l), u2, h); 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, 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, ys1, zs2), pos.up(h), u1, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs2), pos, u1, h); TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs2), pos, u1, h);
} else if (h == 0) { // XZ plane -> L has to be positive } else if (h == 0) { // XZ plane -> L has to be positive
double ys = w < 0 ? shift : -shift; double ys = w < 0 ? shift : -shift;
if (shiftBackwards) if (shiftBackwards)
ys = -ys; ys = -ys;
double xs1 = w < 0 ? -shift : shift; double xs1 = w < 0 ? -shift : shift;
double zs1 = shift; double zs1 = shift;
double xs2 = stretch ? -xs1 : xs1; double xs2 = stretch ? -xs1 : xs1;
double zs2 = stretch ? -zs1 : zs1; double zs2 = stretch ? -zs1 : zs1;
double u1 = (mirrorTexture) ? w : 0; double u1 = (mirrorTexture) ? w : 0;
double u2 = (mirrorTexture) ? 0 : w; double u2 = (mirrorTexture) ? 0 : w;
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys, zs1), pos.south(l), u1, l); 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(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, zs2), pos.east(w), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs1), pos.east(w).south(l), u2, l); TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs1), pos.east(w).south(l), u2, l);
} else if (l == 0) { // XY plane -> H has to be positive } else if (l == 0) { // XY plane -> H has to be positive
double zs = w < 0 ? shift : -shift; double zs = w < 0 ? shift : -shift;
if (shiftBackwards) if (shiftBackwards)
zs = -zs; zs = -zs;
double ys1 = shiftVertical ? shift : 0; double ys1 = shiftVertical ? shift : 0;
double xs1 = w < 0 ? -shift : shift; double xs1 = w < 0 ? -shift : shift;
if (!stretch && (w > 0 ^ mirrorTexture)) if (!stretch && (w > 0 ^ mirrorTexture))
xs1 = -xs1; xs1 = -xs1;
double ys2 = stretch ? -ys1 : ys1; double ys2 = stretch ? -ys1 : ys1;
double xs2 = stretch ? -xs1 : xs1; double xs2 = stretch ? -xs1 : xs1;
double u1 = (mirrorTexture) ? w : 0; double u1 = (mirrorTexture) ? w : 0;
double u2 = (mirrorTexture) ? 0 : w; double u2 = (mirrorTexture) ? 0 : w;
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys2, zs), pos, u1, h); 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(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, ys1, zs), pos.east(w).up(h), u2, 0);
TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys2, zs), pos.east(w), u2, h); 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) { 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(); 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.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer; import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer; 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.client.resources.ReloadListener;
import net.minecraft.profiler.IProfiler; import net.minecraft.profiler.IProfiler;
@ -23,7 +22,6 @@ public class CachedBufferReloader extends ReloadListener<String> {
ContraptionRenderer.invalidateCache(); ContraptionRenderer.invalidateCache();
MechanicalBearingTileEntityRenderer.invalidateCache(); MechanicalBearingTileEntityRenderer.invalidateCache();
ColoredIndicatorRenderer.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.BELT;
import static com.simibubi.create.AllBlocks.COGWHEEL; 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.AllBlocks.LARGE_COGWHEEL;
import static com.simibubi.create.CreateConfig.parameters; import static com.simibubi.create.CreateConfig.parameters;
import static net.minecraft.state.properties.BlockStateProperties.AXIS; 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.AllBlocks;
import com.simibubi.create.foundation.block.IRenderUtilityBlock; import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.block.IWithTileEntity; 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.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; 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.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; 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.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.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock; 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.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -99,8 +100,8 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
} }
@Override @Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) { public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
return Arrays.asList(te.getPos().up(2)); return Arrays.asList(pos.up(2));
} }
@Override @Override
@ -112,15 +113,35 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
} }
@Override @Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) { public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
BlockState blockState = world.getBlockState(pos.down(2)); return pos.down(2);
if (!AllBlocks.BELT.typeOf(blockState) || blockState.get(BeltBlock.SLOPE) != Slope.HORIZONTAL)
return Optional.empty();
return Optional.of(pos.down(2));
} }
@Override @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() MechanicalPressTileEntity pressTe = (MechanicalPressTileEntity) te.getWorld()
.getTileEntity(state.attachmentPos); .getTileEntity(state.attachmentPos);
@ -128,42 +149,23 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
if (pressTe == null || pressTe.getSpeed() == 0) if (pressTe == null || pressTe.getSpeed() == 0)
return false; return false;
// Not an Item
if (!(entity instanceof ItemEntity))
return false;
// Running // Running
if (pressTe.running) { if (pressTe.running) {
double distanceTo = entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())); if (pressTe.runningTicks == 30) {
if (distanceTo < .32f) Optional<PressingRecipe> recipe = pressTe.getRecipe(transportedStack.stack);
return true; if (!recipe.isPresent())
if (distanceTo < .4f) { return false;
entity.setPosition(te.getPos().getX() + .5f, entity.posY, te.getPos().getZ() + .5f); ItemStack out = recipe.get().getRecipeOutput().copy();
return true; 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; return true;
}
// 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 false; return false;

View file

@ -6,13 +6,17 @@ import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; 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 com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
@ -90,26 +94,40 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
return; return;
if (runningTicks == 30) { 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) { if (!beltMode) {
for (int i = 0; i < 20; i++) { AxisAlignedBB bb = new AxisAlignedBB(pos.down(beltMode ? 2 : 1));
Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .25f).mul(1, 0, 1); for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, itemEntity.getItem()), entity.posX, if (!(entity instanceof ItemEntity))
entity.posY, entity.posZ, motion.x, motion.y, motion.z); 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) { if (!world.isRemote) {
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, .5f, 1f); world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, .5f, 1f);
world.playSound(null, getPos(), SoundEvents.BLOCK_ANVIL_LAND, SoundCategory.BLOCKS, .125f, 1f); world.playSound(null, getPos(), SoundEvents.BLOCK_ANVIL_LAND, SoundCategory.BLOCKS, .125f, 1f);
@ -128,8 +146,18 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
runningTicks++; runningTicks++;
} }
public Optional<PressingRecipe> getRecipe(ItemEntity itemEntity) { public void makeParticleEffect(Vec3d pos, ItemStack stack) {
pressingInv.setInventorySlotContents(0, itemEntity.getItem()); 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, Optional<PressingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.PRESSING, pressingInv,
world); world);
return recipe; return recipe;

View file

@ -4,10 +4,11 @@ import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
public class ProcessingInventory extends RecipeWrapper { public class ProcessingInventory extends RecipeWrapper implements IItemHandler {
protected int remainingTime; protected int remainingTime;
protected int recipeDuration; protected int recipeDuration;
protected boolean appliedRecipe; protected boolean appliedRecipe;
@ -50,8 +51,40 @@ public class ProcessingInventory extends RecipeWrapper {
return inventory; return inventory;
} }
@Override
public int getInventoryStackLimit() {
return 64;
}
public ItemStackHandler getItems() { public ItemStackHandler getItems() {
return (ItemStackHandler) inv; 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.Random;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllRecipes; import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; 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 com.simibubi.create.modules.logistics.block.IHaveFilter;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
@ -24,15 +26,23 @@ import net.minecraft.particles.BlockParticleData;
import net.minecraft.particles.IParticleData; import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; 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.MathHelper;
import net.minecraft.util.math.Vec3d; 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 class SawTileEntity extends KineticTileEntity implements IHaveFilter {
public ProcessingInventory inventory; public ProcessingInventory inventory;
private int recipeIndex; private int recipeIndex;
private ItemStack filter; private ItemStack filter;
private LazyOptional<IItemHandler> invProvider = LazyOptional.empty();
public SawTileEntity() { public SawTileEntity() {
super(AllTileEntities.SAW.type); super(AllTileEntities.SAW.type);
@ -40,6 +50,7 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
inventory.remainingTime = -1; inventory.remainingTime = -1;
filter = ItemStack.EMPTY; filter = ItemStack.EMPTY;
recipeIndex = 0; recipeIndex = 0;
invProvider = LazyOptional.of(() -> inventory);
} }
@Override @Override
@ -78,12 +89,17 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return; return;
if (getSpeed() == 0) if (getSpeed() == 0)
return; return;
if (inventory.remainingTime == -1) if (inventory.remainingTime == -1) {
if (!inventory.isEmpty() && !inventory.appliedRecipe)
start();
return; return;
}
float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 32, 1, 128); float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 32, 1, 128);
inventory.remainingTime -= processingSpeed; inventory.remainingTime -= processingSpeed;
spawnParticles(inventory.getStackInSlot(0));
if (inventory.remainingTime > 0)
spawnParticles(inventory.getStackInSlot(0));
if (world.isRemote) if (world.isRemote)
return; return;
@ -95,10 +111,69 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return; return;
} }
Vec3d outPos = VecHelper.getCenterOf(pos).add(getItemMovementVec().scale(.5f).add(0, .5, 0)); Vec3d itemMovement = getItemMovementVec();
Vec3d outMotion = getItemMovementVec().scale(.0625).add(0, .125, 0); 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) { 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++) { for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot); ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty()) if (stack.isEmpty())
@ -108,6 +183,7 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
world.addEntity(entityIn); world.addEntity(entityIn);
} }
inventory.clear(); inventory.clear();
world.updateComparatorOutputLevel(pos, getBlockState().getBlock());
inventory.remainingTime = -1; inventory.remainingTime = -1;
sendData(); sendData();
return; return;
@ -116,6 +192,19 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return; 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) { protected void spawnParticles(ItemStack stack) {
if (stack == null || stack.isEmpty()) if (stack == null || stack.isEmpty())
return; return;
@ -198,6 +287,17 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
inventory.clear(); inventory.clear();
inventory.setInventorySlotContents(0, entity.getItem().copy()); 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(); List<IRecipe<?>> recipes = getRecipes();
boolean valid = !recipes.isEmpty(); boolean valid = !recipes.isEmpty();
@ -206,7 +306,6 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
if (recipes.isEmpty()) { if (recipes.isEmpty()) {
inventory.remainingTime = inventory.recipeDuration = 10; inventory.remainingTime = inventory.recipeDuration = 10;
inventory.appliedRecipe = false; inventory.appliedRecipe = false;
entity.remove();
sendData(); sendData();
return; return;
} }
@ -222,11 +321,9 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
time = ((CuttingRecipe) recipe).getProcessingDuration(); 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.recipeDuration = inventory.remainingTime;
inventory.appliedRecipe = false; inventory.appliedRecipe = false;
entity.remove();
sendData(); sendData();
} }

View file

@ -24,6 +24,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> { public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
@ -43,9 +44,11 @@ public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE); boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE);
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
float offset = te.inventory.recipeDuration != 0 boolean moving = te.inventory.recipeDuration != 0;
? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration float offset = moving ? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration : 0;
: 0; if (moving)
offset = MathHelper.clamp(offset + (-partialTicks + .5f) / te.inventory.recipeDuration, 0, 1);
if (te.getSpeed() == 0) if (te.getSpeed() == 0)
offset = .5f; offset = .5f;
if (te.getSpeed() < 0 ^ alongZ) if (te.getSpeed() < 0 ^ alongZ)

View file

@ -2,11 +2,11 @@ package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT; import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -33,32 +34,52 @@ public enum AllBeltAttachments {
} }
public interface IBeltAttachment { 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) { default void onAttachmentPlaced(IWorld world, BlockPos pos, BlockState state) {
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state); BlockPos beltPos = getBeltPositionForAttachment(world, pos, state);
if (!beltPos.isPresent()) TileEntity te = world.getTileEntity(beltPos);
if (te == null || !(te instanceof BeltTileEntity))
return; return;
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get()); BeltTileEntity belt = (BeltTileEntity) te;
if (te == null) if (!isAttachedCorrectly(world, pos, belt.getPos(), state, belt.getBlockState()))
return; return;
te.attachmentTracker.addAttachment(world, pos); belt.attachmentTracker.addAttachment(world, pos);
te.sendData(); belt.markDirty();
belt.sendData();
} }
default void onAttachmentRemoved(IWorld world, BlockPos pos, BlockState state) { default void onAttachmentRemoved(IWorld world, BlockPos pos, BlockState state) {
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state); BlockPos beltPos = getBeltPositionForAttachment(world, pos, state);
if (!beltPos.isPresent()) TileEntity te = world.getTileEntity(beltPos);
if (te == null || !(te instanceof BeltTileEntity))
return; return;
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get()); BeltTileEntity belt = (BeltTileEntity) te;
if (te == null) if (!isAttachedCorrectly(world, pos, belt.getPos(), state, belt.getBlockState()))
return; return;
te.attachmentTracker.removeAttachment(pos); belt.attachmentTracker.removeAttachment(pos);
te.sendData(); belt.markDirty();
belt.sendData();
} }
} }
@ -67,6 +88,7 @@ public enum AllBeltAttachments {
public BlockPos attachmentPos; public BlockPos attachmentPos;
public int processingDuration; public int processingDuration;
public Entity processingEntity; public Entity processingEntity;
public TransportedItemStack processingStack;
public BeltAttachmentState(IBeltAttachment attachment, BlockPos attachmentPos) { public BeltAttachmentState(IBeltAttachment attachment, BlockPos attachmentPos) {
this.attachment = attachment; this.attachment = attachment;
@ -86,19 +108,25 @@ public enum AllBeltAttachments {
public void findAttachments(BeltTileEntity belt) { public void findAttachments(BeltTileEntity belt) {
for (AllBeltAttachments ba : AllBeltAttachments.values()) { for (AllBeltAttachments ba : AllBeltAttachments.values()) {
List<BlockPos> attachmentPositions = ba.attachment.getPotentialAttachmentLocations(belt);
World world = belt.getWorld(); 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) { for (BlockPos potentialPos : attachmentPositions) {
if (!world.isBlockPresent(potentialPos)) if (!world.isBlockPresent(potentialPos))
continue; continue;
BlockState state = world.getBlockState(potentialPos); BlockState state = world.getBlockState(potentialPos);
if (!(state.getBlock() instanceof IBeltAttachment)) if (!(state.getBlock() instanceof IBeltAttachment))
continue; continue;
Optional<BlockPos> validBeltPos = ((IBeltAttachment) state.getBlock()).getValidBeltPositionFor(world, potentialPos, state); IBeltAttachment attachment = (IBeltAttachment) state.getBlock();
if (!validBeltPos.isPresent()) if (!attachment.getBeltPositionForAttachment(world, potentialPos, state).equals(beltPos))
continue; continue;
if (validBeltPos.get().equals(belt.getPos())) if (!attachment.isAttachedCorrectly(world, potentialPos, beltPos, state, beltState))
addAttachment(world, potentialPos); 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.block.IWithoutBlockItem;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; 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 com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -38,7 +39,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.Tags; import net.minecraftforge.common.Tags;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.IItemHandler;
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> { 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 (entityIn instanceof ItemEntity && entityIn.isAlive()) {
if (worldIn.isRemote) if (worldIn.isRemote)
return; return;
if (entityIn.getMotion().y > 0)
return;
withTileEntityDo(worldIn, pos, te -> { withTileEntityDo(worldIn, pos, te -> {
ItemEntity itemEntity = (ItemEntity) entityIn; ItemEntity itemEntity = (ItemEntity) entityIn;
ItemStack remainder = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) IItemHandler handler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
.orElseGet(() -> new ItemStackHandler(0)).insertItem(0, itemEntity.getItem().copy(), false); if (handler == null)
return;
ItemStack remainder = handler.insertItem(0, itemEntity.getItem().copy(), false);
if (remainder.isEmpty()) if (remainder.isEmpty())
itemEntity.remove(); itemEntity.remove();
}); });
@ -133,19 +138,42 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
if (player.isSneaking() || !player.isAllowEdit()) if (player.isSneaking() || !player.isAllowEdit())
return false; return false;
ItemStack heldItem = player.getHeldItem(handIn); ItemStack heldItem = player.getHeldItem(handIn);
if (!Tags.Items.DYES.contains(heldItem.getItem())) boolean isShaft = heldItem.getItem() == AllBlocks.SHAFT.get().asItem();
return false; boolean isDye = Tags.Items.DYES.contains(heldItem.getItem());
if (worldIn.isRemote)
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; return true;
withTileEntityDo(worldIn, pos, te -> { }
DyeColor dyeColor = DyeColor.getColor(heldItem);
if (dyeColor == null) if (isDye) {
return; if (worldIn.isRemote)
te.applyColor(dyeColor); return true;
}); withTileEntityDo(worldIn, pos, te -> {
if (!player.isCreative()) DyeColor dyeColor = DyeColor.getColor(heldItem);
heldItem.shrink(1); if (dyeColor == null)
return true; return;
te.applyColor(dyeColor);
});
if (!player.isCreative())
heldItem.shrink(1);
return true;
}
return false;
} }
@Override @Override
@ -177,8 +205,15 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
@Override @Override
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
withTileEntityDo(worldIn, pos, te -> { 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); 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); super.onBlockHarvested(worldIn, pos, state, player);
} }
@ -211,16 +246,20 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
break; break;
BeltTileEntity te = (BeltTileEntity) worldIn.getTileEntity(toDestroy); 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.setSource(null);
te.remove(); te.remove();
if (hasPulley) { if (te.hasPulley())
worldIn.setBlockState(toDestroy, AllBlocks.SHAFT.get().getDefaultState() worldIn.setBlockState(toDestroy, AllBlocks.SHAFT.get().getDefaultState()
.with(BlockStateProperties.AXIS, getRotationAxis(destroyedBlock)), 3); .with(BlockStateProperties.AXIS, getRotationAxis(destroyedBlock)), 3);
} else { else
worldIn.destroyBlock(toDestroy, false); worldIn.destroyBlock(toDestroy, false);
}
if (destroyedBlock.get(PART) == Part.END) if (destroyedBlock.get(PART) == Part.END)
break; break;

View file

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

View file

@ -93,7 +93,7 @@ public class BeltMovementHandler {
// Attachment pauses movement // Attachment pauses movement
for (BeltAttachmentState state : belt.attachmentTracker.attachments) { for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
if (state.attachment.handleEntity(belt, entityIn, state)) { if (state.attachment.processEntity(belt, entityIn, state)) {
info.ticksSinceLastCollision--; info.ticksSinceLastCollision--;
return; 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.AllBeltAttachments.Tracker;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; 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.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo; import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.item.DyeColor; import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
@ -197,6 +199,13 @@ public class BeltTileEntity extends KineticTileEntity {
return getSpeed() / 1600f; 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() { public boolean hasPulley() {
if (!AllBlocks.BELT.typeOf(getBlockState())) if (!AllBlocks.BELT.typeOf(getBlockState()))
return false; return false;
@ -270,4 +279,44 @@ public class BeltTileEntity extends KineticTileEntity {
return inventory; 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.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.IndependentShadowRenderer;
import com.simibubi.create.foundation.utility.TessellatorHelper; import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; 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.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder; 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.Tessellator;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer; 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.state.properties.BlockStateProperties;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
@ -28,27 +32,66 @@ public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
@Override @Override
public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) { public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(te, x, y, z, partialTicks, 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.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK); TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer()); renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw(); 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 @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 static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper; 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.item.CardboardBoxItem;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; 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.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@ -126,6 +130,8 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
IItemHandler inv = getInventory().orElse(null); IItemHandler inv = getInventory().orElse(null);
ItemStack extracting = ItemStack.EMPTY; ItemStack extracting = ItemStack.EMPTY;
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : 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() int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get()
: filterItem.getCount(); : filterItem.getCount();
boolean checkHasEnoughItems = !filterItem.isEmpty(); boolean checkHasEnoughItems = !filterItem.isEmpty();
@ -171,18 +177,26 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
break Extraction; break Extraction;
} while (true); } 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) { if (!simulate && hasEnoughItems) {
World world = getWorld(); Vec3d entityPos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Vec3d pos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Entity entityIn = null; Entity entityIn = null;
if (extracting.getItem() instanceof CardboardBoxItem) { if (extracting.getItem() instanceof CardboardBoxItem) {
Direction face = getWorld().getBlockState(getPos()).get(HORIZONTAL_FACING).getOpposite(); 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); world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .25f, .05f);
} else { } 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); entityIn.setMotion(Vec3d.ZERO);
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, .1f); 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.Arrays;
import java.util.List; 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.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.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; 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.BeltInventory.TransportedItemStack;
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.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator; 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.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock; 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.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; 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.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.shapes.VoxelShapes;
@ -138,33 +131,32 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
} }
@Override @Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) { public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
return Arrays.asList(te.getPos().up()); return Arrays.asList(pos.up());
} }
@Override @Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) { public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
BlockPos validPos = pos.down(); return 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);
} }
@Override @Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
boolean isItem = entity instanceof ItemEntity; return process(te, transported, state);
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);
});
@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; 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.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity; 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.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.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ItemParticleData;
@ -16,6 +15,7 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@ -27,6 +27,8 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
protected boolean waitingForInventorySpace; protected boolean waitingForInventorySpace;
private boolean initialize; private boolean initialize;
private ItemStack justEaten;
public BeltFunnelTileEntity() { public BeltFunnelTileEntity() {
super(AllTileEntities.BELT_FUNNEL.type); super(AllTileEntities.BELT_FUNNEL.type);
inventory = LazyOptional.empty(); inventory = LazyOptional.empty();
@ -38,22 +40,33 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
super.read(compound); super.read(compound);
} }
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Waiting", waitingForInventorySpace);
return super.write(compound);
}
@Override @Override
public void onLoad() { public void onLoad() {
initialize = true; initialize = true;
} }
@Override
public CompoundNBT writeToClient(CompoundNBT tag) {
if (justEaten != null) {
tag.put("Nom", justEaten.serializeNBT());
justEaten = null;
}
return super.writeToClient(tag);
}
@Override @Override
public void readClientUpdate(CompoundNBT tag) { public void readClientUpdate(CompoundNBT tag) {
super.readClientUpdate(tag); super.readClientUpdate(tag);
if (!waitingForInventorySpace) if (!waitingForInventorySpace)
neighborChanged(); neighborChanged();
} if (tag.contains("Nom"))
justEaten = ItemStack.read(tag.getCompound("Nom"));
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Waiting", waitingForInventorySpace);
return super.write(compound);
} }
@Override @Override
@ -72,6 +85,10 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
neighborChanged(); neighborChanged();
initialize = false; initialize = false;
} }
if (world.isRemote && justEaten != null) {
spawnParticles(justEaten);
justEaten = null;
}
} }
@Override @Override
@ -87,42 +104,34 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
sendData(); sendData();
} }
public void tryToInsert(Entity entity) { public ItemStack tryToInsert(ItemStack stack) {
if (!inventory.isPresent()) if (!inventory.isPresent())
return; return stack;
if (waitingForInventorySpace) if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerSegment))
return; return stack;
ItemStack stack = null;
if (entity instanceof ItemEntity)
stack = ((ItemEntity) entity).getItem().copy();
if (entity instanceof CardboardBoxEntity)
stack = ((CardboardBoxEntity) entity).getBox().copy();
IItemHandler inv = inventory.orElse(null); IItemHandler inv = inventory.orElse(null);
stack = ItemHandlerHelper.insertItemStacked(inv, stack, false); ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, stack.copy(), false);
if (stack.isEmpty()) { if (remainder.isEmpty()) {
if (!world.isRemote) { if (!world.isRemote)
entity.remove();
world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f); world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f);
} else { justEaten = stack;
Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec(); } else {
float xSpeed = directionVec.getX() * 1 / 8f; waitingForInventorySpace = true;
float zSpeed = directionVec.getZ() * 1 / 8f;
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), entity.posX,
entity.posY, entity.posZ, xSpeed, 1 / 6f, zSpeed);
}
return;
} }
waitingForInventorySpace = true;
sendData(); sendData();
return remainder;
}
if (entity instanceof ItemEntity) public void spawnParticles(ItemStack stack) {
if (!stack.equals(((ItemEntity) entity).getItem(), false)) Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec();
((ItemEntity) entity).setItem(stack); 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Random; import java.util.Random;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
@ -129,16 +128,20 @@ public class EntityDetectorBlock extends HorizontalBlock
} }
@Override @Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) { public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
Direction side = te.getBlockState().get(BeltBlock.HORIZONTAL_FACING).rotateY(); Direction side = beltState.get(BeltBlock.HORIZONTAL_FACING).rotateY();
return Arrays.asList(te.getPos().offset(side), te.getPos().offset(side.getOpposite())); return Arrays.asList(pos.offset(side), pos.offset(side.getOpposite()));
} }
@Override @Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) { public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
if (!state.get(BELT)) return pos.offset(state.get(HORIZONTAL_FACING));
return Optional.empty(); }
return Optional.of(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 @Override
@ -178,7 +181,7 @@ public class EntityDetectorBlock extends HorizontalBlock
} }
@Override @Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { public boolean processEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
if (te.getWorld().isRemote) if (te.getWorld().isRemote)
return false; return false;

View file

@ -1,95 +1,140 @@
{ {
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", "credit": "Made with Blockbench",
"textures": { "textures": {
"particle": "create:block/belt_funnel", "belt_funnel": "create:block/belt_funnel",
"belt_funnel": "create:block/belt_funnel", "particle": "create:block/belt_funnel",
"brass_casing": "create:block/brass_casing" "brass_casing": "create:block/brass_casing"
}, },
"elements": [ "elements": [
{ {
"name": "Bottom", "name": "Bottom",
"from": [ 3, -4.1, -1 ], "from": [3, -4.1, -1],
"to": [ 13, -3.1, 5 ], "to": [13, -3.1, 5],
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] }, "north": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ] }, "east": {"uv": [10, 11, 16, 12], "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] }, "south": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ], "rotation": 180 }, "west": {"uv": [10, 11, 16, 12], "rotation": 180, "texture": "#belt_funnel"},
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 }, "up": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"},
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 } "down": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"}
} }
}, },
{ {
"name": "Top", "name": "Top",
"from": [ 3, 7, -1 ], "from": [3, 7, -1],
"to": [ 13, 8, 5 ], "to": [13, 8, 5],
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] }, "north": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 1 ] }, "east": {"uv": [10, 0, 16, 1], "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] }, "south": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 1 ], "rotation": 180 }, "west": {"uv": [10, 0, 16, 1], "rotation": 180, "texture": "#belt_funnel"},
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 }, "up": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"},
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 } "down": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"}
} }
}, },
{ {
"name": "Side", "name": "Side",
"from": [ 3, -3.1, -1 ], "from": [3, -3.1, -1],
"to": [ 4, 7, 5 ], "to": [4, 7, 5],
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] }, "north": {"uv": [9, 1, 10, 11.1], "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] }, "east": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] }, "south": {"uv": [0, 1, 1, 11.1], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] } "west": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"}
} }
}, },
{ {
"name": "Center", "name": "Center",
"from": [ 4, -3.1, -1 ], "from": [4, -3.1, -1],
"to": [ 12, 7, 4 ], "to": [12, 7, 4],
"faces": { "faces": {
"north": { "texture": "#brass_casing", "uv": [ 4, 3, 12, 13.1 ] }, "north": {"uv": [4, 3, 12, 13.1], "texture": "#brass_casing"},
"east": { "texture": "#belt_funnel", "uv": [ 9, 3, 10, 9 ], "rotation": 90 }, "east": {"uv": [9, 3, 10, 9], "rotation": 90, "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 1, 1, 9, 11.1 ] }, "south": {"uv": [1, 1, 9, 11.1], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 0, 2, 1, 8 ], "rotation": 90 } "west": {"uv": [0, 2, 1, 8], "rotation": 90, "texture": "#belt_funnel"}
} }
}, },
{ {
"name": "Top", "name": "Top",
"from": [ 4, 6, 0 ], "from": [4, 9, -1],
"to": [ 12, 8, 4.8 ], "to": [12, 10, 4.25],
"rotation": { "origin": [ 8, 8, 0 ], "axis": "x", "angle": -22.5 }, "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 1, 7, 9, 9 ], "rotation": 180 }, "north": {"uv": [1, 12, 9, 13], "rotation": 180, "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 11, 4.6, 16, 6.6 ], "rotation": 180 }, "east": {"uv": [10, 5, 16, 6], "rotation": 180, "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 9, 2, 11, 10 ], "rotation": 90 }, "south": {"uv": [9, 2, 11, 10], "rotation": 90, "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 5, 15, 7.4 ], "rotation": 180 }, "west": {"uv": [10, 5, 16, 6], "texture": "#belt_funnel"},
"up": { "texture": "#belt_funnel", "uv": [ 11, 2, 16, 9.4 ], "rotation": 90 }, "up": {"uv": [10, 2, 16, 10], "rotation": 90, "texture": "#belt_funnel"},
"down": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.8 ] } "down": {"uv": [1, 8, 9, 12.8], "texture": "#belt_funnel"}
} }
}, },
{ {
"name": "Ramp", "name": "Top",
"from": [ 4, -4, -8 ], "from": [4, 7, -1],
"to": [ 12, 3, -1 ], "to": [12, 9, 2.5],
"rotation": { "origin": [ 8, -4, -1 ], "axis": "x", "angle": 45.0 }, "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"faces": { "faces": {
"north": { "texture": "#brass_casing", "uv": [ 4, 5, 12, 12 ] }, "north": {"uv": [1, 11, 9, 13], "texture": "#belt_funnel"},
"east": { "texture": "#brass_casing", "uv": [ 4, 9, 11, 16 ], "rotation": 90 }, "east": {"uv": [10, 5, 14, 7], "rotation": 180, "texture": "#belt_funnel"},
"west": { "texture": "#brass_casing", "uv": [ 5, 9, 12, 16 ], "rotation": 270 }, "west": {"uv": [10, 5, 14, 6], "texture": "#belt_funnel"}
"down": { "texture": "#brass_casing", "uv": [ 4, 0, 12, 7 ] } }
} },
}, {
{ "name": "Ramp",
"name": "Side", "from": [4, -4, -8],
"from": [ 12, -3.1, -1 ], "to": [12, 3, -1],
"to": [ 13, 7, 5 ], "rotation": {"angle": 45, "axis": "x", "origin": [8, -4, -1]},
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] }, "north": {"uv": [4, 5, 12, 12], "texture": "#brass_casing"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ], "rotation": 180 }, "east": {"uv": [4, 9, 11, 16], "rotation": 90, "texture": "#brass_casing"},
"south": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] }, "west": {"uv": [5, 9, 12, 16], "rotation": 270, "texture": "#brass_casing"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] } "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", "parent": "block/block",
"textures": { "textures": {
"extractor": "create:block/extractor", "1": "create:block/brass_casing",
"extractor": "create:block/extractor",
"particle": "create:block/extractor" "particle": "create:block/extractor"
}, },
"elements": [ "elements": [
{ {
"name": "Bottom", "name": "Bottom",
"from": [ 4, 2, -1 ], "from": [4, 2, -1],
"to": [ 12, 3, 5 ], "to": [12, 3, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 }, "west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 } "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 ], "name": "Top",
"to": [ 12, 10, 5 ], "from": [4, 9, -1],
"faces": { "to": [12, 10, 5],
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "faces": {
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] }, "north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 }, "south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 } "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 ], "name": "Side",
"faces": { "from": [4, 3, -1],
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 }, "to": [5, 9, 5],
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] }, "faces": {
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] } "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": { "name": "Side",
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 }, "from": [11, 3, -1],
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] }, "to": [12, 9, 5],
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] } "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"},
"name": "Center", "west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
"from": [ 5, 3, 3 ], }
"to": [ 11, 9, 4 ], },
"faces": { {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] } "name": "Center",
} "from": [5, 3, 0],
}, "to": [11, 9, 4],
{ "faces": {
"name": "FilterSpot", "north": {"uv": [5, 5, 11, 11], "texture": "#1"},
"from": [ 5, 10, -0.6 ], "south": {"uv": [7, 1, 13, 7], "texture": "#extractor"}
"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 }, "name": "FilterSpot",
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 }, "from": [5, 10, -0.6],
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 }, "to": [11, 12, 4],
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] }, "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 11, -1]},
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 } "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)", "credit": "Made with Blockbench",
"parent": "block/block", "parent": "create:block/extractor",
"textures": { "textures": {
"redstone_antenna": "create:block/redstone_antenna", "2": "create:block/brass_casing",
"extractor": "create:block/extractor", "redstone_antenna": "create:block/redstone_antenna",
"extractor": "create:block/extractor",
"particle": "create:block/extractor" "particle": "create:block/extractor"
}, },
"elements": [ "elements": [
{ {
"name": "Bottom", "name": "Bottom",
"from": [ 4, 2, -1 ], "from": [4, 2, -1],
"to": [ 12, 3, 5 ], "to": [12, 3, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 }, "west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 } "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 ], "name": "Top",
"to": [ 12, 10, 5 ], "from": [4, 9, -1],
"faces": { "to": [12, 10, 5],
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "faces": {
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] }, "north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 }, "south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 } "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 ], "name": "Side",
"faces": { "from": [4, 3, -1],
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 }, "to": [5, 9, 5],
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] }, "faces": {
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] } "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": { "name": "Side",
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 }, "from": [11, 3, -1],
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] }, "to": [12, 9, 5],
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] } "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"},
"name": "Center", "west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
"from": [ 5, 3, 3 ], }
"to": [ 11, 9, 4 ], },
"faces": { {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] } "name": "Center",
} "from": [5, 3, 0],
}, "to": [11, 9, 4],
{ "faces": {
"name": "FilterSpot", "north": {"uv": [5, 5, 11, 11], "texture": "#2"},
"from": [ 5, 10, -0.6 ], "south": {"uv": [7, 1, 13, 7], "texture": "#extractor"}
"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 }, "name": "FilterSpot",
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 }, "from": [5, 10, -0.6],
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 }, "to": [11, 12, 4],
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] }, "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 11, -1]},
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 } "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"},
"name": "AntennaX", "west": {"uv": [0.1, 0, 4.7, 2], "texture": "#extractor"},
"from": [ 11, 7, 2 ], "up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"}
"to": [ 14, 17, 3 ], }
"faces": { },
"north": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }, {
"south": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }, "name": "AntennaX",
"down": { "texture": "#redstone_antenna", "uv": [ 0, 9, 3, 10 ] } "from": [11, 7, 2],
} "to": [14, 17, 3],
}, "faces": {
{ "north": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"name": "AntennaZ", "south": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"from": [ 12, 7, 1 ], "down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"}
"to": [ 13, 17, 4 ], }
"faces": { },
"east": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }, {
"west": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] } "name": "AntennaZ",
} "from": [12, 7, 1],
}, "to": [13, 17, 4],
{ "faces": {
"name": "AntennaTop", "east": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"from": [ 12, 15, 2 ], "west": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"}
"to": [ 13, 16, 3 ], }
"faces": { },
"up": { "texture": "#redstone_antenna", "uv": [ 1, 1, 2, 2 ] } {
} "name": "AntennaTop",
}, "from": [12, 15, 2],
{ "to": [13, 16, 3],
"name": "AntennaDish", "faces": {
"from": [ 10, 13, 0 ], "up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"}
"to": [ 15, 13, 5 ], }
"faces": { },
"up": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] }, {
"down": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] } "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", "parent": "create:block/extractor"
"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 }
}
}
]
} }

View file

@ -1,123 +1,3 @@
{ {
"parent": "block/block", "parent": "create:block/extractor_wireless"
"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 ] }
}
}
]
} }