Merge branch 'unified-contraptions' of https://github.com/simibubi/Create into 0.2

This commit is contained in:
simibubi 2019-12-12 11:58:29 +01:00
commit 785d77a59d
63 changed files with 1295 additions and 1592 deletions

View file

@ -9,17 +9,17 @@ import com.simibubi.create.foundation.block.RenderUtilityDirectionalBlock;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.IModule;
import com.simibubi.create.modules.contraptions.components.actors.DrillBlock;
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock;
import com.simibubi.create.modules.contraptions.components.actors.DrillBlock.DrillHeadBlock;
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock;
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock.HarvesterBladeBlock;
import com.simibubi.create.modules.contraptions.components.constructs.LinearChassisBlock;
import com.simibubi.create.modules.contraptions.components.constructs.RadialChassisBlock;
import com.simibubi.create.modules.contraptions.components.constructs.bearing.MechanicalBearingBlock;
import com.simibubi.create.modules.contraptions.components.constructs.mounted.CartAssemblerBlock;
import com.simibubi.create.modules.contraptions.components.constructs.mounted.CartAssemblerBlock.MinecartAnchorBlock;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonBlock;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonHeadBlock;
import com.simibubi.create.modules.contraptions.components.constructs.piston.PistonPoleBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.LinearChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.RadialChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerBlock.MinecartAnchorBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonHeadBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonPoleBlock;
import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCrafterBlock;
import com.simibubi.create.modules.contraptions.components.crusher.CrushingWheelBlock;
import com.simibubi.create.modules.contraptions.components.crusher.CrushingWheelControllerBlock;

View file

@ -2,8 +2,8 @@ package com.simibubi.create;
import java.util.function.Function;
import com.simibubi.create.modules.contraptions.components.constructs.mounted.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.constructs.mounted.ContraptionEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntityRenderer;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntityRenderer;

View file

@ -6,7 +6,7 @@ import java.util.function.Supplier;
import com.simibubi.create.foundation.packet.NbtPacket;
import com.simibubi.create.foundation.packet.SimplePacketBase;
import com.simibubi.create.modules.contraptions.components.constructs.ConfigureChassisPacket;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ConfigureChassisPacket;
import com.simibubi.create.modules.contraptions.components.mixer.ConfigureMixerPacket;
import com.simibubi.create.modules.contraptions.components.motor.ConfigureMotorPacket;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunBeamPacket;

View file

@ -8,11 +8,11 @@ import com.simibubi.create.modules.contraptions.components.actors.DrillTileEntit
import com.simibubi.create.modules.contraptions.components.actors.DrillTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.actors.HarvesterTileEntity;
import com.simibubi.create.modules.contraptions.components.actors.HarvesterTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.constructs.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.constructs.bearing.MechanicalBearingTileEntity;
import com.simibubi.create.modules.contraptions.components.constructs.bearing.MechanicalBearingTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonTileEntity;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCrafterTileEntity;
import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCrafterTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.crusher.CrushingWheelControllerTileEntity;

View file

@ -6,7 +6,6 @@ import org.apache.logging.log4j.Logger;
import com.simibubi.create.foundation.world.OreGeneration;
import com.simibubi.create.modules.ModuleLoadedCondition;
import com.simibubi.create.modules.contraptions.TorquePropagator;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MovingConstructHandler;
import com.simibubi.create.modules.logistics.FrequencyHandler;
import com.simibubi.create.modules.logistics.management.LogisticalNetworkHandler;
import com.simibubi.create.modules.logistics.transport.villager.LogisticianHandler;
@ -42,7 +41,6 @@ public class Create {
public static ItemGroup creativeTab = new CreateItemGroup();
public static ServerSchematicLoader schematicReceiver;
public static FrequencyHandler frequencyHandler;
public static MovingConstructHandler constructHandler;
public static LogisticalNetworkHandler logisticalNetworkHandler;
public static TorquePropagator torquePropagator;
public static LogisticianHandler logisticianHandler;
@ -74,7 +72,6 @@ public class Create {
public static void init(final FMLCommonSetupEvent event) {
schematicReceiver = new ServerSchematicLoader();
frequencyHandler = new FrequencyHandler();
constructHandler = new MovingConstructHandler();
logisticalNetworkHandler = new LogisticalNetworkHandler();
torquePropagator = new TorquePropagator();

View file

@ -13,7 +13,7 @@ import com.simibubi.create.foundation.block.SpriteShifter.SpriteShiftEntry;
import com.simibubi.create.foundation.utility.SuperByteBufferCache;
import com.simibubi.create.modules.contraptions.WrenchModel;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.constructs.ContraptionRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionRenderer;
import com.simibubi.create.modules.curiosities.deforester.DeforesterModel;
import com.simibubi.create.modules.curiosities.partialWindows.WindowInABlockModel;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunModel;

View file

@ -44,7 +44,6 @@ public class Events {
public static void onLoadWorld(WorldEvent.Load event) {
IWorld world = event.getWorld();
Create.frequencyHandler.onLoadWorld(world);
Create.constructHandler.onLoadWorld(world);
Create.logisticalNetworkHandler.onLoadWorld(world);
Create.torquePropagator.onLoadWorld(world);
}
@ -53,7 +52,6 @@ public class Events {
public static void onUnloadWorld(WorldEvent.Unload event) {
IWorld world = event.getWorld();
Create.frequencyHandler.onUnloadWorld(world);
Create.constructHandler.onUnloadWorld(world);
Create.logisticalNetworkHandler.onUnloadWorld(world);
Create.torquePropagator.onUnloadWorld(world);
}

View file

@ -1,7 +1,6 @@
package com.simibubi.create;
import com.simibubi.create.foundation.block.SpriteShifter;
import com.simibubi.create.modules.contraptions.components.constructs.bearing.MechanicalBearingTileEntityRenderer;
import net.minecraft.client.resources.ReloadListener;
import net.minecraft.profiler.IProfiler;
@ -16,7 +15,6 @@ public class ResourceReloadHandler extends ReloadListener<String> {
@Override
protected void apply(String splashList, IResourceManager resourceManagerIn, IProfiler profilerIn) {
MechanicalBearingTileEntityRenderer.invalidateCache();
SpriteShifter.reloadUVs();
CreateClient.bufferCache.invalidate();
}

View file

@ -1,5 +1,9 @@
package com.simibubi.create.foundation.utility;
import static net.minecraft.block.Block.makeCuboidShape;
import java.util.Arrays;
import net.minecraft.block.Blocks;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.block.PistonHeadBlock;
@ -9,10 +13,6 @@ import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import java.util.Arrays;
import static net.minecraft.block.Block.makeCuboidShape;
public class AllShapes {
public static final VoxelShaper

View file

@ -1,159 +0,0 @@
package com.simibubi.create.foundation.utility;
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;
@Deprecated
public abstract class BufferManipulator {
public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize();
protected ByteBuffer original;
protected ByteBuffer mutable;
public BufferManipulator(ByteBuffer original) {
original.rewind();
this.original = original;
this.mutable = GLAllocation.createDirectByteBuffer(original.capacity());
this.mutable.order(original.order());
this.mutable.limit(original.limit());
mutable.put(this.original);
mutable.rewind();
}
protected static int vertexCount(ByteBuffer buffer) {
return buffer.limit() / FORMAT_LENGTH;
}
protected static int getBufferPosition(int vertexIndex) {
return vertexIndex * FORMAT_LENGTH;
}
protected static float getX(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index));
}
protected static float getY(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index) + 4);
}
protected static float getZ(ByteBuffer buffer, int index) {
return buffer.getFloat(getBufferPosition(index) + 8);
}
protected static byte getR(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 12);
}
protected static byte getG(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 13);
}
protected static byte getB(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 14);
}
protected static byte getA(ByteBuffer buffer, int index) {
return buffer.get(getBufferPosition(index) + 15);
}
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 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 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 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 static void putLight(ByteBuffer buffer, int index, int packedLight) {
buffer.putInt(getBufferPosition(index) + 24, packedLight);
}
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);
buffer.put(bufferPosition + 14, b);
buffer.put(bufferPosition + 15, a);
}
public ByteBuffer getTranslated(float xIn, float yIn, float zIn, int packedLightCoords) {
original.rewind();
mutable.rewind();
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + xIn, getY(original, vertex) + yIn,
getZ(original, vertex) + zIn);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
public static ByteBuffer remanipulateBuffer(ByteBuffer buffer, float x, float y, float z, float xOrigin,
float yOrigin, float zOrigin, float yaw, float pitch) {
buffer.rewind();
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;
}
public static ByteBuffer recolorBuffer(ByteBuffer buffer, int color) {
buffer.rewind();
boolean defaultColor = color == -1;
int b = defaultColor ? 128 : color & 0xFF;
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
for (int vertex = 0; vertex < vertexCount(buffer); vertex++) {
float lum = 1;
int r2 = (int) (r * lum);
int g2 = (int) (g * lum);
int b2 = (int) (b * lum);
putColor(buffer, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
}
return buffer;
}
}

View file

