mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-23 11:28:10 +01:00
Cart Assembler and Agile Contraptions
- Started generalizing contraptions for other means of transportation - Added mounted contraptions for minecarts
This commit is contained in:
parent
ee75468719
commit
a391d74810
39 changed files with 1417 additions and 462 deletions
|
@ -24,6 +24,8 @@ import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalP
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.PistonPoleBlock;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.PistonPoleBlock;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.RotationChassisBlock;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.RotationChassisBlock;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.TranslationChassisBlock;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.TranslationChassisBlock;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.mounted.CartAssemblerBlock;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.mounted.CartAssemblerBlock.MinecartAnchorBlock;
|
||||||
import com.simibubi.create.modules.contraptions.redstone.ContactBlock;
|
import com.simibubi.create.modules.contraptions.redstone.ContactBlock;
|
||||||
import com.simibubi.create.modules.contraptions.relays.ClutchBlock;
|
import com.simibubi.create.modules.contraptions.relays.ClutchBlock;
|
||||||
import com.simibubi.create.modules.contraptions.relays.CogWheelBlock;
|
import com.simibubi.create.modules.contraptions.relays.CogWheelBlock;
|
||||||
|
@ -125,6 +127,8 @@ public enum AllBlocks {
|
||||||
SAW(new SawBlock()),
|
SAW(new SawBlock()),
|
||||||
HARVESTER(new HarvesterBlock()),
|
HARVESTER(new HarvesterBlock()),
|
||||||
HARVESTER_BLADE(new HarvesterBladeBlock()),
|
HARVESTER_BLADE(new HarvesterBladeBlock()),
|
||||||
|
CART_ASSEMBLER(new CartAssemblerBlock()),
|
||||||
|
MINECART_ANCHOR(new MinecartAnchorBlock()),
|
||||||
|
|
||||||
__LOGISTICS__(),
|
__LOGISTICS__(),
|
||||||
CONTACT(new ContactBlock()),
|
CONTACT(new ContactBlock()),
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.mounted.ContraptionEntity;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.mounted.ContraptionEntityRenderer;
|
||||||
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
|
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
|
||||||
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntityRenderer;
|
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntityRenderer;
|
||||||
|
|
||||||
|
@ -19,6 +21,7 @@ import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
||||||
public enum AllEntities {
|
public enum AllEntities {
|
||||||
|
|
||||||
CARDBOARD_BOX(CardboardBoxEntity::new, 30, 3, CardboardBoxEntity::build),
|
CARDBOARD_BOX(CardboardBoxEntity::new, 30, 3, CardboardBoxEntity::build),
|
||||||
|
CONTRAPTION(ContraptionEntity::new, 30, 3, ContraptionEntity::build),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -56,6 +59,7 @@ public enum AllEntities {
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
public static void registerRenderers() {
|
public static void registerRenderers() {
|
||||||
RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::new);
|
RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::new);
|
||||||
|
RenderingRegistry.registerEntityRenderingHandler(ContraptionEntity.class, ContraptionEntityRenderer::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,8 @@ public enum AllItems {
|
||||||
PROPELLER(ingredient()),
|
PROPELLER(ingredient()),
|
||||||
CRUSHED_IRON(ingredient()),
|
CRUSHED_IRON(ingredient()),
|
||||||
CRUSHED_GOLD(ingredient()),
|
CRUSHED_GOLD(ingredient()),
|
||||||
|
TIME_SCARF(ingredient()),
|
||||||
|
MOTION_SCARF(ingredient()),
|
||||||
|
|
||||||
__LOGISTICS__(),
|
__LOGISTICS__(),
|
||||||
CARDBOARD_BOX_1616(new CardboardBoxItem(standardItemProperties())),
|
CARDBOARD_BOX_1616(new CardboardBoxItem(standardItemProperties())),
|
||||||
|
|
|
@ -5,10 +5,11 @@ import java.nio.ByteBuffer;
|
||||||
import net.minecraft.client.renderer.GLAllocation;
|
import net.minecraft.client.renderer.GLAllocation;
|
||||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
public abstract class BufferManipulator {
|
public abstract class BufferManipulator {
|
||||||
|
|
||||||
protected static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize();
|
public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize();
|
||||||
protected ByteBuffer original;
|
protected ByteBuffer original;
|
||||||
protected ByteBuffer mutable;
|
protected ByteBuffer mutable;
|
||||||
|
|
||||||
|
@ -23,66 +24,66 @@ public abstract class BufferManipulator {
|
||||||
mutable.rewind();
|
mutable.rewind();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int vertexCount(ByteBuffer buffer) {
|
protected static int vertexCount(ByteBuffer buffer) {
|
||||||
return buffer.limit() / FORMAT_LENGTH;
|
return buffer.limit() / FORMAT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getBufferPosition(int vertexIndex) {
|
protected static int getBufferPosition(int vertexIndex) {
|
||||||
return vertexIndex * FORMAT_LENGTH;
|
return vertexIndex * FORMAT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getX(ByteBuffer buffer, int index) {
|
protected static float getX(ByteBuffer buffer, int index) {
|
||||||
return buffer.getFloat(getBufferPosition(index));
|
return buffer.getFloat(getBufferPosition(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getY(ByteBuffer buffer, int index) {
|
protected static float getY(ByteBuffer buffer, int index) {
|
||||||
return buffer.getFloat(getBufferPosition(index) + 4);
|
return buffer.getFloat(getBufferPosition(index) + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getZ(ByteBuffer buffer, int index) {
|
protected static float getZ(ByteBuffer buffer, int index) {
|
||||||
return buffer.getFloat(getBufferPosition(index) + 8);
|
return buffer.getFloat(getBufferPosition(index) + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte getR(ByteBuffer buffer, int index) {
|
protected static byte getR(ByteBuffer buffer, int index) {
|
||||||
return buffer.get(getBufferPosition(index) + 12);
|
return buffer.get(getBufferPosition(index) + 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte getG(ByteBuffer buffer, int index) {
|
protected static byte getG(ByteBuffer buffer, int index) {
|
||||||
return buffer.get(getBufferPosition(index) + 13);
|
return buffer.get(getBufferPosition(index) + 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte getB(ByteBuffer buffer, int index) {
|
protected static byte getB(ByteBuffer buffer, int index) {
|
||||||
return buffer.get(getBufferPosition(index) + 14);
|
return buffer.get(getBufferPosition(index) + 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte getA(ByteBuffer buffer, int index) {
|
protected static byte getA(ByteBuffer buffer, int index) {
|
||||||
return buffer.get(getBufferPosition(index) + 15);
|
return buffer.get(getBufferPosition(index) + 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void putPos(ByteBuffer buffer, int index, float x, float y, float z) {
|
protected static void putPos(ByteBuffer buffer, int index, float x, float y, float z) {
|
||||||
int pos = getBufferPosition(index);
|
int pos = getBufferPosition(index);
|
||||||
buffer.putFloat(pos, x);
|
buffer.putFloat(pos, x);
|
||||||
buffer.putFloat(pos + 4, y);
|
buffer.putFloat(pos + 4, y);
|
||||||
buffer.putFloat(pos + 8, z);
|
buffer.putFloat(pos + 8, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float rotateX(float x, float y, float z, float sin, float cos, Axis axis) {
|
protected static float rotateX(float x, float y, float z, float sin, float cos, Axis axis) {
|
||||||
return axis == Axis.Y ? x * cos + z * sin : axis == Axis.Z ? x * cos - y * sin : x;
|
return axis == Axis.Y ? x * cos + z * sin : axis == Axis.Z ? x * cos - y * sin : x;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float rotateY(float x, float y, float z, float sin, float cos, Axis axis) {
|
protected static float rotateY(float x, float y, float z, float sin, float cos, Axis axis) {
|
||||||
return axis == Axis.Y ? y : axis == Axis.Z ? y * cos + x * sin : y * cos - z * sin;
|
return axis == Axis.Y ? y : axis == Axis.Z ? y * cos + x * sin : y * cos - z * sin;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float rotateZ(float x, float y, float z, float sin, float cos, Axis axis) {
|
protected static float rotateZ(float x, float y, float z, float sin, float cos, Axis axis) {
|
||||||
return axis == Axis.Y ? z * cos - x * sin : axis == Axis.Z ? z : z * cos + y * sin;
|
return axis == Axis.Y ? z * cos - x * sin : axis == Axis.Z ? z : z * cos + y * sin;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void putLight(ByteBuffer buffer, int index, int packedLight) {
|
protected static void putLight(ByteBuffer buffer, int index, int packedLight) {
|
||||||
buffer.putInt(getBufferPosition(index) + 24, packedLight);
|
buffer.putInt(getBufferPosition(index) + 24, packedLight);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void putColor(ByteBuffer buffer, int index, byte r, byte g, byte b, byte a) {
|
protected static void putColor(ByteBuffer buffer, int index, byte r, byte g, byte b, byte a) {
|
||||||
int bufferPosition = getBufferPosition(index);
|
int bufferPosition = getBufferPosition(index);
|
||||||
buffer.put(bufferPosition + 12, r);
|
buffer.put(bufferPosition + 12, r);
|
||||||
buffer.put(bufferPosition + 13, g);
|
buffer.put(bufferPosition + 13, g);
|
||||||
|
@ -90,4 +91,35 @@ public abstract class BufferManipulator {
|
||||||
buffer.put(bufferPosition + 15, a);
|
buffer.put(bufferPosition + 15, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ByteBuffer remanipulateBuffer(ByteBuffer buffer, float x, float y, float z, float xOrigin,
|
||||||
|
float yOrigin, float zOrigin, float yaw, float pitch) {
|
||||||
|
buffer.rewind();
|
||||||
|
|
||||||
|
float cosYaw = MathHelper.cos(yaw);
|
||||||
|
float sinYaw = MathHelper.sin(yaw);
|
||||||
|
float cosPitch = MathHelper.cos(pitch);
|
||||||
|
float sinPitch = MathHelper.sin(pitch);
|
||||||
|
|
||||||
|
for (int vertex = 0; vertex < vertexCount(buffer); vertex++) {
|
||||||
|
float xL = getX(buffer, vertex) - xOrigin;
|
||||||
|
float yL = getY(buffer, vertex) - yOrigin;
|
||||||
|
float zL = getZ(buffer, vertex) - zOrigin;
|
||||||
|
|
||||||
|
float xL2 = rotateX(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
float yL2 = rotateY(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
float zL2 = rotateZ(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
|
||||||
|
xL = rotateX(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
yL = rotateY(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
zL = rotateZ(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
|
||||||
|
float xPos = xL + x + xOrigin;
|
||||||
|
float yPos = yL + y + yOrigin;
|
||||||
|
float zPos = zL + z + zOrigin;
|
||||||
|
putPos(buffer, vertex, xPos, yPos, zPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
import net.minecraft.client.renderer.Tessellator;
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -29,6 +30,22 @@ public class TessellatorHelper {
|
||||||
Vec3d view = renderInfo.getProjectedView();
|
Vec3d view = renderInfo.getProjectedView();
|
||||||
GlStateManager.translated(-view.x, -view.y, -view.z);
|
GlStateManager.translated(-view.x, -view.y, -view.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void prepareFastRender() {
|
||||||
|
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();
|
||||||
|
GlStateManager.disableCull();
|
||||||
|
|
||||||
|
if (net.minecraft.client.Minecraft.isAmbientOcclusionEnabled())
|
||||||
|
GlStateManager.shadeModel(GL11.GL_SMOOTH);
|
||||||
|
else
|
||||||
|
GlStateManager.shadeModel(GL11.GL_FLAT);
|
||||||
|
|
||||||
|
GlStateManager.color3f(1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
public static void begin() {
|
public static void begin() {
|
||||||
begin(DefaultVertexFormats.POSITION_TEX);
|
begin(DefaultVertexFormats.POSITION_TEX);
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create.foundation.utility;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.DoubleNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
@ -36,4 +38,16 @@ public class VecHelper {
|
||||||
vec.z + (r.nextFloat() - .5f) * 2 * radius);
|
vec.z + (r.nextFloat() - .5f) * 2 * radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ListNBT writeNBT(Vec3d vec) {
|
||||||
|
ListNBT listnbt = new ListNBT();
|
||||||
|
listnbt.add(new DoubleNBT(vec.x));
|
||||||
|
listnbt.add(new DoubleNBT(vec.y));
|
||||||
|
listnbt.add(new DoubleNBT(vec.z));
|
||||||
|
return listnbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vec3d readNBT(ListNBT list) {
|
||||||
|
return new Vec3d(list.getDouble(0), list.getDouble(1), list.getDouble(2));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ package com.simibubi.create.modules.contraptions;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
|
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonTileEntityRenderer;
|
|
||||||
|
|
||||||
import net.minecraft.client.resources.ReloadListener;
|
import net.minecraft.client.resources.ReloadListener;
|
||||||
import net.minecraft.profiler.IProfiler;
|
import net.minecraft.profiler.IProfiler;
|
||||||
|
@ -19,7 +19,7 @@ public class CachedBufferReloader extends ReloadListener<String> {
|
||||||
@Override
|
@Override
|
||||||
protected void apply(String splashList, IResourceManager resourceManagerIn, IProfiler profilerIn) {
|
protected void apply(String splashList, IResourceManager resourceManagerIn, IProfiler profilerIn) {
|
||||||
KineticTileEntityRenderer.invalidateCache();
|
KineticTileEntityRenderer.invalidateCache();
|
||||||
MechanicalPistonTileEntityRenderer.invalidateCache();
|
ContraptionRenderer.invalidateCache();
|
||||||
MechanicalBearingTileEntityRenderer.invalidateCache();
|
MechanicalBearingTileEntityRenderer.invalidateCache();
|
||||||
ColoredIndicatorRenderer.invalidateCache();
|
ColoredIndicatorRenderer.invalidateCache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simibubi.create.modules.contraptions.receivers;
|
package com.simibubi.create.modules.contraptions.receivers;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.block.IRenderUtilityBlock;
|
import com.simibubi.create.foundation.block.IRenderUtilityBlock;
|
||||||
|
@ -13,7 +14,6 @@ import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.DirectionalBlock;
|
import net.minecraft.block.DirectionalBlock;
|
||||||
import net.minecraft.block.material.PushReaction;
|
import net.minecraft.block.material.PushReaction;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.state.StateContainer.Builder;
|
import net.minecraft.state.StateContainer.Builder;
|
||||||
|
@ -80,17 +80,17 @@ public class DrillBlock extends DirectionalKineticBlock
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
public void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
public ByteBuffer renderInConstruct(MovementContext context) {
|
||||||
DrillTileEntityRenderer.renderInConstruct(context, x, y, z, buffer);
|
return DrillTileEntityRenderer.renderInConstruct(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitPosition(MovementContext context) {
|
public void visitPosition(MovementContext context) {
|
||||||
Direction movement = context.getMovementDirection();
|
Direction movement = context.getMovementDirection();
|
||||||
BlockState block = context.state;
|
|
||||||
|
// BlockState block = context.state;
|
||||||
if (movement != block.get(FACING))
|
// if (movement == block.get(FACING).getOpposite())
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
World world = context.world;
|
World world = context.world;
|
||||||
BlockPos pos = context.currentGridPos;
|
BlockPos pos = context.currentGridPos;
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create.modules.contraptions.receivers;
|
||||||
|
|
||||||
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
|
@ -10,7 +12,6 @@ import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMoveme
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -27,7 +28,7 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer {
|
||||||
return AllBlocks.DRILL_HEAD.get().getDefaultState().with(FACING, state.get(FACING));
|
return AllBlocks.DRILL_HEAD.get().getDefaultState().with(FACING, state.get(FACING));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
public static ByteBuffer renderInConstruct(MovementContext context) {
|
||||||
World world = context.world;
|
World world = context.world;
|
||||||
BlockState state = context.state;
|
BlockState state = context.state;
|
||||||
BlockPos pos = context.currentGridPos;
|
BlockPos pos = context.currentGridPos;
|
||||||
|
@ -35,12 +36,13 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer {
|
||||||
final BlockState renderedState = getRenderedBlockState(state);
|
final BlockState renderedState = getRenderedBlockState(state);
|
||||||
cacheIfMissing(renderedState, world, BlockModelSpinner::new);
|
cacheIfMissing(renderedState, world, BlockModelSpinner::new);
|
||||||
|
|
||||||
float speed = context.getMovementDirection() == state.get(FACING)? 100 : 0;
|
float speed = (float) (context.getMovementDirection() == state.get(FACING) ? context.getAnimationSpeed() : 0);
|
||||||
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
|
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
|
||||||
float time = Animation.getWorldTime(Minecraft.getInstance().world,
|
float time = Animation.getWorldTime(Minecraft.getInstance().world,
|
||||||
Minecraft.getInstance().getRenderPartialTicks());
|
Minecraft.getInstance().getRenderPartialTicks());
|
||||||
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
||||||
renderFromCache(buffer, renderedState, world, (float) x, (float) y, (float) z, pos, axis, angle);
|
return ((BlockModelSpinner) getBuffer(renderedState)).getTransformed(0, 0, 0, angle, axis,
|
||||||
|
world.getCombinedLight(pos, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simibubi.create.modules.contraptions.receivers;
|
package com.simibubi.create.modules.contraptions.receivers;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
@ -14,7 +15,6 @@ import net.minecraft.block.CropsBlock;
|
||||||
import net.minecraft.block.HorizontalBlock;
|
import net.minecraft.block.HorizontalBlock;
|
||||||
import net.minecraft.block.SugarCaneBlock;
|
import net.minecraft.block.SugarCaneBlock;
|
||||||
import net.minecraft.block.material.PushReaction;
|
import net.minecraft.block.material.PushReaction;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.item.BlockItemUseContext;
|
import net.minecraft.item.BlockItemUseContext;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -74,8 +74,8 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
public void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
public ByteBuffer renderInConstruct(MovementContext context) {
|
||||||
HarvesterTileEntityRenderer.renderInConstruct(context, x, y, z, buffer);
|
return HarvesterTileEntityRenderer.renderInConstruct(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -58,40 +58,42 @@ public class HarvesterTileEntityRenderer extends TileEntityRenderer<HarvesterTil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
public static ByteBuffer renderInConstruct(MovementContext context) {
|
||||||
World world = context.world;
|
World world = context.world;
|
||||||
BlockState state = context.state;
|
BlockState state = context.state;
|
||||||
BlockPos pos = context.currentGridPos;
|
BlockPos pos = context.currentGridPos;
|
||||||
Direction facing = context.getMovementDirection();
|
Direction facing = context.getMovementDirection();
|
||||||
|
|
||||||
float speed = facing == state.get(HORIZONTAL_FACING) ? 100 * facing.getAxisDirection().getOffset() : 0;
|
float speed = (float) (facing == state.get(HORIZONTAL_FACING)
|
||||||
|
? context.getAnimationSpeed() * facing.getAxisDirection().getOffset()
|
||||||
|
: 0);
|
||||||
if (facing.getAxis() == Axis.X)
|
if (facing.getAxis() == Axis.X)
|
||||||
speed = -speed;
|
speed = -speed;
|
||||||
|
|
||||||
float time = Animation.getWorldTime(Minecraft.getInstance().world,
|
float time = Animation.getWorldTime(Minecraft.getInstance().world,
|
||||||
Minecraft.getInstance().getRenderPartialTicks());
|
Minecraft.getInstance().getRenderPartialTicks());
|
||||||
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
||||||
render(world, state, pos, x, y, z, angle, buffer);
|
return getVertexData(world, state, pos, 0, 0, 0, angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderTileEntityFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks,
|
public void renderTileEntityFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks,
|
||||||
int destroyStage, BufferBuilder buffer) {
|
int destroyStage, BufferBuilder buffer) {
|
||||||
render(te.getWorld(), te.getBlockState(), te.getPos(), x, y, z, 0, buffer);
|
buffer.putBulkData(getVertexData(te.getWorld(), te.getBlockState(), te.getPos(), x, y, z, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void render(World world, BlockState state, BlockPos pos, double x, double y, double z, float angle,
|
public static ByteBuffer getVertexData(World world, BlockState state, BlockPos pos, double x, double y, double z,
|
||||||
BufferBuilder buffer) {
|
float angle) {
|
||||||
if (!AllBlocks.HARVESTER.typeOf(state))
|
if (!AllBlocks.HARVESTER.typeOf(state))
|
||||||
return;
|
return ByteBuffer.wrap(new byte[] {});
|
||||||
|
|
||||||
BlockState renderedState = AllBlocks.HARVESTER_BLADE.get().getDefaultState().with(HORIZONTAL_FACING,
|
BlockState renderedState = AllBlocks.HARVESTER_BLADE.get().getDefaultState().with(HORIZONTAL_FACING,
|
||||||
state.get(HORIZONTAL_FACING));
|
state.get(HORIZONTAL_FACING));
|
||||||
|
|
||||||
KineticTileEntityRenderer.cacheIfMissing(renderedState, world, HarvesterRenderer::new);
|
KineticTileEntityRenderer.cacheIfMissing(renderedState, world, HarvesterRenderer::new);
|
||||||
HarvesterRenderer renderer = (HarvesterRenderer) KineticTileEntityRenderer.getBuffer(renderedState);
|
HarvesterRenderer renderer = (HarvesterRenderer) KineticTileEntityRenderer.getBuffer(renderedState);
|
||||||
buffer.putBulkData(renderer.getTransformed((float) x, (float) y, (float) z, angle, state.get(HORIZONTAL_FACING),
|
ByteBuffer byteBuffer = renderer.getTransformed((float) x, (float) y, (float) z, angle,
|
||||||
state.getPackedLightmapCoords(world, pos)));
|
state.get(HORIZONTAL_FACING), state.getPackedLightmapCoords(world, pos));
|
||||||
|
return byteBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
||||||
|
|
||||||
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
|
|
||||||
import static com.simibubi.create.AllBlocks.PISTON_POLE;
|
|
||||||
import static com.simibubi.create.AllBlocks.STICKY_MECHANICAL_PISTON;
|
|
||||||
import static com.simibubi.create.CreateConfig.parameters;
|
import static com.simibubi.create.CreateConfig.parameters;
|
||||||
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
|
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
|
||||||
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||||
|
@ -14,6 +11,7 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.MutablePair;
|
import org.apache.commons.lang3.tuple.MutablePair;
|
||||||
|
@ -22,7 +20,6 @@ import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.CreateConfig;
|
import com.simibubi.create.CreateConfig;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.SawBlock;
|
import com.simibubi.create.modules.contraptions.receivers.SawBlock;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
|
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.FallingBlock;
|
import net.minecraft.block.FallingBlock;
|
||||||
|
@ -34,47 +31,66 @@ import net.minecraft.nbt.FloatNBT;
|
||||||
import net.minecraft.nbt.ListNBT;
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.state.properties.PistonType;
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
|
||||||
public class TranslationConstruct {
|
public class Contraption {
|
||||||
|
|
||||||
protected Map<BlockPos, BlockInfo> blocks;
|
protected Map<BlockPos, BlockInfo> blocks;
|
||||||
protected List<MutablePair<BlockInfo, MovementContext>> actors;
|
protected List<MutablePair<BlockInfo, MovementContext>> actors;
|
||||||
|
|
||||||
protected AxisAlignedBB constructCollisionBox;
|
protected AxisAlignedBB constructCollisionBox;
|
||||||
protected AxisAlignedBB pistonCollisionBox;
|
|
||||||
|
|
||||||
protected Set<BlockPos> cachedColliders;
|
protected Set<BlockPos> cachedColliders;
|
||||||
protected Direction cachedColliderDirection;
|
protected Direction cachedColliderDirection;
|
||||||
|
protected BlockPos anchor;
|
||||||
|
|
||||||
protected int extensionLength;
|
public Contraption() {
|
||||||
protected int initialExtensionProgress;
|
|
||||||
protected Direction orientation;
|
|
||||||
|
|
||||||
public TranslationConstruct() {
|
|
||||||
blocks = new HashMap<>();
|
blocks = new HashMap<>();
|
||||||
actors = new ArrayList<>();
|
actors = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TranslationConstruct movePistonAt(World world, BlockPos pos, Direction direction, boolean retract) {
|
private static List<BlockInfo> getChassisClusterAt(World world, BlockPos pos) {
|
||||||
if (isFrozen())
|
List<BlockPos> search = new LinkedList<>();
|
||||||
return null;
|
Set<BlockPos> visited = new HashSet<>();
|
||||||
TranslationConstruct construct = new TranslationConstruct();
|
List<BlockInfo> chassis = new LinkedList<>();
|
||||||
construct.orientation = direction;
|
BlockState anchorChassis = world.getBlockState(pos);
|
||||||
if (!construct.collectExtensions(world, pos, direction))
|
Axis axis = anchorChassis.get(AXIS);
|
||||||
return null;
|
search.add(pos);
|
||||||
if (!construct.searchMovedStructure(world, pos.offset(direction, construct.initialExtensionProgress + 1),
|
|
||||||
retract ? direction.getOpposite() : direction))
|
while (!search.isEmpty()) {
|
||||||
return null;
|
if (chassis.size() > parameters.maxChassisForTranslation.get())
|
||||||
return construct;
|
return null;
|
||||||
|
|
||||||
|
BlockPos current = search.remove(0);
|
||||||
|
if (visited.contains(current))
|
||||||
|
continue;
|
||||||
|
if (!world.isAreaLoaded(current, 1))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
BlockState state = world.getBlockState(current);
|
||||||
|
if (!isChassis(state))
|
||||||
|
continue;
|
||||||
|
if (!TranslationChassisBlock.sameKind(anchorChassis, state))
|
||||||
|
continue;
|
||||||
|
if (state.get(AXIS) != axis)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
visited.add(current);
|
||||||
|
chassis.add(new BlockInfo(current, world.getBlockState(current), getTileEntityNBT(world, current)));
|
||||||
|
|
||||||
|
for (Direction offset : Direction.values()) {
|
||||||
|
if (offset.getAxis() == axis)
|
||||||
|
continue;
|
||||||
|
search.add(current.offset(offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chassis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<BlockPos> getColliders(World world, Direction movementDirection) {
|
public Set<BlockPos> getColliders(World world, Direction movementDirection) {
|
||||||
|
@ -101,86 +117,17 @@ public class TranslationConstruct {
|
||||||
return cachedColliders;
|
return cachedColliders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean collectExtensions(World world, BlockPos pos, Direction direction) {
|
protected boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
|
||||||
List<BlockInfo> poles = new ArrayList<>();
|
|
||||||
BlockPos actualStart = pos;
|
|
||||||
BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
|
|
||||||
int extensionsInFront = 0;
|
|
||||||
boolean sticky = STICKY_MECHANICAL_PISTON.typeOf(world.getBlockState(pos));
|
|
||||||
|
|
||||||
if (world.getBlockState(pos).get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
|
|
||||||
while (PISTON_POLE.typeOf(nextBlock) && nextBlock.get(FACING).getAxis() == direction.getAxis()
|
|
||||||
|| MECHANICAL_PISTON_HEAD.typeOf(nextBlock) && nextBlock.get(FACING) == direction) {
|
|
||||||
|
|
||||||
actualStart = actualStart.offset(direction);
|
|
||||||
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
|
|
||||||
extensionsInFront++;
|
|
||||||
nextBlock = world.getBlockState(actualStart.offset(direction));
|
|
||||||
|
|
||||||
if (extensionsInFront > parameters.maxPistonPoles.get())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extensionsInFront == 0)
|
|
||||||
poles.add(
|
|
||||||
new BlockInfo(pos,
|
|
||||||
MECHANICAL_PISTON_HEAD.get().getDefaultState().with(FACING, direction).with(
|
|
||||||
BlockStateProperties.PISTON_TYPE, sticky ? PistonType.STICKY : PistonType.DEFAULT),
|
|
||||||
null));
|
|
||||||
else
|
|
||||||
poles.add(new BlockInfo(pos, PISTON_POLE.get().getDefaultState().with(FACING, direction), null));
|
|
||||||
|
|
||||||
BlockPos end = pos;
|
|
||||||
nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
|
|
||||||
int extensionsInBack = 0;
|
|
||||||
|
|
||||||
while (PISTON_POLE.typeOf(nextBlock)) {
|
|
||||||
end = end.offset(direction.getOpposite());
|
|
||||||
poles.add(new BlockInfo(end, nextBlock.with(FACING, direction), null));
|
|
||||||
extensionsInBack++;
|
|
||||||
nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
|
|
||||||
|
|
||||||
if (extensionsInFront + extensionsInBack > parameters.maxPistonPoles.get())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
extensionLength = extensionsInBack + extensionsInFront;
|
|
||||||
initialExtensionProgress = extensionsInFront;
|
|
||||||
pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront));
|
|
||||||
|
|
||||||
for (BlockInfo pole : poles) {
|
|
||||||
BlockPos polePos = pole.pos.offset(direction, -extensionsInFront);
|
|
||||||
blocks.put(polePos, new BlockInfo(polePos, pole.state, null));
|
|
||||||
pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
|
|
||||||
List<BlockPos> frontier = new ArrayList<>();
|
List<BlockPos> frontier = new ArrayList<>();
|
||||||
Set<BlockPos> visited = new HashSet<>();
|
Set<BlockPos> visited = new HashSet<>();
|
||||||
constructCollisionBox = new AxisAlignedBB(pos.offset(direction, initialExtensionProgress));
|
anchor = pos;
|
||||||
frontier.add(pos);
|
|
||||||
|
|
||||||
for (int offset = 1; offset <= parameters.maxChassisRange.get(); offset++) {
|
if (constructCollisionBox == null)
|
||||||
BlockPos currentPos = pos.offset(direction, offset);
|
constructCollisionBox = new AxisAlignedBB(pos);
|
||||||
if (!world.isAreaLoaded(currentPos, 1))
|
|
||||||
return false;
|
frontier.add(pos);
|
||||||
if (!world.isBlockPresent(currentPos))
|
if (!addToInitialFrontier(world, pos, direction, frontier))
|
||||||
break;
|
return false;
|
||||||
BlockState state = world.getBlockState(currentPos);
|
|
||||||
if (state.getMaterial().isReplaceable())
|
|
||||||
break;
|
|
||||||
if (state.getCollisionShape(world, currentPos).isEmpty())
|
|
||||||
break;
|
|
||||||
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite())
|
|
||||||
break;
|
|
||||||
if (!canPush(world, currentPos, direction))
|
|
||||||
return false;
|
|
||||||
frontier.add(currentPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int limit = 1000; limit > 0; limit--) {
|
for (int limit = 1000; limit > 0; limit--) {
|
||||||
if (frontier.isEmpty())
|
if (frontier.isEmpty())
|
||||||
|
@ -192,6 +139,10 @@ public class TranslationConstruct {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean moveBlock(World world, BlockPos pos, Direction direction, List<BlockPos> frontier,
|
private boolean moveBlock(World world, BlockPos pos, Direction direction, List<BlockPos> frontier,
|
||||||
Set<BlockPos> visited) {
|
Set<BlockPos> visited) {
|
||||||
visited.add(pos);
|
visited.add(pos);
|
||||||
|
@ -349,42 +300,8 @@ public class TranslationConstruct {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<BlockInfo> getChassisClusterAt(World world, BlockPos pos) {
|
private static boolean isChassis(BlockState state) {
|
||||||
List<BlockPos> search = new LinkedList<>();
|
return TranslationChassisBlock.isChassis(state);
|
||||||
Set<BlockPos> visited = new HashSet<>();
|
|
||||||
List<BlockInfo> chassis = new LinkedList<>();
|
|
||||||
BlockState anchorChassis = world.getBlockState(pos);
|
|
||||||
Axis axis = anchorChassis.get(AXIS);
|
|
||||||
search.add(pos);
|
|
||||||
|
|
||||||
while (!search.isEmpty()) {
|
|
||||||
if (chassis.size() > parameters.maxChassisForTranslation.get())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
BlockPos current = search.remove(0);
|
|
||||||
if (visited.contains(current))
|
|
||||||
continue;
|
|
||||||
if (!world.isAreaLoaded(current, 1))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
BlockState state = world.getBlockState(current);
|
|
||||||
if (!isChassis(state))
|
|
||||||
continue;
|
|
||||||
if (!TranslationChassisBlock.sameKind(anchorChassis, state))
|
|
||||||
continue;
|
|
||||||
if (state.get(AXIS) != axis)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
visited.add(current);
|
|
||||||
chassis.add(capture(world, current));
|
|
||||||
|
|
||||||
for (Direction offset : Direction.values()) {
|
|
||||||
if (offset.getAxis() == axis)
|
|
||||||
continue;
|
|
||||||
search.add(current.offset(offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chassis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean notSupportive(World world, BlockPos pos, Direction facing) {
|
private boolean notSupportive(World world, BlockPos pos, Direction facing) {
|
||||||
|
@ -396,11 +313,7 @@ public class TranslationConstruct {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isChassis(BlockState state) {
|
protected static boolean canPush(World world, BlockPos pos, Direction direction) {
|
||||||
return TranslationChassisBlock.isChassis(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean canPush(World world, BlockPos pos, Direction direction) {
|
|
||||||
BlockState blockState = world.getBlockState(pos);
|
BlockState blockState = world.getBlockState(pos);
|
||||||
if (isChassis(blockState))
|
if (isChassis(blockState))
|
||||||
return true;
|
return true;
|
||||||
|
@ -409,19 +322,15 @@ public class TranslationConstruct {
|
||||||
return PistonBlock.canPush(blockState, world, pos, direction, true, direction);
|
return PistonBlock.canPush(blockState, world, pos, direction, true, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void add(BlockPos pos, BlockInfo block) {
|
protected BlockInfo capture(World world, BlockPos pos) {
|
||||||
BlockPos localPos = pos.offset(orientation, -initialExtensionProgress);
|
|
||||||
BlockInfo blockInfo = new BlockInfo(localPos, block.state, block.nbt);
|
|
||||||
blocks.put(localPos, blockInfo);
|
|
||||||
if (block.state.getBlock() instanceof IHaveMovementBehavior)
|
|
||||||
actors.add(MutablePair.of(blockInfo, null));
|
|
||||||
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(localPos));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BlockInfo capture(World world, BlockPos pos) {
|
|
||||||
BlockState blockstate = world.getBlockState(pos);
|
BlockState blockstate = world.getBlockState(pos);
|
||||||
if (AllBlocks.SAW.typeOf(blockstate))
|
if (AllBlocks.SAW.typeOf(blockstate))
|
||||||
blockstate = blockstate.with(SawBlock.RUNNING, true);
|
blockstate = blockstate.with(SawBlock.RUNNING, true);
|
||||||
|
CompoundNBT compoundnbt = getTileEntityNBT(world, pos);
|
||||||
|
return new BlockInfo(pos, blockstate, compoundnbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompoundNBT getTileEntityNBT(World world, BlockPos pos) {
|
||||||
TileEntity tileentity = world.getTileEntity(pos);
|
TileEntity tileentity = world.getTileEntity(pos);
|
||||||
CompoundNBT compoundnbt = null;
|
CompoundNBT compoundnbt = null;
|
||||||
if (tileentity != null) {
|
if (tileentity != null) {
|
||||||
|
@ -430,17 +339,43 @@ public class TranslationConstruct {
|
||||||
compoundnbt.remove("y");
|
compoundnbt.remove("y");
|
||||||
compoundnbt.remove("z");
|
compoundnbt.remove("z");
|
||||||
}
|
}
|
||||||
return new BlockInfo(pos, blockstate, compoundnbt);
|
return compoundnbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(BlockPos pos, BlockInfo block) {
|
||||||
|
BlockInfo blockInfo = new BlockInfo(pos, block.state, block.nbt);
|
||||||
|
blocks.put(pos, blockInfo);
|
||||||
|
if (block.state.getBlock() instanceof IHaveMovementBehavior)
|
||||||
|
getActors().add(MutablePair.of(blockInfo, null));
|
||||||
|
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readNBT(CompoundNBT nbt) {
|
||||||
|
nbt.getList("Blocks", 10).forEach(c -> {
|
||||||
|
CompoundNBT comp = (CompoundNBT) c;
|
||||||
|
BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")),
|
||||||
|
NBTUtil.readBlockState(comp.getCompound("Block")),
|
||||||
|
comp.contains("Data") ? comp.getCompound("Data") : null);
|
||||||
|
blocks.put(info.pos, info);
|
||||||
|
});
|
||||||
|
|
||||||
|
nbt.getList("Actors", 10).forEach(c -> {
|
||||||
|
CompoundNBT comp = (CompoundNBT) c;
|
||||||
|
BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos")));
|
||||||
|
MovementContext context = MovementContext.readNBT(comp);
|
||||||
|
getActors().add(MutablePair.of(info, context));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (nbt.contains("BoundsFront"))
|
||||||
|
constructCollisionBox = readAABB(nbt.getList("BoundsFront", 5));
|
||||||
|
|
||||||
|
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AxisAlignedBB getCollisionBoxFront() {
|
public AxisAlignedBB getCollisionBoxFront() {
|
||||||
return constructCollisionBox;
|
return constructCollisionBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AxisAlignedBB getCollisionBoxBack() {
|
|
||||||
return pistonCollisionBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompoundNBT writeNBT() {
|
public CompoundNBT writeNBT() {
|
||||||
CompoundNBT nbt = new CompoundNBT();
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
ListNBT blocks = new ListNBT();
|
ListNBT blocks = new ListNBT();
|
||||||
|
@ -452,19 +387,22 @@ public class TranslationConstruct {
|
||||||
c.put("Data", block.nbt);
|
c.put("Data", block.nbt);
|
||||||
blocks.add(c);
|
blocks.add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListNBT actorsNBT = new ListNBT();
|
||||||
|
for (MutablePair<BlockInfo, MovementContext> actor : getActors()) {
|
||||||
|
CompoundNBT compound = new CompoundNBT();
|
||||||
|
compound.put("Pos", NBTUtil.writeBlockPos(actor.left.pos));
|
||||||
|
actor.right.writeToNBT(compound);
|
||||||
|
actorsNBT.add(compound);
|
||||||
|
}
|
||||||
|
nbt.put("Actors", actorsNBT);
|
||||||
|
|
||||||
if (constructCollisionBox != null) {
|
if (constructCollisionBox != null) {
|
||||||
ListNBT bb = writeAABB(constructCollisionBox);
|
ListNBT bb = writeAABB(constructCollisionBox);
|
||||||
nbt.put("BoundsFront", bb);
|
nbt.put("BoundsFront", bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pistonCollisionBox != null) {
|
|
||||||
ListNBT bb = writeAABB(pistonCollisionBox);
|
|
||||||
nbt.put("BoundsBack", bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
nbt.put("Blocks", blocks);
|
nbt.put("Blocks", blocks);
|
||||||
nbt.putInt("ExtensionLength", extensionLength);
|
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,32 +425,38 @@ public class TranslationConstruct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TranslationConstruct fromNBT(CompoundNBT nbt) {
|
|
||||||
TranslationConstruct construct = new TranslationConstruct();
|
|
||||||
nbt.getList("Blocks", 10).forEach(c -> {
|
|
||||||
CompoundNBT comp = (CompoundNBT) c;
|
|
||||||
BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")),
|
|
||||||
NBTUtil.readBlockState(comp.getCompound("Block")),
|
|
||||||
comp.contains("Data") ? comp.getCompound("Data") : null);
|
|
||||||
construct.blocks.put(info.pos, info);
|
|
||||||
});
|
|
||||||
construct.extensionLength = nbt.getInt("ExtensionLength");
|
|
||||||
|
|
||||||
if (nbt.contains("BoundsFront"))
|
|
||||||
construct.constructCollisionBox = construct.readAABB(nbt.getList("BoundsFront", 5));
|
|
||||||
if (nbt.contains("BoundsBack"))
|
|
||||||
construct.pistonCollisionBox = construct.readAABB(nbt.getList("BoundsBack", 5));
|
|
||||||
|
|
||||||
// Find blocks with special movement behaviour
|
|
||||||
construct.blocks.values().forEach(block -> {
|
|
||||||
if (block.state.getBlock() instanceof IHaveMovementBehavior)
|
|
||||||
construct.actors.add(MutablePair.of(block, null));
|
|
||||||
});
|
|
||||||
|
|
||||||
return construct;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isFrozen() {
|
public static boolean isFrozen() {
|
||||||
return CreateConfig.parameters.freezePistonConstructs.get();
|
return CreateConfig.parameters.freezePistonConstructs.get();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void disassemble(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customPlacement) {
|
||||||
|
for (BlockInfo block : blocks.values()) {
|
||||||
|
BlockPos targetPos = block.pos.add(offset);
|
||||||
|
BlockState state = block.state;
|
||||||
|
|
||||||
|
if (customPlacement.test(targetPos, state))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (Direction face : Direction.values())
|
||||||
|
state = state.updatePostPlacement(face, world.getBlockState(targetPos.offset(face)), world, targetPos,
|
||||||
|
targetPos.offset(face));
|
||||||
|
if (AllBlocks.SAW.typeOf(state))
|
||||||
|
state = state.with(SawBlock.RUNNING, false);
|
||||||
|
|
||||||
|
world.destroyBlock(targetPos, world.getBlockState(targetPos).getCollisionShape(world, targetPos).isEmpty());
|
||||||
|
world.setBlockState(targetPos, state, 3);
|
||||||
|
TileEntity tileEntity = world.getTileEntity(targetPos);
|
||||||
|
if (tileEntity != null && block.nbt != null) {
|
||||||
|
block.nbt.putInt("x", targetPos.getX());
|
||||||
|
block.nbt.putInt("y", targetPos.getY());
|
||||||
|
block.nbt.putInt("z", targetPos.getZ());
|
||||||
|
tileEntity.read(block.nbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MutablePair<BlockInfo, MovementContext>> getActors() {
|
||||||
|
return actors;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.simibubi.create.foundation.utility.BufferManipulator;
|
||||||
|
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||||
|
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
|
||||||
|
public class ContraptionRenderer {
|
||||||
|
|
||||||
|
protected static Cache<Contraption, ContraptionVertexBuffer> cachedConstructs;
|
||||||
|
protected static PlacementSimulationWorld renderWorld;
|
||||||
|
|
||||||
|
public static <T extends BufferManipulator> void cacheContraptionIfMissing(Contraption c) {
|
||||||
|
if (cachedConstructs == null)
|
||||||
|
cachedConstructs = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.SECONDS).build();
|
||||||
|
if (cachedConstructs.getIfPresent(c) != null)
|
||||||
|
return;
|
||||||
|
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
|
||||||
|
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
|
||||||
|
|
||||||
|
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
|
||||||
|
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
|
||||||
|
Random random = new Random();
|
||||||
|
BufferBuilder builder = new BufferBuilder(0);
|
||||||
|
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
||||||
|
builder.setTranslation(0, 0, 0);
|
||||||
|
|
||||||
|
for (BlockInfo info : c.blocks.values()) {
|
||||||
|
renderWorld.setBlockState(info.pos, info.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BlockInfo info : c.blocks.values()) {
|
||||||
|
IBakedModel originalModel = dispatcher.getModelForState(info.state);
|
||||||
|
blockRenderer.renderModel(renderWorld, originalModel, info.state, info.pos, builder, true, random, 42,
|
||||||
|
EmptyModelData.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.finishDrawing();
|
||||||
|
renderWorld.clear();
|
||||||
|
cachedConstructs.put(c, new ContraptionVertexBuffer(builder.getByteBuffer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ContraptionVertexBuffer get(Contraption c) {
|
||||||
|
return cachedConstructs.getIfPresent(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void renderActors(World world, Contraption c, float xIn, float yIn, float zIn, float yaw, float pitch,
|
||||||
|
BufferBuilder buffer) {
|
||||||
|
for (Pair<BlockInfo, MovementContext> actor : c.getActors()) {
|
||||||
|
MovementContext context = actor.getRight();
|
||||||
|
if (context == null)
|
||||||
|
continue;
|
||||||
|
if (context.world == null)
|
||||||
|
context.world = world;
|
||||||
|
|
||||||
|
BlockInfo blockInfo = actor.getLeft();
|
||||||
|
IHaveMovementBehavior block = (IHaveMovementBehavior) blockInfo.state.getBlock();
|
||||||
|
ByteBuffer renderInConstruct = block.renderInConstruct(context);
|
||||||
|
if (renderInConstruct == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int posX = blockInfo.pos.getX();
|
||||||
|
int posY = blockInfo.pos.getY();
|
||||||
|
int posZ = blockInfo.pos.getZ();
|
||||||
|
|
||||||
|
float x = xIn + posX;
|
||||||
|
float y = yIn + posY;
|
||||||
|
float z = zIn + posZ;
|
||||||
|
|
||||||
|
float xOrigin = -posX + c.anchor.getX() + .5f;
|
||||||
|
float yOrigin = -posY + c.anchor.getY() + .5f;
|
||||||
|
float zOrigin = -posZ + c.anchor.getZ() + .5f;
|
||||||
|
|
||||||
|
buffer.putBulkData(BufferManipulator.remanipulateBuffer(renderInConstruct, x, y, z, xOrigin, yOrigin,
|
||||||
|
zOrigin, yaw, pitch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void invalidateCache() {
|
||||||
|
if (cachedConstructs != null)
|
||||||
|
cachedConstructs.invalidateAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.BufferManipulator;
|
||||||
|
|
||||||
|
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.world.World;
|
||||||
|
|
||||||
|
public class ContraptionVertexBuffer extends BufferManipulator {
|
||||||
|
|
||||||
|
public ContraptionVertexBuffer(ByteBuffer original) {
|
||||||
|
super(original);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getTranslated(World world, float x, float y, float z, Vec3d offset) {
|
||||||
|
original.rewind();
|
||||||
|
mutable.rewind();
|
||||||
|
|
||||||
|
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
|
||||||
|
float xL = getX(original, vertex);
|
||||||
|
float yL = getY(original, vertex);
|
||||||
|
float zL = getZ(original, vertex);
|
||||||
|
putPos(mutable, vertex, xL + x + (float) offset.x, yL + y + (float) offset.y, zL + z + (float) offset.z);
|
||||||
|
BlockPos pos = new BlockPos(offset.x + xL, offset.y + yL, offset.z + zL);
|
||||||
|
putLight(mutable, vertex, world.getCombinedLight(pos, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getTranslatedAndRotated(World world, float x, float y, float z, float yaw, float pitch,
|
||||||
|
Vec3d offset, Vec3d rotationOffset) {
|
||||||
|
original.rewind();
|
||||||
|
mutable.rewind();
|
||||||
|
|
||||||
|
float cosYaw = MathHelper.cos(yaw);
|
||||||
|
float sinYaw = MathHelper.sin(yaw);
|
||||||
|
float cosPitch = MathHelper.cos(pitch);
|
||||||
|
float sinPitch = MathHelper.sin(pitch);
|
||||||
|
|
||||||
|
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
|
||||||
|
float xL = getX(original, vertex) - (float) rotationOffset.x;
|
||||||
|
float yL = getY(original, vertex) - (float) rotationOffset.y;
|
||||||
|
float zL = getZ(original, vertex) - (float) rotationOffset.z;
|
||||||
|
|
||||||
|
float xL2 = rotateX(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
float yL2 = rotateY(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
float zL2 = rotateZ(xL, yL, zL, sinPitch, cosPitch, Axis.X);
|
||||||
|
//
|
||||||
|
xL = rotateX(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
yL = rotateY(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
zL = rotateZ(xL2, yL2, zL2, sinYaw, cosYaw, Axis.Y);
|
||||||
|
|
||||||
|
float xPos = xL + x + (float) (offset.x + rotationOffset.x);
|
||||||
|
float yPos = yL + y + (float) (offset.y + rotationOffset.y);
|
||||||
|
float zPos = zL + z + (float) (offset.z + rotationOffset.z);
|
||||||
|
putPos(mutable, vertex, xPos, yPos, zPos);
|
||||||
|
BlockPos pos = new BlockPos(xL + rotationOffset.x - .5f, yL + rotationOffset.y - .5f,
|
||||||
|
zL + rotationOffset.z - .5f);
|
||||||
|
putLight(mutable, vertex, world.getCombinedLight(pos, 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutable;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,19 @@
|
||||||
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.common.util.Constants.NBT;
|
||||||
|
|
||||||
public interface IHaveMovementBehavior {
|
public interface IHaveMovementBehavior {
|
||||||
|
|
||||||
|
@ -28,29 +34,50 @@ public interface IHaveMovementBehavior {
|
||||||
public class MovementContext {
|
public class MovementContext {
|
||||||
|
|
||||||
public BlockPos currentGridPos;
|
public BlockPos currentGridPos;
|
||||||
public Vec3d movementVec;
|
public Vec3d motion;
|
||||||
public float movementSpeedModifier = 1;
|
public float movementSpeedModifier = 1;
|
||||||
|
|
||||||
public MoverType moverType;
|
public MoverType moverType;
|
||||||
public Object mover;
|
|
||||||
public World world;
|
public World world;
|
||||||
public BlockState state;
|
public BlockState state;
|
||||||
|
|
||||||
public MovementContext(World world, BlockState state, MoverType moverType, Object mover) {
|
public MovementContext(BlockState state, MoverType moverType) {
|
||||||
this.world = world;
|
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.moverType = moverType;
|
this.moverType = moverType;
|
||||||
this.mover = mover;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Direction getMovementDirection() {
|
public Direction getMovementDirection() {
|
||||||
return Direction.getFacingFromVector(movementVec.x, movementVec.y, movementVec.z);
|
return Direction.getFacingFromVector(motion.x, motion.y, motion.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAnimationSpeed() {
|
||||||
|
int modifier = moverType == MoverType.MINECART ? 1000 : 200;
|
||||||
|
return ((int) (motion.length() * modifier)) / 100 * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MovementContext readNBT(CompoundNBT nbt) {
|
||||||
|
MovementContext context = new MovementContext(NBTUtil.readBlockState(nbt.getCompound("State")),
|
||||||
|
MoverType.valueOf(nbt.getString("MoverType")));
|
||||||
|
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
|
||||||
|
context.movementSpeedModifier = nbt.getFloat("SpeedModifier");
|
||||||
|
context.currentGridPos = NBTUtil.readBlockPos(nbt.getCompound("GridPos"));
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundNBT writeToNBT(CompoundNBT nbt) {
|
||||||
|
nbt.put("State", NBTUtil.writeBlockState(state));
|
||||||
|
nbt.putString("MoverType", moverType.name());
|
||||||
|
nbt.put("Motion", VecHelper.writeNBT(motion));
|
||||||
|
nbt.putFloat("SpeedModifier", movementSpeedModifier);
|
||||||
|
nbt.put("GridPos", NBTUtil.writeBlockPos(currentGridPos));
|
||||||
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
default void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
default ByteBuffer renderInConstruct(MovementContext context) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
||||||
|
|
||||||
import static com.simibubi.create.CreateConfig.parameters;
|
import static com.simibubi.create.CreateConfig.parameters;
|
||||||
|
import static com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.STATE;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -11,17 +12,14 @@ import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.SawBlock;
|
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MoverType;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MoverType;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.tileentity.ITickableTileEntity;
|
import net.minecraft.tileentity.ITickableTileEntity;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
@ -34,7 +32,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
public class MechanicalPistonTileEntity extends KineticTileEntity implements ITickableTileEntity {
|
public class MechanicalPistonTileEntity extends KineticTileEntity implements ITickableTileEntity {
|
||||||
|
|
||||||
protected TranslationConstruct movingConstruct;
|
protected PistonContraption movedContraption;
|
||||||
protected float offset;
|
protected float offset;
|
||||||
protected boolean running;
|
protected boolean running;
|
||||||
protected boolean assembleNextTick;
|
protected boolean assembleNextTick;
|
||||||
|
@ -73,8 +71,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
public CompoundNBT write(CompoundNBT tag) {
|
public CompoundNBT write(CompoundNBT tag) {
|
||||||
tag.putBoolean("Running", running);
|
tag.putBoolean("Running", running);
|
||||||
tag.putFloat("Offset", offset);
|
tag.putFloat("Offset", offset);
|
||||||
if (running && !TranslationConstruct.isFrozen())
|
if (running && !PistonContraption.isFrozen())
|
||||||
tag.put("Construct", movingConstruct.writeNBT());
|
tag.put("Construct", movedContraption.writeNBT());
|
||||||
|
|
||||||
return super.write(tag);
|
return super.write(tag);
|
||||||
}
|
}
|
||||||
|
@ -83,12 +81,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
public void read(CompoundNBT tag) {
|
public void read(CompoundNBT tag) {
|
||||||
running = tag.getBoolean("Running");
|
running = tag.getBoolean("Running");
|
||||||
offset = tag.getFloat("Offset");
|
offset = tag.getFloat("Offset");
|
||||||
if (running && !TranslationConstruct.isFrozen()) {
|
if (running && !PistonContraption.isFrozen()) {
|
||||||
movingConstruct = TranslationConstruct.fromNBT(tag.getCompound("Construct"));
|
movedContraption = new PistonContraption();
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors) {
|
movedContraption.readNBT(tag.getCompound("Construct"));
|
||||||
MovementContext context = new MovementContext(world, pair.left.state, MoverType.PISTON, this);
|
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
|
||||||
|
MovementContext context = new MovementContext(pair.left.state, MoverType.PISTON);
|
||||||
|
context.world = world;
|
||||||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||||
context.movementVec = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
|
context.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
|
||||||
context.currentGridPos = pair.left.pos.offset(direction, getModulatedOffset(offset));
|
context.currentGridPos = pair.left.pos.offset(direction, getModulatedOffset(offset));
|
||||||
pair.setRight(context);
|
pair.setRight(context);
|
||||||
}
|
}
|
||||||
|
@ -98,12 +98,12 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onBlockVisited(float newOffset) {
|
protected void onBlockVisited(float newOffset) {
|
||||||
if (TranslationConstruct.isFrozen())
|
if (PistonContraption.isFrozen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||||
|
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors) {
|
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
|
||||||
BlockInfo block = pair.left;
|
BlockInfo block = pair.left;
|
||||||
MovementContext context = pair.right;
|
MovementContext context = pair.right;
|
||||||
|
|
||||||
|
@ -120,39 +120,40 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||||
|
|
||||||
// Collect Construct
|
// Collect Construct
|
||||||
movingConstruct = TranslationConstruct.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
|
movedContraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
|
||||||
if (movingConstruct == null)
|
if (movedContraption == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check if not at limit already
|
// Check if not at limit already
|
||||||
float resultingOffset = movingConstruct.initialExtensionProgress + getMovementSpeed();
|
float resultingOffset = movedContraption.initialExtensionProgress + getMovementSpeed();
|
||||||
if (resultingOffset <= 0 || resultingOffset >= movingConstruct.extensionLength) {
|
if (resultingOffset <= 0 || resultingOffset >= movedContraption.extensionLength) {
|
||||||
movingConstruct = null;
|
movedContraption = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hasBlockCollisions(resultingOffset + .5f)) {
|
if (hasBlockCollisions(resultingOffset + .5f)) {
|
||||||
movingConstruct = null;
|
movedContraption = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run
|
// Run
|
||||||
running = true;
|
running = true;
|
||||||
offset = movingConstruct.initialExtensionProgress;
|
offset = movedContraption.initialExtensionProgress;
|
||||||
if (!world.isRemote)
|
if (!world.isRemote)
|
||||||
Create.constructHandler.add(this);
|
Create.constructHandler.add(this);
|
||||||
|
|
||||||
sendData();
|
sendData();
|
||||||
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66);
|
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66);
|
||||||
for (BlockInfo block : movingConstruct.blocks.values()) {
|
for (BlockInfo block : movedContraption.blocks.values()) {
|
||||||
BlockPos startPos = block.pos.offset(direction, movingConstruct.initialExtensionProgress);
|
BlockPos startPos = block.pos.offset(direction, movedContraption.initialExtensionProgress);
|
||||||
if (startPos.equals(pos))
|
if (startPos.equals(pos))
|
||||||
continue;
|
continue;
|
||||||
getWorld().setBlockState(startPos, Blocks.AIR.getDefaultState(), 67);
|
getWorld().setBlockState(startPos, Blocks.AIR.getDefaultState(), 67);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors) {
|
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
|
||||||
MovementContext context = new MovementContext(world, pair.left.state, MoverType.PISTON, this);
|
MovementContext context = new MovementContext(pair.left.state, MoverType.PISTON);
|
||||||
context.movementVec = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
|
context.world = world;
|
||||||
|
context.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
|
||||||
context.currentGridPos = pair.left.pos.offset(direction, getModulatedOffset(offset));
|
context.currentGridPos = pair.left.pos.offset(direction, getModulatedOffset(offset));
|
||||||
pair.setRight(context);
|
pair.setRight(context);
|
||||||
}
|
}
|
||||||
|
@ -167,38 +168,19 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||||
if (!removed)
|
if (!removed)
|
||||||
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
|
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
|
||||||
|
movedContraption.disassemble(world, BlockPos.ZERO.offset(direction, getModulatedOffset(offset)),
|
||||||
for (BlockInfo block : movingConstruct.blocks.values()) {
|
(targetPos, state) -> {
|
||||||
BlockPos targetPos = block.pos.offset(direction, getModulatedOffset(offset));
|
if (targetPos.equals(pos)) {
|
||||||
BlockState state = block.state;
|
if (!AllBlocks.PISTON_POLE.typeOf(state) && !removed)
|
||||||
if (targetPos.equals(pos)) {
|
world.setBlockState(pos, getBlockState().with(STATE, PistonState.RETRACTED), 3);
|
||||||
if (!AllBlocks.PISTON_POLE.typeOf(state) && !removed)
|
return true;
|
||||||
getWorld().setBlockState(pos,
|
}
|
||||||
getBlockState().with(MechanicalPistonBlock.STATE, PistonState.RETRACTED), 3);
|
return false;
|
||||||
continue;
|
});
|
||||||
}
|
|
||||||
for (Direction face : Direction.values())
|
|
||||||
state = state.updatePostPlacement(face, world.getBlockState(targetPos.offset(face)), world, targetPos,
|
|
||||||
targetPos.offset(face));
|
|
||||||
|
|
||||||
if (AllBlocks.SAW.typeOf(state))
|
|
||||||
state = state.with(SawBlock.RUNNING, false);
|
|
||||||
|
|
||||||
world.destroyBlock(targetPos, world.getBlockState(targetPos).getCollisionShape(world, targetPos).isEmpty());
|
|
||||||
getWorld().setBlockState(targetPos, state, 3);
|
|
||||||
TileEntity tileEntity = world.getTileEntity(targetPos);
|
|
||||||
if (tileEntity != null && block.nbt != null) {
|
|
||||||
block.nbt.putInt("x", targetPos.getX());
|
|
||||||
block.nbt.putInt("y", targetPos.getY());
|
|
||||||
block.nbt.putInt("z", targetPos.getZ());
|
|
||||||
tileEntity.read(block.nbt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
running = false;
|
running = false;
|
||||||
if (!world.isRemote)
|
if (!world.isRemote)
|
||||||
Create.constructHandler.remove(this);
|
Create.constructHandler.remove(this);
|
||||||
movingConstruct = null;
|
movedContraption = null;
|
||||||
sendData();
|
sendData();
|
||||||
|
|
||||||
if (removed)
|
if (removed)
|
||||||
|
@ -213,10 +195,10 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
if (speed == 0)
|
if (speed == 0)
|
||||||
disassembleConstruct();
|
disassembleConstruct();
|
||||||
else {
|
else {
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors)
|
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors())
|
||||||
pair.right.movementVec = new Vec3d(
|
pair.right.motion = new Vec3d(
|
||||||
getBlockState().get(BlockStateProperties.FACING).getDirectionVec())
|
getBlockState().get(BlockStateProperties.FACING).getDirectionVec())
|
||||||
.scale(getMovementSpeed()).normalize();
|
.scale(getMovementSpeed());
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -257,14 +239,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
|
|
||||||
offset = newOffset;
|
offset = newOffset;
|
||||||
|
|
||||||
if (offset <= 0 || offset >= movingConstruct.extensionLength) {
|
if (offset <= 0 || offset >= movedContraption.extensionLength) {
|
||||||
disassembleConstruct();
|
disassembleConstruct();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasBlockCollisions(float newOffset) {
|
private boolean hasBlockCollisions(float newOffset) {
|
||||||
if (TranslationConstruct.isFrozen())
|
if (PistonContraption.isFrozen())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
|
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
|
||||||
|
@ -280,7 +262,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
|
|
||||||
if (otherPiston == this)
|
if (otherPiston == this)
|
||||||
continue;
|
continue;
|
||||||
if (!otherPiston.running || otherPiston.movingConstruct == null) {
|
if (!otherPiston.running || otherPiston.movedContraption == null) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -291,10 +273,10 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
|
BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
|
||||||
getModulatedOffset(otherPiston.offset));
|
getModulatedOffset(otherPiston.offset));
|
||||||
|
|
||||||
for (AxisAlignedBB tBB : Arrays.asList(movingConstruct.constructCollisionBox,
|
for (AxisAlignedBB tBB : Arrays.asList(movedContraption.constructCollisionBox,
|
||||||
movingConstruct.pistonCollisionBox)) {
|
movedContraption.pistonCollisionBox)) {
|
||||||
for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movingConstruct.constructCollisionBox,
|
for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movedContraption.constructCollisionBox,
|
||||||
otherPiston.movingConstruct.pistonCollisionBox)) {
|
otherPiston.movedContraption.pistonCollisionBox)) {
|
||||||
if (tBB == null || oBB == null)
|
if (tBB == null || oBB == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -306,9 +288,9 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
|
|
||||||
if (thisBB.intersects(otherBB)) {
|
if (thisBB.intersects(otherBB)) {
|
||||||
boolean actuallyColliding = false;
|
boolean actuallyColliding = false;
|
||||||
for (BlockPos colliderPos : movingConstruct.getColliders(world, movementDirection)) {
|
for (BlockPos colliderPos : movedContraption.getColliders(world, movementDirection)) {
|
||||||
colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
|
colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
|
||||||
if (!otherPiston.movingConstruct.blocks.containsKey(colliderPos))
|
if (!otherPiston.movedContraption.blocks.containsKey(colliderPos))
|
||||||
continue;
|
continue;
|
||||||
actuallyColliding = true;
|
actuallyColliding = true;
|
||||||
}
|
}
|
||||||
|
@ -327,7 +309,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Other Blocks in world
|
// Other Blocks in world
|
||||||
for (BlockPos pos : movingConstruct.getColliders(world,
|
for (BlockPos pos : movedContraption.getColliders(world,
|
||||||
getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
|
getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
|
||||||
BlockPos colliderPos = pos.add(relativePos);
|
BlockPos colliderPos = pos.add(relativePos);
|
||||||
|
|
||||||
|
@ -342,7 +324,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getModulatedOffset(float offset) {
|
private int getModulatedOffset(float offset) {
|
||||||
return MathHelper.clamp((int) (offset + .5f), 0, movingConstruct.extensionLength);
|
return MathHelper.clamp((int) (offset + .5f), 0, movedContraption.extensionLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getMovementSpeed() {
|
public float getMovementSpeed() {
|
||||||
|
@ -354,7 +336,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
||||||
|
|
||||||
public Vec3d getConstructOffset(float partialTicks) {
|
public Vec3d getConstructOffset(float partialTicks) {
|
||||||
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
|
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
|
||||||
movingConstruct.extensionLength);
|
movedContraption.extensionLength);
|
||||||
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
|
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,17 @@
|
||||||
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
|
|
||||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
|
||||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
import net.minecraft.client.renderer.model.IBakedModel;
|
|
||||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
|
||||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
|
||||||
|
|
||||||
public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRenderer {
|
public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRenderer {
|
||||||
|
|
||||||
protected static Cache<TranslationConstruct, TranslationConstructVertexBuffer> cachedConstructs;
|
|
||||||
protected static PlacementSimulationWorld renderWorld;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
|
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
|
||||||
int destroyStage, BufferBuilder buffer) {
|
int destroyStage, BufferBuilder buffer) {
|
||||||
|
@ -44,58 +23,21 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
|
||||||
if (!pistonTe.running)
|
if (!pistonTe.running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cacheConstructIfMissing(pistonTe.movingConstruct);
|
ContraptionRenderer.cacheContraptionIfMissing(pistonTe.movedContraption);
|
||||||
renderConstructFromCache(pistonTe.movingConstruct, pistonTe, x, y, z, partialTicks, buffer);
|
renderConstructFromCache(pistonTe.movedContraption, pistonTe, x, y, z, partialTicks, buffer);
|
||||||
for (Pair<BlockInfo, MovementContext> actor : pistonTe.movingConstruct.actors) {
|
|
||||||
MovementContext context = actor.getRight();
|
|
||||||
if (context == null)
|
|
||||||
continue;
|
|
||||||
final Vec3d offset = pistonTe.getConstructOffset(partialTicks);
|
|
||||||
BlockInfo blockInfo = actor.getLeft();
|
|
||||||
IHaveMovementBehavior block = (IHaveMovementBehavior) blockInfo.state.getBlock();
|
|
||||||
BlockPos pos = blockInfo.pos.subtract(te.getPos());
|
|
||||||
block.renderInConstruct(context, x + offset.x + pos.getX(),
|
|
||||||
y + offset.y + pos.getY(), z + offset.z + pos.getZ(), buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Vec3d offset = pistonTe.getConstructOffset(partialTicks).subtract(new Vec3d(pistonTe.getPos()));
|
||||||
|
ContraptionRenderer.renderActors(pistonTe.getWorld(), pistonTe.movedContraption, (float) (x + offset.x),
|
||||||
|
(float) (y + offset.y), (float) (z + offset.z), 0, 0, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void cacheConstructIfMissing(TranslationConstruct c) {
|
protected void renderConstructFromCache(Contraption c, MechanicalPistonTileEntity te, double x, double y, double z,
|
||||||
if (cachedConstructs == null)
|
float partialTicks, BufferBuilder buffer) {
|
||||||
cachedConstructs = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.SECONDS).build();
|
|
||||||
if (cachedConstructs.getIfPresent(c) != null)
|
|
||||||
return;
|
|
||||||
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
|
|
||||||
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
|
|
||||||
|
|
||||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
|
|
||||||
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
|
|
||||||
Random random = new Random();
|
|
||||||
BufferBuilder builder = new BufferBuilder(0);
|
|
||||||
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
|
|
||||||
builder.setTranslation(0, 0, 0);
|
|
||||||
|
|
||||||
for (BlockInfo info : c.blocks.values()) {
|
|
||||||
renderWorld.setBlockState(info.pos, info.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BlockInfo info : c.blocks.values()) {
|
|
||||||
IBakedModel originalModel = dispatcher.getModelForState(info.state);
|
|
||||||
blockRenderer.renderModel(renderWorld, originalModel, info.state, info.pos, builder, true, random, 42,
|
|
||||||
EmptyModelData.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.finishDrawing();
|
|
||||||
renderWorld.clear();
|
|
||||||
cachedConstructs.put(c, new TranslationConstructVertexBuffer(builder.getByteBuffer()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void renderConstructFromCache(TranslationConstruct c, MechanicalPistonTileEntity te, double x, double y,
|
|
||||||
double z, float partialTicks, BufferBuilder buffer) {
|
|
||||||
final Vec3d offset = te.getConstructOffset(partialTicks);
|
final Vec3d offset = te.getConstructOffset(partialTicks);
|
||||||
buffer.putBulkData(cachedConstructs.getIfPresent(c).getTransformed(te,
|
float xPos = (float) (x - te.getPos().getX());
|
||||||
(float) (x + offset.x - te.getPos().getX()), (float) (y + offset.y - te.getPos().getY()),
|
float yPos = (float) (y - te.getPos().getY());
|
||||||
(float) (z + offset.z - te.getPos().getZ()), offset));
|
float zPos = (float) (z - te.getPos().getZ());
|
||||||
|
buffer.putBulkData(ContraptionRenderer.get(c).getTranslated(te.getWorld(), xPos, yPos, zPos, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -104,9 +46,4 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
|
||||||
((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState()));
|
((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void invalidateCache() {
|
|
||||||
if (cachedConstructs != null)
|
|
||||||
cachedConstructs.invalidateAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,12 +48,12 @@ public class MovingConstructHandler {
|
||||||
|
|
||||||
public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
|
public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
|
||||||
float newOffset) {
|
float newOffset) {
|
||||||
if (TranslationConstruct.isFrozen())
|
if (PistonContraption.isFrozen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
World world = te.getWorld();
|
World world = te.getWorld();
|
||||||
Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
|
Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
|
||||||
TranslationConstruct construct = te.movingConstruct;
|
Contraption construct = te.movedContraption;
|
||||||
|
|
||||||
// if (world.isRemote) {
|
// if (world.isRemote) {
|
||||||
// renderedBBs.clear();
|
// renderedBBs.clear();
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
||||||
|
|
||||||
|
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
|
||||||
|
import static com.simibubi.create.AllBlocks.PISTON_POLE;
|
||||||
|
import static com.simibubi.create.AllBlocks.STICKY_MECHANICAL_PISTON;
|
||||||
|
import static com.simibubi.create.CreateConfig.parameters;
|
||||||
|
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.state.properties.PistonType;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
|
||||||
|
public class PistonContraption extends Contraption {
|
||||||
|
|
||||||
|
protected AxisAlignedBB pistonCollisionBox;
|
||||||
|
|
||||||
|
protected int extensionLength;
|
||||||
|
protected int initialExtensionProgress;
|
||||||
|
protected Direction orientation;
|
||||||
|
|
||||||
|
public static PistonContraption movePistonAt(World world, BlockPos pos, Direction direction, boolean retract) {
|
||||||
|
if (isFrozen())
|
||||||
|
return null;
|
||||||
|
PistonContraption construct = new PistonContraption();
|
||||||
|
construct.orientation = direction;
|
||||||
|
if (!construct.collectExtensions(world, pos, direction))
|
||||||
|
return null;
|
||||||
|
if (!construct.searchMovedStructure(world, pos.offset(direction, construct.initialExtensionProgress + 1),
|
||||||
|
retract ? direction.getOpposite() : direction))
|
||||||
|
return null;
|
||||||
|
return construct;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean collectExtensions(World world, BlockPos pos, Direction direction) {
|
||||||
|
List<BlockInfo> poles = new ArrayList<>();
|
||||||
|
BlockPos actualStart = pos;
|
||||||
|
BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
|
||||||
|
int extensionsInFront = 0;
|
||||||
|
boolean sticky = STICKY_MECHANICAL_PISTON.typeOf(world.getBlockState(pos));
|
||||||
|
|
||||||
|
if (world.getBlockState(pos).get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
|
||||||
|
while (PISTON_POLE.typeOf(nextBlock) && nextBlock.get(FACING).getAxis() == direction.getAxis()
|
||||||
|
|| MECHANICAL_PISTON_HEAD.typeOf(nextBlock) && nextBlock.get(FACING) == direction) {
|
||||||
|
|
||||||
|
actualStart = actualStart.offset(direction);
|
||||||
|
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
|
||||||
|
extensionsInFront++;
|
||||||
|
nextBlock = world.getBlockState(actualStart.offset(direction));
|
||||||
|
|
||||||
|
if (extensionsInFront > parameters.maxPistonPoles.get())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensionsInFront == 0)
|
||||||
|
poles.add(
|
||||||
|
new BlockInfo(pos,
|
||||||
|
MECHANICAL_PISTON_HEAD.get().getDefaultState().with(FACING, direction).with(
|
||||||
|
BlockStateProperties.PISTON_TYPE, sticky ? PistonType.STICKY : PistonType.DEFAULT),
|
||||||
|
null));
|
||||||
|
else
|
||||||
|
poles.add(new BlockInfo(pos, PISTON_POLE.get().getDefaultState().with(FACING, direction), null));
|
||||||
|
|
||||||
|
BlockPos end = pos;
|
||||||
|
nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
|
||||||
|
int extensionsInBack = 0;
|
||||||
|
|
||||||
|
while (PISTON_POLE.typeOf(nextBlock)) {
|
||||||
|
end = end.offset(direction.getOpposite());
|
||||||
|
poles.add(new BlockInfo(end, nextBlock.with(FACING, direction), null));
|
||||||
|
extensionsInBack++;
|
||||||
|
nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
|
||||||
|
|
||||||
|
if (extensionsInFront + extensionsInBack > parameters.maxPistonPoles.get())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extensionLength = extensionsInBack + extensionsInFront;
|
||||||
|
initialExtensionProgress = extensionsInFront;
|
||||||
|
pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront));
|
||||||
|
|
||||||
|
for (BlockInfo pole : poles) {
|
||||||
|
BlockPos polePos = pole.pos.offset(direction, -extensionsInFront);
|
||||||
|
blocks.put(polePos, new BlockInfo(polePos, pole.state, null));
|
||||||
|
pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos));
|
||||||
|
}
|
||||||
|
|
||||||
|
constructCollisionBox = new AxisAlignedBB(pos.offset(direction, initialExtensionProgress));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
|
||||||
|
for (int offset = 1; offset <= parameters.maxChassisRange.get(); offset++) {
|
||||||
|
BlockPos currentPos = pos.offset(direction, offset);
|
||||||
|
if (!world.isAreaLoaded(currentPos, 1))
|
||||||
|
return false;
|
||||||
|
if (!world.isBlockPresent(currentPos))
|
||||||
|
break;
|
||||||
|
BlockState state = world.getBlockState(currentPos);
|
||||||
|
if (state.getMaterial().isReplaceable())
|
||||||
|
break;
|
||||||
|
if (state.getCollisionShape(world, currentPos).isEmpty())
|
||||||
|
break;
|
||||||
|
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite())
|
||||||
|
break;
|
||||||
|
if (!canPush(world, currentPos, direction))
|
||||||
|
return false;
|
||||||
|
frontier.add(currentPos);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void add(BlockPos pos, BlockInfo block) {
|
||||||
|
super.add(pos.offset(orientation, -initialExtensionProgress), block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readNBT(CompoundNBT nbt) {
|
||||||
|
super.readNBT(nbt);
|
||||||
|
extensionLength = nbt.getInt("ExtensionLength");
|
||||||
|
if (nbt.contains("BoundsBack"))
|
||||||
|
pistonCollisionBox = readAABB(nbt.getList("BoundsBack", 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundNBT writeNBT() {
|
||||||
|
CompoundNBT nbt = super.writeNBT();
|
||||||
|
|
||||||
|
if (pistonCollisionBox != null) {
|
||||||
|
ListNBT bb = writeAABB(pistonCollisionBox);
|
||||||
|
nbt.put("BoundsBack", bb);
|
||||||
|
}
|
||||||
|
nbt.putInt("ExtensionLength", extensionLength);
|
||||||
|
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB getCollisionBoxBack() {
|
||||||
|
return pistonCollisionBox;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
package com.simibubi.create.modules.contraptions.receivers.constructs;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.BufferManipulator;
|
|
||||||
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
|
|
||||||
public class TranslationConstructVertexBuffer extends BufferManipulator {
|
|
||||||
|
|
||||||
public TranslationConstructVertexBuffer(ByteBuffer original) {
|
|
||||||
super(original);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteBuffer getTransformed(TileEntity te, float x, float y, float z, Vec3d offset) {
|
|
||||||
original.rewind();
|
|
||||||
mutable.rewind();
|
|
||||||
|
|
||||||
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
|
|
||||||
float xL = getX(original, vertex);
|
|
||||||
float yL = getY(original, vertex);
|
|
||||||
float zL = getZ(original, vertex);
|
|
||||||
putPos(mutable, vertex, xL + x, yL + y, zL + z);
|
|
||||||
BlockPos pos = new BlockPos(offset.x + xL, offset.y + yL, offset.z + zL);
|
|
||||||
putLight(mutable, vertex, te.getWorld().getCombinedLight(pos, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return mutable;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.foundation.block.RenderUtilityBlock;
|
||||||
|
|
||||||
|
import net.minecraft.block.AbstractRailBlock;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.block.material.PushReaction;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
|
import net.minecraft.item.BlockItemUseContext;
|
||||||
|
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.state.properties.RailShape;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
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.World;
|
||||||
|
|
||||||
|
public class CartAssemblerBlock extends AbstractRailBlock {
|
||||||
|
|
||||||
|
public static IProperty<RailShape> RAIL_SHAPE = EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST,
|
||||||
|
RailShape.NORTH_SOUTH);
|
||||||
|
public static BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||||||
|
|
||||||
|
public static VoxelShape X_SHAPE = VoxelShapes.or(VoxelShapes.fullCube(), makeCuboidShape(1, 0, -2, 15, 13, 18));
|
||||||
|
public static VoxelShape Z_SHAPE = VoxelShapes.or(VoxelShapes.fullCube(), makeCuboidShape(-2, 0, 1, 18, 13, 15));
|
||||||
|
|
||||||
|
public CartAssemblerBlock() {
|
||||||
|
super(true, Properties.from(Blocks.PISTON));
|
||||||
|
setDefaultState(getDefaultState().with(POWERED, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||||
|
builder.add(RAIL_SHAPE, POWERED);
|
||||||
|
super.fillStateContainer(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||||
|
boolean alongX = context.getPlacementHorizontalFacing().getAxis() == Axis.X;
|
||||||
|
boolean powered = context.getWorld().isBlockPowered(context.getPos());
|
||||||
|
return super.getStateForPlacement(context).with(POWERED, Boolean.valueOf(powered)).with(RAIL_SHAPE,
|
||||||
|
alongX ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canMakeSlopes(BlockState state, IBlockReader world, BlockPos pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) {
|
||||||
|
if (!cart.canBeRidden())
|
||||||
|
return;
|
||||||
|
if (state.get(POWERED))
|
||||||
|
disassemble(world, pos, cart);
|
||||||
|
else
|
||||||
|
assemble(world, pos, cart);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assemble(World world, BlockPos pos, AbstractMinecartEntity cart) {
|
||||||
|
if (!cart.getPassengers().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
|
||||||
|
ContraptionEntity entity = new ContraptionEntity(world, contraption,
|
||||||
|
ContraptionEntity.yawFromMotion(cart.getMotion()));
|
||||||
|
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
world.addEntity(entity);
|
||||||
|
entity.startRiding(cart);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void disassemble(World world, BlockPos pos, AbstractMinecartEntity cart) {
|
||||||
|
if (cart.getPassengers().isEmpty())
|
||||||
|
return;
|
||||||
|
Entity entity = cart.getPassengers().get(0);
|
||||||
|
if (!(entity instanceof ContraptionEntity))
|
||||||
|
return;
|
||||||
|
MountedContraption contraption = ((ContraptionEntity) entity).contraption;
|
||||||
|
if (contraption == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
contraption.disassemble(world, pos.subtract(contraption.getAnchor()), (targetPos, state) -> {
|
||||||
|
return targetPos.equals(pos);
|
||||||
|
});
|
||||||
|
|
||||||
|
cart.removePassengers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
||||||
|
boolean isMoving) {
|
||||||
|
super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving);
|
||||||
|
|
||||||
|
if (worldIn.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
boolean previouslyPowered = state.get(POWERED);
|
||||||
|
if (previouslyPowered != worldIn.isBlockPowered(pos)) {
|
||||||
|
worldIn.setBlockState(pos, state.cycle(POWERED), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IProperty<RailShape> getShapeProperty() {
|
||||||
|
return RAIL_SHAPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||||
|
return state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? X_SHAPE : Z_SHAPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos,
|
||||||
|
ISelectionContext context) {
|
||||||
|
if (context.getEntity() instanceof AbstractMinecartEntity)
|
||||||
|
return VoxelShapes.empty();
|
||||||
|
return VoxelShapes.fullCube();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PushReaction getPushReaction(BlockState state) {
|
||||||
|
return PushReaction.BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MinecartAnchorBlock extends RenderUtilityBlock {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fillStateContainer(Builder<Block, BlockState> builder) {
|
||||||
|
builder.add(BlockStateProperties.HORIZONTAL_AXIS);
|
||||||
|
super.fillStateContainer(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockState createAnchor(BlockState state) {
|
||||||
|
Axis axis = state.get(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? Axis.Z : Axis.X;
|
||||||
|
return AllBlocks.MINECART_ANCHOR.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllEntities;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.network.IPacket;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.particles.ParticleTypes;
|
||||||
|
import net.minecraft.util.DamageSource;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||||
|
import net.minecraftforge.fml.network.FMLPlayMessages.SpawnEntity;
|
||||||
|
import net.minecraftforge.fml.network.NetworkHooks;
|
||||||
|
|
||||||
|
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
|
||||||
|
|
||||||
|
protected MountedContraption contraption;
|
||||||
|
protected float initialAngle;
|
||||||
|
|
||||||
|
// Not synchronizing any of these
|
||||||
|
public float targetYaw;
|
||||||
|
public float targetPitch;
|
||||||
|
public float contraptionYaw;
|
||||||
|
public float contraptionPitch;
|
||||||
|
|
||||||
|
public ContraptionEntity(EntityType<?> entityTypeIn, World worldIn) {
|
||||||
|
super(entityTypeIn, worldIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ContraptionEntity(World world) {
|
||||||
|
this(AllEntities.CONTRAPTION.type, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContraptionEntity(World world, MountedContraption contraption, float initialAngle) {
|
||||||
|
this(world);
|
||||||
|
this.contraption = contraption;
|
||||||
|
this.initialAngle = initialAngle;
|
||||||
|
this.prevRotationYaw = initialAngle;
|
||||||
|
this.contraptionYaw = initialAngle;
|
||||||
|
this.targetYaw = initialAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerData() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
Entity e = getRidingEntity();
|
||||||
|
if (e == null)
|
||||||
|
remove();
|
||||||
|
else {
|
||||||
|
Vec3d movementVector = e.getMotion();
|
||||||
|
Vec3d motion = movementVector.normalize();
|
||||||
|
if (motion.length() > 0) {
|
||||||
|
targetYaw = yawFromMotion(motion);
|
||||||
|
targetPitch = (float) ((Math.atan(motion.y) * 73.0D) / Math.PI * 180);
|
||||||
|
if (targetYaw < 0)
|
||||||
|
targetYaw += 360;
|
||||||
|
if (contraptionYaw < 0)
|
||||||
|
contraptionYaw += 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
float speed = 0.2f;
|
||||||
|
prevRotationYaw = contraptionYaw;
|
||||||
|
contraptionYaw = angleLerp(speed, contraptionYaw, targetYaw);
|
||||||
|
prevRotationPitch = contraptionPitch;
|
||||||
|
contraptionPitch = angleLerp(speed, contraptionPitch, targetPitch);
|
||||||
|
|
||||||
|
tickActors(movementVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tickActors(Vec3d movementVector) {
|
||||||
|
contraption.getActors().forEach(pair -> {
|
||||||
|
MovementContext context = pair.right;
|
||||||
|
float deg = -contraptionYaw + initialAngle;
|
||||||
|
context.motion = VecHelper.rotate(movementVector, deg, Axis.Y);
|
||||||
|
|
||||||
|
if (context.world == null)
|
||||||
|
context.world = world;
|
||||||
|
|
||||||
|
Vec3d offset = new Vec3d(pair.left.pos.subtract(contraption.getAnchor()));
|
||||||
|
world.addParticle(ParticleTypes.BUBBLE, offset.x, offset.y, offset.z, 0, 0, 0);
|
||||||
|
|
||||||
|
offset = VecHelper.rotate(offset, deg, Axis.Y);
|
||||||
|
world.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0);
|
||||||
|
|
||||||
|
offset = offset.add(new Vec3d(getPosition()).add(0.5, 0, 0.5));
|
||||||
|
world.addParticle(ParticleTypes.NOTE, offset.x, offset.y, offset.z, 0, 10, 0);
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockPos gridPos = new BlockPos(offset);
|
||||||
|
if (context.currentGridPos.equals(gridPos))
|
||||||
|
return;
|
||||||
|
context.currentGridPos = gridPos;
|
||||||
|
|
||||||
|
IHaveMovementBehavior actor = (IHaveMovementBehavior) pair.left.state.getBlock();
|
||||||
|
actor.visitPosition(context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float yawFromMotion(Vec3d motion) {
|
||||||
|
return (float) ((Math.PI / 2 - Math.atan2(motion.z, motion.x)) / Math.PI * 180);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getYaw(float partialTicks) {
|
||||||
|
float yaw = contraptionYaw;
|
||||||
|
return (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, this.prevRotationYaw, yaw)) - initialAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPitch(float partialTicks) {
|
||||||
|
float pitch = contraptionPitch;
|
||||||
|
return partialTicks == 1.0F ? pitch : angleLerp(partialTicks, this.prevRotationPitch, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float angleLerp(float pct, float current, float target) {
|
||||||
|
current = current % 360;
|
||||||
|
target = target % 360;
|
||||||
|
float shortest_angle = ((((target - current) % 360) + 540) % 360) - 180;
|
||||||
|
return current + shortest_angle * pct;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hitByEntity(Entity entityIn) {
|
||||||
|
return entityIn instanceof PlayerEntity
|
||||||
|
? this.attackEntityFrom(DamageSource.causePlayerDamage((PlayerEntity) entityIn), 0.0F)
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean attackEntityFrom(DamageSource source, float amount) {
|
||||||
|
if (this.isInvulnerableTo(source)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (this.isAlive() && !this.world.isRemote) {
|
||||||
|
this.remove();
|
||||||
|
this.markVelocityChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
EntityType.Builder<ContraptionEntity> entityBuilder = (EntityType.Builder<ContraptionEntity>) builder;
|
||||||
|
return entityBuilder.setCustomClientFactory(ContraptionEntity::spawn).size(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ContraptionEntity spawn(SpawnEntity spawnEntity, World world) {
|
||||||
|
return new ContraptionEntity(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readAdditional(CompoundNBT compound) {
|
||||||
|
contraption = new MountedContraption();
|
||||||
|
contraption.readNBT(compound.getCompound("Contraption"));
|
||||||
|
initialAngle = compound.getFloat("InitialAngle");
|
||||||
|
prevRotationYaw = initialAngle;
|
||||||
|
contraptionYaw = initialAngle;
|
||||||
|
targetYaw = initialAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeAdditional(CompoundNBT compound) {
|
||||||
|
compound.put("Contraption", contraption.writeNBT());
|
||||||
|
compound.putFloat("InitialAngle", initialAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPacket<?> createSpawnPacket() {
|
||||||
|
return NetworkHooks.getEntitySpawningPacket(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeSpawnData(PacketBuffer buffer) {
|
||||||
|
CompoundNBT compound = new CompoundNBT();
|
||||||
|
writeAdditional(compound);
|
||||||
|
buffer.writeCompoundTag(compound);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readSpawnData(PacketBuffer additionalData) {
|
||||||
|
readAdditional(additionalData.readCompoundTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionVertexBuffer;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity> {
|
||||||
|
|
||||||
|
public ContraptionEntityRenderer(EntityRendererManager rendererManager) {
|
||||||
|
super(rendererManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ResourceLocation getEntityTexture(ContraptionEntity arg0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doRender(ContraptionEntity entity, double x, double y, double z, float yaw, float partialTicks) {
|
||||||
|
if (!entity.isAlive())
|
||||||
|
return;
|
||||||
|
if (entity.contraption == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GlStateManager.pushMatrix();
|
||||||
|
GlStateManager.translated(0, .5, 0);
|
||||||
|
|
||||||
|
float angleYaw = (float) (entity.getYaw(partialTicks) / 180 * Math.PI);
|
||||||
|
float anglePitch = (float) (entity.getPitch(partialTicks) / 180 * Math.PI);
|
||||||
|
|
||||||
|
Entity ridingEntity = entity.getRidingEntity();
|
||||||
|
if (ridingEntity != null && ridingEntity instanceof AbstractMinecartEntity) {
|
||||||
|
AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity;
|
||||||
|
|
||||||
|
long i = (long) entity.getEntityId() * 493286711L;
|
||||||
|
i = i * i * 4392167121L + i * 98761L;
|
||||||
|
float f = (((float) (i >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
|
||||||
|
float f1 = (((float) (i >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
|
||||||
|
float f2 = (((float) (i >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
|
||||||
|
GlStateManager.translatef(f, f1, f2);
|
||||||
|
|
||||||
|
double cartX = MathHelper.lerp((double) partialTicks, cart.lastTickPosX, cart.posX);
|
||||||
|
double cartY = MathHelper.lerp((double) partialTicks, cart.lastTickPosY, cart.posY);
|
||||||
|
double cartZ = MathHelper.lerp((double) partialTicks, cart.lastTickPosZ, cart.posZ);
|
||||||
|
Vec3d cartPos = cart.getPos(cartX, cartY, cartZ);
|
||||||
|
|
||||||
|
if (cartPos != null) {
|
||||||
|
|
||||||
|
Vec3d cartPosFront = cart.getPosOffset(cartX, cartY, cartZ, (double) 0.3F);
|
||||||
|
Vec3d cartPosBack = cart.getPosOffset(cartX, cartY, cartZ, (double) -0.3F);
|
||||||
|
if (cartPosFront == null)
|
||||||
|
cartPosFront = cartPos;
|
||||||
|
if (cartPosBack == null)
|
||||||
|
cartPosBack = cartPos;
|
||||||
|
|
||||||
|
cartX = cartPos.x - cartX;
|
||||||
|
cartY = (cartPosFront.y + cartPosBack.y) / 2.0D - cartY;
|
||||||
|
cartZ = cartPos.z - cartZ;
|
||||||
|
|
||||||
|
GlStateManager.translatef((float) cartX, (float) cartY, (float) cartZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ContraptionRenderer.cacheContraptionIfMissing(entity.contraption);
|
||||||
|
TessellatorHelper.prepareFastRender();
|
||||||
|
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
|
||||||
|
ContraptionVertexBuffer buffer = ContraptionRenderer.get(entity.contraption);
|
||||||
|
if (buffer != null) {
|
||||||
|
BlockPos anchor = entity.contraption.getAnchor();
|
||||||
|
Vec3d rotationOffset = VecHelper.getCenterOf(anchor);
|
||||||
|
Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1);
|
||||||
|
Tessellator.getInstance().getBuffer().putBulkData(buffer.getTranslatedAndRotated(entity.world, (float) x,
|
||||||
|
(float) y, (float) z, angleYaw, -anglePitch, offset, rotationOffset));
|
||||||
|
ContraptionRenderer.renderActors(entity.world, entity.contraption, (float) (x + offset.x),
|
||||||
|
(float) (y + offset.y), (float) (z + offset.z), angleYaw, -anglePitch,
|
||||||
|
Tessellator.getInstance().getBuffer());
|
||||||
|
}
|
||||||
|
TessellatorHelper.draw();
|
||||||
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
|
super.doRender(entity, x, y, z, yaw, partialTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.receivers.constructs.mounted;
|
||||||
|
|
||||||
|
import static com.simibubi.create.modules.contraptions.receivers.constructs.mounted.CartAssemblerBlock.RAIL_SHAPE;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.MutablePair;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.Contraption;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
||||||
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MoverType;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.state.properties.RailShape;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
|
||||||
|
public class MountedContraption extends Contraption {
|
||||||
|
|
||||||
|
public static MountedContraption assembleMinecart(World world, BlockPos pos, AbstractMinecartEntity cart) {
|
||||||
|
if (isFrozen())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
if (!state.has(RAIL_SHAPE))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
MountedContraption contraption = new MountedContraption();
|
||||||
|
Vec3d vec = cart.getMotion();
|
||||||
|
if (!contraption.searchMovedStructure(world, pos, Direction.getFacingFromVector(vec.x, vec.y, vec.z)))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
|
||||||
|
contraption.add(pos, new BlockInfo(pos,
|
||||||
|
AllBlocks.MINECART_ANCHOR.block.getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis),
|
||||||
|
null));
|
||||||
|
|
||||||
|
for (BlockInfo block : contraption.blocks.values()) {
|
||||||
|
BlockPos startPos = pos;
|
||||||
|
if (startPos.equals(block.pos))
|
||||||
|
continue;
|
||||||
|
world.setBlockState(block.pos, Blocks.AIR.getDefaultState(), 67);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MutablePair<BlockInfo, MovementContext> pair : contraption.getActors()) {
|
||||||
|
MovementContext context = new MovementContext(pair.left.state, MoverType.MINECART);
|
||||||
|
context.world = world;
|
||||||
|
context.motion = vec;
|
||||||
|
context.currentGridPos = pair.left.pos;
|
||||||
|
pair.setRight(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contraption;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
|
||||||
|
frontier.clear();
|
||||||
|
frontier.add(pos.up());
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
if (!AllBlocks.CART_ASSEMBLER.typeOf(state))
|
||||||
|
return false;
|
||||||
|
Axis axis = state.get(CartAssemblerBlock.RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.Z : Axis.X;
|
||||||
|
for (AxisDirection axisDirection : AxisDirection.values())
|
||||||
|
frontier.add(pos.offset(Direction.getFacingFromAxis(axisDirection, axis)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BlockInfo capture(World world, BlockPos pos) {
|
||||||
|
BlockInfo capture = super.capture(world, pos);
|
||||||
|
if (AllBlocks.CART_ASSEMBLER.typeOf(capture.state))
|
||||||
|
return new BlockInfo(capture.pos, CartAssemblerBlock.createAnchor(capture.state), null);
|
||||||
|
return capture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPos getAnchor() {
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ import java.util.Random;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
|
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
|
||||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonTileEntity;
|
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -109,11 +108,9 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen
|
||||||
Direction direction = block.get(FACING);
|
Direction direction = block.get(FACING);
|
||||||
if (!hasValidContact(world, pos, direction))
|
if (!hasValidContact(world, pos, direction))
|
||||||
return;
|
return;
|
||||||
if (context.moverType != MoverType.PISTON)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int ticksToStayActive = (int) Math
|
int ticksToStayActive = (int) Math
|
||||||
.ceil(1 / Math.abs(((MechanicalPistonTileEntity) context.mover).getMovementSpeed()));
|
.ceil(1 / Math.abs(context.motion.length()));
|
||||||
world.setBlockState(pos.offset(direction), world.getBlockState(pos.offset(direction)).with(POWERED, true));
|
world.setBlockState(pos.offset(direction), world.getBlockState(pos.offset(direction)).with(POWERED, true));
|
||||||
world.getPendingBlockTicks().scheduleTick(pos.offset(direction), this, ticksToStayActive, TickPriority.NORMAL);
|
world.getPendingBlockTicks().scheduleTick(pos.offset(direction), this, ticksToStayActive, TickPriority.NORMAL);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -4,7 +4,6 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.culling.ICamera;
|
|
||||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||||
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
import net.minecraft.client.renderer.entity.EntityRendererManager;
|
||||||
import net.minecraft.client.renderer.model.IBakedModel;
|
import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
|
@ -24,18 +23,6 @@ public class CardboardBoxEntityRenderer extends EntityRenderer<CardboardBoxEntit
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldRender(CardboardBoxEntity livingEntity, ICamera camera, double camX, double camY,
|
|
||||||
double camZ) {
|
|
||||||
return super.shouldRender(livingEntity, camera, camX, camY, camZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void renderMultipass(CardboardBoxEntity entityIn, double x, double y, double z, float entityYaw,
|
|
||||||
float partialTicks) {
|
|
||||||
super.renderMultipass(entityIn, x, y, z, entityYaw, partialTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doRender(CardboardBoxEntity entity, double x, double y, double z, float entityYaw, float partialTicks) {
|
public void doRender(CardboardBoxEntity entity, double x, double y, double z, float entityYaw, float partialTicks) {
|
||||||
IBakedModel model = getModelForBox(entity);
|
IBakedModel model = getModelForBox(entity);
|
||||||
|
|
|
@ -5,13 +5,12 @@ import org.lwjgl.opengl.GL11;
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
|
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
|
||||||
|
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.RenderHelper;
|
import net.minecraft.client.renderer.RenderHelper;
|
||||||
import net.minecraft.client.renderer.Tessellator;
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
import net.minecraft.client.renderer.entity.model.BookModel;
|
import net.minecraft.client.renderer.entity.model.BookModel;
|
||||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
@ -25,19 +24,8 @@ public class LogisticiansTableTileEntityRenderer extends TileEntityRenderer<Logi
|
||||||
|
|
||||||
public void render(LogisticiansTableTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
|
public void render(LogisticiansTableTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
|
||||||
int destroyStage) {
|
int destroyStage) {
|
||||||
Minecraft.getInstance().textureManager
|
TessellatorHelper.prepareFastRender();
|
||||||
.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();
|
|
||||||
GlStateManager.disableCull();
|
|
||||||
|
|
||||||
if (net.minecraft.client.Minecraft.isAmbientOcclusionEnabled())
|
|
||||||
GlStateManager.shadeModel(GL11.GL_SMOOTH);
|
|
||||||
else
|
|
||||||
GlStateManager.shadeModel(GL11.GL_FLAT);
|
|
||||||
|
|
||||||
GlStateManager.color3f(1, 1, 1);
|
|
||||||
BlockPos pos = tileEntityIn.getPos();
|
BlockPos pos = tileEntityIn.getPos();
|
||||||
BlockState blockState = tileEntityIn.getBlockState();
|
BlockState blockState = tileEntityIn.getBlockState();
|
||||||
BlockState renderedState = AllBlocks.LOGISTICIANS_TABLE_INDICATOR.get().getDefaultState();
|
BlockState renderedState = AllBlocks.LOGISTICIANS_TABLE_INDICATOR.get().getDefaultState();
|
||||||
|
@ -63,5 +51,4 @@ public class LogisticiansTableTileEntityRenderer extends TileEntityRenderer<Logi
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"forge_marker": 1,
|
||||||
|
"defaults": {
|
||||||
|
"model": "create:block/cart_assembler"
|
||||||
|
},
|
||||||
|
"variants": {
|
||||||
|
"shape": {
|
||||||
|
"north_south": { },
|
||||||
|
"east_west": { "y": 90 }
|
||||||
|
},
|
||||||
|
"powered": {
|
||||||
|
"false": { },
|
||||||
|
"true": {
|
||||||
|
"textures": {
|
||||||
|
"clutch_off": "create:block/clutch_on"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"forge_marker": 1,
|
||||||
|
"defaults": {
|
||||||
|
"model": "create:block/minecart_anchor"
|
||||||
|
},
|
||||||
|
"variants": {
|
||||||
|
"axis": {
|
||||||
|
"x": { "y": 90 },
|
||||||
|
"z": { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,8 @@
|
||||||
"item.create.dough": "Dough",
|
"item.create.dough": "Dough",
|
||||||
"item.create.crushed_iron": "Crushed Iron Ore",
|
"item.create.crushed_iron": "Crushed Iron Ore",
|
||||||
"item.create.crushed_gold": "Crushed Gold Ore",
|
"item.create.crushed_gold": "Crushed Gold Ore",
|
||||||
|
"item.create.time_scarf": "Scarf with a clock on it",
|
||||||
|
"item.create.motion_scarf": "Scarf of Perpetuality",
|
||||||
|
|
||||||
"item.create.logistical_controller_supply": "Item Supply",
|
"item.create.logistical_controller_supply": "Item Supply",
|
||||||
"item.create.logistical_controller_request": "Item Request",
|
"item.create.logistical_controller_request": "Item Request",
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
{
|
||||||
|
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
|
||||||
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"particle": "create:block/translation_chassis_side",
|
||||||
|
"gearbox_top": "create:block/gearbox_top",
|
||||||
|
"clutch_off": "create:block/clutch_off",
|
||||||
|
"rail": "minecraft:block/rail",
|
||||||
|
"translation_chassis_side": "create:block/translation_chassis_side"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"name": "Rail",
|
||||||
|
"from": [ 0, 1, 0 ],
|
||||||
|
"to": [ 16, 1, 16 ],
|
||||||
|
"faces": {
|
||||||
|
"up": { "texture": "#rail", "uv": [ 0, 0, 16, 16 ] },
|
||||||
|
"down": { "texture": "#rail", "uv": [ 0, 0, 16, 16 ], "rotation": 180 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Side",
|
||||||
|
"from": [ 0, 0, 0 ],
|
||||||
|
"to": [ 2, 16, 16 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#gearbox_top", "uv": [ 14, 0, 16, 16 ] },
|
||||||
|
"east": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 16 ], "rotation": 90 },
|
||||||
|
"south": { "texture": "#gearbox_top", "uv": [ 0, 16, 2, 0 ] },
|
||||||
|
"west": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 16 ], "rotation": 90 },
|
||||||
|
"up": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 2, 16 ] },
|
||||||
|
"down": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 2, 16 ] }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Side",
|
||||||
|
"from": [ 14, 0, 0 ],
|
||||||
|
"to": [ 16, 16, 16 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#gearbox_top", "uv": [ 0, 0, 2, 16 ] },
|
||||||
|
"east": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 16 ], "rotation": 90 },
|
||||||
|
"south": { "texture": "#gearbox_top", "uv": [ 14, 16, 16, 0 ] },
|
||||||
|
"west": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 16 ], "rotation": 90 },
|
||||||
|
"up": { "texture": "#translation_chassis_side", "uv": [ 14, 0, 16, 16 ] },
|
||||||
|
"down": { "texture": "#translation_chassis_side", "uv": [ 14, 0, 16, 16 ] }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Top",
|
||||||
|
"from": [ 2, 14, 0 ],
|
||||||
|
"to": [ 14, 16, 16 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#gearbox_top", "uv": [ 2, 0, 14, 2 ] },
|
||||||
|
"south": { "texture": "#gearbox_top", "uv": [ 2, 0, 14, 2 ] },
|
||||||
|
"up": { "texture": "#translation_chassis_side", "uv": [ 2, 0, 14, 16 ], "rotation": 180 },
|
||||||
|
"down": { "texture": "#translation_chassis_side", "uv": [ 2, 0, 14, 16 ] }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Indicator",
|
||||||
|
"from": [ 1, 10, 2 ],
|
||||||
|
"to": [ 15, 14, 14 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#clutch_off", "uv": [ 1, 6, 15, 10 ] },
|
||||||
|
"south": { "texture": "#clutch_off", "uv": [ 1, 6, 15, 10 ] },
|
||||||
|
"down": { "texture": "#gearbox_top", "uv": [ 1, 2, 15, 14 ] }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Side",
|
||||||
|
"from": [ 15.875, 0.062, 1.125 ],
|
||||||
|
"to": [ 17.875, 12.937, 14.875 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#gearbox_top", "uv": [ 0, 0, 2, 12.875 ] },
|
||||||
|
"east": { "texture": "#translation_chassis_side", "uv": [ 2, 1, 14, 15 ], "rotation": 90 },
|
||||||
|
"south": { "texture": "#gearbox_top", "uv": [ 14, 16, 16, 3 ] },
|
||||||
|
"up": { "texture": "#translation_chassis_side", "uv": [ 7, 1, 9, 15 ] },
|
||||||
|
"down": { "texture": "#translation_chassis_side", "uv": [ 7, 1, 9, 15 ] }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Side",
|
||||||
|
"from": [ -1.875, 0.062, 1.125 ],
|
||||||
|
"to": [ 0.125, 12.937, 14.875 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#gearbox_top", "uv": [ 14, 0, 16, 12.875 ] },
|
||||||
|
"south": { "texture": "#gearbox_top", "uv": [ 0, 16, 2, 3 ] },
|
||||||
|
"west": { "texture": "#translation_chassis_side", "uv": [ 2, 1, 14, 15 ], "rotation": 90 },
|
||||||
|
"up": { "texture": "#translation_chassis_side", "uv": [ 7, 1, 9, 15 ] },
|
||||||
|
"down": { "texture": "#translation_chassis_side", "uv": [ 7, 1, 9, 15 ] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "create:block/cart_assembler",
|
||||||
|
"textures": {
|
||||||
|
"clutch_off": "create:block/clutch_on"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
|
||||||
|
"textures": {
|
||||||
|
"translation_chassis_side": "create:block/translation_chassis_side"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"name": "Top",
|
||||||
|
"from": [ 0, 12, 0 ],
|
||||||
|
"to": [ 16, 16, 16 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 4 ] },
|
||||||
|
"east": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 4, 16 ], "rotation": 90 },
|
||||||
|
"south": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 4 ] },
|
||||||
|
"west": { "texture": "#translation_chassis_side", "uv": [ 12, 0, 16, 16 ], "rotation": 270 },
|
||||||
|
"up": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 16 ] },
|
||||||
|
"down": { "texture": "#translation_chassis_side", "uv": [ 0, 0, 16, 16 ] }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Inner",
|
||||||
|
"from": [ 4, 4, 4 ],
|
||||||
|
"to": [ 12, 12, 12 ],
|
||||||
|
"faces": {
|
||||||
|
"north": { "texture": "#translation_chassis_side", "uv": [ 4, 8, 12, 16 ] },
|
||||||
|
"east": { "texture": "#translation_chassis_side", "uv": [ 4, 8, 12, 16 ] },
|
||||||
|
"south": { "texture": "#translation_chassis_side", "uv": [ 4, 8, 12, 16 ] },
|
||||||
|
"west": { "texture": "#translation_chassis_side", "uv": [ 4, 8, 12, 16 ] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"parent": "create:block/cart_assembler"
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "create:item/motion_scarf"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "create:item/time_scarf"
|
||||||
|
}
|
||||||
|
}
|
BIN
src/main/resources/assets/create/textures/item/motion_scarf.png
Normal file
BIN
src/main/resources/assets/create/textures/item/motion_scarf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 603 B |
BIN
src/main/resources/assets/create/textures/item/time_scarf.png
Normal file
BIN
src/main/resources/assets/create/textures/item/time_scarf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 630 B |
6
src/main/resources/data/minecraft/tags/blocks/rails.json
Normal file
6
src/main/resources/data/minecraft/tags/blocks/rails.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"create:cart_assembler"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue