Beispiel #1
0
        private Vec3i findFreeMetalVoxel()
        {
            SmithingRecipe recipe = SelectedRecipe;

            int ymax = recipe.QuantityLayers;

            for (int y = 5; y >= 0; y--)
            {
                for (int z = 0; z < 16; z++)
                {
                    for (int x = 0; x < 16; x++)
                    {
                        bool requireMetalHere = y >= ymax ? false : recipe.Voxels[x, y, z];
                        EnumVoxelMaterial mat = (EnumVoxelMaterial)Voxels[x, y, z];

                        if (!requireMetalHere && mat == EnumVoxelMaterial.Metal)
                        {
                            return(new Vec3i(x, y, z));
                        }
                    }
                }
            }

            return(null);
        }
Beispiel #2
0
        private void spawnParticles(Vec3i voxelPos, EnumVoxelMaterial voxelMat, IPlayer byPlayer)
        {
            float temp = workItemStack.Collectible.GetTemperature(Api.World, workItemStack);

            if (voxelMat == EnumVoxelMaterial.Metal && temp > 800)
            {
                bigMetalSparks.MinPos = Pos.ToVec3d().AddCopy(voxelPos.X / 16f, voxYOff + voxelPos.Y / 16f + 0.0625f, voxelPos.Z / 16f);
                bigMetalSparks.AddPos.Set(1 / 16f, 0, 1 / 16f);
                bigMetalSparks.VertexFlags = (byte)GameMath.Clamp((int)(temp - 700) / 2, 32, 128);
                Api.World.SpawnParticles(bigMetalSparks, byPlayer);

                smallMetalSparks.MinPos      = Pos.ToVec3d().AddCopy(voxelPos.X / 16f, voxYOff + voxelPos.Y / 16f + 0.0625f, voxelPos.Z / 16f);
                smallMetalSparks.VertexFlags = (byte)GameMath.Clamp((int)(temp - 770) / 3, 32, 128);
                smallMetalSparks.AddPos.Set(1 / 16f, 0, 1 / 16f);
                Api.World.SpawnParticles(smallMetalSparks, byPlayer);
            }

            if (voxelMat == EnumVoxelMaterial.Slag)
            {
                slagPieces.Color  = workItemStack.Collectible.GetRandomColor(Api as ICoreClientAPI, workItemStack);
                slagPieces.MinPos = Pos.ToVec3d().AddCopy(voxelPos.X / 16f, voxYOff + voxelPos.Y / 16f + 0.0625f, voxelPos.Z / 16f);

                Api.World.SpawnParticles(slagPieces, byPlayer);
            }
        }
Beispiel #3
0
        void onHelveHitSuccess(EnumVoxelMaterial mat, Vec3i usableMetalVoxel, int x, int y, int z)
        {
            if (Api.World.Side == EnumAppSide.Client)
            {
                spawnParticles(new Vec3i(x, y, z), mat == EnumVoxelMaterial.Empty ? EnumVoxelMaterial.Metal : mat, null);
                if (usableMetalVoxel != null)
                {
                    spawnParticles(usableMetalVoxel, EnumVoxelMaterial.Metal, null);
                }
            }

            RegenMeshAndSelectionBoxes();
            CheckIfFinished(null);
        }