@ -31,6 +31,7 @@ public class SuperByteBuffer {
// Vertex Lighting
private boolean shouldLight;
private IVertexLighter vertexLighter;
private float lightOffsetX, lightOffsetY, lightOffsetZ;
private int packedLightCoords;
// Vertex Coloring
@ -84,7 +85,8 @@ public class SuperByteBuffer {
if (shouldLight) {
if (vertexLighter != null)
putLight(mutable, vertex, vertexLighter.getPackedLight(x2, y2, z2));
putLight(mutable, vertex,
vertexLighter.getPackedLight(x2 + lightOffsetX, y2 + lightOffsetY, z2 + lightOffsetZ));
else
putLight(mutable, vertex, packedLightCoords);
}
@ -153,6 +155,7 @@ public class SuperByteBuffer {
public SuperByteBuffer light(int packedLightCoords) {
shouldLight = true;
vertexLighter = null;
this.packedLightCoords = packedLightCoords;
return this;
}
@ -163,6 +166,13 @@ public class SuperByteBuffer {
return this;
}
public SuperByteBuffer offsetLighting(double x, double y, double z) {
lightOffsetX = (float) x;
lightOffsetY = (float) y;
lightOffsetZ = (float) z;
return this;
}
public SuperByteBuffer color(int color) {
shouldColor = true;
r = ((color >> 16) & 0xFF);

View file

@ -4,6 +4,7 @@ import java.util.Random;
import net.minecraft.nbt.DoubleNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -11,9 +12,15 @@ import net.minecraft.util.math.Vec3i;
public class VecHelper {
public static Vec3d rotate(Vec3d vec, float deg, Axis axis) {
float angle = (float) (deg / 180f * Math.PI);
public static Vec3d rotate(Vec3d vec, double xRot, double yRot, double zRot) {
return rotate(rotate(rotate(vec, xRot, Axis.X), yRot, Axis.Y), zRot, Axis.Z);
}
public static Vec3d rotate(Vec3d vec, double deg, Axis axis) {
if (deg == 0)
return vec;
float angle = (float) (deg / 180f * Math.PI);
double sin = MathHelper.sin(angle);
double cos = MathHelper.cos(angle);
double x = vec.x;
@ -29,6 +36,10 @@ public class VecHelper {
return vec;
}
public static boolean isVecPointingTowards(Vec3d vec, Direction direction) {
return new Vec3d(direction.getDirectionVec()).distanceTo(vec.normalize()) < .75;
}
public static Vec3d getCenterOf(Vec3i pos) {
return new Vec3d(pos).add(.5f, .5f, .5f);
}

View file

@ -1,6 +1,11 @@
package com.simibubi.create.foundation.world;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import com.simibubi.create.AllBlocks;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.world.biome.Biome;
@ -12,10 +17,6 @@ import net.minecraft.world.gen.placement.CountRangeConfig;
import net.minecraft.world.gen.placement.Placement;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public enum OreGeneration {
TEST_BLOB_1(new BasicOreGenConfig(Blocks.EMERALD_BLOCK, 25, 2, 128)),

View file

@ -26,8 +26,8 @@ import net.minecraft.particles.RedstoneParticleData;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.server.ServerWorld;

View file

@ -4,10 +4,11 @@ import java.util.List;
import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -85,18 +86,22 @@ public class DrillBlock extends DirectionalKineticBlock
}
@Override
public void visitPosition(MovementContext context) {
Direction movement = context.getMovementDirection();
// BlockState block = context.state;
// if (movement == block.get(FACING).getOpposite())
// return;
public boolean isActive(MovementContext context) {
return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.get(FACING).getOpposite());
}
@Override
public Vec3d getActiveAreaOffset(MovementContext context) {
return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f);
}
@Override
public void visitNewPosition(MovementContext context, BlockPos pos) {
World world = context.world;
BlockPos pos = context.currentGridPos;
pos = pos.offset(movement);
BlockState stateVisited = world.getBlockState(pos);
if (world.isRemote)
return;
if (stateVisited.getCollisionShape(world, pos).isEmpty())
return;
if (stateVisited.getBlockHardness(world, pos) == -1)
@ -108,8 +113,7 @@ public class DrillBlock extends DirectionalKineticBlock
for (ItemStack stack : drops) {
ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack);
itemEntity.setMotion(
new Vec3d(movement.getDirectionVec()).add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f));
itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f));
world.addEntity(itemEntity);
}
}

View file

@ -6,10 +6,11 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VecHelper;
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.components.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction.Axis;
@ -29,7 +30,9 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer {
BlockState state = context.state;
SuperByteBuffer buffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, getRenderedBlockState(state));
float speed = (float) (context.getMovementDirection() == state.get(FACING) ? context.getAnimationSpeed() : 0);
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(FACING).getOpposite())
? context.getAnimationSpeed()
: 0);
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
float time = AnimationTickHolder.getRenderTick();
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);

View file

@ -4,9 +4,10 @@ import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -105,18 +106,25 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
}
@Override
public void visitPosition(MovementContext context) {
Direction movement = context.getMovementDirection();
public boolean isActive(MovementContext context) {
return !VecHelper.isVecPointingTowards(context.relativeMotion,
context.state.get(HORIZONTAL_FACING).getOpposite());
}
@Override
public Vec3d getActiveAreaOffset(MovementContext context) {
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5);
}
@Override
public void visitNewPosition(MovementContext context, BlockPos pos) {
World world = context.world;
BlockState block = context.state;
BlockPos pos = context.currentGridPos;
if (movement != block.get(HORIZONTAL_FACING))
return;
BlockState stateVisited = world.getBlockState(pos);
boolean notCropButCuttable = false;
if (world.isRemote)
return;
if (stateVisited.getBlock() == Blocks.SUGAR_CANE) {
notCropButCuttable = true;
pos = pos.up();
@ -141,8 +149,7 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
seedSubtracted = true;
}
ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack);
itemEntity.setMotion(
new Vec3d(movement.getDirectionVec()).add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f));
itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f));
world.addEntity(itemEntity);
}
}

View file

@ -7,7 +7,8 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
@ -28,12 +29,9 @@ public class HarvesterTileEntityRenderer extends TileEntityRenderer<HarvesterTil
public static SuperByteBuffer renderInContraption(MovementContext context) {
BlockState state = context.state;
Direction facing = context.getMovementDirection();
float speed = (float) (facing == state.get(HORIZONTAL_FACING)
? context.getAnimationSpeed() * facing.getAxisDirection().getOffset()
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(HORIZONTAL_FACING).getOpposite())
? context.getAnimationSpeed() * state.get(HORIZONTAL_FACING).getAxisDirection().getOffset()
: 0);
if (facing.getAxis() == Axis.X)
speed = -speed;
float time = AnimationTickHolder.getRenderTick();
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);

View file

@ -1,83 +0,0 @@
package com.simibubi.create.modules.contraptions.components.constructs;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonTileEntity;
import net.minecraft.block.BlockState;
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 {
public enum MoverType {
PISTON, BEARING, MINECART;
}
default void visitPosition(MovementContext context) {
}
default void tick(MechanicalPistonTileEntity piston) {
}
default boolean hasSpecialRenderer() {
return false;
}
public class MovementContext {
public BlockPos currentGridPos;
public Vec3d motion;
public float movementSpeedModifier = 1;
public MoverType moverType;
public World world;
public BlockState state;
public MovementContext(BlockState state, MoverType moverType) {
this.state = state;
this.moverType = moverType;
}
public Direction getMovementDirection() {
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 SuperByteBuffer renderInContraption(MovementContext context) {
return null;
}
}

View file

@ -1,108 +0,0 @@
package com.simibubi.create.modules.contraptions.components.constructs.bearing;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
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.Direction;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.client.model.data.EmptyModelData;
public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRenderer {
protected static Cache<RotationConstruct, RotationConstructVertexBuffer> cachedConstructs;
protected static PlacementSimulationWorld renderWorld;
@Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
MechanicalBearingTileEntity bearingTe = (MechanicalBearingTileEntity) te;
final Direction facing = te.getBlockState().get(BlockStateProperties.FACING);
BlockState capState = AllBlocks.MECHANICAL_BEARING_TOP.get().getDefaultState().with(BlockStateProperties.FACING,
facing);
SuperByteBuffer superBuffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, capState);
float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks);
kineticRotationTransform(superBuffer, bearingTe, facing.getAxis(), interpolatedAngle, getWorld());
superBuffer.translate(x, y, z).renderInto(buffer);
if (!bearingTe.running)
return;
cacheConstructIfMissing(bearingTe.movingConstruct);
renderConstructFromCache(bearingTe.movingConstruct, bearingTe, x, y, z, partialTicks, buffer);
}
protected void cacheConstructIfMissing(RotationConstruct 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 RotationConstructVertexBuffer(builder.getByteBuffer()));
}
protected void renderConstructFromCache(RotationConstruct c, MechanicalBearingTileEntity te, double x, double y,
double z, float partialTicks, BufferBuilder buffer) {
float zfightBonus = 1 / 128f;
Direction direction = te.getBlockState().get(BlockStateProperties.FACING);
Vec3i vec = direction.getDirectionVec();
buffer.putBulkData(cachedConstructs.getIfPresent(c).getTransformed(te, (float) (x) + vec.getX() * zfightBonus,
(float) (y) + vec.getY() * zfightBonus, (float) (z) + vec.getZ() * zfightBonus,
te.getInterpolatedAngle(partialTicks), direction.getAxis()));
}
@Override
protected BlockState getRenderedBlockState(KineticTileEntity te) {
return AllBlocks.SHAFT_HALF.get().getDefaultState().with(BlockStateProperties.FACING,
te.getBlockState().get(BlockStateProperties.FACING).getOpposite());
}
public static void invalidateCache() {
if (cachedConstructs != null)
cachedConstructs.invalidateAll();
}
}

View file

@ -1,212 +0,0 @@
package com.simibubi.create.modules.contraptions.components.constructs.bearing;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.simibubi.create.AllBlockTags;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.contraptions.components.constructs.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.constructs.RadialChassisBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.PistonBlock;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class RotationConstruct {
protected Map<BlockPos, BlockInfo> blocks;
protected int sailBlocks;
public RotationConstruct() {
blocks = new HashMap<>();
sailBlocks = 0;
}
public static RotationConstruct getAttachedForRotating(World world, BlockPos pos, Direction direction) {
RotationConstruct construct = new RotationConstruct();
if (!construct.collectAttached(world, pos, direction))
return null;
return construct;
}
public int getSailBlocks() {
return sailBlocks;
}
protected boolean collectAttached(World world, BlockPos pos, Direction direction) {
if (isFrozen())
return false;
// Find chassis
List<BlockInfo> chassis = collectChassis(world, pos, direction);
if (chassis == null)
return false;
// Get single block
if (chassis.isEmpty()) {
BlockPos blockPos = pos.offset(direction);
BlockState state = world.getBlockState(pos.offset(direction));
if (state.getMaterial().isReplaceable() || state.isAir(world, blockPos))
return true;
if (state.getCollisionShape(world, blockPos).isEmpty())
return true;
if (!canRotate(world, blockPos, direction))
return false;
blocks.put(blockPos, new BlockInfo(blockPos.subtract(pos), state, null));
// Get attached blocks by chassis
} else {
List<BlockInfo> attachedBlocksByChassis = getAttachedBlocksByChassis(world, direction, chassis);
if (attachedBlocksByChassis == null)
return false;
attachedBlocksByChassis.forEach(info -> {
if (isSailBlock(info.state))
sailBlocks++;
blocks.put(info.pos, new BlockInfo(info.pos.subtract(pos), info.state, info.nbt));
});
}
return true;
}
private List<BlockInfo> getAttachedBlocksByChassis(World world, Direction direction, List<BlockInfo> chassis) {
List<BlockInfo> blocks = new ArrayList<>();
RadialChassisBlock def = (RadialChassisBlock) AllBlocks.ROTATION_CHASSIS.block;
for (BlockInfo chassisBlock : chassis) {
blocks.add(chassisBlock);
BlockState state = chassisBlock.state;
BlockPos currentPos = chassisBlock.pos;
TileEntity tileEntity = world.getTileEntity(currentPos);
if (!(tileEntity instanceof ChassisTileEntity))
return null;
int chassisRange = ((ChassisTileEntity) tileEntity).getRange();
Set<BlockPos> visited = new HashSet<>();
for (Direction facing : Direction.values()) {
if (facing.getAxis() == direction.getAxis())
continue;
if (!state.get(def.getGlueableSide(state, facing)))
continue;
BlockPos startPos = currentPos.offset(facing);
List<BlockPos> frontier = new LinkedList<>();
frontier.add(startPos);
CompoundNBT nbt = new CompoundNBT();
nbt.putInt("Range", chassisRange);
while (!frontier.isEmpty()) {
BlockPos searchPos = frontier.remove(0);
BlockState searchedState = world.getBlockState(searchPos);
if (visited.contains(searchPos))
continue;
if (!searchPos.withinDistance(currentPos, chassisRange + .5f))
continue;
if (searchedState.getMaterial().isReplaceable() || state.isAir(world, searchPos))
continue;
if (searchedState.getCollisionShape(world, searchPos).isEmpty())
continue;
if (!canRotate(world, searchPos, direction))
return null;
visited.add(searchPos);
blocks.add(new BlockInfo(searchPos, searchedState,
AllBlocks.ROTATION_CHASSIS.typeOf(searchedState) ? nbt : null));
for (Direction offset : Direction.values()) {
if (offset.getAxis() == direction.getAxis())
continue;
if (searchPos.equals(currentPos) && offset != facing)
continue;
frontier.add(searchPos.offset(offset));
}
}
}
}
return blocks;
}
private List<BlockInfo> collectChassis(World world, BlockPos pos, Direction direction) {
List<BlockInfo> chassis = new ArrayList<>();
for (int distance = 1; distance <= CreateConfig.parameters.maxChassisForRotation.get(); distance++) {
BlockPos currentPos = pos.offset(direction, distance);
if (!world.isBlockPresent(currentPos))
return chassis;
BlockState state = world.getBlockState(currentPos);
if (!AllBlocks.ROTATION_CHASSIS.typeOf(state))
return chassis;
if (direction.getAxis() != state.get(BlockStateProperties.AXIS))
return chassis;
chassis.add(new BlockInfo(currentPos, state, null));
}
return chassis;
}
private static boolean isSailBlock(BlockState state) {
return AllBlockTags.WINDMILL_SAILS.matches(state);
}
public CompoundNBT writeNBT() {
CompoundNBT nbt = new CompoundNBT();
ListNBT blocks = new ListNBT();
for (BlockInfo block : this.blocks.values()) {
CompoundNBT c = new CompoundNBT();
c.put("Block", NBTUtil.writeBlockState(block.state));
c.put("Pos", NBTUtil.writeBlockPos(block.pos));
if (block.nbt != null)
c.put("Data", block.nbt);
blocks.add(c);
}
nbt.put("Blocks", blocks);
return nbt;
}
public static RotationConstruct fromNBT(CompoundNBT nbt) {
RotationConstruct construct = new RotationConstruct();
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);
});
return construct;
}
private static boolean canRotate(World world, BlockPos pos, Direction direction) {
return PistonBlock.canPush(world.getBlockState(pos), world, pos, direction, true, direction)
|| AllBlocks.ROTATION_CHASSIS.typeOf(world.getBlockState(pos));
}
public static boolean isFrozen() {
return CreateConfig.parameters.freezeRotationConstructs.get();
}
}

