Aetheria/Assets/Scripts/ServerShared/GameContext.cs
hyperion51 776e08a1d1 Local Zone Generation
Added the ability to generate zones locally in order to facilitate rapidly iterating generation parameters. Then of course I tweaked the shit out of the zone generation!
2020-03-30 03:11:57 +01:00

188 lines
5.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using static Unity.Mathematics.math;
public class GameContext
{
private DatabaseCache _cache;
public GlobalData GlobalData => _cache.GetAll<GlobalData>().FirstOrDefault();
private readonly Dictionary<CraftedItemData, int> Tier = new Dictionary<CraftedItemData, int>();
public GameContext(DatabaseCache cache)
{
_cache = cache;
var globalData = _cache.GetAll<GlobalData>().FirstOrDefault();
if (globalData == null)
{
globalData = new GlobalData();
_cache.Add(globalData);
}
}
public int ItemTier(CraftedItemData itemData)
{
if (Tier.ContainsKey(itemData)) return Tier[itemData];
Tier[itemData] = itemData.Ingredients.Keys.Max(ci => _cache.Get<ItemData>(ci) is CraftedItemData craftableIngredient ? ItemTier(craftableIngredient) : 0);
return Tier[itemData];
}
public ItemData GetData(ItemInstance item)
{
return _cache.Get<ItemData>(item.Data);
}
public SimpleCommodityData GetData(SimpleCommodity item)
{
return _cache.Get<SimpleCommodityData>(item.Data);
}
public CraftedItemData GetData(CraftedItemInstance item)
{
return _cache.Get<CraftedItemData>(item.Data);
}
public EquippableItemData GetData(Gear gear)
{
return _cache.Get<EquippableItemData>(gear.Data);
}
public float GetMass(ItemInstance item)
{
var data = GetData(item);
switch (item)
{
case CraftedItemInstance _:
return data.Mass;
case SimpleCommodity commodity:
return data.Mass * commodity.Quantity;
}
return 0;
}
public float GetHeatCapacity(ItemInstance item)
{
var data = GetData(item);
switch (item)
{
case CraftedItemInstance _:
return data.Mass * data.SpecificHeat;
case SimpleCommodity commodity:
return data.Mass * data.SpecificHeat * commodity.Quantity;
}
return 0;
}
// Determine quality of either the item itself or the specific ingredient this stat depends on
public float Quality(PerformanceStat stat, Gear item)
{
Guid? ingredientID = stat.Ingredient;
float quality;
if (ingredientID == null)
quality = item.CompoundQuality();
else
{
var ingredientInstance =
item.Ingredients.FirstOrDefault(i => i.Data == ingredientID) as CraftedItemInstance;
if (ingredientInstance == null)
throw new InvalidOperationException(
$"Item {item.ID} has invalid crafting ingredients!");
quality = ingredientInstance.CompoundQuality();
}
return quality;
}
// Returns stat when not equipped
public float Evaluate(PerformanceStat stat, Gear item)
{
var quality = pow(Quality(stat, item), stat.QualityExponent);
var result = lerp(stat.Min, stat.Max, quality);
if (float.IsNaN(result))
return stat.Min;
return result;
}
// Returns stat using ship temperature and modifiers
public float Evaluate(PerformanceStat stat, Gear item, Ship ship)
{
var itemData = GetData(item);
var heat = !stat.HeatDependent ? 1 : pow(itemData.Performance(ship.Temperature), Evaluate(itemData.HeatExponent,item));
var durability = !stat.DurabilityDependent ? 1 : pow(item.Durability / itemData.Durability, Evaluate(itemData.DurabilityExponent,item));
var quality = pow(Quality(stat, item), stat.QualityExponent);
var scaleModifier = stat.GetScaleModifiers(ship).Values.Aggregate(1.0f, (current, mod) => current * mod);
var constantModifier = stat.GetConstantModifiers(ship).Values.Sum();
var result = lerp(stat.Min, stat.Max, heat * durability * quality) * scaleModifier + constantModifier;
if (float.IsNaN(result))
return stat.Min;
return result;
}
public SimpleCommodity CreateInstance(Guid data, int count)
{
var item = _cache.Get<SimpleCommodityData>(data);
if (item != null)
return new SimpleCommodity
{
Data = data,
Quantity = count,
ID = Guid.NewGuid()
};
throw new InvalidOperationException("Attempted to create Simple Commodity instance using missing or incorrect item id");
}
public CraftedItemInstance CreateInstance(Guid data, float quality)
{
var item = _cache.Get<CraftedItemData>(data);
if (item == null)
{
throw new InvalidOperationException("Attempted to create crafted item instance using missing or incorrect item id");
}
var ingredients = item.Ingredients.SelectMany(ci =>
{
var ingredient = _cache.Get(ci.Key);
return ingredient is SimpleCommodityData
? (IEnumerable<ItemInstance>) new[] {CreateInstance(ci.Key, ci.Value)}
: Enumerable.Range(0, ci.Value).Select(i => CreateInstance(ci.Key, quality));
})
.ToList();
if (item is EquippableItemData equippableItemData)
{
return new Gear
{
Context = this,
Data = data,
Durability = equippableItemData.Durability,
ID = Guid.NewGuid(),
Ingredients = ingredients,
Quality = quality
};
}
return new CompoundCommodity
{
Context = this,
Data = data,
ID = Guid.NewGuid(),
Ingredients = ingredients,
Quality = quality
};
}
}