Merge branch 'better-belts' into 0.2

This commit is contained in:
simibubi 2019-11-20 22:51:23 +01:00
commit 1e23aa82aa
55 changed files with 3561 additions and 1391 deletions

View file

@ -6,7 +6,7 @@ import com.simibubi.create.modules.IModule;
import com.simibubi.create.modules.contraptions.WrenchItem;
import com.simibubi.create.modules.contraptions.WrenchItemRenderer;
import com.simibubi.create.modules.contraptions.relays.VerticalGearboxItem;
import com.simibubi.create.modules.contraptions.relays.belt.BeltItem;
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItem;
import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem;
import com.simibubi.create.modules.curiosities.deforester.DeforesterItem;
import com.simibubi.create.modules.curiosities.deforester.DeforesterItemRenderer;
@ -82,7 +82,7 @@ public enum AllItems {
BLUEPRINT(new SchematicItem(standardItemProperties())),
__CONTRAPTIONS__(),
BELT_CONNECTOR(new BeltItem(standardItemProperties())),
BELT_CONNECTOR(new BeltConnectorItem(standardItemProperties())),
VERTICAL_GEARBOX(new VerticalGearboxItem(new Properties())),
FLOUR(ingredient()),
DOUGH(ingredient()),

View file

@ -44,6 +44,7 @@ import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.RedstoneBridgeTileEntity;
import com.simibubi.create.modules.logistics.block.StockswitchTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntity;
import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntity;
@ -180,6 +181,7 @@ public enum AllTileEntities {
bind(RedstoneBridgeTileEntity.class, new LinkedTileEntityRenderer());
bind(LinkedExtractorTileEntity.class, new LinkedExtractorTileEntityRenderer());
bind(ExtractorTileEntity.class, new ExtractorTileEntityRenderer());
bind(BeltFunnelTileEntity.class, new BeltFunnelTileEntityRenderer());
bind(EntityDetectorTileEntity.class, new EntityDetectorTileEntityRenderer());
bind(MechanicalPressTileEntity.class, new MechanicalPressTileEntityRenderer());
bind(FlexpeaterTileEntity.class, new FlexpeaterTileEntityRenderer());

View file

@ -10,7 +10,7 @@ import com.simibubi.create.foundation.utility.TooltipHelper;
import com.simibubi.create.modules.contraptions.KineticDebugger;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.TurntableHandler;
import com.simibubi.create.modules.contraptions.relays.belt.BeltItemHandler;
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
@ -56,7 +56,7 @@ public class ClientEvents {
public static void onGameTick() {
CreateClient.gameTick();
BeltItemHandler.gameTick();
BeltConnectorItemHandler.gameTick();
}
@SubscribeEvent

View file

@ -28,9 +28,9 @@ public abstract class SyncedTileEntity extends TileEntity {
}
public void sendData() {
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16);
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 4 | 16);
}
public void causeBlockUpdate() {
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 1);
}

View file

