public MyEnvironmentItemMapping(MyRuntimeEnvironmentItemInfo[] map, MyEnvironmentRule rule, MyProceduralEnvironmentDefinition env)
        {
            Rule = rule;

            SortedDictionary <int, List <MyRuntimeEnvironmentItemInfo> > infos = new SortedDictionary <int, List <MyRuntimeEnvironmentItemInfo> >();

            foreach (var item in map)
            {
                var def = item.Type;

                List <MyRuntimeEnvironmentItemInfo> lodItems;
                // We store in the prev slot because of the binary search bias
                if (!infos.TryGetValue(def.LodFrom + 1, out lodItems))
                {
                    lodItems = new List <MyRuntimeEnvironmentItemInfo>();
                    infos[def.LodFrom + 1] = lodItems;
                }

                lodItems.Add(item);
            }

            Keys = infos.Keys.ToArray();
            List <MyRuntimeEnvironmentItemInfo>[] itemInfos = infos.Values.ToArray();

            Samplers = new MyDiscreteSampler <MyRuntimeEnvironmentItemInfo> [Keys.Length];

            int i = 0;

            for (int index = 0; index < Keys.Length; ++index)
            {
                Samplers[index] = PrepareSampler(itemInfos.Range(index, itemInfos.Length).SelectMany(x => x));
            }
        }
        public void Prepare()
        {
            // Item types
            if (m_ob.ItemTypes != null)
            {
                foreach (var item in m_ob.ItemTypes)
                {
                    try
                    {
                        var itemType = new MyItemTypeDefinition(item);
                        ItemTypes.Add(item.Name, itemType);
                    }
                    catch (ArgumentException)
                    {
                        MyLog.Default.Error("Duplicate environment item definition for item {0}.", item.Name);
                    }
                    catch (Exception e)
                    {
                        MyLog.Default.Error("Error preparing environment item definition for item {0}:\n {1}", item.Name, e.Message);
                    }
                }
            }

            // Mappings
            MaterialEnvironmentMappings = new Dictionary <MyBiomeMaterial, List <MyEnvironmentItemMapping> >(MyBiomeMaterial.Comparer);

            List <MyRuntimeEnvironmentItemInfo> items = new List <MyRuntimeEnvironmentItemInfo>();

            var mappings = m_ob.EnvironmentMappings;

            if (mappings != null && mappings.Length > 0)
            {
                MaterialEnvironmentMappings = new Dictionary <MyBiomeMaterial, List <MyEnvironmentItemMapping> >(MyBiomeMaterial.Comparer);

                for (int i = 0; i < mappings.Length; i++)
                {
                    var map = mappings[i];

                    var rule = new MyEnvironmentRule
                    {
                        Height    = map.Height,
                        Slope     = map.Slope,
                        Latitude  = map.Latitude,
                        Longitude = map.Longitude
                    };

                    // If the mapping does not assign a material it is ignored
                    if (map.Materials == null)
                    {
                        MyLog.Default.Warning("Mapping in definition {0} does not define any materials, it will not be applied.", Id);
                        continue;
                    }

                    // If not biomes we take default
                    if (map.Biomes == null)
                    {
                        map.Biomes = ArrayOfZero;
                    }

                    // Check items if they are valid
                    bool anyAdded  = false;
                    var  ruleItems = new MyRuntimeEnvironmentItemInfo[map.Items.Length];
                    for (int j = 0; j < map.Items.Length; ++j)
                    {
                        if (!ItemTypes.ContainsKey(map.Items[j].Type))
                        {
                            MyLog.Default.Error("No definition for item type {0}", map.Items[j].Type);
                        }
                        else
                        {
                            ruleItems[j] = new MyRuntimeEnvironmentItemInfo(this, map.Items[j], items.Count);
                            items.Add(ruleItems[j]);
                            anyAdded = true;
                        }
                    }

                    // if no items were valid we skip this rule.
                    if (!anyAdded)
                    {
                        continue;
                    }

                    var mapping = new MyEnvironmentItemMapping(ruleItems, rule, this);

                    foreach (var biome in map.Biomes)
                    {
                        foreach (var material in map.Materials)
                        {
                            MyBiomeMaterial bm = new MyBiomeMaterial((byte)biome, MyDefinitionManager.Static.GetVoxelMaterialDefinition(material).Index);

                            List <MyEnvironmentItemMapping> mappingList;
                            if (!MaterialEnvironmentMappings.TryGetValue(bm, out mappingList))
                            {
                                mappingList = new List <MyEnvironmentItemMapping>();
                                MaterialEnvironmentMappings[bm] = mappingList;
                            }

                            mappingList.Add(mapping);
                        }
                    }
                }
            }

            Items = items.GetInternalArray();

            m_ob = null;
        }