View file

@ -1,42 +0,0 @@
package com.simibubi.create.modules.contraptions.components.constructs.bearing;
import java.nio.ByteBuffer;
import com.simibubi.create.foundation.utility.BufferManipulator;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
public class RotationConstructVertexBuffer extends BufferManipulator {
public RotationConstructVertexBuffer(ByteBuffer original) {
super(original);
}
public ByteBuffer getTransformed(TileEntity te, float x, float y, float z, float angle, Axis axis) {
original.rewind();
mutable.rewind();
float cos = MathHelper.cos(angle);
float sin = MathHelper.sin(angle);
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
float xL = getX(original, vertex) -.5f;
float yL = getY(original, vertex) -.5f;
float zL = getZ(original, vertex) -.5f;
float xL2 = rotateX(xL, yL, zL, sin, cos, axis) + .5f;
float yL2 = rotateY(xL, yL, zL, sin, cos, axis) + .5f;
float zL2 = rotateZ(xL, yL, zL, sin, cos, axis) + .5f;
putPos(mutable, vertex, xL2 + x, yL2 + y, zL2 + z);
BlockPos pos = new BlockPos(te.getPos().getX() + xL2, te.getPos().getY() + yL2, te.getPos().getZ() + zL2);
putLight(mutable, vertex, te.getWorld().getCombinedLight(pos, 0));
}
return mutable;
}
}

View file

@ -1,202 +0,0 @@
package com.simibubi.create.modules.contraptions.components.constructs.mounted;
import com.simibubi.create.AllEntities;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.contraptions.components.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;
enum MovementType {
TRANSLATION, ROTATION, MOUNTED;
}
// 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());
}
}

View file

@ -1,347 +0,0 @@
package com.simibubi.create.modules.contraptions.components.constructs.piston;
import static com.simibubi.create.CreateConfig.parameters;
import static com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonBlock.STATE;
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.lang3.tuple.MutablePair;
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.components.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior.MoverType;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.Blocks;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class MechanicalPistonTileEntity extends KineticTileEntity {
protected PistonContraption movedContraption;
protected float offset;
protected boolean running;
protected boolean assembleNextTick;
protected boolean hadCollisionWithOtherPiston;
public MechanicalPistonTileEntity() {
super(AllTileEntities.MECHANICAL_PISTON.type);
}
@Override
public void onSpeedChanged() {
super.onSpeedChanged();
assembleNextTick = true;
}
@Override
public void remove() {
this.removed = true;
if (!world.isRemote)
disassembleConstruct();
super.remove();
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return INFINITE_EXTENT_AABB;
}
@Override
@OnlyIn(Dist.CLIENT)
public double getMaxRenderDistanceSquared() {
return super.getMaxRenderDistanceSquared() * 16;
}
@Override
public CompoundNBT write(CompoundNBT tag) {
tag.putBoolean("Running", running);
tag.putFloat("Offset", offset);
if (running && !PistonContraption.isFrozen())
tag.put("Construct", movedContraption.writeNBT());
return super.write(tag);
}
@Override
public void read(CompoundNBT tag) {
running = tag.getBoolean("Running");
offset = tag.getFloat("Offset");
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.motion = new Vec3d(direction.getDirectionVec()).scale(getMovementSpeed()).normalize();
context.currentGridPos = pair.left.pos.offset(direction, getModulatedOffset(offset));
pair.setRight(context);
}
}
super.read(tag);
}
protected void onBlockVisited(float newOffset) {
if (PistonContraption.isFrozen())
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors()) {
BlockInfo block = pair.left;
MovementContext context = pair.right;
BlockPos newPos = block.pos.offset(direction, getModulatedOffset(newOffset));
context.currentGridPos = newPos;
IHaveMovementBehavior actor = (IHaveMovementBehavior) block.state.getBlock();
actor.visitPosition(context);
}
}
public void assembleConstruct() {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
movedContraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
if (movedContraption == null)
return;
// Check if not at limit already
float resultingOffset = movedContraption.initialExtensionProgress + getMovementSpeed();
if (resultingOffset <= 0 || resultingOffset >= movedContraption.extensionLength) {
movedContraption = null;
return;
}
if (hasBlockCollisions(resultingOffset + .5f)) {
movedContraption = null;
return;
}
// Run
running = true;
offset = movedContraption.initialExtensionProgress;
if (!world.isRemote)
Create.constructHandler.add(this);
sendData();
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66);
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 : 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);
}
onBlockVisited(offset);
}
public void disassembleConstruct() {
if (!running)
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
if (!removed)
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
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);
movedContraption = null;
sendData();
if (removed)
AllBlocks.MECHANICAL_PISTON.get().onBlockHarvested(world, pos, getBlockState(), null);
}
@Override
public void tick() {
super.tick();
if (isRemoved())
return;
if (!world.isRemote && assembleNextTick) {
assembleNextTick = false;
if (running) {
if (getSpeed() == 0)
disassembleConstruct();
else {
for (MutablePair<BlockInfo, MovementContext> pair : movedContraption.getActors())
pair.right.motion = new Vec3d(
getBlockState().get(BlockStateProperties.FACING).getDirectionVec())
.scale(getMovementSpeed());
sendData();
}
return;
}
assembleConstruct();
return;
}
if (!running)
return;
float movementSpeed = getMovementSpeed();
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
float newOffset = offset + movementSpeed;
MovingConstructHandler.moveEntities(this, movementSpeed, movementDirection, newOffset);
if (world.isRemote) {
offset = newOffset;
return;
}
if (getModulatedOffset(newOffset) != getModulatedOffset(offset)) {
onBlockVisited(newOffset);
}
float movement = .5f + (movementSpeed < 0 ? -1f : 0);
if (getModulatedOffset(newOffset + movement) != getModulatedOffset(offset + movement)) {
if (hasBlockCollisions(newOffset + movement)) {
disassembleConstruct();
if (hadCollisionWithOtherPiston)
hadCollisionWithOtherPiston = false;
else if (movementSpeed > 0)
assembleNextTick = true;
return;
}
}
offset = newOffset;
if (offset <= 0 || offset >= movedContraption.extensionLength) {
disassembleConstruct();
return;
}
}
private boolean hasBlockCollisions(float newOffset) {
if (PistonContraption.isFrozen())
return true;
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
BlockPos relativePos = BlockPos.ZERO.offset(movementDirection, getModulatedOffset(newOffset));
// Other moving Pistons
int maxPossibleRange = parameters.maxPistonPoles.get() + parameters.maxChassisRange.get()
+ parameters.maxChassisForTranslation.get();
Iterator<MechanicalPistonTileEntity> iterator = Create.constructHandler.getOtherMovingPistonsInWorld(this)
.iterator();
pistonLoop: while (iterator.hasNext()) {
MechanicalPistonTileEntity otherPiston = iterator.next();
if (otherPiston == this)
continue;
if (!otherPiston.running || otherPiston.movedContraption == null) {
iterator.remove();
continue;
}
if (otherPiston.pos.manhattanDistance(pos) > maxPossibleRange * 2)
continue;
Direction otherMovementDirection = otherPiston.getBlockState().get(BlockStateProperties.FACING);
BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
getModulatedOffset(otherPiston.offset));
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;
boolean frontalCollision = otherMovementDirection == movementDirection.getOpposite();
BlockPos thisColliderOffset = relativePos.offset(movementDirection,
frontalCollision ? (getMovementSpeed() > 0 ? 1 : -1) : 0);
AxisAlignedBB thisBB = tBB.offset(thisColliderOffset);
AxisAlignedBB otherBB = oBB.offset(otherRelativePos);
if (thisBB.intersects(otherBB)) {
boolean actuallyColliding = false;
for (BlockPos colliderPos : movedContraption.getColliders(world, movementDirection)) {
colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
if (!otherPiston.movedContraption.blocks.containsKey(colliderPos))
continue;
actuallyColliding = true;
}
if (!actuallyColliding)
continue pistonLoop;
hadCollisionWithOtherPiston = true;
return true;
}
}
}
}
if (!running)
return false;
// Other Blocks in world
for (BlockPos pos : movedContraption.getColliders(world,
getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
BlockPos colliderPos = pos.add(relativePos);
if (!world.isBlockPresent(colliderPos))
return true;
if (!world.getBlockState(colliderPos).getMaterial().isReplaceable()
&& !world.getBlockState(colliderPos).getCollisionShape(world, colliderPos).isEmpty())
return true;
}
return false;
}
private int getModulatedOffset(float offset) {
return MathHelper.clamp((int) (offset + .5f), 0, movedContraption.extensionLength);
}
public float getMovementSpeed() {
Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING);
int movementModifier = pistonDirection.getAxisDirection().getOffset()
* (pistonDirection.getAxis() == Axis.Z ? -1 : 1);
return getSpeed() * -movementModifier / 1024f;
}
public Vec3d getConstructOffset(float partialTicks) {
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
movedContraption.extensionLength);
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
}
}