@ -91,6 +91,19 @@ public abstract class BufferManipulator {
buffer.put(bufferPosition + 15, a);
}
public ByteBuffer getTranslated(float xIn, float yIn, float zIn, int packedLightCoords) {
original.rewind();
mutable.rewind();
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + xIn, getY(original, vertex) + yIn,
getZ(original, vertex) + zIn);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
public static ByteBuffer remanipulateBuffer(ByteBuffer buffer, float x, float y, float z, float xOrigin,
float yOrigin, float zOrigin, float yaw, float pitch) {
buffer.rewind();

View file

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

View file

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

View file

@ -3,11 +3,15 @@ package com.simibubi.create.foundation.utility;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.mutable.MutableObject;
import net.minecraft.block.Block;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
public class VoxelShaper {
@ -17,7 +21,11 @@ public class VoxelShaper {
return shapes.get(direction);
}
public static VoxelShaper forHorizontalBlock(VoxelShape southShape) {
public VoxelShape get(Axis axis) {
return shapes.get(axisAsFace(axis));
}
public static VoxelShaper forHorizontal(VoxelShape southShape) {
VoxelShaper voxelShaper = new VoxelShaper();
for (Direction facing : Direction.values()) {
if (facing.getAxis().isVertical())
@ -27,7 +35,27 @@ public class VoxelShaper {
return voxelShaper;
}
public static VoxelShaper forDirectionalBlock(VoxelShape southShape) {
public static VoxelShaper forHorizontalAxis(VoxelShape zShape) {
VoxelShaper voxelShaper = new VoxelShaper();
for (Axis axis : Axis.values()) {
if (axis.isVertical())
continue;
Direction facing = axisAsFace(axis);
voxelShaper.shapes.put(facing, rotatedCopy(zShape, 0, (int) -facing.getHorizontalAngle()));
}
return voxelShaper;
}
public static VoxelShaper forRotatedPillar(VoxelShape zShape) {
VoxelShaper voxelShaper = new VoxelShaper();
for (Axis axis : Axis.values()) {
Direction facing = axisAsFace(axis);
voxelShaper.shapes.put(facing, rotatedCopy(zShape, 0, (int) -facing.getHorizontalAngle()));
}
return voxelShaper;
}
public static VoxelShaper forDirectional(VoxelShape southShape) {
VoxelShaper voxelShaper = new VoxelShaper();
for (Direction facing : Direction.values()) {
int rotX = facing.getAxis().isVertical() ? (facing == Direction.UP ? 270 : 90) : 0;
@ -43,19 +71,28 @@ public class VoxelShaper {
return this;
}
public static VoxelShape rotatedCopy(VoxelShape shape, int rotX, int rotY) {
Vec3d center = new Vec3d(8, 8, 8);
Vec3d v1 = new Vec3d(shape.getStart(Axis.X), shape.getStart(Axis.Y), shape.getStart(Axis.Z)).scale(16)
.subtract(center);
Vec3d v2 = new Vec3d(shape.getEnd(Axis.X), shape.getEnd(Axis.Y), shape.getEnd(Axis.Z)).scale(16)
.subtract(center);
private static Direction axisAsFace(Axis axis) {
return Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
}
v1 = VecHelper.rotate(v1, rotX, Axis.X);
v1 = VecHelper.rotate(v1, rotY, Axis.Y).add(center);
v2 = VecHelper.rotate(v2, rotX, Axis.X);
v2 = VecHelper.rotate(v2, rotY, Axis.Y).add(center);
private static VoxelShape rotatedCopy(VoxelShape shape, int rotX, int rotY) {
MutableObject<VoxelShape> result = new MutableObject<>(VoxelShapes.empty());
return Block.makeCuboidShape(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
shape.forEachBox((x1, y1, z1, x2, y2, z2) -> {
Vec3d center = new Vec3d(8, 8, 8);
Vec3d v1 = new Vec3d(x1, y1, z1).scale(16).subtract(center);
Vec3d v2 = new Vec3d(x2, y2, z2).scale(16).subtract(center);
v1 = VecHelper.rotate(v1, rotX, Axis.X);
v1 = VecHelper.rotate(v1, rotY, Axis.Y).add(center);
v2 = VecHelper.rotate(v2, rotX, Axis.X);
v2 = VecHelper.rotate(v2, rotY, Axis.Y).add(center);
VoxelShape rotated = Block.makeCuboidShape(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
result.setValue(VoxelShapes.or(result.getValue(), rotated));
});
return result.getValue();
}
}

View file

@ -5,6 +5,6 @@ import net.minecraft.block.Block;
public class VoxelShapers {
public static final VoxelShaper SHORT_CASING = VoxelShaper
.forDirectionalBlock(Block.makeCuboidShape(0, 0, 0, 16, 16, 12));
.forDirectional(Block.makeCuboidShape(0, 0, 0, 16, 16, 12));
}

View file

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

View file

@ -2,7 +2,6 @@ package com.simibubi.create.modules.contraptions;
import static com.simibubi.create.AllBlocks.BELT;
import static com.simibubi.create.AllBlocks.COGWHEEL;
import static com.simibubi.create.AllBlocks.ENCASED_FAN;
import static com.simibubi.create.AllBlocks.LARGE_COGWHEEL;
import static com.simibubi.create.CreateConfig.parameters;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
@ -76,12 +75,6 @@ public class RotationPropagator {
return connected ? 1 : 0;
}
// Attached Fans
if (ENCASED_FAN.typeOf(stateFrom) && ENCASED_FAN.typeOf(stateTo)) {
if (stateFrom.get(AXIS) == stateTo.get(AXIS))
return 1;
}
// Large Gear <-> Large Gear
if (isLargeToLargeGear(stateFrom, stateTo, diff)) {
Axis sourceAxis = stateFrom.get(AXIS);

View file

@ -34,7 +34,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTileEntity> {
protected static Map<BlockState, BufferManipulator> cachedBuffers;
public static Map<BlockState, BufferManipulator> cachedBuffers;
public static boolean rainbowMode = false;
public static class BlockModelSpinner extends BufferManipulator {

View file

@ -0,0 +1,71 @@
package com.simibubi.create.modules.contraptions.receivers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EncasedFanBeltHandler {
// Fans need to be aware of belt TEs within their range
// all belts are handled equally
// requires ref to controller and index
static List<BeltTileEntity> findBelts(EncasedFanTileEntity fan) {
if (fan.getSpeed() == 0)
return Collections.emptyList();
List<BeltTileEntity> belts = new ArrayList<>();
AxisAlignedBB searchBB = fan.frontBB.shrink(.25).contract(0, 0, 0).expand(0, -.25f, 0);
BlockPos.getAllInBox((int) searchBB.minX, (int) searchBB.minY, (int) searchBB.minZ, (int) searchBB.maxX - 1,
(int) searchBB.maxY - 1, (int) searchBB.maxZ - 1)
.filter(p -> AllBlocks.BELT.typeOf(fan.getWorld().getBlockState(p))).forEach(p -> {
TileEntity te = fan.getWorld().getTileEntity(p);
if (te == null || !(te instanceof BeltTileEntity))
return;
belts.add((BeltTileEntity) te);
});
return belts;
}
static void tickBelts(EncasedFanTileEntity fan, List<BeltTileEntity> belts) {
Type processingType = fan.getProcessingType();
if (processingType == null)
return;
for (BeltTileEntity belt : belts) {
BeltTileEntity controller = belt.getControllerTE();
if (controller == null)
continue;
World world = belt.getWorld();
controller.getInventory().forEachWithin(belt.index + .5f, .5f, (transported) -> {
if (world.rand.nextInt(4) == 0 && world.isRemote) {
Vec3d vec = controller.getInventory().getVectorForOffset(transported.beltPosition);
if (processingType == Type.BLASTING)
world.addParticle(ParticleTypes.LARGE_SMOKE, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SMOKING)
world.addParticle(ParticleTypes.CLOUD, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SPLASHING)
world.addParticle(ParticleTypes.BUBBLE_POP, vec.x + (world.rand.nextFloat() - .5f) * .5f,
vec.y + .25f, vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 16f, 0);
}
if (world.isRemote)
return null;
return InWorldProcessing.applyProcessing(transported, belt, processingType);
});
}
}
}

View file

@ -26,7 +26,7 @@ public class EncasedFanParticleHandler {
private void initEffects() {
List<FanEffect> standardFX = new ArrayList<>(2);
standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 3f, 1));
standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 8f, 1));
standardFX.add(new FanEffect(new RedstoneParticleData(1, 1, 1, 1), 1 / 2f, 1 / 32f, 1/16f, 512f));
effects.put(Blocks.AIR, standardFX);

View file

@ -5,6 +5,7 @@ import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import java.util.Collections;
import java.util.List;
import com.simibubi.create.AllBlockTags;
@ -14,6 +15,7 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
@ -51,6 +53,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
protected boolean findFrontBlock;
protected BlockState frontBlock;
protected boolean isGenerator;
protected List<BeltTileEntity> affectedBelts = Collections.emptyList();
public EncasedFanTileEntity() {
super(AllTileEntities.ENCASED_FAN.type);
@ -67,6 +70,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
super.readClientUpdate(tag);
updateFrontBlock();
updateBBs();
affectedBelts = EncasedFanBeltHandler.findBelts(this);
}
@Override
@ -140,6 +144,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
}
affectedBelts = EncasedFanBeltHandler.findBelts(this);
sendData();
}
@ -190,6 +195,8 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
if (getSpeed() == 0 || isGenerator)
return;
EncasedFanBeltHandler.tickBelts(this, affectedBelts);
List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB);
for (Entity entity : frontEntities) {
moveEntity(entity, true);
@ -238,7 +245,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
return;
if (canProcess((ItemEntity) entity))
InWorldProcessing.process((ItemEntity) entity, getProcessingType());
InWorldProcessing.applyProcessing((ItemEntity) entity, getProcessingType());
} else {
if (getProcessingType() == Type.SMOKING) {

View file

@ -39,7 +39,7 @@ import net.minecraftforge.common.IPlantable;
public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBehavior {
private static VoxelShaper SHAPER = VoxelShaper.forHorizontalBlock(Block.makeCuboidShape(0, 2, 0, 16, 14, 3));
private static VoxelShaper SHAPER = VoxelShaper.forHorizontal(Block.makeCuboidShape(0, 2, 0, 16, 14, 3));
public HarvesterBlock() {
super(Properties.from(Blocks.IRON_BLOCK));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,6 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@ -9,20 +10,28 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.block.IWithoutBlockItem;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity.TransportedEntityInfo;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.IProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
@ -31,121 +40,110 @@ import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.common.Tags;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> {
public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
private static final VoxelShape FULL = makeCuboidShape(0, 0, 0, 16, 16, 16),
FLAT_STRAIGHT_X = makeCuboidShape(1, 3, 0, 15, 13, 16),
FLAT_STRAIGHT_Z = makeCuboidShape(0, 3, 1, 16, 13, 15),
VERTICAL_STRAIGHT_X = makeCuboidShape(3, 0, 1, 13, 16, 15),
VERTICAL_STRAIGHT_Z = makeCuboidShape(1, 0, 3, 15, 16, 13),
SLOPE_END_EAST = makeCuboidShape(0, 3, 1, 10, 13, 15),
SLOPE_END_WEST = makeCuboidShape(6, 3, 1, 16, 13, 15),
SLOPE_END_SOUTH = makeCuboidShape(1, 3, 0, 15, 13, 10),
SLOPE_END_NORTH = makeCuboidShape(1, 3, 6, 15, 13, 16),
SLOPE_BUILDING_BLOCK_X = makeCuboidShape(5, 5, 1, 11, 11, 15),
SLOPE_BUILDING_BLOCK_Z = makeCuboidShape(1, 5, 5, 15, 11, 11),
SLOPE_UPWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, false)),
SLOPE_UPWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, false)),
SLOPE_UPWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, false)),
SLOPE_UPWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, false)),
SLOPE_DOWNWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, true)),
SLOPE_DOWNWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, true)),
SLOPE_DOWNWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, true)),
SLOPE_DOWNWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, true)),
SLOPE_EAST = createSlope(Direction.EAST), SLOPE_WEST = createSlope(Direction.WEST),
SLOPE_NORTH = createSlope(Direction.NORTH), SLOPE_SOUTH = createSlope(Direction.SOUTH);
public static final BooleanProperty CASING = BooleanProperty.create("casing");
private final VoxelShape collisionMask = makeCuboidShape(0, 0, 0, 16, 19, 16);
public BeltBlock() {
super(Properties.from(Blocks.BROWN_WOOL));
setDefaultState(getDefaultState().with(SLOPE, Slope.HORIZONTAL).with(PART, Part.START));
setDefaultState(getDefaultState().with(SLOPE, Slope.HORIZONTAL).with(PART, Part.START).with(CASING, false));
}
@Override
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
if (face.getAxis() != getRotationAxis(state))
return false;
BeltTileEntity beltEntity = (BeltTileEntity) world.getTileEntity(pos);
return beltEntity != null && beltEntity.hasPulley();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(HORIZONTAL_FACING).rotateY().getAxis();
}
@Override
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos,
PlayerEntity player) {
return new ItemStack(AllItems.BELT_CONNECTOR.item);
return AllItems.BELT_CONNECTOR.asStack();
}
@Override
public Material getMaterial(BlockState state) {
return state.get(CASING) ? Material.WOOD : Material.WOOL;
}
@Override
public boolean isFlammable(BlockState state, IBlockReader world, BlockPos pos, Direction face) {
return false;
}
@Override
public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
return;
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
return;
BeltTileEntity belt = null;
BlockPos entityPosition = entityIn.getPosition();
BlockPos beltPos = null;
if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition)))
belt = (BeltTileEntity) worldIn.getTileEntity(entityPosition);
beltPos = entityPosition;
else if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition.down())))
belt = (BeltTileEntity) worldIn.getTileEntity(entityPosition.down());
if (belt == null || !belt.hasSource())
beltPos = entityPosition.down();
if (beltPos == null)
return;
if (!(worldIn instanceof World))
return;
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
if (controller == null)
return;
if (controller.passengers == null)
return;
if (controller.passengers.containsKey(entityIn))
controller.passengers.get(entityIn).refresh(belt.getPos(), belt.getBlockState());
else
controller.passengers.put(entityIn, new TransportedEntityInfo(belt.getPos(), belt.getBlockState()));
}
@Override
public float getSlipperiness(BlockState state, IWorldReader world, BlockPos pos, Entity entity) {
return super.getSlipperiness(state, world, pos, entity);
onEntityCollision(worldIn.getBlockState(beltPos), (World) worldIn, beltPos, entityIn);
}
@Override
public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) {
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
return;
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
return;
BeltTileEntity belt = null;
belt = (BeltTileEntity) worldIn.getTileEntity(pos);
if (belt == null || !belt.hasSource())
if (state.get(SLOPE) == Slope.VERTICAL)
return;
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
return;
if (belt == null || belt.getSpeed() == 0)
return;
if (entityIn instanceof ItemEntity && entityIn.isAlive()) {
if (worldIn.isRemote)
return;
if (entityIn.getMotion().y > 0)
return;
withTileEntityDo(worldIn, pos, te -> {
ItemEntity itemEntity = (ItemEntity) entityIn;
IItemHandler handler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
if (handler == null)
return;
ItemStack remainder = handler.insertItem(0, itemEntity.getItem().copy(), false);
if (remainder.isEmpty())
itemEntity.remove();
});
return;
}
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
if (controller == null)
if (controller == null || controller.passengers == null)
return;
if (controller.passengers == null)
return;
if (controller.passengers.containsKey(entityIn)) {
TransportedEntityInfo transportedEntityInfo = controller.passengers.get(entityIn);
if (transportedEntityInfo.ticksSinceLastCollision != 0 || pos.equals(entityIn.getPosition()))
transportedEntityInfo.refresh(pos, state);
TransportedEntityInfo info = controller.passengers.get(entityIn);
if (info.ticksSinceLastCollision != 0 || pos.equals(entityIn.getPosition()))
info.refresh(pos, state);
} else
controller.passengers.put(entityIn, new TransportedEntityInfo(pos, state));
}
@ -163,19 +161,103 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
if (player.isSneaking() || !player.isAllowEdit())
return false;
ItemStack heldItem = player.getHeldItem(handIn);
if (!Tags.Items.DYES.contains(heldItem.getItem()))
return false;
if (worldIn.isRemote)
boolean isShaft = heldItem.getItem() == AllBlocks.SHAFT.get().asItem();
boolean isCasing = heldItem.getItem() == AllBlocks.LOGISTICAL_CASING.get().asItem();
boolean isDye = Tags.Items.DYES.contains(heldItem.getItem());
boolean isHand = heldItem.isEmpty() && handIn == Hand.MAIN_HAND;
if (isDye) {
if (worldIn.isRemote)
return true;
withTileEntityDo(worldIn, pos, te -> {
DyeColor dyeColor = DyeColor.getColor(heldItem);
if (dyeColor == null)
return;
te.applyColor(dyeColor);
});
if (!player.isCreative())
heldItem.shrink(1);
return true;
withTileEntityDo(worldIn, pos, te -> te.applyColor(DyeColor.getColor(heldItem)));
if (!player.isCreative())
heldItem.shrink(1);
return true;
}
TileEntity te = worldIn.getTileEntity(pos);
if (te == null || !(te instanceof BeltTileEntity))
return false;
BeltTileEntity belt = (BeltTileEntity) te;
if (isHand) {
BeltTileEntity controllerBelt = belt.getControllerTE();
if (controllerBelt == null)
return false;
if (worldIn.isRemote)
return true;
controllerBelt.getInventory().forEachWithin(belt.index, .75f, (transportedItemStack) -> {
player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack);
return Collections.emptyList();
});
}
if (isShaft) {
if (state.get(PART) != Part.MIDDLE)
return false;
if (worldIn.isRemote)
return true;
if (!player.isCreative())
heldItem.shrink(1);
worldIn.setBlockState(pos, state.with(PART, Part.PULLEY), 2);
belt.attachKinetics();
return true;
}
if (isCasing) {
if (state.get(CASING))
return false;
if (state.get(SLOPE) == Slope.VERTICAL)
return false;
if (!player.isCreative())
heldItem.shrink(1);
worldIn.setBlockState(pos, state.with(CASING, true), 2);
return true;
}
return false;
}
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
World world = context.getWorld();
TileEntity te = world.getTileEntity(context.getPos());
if (te == null || !(te instanceof BeltTileEntity))
return ActionResultType.PASS;
BeltTileEntity belt = (BeltTileEntity) te;
PlayerEntity player = context.getPlayer();
if (state.get(CASING)) {
if (world.isRemote)
return ActionResultType.SUCCESS;
world.setBlockState(context.getPos(), state.with(CASING, false), 2);
if (!player.isCreative())
player.inventory.placeItemBackInInventory(world, new ItemStack(AllBlocks.LOGISTICAL_CASING.block));
return ActionResultType.SUCCESS;
}
if (state.get(PART) == Part.PULLEY) {
if (world.isRemote)
return ActionResultType.SUCCESS;
world.setBlockState(context.getPos(), state.with(PART, Part.MIDDLE), 2);
belt.detachKinetics();
belt.attachKinetics();
if (!player.isCreative())
player.inventory.placeItemBackInInventory(world, new ItemStack(AllBlocks.SHAFT.block));
return ActionResultType.SUCCESS;
}
return super.onWrenched(state, context);
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(SLOPE, PART);
builder.add(SLOPE, PART, CASING);
super.fillStateContainer(builder);
}
@ -184,47 +266,31 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
return true;
}
@Override
public PathNodeType getAiPathNodeType(BlockState state, IBlockReader world, BlockPos pos, MobEntity entity) {
return PathNodeType.DANGER_OTHER;
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
Direction facing = state.get(HORIZONTAL_FACING);
Axis axis = facing.getAxis();
Part part = state.get(PART);
Slope slope = state.get(SLOPE);
return VoxelShapes.or(BeltShapes.getShape(state), BeltShapes.getCasingShape(state));
}
if (slope == Slope.HORIZONTAL)
return axis == Axis.Z ? FLAT_STRAIGHT_X : FLAT_STRAIGHT_Z;
if (slope == Slope.VERTICAL)
return axis == Axis.X ? VERTICAL_STRAIGHT_X : VERTICAL_STRAIGHT_Z;
if (part != Part.MIDDLE) {
if (part == Part.START)
slope = slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD;
else
facing = facing.getOpposite();
if (facing == Direction.NORTH)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_NORTH : SLOPE_DOWNWARD_END_NORTH;
if (facing == Direction.SOUTH)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_SOUTH : SLOPE_DOWNWARD_END_SOUTH;
if (facing == Direction.EAST)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_EAST : SLOPE_DOWNWARD_END_EAST;
if (facing == Direction.WEST)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_WEST : SLOPE_DOWNWARD_END_WEST;
@Override
public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos,
ISelectionContext context) {
VoxelShape shape = getShape(state, worldIn, pos, context);
BeltTileEntity belt = (BeltTileEntity) worldIn.getTileEntity(pos);
if (belt == null || context.getEntity() == null)
return shape;
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
if (controller == null)
return shape;
if (controller.passengers == null || !controller.passengers.containsKey(context.getEntity())) {
return VoxelShapes.combine(collisionMask, shape, IBooleanFunction.AND);
}
if (slope == Slope.DOWNWARD)
facing = facing.getOpposite();
if (facing == Direction.NORTH)
return SLOPE_NORTH;
if (facing == Direction.SOUTH)
return SLOPE_SOUTH;
if (facing == Direction.EAST)
return SLOPE_EAST;
if (facing == Direction.WEST)
return SLOPE_WEST;
return FULL;
return shape;
}
@Override
@ -233,15 +299,22 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
}
@Override
protected boolean hasStaticPart() {
return false;
public boolean canRenderInLayer(BlockState state, BlockRenderLayer layer) {
return state.get(CASING) && layer == getRenderLayer();
}
@Override
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
withTileEntityDo(worldIn, pos, te -> {
if (te.hasPulley())
if (worldIn.isRemote)
return;
if (te.hasPulley() && (player == null || !player.isCreative()))
Block.spawnDrops(AllBlocks.SHAFT.get().getDefaultState(), worldIn, pos);
if (te.isController()) {
BeltInventory inv = te.getInventory();
for (TransportedItemStack stack : inv.items)
inv.eject(stack);
}
});
super.onBlockHarvested(worldIn, pos, state, player);
}
@ -250,6 +323,8 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (worldIn.isRemote)
return;
if (state.getBlock() == newState.getBlock())
return;
boolean endWasDestroyed = state.get(PART) == Part.END;
TileEntity tileEntity = worldIn.getTileEntity(pos);
@ -274,16 +349,20 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
break;
BeltTileEntity te = (BeltTileEntity) worldIn.getTileEntity(toDestroy);
boolean hasPulley = te.hasPulley();
if (te.isController()) {
BeltInventory inv = te.getInventory();
for (TransportedItemStack stack : inv.items)
inv.eject(stack);
}
te.setSource(null);
te.remove();
if (hasPulley) {
if (te.hasPulley())
worldIn.setBlockState(toDestroy, AllBlocks.SHAFT.get().getDefaultState()
.with(BlockStateProperties.AXIS, getRotationAxis(destroyedBlock)), 3);
} else {
else
worldIn.destroyBlock(toDestroy, false);
}
if (destroyedBlock.get(PART) == Part.END)
break;
@ -308,19 +387,6 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
}
@Override
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
if (face.getAxis() != getRotationAxis(state))
return false;
BeltTileEntity beltEntity = (BeltTileEntity) world.getTileEntity(pos);
return beltEntity != null && beltEntity.hasPulley();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(HORIZONTAL_FACING).getAxis() == Axis.X ? Axis.Z : Axis.X;
}
public enum Slope implements IStringSerializable {
HORIZONTAL, UPWARD, DOWNWARD, VERTICAL;
@ -331,7 +397,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
}
public enum Part implements IStringSerializable {
START, MIDDLE, END;
START, MIDDLE, END, PULLEY;
@Override
public String getName() {
@ -339,18 +405,6 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
}
}
public static boolean isUpperEnd(BlockState state, float speed) {
Direction facing = state.get(HORIZONTAL_FACING);
if (state.get(SLOPE) == Slope.UPWARD && state.get(PART) == Part.END) {
return facing.getAxisDirection().getOffset() * Math.signum(speed) == (facing.getAxis() == Axis.X ? -1 : 1);
}
if (state.get(SLOPE) == Slope.DOWNWARD && state.get(PART) == Part.START) {
return facing.getAxisDirection().getOffset() * Math.signum(speed) == (facing.getAxis() == Axis.Z ? -1 : 1);
}
return false;
}
public static List<BlockPos> getBeltChain(World world, BlockPos controllerPos) {
List<BlockPos> positions = new LinkedList<>();
@ -382,33 +436,34 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
return positions;
}
protected static VoxelShape createSlope(Direction facing) {
return VoxelShapes.or(createHalfSlope(facing.getOpposite(), false), createHalfSlope(facing, true));
@Override
protected boolean hasStaticPart() {
return false;
}
protected static VoxelShape createHalfSlope(Direction facing, boolean upward) {
VoxelShape shape = VoxelShapes.empty();
VoxelShape buildingBlock = facing.getAxis() == Axis.X ? SLOPE_BUILDING_BLOCK_X : SLOPE_BUILDING_BLOCK_Z;
Vec3i directionVec = facing.getDirectionVec();
public static boolean canAccessFromSide(Direction facing, BlockState belt) {
if (facing == null)
return true;
if (!belt.get(BeltBlock.CASING))
return false;
Part part = belt.get(BeltBlock.PART);
if (part != Part.MIDDLE && facing.getAxis() == belt.get(HORIZONTAL_FACING).rotateY().getAxis())
return false;
int x = directionVec.getX();
int y = upward ? 1 : -1;
int z = directionVec.getZ();
Slope slope = belt.get(BeltBlock.SLOPE);
if (slope != Slope.HORIZONTAL) {
if (slope == Slope.DOWNWARD && part == Part.END)
return true;
if (slope == Slope.UPWARD && part == Part.START)
return true;
Direction beltSide = belt.get(HORIZONTAL_FACING);
if (slope == Slope.DOWNWARD)
beltSide = beltSide.getOpposite();
if (beltSide == facing)
return false;
}
for (int segment = 0; segment < 6; segment++)
shape = VoxelShapes.or(shape,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f));
if (!upward)
return shape;
VoxelShape mask = makeCuboidShape(0, -8, 0, 16, 24, 16);
for (int segment = 6; segment < 11; segment++)
shape = VoxelShapes.or(shape,
VoxelShapes.combine(mask,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f),
IBooleanFunction.AND));
return shape;
return true;
}
}

View file

@ -6,6 +6,7 @@ import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.ShaftBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
@ -22,9 +23,9 @@ import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class BeltItem extends Item {
public class BeltConnectorItem extends Item {
public BeltItem(Properties properties) {
public BeltConnectorItem(Properties properties) {
super(properties);
}
@ -95,11 +96,23 @@ public class BeltItem extends Item {
List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing);
BlockState beltBlock = AllBlocks.BELT.get().getDefaultState();
int index = 0;
for (BlockPos pos : beltsToCreate) {
BeltBlock.Part part = pos.equals(start) ? Part.START : pos.equals(end) ? Part.END : Part.MIDDLE;
boolean pulley = AllBlocks.SHAFT.typeOf(world.getBlockState(pos));
if (part == Part.MIDDLE && pulley)
part = Part.PULLEY;
world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part)
.with(BeltBlock.HORIZONTAL_FACING, facing), 3);
connectBelt(world, pos, start);
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(pos);
if (te != null) {
te.setController(start);
te.beltLength = beltsToCreate.size();
te.index = index;
}
index++;
}
}
@ -151,12 +164,6 @@ public class BeltItem extends Item {
return positions;
}
private void connectBelt(World world, BlockPos pos, BlockPos target) {
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(pos);
if (te != null)
te.setController(target);
}
public static boolean canConnect(World world, BlockPos first, BlockPos second) {
if (!world.isAreaLoaded(first, 1))
return false;
@ -190,11 +197,15 @@ public class BeltItem extends Item {
int limit = 1000;
for (BlockPos currentPos = first.add(step); !currentPos.equals(second)
&& limit-- > 0; currentPos = currentPos.add(step)) {
if (!world.getBlockState(currentPos).getMaterial().isReplaceable())
BlockState blockState = world.getBlockState(currentPos);
if (AllBlocks.SHAFT.typeOf(blockState) && blockState.get(ShaftBlock.AXIS) == axis)
continue;
if (!blockState.getMaterial().isReplaceable())
return false;
}
return true;
}
public static boolean validateAxis(World world, BlockPos pos) {

View file

@ -23,7 +23,7 @@ import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class BeltItemHandler {
public class BeltConnectorItemHandler {
private static Random r = new Random();
@ -73,7 +73,7 @@ public class BeltItemHandler {
if (!selected.withinDistance(first, CreateConfig.parameters.maxBeltLength.get()))
return;
boolean canConnect = BeltItem.validateAxis(world, selected) && BeltItem.canConnect(world, first, selected);
boolean canConnect = BeltConnectorItem.validateAxis(world, selected) && BeltConnectorItem.canConnect(world, first, selected);
Vec3d start = new Vec3d(first);
Vec3d end = new Vec3d(selected);

View file

@ -0,0 +1,380 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;
import com.simibubi.create.AllBlocks;
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.BeltBlock.Slope;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public class BeltInventory {
final BeltTileEntity belt;
final List<TransportedItemStack> items;
boolean beltMovementPositive;
final float SEGMENT_WINDOW = .75f;
public BeltInventory(BeltTileEntity te) {
this.belt = te;
items = new LinkedList<>();
}
public void tick() {
// Reverse item collection if belt just reversed
if (beltMovementPositive != movingPositive()) {
beltMovementPositive = movingPositive();
Collections.reverse(items);
belt.markDirty();
belt.sendData();
}
// Assuming the first entry is furthest on the belt
TransportedItemStack stackInFront = null;
TransportedItemStack current = null;
Iterator<TransportedItemStack> iterator = items.iterator();
float beltSpeed = belt.getDirectionAwareBeltMovementSpeed();
float spacing = 1;
Items: while (iterator.hasNext()) {
stackInFront = current;
current = iterator.next();
current.prevBeltPosition = current.beltPosition;
current.prevSideOffset = current.sideOffset;
if (current.stack.isEmpty()) {
iterator.remove();
current = null;
continue;
}
float movement = beltSpeed;
// Don't move if locked
boolean onClient = belt.getWorld().isRemote;
if (onClient && current.locked)
continue;
// Don't move if other items are waiting in front
float currentPos = current.beltPosition;
if (stackInFront != null) {
float diff = stackInFront.beltPosition - currentPos;
if (Math.abs(diff) <= spacing)
continue;
movement = beltMovementPositive ? Math.min(movement, diff - spacing)
: Math.max(movement, diff + spacing);
}
// Determine current segment
int segmentBefore = (int) currentPos;
float min = segmentBefore + .5f - (SEGMENT_WINDOW / 2);
float max = segmentBefore + .5f + (SEGMENT_WINDOW / 2);
if (currentPos < min || currentPos > max)
segmentBefore = -1;
// 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 + .5f <= current.beltPosition + limitedMovement
: segment + .5f >= 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 + (beltMovementPositive ? 1 / 64f : -1 / 64f);
current.locked = true;
belt.sendData();
continue Items;
}
}
}
}
// Apply Movement
current.beltPosition += limitedMovement;
current.sideOffset += (current.getTargetSideOffset() - current.sideOffset) * Math.abs(limitedMovement) * 2f;
currentPos = current.beltPosition;
// Determine segment after movement
int segmentAfter = (int) currentPos;
min = segmentAfter + .5f - (SEGMENT_WINDOW / 2);
max = segmentAfter + .5f + (SEGMENT_WINDOW / 2);
if (currentPos < min || currentPos > max)
segmentAfter = -1;
// Item changed segments
World world = belt.getWorld();
if (segmentBefore != segmentAfter) {
for (int segment : new int[] { segmentBefore, segmentAfter }) {
if (segment == -1)
continue;
if (!world.isRemote)
world.updateComparatorOutputLevel(getPositionForOffset(segment),
belt.getBlockState().getBlock());
}
}
// End reached
if (limitedMovement != movement) {
if (world.isRemote)
continue;
BlockPos nextPosition = getPositionForOffset(beltMovementPositive ? belt.beltLength : -1);
BlockState state = world.getBlockState(nextPosition);
Direction movementFacing = belt.getMovementFacing();
// next block is a basin or a saw
if (AllBlocks.BASIN.typeOf(state) || AllBlocks.SAW.typeOf(state)) {
TileEntity te = world.getTileEntity(nextPosition);
if (te != null) {
LazyOptional<IItemHandler> optional = te
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP);
if (optional.isPresent()) {
IItemHandler itemHandler = optional.orElse(null);
ItemStack remainder = ItemHandlerHelper.insertItemStacked(itemHandler, current.stack.copy(),
false);
if (remainder.equals(current.stack, false))
continue;
current.stack = remainder;
if (remainder.isEmpty()) {
iterator.remove();
current = null;
}
belt.sendData();
}
}
continue;
}
// next block is not a belt
if (!AllBlocks.BELT.typeOf(state)) {
if (!Block.hasSolidSide(state, world, nextPosition, movementFacing.getOpposite())) {
eject(current);
iterator.remove();
current = null;
belt.sendData();
}
continue;
}
// Next block is a belt
TileEntity te = world.getTileEntity(nextPosition);
if (te == null || !(te instanceof BeltTileEntity))
continue;
BeltTileEntity nextBelt = (BeltTileEntity) te;
Direction nextMovementFacing = nextBelt.getMovementFacing();
// next belt goes the opposite way
if (nextMovementFacing == movementFacing.getOpposite())
continue;
// Inserting into other belt
if (nextBelt.tryInsertingFromSide(movementFacing, current, false)) {
iterator.remove();
current = null;
belt.sendData();
}
}
}
}
public boolean canInsertAt(int segment) {
return canInsertFrom(segment, Direction.UP);
}
public boolean canInsertFrom(int segment, Direction side) {
float min = segment + .5f - (SEGMENT_WINDOW / 2);
float max = segment + .5f + (SEGMENT_WINDOW / 2);
for (TransportedItemStack stack : items) {
float currentPos = stack.beltPosition;
// Searched past relevant stacks
if (beltMovementPositive ? currentPos < segment : currentPos - 1 > segment)
break;
// Item inside extraction window
if (currentPos > min && currentPos < max)
return false;
// Items on the belt get prioritized if the previous item was inserted on the
// same segment
if (stack.insertedAt == segment && stack.insertedFrom == side
&& (beltMovementPositive ? currentPos <= segment + 1.5 : currentPos - 1.5 >= segment))
return false;
}
return true;
}
protected void insert(TransportedItemStack newStack) {
if (items.isEmpty())
items.add(newStack);
else {
int index = 0;
for (TransportedItemStack stack : items) {
if (stack.compareTo(newStack) > 0 == beltMovementPositive)
break;
index++;
}
items.add(index, newStack);
}
}
public TransportedItemStack getStackAtOffset(int offset) {
float min = offset + .5f - (SEGMENT_WINDOW / 2);
float max = offset + .5f + (SEGMENT_WINDOW / 2);
for (TransportedItemStack stack : items) {
if (stack.beltPosition > max)
break;
if (stack.beltPosition > min)
return stack;
}
return null;
}
public void read(CompoundNBT nbt) {
items.clear();
nbt.getList("Items", NBT.TAG_COMPOUND)
.forEach(inbt -> items.add(TransportedItemStack.read((CompoundNBT) inbt)));
beltMovementPositive = nbt.getBoolean("PositiveOrder");
}
public CompoundNBT write() {
CompoundNBT nbt = new CompoundNBT();
ListNBT itemsNBT = new ListNBT();
items.forEach(stack -> itemsNBT.add(stack.serializeNBT()));
nbt.put("Items", itemsNBT);
nbt.putBoolean("PositiveOrder", beltMovementPositive);
return nbt;
}
public void eject(TransportedItemStack stack) {
ItemStack ejected = stack.stack;
Vec3d outPos = getVectorForOffset(stack.beltPosition);
float movementSpeed = Math.max(Math.abs(belt.getBeltMovementSpeed()), 1 / 8f);
Vec3d outMotion = new Vec3d(belt.getBeltChainDirection()).scale(movementSpeed).add(0, 1 / 8f, 0);
outPos.add(outMotion.normalize());
ItemEntity entity = new ItemEntity(belt.getWorld(), outPos.x, outPos.y + 6 / 16f, outPos.z, ejected);
entity.setMotion(outMotion);
entity.velocityChanged = true;
belt.getWorld().addEntity(entity);
}
public Vec3d getVectorForOffset(float offset) {
Slope slope = belt.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
float verticalMovement = verticality;
if (offset < .5)
verticalMovement = 0;
verticalMovement = verticalMovement * (Math.min(offset, belt.beltLength - .5f) - .5f);
Vec3d vec = VecHelper.getCenterOf(belt.getPos());
vec = vec.add(new Vec3d(belt.getBeltFacing().getDirectionVec()).scale(offset - .5f)).add(0, verticalMovement,
0);
return vec;
}
private BeltTileEntity getBeltSegment(int segment) {
BlockPos pos = getPositionForOffset(segment);
TileEntity te = belt.getWorld().getTileEntity(pos);
if (te == null || !(te instanceof BeltTileEntity))
return null;
return (BeltTileEntity) te;
}
private BlockPos getPositionForOffset(int offset) {
BlockPos pos = belt.getPos();
Vec3i vec = belt.getBeltFacing().getDirectionVec();
Slope slope = belt.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
return pos.add(offset * vec.getX(), MathHelper.clamp(offset, 0, belt.beltLength - 1) * verticality,
offset * vec.getZ());
}
private boolean movingPositive() {
return belt.getDirectionAwareBeltMovementSpeed() > 0;
}
public IItemHandler createHandlerForSegment(int segment) {
return new ItemHandlerBeltSegment(this, segment);
}
public void forEachWithin(float position, float distance,
Function<TransportedItemStack, List<TransportedItemStack>> callback) {
List<TransportedItemStack> toBeAdded = new ArrayList<>();
boolean dirty = false;
for (Iterator<TransportedItemStack> iterator = items.iterator(); iterator.hasNext();) {
TransportedItemStack transportedItemStack = iterator.next();
if (Math.abs(position - transportedItemStack.beltPosition) < distance) {
List<TransportedItemStack> apply = callback.apply(transportedItemStack);
if (apply == null)
continue;
dirty = true;
toBeAdded.addAll(apply);
iterator.remove();
}
}
toBeAdded.forEach(this::insert);
if (dirty) {
belt.markDirty();
belt.sendData();
}
}
}

