diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index e8c7118e8..b5069679b 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -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()), diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 168771242..81c136b9b 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -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()); diff --git a/src/main/java/com/simibubi/create/ClientEvents.java b/src/main/java/com/simibubi/create/ClientEvents.java index d33ca1cff..f1ccba3d9 100644 --- a/src/main/java/com/simibubi/create/ClientEvents.java +++ b/src/main/java/com/simibubi/create/ClientEvents.java @@ -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 diff --git a/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java b/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java index 2fe20f40d..9f9eb3b8e 100644 --- a/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/block/SyncedTileEntity.java @@ -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); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/BufferManipulator.java b/src/main/java/com/simibubi/create/foundation/utility/BufferManipulator.java index db17c9363..f96eba0dc 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BufferManipulator.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BufferManipulator.java @@ -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(); diff --git a/src/main/java/com/simibubi/create/foundation/utility/IndependentShadowRenderer.java b/src/main/java/com/simibubi/create/foundation/utility/IndependentShadowRenderer.java new file mode 100644 index 000000000..e4584a584 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/IndependentShadowRenderer.java @@ -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(); + } + } + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java b/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java index 81f529ac2..472666268 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/TessellatorHelper.java @@ -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(); + } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/VoxelShaper.java b/src/main/java/com/simibubi/create/foundation/utility/VoxelShaper.java index 9df7baa4a..41419b239 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VoxelShaper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VoxelShaper.java @@ -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 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(); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/VoxelShapers.java b/src/main/java/com/simibubi/create/foundation/utility/VoxelShapers.java index aeac7583e..db6b7972f 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VoxelShapers.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VoxelShapers.java @@ -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)); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java b/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java index 6a900e39e..694b4d6a9 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/CachedBufferReloader.java @@ -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 { MechanicalBearingTileEntityRenderer.invalidateCache(); ColoredIndicatorRenderer.invalidateCache(); CTModelTextureHandler.reloadUVs(); + BeltModelAnimator.invalidateCache(); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java b/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java index d3a5b4c6d..1606125c7 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java @@ -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); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java index f678ae385..8013d74c0 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java @@ -34,7 +34,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber(value = Dist.CLIENT) public class KineticTileEntityRenderer extends TileEntityRendererFast { - protected static Map cachedBuffers; + public static Map cachedBuffers; public static boolean rainbowMode = false; public static class BlockModelSpinner extends BufferManipulator { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBeltHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBeltHandler.java new file mode 100644 index 000000000..ab4e01f04 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanBeltHandler.java @@ -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 findBelts(EncasedFanTileEntity fan) { + if (fan.getSpeed() == 0) + return Collections.emptyList(); + List 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 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); + }); + } + + } +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java index cf04c912d..f40e14b24 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanParticleHandler.java @@ -26,7 +26,7 @@ public class EncasedFanParticleHandler { private void initEffects() { List 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); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java index 806902bce..cb684146e 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/EncasedFanTileEntity.java @@ -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 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 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) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java index 21d42444e..e825466bd 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java @@ -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)); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java index ed3529f17..9f9dcebcb 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressBlock.java @@ -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 getPotentialAttachmentLocations(BeltTileEntity te) { - return Arrays.asList(te.getPos().up(2)); + public List 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 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 recipe = pressTe.getRecipe(transportedStack.stack); + if (!recipe.isPresent()) + return false; + ItemStack out = recipe.get().getRecipeOutput().copy(); + List 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; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java index 876247563..348878c48 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/MechanicalPressTileEntity.java @@ -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 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 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 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 getRecipe(ItemStack item) { + pressingInv.setInventorySlotContents(0, item); Optional recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.PRESSING, pressingInv, world); return recipe; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/ProcessingInventory.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/ProcessingInventory.java index 4906d93c4..63bb24193 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/ProcessingInventory.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/ProcessingInventory.java @@ -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(); + } + } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntity.java index 623a254f9..631c28311 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntity.java @@ -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 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 LazyOptional getCapability(Capability 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> 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(); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntityRenderer.java index 5a2a075d1..ad1bc7d2b 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/SawTileEntityRenderer.java @@ -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 { 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 { 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 { // Filter filterRenderer.render(te, x, y, z, partialTicks, destroyStage); - + // Kinetic renders final BlockState state = getRenderedBlockState(te); KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java index 80e7e331e..2373205ff 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java @@ -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 getPotentialAttachmentLocations(BeltTileEntity te); - public Optional getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state); + public List 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 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 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 attachmentPositions = ba.attachment.getPotentialAttachmentLocations(belt); World world = belt.getWorld(); + BlockPos beltPos = belt.getPos(); + BlockState beltState = belt.getBlockState(); + List 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 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); } } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java index 799ab5847..f08081956 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltBlock.java @@ -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 { public static final IProperty SLOPE = EnumProperty.create("slope", Slope.class); public static final IProperty 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 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 getBeltChain(World world, BlockPos controllerPos) { List 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; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltItem.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItem.java similarity index 89% rename from src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltItem.java rename to src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItem.java index 6760981ea..cdef9d8e0 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltItem.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItem.java @@ -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 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) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltItemHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItemHandler.java similarity index 96% rename from src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltItemHandler.java rename to src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItemHandler.java index 39721de7e..b7210dd91 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltItemHandler.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltConnectorItemHandler.java @@ -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); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java new file mode 100644 index 000000000..c0c09313e --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltInventory.java @@ -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 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 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 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> callback) { + List toBeAdded = new ArrayList<>(); + boolean dirty = false; + for (Iterator iterator = items.iterator(); iterator.hasNext();) { + TransportedItemStack transportedItemStack = iterator.next(); + if (Math.abs(position - transportedItemStack.beltPosition) < distance) { + List 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(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltModelAnimator.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltModelAnimator.java new file mode 100644 index 000000000..530ddb1ca --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltModelAnimator.java @@ -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; + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltMovementHandler.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltMovementHandler.java new file mode 100644 index 000000000..435dce9f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltMovementHandler.java @@ -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; + } + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltShapes.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltShapes.java new file mode 100644 index 000000000..4b7e5b0a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltShapes.java @@ -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; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java index af0e97f2c..ee8052b49 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java @@ -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 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 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 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 LazyOptional getCapability(Capability 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 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; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java index 669af7319..1b92bebc3 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntityRenderer.java @@ -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 { - 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)); } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/ItemHandlerBeltSegment.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/ItemHandlerBeltSegment.java new file mode 100644 index 000000000..a4f1e2f62 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/ItemHandlerBeltSegment.java @@ -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; + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/TransportedItemStack.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/TransportedItemStack.java new file mode 100644 index 000000000..491c859ad --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/TransportedItemStack.java @@ -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 { + 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; + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java index 8369c85e7..57a9e61de 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/partialWindows/WindowInABlockTileEntity.java @@ -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(); } diff --git a/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java b/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java index 47d1400c6..c35402825 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java +++ b/src/main/java/com/simibubi/create/modules/logistics/InWorldProcessing.java @@ -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 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 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 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 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 stacks = process(transported.stack, type, belt.getWorld()); + List transportedStacks = new ArrayList<>(); + for (ItemStack additional : stacks) { + TransportedItemStack newTransported = transported.getSimilar(); + newTransported.stack = additional.copy(); + transportedStacks.add(newTransported); + } + return transportedStacks; + } + + private static List process(ItemStack stack, Type type, World world) { if (type == Type.SPLASHING) { - splashingInv.setInventorySlotContents(0, entity.getItem()); + splashingInv.setInventorySlotContents(0, stack); Optional 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 = 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 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 = 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 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 applyRecipeOn(ItemStack stackIn, IRecipe recipe) { List 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 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() { diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java index e0dd32aae..29b5d40a2 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java @@ -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); } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java index 6f3add356..4919c99f6 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelBlock.java @@ -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 { +public class BeltFunnelBlock extends HorizontalBlock + implements IBeltAttachment, IWithTileEntity, 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 getPotentialAttachmentLocations(BeltTileEntity te) { - return Arrays.asList(te.getPos().up()); + public List getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) { + return Arrays.asList(pos.up()); } @Override - public Optional 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 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(); + } + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java index dfbf5e4e6..53a5f4b9b 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntity.java @@ -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 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(); } } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntityRenderer.java new file mode 100644 index 000000000..3dac7ee86 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/BeltFunnelTileEntityRenderer.java @@ -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 { + + 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); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java index 601e206b6..c34911991 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/EntityDetectorBlock.java @@ -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 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 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 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; diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorBlock.java index ebcc1db38..b666ef189 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/belts/ExtractorBlock.java @@ -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)) { diff --git a/src/main/resources/assets/create/blockstates/belt.json b/src/main/resources/assets/create/blockstates/belt.json index 77cac73ca..2a47694c3 100644 --- a/src/main/resources/assets/create/blockstates/belt.json +++ b/src/main/resources/assets/create/blockstates/belt.json @@ -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 } } } diff --git a/src/main/resources/assets/create/models/block/belt/diagonal_casing_bottom.json b/src/main/resources/assets/create/models/block/belt/diagonal_casing_bottom.json new file mode 100644 index 000000000..252ffe61c --- /dev/null +++ b/src/main/resources/assets/create/models/block/belt/diagonal_casing_bottom.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/belt/diagonal_casing_middle.json b/src/main/resources/assets/create/models/block/belt/diagonal_casing_middle.json new file mode 100644 index 000000000..4f16acd03 --- /dev/null +++ b/src/main/resources/assets/create/models/block/belt/diagonal_casing_middle.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/belt/diagonal_casing_middle_pulley.json b/src/main/resources/assets/create/models/block/belt/diagonal_casing_middle_pulley.json new file mode 100644 index 000000000..86ce620c3 --- /dev/null +++ b/src/main/resources/assets/create/models/block/belt/diagonal_casing_middle_pulley.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/belt/diagonal_casing_top.json b/src/main/resources/assets/create/models/block/belt/diagonal_casing_top.json new file mode 100644 index 000000000..563fa1f8e --- /dev/null +++ b/src/main/resources/assets/create/models/block/belt/diagonal_casing_top.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/belt/horizontal_casing.json b/src/main/resources/assets/create/models/block/belt/horizontal_casing.json new file mode 100644 index 000000000..f6dd1ac0d --- /dev/null +++ b/src/main/resources/assets/create/models/block/belt/horizontal_casing.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/belt/horizontal_casing_pulley.json b/src/main/resources/assets/create/models/block/belt/horizontal_casing_pulley.json new file mode 100644 index 000000000..cfe4b73cd --- /dev/null +++ b/src/main/resources/assets/create/models/block/belt/horizontal_casing_pulley.json @@ -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"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/belt_funnel.json b/src/main/resources/assets/create/models/block/belt_funnel.json index 8ba5f3c81..e60aba5c4 100644 --- a/src/main/resources/assets/create/models/block/belt_funnel.json +++ b/src/main/resources/assets/create/models/block/belt_funnel.json @@ -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] + } + } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/extractor.json b/src/main/resources/assets/create/models/block/extractor.json index bf006e499..6ef918d7b 100644 --- a/src/main/resources/assets/create/models/block/extractor.json +++ b/src/main/resources/assets/create/models/block/extractor.json @@ -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] + } + } } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/extractor_wireless.json b/src/main/resources/assets/create/models/block/extractor_wireless.json index 0e7a78d33..df565ee16 100644 --- a/src/main/resources/assets/create/models/block/extractor_wireless.json +++ b/src/main/resources/assets/create/models/block/extractor_wireless.json @@ -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"} + } + } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/extractor.json b/src/main/resources/assets/create/models/item/extractor.json index 0a39d9155..948131ef6 100644 --- a/src/main/resources/assets/create/models/item/extractor.json +++ b/src/main/resources/assets/create/models/item/extractor.json @@ -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" } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/linked_extractor.json b/src/main/resources/assets/create/models/item/linked_extractor.json index 7ad05603f..195ee3078 100644 --- a/src/main/resources/assets/create/models/item/linked_extractor.json +++ b/src/main/resources/assets/create/models/item/linked_extractor.json @@ -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" } \ No newline at end of file diff --git a/src/main/resources/data/create/loot_tables/blocks/belt_support.json b/src/main/resources/data/create/loot_tables/blocks/belt_support.json new file mode 100644 index 000000000..6ff088bdd --- /dev/null +++ b/src/main/resources/data/create/loot_tables/blocks/belt_support.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "create:belt_support" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/walls.json b/src/main/resources/data/minecraft/tags/blocks/walls.json index 87e29446a..c9d6babae 100644 --- a/src/main/resources/data/minecraft/tags/blocks/walls.json +++ b/src/main/resources/data/minecraft/tags/blocks/walls.json @@ -1,8 +1,6 @@ { "replace": false, "values": [ - "create:belt", - "create:crushing_wheel", "create:limestone_wall", "create:limestone_bricks_wall", "create:weathered_limestone_wall",