/// <summary> /// Gets the ordinal value associated with the specified side. /// Returns 255 if the parameter contains multiple sides. /// </summary> public static byte ToOrdinal(BlockSides side) { switch (side) { case BlockSides.Right: return(0); case BlockSides.Left: return(1); case BlockSides.Top: return(2); case BlockSides.Bottom: return(3); case BlockSides.Front: return(4); case BlockSides.Back: return(5); default: return(255); } }
/// <summary> /// Serializes a rotation into a buffer using 5 bits. /// </summary> public static void Serialize(BitBuffer buffer, byte rotation) { BlockSides facing = GetFacing(rotation); buffer.WriteBits(BlockSide.ToOrdinal(facing), 3); buffer.WriteBits((ulong)GetAmount(rotation, (facing & BlockSides.Y) != BlockSides.None ? 1 : 0), 2); }
/// <summary> /// Returns false if the offset value is out of bounds. /// </summary> // ReSharper disable once AnnotateCanBeNullParameter public bool GetOffset(BlockSides side, out BlockPosition output) { switch (side) { case BlockSides.Right: output = X == MaxAxisValue ? null : new BlockPosition(X + 1, Y, Z); break; case BlockSides.Left: output = X == 0 ? null : new BlockPosition(X - 1, Y, Z); break; case BlockSides.Top: output = Y == MaxAxisValue ? null : new BlockPosition(X, Y + 1, Z); break; case BlockSides.Bottom: output = Y == 0 ? null : new BlockPosition(X, Y - 1, Z); break; case BlockSides.Front: output = Z == MaxAxisValue ? null : new BlockPosition(X, Y, Z + 1); break; case BlockSides.Back: output = Z == 0 ? null : new BlockPosition(X, Y, Z - 1); break; default: throw new AssertionException("Invalid side: " + side, null); } return(output != null); }
private static float ForceData(Transform bot, BlockSides facing, float x, float y, float z, out Vector3 direction) { switch (facing) { case BlockSides.Right: direction = bot.right; return(x < 0 ? 0f : x); case BlockSides.Left: direction = bot.right; return(x > 0 ? 0f : x); case BlockSides.Top: direction = bot.up; return(y < 0 ? 0f : y); case BlockSides.Bottom: direction = bot.up; return(y > 0 ? 0f : y); case BlockSides.Front: direction = bot.forward; return(z < 0 ? 0f : z); case BlockSides.Back: direction = bot.forward; return(z > 0 ? 0f : z); default: throw new AssertionException("Invalid facing: " + facing, null); } }
private static void RemoveConnectedBlocks <T>(T block, int ignoreBit, IDictionary <BlockPosition, T> blocks) where T : IBlock { Assert.IsTrue(blocks.Remove(block.Position), "The block is no longer in the dictionary."); for (int bit = 0; bit < 6; bit++) { if (bit == ignoreBit) { continue; } BlockSides side = block.ConnectSides & (BlockSides)(1 << bit); if (side == BlockSides.None || !block.Position.GetOffset(side, out BlockPosition offset) || !blocks.TryGetValue(offset, out T other)) { continue; } int inverseBit = bit % 2 == 0 ? bit + 1 : bit - 1; if ((other.ConnectSides & (BlockSides)(1 << inverseBit)) != BlockSides.None) { RemoveConnectedBlocks(other, inverseBit, blocks); } } }
/// <summary> /// Rotates all of the specified sides by the specified rotation around all axises. /// </summary> public static BlockSides RotateSides(BlockSides sides, byte rotation) { if (rotation == 0 || sides == BlockSides.None || sides == BlockSides.All) { return(sides); } int facingAxis = GetAmount(rotation, 3); int variantStorage = facingAxis == 1 ? 1 : 0; int output = (int)sides; for (int axis = 2; axis >= 0; axis--) { if (axis == variantStorage) { continue; } int amount = GetAmount(rotation, axis); if (amount == 0) { continue; } output = RotateSidesAroundAxis(output, amount, axis); } int variant = GetAmount(rotation, variantStorage); output = RotateSidesAroundAxis(output, facingAxis == 2 ? (4 - variant) % 4 : variant, facingAxis); return((BlockSides)output); }
private static void InitializeMulti(IMultiBlockParent parent, MultiBlockInfo info, byte rotation, BlockPosition position, KeyValuePair <BlockPosition, BlockSides>[] partPositions, Function <int, IMultiBlockPart[]> partsArrayConstructor, Function <KeyValuePair <BlockPosition, BlockSides>, IMultiBlockPart> partConstructor, out IMultiBlockPart[] parts) { BlockSides parentSides = BlockSides.None; parts = partsArrayConstructor(partPositions.Length - 1); int partsIndex = 0; foreach (KeyValuePair <BlockPosition, BlockSides> pair in partPositions) { if (pair.Key.Equals(position)) { parentSides = pair.Value; } else { parts[partsIndex++] = partConstructor(pair); } } foreach (IMultiBlockPart part in parts) { part.Initialize(parent); } parent.Initialize(parentSides, position, info, rotation, parts); }
/// <summary> /// The Y axis will face towards the specified facing. /// The variant specifies extra rotation around the facing axis. /// It can be any number, it DOESN'T have to be less than 4. /// </summary> public static byte GetByte(BlockSides facing, byte variant) { switch (facing) { case BlockSides.Right: return(GetByte(variant, 0, 3, 0)); case BlockSides.Left: return(GetByte(variant, 0, 1, 0)); case BlockSides.Top: return(GetByte(0, variant, 0, 1)); case BlockSides.Bottom: return(GetByte(2, variant, 0, 1)); case BlockSides.Front: return(GetByte(variant, 1, 1, 2)); case BlockSides.Back: return(GetByte(variant, 1, 3, 2)); default: throw new AssertionException("Invalid facing: " + facing, null); } }
public FileReference GetTextureForSide(BlockSides side) { if (side == BlockSides.Top) { return new FileReference("grass.png"); } return new FileReference("dirt.png"); }
public void Initialize(BlockSides connectSides, BlockPosition position, MultiBlockInfo info, byte rotation, IMultiBlockPart[] parts) { ConnectSides = connectSides; Position = position; Type = info.Type; Rotation = rotation; Parts = (PlacedMultiBlockPart[])parts; }
public void Initialize(BlockSides connectSides, BlockPosition position, MultiBlockInfo info, byte rotation, IMultiBlockPart[] parts) { ConnectSides = connectSides; Position = position; Info = info; Rotation = rotation; Parts = (LiveMultiBlockPart[])parts; InitializeBase(); }
public void RotateSides_Manual() { const BlockSides sides = BlockSides.X | BlockSides.Bottom | BlockSides.Back; BlockSides facing = BlockSides.Back; Assert.AreEqual( BlockSides.Left | BlockSides.Y | BlockSides.Front, Rotation.RotateSides(sides, Rotation.GetByte(facing, 0)) ); Assert.AreEqual( BlockSides.X | BlockSides.Top | BlockSides.Front, Rotation.RotateSides(sides, Rotation.GetByte(facing, 1)) ); Assert.AreEqual( BlockSides.Right | BlockSides.Y | BlockSides.Front, Rotation.RotateSides(sides, Rotation.GetByte(facing, 2)) ); Assert.AreEqual( BlockSides.X | BlockSides.Bottom | BlockSides.Front, Rotation.RotateSides(sides, Rotation.GetByte(facing, 3)) ); facing = BlockSides.Right; Assert.AreEqual( BlockSides.Left | BlockSides.Bottom | BlockSides.Z, Rotation.RotateSides(sides, Rotation.GetByte(facing, 3)) ); facing = BlockSides.Bottom; Assert.AreEqual( BlockSides.X | BlockSides.Top | BlockSides.Front, Rotation.RotateSides(sides, Rotation.GetByte(facing, 0)) ); Assert.AreEqual( BlockSides.X | BlockSides.Top | BlockSides.Back, Rotation.RotateSides(sides, Rotation.GetByte(facing, 2)) ); Assert.AreEqual( BlockSides.Right | BlockSides.Top | BlockSides.Z, Rotation.RotateSides(sides, Rotation.GetByte(facing, 1)) ); Assert.AreEqual( BlockSides.Left | BlockSides.Top | BlockSides.Z, Rotation.RotateSides(sides, Rotation.GetByte(facing, 3)) ); }
public FileReference GetTextureForSide(BlockSides side) { switch(side) { case BlockSides.Left: return new FileReference(Left); case BlockSides.Right: return new FileReference(Right); case BlockSides.Front: return new FileReference(Front); case BlockSides.Back: return new FileReference(Back); case BlockSides.Top: return new FileReference(Top); case BlockSides.Bottom: return new FileReference(Bottom); } return new FileReference("invalid.png"); }
public FileReference GetTextureForSide(BlockSides side) { // if(side == BlockSides.Top) // return new FileReference("stone_top.png"); // if(side == BlockSides.Bottom) // return new FileReference("stone_bottom.png"); // if(side == BlockSides.Left) // return new FileReference("stone_left.png"); // if(side == BlockSides.Right) // return new FileReference("stone_right.png"); // if(side == BlockSides.Front) // return new FileReference("stone_front.png"); // if(side == BlockSides.Back) // return new FileReference("stone_back.png"); return new FileReference("stone.png"); }
/// <summary> /// Determines whether a block at the specified position with the specified /// connection sides can connect to any other block. /// </summary> private bool CanConnect(BlockPosition position, BlockSides rotatedConnectSides) { for (int bit = 0; bit < 6; bit++) { BlockSides side = rotatedConnectSides & (BlockSides)(1 << bit); if (side == BlockSides.None || !position.GetOffseted(side, out BlockPosition offseted) || !_blocks.TryGetValue(offseted, out IPlacedBlock block)) { continue; } int inverseBit = bit % 2 == 0 ? bit + 1 : bit - 1; if ((block.ConnectSides & (BlockSides)(1 << inverseBit)) != BlockSides.None) { return(true); } } return(false); }
public void RotateSides_FixedSideCount() { const byte max = byte.MaxValue >> 2; //00 11 11 11 for (byte sideByte = 0; sideByte <= max; sideByte++) { int count = BitCount(sideByte); BlockSides sides = (BlockSides)sideByte; for (int facingBit = 0; facingBit < 6; facingBit++) { BlockSides facing = (BlockSides)(1 << facingBit); for (byte variant = 0; variant < 4; variant++) { Assert.AreEqual( count, BitCount((byte)Rotation.RotateSides(sides, Rotation.GetByte(facing, variant))) ); } } } }
public static Vector3Int GetNormal(BlockSides drawSide) { Vector3Int normal; switch (drawSide) { case BlockSides.Right: normal = Vector3Int.right; break; case BlockSides.Left: normal = Vector3Int.left; break; case BlockSides.Up: normal = Vector3Int.up; break; case BlockSides.Down: normal = Vector3Int.down; break; case BlockSides.Front: normal = new Vector3Int(0, 0, 1); break; case BlockSides.Back: normal = new Vector3Int(0, 0, -1); break; default: normal = Vector3Int.zero; break; } return(normal); }
public uint GetMaterialCode(BlockSides side) { switch (Material) { case 3: // Grass, TODO: Material type enum switch (side) { case BlockSides.Back: case BlockSides.Front: case BlockSides.Left: case BlockSides.Right: return(Material + 0x100u); case BlockSides.Top: return(Material + 0x200u); default: return(Material); } default: return(Material); } }
private static void AddSingle(BlockType type, uint health, uint mass, BlockSides connectSides) { Blocks[(ushort)type] = new SingleBlockInfo(type, health, mass, Resources.Load("Blocks/" + type) as GameObject, connectSides); }
public ThrusterSystem(CompleteStructure structure, RealLiveBlock block, ThrusterConstants constants) : base(structure, block) { Constants = constants; _facing = Rotation.RotateSides(constants.Facing, block.Rotation); }
public static Mesh GenerateMesh(Vector3Int chunkIndex) { #region SetupMesh Mesh mesh = new Mesh(); List <Vector3> vericies = new List <Vector3>(); List <int> triangles = new List <int>(); List <Vector2> uv = new List <Vector2>(); List <Vector3> normals = new List <Vector3>(); #endregion Fill(); AssignMesh(); return(mesh); void Fill() { for (int x = 0; x < ChunckData.chunkSize; x++) { for (int z = 0; z < ChunckData.chunkSize; z++) { for (int y = 0; y < ChunckData.chunkSize; y++) { Vector3Int position = new Vector3Int(x, y, z); SetBlock( position, GetVisibleSidesOfBlock(position)); } } } BlockSides GetVisibleSidesOfBlock(Vector3Int position) { BlockSides drawSides = 0; if (WorldChunksData.GetBlock(chunkIndex, position) is SimpleBlockBase) { foreach (Enum value in Enum.GetValues(typeof(BlockSides))) { if ((BlockSides)value != BlockSides.None) { if (!(WorldChunksData.GetBlock(chunkIndex, position + BlockSidesUtils.GetNormal((BlockSides)value)) is SimpleBlockBase)) { drawSides += (int)(BlockSides)value; } } } } return(drawSides); } void SetBlock(Vector3Int position, BlockSides drawSides) { foreach (Enum value in Enum.GetValues(typeof(BlockSides))) { if ((BlockSides)value != BlockSides.None) { if (drawSides.HasFlag(value)) { SetSide((BlockSides)value); } } } void SetSide(BlockSides drawSide) { SetUVandNormals(); SetTriangles(); SetVerticies(); void SetUVandNormals() { uv.Add(Vector2.zero); uv.Add(Vector2.up); uv.Add(Vector2.right); uv.Add(Vector2.one); for (int i = 0; i < 4; i++) { normals.Add(BlockSidesUtils.GetNormal(drawSide)); } } void SetTriangles() { //first triangle triangles.Add(vericies.Count); triangles.Add(vericies.Count + 1); triangles.Add(vericies.Count + 2); //second triangle triangles.Add(vericies.Count + 2); triangles.Add(vericies.Count + 1); triangles.Add(vericies.Count + 3); } void SetVerticies() { switch (drawSide) { case BlockSides.Right: vericies.Add(position + new Vector3(1, 0, 0)); vericies.Add(position + new Vector3(1, 1, 0)); vericies.Add(position + new Vector3(1, 0, 1)); vericies.Add(position + new Vector3(1, 1, 1)); break; case BlockSides.Left: vericies.Add(position + new Vector3(0, 0, 1)); vericies.Add(position + new Vector3(0, 1, 1)); vericies.Add(position + new Vector3(0, 0, 0)); vericies.Add(position + new Vector3(0, 1, 0)); break; case BlockSides.Up: vericies.Add(position + new Vector3(0, 1, 1)); vericies.Add(position + new Vector3(1, 1, 1)); vericies.Add(position + new Vector3(0, 1, 0)); vericies.Add(position + new Vector3(1, 1, 0)); break; case BlockSides.Down: vericies.Add(position + new Vector3(0, 0, 0)); vericies.Add(position + new Vector3(1, 0, 0)); vericies.Add(position + new Vector3(0, 0, 1)); vericies.Add(position + new Vector3(1, 0, 1)); break; case BlockSides.Front: vericies.Add(position + new Vector3(1, 0, 1)); vericies.Add(position + new Vector3(1, 1, 1)); vericies.Add(position + new Vector3(0, 0, 1)); vericies.Add(position + new Vector3(0, 1, 1)); break; case BlockSides.Back: vericies.Add(position + new Vector3(0, 0, 0)); vericies.Add(position + new Vector3(0, 1, 0)); vericies.Add(position + new Vector3(1, 0, 0)); vericies.Add(position + new Vector3(1, 1, 0)); break; } } } } } void AssignMesh() { mesh.vertices = vericies.ToArray(); mesh.triangles = triangles.ToArray(); mesh.uv = uv.ToArray(); mesh.normals = normals.ToArray(); } }
public ThrusterConstants(Vector3 offset, float force, BlockSides facing) { Offset = offset; Force = force; Facing = facing; }
/// <summary> /// Sets the sides at which a specific part of the multi block can connect to other blocks. /// Returns itself for chaining. 0;0;0 must be set. /// </summary> public MultiBlockInfo Add(byte x, byte y, byte z, BlockSides connectSides) { _partConnectSides.Add(new KeyValuePair <Vector3Int, BlockSides>(new Vector3Int(x, y, z), connectSides)); return(this); }
/// <summary> /// Checks if the current block has a certain side /// </summary> /// <param name="side">Side to check</param> /// <returns>True if the block has <paramref name="side"/> as side</returns> public bool HasSide(BlockSides side) { return((Sides & side) != 0); }
/// <summary> /// Create a new renderable block instance /// </summary> /// <param name="position">Draw position</param> /// <param name="sides">Sides to draw</param> public GraphicalBlock(Vector3 position, BlockSides sides, MaterialType material) { Sides = sides; Position = position; Material = (ushort)material; }
public PlacedMultiBlockPart(BlockSides connectSides, BlockPosition position) { ConnectSides = connectSides; Position = position; }
public SingleBlockInfo(BlockType type, uint health, uint mass, GameObject prefab, BlockSides connectSides) : base(type, health, mass, prefab) { ConnectSides = connectSides; }
/* _________________________ (1,1,0) / _________Top_________ /| / / ___________________/ / | / / /| | / / | /|\ / / / | | / / . | | / / /| | | / / /| | | / / / | | | / / / | | | / / / | | | / / /| | | | +Y axis / /_/__________________/ / / | | | | /________________________/ / | | | | Left--> | ______________________ | | | | | | | | | | | |_________| | |__| | | | | | | | |___________| | |____| | | | | | / / ___________| | |_ / / | | | / / / | | |/ / / / | | | / / / | | | / / / | | |/ / / | | |/ / / | | | / / | | ' / / +Z axis | | |/_/_______________| | / / | |____________________| | / / |________Front___________|/ \/ (0,0,1) ----------------------> +X axis */ public static void createCubeSide(ref IList<VertexPositionColorTexture> vertexes, ref IList<short> indices, Vector3 frontBottomLeftOfCube, BlockSides sideType, ITextureReference texture) { //Create vertexes float x = frontBottomLeftOfCube.X; float y = frontBottomLeftOfCube.Y; float z = frontBottomLeftOfCube.Z; RectangleF textLoc = texture.TextureLocation; switch (sideType) { case BlockSides.Front: appendIndiciesForSideOfCube(ref vertexes, ref indices); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y - 0.0f, z - 0.0f, Color.Gray, textLoc.X, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y - 0.0f, z - 0.0f, Color.Gray, textLoc.X + textLoc.Width, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y + 1.0f, z - 0.0f, Color.White, textLoc.X + textLoc.Width, textLoc.Y + textLoc.Height)); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y + 1.0f, z - 0.0f, Color.White, textLoc.X, textLoc.Y + textLoc.Height)); break; case BlockSides.Back: appendIndiciesForSideOfCube(ref vertexes, ref indices); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y + 1.0f, z + 1.0f, Color.White, textLoc.X, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y + 1.0f, z + 1.0f, Color.White, textLoc.X + textLoc.Width, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y - 0.0f, z + 1.0f, Color.Gray, textLoc.X + textLoc.Width, textLoc.Y + textLoc.Height)); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y - 0.0f, z + 1.0f, Color.Gray, textLoc.X, textLoc.Y + textLoc.Height)); break; case BlockSides.Left: appendIndiciesForSideOfCube(ref vertexes, ref indices); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y - 0.0f, z + 1.0f, Color.Gray, textLoc.X, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y - 0.0f, z - 0.0f, Color.Gray, textLoc.X + textLoc.Width, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y + 1.0f, z - 0.0f, Color.White, textLoc.X + textLoc.Width, textLoc.Y + textLoc.Height)); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y + 1.0f, z + 1.0f, Color.White, textLoc.X, textLoc.Y + textLoc.Height)); break; case BlockSides.Right: appendIndiciesForSideOfCube(ref vertexes, ref indices); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y + 1.0f, z + 1.0f, Color.White, textLoc.X, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y + 1.0f, z - 0.0f, Color.White, textLoc.X + textLoc.Width, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y - 0.0f, z - 0.0f, Color.Gray, textLoc.X + textLoc.Width, textLoc.Y + textLoc.Height)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y - 0.0f, z + 1.0f, Color.Gray, textLoc.X, textLoc.Y + textLoc.Height)); break; case BlockSides.Top: appendIndiciesForSideOfCube(ref vertexes, ref indices); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y + 1.0f, z - 0.0f, Color.White, textLoc.X, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y + 1.0f, z - 0.0f, Color.White, textLoc.X + textLoc.Width, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y + 1.0f, z + 1.0f, Color.White, textLoc.X + textLoc.Width, textLoc.Y + textLoc.Height)); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y + 1.0f, z + 1.0f, Color.White, textLoc.X, textLoc.Y + textLoc.Height)); break; case BlockSides.Bottom: appendIndiciesForSideOfCube(ref vertexes, ref indices); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y - 0.0f, z + 1.0f, Color.Gray, textLoc.X, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y - 0.0f, z + 1.0f, Color.Gray, textLoc.X + textLoc.Width, textLoc.Y)); vertexes.Add(new VertexPositionColorTexture(x + 1.0f, y - 0.0f, z - 0.0f, Color.Gray, textLoc.X + textLoc.Width, textLoc.Y + textLoc.Height)); vertexes.Add(new VertexPositionColorTexture(x - 0.0f, y - 0.0f, z - 0.0f, Color.Gray, textLoc.X, textLoc.Y + textLoc.Height)); break; } }