View file

@ -0,0 +1,86 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.nio.ByteBuffer;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BufferManipulator;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
public class BeltModelAnimator extends BufferManipulator {
protected static TextureAtlasSprite beltTextures;
protected static TextureAtlasSprite originalTexture;
public BeltModelAnimator(ByteBuffer template) {
super(template);
}
private void initSprites() {
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
originalTexture = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt"));
beltTextures = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt_animated"));
}
public ByteBuffer getTransformed(BeltTileEntity te, float x, float y, float z, int color) {
original.rewind();
mutable.rewind();
float textureOffsetX = 0;
float textureOffsetY = 0;
if (te.getSpeed() != 0) {
float time = AnimationTickHolder.getRenderTick();
Direction direction = te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
if (direction == Direction.EAST || direction == Direction.NORTH)
time = -time;
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
if (textureIndex < 0)
textureIndex += 16;
if (beltTextures == null)
initSprites();
textureOffsetX = beltTextures.getInterpolatedU((textureIndex % 4) * 4) - originalTexture.getMinU();
textureOffsetY = beltTextures.getInterpolatedV((textureIndex / 4) * 4) - originalTexture.getMinV();
}
final BlockState blockState = te.getBlockState();
int packedLightCoords = blockState.getPackedLightmapCoords(te.getWorld(), te.getPos());
float texOffX = textureOffsetX;
float texOffY = textureOffsetY;
boolean defaultColor = color == -1;
int b = defaultColor ? 128 : color & 0xFF;
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + x, getY(original, vertex) + y, getZ(original, vertex) + z);
putLight(mutable, vertex, packedLightCoords);
int bufferPosition = getBufferPosition(vertex);
mutable.putFloat(bufferPosition + 16, original.getFloat(bufferPosition + 16) + texOffX);
mutable.putFloat(bufferPosition + 20, original.getFloat(bufferPosition + 20) + texOffY);
byte lumByte = getR(original, vertex);
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
int r2 = (int) (r * lum);
int g2 = (int) (g * lum);
int b2 = (int) (b * lum);
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
}
return mutable;
}
public static void invalidateCache() {
beltTextures = null;
}
}

View file

@ -0,0 +1,184 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import static net.minecraft.entity.MoverType.SELF;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
public class BeltMovementHandler {
public static class TransportedEntityInfo {
int ticksSinceLastCollision;
BlockPos lastCollidedPos;
BlockState lastCollidedState;
public TransportedEntityInfo(BlockPos collision, BlockState belt) {
refresh(collision, belt);
}
public void refresh(BlockPos collision, BlockState belt) {
ticksSinceLastCollision = 0;
lastCollidedPos = new BlockPos(collision).toImmutable();
lastCollidedState = belt;
}
public TransportedEntityInfo tick() {
ticksSinceLastCollision++;
return this;
}
}
public static boolean canBeTransported(Entity entity) {
if (!entity.isAlive())
return false;
if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isSneaking())
return false;
return true;
}
public static void transportEntity(BeltTileEntity beltTe, Entity entityIn, TransportedEntityInfo info) {
BlockPos pos = info.lastCollidedPos;
World world = beltTe.getWorld();
TileEntity te = world.getTileEntity(pos);
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
BlockState blockState = info.lastCollidedState;
Direction movementFacing = Direction.getFacingFromAxisDirection(
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
beltTe.getSpeed() < 0 ? POSITIVE : NEGATIVE);
boolean collidedWithBelt = te instanceof BeltTileEntity;
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
// Don't fight other Belts
if (!collidedWithBelt || betweenBelts) {
return;
}
// Too slow
boolean notHorizontal = beltTe.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
if (Math.abs(beltTe.getSpeed()) < (notHorizontal ? 32 : 1))
return;
// Not on top
if (entityIn.posY - .25f < pos.getY())
return;
// Lock entities in place
boolean isPlayer = entityIn instanceof PlayerEntity;
if (entityIn instanceof LivingEntity && !isPlayer) {
((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 10, 1, false, false));
}
BeltTileEntity belt = (BeltTileEntity) te;
// Attachment pauses movement
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
if (state.attachment.processEntity(belt, entityIn, state)) {
info.ticksSinceLastCollision--;
return;
}
}
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
final Slope slope = blockState.get(BeltBlock.SLOPE);
final Axis axis = beltFacing.getAxis();
float movementSpeed = beltTe.getBeltMovementSpeed();
final Direction movementDirection = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
Vec3i centeringDirection = Direction.getFacingFromAxis(POSITIVE, beltFacing.rotateY().getAxis())
.getDirectionVec();
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(movementSpeed);
double diffCenter = axis == Axis.Z ? (pos.getX() + .5f - entityIn.posX) : (pos.getZ() + .5f - entityIn.posZ);
if (Math.abs(diffCenter) > 48 / 64f)
return;
Part part = blockState.get(BeltBlock.PART);
float top = 13 / 16f;
boolean onSlope = notHorizontal && (part == Part.MIDDLE || part == Part.PULLEY
|| part == (slope == Slope.UPWARD ? Part.END : Part.START) && entityIn.posY - pos.getY() < top
|| part == (slope == Slope.UPWARD ? Part.START : Part.END) && entityIn.posY - pos.getY() > top);
boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? Slope.DOWNWARD : Slope.UPWARD);
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? Slope.UPWARD : Slope.DOWNWARD);
if (beltFacing.getAxis() == Axis.Z) {
boolean b = movingDown;
movingDown = movingUp;
movingUp = b;
}
if (movingUp)
movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
if (movingDown)
movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4);
movement = movement.add(centering);
float step = entityIn.stepHeight;
if (!isPlayer)
entityIn.stepHeight = 1;
// Entity Collisions
if (Math.abs(movementSpeed) < .5f) {
Vec3d checkDistance = movement.normalize().scale(0.5);
AxisAlignedBB bb = entityIn.getBoundingBox();
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
if (!world
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
.isEmpty()) {
entityIn.setMotion(0, 0, 0);
info.ticksSinceLastCollision--;
return;
}
}
if (movingUp) {
float minVelocity = .13f;
float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity));
entityIn.move(SELF, new Vec3d(0, yMovement, 0));
entityIn.move(SELF, movement.mul(1, 0, 1));
} else if (movingDown) {
entityIn.move(SELF, movement.mul(1, 0, 1));
entityIn.move(SELF, movement.mul(0, 1, 0));
} else {
entityIn.move(SELF, movement);
}
if (!isPlayer)
entityIn.stepHeight = step;
boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition()))
|| AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition().down())));
if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > 0)
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
if (movedPastEndingSlope) {
entityIn.setMotion(movement);
entityIn.velocityChanged = true;
}
}
}

View file

@ -0,0 +1,119 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import static net.minecraft.block.Block.makeCuboidShape;
import com.simibubi.create.foundation.utility.VoxelShaper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
public class BeltShapes {
private static final VoxelShape SLOPE_BUILDING_BLOCK_X = makeCuboidShape(5, 5, 1, 11, 11, 15),
SLOPE_BUILDING_BLOCK_Z = makeCuboidShape(1, 5, 5, 15, 11, 11),
CASING_HORIZONTAL = makeCuboidShape(0, 0, 0, 16, 11, 16);
private static final VoxelShaper SLOPE_END = VoxelShaper.forHorizontal(makeCuboidShape(1, 3, 0, 15, 13, 10)),
SLOPE_TOP_END = VoxelShaper.forHorizontal(
VoxelShapes.or(SLOPE_END.get(Direction.SOUTH), createHalfSlope(Direction.SOUTH, false))),
SLOPE_BOTTOM_END = VoxelShaper.forHorizontal(
VoxelShapes.or(SLOPE_END.get(Direction.SOUTH), createHalfSlope(Direction.SOUTH, true))),
FLAT_STRAIGHT = VoxelShaper.forHorizontalAxis(makeCuboidShape(0, 3, 1, 16, 13, 15)),
VERTICAL_STRAIGHT = VoxelShaper.forHorizontalAxis(makeCuboidShape(1, 0, 3, 15, 16, 13)),
SLOPE_STRAIGHT = VoxelShaper.forHorizontal(createSlope(Direction.SOUTH)),
CASING_TOP_END = VoxelShaper.forHorizontal(makeCuboidShape(0, 0, 0, 16, 11, 11));
public static VoxelShape getShape(BlockState state) {
Direction facing = state.get(BeltBlock.HORIZONTAL_FACING);
Axis axis = facing.getAxis();
Axis perpendicularAxis = facing.rotateY().getAxis();
Part part = state.get(BeltBlock.PART);
Slope slope = state.get(BeltBlock.SLOPE);
if (slope == Slope.HORIZONTAL)
return FLAT_STRAIGHT.get(perpendicularAxis);
if (slope == Slope.VERTICAL)
return VERTICAL_STRAIGHT.get(axis);
if (part != Part.MIDDLE && part != Part.PULLEY) {
boolean upward = slope == Slope.UPWARD;
if (part == Part.START)
upward = !upward;
else
facing = facing.getOpposite();
return upward ? SLOPE_TOP_END.get(facing) : SLOPE_BOTTOM_END.get(facing);
}
if (slope == Slope.DOWNWARD)
facing = facing.getOpposite();
return SLOPE_STRAIGHT.get(facing);
}
public static VoxelShape getCasingShape(BlockState state) {
if (!state.get(BeltBlock.CASING))
return VoxelShapes.empty();
Direction facing = state.get(BeltBlock.HORIZONTAL_FACING);
Part part = state.get(BeltBlock.PART);
Slope slope = state.get(BeltBlock.SLOPE);
if (slope == Slope.HORIZONTAL)
return CASING_HORIZONTAL;
if (slope == Slope.VERTICAL)
return VoxelShapes.empty();
if (part != Part.MIDDLE) {
boolean upward = slope == Slope.UPWARD;
if (part == Part.START)
upward = !upward;
else
facing = facing.getOpposite();
return upward ? CASING_TOP_END.get(facing) : CASING_HORIZONTAL;
}
if (slope == Slope.DOWNWARD)
facing = facing.getOpposite();
return CASING_TOP_END.get(facing.getOpposite());
}
protected static VoxelShape createSlope(Direction facing) {
return VoxelShapes.or(createHalfSlope(facing.getOpposite(), false), createHalfSlope(facing, true));
}
protected static VoxelShape createHalfSlope(Direction facing, boolean upward) {
VoxelShape shape = VoxelShapes.empty();
VoxelShape buildingBlock = facing.getAxis() == Axis.X ? SLOPE_BUILDING_BLOCK_X : SLOPE_BUILDING_BLOCK_Z;
Vec3i directionVec = facing.getDirectionVec();
int x = directionVec.getX();
int y = upward ? 1 : -1;
int z = directionVec.getZ();
for (int segment = 0; segment < 6; segment++)
shape = VoxelShapes.or(shape,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f));
if (!upward)
return shape;
VoxelShape mask = makeCuboidShape(0, -8, 0, 16, 24, 16);
for (int segment = 6; segment < 11; segment++)
shape = VoxelShapes.or(shape,
VoxelShapes.combine(mask,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f),
IBooleanFunction.AND));
return shape;
}
}

