mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-23 03:18:06 +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.RotationChassisBlock;
|
||||
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.relays.ClutchBlock;
|
||||
import com.simibubi.create.modules.contraptions.relays.CogWheelBlock;
|
||||
|
@ -125,6 +127,8 @@ public enum AllBlocks {
|
|||
SAW(new SawBlock()),
|
||||
HARVESTER(new HarvesterBlock()),
|
||||
HARVESTER_BLADE(new HarvesterBladeBlock()),
|
||||
CART_ASSEMBLER(new CartAssemblerBlock()),
|
||||
MINECART_ANCHOR(new MinecartAnchorBlock()),
|
||||
|
||||
__LOGISTICS__(),
|
||||
CONTACT(new ContactBlock()),
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create;
|
|||
|
||||
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.CardboardBoxEntityRenderer;
|
||||
|
||||
|
@ -19,6 +21,7 @@ import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
|||
public enum AllEntities {
|
||||
|
||||
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)
|
||||
public static void registerRenderers() {
|
||||
RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(ContraptionEntity.class, ContraptionEntityRenderer::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -81,6 +81,8 @@ public enum AllItems {
|
|||
PROPELLER(ingredient()),
|
||||
CRUSHED_IRON(ingredient()),
|
||||
CRUSHED_GOLD(ingredient()),
|
||||
TIME_SCARF(ingredient()),
|
||||
MOTION_SCARF(ingredient()),
|
||||
|
||||
__LOGISTICS__(),
|
||||
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.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
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 mutable;
|
||||
|
||||
|
@ -23,66 +24,66 @@ public abstract class BufferManipulator {
|
|||
mutable.rewind();
|
||||
}
|
||||
|
||||
protected int vertexCount(ByteBuffer buffer) {
|
||||
protected static int vertexCount(ByteBuffer buffer) {
|
||||
return buffer.limit() / FORMAT_LENGTH;
|
||||
}
|
||||
|
||||
protected int getBufferPosition(int vertexIndex) {
|
||||
|
||||
protected static int getBufferPosition(int vertexIndex) {
|
||||
return vertexIndex * FORMAT_LENGTH;
|
||||
}
|
||||
|
||||
protected float getX(ByteBuffer buffer, int index) {
|
||||
|
||||
protected static float getX(ByteBuffer buffer, int 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);
|
||||
}
|
||||
|
||||
protected float getZ(ByteBuffer buffer, int index) {
|
||||
|
||||
protected static float getZ(ByteBuffer buffer, int index) {
|
||||
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);
|
||||
}
|
||||
|
||||
protected byte getG(ByteBuffer buffer, int index) {
|
||||
|
||||
protected static byte getG(ByteBuffer buffer, int index) {
|
||||
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);
|
||||
}
|
||||
|
||||
protected byte getA(ByteBuffer buffer, int index) {
|
||||
|
||||
protected static byte getA(ByteBuffer buffer, int index) {
|
||||
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);
|
||||
buffer.putFloat(pos, x);
|
||||
buffer.putFloat(pos + 4, y);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
buffer.put(bufferPosition + 12, r);
|
||||
buffer.put(bufferPosition + 13, g);
|
||||
|
@ -90,4 +91,35 @@ public abstract class BufferManipulator {
|
|||
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.BufferBuilder;
|
||||
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.VertexFormat;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -29,6 +30,22 @@ public class TessellatorHelper {
|
|||
Vec3d view = renderInfo.getProjectedView();
|
||||
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() {
|
||||
begin(DefaultVertexFormats.POSITION_TEX);
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create.foundation.utility;
|
|||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.nbt.DoubleNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
@ -36,4 +38,16 @@ public class VecHelper {
|
|||
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.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.MechanicalPistonTileEntityRenderer;
|
||||
|
||||
import net.minecraft.client.resources.ReloadListener;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
|
@ -19,7 +19,7 @@ public class CachedBufferReloader extends ReloadListener<String> {
|
|||
@Override
|
||||
protected void apply(String splashList, IResourceManager resourceManagerIn, IProfiler profilerIn) {
|
||||
KineticTileEntityRenderer.invalidateCache();
|
||||
MechanicalPistonTileEntityRenderer.invalidateCache();
|
||||
ContraptionRenderer.invalidateCache();
|
||||
MechanicalBearingTileEntityRenderer.invalidateCache();
|
||||
ColoredIndicatorRenderer.invalidateCache();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.modules.contraptions.receivers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
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.DirectionalBlock;
|
||||
import net.minecraft.block.material.PushReaction;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.state.StateContainer.Builder;
|
||||
|
@ -80,17 +80,17 @@ public class DrillBlock extends DirectionalKineticBlock
|
|||
|
||||
@Override
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
public void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
||||
DrillTileEntityRenderer.renderInConstruct(context, x, y, z, buffer);
|
||||
public ByteBuffer renderInConstruct(MovementContext context) {
|
||||
return DrillTileEntityRenderer.renderInConstruct(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPosition(MovementContext context) {
|
||||
Direction movement = context.getMovementDirection();
|
||||
BlockState block = context.state;
|
||||
|
||||
if (movement != block.get(FACING))
|
||||
return;
|
||||
|
||||
// BlockState block = context.state;
|
||||
// if (movement == block.get(FACING).getOpposite())
|
||||
// return;
|
||||
|
||||
World world = context.world;
|
||||
BlockPos pos = context.currentGridPos;
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create.modules.contraptions.receivers;
|
|||
|
||||
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||
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.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
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));
|
||||
}
|
||||
|
||||
public static void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
||||
public static ByteBuffer renderInConstruct(MovementContext context) {
|
||||
World world = context.world;
|
||||
BlockState state = context.state;
|
||||
BlockPos pos = context.currentGridPos;
|
||||
|
@ -35,12 +36,13 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer {
|
|||
final BlockState renderedState = getRenderedBlockState(state);
|
||||
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);
|
||||
float time = Animation.getWorldTime(Minecraft.getInstance().world,
|
||||
Minecraft.getInstance().getRenderPartialTicks());
|
||||
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;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
|
@ -14,7 +15,6 @@ import net.minecraft.block.CropsBlock;
|
|||
import net.minecraft.block.HorizontalBlock;
|
||||
import net.minecraft.block.SugarCaneBlock;
|
||||
import net.minecraft.block.material.PushReaction;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
@ -74,8 +74,8 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
|
|||
|
||||
@Override
|
||||
@OnlyIn(value = Dist.CLIENT)
|
||||
public void renderInConstruct(MovementContext context, double x, double y, double z, BufferBuilder buffer) {
|
||||
HarvesterTileEntityRenderer.renderInConstruct(context, x, y, z, buffer);
|
||||
public ByteBuffer renderInConstruct(MovementContext context) {
|
||||
return HarvesterTileEntityRenderer.renderInConstruct(context);
|
||||
}
|
||||
|
||||
@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;
|
||||
BlockState state = context.state;
|
||||
BlockPos pos = context.currentGridPos;
|
||||
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)
|
||||
speed = -speed;
|
||||
|
||||
|
||||
float time = Animation.getWorldTime(Minecraft.getInstance().world,
|
||||
Minecraft.getInstance().getRenderPartialTicks());
|
||||
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
|
||||
public void renderTileEntityFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks,
|
||||
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,
|
||||
BufferBuilder buffer) {
|
||||
public static ByteBuffer getVertexData(World world, BlockState state, BlockPos pos, double x, double y, double z,
|
||||
float angle) {
|
||||
if (!AllBlocks.HARVESTER.typeOf(state))
|
||||
return;
|
||||
|
||||
return ByteBuffer.wrap(new byte[] {});
|
||||
BlockState renderedState = AllBlocks.HARVESTER_BLADE.get().getDefaultState().with(HORIZONTAL_FACING,
|
||||
state.get(HORIZONTAL_FACING));
|
||||
|
||||
KineticTileEntityRenderer.cacheIfMissing(renderedState, world, HarvesterRenderer::new);
|
||||
HarvesterRenderer renderer = (HarvesterRenderer) KineticTileEntityRenderer.getBuffer(renderedState);
|
||||
buffer.putBulkData(renderer.getTransformed((float) x, (float) y, (float) z, angle, state.get(HORIZONTAL_FACING),
|
||||
state.getPackedLightmapCoords(world, pos)));
|
||||
ByteBuffer byteBuffer = renderer.getTransformed((float) x, (float) y, (float) z, angle,
|
||||
state.get(HORIZONTAL_FACING), state.getPackedLightmapCoords(world, pos));
|
||||
return byteBuffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
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.AXIS;
|
||||
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||
|
@ -14,6 +11,7 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
|
||||
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.modules.contraptions.receivers.SawBlock;
|
||||
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.FallingBlock;
|
||||
|
@ -34,47 +31,66 @@ import net.minecraft.nbt.FloatNBT;
|
|||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.state.properties.PistonType;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.Direction.AxisDirection;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||
|
||||
public class TranslationConstruct {
|
||||
public class Contraption {
|
||||
|
||||
protected Map<BlockPos, BlockInfo> blocks;
|
||||
protected List<MutablePair<BlockInfo, MovementContext>> actors;
|
||||
|
||||
protected AxisAlignedBB constructCollisionBox;
|
||||
protected AxisAlignedBB pistonCollisionBox;
|
||||
|
||||
protected Set<BlockPos> cachedColliders;
|
||||
protected Direction cachedColliderDirection;
|
||||
protected BlockPos anchor;
|
||||
|
||||
protected int extensionLength;
|
||||
protected int initialExtensionProgress;
|
||||
protected Direction orientation;
|
||||
|
||||
public TranslationConstruct() {
|
||||
public Contraption() {
|
||||
blocks = new HashMap<>();
|
||||
actors = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static TranslationConstruct movePistonAt(World world, BlockPos pos, Direction direction, boolean retract) {
|
||||
if (isFrozen())
|
||||
return null;
|
||||
TranslationConstruct construct = new TranslationConstruct();
|
||||
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 static List<BlockInfo> getChassisClusterAt(World world, BlockPos pos) {
|
||||
List<BlockPos> search = new LinkedList<>();
|
||||
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(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) {
|
||||
|
@ -101,86 +117,17 @@ public class TranslationConstruct {
|
|||
return cachedColliders;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
|
||||
protected boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
|
||||
List<BlockPos> frontier = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
constructCollisionBox = new AxisAlignedBB(pos.offset(direction, initialExtensionProgress));
|
||||
frontier.add(pos);
|
||||
anchor = pos;
|
||||
|
||||
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);
|
||||
}
|
||||
if (constructCollisionBox == null)
|
||||
constructCollisionBox = new AxisAlignedBB(pos);
|
||||
|
||||
frontier.add(pos);
|
||||
if (!addToInitialFrontier(world, pos, direction, frontier))
|
||||
return false;
|
||||
|
||||
for (int limit = 1000; limit > 0; limit--) {
|
||||
if (frontier.isEmpty())
|
||||
|
@ -192,6 +139,10 @@ public class TranslationConstruct {
|
|||
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,
|
||||
Set<BlockPos> visited) {
|
||||
visited.add(pos);
|
||||
|
@ -349,42 +300,8 @@ public class TranslationConstruct {
|
|||
return true;
|
||||
}
|
||||
|
||||
private static List<BlockInfo> getChassisClusterAt(World world, BlockPos pos) {
|
||||
List<BlockPos> search = new LinkedList<>();
|
||||
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 static boolean isChassis(BlockState state) {
|
||||
return TranslationChassisBlock.isChassis(state);
|
||||
}
|
||||
|
||||
private boolean notSupportive(World world, BlockPos pos, Direction facing) {
|
||||
|
@ -396,11 +313,7 @@ public class TranslationConstruct {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static boolean isChassis(BlockState state) {
|
||||
return TranslationChassisBlock.isChassis(state);
|
||||
}
|
||||
|
||||
private static boolean canPush(World world, BlockPos pos, Direction direction) {
|
||||
protected static boolean canPush(World world, BlockPos pos, Direction direction) {
|
||||
BlockState blockState = world.getBlockState(pos);
|
||||
if (isChassis(blockState))
|
||||
return true;
|
||||
|
@ -409,19 +322,15 @@ public class TranslationConstruct {
|
|||
return PistonBlock.canPush(blockState, world, pos, direction, true, direction);
|
||||
}
|
||||
|
||||
private void add(BlockPos pos, BlockInfo block) {
|
||||
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) {
|
||||
protected BlockInfo capture(World world, BlockPos pos) {
|
||||
BlockState blockstate = world.getBlockState(pos);
|
||||
if (AllBlocks.SAW.typeOf(blockstate))
|
||||
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);
|
||||
CompoundNBT compoundnbt = null;
|
||||
if (tileentity != null) {
|
||||
|
@ -430,17 +339,43 @@ public class TranslationConstruct {
|
|||
compoundnbt.remove("y");
|
||||
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() {
|
||||
return constructCollisionBox;
|
||||
}
|
||||
|
||||
public AxisAlignedBB getCollisionBoxBack() {
|
||||
return pistonCollisionBox;
|
||||
}
|
||||
|
||||
public CompoundNBT writeNBT() {
|
||||
CompoundNBT nbt = new CompoundNBT();
|
||||
ListNBT blocks = new ListNBT();
|
||||
|
@ -452,19 +387,22 @@ public class TranslationConstruct {
|
|||
c.put("Data", block.nbt);
|
||||
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) {
|
||||
ListNBT bb = writeAABB(constructCollisionBox);
|
||||
nbt.put("BoundsFront", bb);
|
||||
}
|
||||
|
||||
if (pistonCollisionBox != null) {
|
||||
ListNBT bb = writeAABB(pistonCollisionBox);
|
||||
nbt.put("BoundsBack", bb);
|
||||
}
|
||||
|
||||
nbt.put("Blocks", blocks);
|
||||
nbt.putInt("ExtensionLength", extensionLength);
|
||||
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
|
||||
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() {
|
||||
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;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
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.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
|
||||
public interface IHaveMovementBehavior {
|
||||
|
||||
|
@ -28,29 +34,50 @@ public interface IHaveMovementBehavior {
|
|||
public class MovementContext {
|
||||
|
||||
public BlockPos currentGridPos;
|
||||
public Vec3d movementVec;
|
||||
public Vec3d motion;
|
||||
public float movementSpeedModifier = 1;
|
||||
|
||||
public MoverType moverType;
|
||||
public Object mover;
|
||||
public World world;
|
||||
public BlockState state;
|
||||
|
||||
public MovementContext(World world, BlockState state, MoverType moverType, Object mover) {
|
||||
this.world = world;
|
||||
public MovementContext(BlockState state, MoverType moverType) {
|
||||
this.state = state;
|
||||
this.moverType = moverType;
|
||||
this.mover = mover;
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
|
||||
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.Iterator;
|
||||
|
@ -11,17 +12,14 @@ import com.simibubi.create.AllBlocks;
|
|||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.Create;
|
||||
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.MoverType;
|
||||
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
|
@ -34,7 +32,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
|||
|
||||
public class MechanicalPistonTileEntity extends KineticTileEntity implements ITickableTileEntity {
|
||||
|
||||
protected TranslationConstruct movingConstruct;
|
||||
protected PistonContraption movedContraption;
|
||||
protected float offset;
|
||||
protected boolean running;
|
||||
protected boolean assembleNextTick;
|
||||
|
@ -73,8 +71,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
public CompoundNBT write(CompoundNBT tag) {
|
||||
tag.putBoolean("Running", running);
|
||||
tag.putFloat("Offset", offset);
|
||||
if (running && !TranslationConstruct.isFrozen())
|
||||
tag.put("Construct", movingConstruct.writeNBT());
|
||||
if (running && !PistonContraption.isFrozen())
|
||||
tag.put("Construct", movedContraption.writeNBT());
|
||||
|
||||
return super.write(tag);
|
||||
}
|
||||
|
@ -83,12 +81,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
public void read(CompoundNBT tag) {
|
||||
running = tag.getBoolean("Running");
|
||||
offset = tag.getFloat("Offset");
|
||||
if (running && !TranslationConstruct.isFrozen()) {
|
||||
movingConstruct = TranslationConstruct.fromNBT(tag.getCompound("Construct"));
|
||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors) {
|
||||
MovementContext context = new MovementContext(world, pair.left.state, MoverType.PISTON, this);
|
||||
if (running && !PistonContraption.isFrozen()) {
|
||||
movedContraption = new PistonContraption();
|
||||
movedContraption.readNBT(tag.getCompound("Construct"));
|
||||
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);
|
||||
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));
|
||||
pair.setRight(context);
|
||||
}
|
||||
|
@ -98,12 +98,12 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
}
|
||||
|
||||
protected void onBlockVisited(float newOffset) {
|
||||
if (TranslationConstruct.isFrozen())
|
||||
if (PistonContraption.isFrozen())
|
||||
return;
|
||||
|
||||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||
|
||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors) {
|
||||
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
|
||||
BlockInfo block = pair.left;
|
||||
MovementContext context = pair.right;
|
||||
|
||||
|
@ -120,39 +120,40 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||
|
||||
// Collect Construct
|
||||
movingConstruct = TranslationConstruct.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
|
||||
if (movingConstruct == null)
|
||||
movedContraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
|
||||
if (movedContraption == null)
|
||||
return;
|
||||
|
||||
// Check if not at limit already
|
||||
float resultingOffset = movingConstruct.initialExtensionProgress + getMovementSpeed();
|
||||
if (resultingOffset <= 0 || resultingOffset >= movingConstruct.extensionLength) {
|
||||
movingConstruct = null;
|
||||
float resultingOffset = movedContraption.initialExtensionProgress + getMovementSpeed();
|
||||
if (resultingOffset <= 0 || resultingOffset >= movedContraption.extensionLength) {
|
||||
movedContraption = null;
|
||||
return;
|
||||
}
|
||||
if (hasBlockCollisions(resultingOffset + .5f)) {
|
||||
movingConstruct = null;
|
||||
movedContraption = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Run
|
||||
running = true;
|
||||
offset = movingConstruct.initialExtensionProgress;
|
||||
offset = movedContraption.initialExtensionProgress;
|
||||
if (!world.isRemote)
|
||||
Create.constructHandler.add(this);
|
||||
|
||||
sendData();
|
||||
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66);
|
||||
for (BlockInfo block : movingConstruct.blocks.values()) {
|
||||
BlockPos startPos = block.pos.offset(direction, movingConstruct.initialExtensionProgress);
|
||||
for (BlockInfo block : movedContraption.blocks.values()) {
|
||||
BlockPos startPos = block.pos.offset(direction, movedContraption.initialExtensionProgress);
|
||||
if (startPos.equals(pos))
|
||||
continue;
|
||||
getWorld().setBlockState(startPos, Blocks.AIR.getDefaultState(), 67);
|
||||
}
|
||||
|
||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors) {
|
||||
MovementContext context = new MovementContext(world, pair.left.state, MoverType.PISTON, this);
|
||||
context.movementVec = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
|
||||
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
|
||||
MovementContext context = new MovementContext(pair.left.state, MoverType.PISTON);
|
||||
context.world = world;
|
||||
context.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
|
||||
context.currentGridPos = pair.left.pos.offset(direction, getModulatedOffset(offset));
|
||||
pair.setRight(context);
|
||||
}
|
||||
|
@ -167,38 +168,19 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
||||
if (!removed)
|
||||
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
|
||||
|
||||
for (BlockInfo block : movingConstruct.blocks.values()) {
|
||||
BlockPos targetPos = block.pos.offset(direction, getModulatedOffset(offset));
|
||||
BlockState state = block.state;
|
||||
if (targetPos.equals(pos)) {
|
||||
if (!AllBlocks.PISTON_POLE.typeOf(state) && !removed)
|
||||
getWorld().setBlockState(pos,
|
||||
getBlockState().with(MechanicalPistonBlock.STATE, PistonState.RETRACTED), 3);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
movedContraption.disassemble(world, BlockPos.ZERO.offset(direction, getModulatedOffset(offset)),
|
||||
(targetPos, state) -> {
|
||||
if (targetPos.equals(pos)) {
|
||||
if (!AllBlocks.PISTON_POLE.typeOf(state) && !removed)
|
||||
world.setBlockState(pos, getBlockState().with(STATE, PistonState.RETRACTED), 3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
running = false;
|
||||
if (!world.isRemote)
|
||||
Create.constructHandler.remove(this);
|
||||
movingConstruct = null;
|
||||
movedContraption = null;
|
||||
sendData();
|
||||
|
||||
if (removed)
|
||||
|
@ -213,10 +195,10 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
if (speed == 0)
|
||||
disassembleConstruct();
|
||||
else {
|
||||
for (MutablePair<BlockInfo, MovementContext> pair : movingConstruct.actors)
|
||||
pair.right.movementVec = new Vec3d(
|
||||
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors())
|
||||
pair.right.motion = new Vec3d(
|
||||
getBlockState().get(BlockStateProperties.FACING).getDirectionVec())
|
||||
.scale(getMovementSpeed()).normalize();
|
||||
.scale(getMovementSpeed());
|
||||
sendData();
|
||||
}
|
||||
return;
|
||||
|
@ -257,14 +239,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
|
||||
offset = newOffset;
|
||||
|
||||
if (offset <= 0 || offset >= movingConstruct.extensionLength) {
|
||||
if (offset <= 0 || offset >= movedContraption.extensionLength) {
|
||||
disassembleConstruct();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasBlockCollisions(float newOffset) {
|
||||
if (TranslationConstruct.isFrozen())
|
||||
if (PistonContraption.isFrozen())
|
||||
return true;
|
||||
|
||||
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
|
||||
|
@ -280,7 +262,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
|
||||
if (otherPiston == this)
|
||||
continue;
|
||||
if (!otherPiston.running || otherPiston.movingConstruct == null) {
|
||||
if (!otherPiston.running || otherPiston.movedContraption == null) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
@ -291,10 +273,10 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
|
||||
getModulatedOffset(otherPiston.offset));
|
||||
|
||||
for (AxisAlignedBB tBB : Arrays.asList(movingConstruct.constructCollisionBox,
|
||||
movingConstruct.pistonCollisionBox)) {
|
||||
for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movingConstruct.constructCollisionBox,
|
||||
otherPiston.movingConstruct.pistonCollisionBox)) {
|
||||
for (AxisAlignedBB tBB : Arrays.asList(movedContraption.constructCollisionBox,
|
||||
movedContraption.pistonCollisionBox)) {
|
||||
for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movedContraption.constructCollisionBox,
|
||||
otherPiston.movedContraption.pistonCollisionBox)) {
|
||||
if (tBB == null || oBB == null)
|
||||
continue;
|
||||
|
||||
|
@ -306,9 +288,9 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
|
||||
if (thisBB.intersects(otherBB)) {
|
||||
boolean actuallyColliding = false;
|
||||
for (BlockPos colliderPos : movingConstruct.getColliders(world, movementDirection)) {
|
||||
for (BlockPos colliderPos : movedContraption.getColliders(world, movementDirection)) {
|
||||
colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
|
||||
if (!otherPiston.movingConstruct.blocks.containsKey(colliderPos))
|
||||
if (!otherPiston.movedContraption.blocks.containsKey(colliderPos))
|
||||
continue;
|
||||
actuallyColliding = true;
|
||||
}
|
||||
|
@ -327,7 +309,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
return false;
|
||||
|
||||
// Other Blocks in world
|
||||
for (BlockPos pos : movingConstruct.getColliders(world,
|
||||
for (BlockPos pos : movedContraption.getColliders(world,
|
||||
getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
|
||||
BlockPos colliderPos = pos.add(relativePos);
|
||||
|
||||
|
@ -342,7 +324,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
}
|
||||
|
||||
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() {
|
||||
|
@ -354,7 +336,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
|
|||
|
||||
public Vec3d getConstructOffset(float partialTicks) {
|
||||
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
|
||||
movingConstruct.extensionLength);
|
||||
movedContraption.extensionLength);
|
||||
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,17 @@
|
|||
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.foundation.utility.PlacementSimulationWorld;
|
||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior.MovementContext;
|
||||
|
||||
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.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
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 {
|
||||
|
||||
protected static Cache<TranslationConstruct, TranslationConstructVertexBuffer> cachedConstructs;
|
||||
protected static PlacementSimulationWorld renderWorld;
|
||||
|
||||
@Override
|
||||
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
|
||||
int destroyStage, BufferBuilder buffer) {
|
||||
|
@ -44,58 +23,21 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
|
|||
if (!pistonTe.running)
|
||||
return;
|
||||
|
||||
cacheConstructIfMissing(pistonTe.movingConstruct);
|
||||
renderConstructFromCache(pistonTe.movingConstruct, 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);
|
||||
}
|
||||
ContraptionRenderer.cacheContraptionIfMissing(pistonTe.movedContraption);
|
||||
renderConstructFromCache(pistonTe.movedContraption, pistonTe, x, y, z, partialTicks, 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) {
|
||||
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 TranslationConstructVertexBuffer(builder.getByteBuffer()));
|
||||
}
|
||||
|
||||
protected void renderConstructFromCache(TranslationConstruct c, MechanicalPistonTileEntity te, double x, double y,
|
||||
double z, float partialTicks, BufferBuilder buffer) {
|
||||
protected void renderConstructFromCache(Contraption c, MechanicalPistonTileEntity te, double x, double y, double z,
|
||||
float partialTicks, BufferBuilder buffer) {
|
||||
final Vec3d offset = te.getConstructOffset(partialTicks);
|
||||
buffer.putBulkData(cachedConstructs.getIfPresent(c).getTransformed(te,
|
||||
(float) (x + offset.x - te.getPos().getX()), (float) (y + offset.y - te.getPos().getY()),
|
||||
(float) (z + offset.z - te.getPos().getZ()), offset));
|
||||
float xPos = (float) (x - te.getPos().getX());
|
||||
float yPos = (float) (y - te.getPos().getY());
|
||||
float zPos = (float) (z - te.getPos().getZ());
|
||||
buffer.putBulkData(ContraptionRenderer.get(c).getTranslated(te.getWorld(), xPos, yPos, zPos, offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -104,9 +46,4 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
|
|||
((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,
|
||||
float newOffset) {
|
||||
if (TranslationConstruct.isFrozen())
|
||||
if (PistonContraption.isFrozen())
|
||||
return;
|
||||
|
||||
World world = te.getWorld();
|
||||
Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
|
||||
TranslationConstruct construct = te.movingConstruct;
|
||||
Contraption construct = te.movedContraption;
|
||||
|
||||
// if (world.isRemote) {
|
||||
// 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.foundation.block.ProperDirectionalBlock;
|
||||
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.BlockState;
|
||||
|
@ -109,11 +108,9 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen
|
|||
Direction direction = block.get(FACING);
|
||||
if (!hasValidContact(world, pos, direction))
|
||||
return;
|
||||
if (context.moverType != MoverType.PISTON)
|
||||
return;
|
||||
|
||||
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.getPendingBlockTicks().scheduleTick(pos.offset(direction), this, ticksToStayActive, TickPriority.NORMAL);
|
||||
return;
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.mojang.blaze3d.platform.GlStateManager;
|
|||
|
||||
import net.minecraft.block.Blocks;
|
||||
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.EntityRendererManager;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
|
@ -24,18 +23,6 @@ public class CardboardBoxEntityRenderer extends EntityRenderer<CardboardBoxEntit
|
|||
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
|
||||
public void doRender(CardboardBoxEntity entity, double x, double y, double z, float entityYaw, float partialTicks) {
|
||||
IBakedModel model = getModelForBox(entity);
|
||||
|
|
|
@ -5,13 +5,12 @@ import org.lwjgl.opengl.GL11;
|
|||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
|
||||
import com.simibubi.create.foundation.utility.TessellatorHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
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.vertex.DefaultVertexFormats;
|
||||
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,
|
||||
int destroyStage) {
|
||||
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();
|
||||
TessellatorHelper.prepareFastRender();
|
||||
|
||||
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();
|
||||
BlockState blockState = tileEntityIn.getBlockState();
|
||||
BlockState renderedState = AllBlocks.LOGISTICIANS_TABLE_INDICATOR.get().getDefaultState();
|
||||
|
@ -63,5 +51,4 @@ public class LogisticiansTableTileEntityRenderer extends TileEntityRenderer<Logi
|
|||
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.crushed_iron": "Crushed Iron 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_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