View file

@ -1,184 +0,0 @@
package com.simibubi.create.modules.contraptions.components.constructs.piston;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.components.constructs.Contraption;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.ReuseableStream;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class MovingConstructHandler {
static List<AxisAlignedBB> renderedBBs = new LinkedList<>();
static Map<IWorld, List<MechanicalPistonTileEntity>> movingPistons = new HashMap<>();
public void onLoadWorld(IWorld world) {
movingPistons.put(world, new ArrayList<>());
Create.logger.debug("Prepared Construct List for " + world.getDimension().getType().getRegistryName());
}
public void onUnloadWorld(IWorld world) {
movingPistons.remove(world);
Create.logger.debug("Removed Construct List for " + world.getDimension().getType().getRegistryName());
}
public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
float newOffset) {
if (PistonContraption.isFrozen())
return;
World world = te.getWorld();
Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
Contraption construct = te.movedContraption;
// if (world.isRemote) {
// renderedBBs.clear();
// if (construct.pistonCollisionBox != null)
// renderedBBs.add(construct.pistonCollisionBox.offset(te.getConstructOffset(0)));
// if (construct.constructCollisionBox != null)
// renderedBBs.add(construct.constructCollisionBox.offset(te.getConstructOffset(0)));
//
// }
if (construct.getCollisionBoxFront() != null) {
AxisAlignedBB constructBB = construct.getCollisionBoxFront().offset(te.getConstructOffset(0)).grow(.5f);
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, constructBB,
e -> e.getPushReaction() == PushReaction.NORMAL)) {
AxisAlignedBB entityScanBB = entity.getBoundingBox().offset(movementVec.scale(-1 * newOffset))
.grow(.5f);
BlockPos min = new BlockPos(entityScanBB.minX, entityScanBB.minY, entityScanBB.minZ);
BlockPos max = new BlockPos(entityScanBB.maxX, entityScanBB.maxY, entityScanBB.maxZ);
Stream<VoxelShape> hits = BlockPos.getAllInBox(min, max).filter(construct.blocks::containsKey)
.map(pos -> {
Vec3d vec = new Vec3d(pos).add(te.getConstructOffset(te.getMovementSpeed() > 0 ? 1 : 0));
return construct.blocks.get(pos).state.getShape(world, new BlockPos(vec)).withOffset(vec.x,
vec.y, vec.z);
});
ReuseableStream<VoxelShape> potentialHits = new ReuseableStream<>(hits);
AxisAlignedBB entityBB = entity.getBoundingBox();
Vec3d motion = entity.getMotion();
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(-movementSpeed).add(motion);
Vec3d allowedMovement = Entity.getAllowedMovement(movement, entityBB, world,
ISelectionContext.forEntity(entity), potentialHits);
for (Object shape : potentialHits.createStream().toArray()) {
VoxelShape voxelShape = (VoxelShape) shape;
if (!entityBB.intersects(voxelShape.getBoundingBox()))
continue;
Direction bestSide = Direction.DOWN;
double bestOffset = 100;
double finalOffset = 0;
for (Direction face : Direction.values()) {
Axis axis = face.getAxis();
double d = axis == Axis.X ? entityBB.getXSize()
: axis == Axis.Y ? entityBB.getYSize() : entityBB.getZSize();
d = d + 1.5f;
Vec3d nudge = new Vec3d(face.getDirectionVec()).scale(d);
AxisAlignedBB nudgedBB = entityBB.offset(nudge.getX(), nudge.getY(), nudge.getZ());
double nudgeDistance = face.getAxisDirection() == AxisDirection.POSITIVE ? -d : d;
double offset = voxelShape.getAllowedOffset(face.getAxis(), nudgedBB, nudgeDistance);
double abs = Math.abs(nudgeDistance - offset);
if (abs < Math.abs(bestOffset) && abs != 0) {
bestOffset = abs;
finalOffset = abs;
bestSide = face;
}
}
if (bestOffset != 0) {
entity.move(MoverType.SELF, new Vec3d(bestSide.getDirectionVec()).scale(finalOffset));
switch (bestSide.getAxis()) {
case X:
entity.setMotion(0, motion.y, motion.z);
break;
case Y:
entity.setMotion(motion.x, bestSide == Direction.UP ? movementSpeed + 1 / 8f : 0, motion.z);
entity.fall(entity.fallDistance, 1);
entity.fallDistance = 0;
entity.onGround = true;
break;
case Z:
entity.setMotion(motion.x, motion.y, 0);
break;
}
break;
}
}
if (!allowedMovement.equals(movement)) {
if (allowedMovement.y != movement.y) {
entity.fall(entity.fallDistance, 1);
entity.fallDistance = 0;
entity.onGround = true;
}
if (entity instanceof PlayerEntity && !world.isRemote)
return;
entity.setMotion(allowedMovement.subtract(movement.subtract(motion)));
entity.velocityChanged = true;
}
}
}
}
public void add(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).add(mechanicalPistonTileEntity);
}
public void remove(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).remove(mechanicalPistonTileEntity);
}
public List<MechanicalPistonTileEntity> getOtherMovingPistonsInWorld(
MechanicalPistonTileEntity mechanicalPistonTileEntity) {
return movingPistons.get(mechanicalPistonTileEntity.getWorld());
}
// @SubscribeEvent
// @OnlyIn(value = Dist.CLIENT)
// public static void onRenderWorld(RenderWorldLastEvent event) {
// for (AxisAlignedBB bb : renderedBBs) {
// TessellatorHelper.prepareForDrawing();
// GlStateManager.disableTexture();
// GlStateManager.lineWidth(3);
// int color = ColorHelper.rainbowColor(renderedBBs.indexOf(bb) * 170);
// WorldRenderer.drawSelectionBoundingBox(bb.grow(1 / 256f), (color >> 16 & 0xFF) / 256f,
// (color >> 8 & 0xFF) / 256f, (color & 0xFF) / 256f, 1);
// GlStateManager.lineWidth(1);
// GlStateManager.enableTexture();
// TessellatorHelper.cleanUpAfterDrawing();
// }
// }
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs;
package com.simibubi.create.modules.contraptions.components.contraptions;
import static com.simibubi.create.CreateConfig.parameters;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
@ -18,10 +18,18 @@ import org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.BearingContraption;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.LinearChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.RadialChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.MountedContraption;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonContraption;
import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FallingBlock;
import net.minecraft.block.PistonBlock;
import net.minecraft.block.ShulkerBoxBlock;
@ -117,13 +125,13 @@ public class Contraption {
return cachedColliders;
}
protected boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
List<BlockPos> frontier = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>();
anchor = pos;
if (constructCollisionBox == null)
constructCollisionBox = new AxisAlignedBB(pos);
constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO);
frontier.add(pos);
if (!addToInitialFrontier(world, pos, direction, frontier))
@ -433,15 +441,29 @@ public class Contraption {
return compoundnbt;
}
protected void add(BlockPos pos, BlockInfo block) {
BlockInfo blockInfo = new BlockInfo(pos, block.state, block.nbt);
blocks.put(pos, blockInfo);
public void add(BlockPos pos, BlockInfo block) {
BlockPos localPos = pos.subtract(anchor);
BlockInfo blockInfo = new BlockInfo(localPos, block.state, block.nbt);
blocks.put(localPos, blockInfo);
if (block.state.getBlock() instanceof IHaveMovementBehavior)
getActors().add(MutablePair.of(blockInfo, null));
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(pos));
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(localPos));
}
public void readNBT(CompoundNBT nbt) {
public static Contraption fromNBT(World world, CompoundNBT nbt) {
String type = nbt.getString("Type");
Contraption contraption = new Contraption();
if (type.equals("Piston"))
contraption = new PistonContraption();
if (type.equals("Mounted"))
contraption = new MountedContraption();
if (type.equals("Bearing"))
contraption = new BearingContraption();
contraption.readNBT(world, nbt);
return contraption;
}
public void readNBT(World world, CompoundNBT nbt) {
nbt.getList("Blocks", 10).forEach(c -> {
CompoundNBT comp = (CompoundNBT) c;
BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")),
@ -453,7 +475,7 @@ public class Contraption {
nbt.getList("Actors", 10).forEach(c -> {
CompoundNBT comp = (CompoundNBT) c;
BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos")));
MovementContext context = MovementContext.readNBT(comp);
MovementContext context = MovementContext.readNBT(world, comp);
getActors().add(MutablePair.of(info, context));
});
@ -469,6 +491,14 @@ public class Contraption {
public CompoundNBT writeNBT() {
CompoundNBT nbt = new CompoundNBT();
if (this instanceof PistonContraption)
nbt.putString("Type", "Piston");
if (this instanceof MountedContraption)
nbt.putString("Type", "Mounted");
if (this instanceof BearingContraption)
nbt.putString("Type", "Bearing");
ListNBT blocks = new ListNBT();
for (BlockInfo block : this.blocks.values()) {
CompoundNBT c = new CompoundNBT();
@ -520,7 +550,25 @@ public class Contraption {
return CreateConfig.parameters.freezePistonConstructs.get();
}
public void disassemble(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customPlacement) {
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
disassemble(world, offset, yaw, pitch, (pos, state) -> false);
}
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
removeBlocksFromWorld(world, offset, (pos, state) -> false);
}
public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customRemoval) {
for (BlockInfo block : blocks.values()) {
BlockPos add = block.pos.add(anchor).add(offset);
if (customRemoval.test(add, block.state))
continue;
world.setBlockState(add, Blocks.AIR.getDefaultState(), 67);
}
}
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch,
BiPredicate<BlockPos, BlockState> customPlacement) {
for (BlockInfo block : blocks.values()) {
BlockPos targetPos = block.pos.add(offset);
BlockState state = block.state;
@ -546,8 +594,21 @@ public class Contraption {
}
}
public void initActors(World world) {
for (MutablePair<BlockInfo, MovementContext> pair : actors) {
BlockState blockState = pair.left.state;
MovementContext context = new MovementContext(world, blockState);
((IHaveMovementBehavior) blockState.getBlock()).startMoving(context);
pair.setRight(context);
}
}
public List<MutablePair<BlockInfo, MovementContext>> getActors() {
return actors;
}
public BlockPos getAnchor() {
return anchor;
}
}

View file

@ -0,0 +1,306 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import org.apache.commons.lang3.tuple.MutablePair;
import com.simibubi.create.AllEntities;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks;
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
protected Contraption contraption;
protected float initialAngle;
protected BlockPos controllerPos;
protected IControlContraption controllerTE;
public float movementSpeedModifier;
public float prevYaw;
public float prevPitch;
public float prevRoll;
public float yaw;
public float pitch;
public float roll;
// Mounted Contraptions
public float targetYaw;
public float targetPitch;
public ContraptionEntity(EntityType<?> entityTypeIn, World worldIn) {
super(entityTypeIn, worldIn);
}
protected ContraptionEntity(World world) {
this(AllEntities.CONTRAPTION.type, world);
}
public ContraptionEntity(World world, Contraption contraption, float initialAngle) {
this(world);
this.contraption = contraption;
this.initialAngle = initialAngle;
this.prevYaw = initialAngle;
this.yaw = initialAngle;
this.targetYaw = initialAngle;
movementSpeedModifier = 1;
}
public <T extends TileEntity & IControlContraption> ContraptionEntity controlledBy(T controller) {
this.controllerPos = controller.getPos();
this.controllerTE = controller;
return this;
}
@Override
public void tick() {
attachToController();
Entity e = getRidingEntity();
if (e != null) {
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 (yaw < 0)
yaw += 360;
}
if (Math.abs(getShortestAngleDiff(yaw, targetYaw)) >= 175) {
initialAngle += 180;
yaw += 180;
prevYaw = yaw;
} else {
float speed = 0.2f;
prevYaw = yaw;
yaw = angleLerp(speed, yaw, targetYaw);
prevPitch = pitch;
pitch = angleLerp(speed, pitch, targetPitch);
}
tickActors(movementVector);
super.tick();
return;
}
prevYaw = yaw;
prevPitch = pitch;
prevRoll = roll;
tickActors(new Vec3d(posX - prevPosX, posY - prevPosY, posZ - prevPosZ));
super.tick();
}
public void tickActors(Vec3d movementVector) {
movementSpeedModifier = 1;
float anglePitch = getPitch(1);
float angleYaw = getYaw(1);
float angleRoll = getRoll(1);
Vec3d rotationVec = new Vec3d(angleRoll, angleYaw, anglePitch);
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
for (MutablePair<BlockInfo, MovementContext> pair : contraption.actors) {
MovementContext context = pair.right;
BlockInfo blockInfo = pair.left;
IHaveMovementBehavior actor = (IHaveMovementBehavior) blockInfo.state.getBlock();
Vec3d actorPosition = new Vec3d(blockInfo.pos);
actorPosition = actorPosition.add(actor.getActiveAreaOffset(context));
actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch);
actorPosition = actorPosition.add(rotationOffset).add(posX, posY, posZ);
Vec3d previousPosition = context.position;
BlockPos gridPosition = new BlockPos(actorPosition);
boolean newPosVisited = true;
if (previousPosition != null) {
context.motion = actorPosition.subtract(previousPosition);
Vec3d relativeMotion = context.motion;
relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch);
context.relativeMotion = relativeMotion;
newPosVisited = !new BlockPos(previousPosition).equals(gridPosition);
}
context.rotation = rotationVec;
context.position = actorPosition;
if (actor.isActive(context)) {
if (newPosVisited)
actor.visitNewPosition(context, gridPosition);
actor.tick(context);
}
if (movementSpeedModifier > context.movementSpeedModifier)
movementSpeedModifier = context.movementSpeedModifier;
}
}
public void moveTo(double x, double y, double z) {
move(x - posX, y - posY, z - posZ);
}
public void move(double x, double y, double z) {
// Collision and stuff
setPosition(posX + x, posY + y, posZ + z);
}
public void rotateTo(double roll, double yaw, double pitch) {
rotate(getShortestAngleDiff(this.roll, roll), getShortestAngleDiff(this.yaw, yaw),
getShortestAngleDiff(this.pitch, pitch));
}
public void rotate(double roll, double yaw, double pitch) {
// Collision and stuff
this.yaw += yaw;
this.pitch += pitch;
this.roll += roll;
}
@Override
public void setPosition(double x, double y, double z) {
Entity e = getRidingEntity();
if (e != null && e instanceof AbstractMinecartEntity) {
x -= .5;
z -= .5;
}
this.posX = x;
this.posY = y;
this.posZ = z;
if (this.isAddedToWorld() && !this.world.isRemote && world instanceof ServerWorld)
((ServerWorld) this.world).chunkCheck(this); // Forge - Process chunk registration after moving.
if (contraption != null) {
AxisAlignedBB cbox = contraption.getCollisionBoxFront();
if (cbox != null)
this.setBoundingBox(cbox.offset(x, y, z));
}
}
@Override
public void stopRiding() {
super.stopRiding();
if (!world.isRemote)
disassemble();
}
public static float yawFromMotion(Vec3d motion) {
return (float) ((3 * Math.PI / 2 + Math.atan2(motion.z, motion.x)) / Math.PI * 180);
}
public float getYaw(float partialTicks) {
return (getRidingEntity() == null ? 1 : -1)
* (partialTicks == 1.0F ? yaw : angleLerp(partialTicks, prevYaw, yaw)) + initialAngle;
}
public float getPitch(float partialTicks) {
return partialTicks == 1.0F ? pitch : angleLerp(partialTicks, prevPitch, pitch);
}
public float getRoll(float partialTicks) {
return partialTicks == 1.0F ? roll : angleLerp(partialTicks, prevRoll, roll);
}
private float angleLerp(float pct, float current, float target) {
return current + getShortestAngleDiff(current, target) * pct;
}
private float getShortestAngleDiff(double current, double target) {
current = current % 360;
target = target % 360;
return (float) (((((target - current) % 360) + 540) % 360) - 180);
}
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked")
EntityType.Builder<ContraptionEntity> entityBuilder = (EntityType.Builder<ContraptionEntity>) builder;
return entityBuilder.size(1, 1);
}
@Override
protected void registerData() {
}
@Override
protected void readAdditional(CompoundNBT compound) {
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
initialAngle = compound.getFloat("InitialAngle");
if (compound.contains("Controller"))
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
prevYaw = initialAngle;
yaw = initialAngle;
targetYaw = initialAngle;
}
public void attachToController() {
if (controllerPos != null && controllerTE == null) {
if (!world.isBlockPresent(controllerPos))
return;
TileEntity te = world.getTileEntity(controllerPos);
if (te == null || !(te instanceof IControlContraption))
remove();
IControlContraption controllerTE = (IControlContraption) te;
this.controllerTE = controllerTE;
controllerTE.attach(this);
}
}
@Override
protected void writeAdditional(CompoundNBT compound) {
compound.put("Contraption", getContraption().writeNBT());
compound.putFloat("InitialAngle", initialAngle);
if (controllerPos != null)
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
}
@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());
}
public void disassemble() {
if (getContraption() != null)
getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)), yaw, pitch);
remove();
}
public Contraption getContraption() {
return contraption;
}
}

View file

@ -1,10 +1,10 @@
package com.simibubi.create.modules.contraptions.components.constructs.mounted;
package com.simibubi.create.modules.contraptions.components.contraptions;
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.components.constructs.ContraptionRenderer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
@ -32,33 +32,31 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
public void doRender(ContraptionEntity entity, double x, double y, double z, float yaw, float partialTicks) {
if (!entity.isAlive())
return;
if (entity.contraption == null)
if (entity.getContraption() == null)
return;
GlStateManager.pushMatrix();
GlStateManager.translated(0, .5, 0);
long randomBits = (long) entity.getEntityId() * 493286711L;
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;
float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float zNudge = (((float) (randomBits >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
GlStateManager.translatef(xNudge, yNudge, zNudge);
float angleYaw = (float) (entity.getYaw(partialTicks) / 180 * Math.PI);
float anglePitch = (float) (entity.getPitch(partialTicks) / 180 * Math.PI);
float angleRoll = (float) (entity.getRoll(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)
@ -74,21 +72,26 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
}
}
BlockPos anchor = entity.contraption.getAnchor();
Vec3d rotationOffset = VecHelper.getCenterOf(anchor);
// Vec3d offset = VecHelper.getCenterOf(anchor).scale(-1);
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
ContraptionRenderer.render(entity.world, entity.contraption, superByteBuffer -> {
ContraptionRenderer.render(entity.world, entity.getContraption(), superByteBuffer -> {
superByteBuffer.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z);
superByteBuffer.rotate(Axis.X, angleRoll);
superByteBuffer.rotate(Axis.Y, angleYaw);
superByteBuffer.rotate(Axis.Z, anglePitch);
superByteBuffer.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z);
superByteBuffer.translate(x, y, z);
superByteBuffer.offsetLighting(-x + entity.posX, -y + entity.posY, -z + entity.posZ);
}, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw();
GlStateManager.popMatrix();
GlStateManager.shadeModel(7424);
GlStateManager.alphaFunc(516, 0.1F);
GlStateManager.matrixMode(5888);
RenderHelper.enableStandardItemLighting();
super.doRender(entity, x, y, z, yaw, partialTicks);
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs;
package com.simibubi.create.modules.contraptions.components.contraptions;
import java.util.Random;
import java.util.function.Consumer;
@ -10,7 +10,7 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
@ -31,7 +31,7 @@ public class ContraptionRenderer {
public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, BufferBuilder buffer) {
SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c));
transform.accept(contraptionBuffer);
buffer.putBulkData(contraptionBuffer.build());
contraptionBuffer.light((lx, ly, lz) -> world.getCombinedLight(new BlockPos(lx, ly, lz), 0)).renderInto(buffer);
renderActors(world, c, transform, buffer);
}

View file

@ -0,0 +1,7 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
public interface IControlContraption {
public void attach(ContraptionEntity contraption);
}

View file

@ -0,0 +1,99 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
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 {
public class MovementContext {
public Vec3d position;
public Vec3d motion;
public Vec3d relativeMotion;
public Vec3d rotation;
public World world;
public BlockState state;
public float movementSpeedModifier;
public CompoundNBT data;
public MovementContext(World world, BlockState state) {
this.world = world;
this.state = state;
motion = Vec3d.ZERO;
relativeMotion = Vec3d.ZERO;
rotation = Vec3d.ZERO;
position = null;
data = new CompoundNBT();
movementSpeedModifier = 1;
}
public float getAnimationSpeed() {
int modifier = 1000;
double length = -motion.length();
if (Math.abs(length) < 1 / 512f)
return 0;
return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100;
}
public static MovementContext readNBT(World world, CompoundNBT nbt) {
BlockState state = NBTUtil.readBlockState(nbt.getCompound("State"));
MovementContext context = new MovementContext(world, state);
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE));
context.rotation = VecHelper.readNBT(nbt.getList("Rotation", NBT.TAG_DOUBLE));
if (nbt.contains("Position"))
context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE));
context.movementSpeedModifier = nbt.getFloat("SpeedModifier");
context.data = nbt.getCompound("Data");
return context;
}
public CompoundNBT writeToNBT(CompoundNBT nbt) {
nbt.put("State", NBTUtil.writeBlockState(state));
nbt.put("Motion", VecHelper.writeNBT(motion));
nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion));
nbt.put("Rotation", VecHelper.writeNBT(rotation));
if (position != null)
nbt.put("Position", VecHelper.writeNBT(position));
nbt.putFloat("SpeedModifier", movementSpeedModifier);
nbt.put("Data", data);
return nbt;
}
}
default boolean isActive(MovementContext context) {
return true;
}
default void tick(MovementContext context) {
}
default void startMoving(MovementContext context) {
}
default void visitNewPosition(MovementContext context, BlockPos pos) {
}
default Vec3d getActiveAreaOffset(MovementContext context) {
return Vec3d.ZERO;
}
@OnlyIn(value = Dist.CLIENT)
default SuperByteBuffer renderInContraption(MovementContext context) {
return null;
}
}