View file

@ -1,5 +1,13 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part.END;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part.MIDDLE;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.DOWNWARD;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.HORIZONTAL;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.UPWARD;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -9,116 +17,180 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class BeltTileEntity extends KineticTileEntity {
protected BlockPos controller;
public Map<Entity, TransportedEntityInfo> passengers;
public AllBeltAttachments.Tracker attachmentTracker;
private CompoundNBT trackerUpdateTag;
public int color;
public int beltLength;
public int index;
protected static class TransportedEntityInfo {
int ticksSinceLastCollision;
BlockPos lastCollidedPos;
BlockState lastCollidedState;
protected BlockPos controller;
protected BeltInventory inventory;
protected LazyOptional<IItemHandler> itemHandler;
public TransportedEntityInfo(BlockPos collision, BlockState belt) {
refresh(collision, belt);
}
public void refresh(BlockPos collision, BlockState belt) {
ticksSinceLastCollision = 0;
lastCollidedPos = new BlockPos(collision).toImmutable();
lastCollidedState = belt;
}
public TransportedEntityInfo tick() {
ticksSinceLastCollision++;
return this;
}
}
private CompoundNBT trackerUpdateTag;
public BeltTileEntity() {
super(AllTileEntities.BELT.type);
controller = BlockPos.ZERO;
attachmentTracker = new Tracker(this);
itemHandler = LazyOptional.empty();
color = -1;
beltLength = -1;
index = -1;
}
protected boolean isLastBelt() {
@Override
public void tick() {
super.tick();
// Initialize Belt Attachments
if (world != null && trackerUpdateTag != null) {
attachmentTracker.readAndSearch(trackerUpdateTag, this);
trackerUpdateTag = null;
}
if (getSpeed() == 0)
return false;
return;
Direction direction = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
return false;
initializeItemHandler();
Part part = getBlockState().get(BeltBlock.PART);
if (part == Part.MIDDLE)
return false;
// Move Items
if (!isController())
return;
getInventory().tick();
boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1))
^ direction.getAxis() == Axis.X;
return part == Part.START ^ movingPositively;
// Move Entities
if (passengers == null)
passengers = new HashMap<>();
List<Entity> toRemove = new ArrayList<>();
passengers.forEach((entity, info) -> {
boolean canBeTransported = BeltMovementHandler.canBeTransported(entity);
boolean leftTheBelt = info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != HORIZONTAL)
? 3
: 1);
if (!canBeTransported || leftTheBelt) {
toRemove.add(entity);
return;
}
info.tick();
BeltMovementHandler.transportEntity(this, entity, info);
});
toRemove.forEach(passengers::remove);
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
if (!isController())
return super.getRenderBoundingBox();
return super.getRenderBoundingBox().grow(beltLength);
}
protected void initializeItemHandler() {
if (world.isRemote || itemHandler.isPresent())
return;
if (!world.isBlockPresent(controller))
return;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return;
IItemHandler handler = ((BeltTileEntity) te).getInventory().createHandlerForSegment(index);
itemHandler = LazyOptional.of(() -> handler);
}
@Override
public boolean hasFastRenderer() {
return !isController();
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
if (side == Direction.UP || BeltBlock.canAccessFromSide(side, getBlockState())) {
return itemHandler.cast();
}
}
return super.getCapability(cap, side);
}
@Override
public void remove() {
super.remove();
itemHandler.invalidate();
}
@Override
public CompoundNBT write(CompoundNBT compound) {
attachmentTracker.write(compound);
compound.put("Controller", NBTUtil.writeBlockPos(controller));
compound.putInt("Color", color);
attachmentTracker.write(compound);
compound.putInt("Length", beltLength);
compound.putInt("Index", index);
if (isController())
compound.put("Inventory", getInventory().write());
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
trackerUpdateTag = compound;
controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
color = compound.getInt("Color");
beltLength = compound.getInt("Length");
index = compound.getInt("Index");
if (isController())
getInventory().read(compound.getCompound("Inventory"));
super.read(compound);
}
public void applyColor(DyeColor colorIn) {
int colorValue = colorIn.getMapColor().colorValue;
for (BlockPos blockPos : BeltBlock.getBeltChain(world, getController())) {
BeltTileEntity tileEntity = (BeltTileEntity) world.getTileEntity(blockPos);
if (tileEntity != null) {
if (tileEntity.color == -1) {
tileEntity.color = colorValue;
} else {
tileEntity.color = ColorHelper.mixColors(tileEntity.color, colorValue, .5f);
}
tileEntity.sendData();
}
BeltTileEntity belt = (BeltTileEntity) world.getTileEntity(blockPos);
if (belt == null)
continue;
belt.color = belt.color == -1 ? colorValue : ColorHelper.mixColors(belt.color, colorValue, .5f);
belt.markDirty();
belt.sendData();
}
}
public BeltTileEntity getControllerTE() {
if (!world.isBlockPresent(controller))
return null;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return null;
return (BeltTileEntity) te;
}
public void setController(BlockPos controller) {
this.controller = controller;
}
@ -131,177 +203,123 @@ public class BeltTileEntity extends KineticTileEntity {
return controller.equals(pos);
}
public float getBeltMovementSpeed() {
return getSpeed() / 1600f;
}
public float getDirectionAwareBeltMovementSpeed() {
int offset = getBeltFacing().getAxisDirection().getOffset();
if (getBeltFacing().getAxis() == Axis.X)
offset *= -1;
return getSpeed() / 1600f * offset;
}
public boolean hasPulley() {
if (!AllBlocks.BELT.typeOf(getBlockState()))
return false;
return getBlockState().get(BeltBlock.PART) == Part.END || getBlockState().get(BeltBlock.PART) == Part.START;
return getBlockState().get(BeltBlock.PART) != Part.MIDDLE;
}
@Override
public void tick() {
super.tick();
if (world != null && trackerUpdateTag != null) {
attachmentTracker.readAndSearch(trackerUpdateTag, this);
trackerUpdateTag = null;
}
if (!isController())
return;
if (passengers == null)
passengers = new HashMap<>();
passengers.forEach((entity, info) -> {
transportEntity(entity, info);
});
List<Entity> toRemove = new ArrayList<>();
passengers.forEach((entity, info) -> {
if (!canTransport(entity))
toRemove.add(entity);
if (info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL) ? 3 : 1)) {
toRemove.add(entity);
}
info.tick();
});
toRemove.forEach(e -> {
if (e instanceof ItemEntity)
((ItemEntity) e).setAgeToCreativeDespawnTime();
passengers.remove(e);
});
protected boolean isLastBelt() {
if (getSpeed() == 0)
return;
return false;
Direction direction = getBeltFacing();
if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
return false;
Part part = getBlockState().get(BeltBlock.PART);
if (part == MIDDLE)
return false;
boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1))
^ direction.getAxis() == Axis.X;
return part == Part.START ^ movingPositively;
}
public void transportEntity(Entity entityIn, TransportedEntityInfo info) {
BlockPos pos = info.lastCollidedPos;
TileEntity te = world.getTileEntity(pos);
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
BlockState blockState = info.lastCollidedState;
Direction movementFacing = Direction.getFacingFromAxisDirection(
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
getSpeed() < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE);
public Vec3i getMovementDirection(boolean firstHalf) {
return this.getMovementDirection(firstHalf, false);
}
boolean collidedWithBelt = te instanceof BeltTileEntity;
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
public Vec3i getBeltChainDirection() {
return this.getMovementDirection(true, true);
}
// Don't fight other Belts
if (!collidedWithBelt || betweenBelts) {
return;
}
// Too slow
boolean notHorizontal = getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
if (Math.abs(getSpeed()) < (notHorizontal ? 32 : 1))
return;
// Not on top
if (entityIn.posY - .25f < pos.getY())
return;
// Lock entities in place
if (entityIn instanceof LivingEntity && !(entityIn instanceof PlayerEntity)) {
((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 1, 9, false, false));
}
BeltTileEntity belt = (BeltTileEntity) te;
// Attachment pauses movement
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
if (state.attachment.handleEntity(belt, entityIn, state)) {
info.ticksSinceLastCollision--;
return;
}
}
protected Vec3i getMovementDirection(boolean firstHalf, boolean ignoreHalves) {
if (getSpeed() == 0)
return BlockPos.ZERO;
final BlockState blockState = getBlockState();
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
final Slope slope = blockState.get(BeltBlock.SLOPE);
final Part part = blockState.get(BeltBlock.PART);
final Axis axis = beltFacing.getAxis();
float movementSpeed = ((KineticTileEntity) te).getSpeed() / 1600f;
final Direction movementDirection = Direction
.getFacingFromAxis(axis == Axis.X ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE, axis);
Vec3i centeringDirection = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis == Axis.X ? Axis.Z : Axis.X)
.getDirectionVec();
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(movementSpeed);
Direction movementFacing = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
boolean notHorizontal = blockState.get(BeltBlock.SLOPE) != HORIZONTAL;
if (getSpeed() < 0)
movementFacing = movementFacing.getOpposite();
Vec3i movement = movementFacing.getDirectionVec();
double diffCenter = axis == Axis.Z ? (pos.getX() + .5f - entityIn.posX) : (pos.getZ() + .5f - entityIn.posZ);
float maxDiffCenter = (entityIn instanceof ItemEntity) ? 32 / 64f : 48 / 64f;
if (Math.abs(diffCenter) > maxDiffCenter)
return;
boolean slopeBeforeHalf = (part == END) == (beltFacing.getAxisDirection() == POSITIVE);
boolean onSlope = notHorizontal && (part == MIDDLE || slopeBeforeHalf == firstHalf || ignoreHalves);
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? UPWARD : DOWNWARD);
Part part = blockState.get(BeltBlock.PART);
float top = 13 / 16f;
boolean onSlope = notHorizontal && (part == Part.MIDDLE
|| part == (slope == Slope.UPWARD ? Part.END : Part.START) && entityIn.posY - pos.getY() < top
|| part == (slope == Slope.UPWARD ? Part.START : Part.END) && entityIn.posY - pos.getY() > top);
if (!onSlope)
return movement;
boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? Slope.DOWNWARD : Slope.UPWARD);
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? Slope.UPWARD : Slope.DOWNWARD);
if (beltFacing.getAxis() == Axis.Z) {
boolean b = movingDown;
movingDown = movingUp;
movingUp = b;
}
if (movingUp)
movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
if (movingDown)
movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4);
movement = movement.add(centering);
float step = entityIn.stepHeight;
if (!(entityIn instanceof PlayerEntity))
entityIn.stepHeight = 1;
// Entity Collisions
if (Math.abs(movementSpeed) < .5f) {
Vec3d checkDistance = movement.scale(2f).add(movement.normalize());
AxisAlignedBB bb = entityIn.getBoundingBox();
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
if (!world
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
.isEmpty()) {
entityIn.setMotion(0, 0, 0);
info.ticksSinceLastCollision--;
return;
}
}
if (movingUp) {
float minVelocity = entityIn instanceof ItemEntity ? .09f : .13f;
float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity));
entityIn.move(MoverType.SELF, new Vec3d(0, yMovement, 0));
entityIn.move(MoverType.SELF, movement.mul(1, 0, 1));
} else if (movingDown) {
entityIn.move(MoverType.SELF, movement.mul(1, 0, 1));
entityIn.move(MoverType.SELF, movement.mul(0, 1, 0));
} else {
entityIn.move(MoverType.SELF, movement);
}
if (!(entityIn instanceof PlayerEntity))
entityIn.stepHeight = step;
boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition()))
|| AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition().down())));
if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > 0)
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
if (movedPastEndingSlope)
entityIn.setMotion(movement);
return new Vec3i(movement.getX(), movingUp ? 1 : -1, movement.getZ());
}
public boolean canTransport(Entity entity) {
if (!entity.isAlive())
return false;
if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isSneaking())
return false;
public Direction getMovementFacing() {
return Direction.getFacingFromAxisDirection(getBeltFacing().getAxis(),
getBeltMovementSpeed() < 0 ? POSITIVE : NEGATIVE);
}
protected Direction getBeltFacing() {
return getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
}
public BeltInventory getInventory() {
if (inventory == null)
inventory = new BeltInventory(this);
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) {
BeltTileEntity nextBeltController = getControllerTE();
if (nextBeltController == null)
return false;
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.markDirty();
nextBeltController.sendData();
return true;
}

View file

