示例#1
0
        private void PopulateBlockEntities(IWorldParser parser, WorldInfoModel worldInfo)
        {
            var chests = new List <ChestInfoModel>();
            var signs  = new List <SignInfoModel>();

            foreach (var region in parser.GetRegions(TARGET_REGION))
            {
                foreach (var column in region.Columns)
                {
                    foreach (var chunk in column.Chunks)
                    {
                        foreach (var block in chunk.Blocks)
                        {
                            if (block is Chest)
                            {
                                var chest = block as Chest;

                                chests.Add(new ChestInfoModel
                                {
                                    X     = chest.WorldX,
                                    Y     = chest.WorldY,
                                    Z     = chest.WorldZ,
                                    Items = chest.Items.Select(i => new InventoryItemModel
                                    {
                                        Name  = i.Id,
                                        Count = i.Count
                                    }).ToList()
                                });
                            }
                            else if (block is Sign)
                            {
                                var    sign         = block as Sign;
                                string textRendered = string.Join("\n", sign.TextLines.Select(s =>
                                {
                                    if (s.Contains('{') && s.Contains('}') && s.Contains("\"text\":"))
                                    {
                                        var obj = JObject.Parse(s);
                                        return(obj.GetValue("text").ToString());
                                    }
                                    else
                                    {
                                        return(s);
                                    }
                                }));

                                signs.Add(new SignInfoModel
                                {
                                    X    = sign.WorldX,
                                    Y    = sign.WorldY,
                                    Z    = sign.WorldZ,
                                    Text = textRendered
                                });
                            }
                        }
                    }
                }
            }

            worldInfo.Chests = chests;
            worldInfo.Signs  = signs;
        }
示例#2
0
        public RenderReturnModel GenerateBlockBitmap(RegionType regionType)
        {
            var regions = _parser.GetRegions(regionType).ToList();

            var minX = regions.Min(r => r.X);
            var maxX = regions.Max(r => r.X);
            var minZ = regions.Min(r => r.Z);
            var maxZ = regions.Max(r => r.Z);

            var imageWidth  = (maxX - minX + 1) * 32 * 16;
            var imageHeight = (maxZ - minZ + 1) * 32 * 16;

            var dX = minX * 32 * 16;
            var dZ = minZ * 32 * 16;

            var bitmap        = new Image <Rgba32>(imageWidth, imageHeight);
            var unknownBlocks = new Dictionary <string, int>();

            int  actualMinX = Int32.MaxValue, actualMaxX = 0, actualMinZ = Int32.MaxValue, actualMaxZ = 0;
            bool blockRendered = false;

            //foreach (var region in regions)
            Parallel.ForEach(regions, region =>
            {
                var regionCache = _cacheProvider?.GetRegionMapCache(region.X, region.Z) ?? new RegionMapCache();

                var populated     = new List <(int, int)>(16 * 16);
                var lastBaseColor = new Dictionary <(int, int), Color>(16 * 16);

                foreach (var column in region.Columns)
                {
                    if (regionCache.ColumnCacheIsStale(column.XWorld, column.ZWorld, column.Modified))
                    {
                        regionCache.UpdateTimestamp(column.XWorld, column.ZWorld, column.Modified);

                        populated.Clear();
                        lastBaseColor.Clear();

                        foreach (var chunk in column.Chunks.OrderByDescending(c => c.YOrder))
                        {
                            foreach (var block in chunk.Blocks.OrderByDescending(b => b.WorldY))
                            {
                                //In image coordinates
                                var x = block.WorldX - dX;
                                var z = block.WorldZ - dZ;

                                //Update image edge extents if neccessary
                                actualMinX = Math.Min(actualMinX, x);
                                actualMaxX = Math.Max(actualMaxX, x);
                                actualMinZ = Math.Min(actualMinZ, z);
                                actualMaxZ = Math.Max(actualMaxZ, z);

                                //Do not draw air
                                if (block.BaseId == 0)
                                {
                                    continue;
                                }

                                //Coordinates populated and completed, ignore
                                if (populated.Contains((x, z)))
                                {
                                    continue;
                                }

                                var baseColor = _textureProvider.GetColorForBlock(block, Color.HotPink);
                                if (baseColor == Color.HotPink)
                                {
                                    var key            = $"{block.Code} ({block.Id})";
                                    unknownBlocks[key] = unknownBlocks.ContainsKey(key) ? unknownBlocks[key] + 1 : 1;
                                }

                                Color color;
                                if (lastBaseColor.ContainsKey((x, z)))
                                {
                                    //Handle non top blocks in transparent stacks

                                    if (baseColor == lastBaseColor[(x, z)])
                                    {
                                        continue;
                                    }

                                    if (!TransparentBlocks.Contains(block.BaseId) && block.SkyLight == 0 && block.BlockLight == 0 && bitmap[x, z].A > 0)
                                    {
                                        populated.Add((x, z));
                                        continue;
                                    }

                                    color = BlendBlocks(bitmap[x, z], baseColor, Math.Max(block.SkyLight, (byte)(block.BlockLight / 2)));
                                    lastBaseColor[(x, z)] = baseColor;
                                }
                                else
                                {
                                    //First block in stack, it can either be transparent or not
                                    color = baseColor;
                                }

                                //Handle blocklight; ie torches, lava etc
                                //if (block.BlockLight > 0)
                                //{
                                //    color = BlendBlocks(color, _textureProvider.GetBlocklightColor(), (byte)(block.BlockLight / 2));
                                //}

                                if (TransparentBlocks.Contains(block.BaseId))
                                {
                                    //This is a transparent block stack, save this color for future (next block in -Y order) reference.
                                    //This is also the flag that a stack is transparent
                                    lastBaseColor[(x, z)] = baseColor;