Beispiel #4
0
        private void RegenOutlineMesh(bool[,,] recipeToOutlineVoxels, byte[,,] voxels)
        {
            recipeOutlineMeshRef?.Dispose();

            MeshData recipeOutlineMesh = new MeshData(24, 36, false, false, true, false);

            recipeOutlineMesh.SetMode(EnumDrawMode.Lines);

            int      greenCol        = (170 << 24) | (100 << 16) | (200 << 8) | (100);
            int      orangeCol       = (220 << 24) | (75 << 16) | (0 << 8) | (47);
            MeshData greenVoxelMesh  = LineMeshUtil.GetCube(greenCol);
            MeshData orangeVoxelMesh = LineMeshUtil.GetCube(orangeCol);

            for (int i = 0; i < greenVoxelMesh.xyz.Length; i++)
            {
                greenVoxelMesh.xyz[i]  = greenVoxelMesh.xyz[i] / 32f + 1 / 32f;
                orangeVoxelMesh.xyz[i] = orangeVoxelMesh.xyz[i] / 32f + 1 / 32f;
            }
            MeshData voxelMeshOffset = greenVoxelMesh.Clone();


            int yMax = recipeToOutlineVoxels.GetLength(1);

            for (int x = 0; x < 16; x++)
            {
                for (int y = 0; y < 6; y++)
                {
                    for (int z = 0; z < 16; z++)
                    {
                        bool requireMetalHere = y >= yMax ? false : recipeToOutlineVoxels[x, y, z];

                        EnumVoxelMaterial mat = (EnumVoxelMaterial)voxels[x, y, z];

                        if (requireMetalHere && mat == EnumVoxelMaterial.Metal)
                        {
                            continue;
                        }
                        if (!requireMetalHere && mat == EnumVoxelMaterial.Empty)
                        {
                            continue;
                        }

                        float px = x / 16f;
                        float py = 10 / 16f + y / 16f;
                        float pz = z / 16f;

                        for (int i = 0; i < greenVoxelMesh.xyz.Length; i += 3)
                        {
                            voxelMeshOffset.xyz[i]     = px + greenVoxelMesh.xyz[i];
                            voxelMeshOffset.xyz[i + 1] = py + greenVoxelMesh.xyz[i + 1];
                            voxelMeshOffset.xyz[i + 2] = pz + greenVoxelMesh.xyz[i + 2];
                        }

                        voxelMeshOffset.Rgba = (requireMetalHere && mat == EnumVoxelMaterial.Empty) ? greenVoxelMesh.Rgba : orangeVoxelMesh.Rgba;

                        recipeOutlineMesh.AddMeshData(voxelMeshOffset);
                    }
                }
            }

            recipeOutlineMeshRef = api.Render.UploadMesh(recipeOutlineMesh);
        }
Beispiel #5
0
        public virtual void OnHelveHammerHit()
        {
            if (workItemStack == null || !CanWorkCurrent)
            {
                return;
            }

            SmithingRecipe recipe = SelectedRecipe;

            if (recipe == null)
            {
                return;
            }

            var mode = (workItemStack.Collectible as IAnvilWorkable).GetHelveWorkableMode(workItemStack, this);

            if (mode == EnumHelveWorkableMode.NotWorkable)
            {
                return;
            }

            rotation = 0;
            int   ymax = recipe.QuantityLayers;
            Vec3i usableMetalVoxel;

            if (mode == EnumHelveWorkableMode.TestSufficientVoxelsWorkable)
            {
                usableMetalVoxel = findFreeMetalVoxel();

                for (int x = 0; x < 16; x++)
                {
                    for (int z = 0; z < 16; z++)
                    {
                        for (int y = 0; y < 6; y++)
                        {
                            bool requireMetalHere = y >= ymax ? false : recipe.Voxels[x, y, z];

                            EnumVoxelMaterial mat = (EnumVoxelMaterial)Voxels[x, y, z];

                            if (mat == EnumVoxelMaterial.Slag)
                            {
                                Voxels[x, y, z] = (byte)EnumVoxelMaterial.Empty;
                                onHelveHitSuccess(mat, null, x, y, z);
                                return;
                            }

                            if (requireMetalHere && usableMetalVoxel != null && mat == EnumVoxelMaterial.Empty)
                            {
                                Voxels[x, y, z] = (byte)EnumVoxelMaterial.Metal;
                                Voxels[usableMetalVoxel.X, usableMetalVoxel.Y, usableMetalVoxel.Z] = (byte)EnumVoxelMaterial.Empty;

                                onHelveHitSuccess(mat, usableMetalVoxel, x, y, z);
                                return;
                            }
                        }
                    }
                }

                if (usableMetalVoxel != null)
                {
                    Voxels[usableMetalVoxel.X, usableMetalVoxel.Y, usableMetalVoxel.Z] = (byte)EnumVoxelMaterial.Empty;
                    onHelveHitSuccess(EnumVoxelMaterial.Metal, null, usableMetalVoxel.X, usableMetalVoxel.Y, usableMetalVoxel.Z);
                    return;
                }
            }
            else
            {
                for (int y = 5; y >= 0; y--)
                {
                    for (int z = 0; z < 16; z++)
                    {
                        for (int x = 0; x < 16; x++)
                        {
                            bool requireMetalHere = y >= ymax ? false : recipe.Voxels[x, y, z];

                            EnumVoxelMaterial mat = (EnumVoxelMaterial)Voxels[x, y, z];

                            if (requireMetalHere && mat == EnumVoxelMaterial.Metal)
                            {
                                continue;
                            }
                            if (!requireMetalHere && mat == EnumVoxelMaterial.Empty)
                            {
                                continue;
                            }

                            if (requireMetalHere && mat == EnumVoxelMaterial.Empty)
                            {
                                Voxels[x, y, z] = (byte)EnumVoxelMaterial.Metal;
                            }
                            else
                            {
                                Voxels[x, y, z] = (byte)EnumVoxelMaterial.Empty;
                            }

                            onHelveHitSuccess(mat == EnumVoxelMaterial.Empty ? EnumVoxelMaterial.Metal : mat, null, x, y, z);

                            return;
                        }
                    }
                }
            }
        }