@ -1,114 +1,159 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.nio.ByteBuffer;
import java.util.Random;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BufferManipulator;
import com.simibubi.create.foundation.utility.IndependentShadowRenderer;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
public class BeltTileEntityRenderer extends KineticTileEntityRenderer {
@SuppressWarnings("deprecation")
public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
protected static class BeltModelAnimator extends BufferManipulator {
protected static TextureAtlasSprite beltTextures;
protected static TextureAtlasSprite originalTexture;
@Override
public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(te, x, y, z, partialTicks, destroyStage);
public BeltModelAnimator(ByteBuffer template) {
super(template);
if (beltTextures == null)
initSprites();
}
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw();
private void initSprites() {
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
originalTexture = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt"));
beltTextures = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt_animated"));
}
if (te.isController()) {
GlStateManager.pushMatrix();
public ByteBuffer getTransformed(BeltTileEntity te, float x, float y, float z, int color) {
original.rewind();
mutable.rewind();
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);
Slope slope = te.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
boolean slopeAlongX = te.getBeltFacing().getAxis() == Axis.X;
float textureOffsetX = 0;
float textureOffsetY = 0;
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);
float verticalMovement = verticality;
if (te.getSpeed() == 0) {
offset = transported.beltPosition;
sideOffset = transported.sideOffset;
}
if (te.getSpeed() != 0) {
float time = AnimationTickHolder.getRenderTick();
Direction direction = te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
if (direction == Direction.EAST || direction == Direction.NORTH)
time = -time;
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
if (textureIndex < 0)
textureIndex += 16;
if (offset < .5)
verticalMovement = 0;
verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f);
Vec3d offsetVec = new Vec3d(directionVec).scale(offset).add(0, verticalMovement, 0);
boolean onSlope = slope != Slope.HORIZONTAL
&& MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset;
float slopeAngle = onSlope
? slope == Slope.DOWNWARD ^ te.getDirectionAwareBeltMovementSpeed() > 0
^ te.getBeltMovementSpeed() < 0 ? -45 : 45
: 0;
textureOffsetX = beltTextures.getInterpolatedU((textureIndex % 4) * 4) - originalTexture.getMinU();
textureOffsetY = beltTextures.getInterpolatedV((textureIndex / 4) * 4) - originalTexture.getMinV();
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;
GlStateManager.rotated(slopeAngle, slopeAlongX ? 0 : 1, 0, slopeAlongX ? 1 : 0);
if (onSlope)
GlStateManager.translated(0, 1 / 8f, 0);
Random r = new Random(transported.angle);
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);
}
if (blockItem) {
GlStateManager.translated(r.nextFloat() * .25f, 0, r.nextFloat() * .25f);
}
GlStateManager.scaled(.5, .5, .5);
itemRenderer.renderItem(transported.stack, TransformType.FIXED);
GlStateManager.popMatrix();
if (!blockItem)
GlStateManager.rotated(10, 0, 1, 0);
GlStateManager.translated(0, blockItem ? 1 / 64d : 1 / 16d, 0);
}
RenderHelper.disableStandardItemLighting();
GlStateManager.popMatrix();
}
final BlockState blockState = te.getBlockState();
int packedLightCoords = blockState.getPackedLightmapCoords(te.getWorld(), te.getPos());
float texOffX = textureOffsetX;
float texOffY = textureOffsetY;
boolean defaultColor = color == -1;
int b = defaultColor ? 128 : color & 0xFF;
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + x, getY(original, vertex) + y,
getZ(original, vertex) + z);
putLight(mutable, vertex, packedLightCoords);
int bufferPosition = getBufferPosition(vertex);
mutable.putFloat(bufferPosition + 16, original.getFloat(bufferPosition + 16) + texOffX);
mutable.putFloat(bufferPosition + 20, original.getFloat(bufferPosition + 20) + texOffY);
byte lumByte = getR(original, vertex);
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
int r2 = (int) (r * lum);
int g2 = (int) (g * lum);
int b2 = (int) (b * lum);
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
}
return mutable;
GlStateManager.popMatrix();
}
}
@Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
public void renderTileEntityFast(BeltTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
BeltTileEntity beltEntity = (BeltTileEntity) te;
if (beltEntity.hasPulley())
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
if (te.hasPulley()) {
final BlockState state = getRenderedBlockState(te);
KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
final BlockPos pos = te.getPos();
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
float angle = KineticTileEntityRenderer.getAngleForTe(te, pos, axis);
KineticTileEntityRenderer.renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos,
axis, angle);
}
cacheIfMissing(beltEntity.getBlockState(), getWorld(), BeltModelAnimator::new);
renderBeltFromCache(beltEntity, (float) x, (float) y, (float) z, buffer);
KineticTileEntityRenderer.cacheIfMissing(te.getBlockState().with(BeltBlock.CASING, false), getWorld(),
BeltModelAnimator::new);
renderBeltFromCache(te, (float) x, (float) y, (float) z, buffer);
}
@Override
protected BlockState getRenderedBlockState(KineticTileEntity te) {
return AllBlocks.BELT_PULLEY.get().getDefaultState().with(BlockStateProperties.AXIS,
((IRotate) AllBlocks.BELT.get()).getRotationAxis(te.getBlockState()));
}
public void renderBeltFromCache(BeltTileEntity te, float x, float y, float z, BufferBuilder buffer) {
buffer.putBulkData(
((BeltModelAnimator) cachedBuffers.get(te.getBlockState())).getTransformed(te, x, y, z, te.color));
buffer.putBulkData(((BeltModelAnimator) KineticTileEntityRenderer.cachedBuffers
.get(te.getBlockState().with(BeltBlock.CASING, false))).getTransformed(te, x, y, z, te.color));
}
}

View file

@ -0,0 +1,69 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
public class ItemHandlerBeltSegment implements IItemHandler {
private final BeltInventory beltInventory;
int offset;
public ItemHandlerBeltSegment(BeltInventory beltInventory, int offset) {
this.beltInventory = beltInventory;
this.offset = offset;
}
@Override
public int getSlots() {
return 1;
}
@Override
public ItemStack getStackInSlot(int slot) {
TransportedItemStack stackAtOffset = this.beltInventory.getStackAtOffset(offset);
if (stackAtOffset == null)
return ItemStack.EMPTY;
return stackAtOffset.stack;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (this.beltInventory.canInsertAt(offset)) {
if (!simulate) {
TransportedItemStack newStack = new TransportedItemStack(stack);
newStack.insertedAt = offset;
newStack.beltPosition = offset + .5f;
newStack.prevBeltPosition = newStack.beltPosition;
this.beltInventory.insert(newStack);
}
return ItemStack.EMPTY;
}
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
TransportedItemStack transported = this.beltInventory.getStackAtOffset(offset);
if (transported == null)
return ItemStack.EMPTY;
amount = Math.min(amount, transported.stack.getCount());
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
if (!simulate) {
this.beltInventory.belt.markDirty();
this.beltInventory.belt.sendData();
}
return extracted;
}
@Override
public int getSlotLimit(int slot) {
return Math.min(getStackInSlot(slot).getMaxStackSize(), 64);
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
}

View file

@ -0,0 +1,87 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Random;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
public class TransportedItemStack implements Comparable<TransportedItemStack> {
public ItemStack stack;
public float beltPosition;
public float sideOffset;
public int angle;
public int insertedAt;
public Direction insertedFrom;
public boolean locked;
public float prevBeltPosition;
public float prevSideOffset;
public InWorldProcessing.Type processedBy;
public int processingTime;
public TransportedItemStack(ItemStack stack) {
this.stack = stack;
angle = new Random().nextInt(360);
sideOffset = prevSideOffset = getTargetSideOffset();
insertedFrom = Direction.UP;
}
public float getTargetSideOffset() {
return (angle - 180) / (360 * 3f);
}
@Override
public int compareTo(TransportedItemStack o) {
return beltPosition < o.beltPosition ? 1 : beltPosition > o.beltPosition ? -1 : 0;
}
public TransportedItemStack getSimilar() {
TransportedItemStack copy = new TransportedItemStack(stack.copy());
copy.beltPosition = beltPosition;
copy.insertedAt = insertedAt;
copy.insertedFrom = insertedFrom;
copy.prevBeltPosition = prevBeltPosition;
copy.prevSideOffset = prevSideOffset;
copy.processedBy = processedBy;
copy.processingTime = processingTime;
return copy;
}
public TransportedItemStack copy() {
TransportedItemStack copy = getSimilar();
copy.angle = angle;
return copy;
}
public CompoundNBT serializeNBT() {
CompoundNBT nbt = new CompoundNBT();
nbt.put("Item", stack.serializeNBT());
nbt.putFloat("Pos", beltPosition);
nbt.putFloat("PrevPos", prevBeltPosition);
nbt.putFloat("Offset", sideOffset);
nbt.putFloat("PrevOffset", prevSideOffset);
nbt.putInt("InSegment", insertedAt);
nbt.putInt("Angle", angle);
nbt.putInt("InDirection", insertedFrom.getIndex());
nbt.putBoolean("Locked", locked);
return nbt;
}
public static TransportedItemStack read(CompoundNBT nbt) {
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
stack.beltPosition = nbt.getFloat("Pos");
stack.prevBeltPosition = nbt.getFloat("PrevPos");
stack.sideOffset = nbt.getFloat("Offset");
stack.prevSideOffset = nbt.getFloat("PrevOffset");
stack.insertedAt = nbt.getInt("InSegment");
stack.angle = nbt.getInt("Angle");
stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection"));
stack.locked = nbt.getBoolean("Locked");
return stack;
}
}

View file

@ -20,7 +20,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity {
private BlockState partialBlock = Blocks.AIR.getDefaultState();
private BlockState windowBlock = Blocks.AIR.getDefaultState();
@OnlyIn(value = Dist.CLIENT)
private IModelData modelData;
@ -64,7 +64,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity {
windowBlock = getWindowBlock().updatePostPlacement(side, world.getBlockState(offsetPos), world, pos,
offsetPos);
}
sendData();
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16);
markDirty();
}

View file