View file

@ -0,0 +1,54 @@
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
import com.simibubi.create.AllBlockTags;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class BearingContraption extends Contraption {
protected int sailBlocks;
protected Direction facing;
public static BearingContraption assembleBearingAt(World world, BlockPos pos, Direction direction) {
if (isFrozen())
return null;
BearingContraption construct = new BearingContraption();
construct.facing = direction;
if (!construct.searchMovedStructure(world, pos.offset(direction), direction))
return null;
construct.initActors(world);
return construct;
}
@Override
public void add(BlockPos pos, BlockInfo block) {
if (AllBlockTags.WINDMILL_SAILS.matches(block.state))
sailBlocks++;
super.add(pos, block);
}
@Override
public CompoundNBT writeNBT() {
CompoundNBT tag = super.writeNBT();
tag.putInt("Sails", sailBlocks);
tag.putInt("facing", facing.getIndex());
return tag;
}
@Override
public void readNBT(World world, CompoundNBT tag) {
sailBlocks = tag.getInt("Sails");
facing = Direction.byIndex(tag.getInt("Facing"));
super.readNBT(world, tag);
}
public int getSailBlocks() {
return sailBlocks;
}
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs.bearing;
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;

View file

@ -1,25 +1,21 @@
package com.simibubi.create.modules.contraptions.components.constructs.bearing;
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.modules.contraptions.components.constructs.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.IControlContraption;
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.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraft.util.math.Vec3d;
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IControlContraption {
protected RotationConstruct movingConstruct;
protected ContraptionEntity movedContraption;
protected float angle;
protected boolean running;
protected boolean assembleNextTick;
@ -30,17 +26,6 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
isWindmill = false;
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return INFINITE_EXTENT_AABB;
}
@Override
@OnlyIn(Dist.CLIENT)
public double getMaxRenderDistanceSquared() {
return super.getMaxRenderDistanceSquared() * 16;
}
@Override
public float getAddedStressCapacity() {
return isWindmill ? super.getAddedStressCapacity() : 0;
@ -77,7 +62,9 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
public float getGeneratedSpeed() {
if (!running || !isWindmill)
return 0;
int sails = movingConstruct.getSailBlocks();
if (movedContraption == null)
return 0;
int sails = ((BearingContraption) movedContraption.getContraption()).getSailBlocks();
return MathHelper.clamp(sails, 0, 128);
}
@ -86,9 +73,6 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
tag.putBoolean("Running", running);
tag.putBoolean("Windmill", isWindmill);
tag.putFloat("Angle", angle);
if (running && !RotationConstruct.isFrozen())
tag.put("Construct", movingConstruct.writeNBT());
return super.write(tag);
}
@ -97,15 +81,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
running = tag.getBoolean("Running");
isWindmill = tag.getBoolean("Windmill");
angle = tag.getFloat("Angle");
if (running && !RotationConstruct.isFrozen())
movingConstruct = RotationConstruct.fromNBT(tag.getCompound("Construct"));
super.read(tag);
}
public float getInterpolatedAngle(float partialTicks) {
if (RotationConstruct.isFrozen())
return 0;
return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed());
}
@ -123,21 +102,22 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
movingConstruct = RotationConstruct.getAttachedForRotating(getWorld(), getPos(), direction);
if (movingConstruct == null)
BearingContraption contraption = BearingContraption.assembleBearingAt(world, pos, direction);
if (contraption == null)
return;
if (isWindmill && movingConstruct.getSailBlocks() == 0)
if (isWindmill && contraption.getSailBlocks() == 0)
return;
movedContraption = new ContraptionEntity(world, contraption, 0).controlledBy(this);
BlockPos anchor = pos.offset(direction);
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
world.addEntity(movedContraption);
// Run
running = true;
angle = 0;
sendData();
for (BlockInfo info : movingConstruct.blocks.values()) {
getWorld().setBlockState(info.pos.add(pos), Blocks.AIR.getDefaultState(), 67);
}
updateGeneratedRotation();
}
@ -145,24 +125,9 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
if (!running)
return;
for (BlockInfo block : movingConstruct.blocks.values()) {
BlockPos targetPos = block.pos.add(pos);
BlockState state = block.state;
for (Direction face : Direction.values())
state = state.updatePostPlacement(face, world.getBlockState(targetPos.offset(face)), world, targetPos,
targetPos.offset(face));
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) {
((ChassisTileEntity) tileEntity).setRange(block.nbt.getInt("Range"));
}
}
movedContraption.disassemble();
movedContraption = null;
running = false;
movingConstruct = null;
angle = 0;
updateGeneratedRotation();
sendData();
@ -172,14 +137,15 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
public void tick() {
super.tick();
if (running && RotationConstruct.isFrozen())
if (running && Contraption.isFrozen())
disassembleConstruct();
if (!world.isRemote && assembleNextTick) {
assembleNextTick = false;
if (running) {
boolean canDisassemble = Math.abs(angle) < Math.PI / 4f || Math.abs(angle) > 7 * Math.PI / 4f;
if (speed == 0 && (canDisassemble || movingConstruct == null || movingConstruct.blocks.isEmpty())) {
if (speed == 0 && (canDisassemble || movedContraption == null
|| movedContraption.getContraption().blocks.isEmpty())) {
disassembleConstruct();
}
return;
@ -197,6 +163,26 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity {
float angularSpeed = getAngularSpeed();
float newAngle = angle + angularSpeed;
angle = (float) (newAngle % (2 * Math.PI));
applyRotation();
}
private void applyRotation() {
if (movedContraption != null) {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
Vec3d vec = new Vec3d(1, 1, 1).scale(angle * 180 / Math.PI).mul(new Vec3d(direction.getDirectionVec()));
movedContraption.rotateTo(vec.x, vec.y, -vec.z);
}
}
@Override
public void attach(ContraptionEntity contraption) {
if (contraption.getContraption() instanceof BearingContraption) {
this.movedContraption = contraption;
BlockPos anchor = pos.offset(getBlockState().get(BlockStateProperties.FACING));
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
if (!world.isRemote)
sendData();
}
}
}

View file

@ -0,0 +1,38 @@
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRenderer {
@Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
MechanicalBearingTileEntity bearingTe = (MechanicalBearingTileEntity) te;
final Direction facing = te.getBlockState().get(BlockStateProperties.FACING);
BlockState capState = AllBlocks.MECHANICAL_BEARING_TOP.get().getDefaultState().with(BlockStateProperties.FACING,
facing);
SuperByteBuffer superBuffer = CreateClient.bufferCache.renderBlockState(KINETIC_TILE, capState);
float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks);
kineticRotationTransform(superBuffer, bearingTe, facing.getAxis(), interpolatedAngle, getWorld());
superBuffer.translate(x, y, z).renderInto(buffer);
}
@Override
protected BlockState getRenderedBlockState(KineticTileEntity te) {
return AllBlocks.SHAFT_HALF.get().getDefaultState().with(BlockStateProperties.FACING,
te.getBlockState().get(BlockStateProperties.FACING).getOpposite());
}
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs;
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import java.util.List;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs;
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import static com.simibubi.create.CreateConfig.parameters;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs;
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs;
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllBlocks;

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs;
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import com.simibubi.create.foundation.utility.Lang;

View file

@ -1,15 +1,16 @@
package com.simibubi.create.modules.contraptions.components.constructs.mounted;
package com.simibubi.create.modules.contraptions.components.contraptions.mounted;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.RenderUtilityBlock;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
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;
@ -71,7 +72,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!cart.getPassengers().isEmpty())
return;
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
Contraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
ContraptionEntity entity = new ContraptionEntity(world, contraption,
ContraptionEntity.yawFromMotion(cart.getMotion()));
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
@ -82,17 +83,8 @@ public class CartAssemblerBlock extends AbstractRailBlock {
protected void disassemble(World world, BlockPos pos, AbstractMinecartEntity cart) {
if (cart.getPassengers().isEmpty())
return;
Entity entity = cart.getPassengers().get(0);
if (!(entity instanceof ContraptionEntity))
if (!(cart.getPassengers().get(0) 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();
}
@ -117,7 +109,8 @@ public class CartAssemblerBlock extends AbstractRailBlock {
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.CART_ASSEMBLER.get(state.get(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? Direction.Axis.Z : Direction.Axis.X);
return AllShapes.CART_ASSEMBLER
.get(state.get(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? Direction.Axis.Z : Direction.Axis.X);
}
@Override
@ -125,7 +118,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
ISelectionContext context) {
if (context.getEntity() instanceof AbstractMinecartEntity)
return VoxelShapes.empty();
return getShape(state, worldIn, pos, context);
return VoxelShapes.fullCube();
}
@Override

View file

@ -1,18 +1,13 @@
package com.simibubi.create.modules.contraptions.components.constructs.mounted;
package com.simibubi.create.modules.contraptions.components.contraptions.mounted;
import static com.simibubi.create.modules.contraptions.components.constructs.mounted.CartAssemblerBlock.RAIL_SHAPE;
import static com.simibubi.create.modules.contraptions.components.contraptions.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.components.constructs.Contraption;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior.MovementContext;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior.MoverType;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
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;
@ -21,12 +16,13 @@ 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.IWorld;
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) {
public static Contraption assembleMinecart(World world, BlockPos pos, AbstractMinecartEntity cart) {
if (isFrozen())
return null;
@ -34,7 +30,7 @@ public class MountedContraption extends Contraption {
if (!state.has(RAIL_SHAPE))
return null;
MountedContraption contraption = new MountedContraption();
Contraption contraption = new MountedContraption();
Vec3d vec = cart.getMotion();
if (!contraption.searchMovedStructure(world, pos, Direction.getFacingFromVector(vec.x, vec.y, vec.z)))
return null;
@ -43,21 +39,8 @@ public class MountedContraption extends Contraption {
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);
}
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
contraption.initActors(world);
return contraption;
}
@ -83,8 +66,14 @@ public class MountedContraption extends Contraption {
return capture;
}
public BlockPos getAnchor() {
return anchor;
@Override
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> pos.equals(anchor));
}
@Override
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
super.disassemble(world, offset, yaw, pitch, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
}
}

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs.piston;
package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
@ -33,7 +33,6 @@ import net.minecraftforge.common.Tags;
public class MechanicalPistonBlock extends DirectionalAxisKineticBlock {
public static final EnumProperty<PistonState> STATE = EnumProperty.create("state", PistonState.class);
protected boolean isSticky;
public MechanicalPistonBlock(boolean sticky) {

View file

@ -1,11 +1,11 @@
package com.simibubi.create.modules.contraptions.components.constructs.piston;
package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.block.IWithoutBlockItem;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;

View file

@ -0,0 +1,257 @@
package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.IControlContraption;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class MechanicalPistonTileEntity extends KineticTileEntity implements IControlContraption {
protected float offset;
protected boolean running;
protected boolean assembleNextTick;
protected boolean hadCollisionWithOtherPiston;
protected ContraptionEntity movedContraption;
protected int extensionLength;
public MechanicalPistonTileEntity() {
super(AllTileEntities.MECHANICAL_PISTON.type);
}
@Override
public void onSpeedChanged() {
super.onSpeedChanged();
assembleNextTick = true;
}
@Override
public void remove() {
this.removed = true;
if (!world.isRemote)
disassembleConstruct();
super.remove();
}
@Override
public CompoundNBT write(CompoundNBT tag) {
tag.putBoolean("Running", running);
tag.putFloat("Offset", offset);
tag.putInt("ExtensionLength", extensionLength);
return super.write(tag);
}
@Override
public void read(CompoundNBT tag) {
running = tag.getBoolean("Running");
offset = tag.getFloat("Offset");
extensionLength = tag.getInt("ExtensionLength");
super.read(tag);
}
public void assembleConstruct() {
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
PistonContraption contraption = PistonContraption.movePistonAt(world, pos, direction, getMovementSpeed() < 0);
if (contraption == null)
return;
// Check if not at limit already
float resultingOffset = contraption.initialExtensionProgress + Math.signum(getMovementSpeed()) * .5f;
extensionLength = contraption.extensionLength;
if (resultingOffset <= 0 || resultingOffset >= extensionLength) {
return;
}
// Run
running = true;
offset = contraption.initialExtensionProgress;
sendData();
BlockPos startPos = BlockPos.ZERO.offset(direction, contraption.initialExtensionProgress);
contraption.removeBlocksFromWorld(world, startPos);
movedContraption = new ContraptionEntity(getWorld(), contraption, 0).controlledBy(this);
moveContraption();
world.addEntity(movedContraption);
}
public void disassembleConstruct() {
if (!running)
return;
if (!removed)
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
movedContraption.disassemble();
running = false;
movedContraption = null;
sendData();
if (removed)
AllBlocks.MECHANICAL_PISTON.get().onBlockHarvested(world, pos, getBlockState(), null);
}
@Override
public void tick() {
super.tick();
if (!world.isRemote && assembleNextTick) {
assembleNextTick = false;
if (running) {
if (getSpeed() == 0)
disassembleConstruct();
else
sendData();
return;
}
assembleConstruct();
return;
}
if (!running)
return;
float movementSpeed = getMovementSpeed();
float newOffset = offset + movementSpeed;
if (movedContraption == null)
return;
if (!world.isRemote && getModulatedOffset(newOffset) != getModulatedOffset(offset)) {
offset = newOffset;
sendData();
}
offset = newOffset;
moveContraption();
if (offset <= 0 || offset >= extensionLength) {
offset = offset <= 0 ? 0 : extensionLength;
if (!world.isRemote)
disassembleConstruct();
return;
}
}
public void moveContraption() {
if (movedContraption != null) {
Vec3d constructOffset = getConstructOffset(0.5f);
Vec3d vec = constructOffset.add(new Vec3d(movedContraption.getContraption().getAnchor()));
movedContraption.setPosition(vec.x, vec.y, vec.z);
}
}
// private boolean hasBlockCollisions(float newOffset) {
// if (PistonContraption.isFrozen())
// return true;
//
// Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
// BlockPos relativePos = BlockPos.ZERO.offset(movementDirection, getModulatedOffset(newOffset));
//
// // Other moving Pistons
// int maxPossibleRange = parameters.maxPistonPoles.get() + parameters.maxChassisRange.get()
// + parameters.maxChassisForTranslation.get();
// Iterator<MechanicalPistonTileEntity> iterator = Create.constructHandler.getOtherMovingPistonsInWorld(this)
// .iterator();
// pistonLoop: while (iterator.hasNext()) {
// MechanicalPistonTileEntity otherPiston = iterator.next();
//
// if (otherPiston == this)
// continue;
// if (!otherPiston.running || otherPiston.movedContraption == null) {
// iterator.remove();
// continue;
// }
// if (otherPiston.pos.manhattanDistance(pos) > maxPossibleRange * 2)
// continue;
//
// Direction otherMovementDirection = otherPiston.getBlockState().get(BlockStateProperties.FACING);
// BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
// getModulatedOffset(otherPiston.offset));
//
// 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;
//
// boolean frontalCollision = otherMovementDirection == movementDirection.getOpposite();
// BlockPos thisColliderOffset = relativePos.offset(movementDirection,
// frontalCollision ? (getMovementSpeed() > 0 ? 1 : -1) : 0);
// AxisAlignedBB thisBB = tBB.offset(thisColliderOffset);
// AxisAlignedBB otherBB = oBB.offset(otherRelativePos);
//
// if (thisBB.intersects(otherBB)) {
// boolean actuallyColliding = false;
// for (BlockPos colliderPos : movedContraption.getColliders(world, movementDirection)) {
// colliderPos = colliderPos.add(thisColliderOffset).subtract(otherRelativePos);
// if (!otherPiston.movedContraption.blocks.containsKey(colliderPos))
// continue;
// actuallyColliding = true;
// }
// if (!actuallyColliding)
// continue pistonLoop;
// hadCollisionWithOtherPiston = true;
// return true;
// }
//
// }
// }
//
// }
//
// if (!running)
// return false;
//
// // Other Blocks in world
// for (BlockPos pos : movedContraption.getColliders(world,
// getMovementSpeed() > 0 ? movementDirection : movementDirection.getOpposite())) {
// BlockPos colliderPos = pos.add(relativePos);
//
// if (!world.isBlockPresent(colliderPos))
// return true;
// if (!world.getBlockState(colliderPos).getMaterial().isReplaceable()
// && !world.getBlockState(colliderPos).getCollisionShape(world, colliderPos).isEmpty())
// return true;
// }
//
// return false;
// }
private int getModulatedOffset(float offset) {
return MathHelper.clamp((int) (offset + .5f), 0, extensionLength);
}
public float getMovementSpeed() {
Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING);
int movementModifier = pistonDirection.getAxisDirection().getOffset()
* (pistonDirection.getAxis() == Axis.Z ? -1 : 1);
return getSpeed() * -movementModifier / 1024f;
}
public Vec3d getConstructOffset(float partialTicks) {
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
extensionLength);
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
}
@Override
public void attach(ContraptionEntity contraption) {
if (contraption.getContraption() instanceof PistonContraption) {
this.movedContraption = contraption;
if (!world.isRemote)
sendData();
}
}
}

View file

@ -1,15 +1,13 @@
package com.simibubi.create.modules.contraptions.components.constructs.piston;
package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import com.simibubi.create.AllBlocks;
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.components.constructs.ContraptionRenderer;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.Vec3d;
public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRenderer {
@ -17,14 +15,6 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer);
MechanicalPistonTileEntity pistonTe = (MechanicalPistonTileEntity) te;
if (!pistonTe.running)
return;
Vec3d offset = pistonTe.getConstructOffset(partialTicks).subtract(new Vec3d(pistonTe.getPos()));
ContraptionRenderer.render(getWorld(), pistonTe.movedContraption, (superBuffer) -> {
superBuffer.translate(x + offset.x, y + offset.y, z + offset.z);
}, buffer);
}
@Override

View file

@ -0,0 +1,167 @@
/*package com.simibubi.create.modules.contraptions.receivers.constructs.piston;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.simibubi.create.Create;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.IWorld;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class MovingConstructHandler {
static List<AxisAlignedBB> renderedBBs = new LinkedList<>();
static Map<IWorld, List<MechanicalPistonTileEntity>> movingPistons = new HashMap<>();
public void onLoadWorld(IWorld world) {
movingPistons.put(world, new ArrayList<>());
Create.logger.debug("Prepared Construct List for " + world.getDimension().getType().getRegistryName());
}
public void onUnloadWorld(IWorld world) {
movingPistons.remove(world);
Create.logger.debug("Removed Construct List for " + world.getDimension().getType().getRegistryName());
}
// public static void moveEntities(MechanicalPistonTileEntity te, float movementSpeed, Direction movementDirection,
// float newOffset) {
// if (PistonContraption.isFrozen())
// return;
//
// World world = te.getWorld();
// Vec3d movementVec = new Vec3d(te.getBlockState().get(BlockStateProperties.FACING).getDirectionVec());
// Contraption construct = te.movedContraption;
//
//// if (world.isRemote) {
//// renderedBBs.clear();
//// if (construct.pistonCollisionBox != null)
//// renderedBBs.add(construct.pistonCollisionBox.offset(te.getConstructOffset(0)));
//// if (construct.constructCollisionBox != null)
//// renderedBBs.add(construct.constructCollisionBox.offset(te.getConstructOffset(0)));
////
//// }
//
// if (construct.getCollisionBoxFront() != null) {
// AxisAlignedBB constructBB = construct.getCollisionBoxFront().offset(te.getConstructOffset(0)).grow(.5f);
//
// for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, constructBB,
// e -> e.getPushReaction() == PushReaction.NORMAL)) {
//
// AxisAlignedBB entityScanBB = entity.getBoundingBox().offset(movementVec.scale(-1 * newOffset))
// .grow(.5f);
// BlockPos min = new BlockPos(entityScanBB.minX, entityScanBB.minY, entityScanBB.minZ);
// BlockPos max = new BlockPos(entityScanBB.maxX, entityScanBB.maxY, entityScanBB.maxZ);
//
// Stream<VoxelShape> hits = BlockPos.getAllInBox(min, max).filter(construct.blocks::containsKey)
// .map(pos -> {
// Vec3d vec = new Vec3d(pos).add(te.getConstructOffset(te.getMovementSpeed() > 0 ? 1 : 0));
// return construct.blocks.get(pos).state.getShape(world, new BlockPos(vec)).withOffset(vec.x,
// vec.y, vec.z);
// });
// ReuseableStream<VoxelShape> potentialHits = new ReuseableStream<>(hits);
//
// AxisAlignedBB entityBB = entity.getBoundingBox();
// Vec3d motion = entity.getMotion();
// Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(-movementSpeed).add(motion);
// Vec3d allowedMovement = Entity.getAllowedMovement(movement, entityBB, world,
// ISelectionContext.forEntity(entity), potentialHits);
//
// for (Object shape : potentialHits.createStream().toArray()) {
// VoxelShape voxelShape = (VoxelShape) shape;
// if (!entityBB.intersects(voxelShape.getBoundingBox()))
// continue;
//
// Direction bestSide = Direction.DOWN;
// double bestOffset = 100;
// double finalOffset = 0;
//
// for (Direction face : Direction.values()) {
// Axis axis = face.getAxis();
// double d = axis == Axis.X ? entityBB.getXSize()
// : axis == Axis.Y ? entityBB.getYSize() : entityBB.getZSize();
// d = d + 1.5f;
//
// Vec3d nudge = new Vec3d(face.getDirectionVec()).scale(d);
// AxisAlignedBB nudgedBB = entityBB.offset(nudge.getX(), nudge.getY(), nudge.getZ());
// double nudgeDistance = face.getAxisDirection() == AxisDirection.POSITIVE ? -d : d;
// double offset = voxelShape.getAllowedOffset(face.getAxis(), nudgedBB, nudgeDistance);
// double abs = Math.abs(nudgeDistance - offset);
// if (abs < Math.abs(bestOffset) && abs != 0) {
// bestOffset = abs;
// finalOffset = abs;
// bestSide = face;
// }
// }
//
// if (bestOffset != 0) {
// entity.move(MoverType.SELF, new Vec3d(bestSide.getDirectionVec()).scale(finalOffset));
// switch (bestSide.getAxis()) {
// case X:
// entity.setMotion(0, motion.y, motion.z);
// break;
// case Y:
// entity.setMotion(motion.x, bestSide == Direction.UP ? movementSpeed + 1 / 8f : 0, motion.z);
// entity.fall(entity.fallDistance, 1);
// entity.fallDistance = 0;
// entity.onGround = true;
// break;
// case Z:
// entity.setMotion(motion.x, motion.y, 0);
// break;
// }
//
// break;
// }
// }
//
// if (!allowedMovement.equals(movement)) {
// if (allowedMovement.y != movement.y) {
// entity.fall(entity.fallDistance, 1);
// entity.fallDistance = 0;
// entity.onGround = true;
// }
// if (entity instanceof PlayerEntity && !world.isRemote)
// return;
// entity.setMotion(allowedMovement.subtract(movement.subtract(motion)));
// entity.velocityChanged = true;
// }
//
// }
// }
// }
public void add(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).add(mechanicalPistonTileEntity);
}
public void remove(MechanicalPistonTileEntity mechanicalPistonTileEntity) {
movingPistons.get(mechanicalPistonTileEntity.getWorld()).remove(mechanicalPistonTileEntity);
}
public List<MechanicalPistonTileEntity> getOtherMovingPistonsInWorld(
MechanicalPistonTileEntity mechanicalPistonTileEntity) {
return movingPistons.get(mechanicalPistonTileEntity.getWorld());
}
// @SubscribeEvent
// @OnlyIn(value = Dist.CLIENT)
// public static void onRenderWorld(RenderWorldLastEvent event) {
// for (AxisAlignedBB bb : renderedBBs) {
// TessellatorHelper.prepareForDrawing();
// GlStateManager.disableTexture();
// GlStateManager.lineWidth(3);
// int color = ColorHelper.rainbowColor(renderedBBs.indexOf(bb) * 170);
// WorldRenderer.drawSelectionBoundingBox(bb.grow(1 / 256f), (color >> 16 & 0xFF) / 256f,
// (color >> 8 & 0xFF) / 256f, (color & 0xFF) / 256f, 1);
// GlStateManager.lineWidth(1);
// GlStateManager.enableTexture();
// TessellatorHelper.cleanUpAfterDrawing();
// }
// }
}*/

View file

@ -1,4 +1,4 @@
package com.simibubi.create.modules.contraptions.components.constructs.piston;
package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_POLE;
@ -10,17 +10,19 @@ import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.components.constructs.Contraption;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.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.tileentity.TileEntity;
import net.minecraft.util.Direction;
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;
@ -39,9 +41,9 @@ public class PistonContraption extends Contraption {
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))
if (!construct.searchMovedStructure(world, construct.anchor, retract ? direction.getOpposite() : direction))
return null;
construct.initActors(world);
return construct;
}
@ -93,13 +95,18 @@ public class PistonContraption extends Contraption {
initialExtensionProgress = extensionsInFront;
pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront));
anchor = pos.offset(direction, initialExtensionProgress + 1);
if (extensionLength == 0)
return false;
for (BlockInfo pole : poles) {
BlockPos polePos = pole.pos.offset(direction, -extensionsInFront);
BlockPos polePos = pole.pos.offset(direction, -extensionsInFront).subtract(anchor);
blocks.put(polePos, new BlockInfo(polePos, pole.state, null));
pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos));
}
constructCollisionBox = new AxisAlignedBB(pos.offset(direction, initialExtensionProgress));
constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO.offset(direction, -initialExtensionProgress));
return true;
}
@ -125,14 +132,48 @@ public class PistonContraption extends Contraption {
return true;
}
protected void add(BlockPos pos, BlockInfo block) {
public void add(BlockPos pos, BlockInfo block) {
// super.add(pos, block);
super.add(pos.offset(orientation, -initialExtensionProgress), block);
}
@Override
public void readNBT(CompoundNBT nbt) {
super.readNBT(nbt);
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
super.disassemble(world, offset, yaw, pitch, (pos, state) -> {
BlockPos pistonPos = anchor.offset(orientation, -initialExtensionProgress - 1);
BlockState pistonState = world.getBlockState(pistonPos);
TileEntity te = world.getTileEntity(pistonPos);
if (pos.equals(pistonPos)) {
if (te == null || te.isRemoved())
return true;
if (!AllBlocks.PISTON_POLE.typeOf(state) && pistonState.getBlock() instanceof MechanicalPistonBlock)
world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED),
3);
return true;
}
return false;
});
}
@Override
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> {
BlockPos pistonPos = anchor.offset(orientation, -initialExtensionProgress - 1);
BlockState blockState = world.getBlockState(pos);
if (pos.equals(pistonPos) && blockState.getBlock() instanceof MechanicalPistonBlock) {
world.setBlockState(pos, blockState.with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66);
return true;
}
return false;
});
}
@Override
public void readNBT(World world, CompoundNBT nbt) {
super.readNBT(world, nbt);
extensionLength = nbt.getInt("ExtensionLength");
initialExtensionProgress = nbt.getInt("InitialLength");
orientation = Direction.byIndex(nbt.getInt("Orientation"));
if (nbt.contains("BoundsBack"))
pistonCollisionBox = readAABB(nbt.getList("BoundsBack", 5));
}
@ -145,7 +186,9 @@ public class PistonContraption extends Contraption {
ListNBT bb = writeAABB(pistonCollisionBox);
nbt.put("BoundsBack", bb);
}
nbt.putInt("InitialLength", initialExtensionProgress);
nbt.putInt("ExtensionLength", extensionLength);
nbt.putInt("Orientation", orientation.getIndex());
return nbt;
}