Beispiel #6
0
        internal void OnUseOver(IPlayer byPlayer, Vec3i voxelPos, BlockSelection blockSel)
        {
            if (voxelPos == null)
            {
                return;
            }

            if (SelectedRecipe == null)
            {
                ditchWorkItemStack();
                return;
            }

            // Send a custom network packet for server side, because
            // serverside blockselection index is inaccurate
            if (Api.Side == EnumAppSide.Client)
            {
                SendUseOverPacket(byPlayer, voxelPos);
            }


            ItemSlot slot = byPlayer.InventoryManager.ActiveHotbarSlot;

            if (slot.Itemstack == null || !CanWorkCurrent)
            {
                return;
            }
            int toolMode = slot.Itemstack.Collectible.GetToolMode(slot, byPlayer, blockSel);

            float yaw = GameMath.Mod(byPlayer.Entity.Pos.Yaw, 2 * GameMath.PI);


            EnumVoxelMaterial voxelMat = (EnumVoxelMaterial)Voxels[voxelPos.X, voxelPos.Y, voxelPos.Z];

            if (voxelMat != EnumVoxelMaterial.Empty)
            {
                spawnParticles(voxelPos, voxelMat, byPlayer);

                switch (toolMode)
                {
                case 0: OnHit(voxelPos); break;

                case 1: OnUpset(voxelPos, BlockFacing.NORTH.FaceWhenRotatedBy(0, yaw - GameMath.PIHALF, 0)); break;

                case 2: OnUpset(voxelPos, BlockFacing.EAST.FaceWhenRotatedBy(0, yaw - GameMath.PIHALF, 0)); break;

                case 3: OnUpset(voxelPos, BlockFacing.SOUTH.FaceWhenRotatedBy(0, yaw - GameMath.PIHALF, 0)); break;

                case 4: OnUpset(voxelPos, BlockFacing.WEST.FaceWhenRotatedBy(0, yaw - GameMath.PIHALF, 0)); break;

                case 5: OnSplit(voxelPos); break;
                }

                RegenMeshAndSelectionBoxes();
                Api.World.BlockAccessor.MarkBlockDirty(Pos);
                Api.World.BlockAccessor.MarkBlockEntityDirty(Pos);
                slot.Itemstack.Collectible.DamageItem(Api.World, byPlayer.Entity, slot);

                if (!HasAnyMetalVoxel())
                {
                    workItemStack = null;
                    return;
                }
            }

            CheckIfFinished(byPlayer);
            MarkDirty();
        }