@ -1,13 +1,17 @@
package com.simibubi.create.modules.logistics;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.ItemHelper;
import com.simibubi.create.modules.contraptions.base.ProcessingRecipe;
import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
@ -40,12 +44,27 @@ public class InWorldProcessing {
}
public static boolean canProcess(ItemEntity entity, Type type) {
World world = entity.world;
if (entity.getPersistentData().contains("CreateData")) {
CompoundNBT compound = entity.getPersistentData().getCompound("CreateData");
if (compound.contains("Processing")) {
CompoundNBT processing = compound.getCompound("Processing");
if (entity.getPersistentData().contains("CreateData")
&& entity.getPersistentData().getCompound("CreateData").contains("Processing"))
return true;
if (Type.valueOf(processing.getString("Type")) != type) {
boolean canProcess = canProcess(entity.getItem(), type, entity.world);
processing.putString("Type", type.name());
if (!canProcess)
processing.putInt("Time", -1);
return canProcess;
} else if (processing.getInt("Time") >= 0)
return true;
else if (processing.getInt("Time") == -1)
return false;
}
}
return canProcess(entity.getItem(), type, entity.world);
}
private static boolean canProcess(ItemStack stack, Type type, World world) {
if (type == Type.BLASTING) {
return true;
}
@ -53,13 +72,13 @@ public class InWorldProcessing {
if (type == Type.SMOKING) {
SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem());
smoker.setInventorySlotContents(0, stack);
Optional<SmokingRecipe> recipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
return recipe.isPresent();
}
if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem());
splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world);
return recipe.isPresent();
@ -68,59 +87,90 @@ public class InWorldProcessing {
return false;
}
public static void process(ItemEntity entity, Type type) {
World world = entity.world;
public static void applyProcessing(ItemEntity entity, Type type) {
if (decrementProcessingTime(entity, type) != 0)
return;
List<ItemStack> stacks = process(entity.getItem(), type, entity.world);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
public static List<TransportedItemStack> applyProcessing(TransportedItemStack transported, BeltTileEntity belt, Type type) {
if (transported.processedBy != type) {
transported.processedBy = type;
transported.processingTime = CreateConfig.parameters.inWorldProcessingTime.get() + 1;
if (!canProcess(transported.stack, type, belt.getWorld()))
transported.processingTime = -1;
return null;
}
if (transported.processingTime == -1)
return null;
if (transported.processingTime-- > 0)
return null;
List<ItemStack> stacks = process(transported.stack, type, belt.getWorld());
List<TransportedItemStack> transportedStacks = new ArrayList<>();
for (ItemStack additional : stacks) {
TransportedItemStack newTransported = transported.getSimilar();
newTransported.stack = additional.copy();
transportedStacks.add(newTransported);
}
return transportedStacks;
}
private static List<ItemStack> process(ItemStack stack, Type type, World world) {
if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem());
splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world);
if (recipe.isPresent())
applyRecipeOn(entity, recipe.get());
return;
return applyRecipeOn(stack, recipe.get());
return null;
}
SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem());
smoker.setInventorySlotContents(0, stack);
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
if (type == Type.BLASTING) {
FurnaceTileEntity furnace = new FurnaceTileEntity();
furnace.setWorld(world);
furnace.setInventorySlotContents(0, entity.getItem());
furnace.setInventorySlotContents(0, stack);
Optional<FurnaceRecipe> smeltingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace,
world);
if (!smokingRecipe.isPresent()) {
if (smeltingRecipe.isPresent()) {
applyRecipeOn(entity, smeltingRecipe.get());
return;
}
if (smeltingRecipe.isPresent())
return applyRecipeOn(stack, smeltingRecipe.get());
BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity();
blastFurnace.setWorld(world);
blastFurnace.setInventorySlotContents(0, entity.getItem());
blastFurnace.setInventorySlotContents(0, stack);
Optional<BlastingRecipe> blastingRecipe = world.getRecipeManager().getRecipe(IRecipeType.BLASTING,
blastFurnace, world);
if (blastingRecipe.isPresent()) {
applyRecipeOn(entity, blastingRecipe.get());
return;
}
if (blastingRecipe.isPresent())
return applyRecipeOn(stack, blastingRecipe.get());
}
entity.remove();
return;
return Collections.emptyList();
}
if (type == Type.SMOKING && smokingRecipe.isPresent()) {
applyRecipeOn(entity, smokingRecipe.get());
return;
}
if (type == Type.SMOKING && smokingRecipe.isPresent())
return applyRecipeOn(stack, smokingRecipe.get());
return null;
}
private static int decrementProcessingTime(ItemEntity entity, Type type) {
@ -143,14 +193,31 @@ public class InWorldProcessing {
processing.putInt("Time", value);
return value;
}
public static void applyRecipeOn(ItemEntity entity, IRecipe<?> recipe) {
List<ItemStack> stacks = applyRecipeOn(entity.getItem(), recipe);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
private static List<ItemStack> applyRecipeOn(ItemStack stackIn, IRecipe<?> recipe) {
List<ItemStack> stacks;
if (recipe instanceof SplashingRecipe) {
if (recipe instanceof ProcessingRecipe) {
stacks = new ArrayList<>();
for (int i = 0; i < entity.getItem().getCount(); i++) {
for (ItemStack stack : ((SplashingRecipe) recipe).rollResults()) {
for (int i = 0; i < stackIn.getCount(); i++) {
List<ItemStack> rollResults = ((ProcessingRecipe<?>) recipe).rollResults();
for (ItemStack stack : rollResults) {
for (ItemStack previouslyRolled : stacks) {
if (stack.isEmpty())
continue;
@ -170,19 +237,10 @@ public class InWorldProcessing {
}
} else {
ItemStack out = recipe.getRecipeOutput().copy();
stacks = ItemHelper.multipliedOutput(entity.getItem(), out);
stacks = ItemHelper.multipliedOutput(stackIn, out);
}
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
return stacks;
}
public static boolean isFrozen() {

View file

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

View file

@ -1,8 +1,8 @@
package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithTileEntity;
@ -10,22 +10,25 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
@ -35,7 +38,8 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, IWithTileEntity<BeltFunnelTileEntity> {
public class BeltFunnelBlock extends HorizontalBlock
implements IBeltAttachment, IWithTileEntity<BeltFunnelTileEntity>, IBlockWithFilter {
public static final VoxelShape SHAPE_NORTH = makeCuboidShape(3, -4, -1, 13, 8, 5),
SHAPE_SOUTH = makeCuboidShape(3, -4, 11, 13, 8, 17), SHAPE_WEST = makeCuboidShape(-1, -4, 3, 5, 8, 13),
@ -43,13 +47,14 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
public BeltFunnelBlock() {
super(Properties.from(Blocks.ANDESITE));
cacheItemPositions();
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
@ -77,9 +82,14 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
BlockPos neighbourPos = pos.offset(state.get(HORIZONTAL_FACING));
BlockState neighbour = worldIn.getBlockState(neighbourPos);
if (AllBlocks.BELT.typeOf(neighbour)) {
return BeltBlock.canAccessFromSide(state.get(HORIZONTAL_FACING), neighbour);
}
return !neighbour.getShape(worldIn, pos).isEmpty();
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = getDefaultState();
@ -138,34 +148,89 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
}
@Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) {
return Arrays.asList(te.getPos().up());
public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
return Arrays.asList(pos.up());
}
@Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) {
BlockPos validPos = pos.down();
BlockState blockState = world.getBlockState(validPos);
if (!AllBlocks.BELT.typeOf(blockState)
|| blockState.get(HORIZONTAL_FACING).getAxis() != state.get(HORIZONTAL_FACING).getAxis())
return Optional.empty();
return Optional.of(validPos);
public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
return pos.down();
}
@Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
boolean isItem = entity instanceof ItemEntity;
if (!isItem && !(entity instanceof CardboardBoxEntity))
return false;
boolean slope = te.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
if (isItem && entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > (slope ? .6f : .4f))
return false;
entity.setMotion(Vec3d.ZERO);
withTileEntityDo(te.getWorld(), state.attachmentPos, funnelTE -> {
funnelTE.tryToInsert(entity);
});
public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
return process(te, transported, state);
}
@Override
public boolean processItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
Direction movementFacing = te.getMovementFacing();
if (movementFacing.getAxis() == Axis.Z)
movementFacing = movementFacing.getOpposite();
if (movementFacing != te.getWorld().getBlockState(state.attachmentPos)
.get(HORIZONTAL_FACING))
return false;
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;
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit);
}
private static final List<Vec3d> itemPositions = new ArrayList<>(Direction.values().length);
private void cacheItemPositions() {
itemPositions.clear();
Vec3d position = Vec3d.ZERO;
Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO);
float zFightOffset = 1 / 128f;
for (int i = 0; i < 4; i++) {
Direction facing = Direction.byHorizontalIndex(i);
position = new Vec3d(8f / 16f + zFightOffset, 9f / 16f, 2.25f / 16f);
float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X)
angle = -angle;
position = VecHelper.rotate(position.subtract(shift), angle, Axis.Y).add(shift);
itemPositions.add(position);
}
}
@Override
public boolean showsCount() {
return true;
}
@Override
public float getItemHitboxScale() {
return 1.76f / 16f;
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING).getOpposite();
return itemPositions.get(facing.getHorizontalIndex());
}
@Override
public Direction getFilterFacing(BlockState state) {
return state.get(HORIZONTAL_FACING).getOpposite();
}
}

View file

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

View file

@ -0,0 +1,22 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class BeltFunnelTileEntityRenderer extends TileEntityRenderer<BeltFunnelTileEntity> {
FilteredTileEntityRenderer filterRenderer;
public BeltFunnelTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override
public void render(BeltFunnelTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
}
}

View file

@ -3,7 +3,6 @@ package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import com.simibubi.create.AllBlocks;
@ -15,6 +14,7 @@ import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
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.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import net.minecraft.block.Block;
@ -129,16 +129,20 @@ public class EntityDetectorBlock extends HorizontalBlock
}
@Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) {
Direction side = te.getBlockState().get(BeltBlock.HORIZONTAL_FACING).rotateY();
return Arrays.asList(te.getPos().offset(side), te.getPos().offset(side.getOpposite()));
public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
Direction side = beltState.get(BeltBlock.HORIZONTAL_FACING).rotateY();
return Arrays.asList(pos.offset(side), pos.offset(side.getOpposite()));
}
@Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) {
if (!state.get(BELT))
return Optional.empty();
return Optional.of(pos.offset(state.get(HORIZONTAL_FACING)));
public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
return pos.offset(state.get(HORIZONTAL_FACING));
}
@Override
public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos, BlockState attachmentState,
BlockState beltState) {
return attachmentState.get(BELT);
}
@Override
@ -178,11 +182,39 @@ public class EntityDetectorBlock extends HorizontalBlock
}
@Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
state.processingDuration = 0;
withTileEntityDo(te.getWorld(), state.attachmentPos, detectorTE -> {
ItemStack filter = detectorTE.getFilter();
if (filter.isEmpty())
return;
// Todo: Package filters
if (!ItemStack.areItemsEqual(transported.stack, filter)) {
state.processingDuration = -1;
return;
}
});
World world = te.getWorld();
BlockState blockState = world.getBlockState(state.attachmentPos);
if (state.processingDuration == 0) {
world.setBlockState(state.attachmentPos, blockState.with(POWERED, true));
world.getPendingBlockTicks().scheduleTick(state.attachmentPos, this, 6);
world.notifyNeighborsOfStateChange(state.attachmentPos, this);
return true;
}
return false;
}
@Override
public boolean processEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
if (te.getWorld().isRemote)
return false;
if (state.processingEntity != entity) {
state.processingEntity = entity;
state.processingDuration = 0;
@ -190,6 +222,8 @@ public class EntityDetectorBlock extends HorizontalBlock
ItemStack filter = detectorTE.getFilter();
if (filter.isEmpty())
return;
// Todo: Package filters
if (!(entity instanceof ItemEntity)
|| !ItemStack.areItemsEqual(((ItemEntity) entity).getItem(), filter)) {
state.processingDuration = -1;

View file

@ -3,7 +3,9 @@ package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import com.simibubi.create.modules.logistics.block.IExtractor;
@ -91,11 +93,17 @@ public class ExtractorBlock extends HorizontalBlock implements IBlockWithFilter
@Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
BlockPos neighbourPos = pos.offset(state.get(HORIZONTAL_FACING));
Direction facing = state.get(HORIZONTAL_FACING);
BlockPos neighbourPos = pos.offset(facing);
BlockState neighbour = worldIn.getBlockState(neighbourPos);
if (AllBlocks.BELT.typeOf(neighbour)) {
return BeltBlock.canAccessFromSide(facing, neighbour);
}
return !neighbour.getShape(worldIn, pos).isEmpty();
}
@Override
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) {
if (world.isRemote())
@ -121,7 +129,7 @@ public class ExtractorBlock extends HorizontalBlock implements IBlockWithFilter
boolean isMoving) {
if (worldIn.isRemote)
return;
Direction blockFacing = state.get(HORIZONTAL_FACING);
if (fromPos.equals(pos.offset(blockFacing))) {
if (!isValidPosition(state, worldIn, pos)) {

View file

@ -1,75 +1,175 @@
{
"forgemarker": 1,
"defaults": {
"model": "create:block/belt/horizontal_middle"
},
"variants": {
"slope=horizontal,part=start,facing=north": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 180 },
"slope=horizontal,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 0 },
"slope=horizontal,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 270 },
"slope=horizontal,part=start,facing=west": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 90 },
"casing=false,slope=horizontal,part=start,facing=north": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 180 },
"casing=false,slope=horizontal,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 0 },
"casing=false,slope=horizontal,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 270 },
"casing=false,slope=horizontal,part=start,facing=west": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 90 },
"slope=horizontal,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 180 },
"slope=horizontal,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 0 },
"slope=horizontal,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 270 },
"slope=horizontal,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 90 },
"casing=false,slope=horizontal,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 180 },
"casing=false,slope=horizontal,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 0 },
"casing=false,slope=horizontal,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 270 },
"casing=false,slope=horizontal,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 90 },
"slope=horizontal,part=end,facing=north": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 180 },
"slope=horizontal,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 0 },
"slope=horizontal,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 270 },
"slope=horizontal,part=end,facing=west": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 90 },
"casing=false,slope=horizontal,part=end,facing=north": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 180 },
"casing=false,slope=horizontal,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 0 },
"casing=false,slope=horizontal,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 270 },
"casing=false,slope=horizontal,part=end,facing=west": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 90 },
"casing=false,slope=horizontal,part=pulley,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 180 },
"casing=false,slope=horizontal,part=pulley,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 0 },
"casing=false,slope=horizontal,part=pulley,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 270 },
"casing=false,slope=horizontal,part=pulley,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 90 },
"casing=false,slope=vertical,part=end,facing=north": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=end,facing=west": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 90 },
"slope=vertical,part=end,facing=north": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 180 },
"slope=vertical,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 0 },
"slope=vertical,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 270 },
"slope=vertical,part=end,facing=west": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 90 },
"slope=vertical,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"slope=vertical,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"slope=vertical,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"slope=vertical,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"slope=vertical,part=start,facing=north": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 180 },
"slope=vertical,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 0 },
"slope=vertical,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 270 },
"slope=vertical,part=start,facing=west": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 90 },
"casing=false,slope=vertical,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"casing=false,slope=vertical,part=start,facing=north": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=start,facing=west": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 90 },
"casing=false,slope=vertical,part=pulley,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=pulley,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=pulley,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=pulley,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"slope=upward,part=start,facing=north": { "model": "create:block/belt/downward_end", "x": 0, "y": 180 },
"slope=upward,part=start,facing=south": { "model": "create:block/belt/downward_end", "x": 0, "y": 0 },
"slope=upward,part=start,facing=east": { "model": "create:block/belt/downward_end", "x": 0, "y": 270 },
"slope=upward,part=start,facing=west": { "model": "create:block/belt/downward_end", "x": 0, "y": 90 },
"casing=false,slope=upward,part=start,facing=north": { "model": "create:block/belt/downward_end", "x": 0, "y": 180 },
"casing=false,slope=upward,part=start,facing=south": { "model": "create:block/belt/downward_end", "x": 0, "y": 0 },
"casing=false,slope=upward,part=start,facing=east": { "model": "create:block/belt/downward_end", "x": 0, "y": 270 },
"casing=false,slope=upward,part=start,facing=west": { "model": "create:block/belt/downward_end", "x": 0, "y": 90 },
"slope=upward,part=middle,facing=north": { "model": "create:block/belt/downward_middle", "x": 0, "y": 180 },
"slope=upward,part=middle,facing=south": { "model": "create:block/belt/downward_middle", "x": 0, "y": 0 },
"slope=upward,part=middle,facing=east": { "model": "create:block/belt/downward_middle", "x": 0, "y": 270 },
"slope=upward,part=middle,facing=west": { "model": "create:block/belt/downward_middle", "x": 0, "y": 90 },
"slope=upward,part=end,facing=north": { "model": "create:block/belt/downward_start", "x": 0, "y": 180 },
"slope=upward,part=end,facing=south": { "model": "create:block/belt/downward_start", "x": 0, "y": 0 },
"slope=upward,part=end,facing=east": { "model": "create:block/belt/downward_start", "x": 0, "y": 270 },
"slope=upward,part=end,facing=west": { "model": "create:block/belt/downward_start", "x": 0, "y": 90 },
"casing=false,slope=upward,part=middle,facing=north": { "model": "create:block/belt/downward_middle", "x": 0, "y": 180 },
"casing=false,slope=upward,part=middle,facing=south": { "model": "create:block/belt/downward_middle", "x": 0, "y": 0 },
"casing=false,slope=upward,part=middle,facing=east": { "model": "create:block/belt/downward_middle", "x": 0, "y": 270 },
"casing=false,slope=upward,part=middle,facing=west": { "model": "create:block/belt/downward_middle", "x": 0, "y": 90 },
"casing=false,slope=upward,part=end,facing=north": { "model": "create:block/belt/downward_start", "x": 0, "y": 180 },
"casing=false,slope=upward,part=end,facing=south": { "model": "create:block/belt/downward_start", "x": 0, "y": 0 },
"casing=false,slope=upward,part=end,facing=east": { "model": "create:block/belt/downward_start", "x": 0, "y": 270 },
"casing=false,slope=upward,part=end,facing=west": { "model": "create:block/belt/downward_start", "x": 0, "y": 90 },
"casing=false,slope=upward,part=pulley,facing=north": { "model": "create:block/belt/downward_middle", "x": 0, "y": 180 },
"casing=false,slope=upward,part=pulley,facing=south": { "model": "create:block/belt/downward_middle", "x": 0, "y": 0 },
"casing=false,slope=upward,part=pulley,facing=east": { "model": "create:block/belt/downward_middle", "x": 0, "y": 270 },
"casing=false,slope=upward,part=pulley,facing=west": { "model": "create:block/belt/downward_middle", "x": 0, "y": 90 },
"slope=downward,part=start,facing=north": { "model": "create:block/belt/upward_end", "x": 0, "y": 180 },
"slope=downward,part=start,facing=south": { "model": "create:block/belt/upward_end", "x": 0, "y": 0 },
"slope=downward,part=start,facing=east": { "model": "create:block/belt/upward_end", "x": 0, "y": 270 },
"slope=downward,part=start,facing=west": { "model": "create:block/belt/upward_end", "x": 0, "y": 90 },
"casing=false,slope=downward,part=start,facing=north": { "model": "create:block/belt/upward_end", "x": 0, "y": 180 },
"casing=false,slope=downward,part=start,facing=south": { "model": "create:block/belt/upward_end", "x": 0, "y": 0 },
"casing=false,slope=downward,part=start,facing=east": { "model": "create:block/belt/upward_end", "x": 0, "y": 270 },
"casing=false,slope=downward,part=start,facing=west": { "model": "create:block/belt/upward_end", "x": 0, "y": 90 },
"slope=downward,part=middle,facing=north": { "model": "create:block/belt/upward_middle", "x": 0, "y": 180 },
"slope=downward,part=middle,facing=south": { "model": "create:block/belt/upward_middle", "x": 0, "y": 0 },
"slope=downward,part=middle,facing=east": { "model": "create:block/belt/upward_middle", "x": 0, "y": 270 },
"slope=downward,part=middle,facing=west": { "model": "create:block/belt/upward_middle", "x": 0, "y": 90 },
"casing=false,slope=downward,part=middle,facing=north": { "model": "create:block/belt/upward_middle", "x": 0, "y": 180 },
"casing=false,slope=downward,part=middle,facing=south": { "model": "create:block/belt/upward_middle", "x": 0, "y": 0 },
"casing=false,slope=downward,part=middle,facing=east": { "model": "create:block/belt/upward_middle", "x": 0, "y": 270 },
"casing=false,slope=downward,part=middle,facing=west": { "model": "create:block/belt/upward_middle", "x": 0, "y": 90 },
"slope=downward,part=end,facing=north": { "model": "create:block/belt/upward_start", "x": 0, "y": 180 },
"slope=downward,part=end,facing=south": { "model": "create:block/belt/upward_start", "x": 0, "y": 0 },
"slope=downward,part=end,facing=east": { "model": "create:block/belt/upward_start", "x": 0, "y": 270 },
"slope=downward,part=end,facing=west": { "model": "create:block/belt/upward_start", "x": 0, "y": 90 }
"casing=false,slope=downward,part=end,facing=north": { "model": "create:block/belt/upward_start", "x": 0, "y": 180 },
"casing=false,slope=downward,part=end,facing=south": { "model": "create:block/belt/upward_start", "x": 0, "y": 0 },
"casing=false,slope=downward,part=end,facing=east": { "model": "create:block/belt/upward_start", "x": 0, "y": 270 },
"casing=false,slope=downward,part=end,facing=west": { "model": "create:block/belt/upward_start", "x": 0, "y": 90 },
"casing=false,slope=downward,part=pulley,facing=north": { "model": "create:block/belt/upward_middle", "x": 0, "y": 180 },
"casing=false,slope=downward,part=pulley,facing=south": { "model": "create:block/belt/upward_middle", "x": 0, "y": 0 },
"casing=false,slope=downward,part=pulley,facing=east": { "model": "create:block/belt/upward_middle", "x": 0, "y": 270 },
"casing=false,slope=downward,part=pulley,facing=west": { "model": "create:block/belt/upward_middle", "x": 0, "y": 90 },
"casing=true,slope=horizontal,part=start,facing=north": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 180 },
"casing=true,slope=horizontal,part=start,facing=south": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 0 },
"casing=true,slope=horizontal,part=start,facing=east": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 270 },
"casing=true,slope=horizontal,part=start,facing=west": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 90 },
"casing=true,slope=horizontal,part=middle,facing=north": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 180 },
"casing=true,slope=horizontal,part=middle,facing=south": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 0 },
"casing=true,slope=horizontal,part=middle,facing=east": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 270 },
"casing=true,slope=horizontal,part=middle,facing=west": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 90 },
"casing=true,slope=horizontal,part=end,facing=north": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 180 },
"casing=true,slope=horizontal,part=end,facing=south": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 0 },
"casing=true,slope=horizontal,part=end,facing=east": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 270 },
"casing=true,slope=horizontal,part=end,facing=west": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 90 },
"casing=true,slope=horizontal,part=pulley,facing=north": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 180 },
"casing=true,slope=horizontal,part=pulley,facing=south": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 0 },
"casing=true,slope=horizontal,part=pulley,facing=east": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 270 },
"casing=true,slope=horizontal,part=pulley,facing=west": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 90 },
"casing=true,slope=upward,part=start,facing=north": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 0 },
"casing=true,slope=upward,part=start,facing=south": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 180 },
"casing=true,slope=upward,part=start,facing=east": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 90 },
"casing=true,slope=upward,part=start,facing=west": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 270 },
"casing=true,slope=upward,part=middle,facing=north": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 0 },
"casing=true,slope=upward,part=middle,facing=south": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 180 },
"casing=true,slope=upward,part=middle,facing=east": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 90 },
"casing=true,slope=upward,part=middle,facing=west": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 270 },
"casing=true,slope=upward,part=end,facing=north": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 180 },
"casing=true,slope=upward,part=end,facing=south": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 0 },
"casing=true,slope=upward,part=end,facing=east": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 270 },
"casing=true,slope=upward,part=end,facing=west": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 90 },
"casing=true,slope=upward,part=pulley,facing=north": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 0 },
"casing=true,slope=upward,part=pulley,facing=south": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 180 },
"casing=true,slope=upward,part=pulley,facing=east": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 90 },
"casing=true,slope=upward,part=pulley,facing=west": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 270 },
"casing=true,slope=vertical,part=end,facing=north": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=end,facing=west": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 90 },
"casing=true,slope=vertical,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"casing=true,slope=vertical,part=start,facing=north": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=start,facing=west": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 90 },
"casing=true,slope=vertical,part=pulley,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=pulley,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=pulley,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=pulley,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"casing=true,slope=downward,part=start,facing=north": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 0 },
"casing=true,slope=downward,part=start,facing=south": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 180 },
"casing=true,slope=downward,part=start,facing=east": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 90 },
"casing=true,slope=downward,part=start,facing=west": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 270 },
"casing=true,slope=downward,part=middle,facing=north": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 180 },
"casing=true,slope=downward,part=middle,facing=south": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 0 },
"casing=true,slope=downward,part=middle,facing=east": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 270 },
"casing=true,slope=downward,part=middle,facing=west": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 90 },
"casing=true,slope=downward,part=end,facing=north": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 180 },
"casing=true,slope=downward,part=end,facing=south": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 0 },
"casing=true,slope=downward,part=end,facing=east": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 270 },
"casing=true,slope=downward,part=end,facing=west": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 90 },
"casing=true,slope=downward,part=pulley,facing=north": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 180 },
"casing=true,slope=downward,part=pulley,facing=south": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 0 },
"casing=true,slope=downward,part=pulley,facing=east": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 270 },
"casing=true,slope=downward,part=pulley,facing=west": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 90 }
}
}

