public void GenerateReport()
{
IsReportReady = false;
_generatedDate = DateTime.Now;
var contentPath = ToolboxUpdater.GetApplicationContentPath();
var accumulateOres = new SortedDictionary<string, long>();
var accumulateAsteroidOres = new List<AsteroidContent>();
var accumulateUnusedOres = new SortedDictionary<string, OreContent>();
var accumulateUsedOres = new SortedDictionary<string, OreContent>();
var accumulatePlayerOres = new SortedDictionary<string, OreContent>();
var accumulateNpcOres = new SortedDictionary<string, OreContent>();
var accumulateItems = new SortedDictionary<string, ComponentItemModel>();
var accumulateComponents = new SortedDictionary<string, ComponentItemModel>();
var accumulateCubes = new SortedDictionary<string, ComponentItemModel>();
var accumulateShips = new List<ShipContent>();
ResetProgress(0, _entities.Count);
foreach (var entity in _entities)
{
Progress++;
if (entity is StructureVoxelModel)
{
var asteroid = (StructureVoxelModel)entity;
#region untouched ores (in asteroid)
Dictionary<string, long> details;
var filename = asteroid.SourceVoxelFilepath;
if (string.IsNullOrEmpty(filename))
filename = asteroid.VoxelFilepath;
try
{
details = MyVoxelMap.GetMaterialAssetDetails(filename);
}
catch
{
details = null;
}
// Accumulate into untouched.
if (details != null)
{
var ores = new Dictionary<string, long>();
foreach (var kvp in details)
{
var bp = SpaceEngineersCore.Resources.VoxelMaterialDefinitions.FirstOrDefault(b => b.Id.SubtypeName == kvp.Key && b.Id.TypeId == SpaceEngineersTypes.VoxelMaterialDefinition);
if (bp != null && bp.CanBeHarvested)
{
var cd = MyDefinitionManager.Static.GetDefinition(SpaceEngineersTypes.Ore, bp.MinedOre);
if (cd != null)
{
if (ores.ContainsKey(cd.DisplayNameEnum.Value.String))
ores[cd.DisplayNameEnum.Value.String] += kvp.Value;
else
ores.Add(cd.DisplayNameEnum.Value.String, kvp.Value);
}
}
}
foreach (var kvp in ores)
{
if (accumulateOres.ContainsKey(kvp.Key))
{
accumulateOres[kvp.Key] += kvp.Value;
}
else
{
accumulateOres.Add(kvp.Key, kvp.Value);
}
}
var oreSum = ores.Values.ToList().Sum();
accumulateAsteroidOres.Add(new AsteroidContent()
{
Name = Path.GetFileNameWithoutExtension(filename),
Position = asteroid.PositionAndOrientation.Value.Position,
UntouchedOreList = ores.Select(kvp => new VoxelMaterialAssetModel { MaterialName = SpaceEngineersApi.GetResourceName(kvp.Key), Volume = Math.Round((double)kvp.Value / 255, 7), Percent = kvp.Value / (double)oreSum }).ToList()
});
}
#endregion
}
else if (entity is StructureFloatingObjectModel)
{
var floating = (StructureFloatingObjectModel)entity;
if (floating.FloatingObject.Item.PhysicalContent.TypeId == SpaceEngineersTypes.Ore || floating.FloatingObject.Item.PhysicalContent.TypeId == SpaceEngineersTypes.Ingot)
{
TallyItems(floating.FloatingObject.Item.PhysicalContent.TypeId, floating.FloatingObject.Item.PhysicalContent.SubtypeName, (decimal)floating.FloatingObject.Item.Amount, contentPath, accumulateUnusedOres, accumulateItems, accumulateComponents);
}
else
{
TallyItems(floating.FloatingObject.Item.PhysicalContent.TypeId, floating.FloatingObject.Item.PhysicalContent.SubtypeName, (decimal)floating.FloatingObject.Item.Amount, contentPath, accumulateUsedOres, accumulateItems, accumulateComponents);
}
}
else if (entity is StructureCharacterModel)
{
var character = (StructureCharacterModel)entity;
// Ignore pilots, as we'll check those in the ship.
if (!character.IsPilot)
{
// Character inventory.
if (character.Character.Inventory != null)
{
foreach (var item in character.Character.Inventory.Items)
{
TallyItems(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName, (decimal)item.Amount, contentPath, accumulatePlayerOres, accumulateItems, accumulateComponents);
}
}
}
}
else if (entity is StructureCubeGridModel)
{
var ship = entity as StructureCubeGridModel;
var isNpc = ship.CubeGrid.CubeBlocks.Any(e => e is MyObjectBuilder_Cockpit && ((MyObjectBuilder_Cockpit)e).Autopilot != null);
var shipContent = new ShipContent()
{
DisplayName = ship.DisplayName,
Position = ship.PositionAndOrientation.Value.Position,
EntityId = ship.EntityId,
BlockCount = ship.BlockCount
};
foreach (MyObjectBuilder_CubeBlock block in ship.CubeGrid.CubeBlocks)
{
var blockType = block.GetType();
var cubeBlockDefinition = SpaceEngineersApi.GetCubeDefinition(block.TypeId, ship.CubeGrid.GridSizeEnum, block.SubtypeName);
var blockTime = TimeSpan.Zero;
string blockTexture = null;
float cubeMass = 0;
// Unconstructed portion.
if (block.ConstructionStockpile != null && block.ConstructionStockpile.Items.Length > 0)
{
foreach (var item in block.ConstructionStockpile.Items)
{
if (isNpc)
{
TallyItems(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName, item.Amount, contentPath, accumulateNpcOres, null, null);
}
else
{
TallyItems(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName, item.Amount, contentPath, accumulateUsedOres, null, null);
}
var def = MyDefinitionManager.Static.GetDefinition(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName);
float componentMass = 0;
var cd = def as MyComponentDefinition;
if (cd != null)
{
componentMass = cd.Mass * item.Amount;
}
else
{
var pd = def as MyPhysicalItemDefinition;
if (pd != null)
{
componentMass = pd.Mass * item.Amount;
}
}
cubeMass += componentMass;
}
}
if (cubeBlockDefinition != null)
{
if (block.BuildPercent < 1f)
{
// break down the components, to get a accurate counted on the number of components actually in the cube.
var componentList = new List<MyComponentDefinition>();
foreach (var component in cubeBlockDefinition.Components)
{
for (var i = 0; i < component.Count; i++)
componentList.Add(component.Definition);
}
// Round up to nearest whole number.
var completeCount = Math.Min(componentList.Count, Math.Ceiling((double)componentList.Count * (double)block.BuildPercent));
// count only the components used to reach the BuildPercent, 1 component at a time.
for (var i = 0; i < completeCount; i++)
{
#region used ore value
if (isNpc)
{
TallyItems(componentList[i].Id.TypeId, componentList[i].Id.SubtypeName, 1, contentPath, accumulateNpcOres, null, null);
}
else
{
TallyItems(componentList[i].Id.TypeId, componentList[i].Id.SubtypeName, 1, contentPath, accumulateUsedOres, null, null);
}
#endregion
float componentMass = componentList[i].Mass * 1;
cubeMass += componentMass;
}
}
else
{
// Fully armed and operational cube.
foreach (var component in cubeBlockDefinition.Components)
{
var cd = (MyComponentDefinition)MyDefinitionManager.Static.GetDefinition(component.Definition.Id);
#region used ore value
if (isNpc)
{
TallyItems(component.Definition.Id.TypeId, component.Definition.Id.SubtypeName, component.Count, contentPath, accumulateNpcOres, null, null);
}
else
{
TallyItems(component.Definition.Id.TypeId, component.Definition.Id.SubtypeName, component.Count, contentPath, accumulateUsedOres, null, null);
}
#endregion
var componentMass = cd.Mass * component.Count;
cubeMass += componentMass;
}
}
blockTime = TimeSpan.FromSeconds(cubeBlockDefinition.MaxIntegrity / cubeBlockDefinition.IntegrityPointsPerSec * block.BuildPercent);
blockTexture = (cubeBlockDefinition.Icons == null || cubeBlockDefinition.Icons.First() == null) ? null : SpaceEngineersCore.GetDataPathOrDefault(cubeBlockDefinition.Icons.First(), Path.Combine(contentPath, cubeBlockDefinition.Icons.First()));
}
if (!blockType.Equals(typeof(MyObjectBuilder_CubeBlockDefinition)))
{
var fields = blockType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
#region Inventories
var inventoryFields = fields.Where(f => f.FieldType == typeof(MyObjectBuilder_Inventory)).ToArray();
foreach (var field in inventoryFields)
{
var inventory = field.GetValue(block) as MyObjectBuilder_Inventory;
if (inventory != null)
{
foreach (var item in inventory.Items)
{
if (isNpc)
{
TallyItems(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName, (decimal)item.Amount, contentPath, accumulateNpcOres, accumulateItems, accumulateComponents);
}
else
{
if (item.PhysicalContent.TypeId == SpaceEngineersTypes.Ore || item.PhysicalContent.TypeId == SpaceEngineersTypes.Ingot)
{
TallyItems(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName, (decimal)item.Amount, contentPath, accumulateUnusedOres, accumulateItems, accumulateComponents);
}
else
{
TallyItems(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName, (decimal)item.Amount, contentPath, accumulateUsedOres, accumulateItems, accumulateComponents);
}
}
}
}
}
#endregion
#region Character inventories
var characterFields = fields.Where(f => f.FieldType == typeof(MyObjectBuilder_Character)).ToArray();
foreach (var field in characterFields)
{
var character = field.GetValue(block) as MyObjectBuilder_Character;
if (character != null)
{
foreach (var item in character.Inventory.Items)
{
TallyItems(item.PhysicalContent.TypeId, item.PhysicalContent.SubtypeName, (decimal)item.Amount, contentPath, accumulatePlayerOres, accumulateItems, accumulateComponents);
}
}
}
#endregion
}
#region tally cubes
if (cubeBlockDefinition != null)
{
var itemsKey = cubeBlockDefinition.DisplayNameText;
if (accumulateCubes.ContainsKey(itemsKey))
{
accumulateCubes[itemsKey].Count += 1;
accumulateCubes[itemsKey].Mass += cubeMass;
accumulateCubes[itemsKey].Time += blockTime;
}
else
{
accumulateCubes.Add(itemsKey, new ComponentItemModel { Name = cubeBlockDefinition.DisplayNameText, Count = 1, Mass = cubeMass, TypeId = cubeBlockDefinition.Id.TypeId, SubtypeId = cubeBlockDefinition.Id.SubtypeName, TextureFile = blockTexture, Time = blockTime });
}
}
#endregion
}
accumulateShips.Add(shipContent);
}
}
#region build lists
var sum = accumulateOres.Values.ToList().Sum();
_untouchedOre = new List<VoxelMaterialAssetModel>();
foreach (var kvp in accumulateOres)
{
_untouchedOre.Add(new VoxelMaterialAssetModel { MaterialName = SpaceEngineersApi.GetResourceName(kvp.Key), Volume = Math.Round((double)kvp.Value / 255, 7), Percent = kvp.Value / (double)sum });
}
_untouchedOreByAsteroid = accumulateAsteroidOres;
_unusedOre = accumulateUnusedOres.Values.ToList();
_usedOre = accumulateUsedOres.Values.ToList();
_playerOre = accumulatePlayerOres.Values.ToList();
_npcOre = accumulateNpcOres.Values.ToList();
_allCubes = accumulateCubes.Values.ToList();
_allComponents = accumulateComponents.Values.ToList();
_allItems = accumulateItems.Values.ToList();
_allShips = accumulateShips;
#endregion
#region create report
IsReportReady = true;
ClearProgress();
#endregion
}