View file

@ -1,10 +1,10 @@
package com.simibubi.create.modules.contraptions.components.constructs.piston;
package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.components.constructs.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;

View file

@ -2,8 +2,8 @@ package com.simibubi.create.modules.contraptions.components.motor;
import com.simibubi.create.foundation.block.IBlockWithScrollableValue;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import net.minecraft.block.BlockState;

View file

@ -8,8 +8,8 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;

View file

@ -3,7 +3,7 @@ package com.simibubi.create.modules.contraptions.components.saw;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import net.minecraft.block.Block;
@ -21,8 +21,8 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;

View file

@ -2,8 +2,8 @@ package com.simibubi.create.modules.contraptions.processing;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.AllShapes;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;

View file

@ -4,7 +4,8 @@ import java.util.Random;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.modules.contraptions.components.constructs.IHaveMovementBehavior;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -15,6 +16,7 @@ import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.TickPriority;
@ -100,19 +102,32 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen
}
@Override
public void visitPosition(MovementContext context) {
public Vec3d getActiveAreaOffset(MovementContext context) {
return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f);
}
@Override
public void visitNewPosition(MovementContext context, BlockPos pos) {
BlockState block = context.state;
World world = context.world;
BlockPos pos = context.currentGridPos;
Direction direction = block.get(FACING);
if (!hasValidContact(world, pos, direction))
if (world.isRemote)
return;
int ticksToStayActive = (int) Math
.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);
BlockState visitedState = world.getBlockState(pos);
if (!AllBlocks.CONTACT.typeOf(visitedState))
return;
Vec3d contact = new Vec3d(block.get(FACING).getDirectionVec());
contact = VecHelper.rotate(contact, context.rotation.x, context.rotation.y, context.rotation.z);
Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z);
if (!hasValidContact(world, pos.offset(direction.getOpposite()), direction))
return;
int ticksToStayActive = 4;
world.setBlockState(pos, visitedState.with(POWERED, true));
world.getPendingBlockTicks().scheduleTick(pos, this, ticksToStayActive, TickPriority.NORMAL);
return;
}