View file

@ -0,0 +1,98 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 5, 2],
"to": [14.9, 11, 14],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 14, 11], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [2, 5, 14, 11], "texture": "#8"}
}
},
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 10, 5],
"faces": {
"north": {"uv": [0, 0, 10, 16], "rotation": 90, "texture": "#2"},
"east": {"uv": [11, 1, 16, 11], "texture": "#2"},
"south": {"uv": [0, 1, 16, 11], "texture": "#2"},
"west": {"uv": [0, 1, 5, 11], "texture": "#2"},
"up": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Zfighter2",
"from": [0.5, 0.1, 15.1],
"to": [15.5, 11.1, 16.1],
"faces": {
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"south": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Right",
"from": [0, 0, 11],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 2, 11], "texture": "#2"},
"east": {"uv": [0, 0, 4, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#2"},
"west": {"uv": [12, 0, 16, 11], "texture": "#2"},
"up": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.325],
"to": [16.1, 11, 4.7],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,74 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 10, 5],
"faces": {
"north": {"uv": [0, 0, 10, 16], "rotation": 90, "texture": "#2"},
"east": {"uv": [11, 1, 16, 11], "texture": "#2"},
"south": {"uv": [0, 1, 16, 11], "texture": "#2"},
"west": {"uv": [0, 1, 5, 11], "texture": "#2"},
"up": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.325],
"to": [16.1, 11, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 13.325, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, 10],
"to": [16.1, 11, 19.3],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 9.3, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 9.3, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,87 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 5, 2],
"to": [14.9, 11, 14],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 14, 11], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [2, 5, 14, 11], "texture": "#8"}
}
},
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 10, 5],
"faces": {
"north": {"uv": [0, 0, 10, 16], "rotation": 90, "texture": "#2"},
"east": {"uv": [11, 1, 16, 11], "texture": "#2"},
"south": {"uv": [0, 1, 16, 11], "texture": "#2"},
"west": {"uv": [0, 1, 5, 11], "texture": "#2"},
"up": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.325],
"to": [16.1, 11, 4.7],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, 11.275],
"to": [16.1, 11, 19.3],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,86 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 4, 4],
"to": [14.9, 11, 14],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 12, 12], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [4, 5, 14, 12], "texture": "#8"}
}
},
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Zfighter2",
"from": [0.5, 0.1, 15.1],
"to": [15.5, 11.1, 16.1],
"faces": {
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"south": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Right",
"from": [0, 0, 11],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 2, 11], "texture": "#2"},
"east": {"uv": [0, 0, 4, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#2"},
"west": {"uv": [12, 0, 16, 11], "texture": "#2"},
"up": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 5], "texture": "#missing"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.328],
"to": [16.1, 11, 4.697],
"rotation": {"angle": -45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,24 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side"
},
"elements": [
{
"name": "Casing",
"from": [0, 0, 0],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 16, 11], "texture": "#1"},
"east": {"uv": [0, 0, 16, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#1"},
"west": {"uv": [0, 0, 16, 11], "texture": "#2"},
"up": {"uv": [0, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,84 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1, 5, 2],
"to": [15, 11, 14],
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 14, 11], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [2, 5, 14, 11], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 11, 4],
"faces": {
"north": {"uv": [0, 0, 16, 11], "texture": "#2"},
"east": {"uv": [12, 0, 16, 11], "texture": "#2"},
"south": {"uv": [14, 0, 16, 11], "texture": "#2"},
"west": {"uv": [0, 0, 4, 11], "texture": "#2"},
"up": {"uv": [0, 0, 4, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 4, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Zfighter",
"from": [0.5, 0.1, -0.1],
"to": [15.5, 10.9, 0.9],
"faces": {
"north": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Zfighter2",
"from": [0.5, 0.1, 15.1],
"to": [15.5, 10.9, 16.1],
"faces": {
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"south": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Right",
"from": [0, 0, 12],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 2, 11], "texture": "#2"},
"east": {"uv": [0, 0, 4, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#2"},
"west": {"uv": [12, 0, 16, 11], "texture": "#2"},
"up": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 4],
"to": [16, 4, 12],
"faces": {
"east": {"uv": [4, 7, 12, 11], "texture": "#2"},
"west": {"uv": [4, 7, 12, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 10], "texture": "#2"},
"down": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#2"}
}
}
]
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "create:belt_support"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View file

@ -1,8 +1,6 @@
{
"replace": false,
"values": [
"create:belt",
"create:crushing_wheel",
"create:limestone_wall",
"create:limestone_bricks_wall",
"create:weathered_limestone_wall",