Entity Spawning & Rendering
Entity rendering now fully supports dynamic entities from game context Entity children now displayed underneath icon GameContext can spawn entities by loadout Selected corporation's initial fleet is spawned in parent corp's home sector Properties panel API is now unified with context menu API Properties panel labels now update dynamically
This commit is contained in:
parent
604acd80b5
commit
110ff883b8
25 changed files with 1019 additions and 165 deletions
|
|
@ -84,7 +84,6 @@ public class Factory : IBehavior, IPersistentBehavior
|
|||
{
|
||||
Context = Context,
|
||||
Data = blueprintItemData.ID,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(),
|
||||
Quality = quality,
|
||||
Blueprint = _blueprint
|
||||
|
|
@ -98,7 +97,6 @@ public class Factory : IBehavior, IPersistentBehavior
|
|||
{
|
||||
Context = Context,
|
||||
Data = blueprintItemData.ID,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(),
|
||||
Quality = quality,
|
||||
Blueprint = _blueprint
|
||||
|
|
@ -118,7 +116,6 @@ public class Factory : IBehavior, IPersistentBehavior
|
|||
{
|
||||
Context = Context,
|
||||
Data = simpleCommodityData.ID,
|
||||
ID = Guid.NewGuid(),
|
||||
Quantity = blueprint.Quantity
|
||||
};
|
||||
Context.Cache.Add(newSimpleCommodity);
|
||||
|
|
@ -181,7 +178,6 @@ public class Factory : IBehavior, IPersistentBehavior
|
|||
{
|
||||
Context = Context,
|
||||
Data = simpleCommodity.Data,
|
||||
ID = Guid.NewGuid(),
|
||||
Quantity = blueprintQuantity
|
||||
};
|
||||
simpleCommodity.Quantity -= blueprintQuantity;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ public class TowingController : IBehavior, IPersistentBehavior, IController, IIn
|
|||
|
||||
public bool Update(float delta)
|
||||
{
|
||||
var towingTask = _context.Cache.Get<StationTowing>(_towingTask);
|
||||
if (towingTask == null)
|
||||
return false;
|
||||
|
||||
if (_path.Any())
|
||||
{
|
||||
_locomotion.Update(delta);
|
||||
|
|
@ -64,7 +68,6 @@ public class TowingController : IBehavior, IPersistentBehavior, IController, IIn
|
|||
}
|
||||
else
|
||||
{
|
||||
var towingTask = _context.Cache.Get<StationTowing>(_towingTask);
|
||||
var destination = float2(0);
|
||||
var velocity = float2(0);
|
||||
if (_towingPhase == TowingPhase.Pickup)
|
||||
|
|
@ -97,19 +100,17 @@ public class TowingController : IBehavior, IPersistentBehavior, IController, IIn
|
|||
_velocityMatch.OnMatch += () =>
|
||||
{
|
||||
var target = _context.ZoneEntities[_entity.Zone][towingTask.Station];
|
||||
_entity.Children.Add(towingTask.Station);
|
||||
target.Parent = _entity.ID;
|
||||
_context.SetParent(target, _entity);
|
||||
_towingPhase = TowingPhase.Delivery;
|
||||
_movementPhase = MovementPhase.Locomotion;
|
||||
};
|
||||
else
|
||||
_velocityMatch.OnMatch += () =>
|
||||
{
|
||||
var orbit = _context.CreateOrbit(towingTask.OrbitParent, _entity.Position);
|
||||
|
||||
var target = _context.ZoneEntities[_entity.Zone][towingTask.Station] as OrbitalEntity;
|
||||
_entity.Children.Remove(towingTask.Station);
|
||||
target.Parent = Guid.Empty;
|
||||
_context.RemoveParent(target);
|
||||
|
||||
var orbit = _context.CreateOrbit(towingTask.OrbitParent, _entity.Position);
|
||||
target.OrbitData = orbit.ID;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,9 @@ public class LoadoutData : DatabaseEntry, INamedEntry
|
|||
[JsonProperty("items"), Key(3)]
|
||||
public List<Guid> Items = new List<Guid>();
|
||||
|
||||
[InspectableDatabaseLink(typeof(SimpleCommodityData)), JsonProperty("resourceRequirements"), Key(4)]
|
||||
public Dictionary<Guid, int> SimpleCargo = new Dictionary<Guid, int>();
|
||||
|
||||
[IgnoreMember] public string EntryName
|
||||
{
|
||||
get => Name;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ using static Unity.Mathematics.math;
|
|||
Union(0, typeof(Ship)),
|
||||
Union(1, typeof(OrbitalEntity)),
|
||||
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<Entity>))]
|
||||
public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackReceiver
|
||||
public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackReceiver, INamedEntry
|
||||
{
|
||||
[JsonProperty("temperature"), Key(1)] public float Temperature;
|
||||
[JsonProperty("energy"), Key(2)] public float Energy;
|
||||
|
|
@ -27,6 +27,7 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR
|
|||
[JsonProperty("hull"), Key(10)] public Guid Hull; // Type: Gear
|
||||
[JsonProperty("persistedBehaviorData"), Key(11)] public Dictionary<Guid, PersistentBehaviorData[]> PersistedBehaviors;
|
||||
[JsonProperty("corporation"), Key(12)] public Guid Corporation;
|
||||
[JsonProperty("name"), Key(13)] public string Name;
|
||||
|
||||
// [IgnoreMember] protected List<IBehavior> Behaviors;
|
||||
[IgnoreMember] public Guid Zone;
|
||||
|
|
@ -44,10 +45,15 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR
|
|||
[IgnoreMember] public float SpecificHeat { get; private set; }
|
||||
[IgnoreMember] public float Visibility => VisibilitySources.Values.Sum();
|
||||
|
||||
[IgnoreMember] public string EntryName
|
||||
{
|
||||
get => Name;
|
||||
set => Name = value;
|
||||
}
|
||||
|
||||
|
||||
public Entity(GameContext context, Guid hull, IEnumerable<Guid> items, IEnumerable<Guid> cargo, Guid zone)
|
||||
{
|
||||
ID = Guid.NewGuid();
|
||||
Context = context;
|
||||
Zone = zone;
|
||||
|
||||
|
|
@ -120,7 +126,8 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR
|
|||
|
||||
SpecificHeat = Context.Cache.Get<Gear>(Hull).HeatCapacity +
|
||||
EquippedItems.Select(i => Context.Cache.Get<Gear>(i)).Sum(i => i.HeatCapacity) +
|
||||
Cargo.Select(i => Context.Cache.Get<ItemInstance>(i)).Sum(ii => ii.HeatCapacity);
|
||||
Cargo.Select(i => Context.Cache.Get<ItemInstance>(i)).Sum(ii => ii.HeatCapacity) +
|
||||
Children.Select(i => Context.Cache.Get<Entity>(i)).Sum(c=>c.SpecificHeat);
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetBehaviors<T>() where T : class, IBehavior
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ public class GameContext
|
|||
private Dictionary<Guid, float2> _orbitVelocities = new Dictionary<Guid, float2>();
|
||||
private Dictionary<Guid, float2> _orbitPositions = new Dictionary<Guid, float2>();
|
||||
private Dictionary<Guid, float2> _previousOrbitPositions = new Dictionary<Guid, float2>();
|
||||
private Dictionary<Guid, float3[]> _asteroidPositions = new Dictionary<Guid, float3[]>();
|
||||
private Dictionary<Guid, bool> _asteroidPositionsUpdated = new Dictionary<Guid, bool>();
|
||||
private Guid _forceLoadZone;
|
||||
private Type[] _statObjects;
|
||||
|
||||
|
|
@ -102,6 +104,9 @@ public class GameContext
|
|||
: float2.zero;
|
||||
}
|
||||
|
||||
foreach (var asteroids in _asteroidPositions.Keys)
|
||||
_asteroidPositionsUpdated[asteroids] = false;
|
||||
|
||||
foreach (var corporation in Cache.GetAll<Corporation>())
|
||||
{
|
||||
foreach (var tasks in corporation.Tasks
|
||||
|
|
@ -222,6 +227,28 @@ public class GameContext
|
|||
return _orbitVelocities.ContainsKey(orbit) ? _orbitVelocities[orbit] : float2.zero;
|
||||
}
|
||||
|
||||
public float3[] GetAsteroidTransforms(Guid planetDataID)
|
||||
{
|
||||
var planetData = Cache.Get<PlanetData>(planetDataID);
|
||||
if (!_asteroidPositions.ContainsKey(planetDataID))
|
||||
{
|
||||
_asteroidPositions[planetDataID] = new float3[planetData.Asteroids.Length];
|
||||
_asteroidPositionsUpdated[planetDataID] = false;
|
||||
}
|
||||
|
||||
if (_asteroidPositionsUpdated[planetDataID])
|
||||
return _asteroidPositions[planetDataID];
|
||||
for (var i = 0; i < planetData.Asteroids.Length; i++)
|
||||
{
|
||||
_asteroidPositions[planetDataID][i] = float3(
|
||||
OrbitData.Evaluate((float) frac(Time / -OrbitalPeriod(planetData.Asteroids[i].x) * GlobalData.OrbitSpeedMultiplier +
|
||||
planetData.Asteroids[i].y)) * planetData.Asteroids[i].x,
|
||||
(float) (Time * planetData.Asteroids[i].w % 360.0));
|
||||
}
|
||||
|
||||
return _asteroidPositions[planetDataID];
|
||||
}
|
||||
|
||||
public OrbitData CreateOrbit(Guid parent, float2 position)
|
||||
{
|
||||
var parentOrbit = Cache.Get<OrbitData>(parent);
|
||||
|
|
@ -236,7 +263,6 @@ public class GameContext
|
|||
{
|
||||
Context = this,
|
||||
Distance = distance,
|
||||
ID = Guid.NewGuid(),
|
||||
Parent = parent,
|
||||
Period = period,
|
||||
Phase = storedPhase,
|
||||
|
|
@ -511,6 +537,138 @@ public class GameContext
|
|||
return stat.Min;
|
||||
return result;
|
||||
}
|
||||
|
||||
public Entity CreateEntity(Guid zone, Guid corporation, Guid loadout)
|
||||
{
|
||||
if (!(Cache.Get(loadout) is LoadoutData loadoutData))
|
||||
{
|
||||
_logger("Attempted to spawn invalid loadout ID");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(Cache.Get(loadoutData.Hull) is HullData hullData))
|
||||
{
|
||||
_logger("Attempted to spawn loadout with invalid hull ID");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(Cache.Get(zone) is ZoneData zoneData))
|
||||
{
|
||||
_logger("Attempted to spawn entity with invalid zone ID");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(Cache.Get(corporation) is Corporation corpData))
|
||||
{
|
||||
_logger("Attempted to spawn entity with invalid corporation ID");
|
||||
return null;
|
||||
}
|
||||
|
||||
var gearData = loadoutData.Items
|
||||
.Take(hullData.Hardpoints.Count)
|
||||
.Where(id => id != Guid.Empty)
|
||||
.Select(id => Cache.Get<GearData>(id))
|
||||
.ToArray();
|
||||
|
||||
if (gearData.Any(g=>g==null))
|
||||
{
|
||||
_logger("Attempted to spawn loadout with invalid gear ID");
|
||||
return null;
|
||||
}
|
||||
|
||||
var cargoData = loadoutData.Items
|
||||
.Skip(hullData.Hardpoints.Count)
|
||||
.Where(id => id != Guid.Empty)
|
||||
.Select(id => Cache.Get<CraftedItemData>(id))
|
||||
.ToArray();
|
||||
|
||||
if (cargoData.Any(g=>g==null))
|
||||
{
|
||||
_logger("Attempted to spawn loadout with invalid cargo ID");
|
||||
return null;
|
||||
}
|
||||
|
||||
var gear = gearData
|
||||
.Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
|
||||
.ToArray();
|
||||
|
||||
if (gear.Any(g=>g==null))
|
||||
return null;
|
||||
|
||||
foreach(var g in gear)
|
||||
Cache.Add(g);
|
||||
|
||||
var cargo = cargoData
|
||||
.Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
|
||||
.ToArray();
|
||||
|
||||
if (cargo.Any(g=>g==null))
|
||||
return null;
|
||||
|
||||
foreach(var c in cargo)
|
||||
Cache.Add(c);
|
||||
|
||||
var simpleCargo = loadoutData.SimpleCargo?
|
||||
.Select(x => CreateInstance(x.Key, x.Value))
|
||||
.ToArray() ?? new SimpleCommodity[0];
|
||||
|
||||
if (simpleCargo.Any(g=>g==null))
|
||||
return null;
|
||||
|
||||
foreach(var c in simpleCargo)
|
||||
Cache.Add(c);
|
||||
|
||||
var hull = CreateInstance(loadoutData.Hull, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax);
|
||||
|
||||
if(hull==null)
|
||||
return null;
|
||||
|
||||
// Load target zone if not yet loaded
|
||||
if (!_loadedZones.Contains(zone))
|
||||
LoadZone(zone);
|
||||
|
||||
if (hullData.HullType == HullType.Ship)
|
||||
{
|
||||
var entity = new Ship(this, hull.ID, gear.Select(g => g.ID),
|
||||
cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), zone)
|
||||
{
|
||||
Name = $"{loadoutData.Name} {Random.NextInt(1,255):X}"
|
||||
};
|
||||
Cache.Add(entity);
|
||||
|
||||
ZoneEntities[zone][entity.ID] = entity;
|
||||
return entity;
|
||||
}
|
||||
|
||||
if (hullData.HullType == HullType.Station)
|
||||
{
|
||||
var distance = lerp(.2f, .8f, Random.NextFloat()) * zoneData.Radius;
|
||||
var orbit = new OrbitData
|
||||
{
|
||||
Context = this,
|
||||
Distance = distance,
|
||||
Parent = _orbits
|
||||
.Select(id => Cache.Get<OrbitData>(id))
|
||||
.First(orbitData => orbitData.Zone == zone && orbitData.Parent == Guid.Empty).ID,
|
||||
Period = OrbitalPeriod(distance),
|
||||
Phase = Random.NextFloat(),
|
||||
Zone = zone
|
||||
};
|
||||
Cache.Add(orbit);
|
||||
|
||||
var entity = new OrbitalEntity(this, hull.ID, gear.Select(g => g.ID),
|
||||
cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), orbit.ID, zone)
|
||||
{
|
||||
Name = $"{loadoutData.Name} {Random.NextInt(1,255):X}"
|
||||
};
|
||||
Cache.Add(entity);
|
||||
|
||||
ZoneEntities[zone][entity.ID] = entity;
|
||||
return entity;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SimpleCommodity CreateInstance(Guid data, int count)
|
||||
{
|
||||
|
|
@ -519,15 +677,14 @@ public class GameContext
|
|||
return new SimpleCommodity
|
||||
{
|
||||
Data = data,
|
||||
Quantity = count,
|
||||
ID = Guid.NewGuid()
|
||||
Quantity = count
|
||||
};
|
||||
|
||||
_logger("Attempted to create Simple Commodity instance using missing or incorrect item id");
|
||||
return null;
|
||||
}
|
||||
|
||||
public CraftedItemInstance CreateInstance(Guid data, float quality)
|
||||
public CraftedItemInstance CreateInstance(Guid data, float qualityMin, float qualityMax)
|
||||
{
|
||||
var item = Cache.Get<CraftedItemData>(data);
|
||||
if (item == null)
|
||||
|
|
@ -548,7 +705,7 @@ public class GameContext
|
|||
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));
|
||||
: Enumerable.Range(0, ci.Value).Select(i => CreateInstance(ci.Key, qualityMin, qualityMax));
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
|
@ -560,9 +717,8 @@ public class GameContext
|
|||
{
|
||||
Context = this,
|
||||
Data = data,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = ingredients.Select(i=>i.ID).ToList(),
|
||||
Quality = quality,
|
||||
Quality = Random.NextFloat(qualityMin, qualityMax),
|
||||
Blueprint = blueprint.ID
|
||||
};
|
||||
newGear.Durability = Evaluate(equippableItemData.Durability, newGear);
|
||||
|
|
@ -574,9 +730,8 @@ public class GameContext
|
|||
{
|
||||
Context = this,
|
||||
Data = data,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = ingredients.Select(i=>i.ID).ToList(),
|
||||
Quality = quality,
|
||||
Quality = Random.NextFloat(qualityMin, qualityMax),
|
||||
Blueprint = blueprint.ID
|
||||
};
|
||||
Cache.Add(newCommodity);
|
||||
|
|
@ -615,4 +770,21 @@ public class GameContext
|
|||
searched.Add(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetParent(Entity child, Entity parent)
|
||||
{
|
||||
child.Parent = parent.ID;
|
||||
parent.Children.Add(child.ID);
|
||||
parent.RecalculateMass();
|
||||
}
|
||||
|
||||
public void RemoveParent(Entity child)
|
||||
{
|
||||
if (child.Parent == Guid.Empty)
|
||||
return;
|
||||
|
||||
var parent = Cache.Get<Entity>(child.Parent);
|
||||
parent.Children.Remove(child.ID);
|
||||
child.Parent = Guid.Empty;
|
||||
}
|
||||
}
|
||||
|
|
@ -133,6 +133,12 @@ public class GlobalData : DatabaseEntry
|
|||
|
||||
[InspectableField, JsonProperty("resourceDensityMaximum"), Key(41)]
|
||||
public float ResourceDensityMaximum = 1.5f;
|
||||
|
||||
[InspectableField, JsonProperty("startingGearQualityMin"), Key(42)]
|
||||
public float StartingGearQualityMin = .1f;
|
||||
|
||||
[InspectableField, JsonProperty("startingGearQualityMax"), Key(43)]
|
||||
public float StartingGearQualityMax = .5f;
|
||||
|
||||
public float PlanetRadius(float mass)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,9 +54,8 @@ public class ZoneGenerator
|
|||
// Create orbit database entries
|
||||
orbitData = planets.Select(planet =>
|
||||
{
|
||||
var data = new OrbitData()
|
||||
var data = new OrbitData
|
||||
{
|
||||
ID = Guid.NewGuid(),
|
||||
Distance = planet.Distance,
|
||||
Period = planet.Period,
|
||||
Phase = planet.Phase,
|
||||
|
|
@ -95,7 +94,6 @@ public class ZoneGenerator
|
|||
var planetData = new PlanetData
|
||||
{
|
||||
Mass = planet.Mass,
|
||||
ID = Guid.NewGuid(),
|
||||
Orbit = orbitMap[planet].ID,
|
||||
Zone = zone.ID,
|
||||
Belt = planet.Belt,
|
||||
|
|
|
|||
Loading…
Reference in a new issue