Ejemplo n.º 1
0
        /// <inheritdoc />
        public bool Passes(IBlockAccess world, Vector3 position, string rule, string value)
        {
            if (!MultiPartModels.TryGetBlockface(rule, out BlockFace face))
            {
                return(false);
            }

            Vector3 offset = face.GetVector3();

            offset = position + offset;

            if (value == "side|up")
            {
                return(IsRedstoneWire(world, offset) ||
                       IsRedstoneWire(world, offset + Vector3.Down));
            }
            else if (value == "up")
            {
                return(IsRedstoneWire(world, offset + Vector3.Up));
            }
            else if (value == "none")
            {
                return(!IsRedstoneWire(world, offset));
            }

            return(false);
        }
Ejemplo n.º 2
0
        private static BlockModel ResolveModel(ResourceManager resources, McResourcePack resourcePack,
                                               BlockState state)
        {
            string name = state.Name;

            if (string.IsNullOrWhiteSpace(name))
            {
                Log.Warn($"State name is null!");
                return(null);
            }

            if (name.Contains("water"))
            {
                return(new LiquidBlockModel()
                {
                    //	IsFlowing = false,
                    IsLava = false,
                    //	Level = state.GetTypedValue(Water.LEVEL)
                });
            }

            if (name.Contains("lava"))
            {
                return(new LiquidBlockModel()
                {
                    //	IsFlowing = false,
                    IsLava = true,
                    //	Level = state.GetTypedValue(Water.LEVEL)
                });;
            }

            BlockStateResource blockStateResource;

            if (resourcePack.BlockStates.TryGetValue(name, out blockStateResource))
            {
                if (blockStateResource != null && blockStateResource.Parts != null &&
                    blockStateResource.Parts.Length > 0 &&
                    blockStateResource.Parts.All(x => x.Apply.All(b => b.Model != null)))
                {
                    var models = MultiPartModels.GetModels(state, blockStateResource);


                    state.MultiPartHelper = blockStateResource;
                    state.IsMultiPart     = true;
                    state.AppliedModels   = models.Select(x => x.ModelName).ToArray();

                    return(new ResourcePackBlockModel(resources, models));
                }

                if (blockStateResource?.Variants == null ||
                    blockStateResource.Variants.Count == 0)
                {
                    return(null);
                }

                if (blockStateResource.Variants.Count == 1)
                {
                    var v = blockStateResource.Variants.FirstOrDefault();
                    if (v.Value == null)
                    {
                        return(null);
                    }

                    var models = v.Value.Where(x => x.Model?.Elements != null && x.Model.Elements.Length > 0).ToArray();

                    if (models.Length == 0)
                    {
                        return(null);
                    }

                    return(new ResourcePackBlockModel(resources, models, v.Value.ToArray().Length > 1));
                }

                BlockStateVariant blockStateVariant = null;

                var data = state.ToDictionary();
                //	data.Remove("waterlogged");

                int closestMatch = 0;
                KeyValuePair <string, BlockStateVariant> closest = default(KeyValuePair <string, BlockStateVariant>);
                foreach (var v in blockStateResource.Variants)
                {
                    int matches           = 0;
                    var variantBlockState = Blocks.State.BlockState.FromString(v.Key);

                    foreach (var kv in data)
                    {
                        if (variantBlockState.TryGetValue(kv.Key, out string vValue))
                        {
                            if (vValue.Equals(kv.Value, StringComparison.InvariantCultureIgnoreCase))
                            {
                                matches++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (matches > closestMatch)
                    {
                        closestMatch = matches;
                        closest      = v;

                        if (matches == data.Count)
                        {
                            break;
                        }
                    }
                }

                blockStateVariant = closest.Value;

                if (blockStateVariant == null)
                {
                    var a = blockStateResource.Variants.FirstOrDefault();
                    blockStateVariant = a.Value;
                }

                var asArray = blockStateVariant.ToArray();

                if (asArray.Length == 0 || asArray.Any(x => x.Model?.Elements == null || x.Model.Elements.Length == 0))
                {
                    return(null);
                }

                return(new ResourcePackBlockModel(resources, asArray, asArray.Length > 1));
            }

            return(null);
        }
Ejemplo n.º 3
0
        private ChunkMesh GenerateSectionMesh(IWorld world, ScheduleType scheduled, Vector3 chunkPosition,
                                              ref ChunkSection section, int yIndex)
        {
            var force = section.New || section.MeshCache == null || section.MeshPositions == null;

            var cached        = section.MeshCache;
            var positionCache = section.MeshPositions;

            Dictionary <Vector3, ChunkMesh.EntryPosition> positions = new Dictionary <Vector3, ChunkMesh.EntryPosition>();

            List <VertexPositionNormalTextureColor> solidVertices = new List <VertexPositionNormalTextureColor>();

            List <int> animatedIndexes    = new List <int>();
            List <int> transparentIndexes = new List <int>();
            List <int> solidIndexes       = new List <int>();

            Dictionary <int, int> processedIndices = new Dictionary <int, int>();

            for (var y = 0; y < 16; y++)
            {
                for (var x = 0; x < ChunkColumn.ChunkWidth; x++)
                {
                    for (var z = 0; z < ChunkColumn.ChunkDepth; z++)
                    {
                        var blockPosition = new Vector3(x, y + (yIndex << 4), z) + chunkPosition;

                        bool isScheduled        = section.IsScheduled(x, y, z);
                        var  neighborsScheduled = HasScheduledNeighbors(world, blockPosition);
                        // bool isLightingScheduled = section.IsLightingScheduled(x, y, z);

                        var isBorderBlock = (scheduled == ScheduleType.Border && (x == 0 || x == 15) || (z == 0 || z == 15));

                        var blockState = section.Get(x, y, z);

                        if (((blockState == null || !blockState.Block.Renderable) ||
                             (!section.New &&
                              !neighborsScheduled)) && !force && !isBorderBlock)
                        {
                            continue;
                        }

                        var shouldRebuildVertices = (force || isScheduled || neighborsScheduled || isBorderBlock);

                        var model = blockState.Model;

                        if (blockState != null && shouldRebuildVertices && blockState.Block.RequiresUpdate)
                        {
                            blockState = blockState.Block.BlockPlaced(world, blockState, blockPosition);
                            section.Set(x, y, z, blockState);

                            model = blockState.Model;
                        }

                        if (blockState is BlockState state && state.IsMultiPart && shouldRebuildVertices)
                        {
                            model = new CachedResourcePackModel(Game.Resources,
                                                                MultiPartModels.GetBlockStateModels(world, blockPosition, state, state.MultiPartHelper));
                            // blockState.Block.Update(world, blockPosition);
                        }

                        if (!shouldRebuildVertices && positionCache.TryGetValue(new Vector3(x, y, z), out var pos))
                        {
                            var indices = pos.Animated
                                                ? cached.AnimatedIndexes
                                                : (pos.Transparent ? cached.TransparentIndexes : cached.SolidIndexes);

                            var indiceIndex = pos.Animated
                                                ? animatedIndexes.Count
                                                : (pos.Transparent ? transparentIndexes.Count : solidIndexes.Count);
                            for (int index = 0; index < pos.Length; index++)
                            {
                                var indice = indices[pos.Index + index];
                                if (!processedIndices.TryGetValue(indice, out var newIndex))
                                {
                                    newIndex = solidVertices.Count;
                                    var vertice = cached.Vertices[indice];
                                    solidVertices.Add(vertice);

                                    processedIndices.Add(indice, newIndex);
                                }

                                if (pos.Animated)
                                {
                                    animatedIndexes.Add(newIndex);
                                }
                                else if (pos.Transparent)
                                {
                                    transparentIndexes.Add(newIndex);
                                }
                                else
                                {
                                    solidIndexes.Add(newIndex);
                                }
                            }

                            positions.TryAdd(new Vector3(x, y, z),
                                             new ChunkMesh.EntryPosition(pos.Transparent, pos.Animated, indiceIndex, pos.Length));
                        }
                        else if (shouldRebuildVertices)
                        {
                            var data = model.GetVertices(world, blockPosition, blockState.Block);

                            if (data.vertices.Length == 0 ||
                                data.indexes.Length == 0)
                            {
                                section.SetRendered(x, y, z, false);
                            }

                            if (data.vertices == null || data.indexes == null || data.vertices.Length == 0 ||
                                data.indexes.Length == 0)
                            {
                                //section.SetRendered(x, y, z, false);
                                if (isScheduled)
                                {
                                    section.SetScheduled(x, y, z, false);
                                }

                                continue;
                            }

                            bool transparent = blockState.Block.Transparent;
                            bool animated    = blockState.Block.Animated;

                            if (data.vertices.Length > 0 && data.indexes.Length > 0)
                            {
                                section.SetRendered(x, y, z, true);

                                int startVerticeIndex = solidVertices.Count;
                                foreach (var vert in data.vertices)
                                {
                                    solidVertices.Add(vert);
                                }

                                int startIndex = animated ? animatedIndexes.Count : (transparent ? transparentIndexes.Count : solidIndexes.Count);
                                for (int i = 0; i < data.indexes.Length; i++)
                                {
                                    var a = data.indexes[i];

                                    if (animated)
                                    {
                                        animatedIndexes.Add(startVerticeIndex + a);
                                    }
                                    else if (transparent)
                                    {
                                        transparentIndexes.Add(startVerticeIndex + a);
                                    }
                                    else
                                    {
                                        solidIndexes.Add(startVerticeIndex + a);
                                    }
                                }

                                positions.TryAdd(new Vector3(x, y, z),
                                                 new ChunkMesh.EntryPosition(transparent, animated, startIndex, data.indexes.Length));
                            }
                        }

                        //if (isLightingScheduled)
                        //    section.SetLightingScheduled(x, y, z, false);
                    }
                }
            }

            section.New = false;

            var mesh = new ChunkMesh(solidVertices.ToArray(), solidIndexes.ToArray(),
                                     transparentIndexes.ToArray(), animatedIndexes.ToArray());

            section.MeshCache     = mesh;
            section.MeshPositions = positions;

            return(mesh);
        }