View file

@ -1,14 +1,15 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import static net.minecraft.block.Block.makeCuboidShape;
import com.simibubi.create.foundation.utility.VoxelShaper;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import static net.minecraft.block.Block.makeCuboidShape;
public class BeltTunnelShapes {
private static VoxelShape block = makeCuboidShape(0, -5, 0, 16, 16, 16);

View file

@ -1,11 +1,14 @@
package com.simibubi.create.modules.contraptions.relays.gauge;
import java.util.Random;
import com.simibubi.create.foundation.block.RenderUtilityBlock;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -29,8 +32,6 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import java.util.Random;
public class GaugeBlock extends DirectionalAxisKineticBlock {
protected Type type;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.logistics.block.inventories;
import com.simibubi.create.foundation.utility.AllShapes;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;

View file

@ -10,9 +10,9 @@ import java.util.Set;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.VoxelShaper;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.VoxelShaper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.schematics.block;
import com.simibubi.create.foundation.utility.AllShapes;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.material.Material;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.schematics.block;
import com.simibubi.create.foundation.utility.AllShapes;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;

View file

@ -1,8 +1,8 @@
package com.simibubi.create.modules.schematics.block;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.utility.AllShapes;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;

View file

@ -16,8 +16,8 @@ import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen;
import com.simibubi.create.foundation.gui.widgets.IconButton;
import com.simibubi.create.foundation.gui.widgets.Indicator;
import com.simibubi.create.foundation.gui.widgets.Indicator.State;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.item.ItemDescription.Palette;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.schematics.packet.ConfigureSchematicannonPacket;
import com.simibubi.create.modules.schematics.packet.ConfigureSchematicannonPacket.Option;

View file

@ -73,6 +73,7 @@
"block.create.mechanical_crafter": "Mechanical Crafter",
"block.create.speed_gauge": "Speedometer",
"block.create.stress_gauge": "Stress Gauge",
"block.create.cart_assembler": "Cart Assembler",
"block.create.sticky_mechanical_piston": "Sticky Mechanical Piston",
"block.create.mechanical_piston": "Mechanical Piston",