Beispiel #7
0
        public static MeshData GenMesh(ICoreClientAPI capi, ItemStack workitemStack, byte[,,] voxels, out int textureId)
        {
            textureId = 0;
            if (workitemStack == null)
            {
                return(null);
            }

            MeshData workItemMesh = new MeshData(24, 36, false);

            workItemMesh.CustomBytes = new CustomMeshDataPartByte()
            {
                Conversion        = DataConversion.NormalizedFloat,
                Count             = workItemMesh.VerticesCount,
                InterleaveSizes   = new int[] { 1 },
                Instanced         = false,
                InterleaveOffsets = new int[] { 0 },
                InterleaveStride  = 1,
                Values            = new byte[workItemMesh.VerticesCount]
            };

            TextureAtlasPosition tposMetal;
            TextureAtlasPosition tposSlag;


            if (workitemStack.Collectible.FirstCodePart() == "ironbloom")
            {
                tposSlag  = capi.BlockTextureAtlas.GetPosition(capi.World.GetBlock(new AssetLocation("anvil-copper")), "ironbloom");
                tposMetal = capi.BlockTextureAtlas.GetPosition(capi.World.GetBlock(new AssetLocation("ingotpile")), "iron");
            }
            else
            {
                tposMetal = capi.BlockTextureAtlas.GetPosition(capi.World.GetBlock(new AssetLocation("ingotpile")), workitemStack.Collectible.LastCodePart());
                tposSlag  = tposMetal;
            }

            MeshData metalVoxelMesh = CubeMeshUtil.GetCubeOnlyScaleXyz(1 / 32f, 1 / 32f, new Vec3f(1 / 32f, 1 / 32f, 1 / 32f));

            CubeMeshUtil.SetXyzFacesAndPacketNormals(metalVoxelMesh);
            metalVoxelMesh.CustomBytes = new CustomMeshDataPartByte()
            {
                Conversion = DataConversion.NormalizedFloat,
                Count      = metalVoxelMesh.VerticesCount,
                Values     = new byte[metalVoxelMesh.VerticesCount]
            };

            textureId = tposMetal.atlasTextureId;

            metalVoxelMesh.XyzFaces      = (byte[])CubeMeshUtil.CubeFaceIndices.Clone();
            metalVoxelMesh.XyzFacesCount = 6;

            //metalVoxelMesh.ColorMapIds = new int[6];
            //metalVoxelMesh.TintsCount = 6;

            for (int i = 0; i < metalVoxelMesh.Rgba.Length; i++)
            {
                metalVoxelMesh.Rgba[i] = 255;
            }
            //metalVoxelMesh.Rgba2 = null;


            MeshData slagVoxelMesh = metalVoxelMesh.Clone();

            for (int i = 0; i < metalVoxelMesh.Uv.Length; i++)
            {
                if (i % 2 > 0)
                {
                    metalVoxelMesh.Uv[i] = tposMetal.y1 + metalVoxelMesh.Uv[i] * 2f / capi.BlockTextureAtlas.Size.Height;

                    slagVoxelMesh.Uv[i] = tposSlag.y1 + slagVoxelMesh.Uv[i] * 2f / capi.BlockTextureAtlas.Size.Height;
                }
                else
                {
                    metalVoxelMesh.Uv[i] = tposMetal.x1 + metalVoxelMesh.Uv[i] * 2f / capi.BlockTextureAtlas.Size.Width;

                    slagVoxelMesh.Uv[i] = tposSlag.x1 + slagVoxelMesh.Uv[i] * 2f / capi.BlockTextureAtlas.Size.Width;
                }
            }

            MeshData metVoxOffset  = metalVoxelMesh.Clone();
            MeshData slagVoxOffset = slagVoxelMesh.Clone();

            for (int x = 0; x < 16; x++)
            {
                for (int y = 0; y < 6; y++)
                {
                    for (int z = 0; z < 16; z++)
                    {
                        EnumVoxelMaterial mat = (EnumVoxelMaterial)voxels[x, y, z];
                        if (mat == EnumVoxelMaterial.Empty)
                        {
                            continue;
                        }

                        float px = x / 16f;
                        float py = 10 / 16f + y / 16f;
                        float pz = z / 16f;

                        MeshData mesh          = mat == EnumVoxelMaterial.Metal ? metalVoxelMesh : slagVoxelMesh;
                        MeshData meshVoxOffset = mat == EnumVoxelMaterial.Metal ? metVoxOffset : slagVoxOffset;

                        for (int i = 0; i < mesh.xyz.Length; i += 3)
                        {
                            meshVoxOffset.xyz[i]     = px + mesh.xyz[i];
                            meshVoxOffset.xyz[i + 1] = py + mesh.xyz[i + 1];
                            meshVoxOffset.xyz[i + 2] = pz + mesh.xyz[i + 2];
                        }

                        float textureSize = 32f / capi.BlockTextureAtlas.Size.Width;

                        float offsetX = px * textureSize;
                        float offsetY = (py * 32f) / capi.BlockTextureAtlas.Size.Width;
                        float offsetZ = pz * textureSize;

                        for (int i = 0; i < mesh.Uv.Length; i += 2)
                        {
                            meshVoxOffset.Uv[i]     = mesh.Uv[i] + GameMath.Mod(offsetX + offsetY, textureSize);
                            meshVoxOffset.Uv[i + 1] = mesh.Uv[i + 1] + GameMath.Mod(offsetZ + offsetY, textureSize);
                        }

                        for (int i = 0; i < meshVoxOffset.CustomBytes.Values.Length; i++)
                        {
                            byte glowSub = (byte)GameMath.Clamp(10 * (Math.Abs(x - 8) + Math.Abs(z - 8) + Math.Abs(y - 2)), 100, 250);
                            meshVoxOffset.CustomBytes.Values[i] = (mat == EnumVoxelMaterial.Metal) ? (byte)0 : glowSub;
                        }

                        workItemMesh.AddMeshData(meshVoxOffset);
                    }
                }
            }

            return(workItemMesh);
        }