WPos PreviewPosition(World world, TypeDictionary init) { if (init.Contains <CenterPositionInit>()) { return(init.Get <CenterPositionInit>().Value(world)); } if (init.Contains <LocationInit>()) { var cell = init.Get <LocationInit>().Value(world); var offset = WVec.Zero; var subCellInit = actor.InitDict.GetOrDefault <SubCellInit>(); var subCell = subCellInit != null?subCellInit.Value(worldRenderer.World) : SubCell.Any; var buildingInfo = Info.TraitInfoOrDefault <BuildingInfo>(); if (buildingInfo != null) { offset = buildingInfo.CenterOffset(world); } return(world.Map.CenterOfSubCell(cell, subCell) + offset); } else { throw new InvalidDataException("Actor {0} must define Location or CenterPosition".F(ID)); } }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits) { if (!inits.Contains <DynamicFacingInit>() && !inits.Contains <FacingInit>()) { inits.Add(new DynamicFacingInit(() => Facing)); } }
/// <summary> /// Schedules to insert an entity into the stage next frame. /// </summary> public static T AddEntity <T>(T entity) where T : Entity { if (_entities.Contains(entity)) { throw new InvalidOperationException($"Entity already exists in scene."); } _removeEntities.Remove(entity); _addEntities.Add(entity); return(entity); }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits) { if (!inits.Contains <FactionInit>()) { inits.Add(new FactionInit(faction)); } }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } if (name != null) { name = name.ToLowerInvariant(); if (!world.Map.Rules.Actors.ContainsKey(name)) { throw new NotImplementedException("No rules definition for unit " + name); } Info = world.Map.Rules.Actors[name]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); // Some traits rely on properties provided by IOccupySpace in their initialization, // so we must ready it now, we cannot wait until all traits have finished construction. if (trait is IOccupySpaceInfo) { OccupiesSpace = Trait <IOccupySpace>(); } } } // PERF: Cache all these traits as soon as the actor is created. This is a fairly cheap one-off cost per // actor that allows us to provide some fast implementations of commonly used methods that are relied on by // performance-sensitive parts of the core game engine, such as pathfinding, visibility and rendering. EffectiveOwner = TraitOrDefault <IEffectiveOwner>(); facing = TraitOrDefault <IFacing>(); health = TraitOrDefault <IHealth>(); renderModifiers = TraitsImplementing <IRenderModifier>().ToArray(); renders = TraitsImplementing <IRender>().ToArray(); mouseBounds = TraitsImplementing <IMouseBounds>().ToArray(); visibilityModifiers = TraitsImplementing <IVisibilityModifier>().ToArray(); defaultVisibility = Trait <IDefaultVisibility>(); Targetables = TraitsImplementing <ITargetable>().ToArray(); targetablePositions = TraitsImplementing <ITargetablePositions>().ToArray(); world.AddFrameEndTask(w => { // Caching this in a AddFrameEndTask, because trait construction order might cause problems if done directly at creation time. // All actors that can move or teleport should have IPositionable, if not it's pretty safe to assume the actor is completely immobile and // all targetable positions can be cached if all ITargetablePositions have no conditional requirements. if (!Info.HasTraitInfo <IPositionableInfo>() && targetablePositions.Any() && targetablePositions.All(tp => tp.AlwaysEnabled)) { staticTargetablePositions = targetablePositions.SelectMany(tp => tp.TargetablePositions(this)).ToArray(); } }); SyncHashes = TraitsImplementing <ISync>().Select(sync => new SyncHash(sync)).ToArray(); }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } occupySpace = Lazy.New(() => TraitOrDefault <IOccupySpace>()); if (name != null) { if (!Rules.Info.ContainsKey(name.ToLowerInvariant())) { throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant())); } Info = Rules.Info[name.ToLowerInvariant()]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); } } Move = Lazy.New(() => TraitOrDefault <IMove>()); Facing = Lazy.New(() => TraitOrDefault <IFacing>()); Size = Lazy.New(() => { var si = Info.Traits.GetOrDefault <SelectableInfo>(); if (si != null && si.Bounds != null) { return(new int2(si.Bounds[0], si.Bounds[1])); } return(TraitsImplementing <IAutoSelectionSize>().Select(x => x.SelectionSize(this)).FirstOrDefault()); }); if (this.HasTrait <RevealsShroud>()) { Sight = new Shroud.ActorVisibility { range = this.Trait <RevealsShroud>().RevealRange, vis = Shroud.GetVisOrigins(this).ToArray() }; } ApplyIRender = (x, wr) => x.Render(this, wr); ApplyRenderModifier = (m, p, wr) => p.ModifyRender(this, wr, m); Bounds = Cached.New(() => CalculateBounds(false)); ExtendedBounds = Cached.New(() => CalculateBounds(true)); }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } if (name != null) { name = name.ToLowerInvariant(); if (!world.Map.Rules.Actors.ContainsKey(name)) { throw new NotImplementedException("No rules definition for unit " + name); } Info = world.Map.Rules.Actors[name]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); // Some traits rely on properties provided by IOccupySpace in their initialization, // so we must ready it now, we cannot wait until all traits have finished construction. if (trait is IOccupySpaceInfo) { OccupiesSpace = Trait <IOccupySpace>(); } } } // PERF: Cache all these traits as soon as the actor is created. This is a fairly cheap one-off cost per // actor that allows us to provide some fast implementations of commonly used methods that are relied on by // performance-sensitive parts of the core game engine, such as pathfinding, visibility and rendering. Bounds = DetermineBounds(); VisualBounds = DetermineVisualBounds(); EffectiveOwner = TraitOrDefault <IEffectiveOwner>(); facing = TraitOrDefault <IFacing>(); health = TraitOrDefault <IHealth>(); renderModifiers = TraitsImplementing <IRenderModifier>().ToArray(); renders = TraitsImplementing <IRender>().ToArray(); disables = TraitsImplementing <IDisable>().ToArray(); visibilityModifiers = TraitsImplementing <IVisibilityModifier>().ToArray(); defaultVisibility = Trait <IDefaultVisibility>(); Targetables = TraitsImplementing <ITargetable>().ToArray(); SyncHashes = TraitsImplementing <ISync>() .Select(sync => Pair.New(sync, Sync.GetHashFunction(sync))) .ToArray() .Select(pair => new SyncHash(pair.First, pair.Second(pair.First))); }
public void Contains() { var td = new TypeDictionary <IServiceCollection, IServiceProvider> { [typeof(ServiceCollection)] = typeof(ServiceProvider) }; td.Contains <ServiceCollection>().ShouldBeTrue(); td.ContainsKey(typeof(ServiceCollection)).ShouldBeTrue(); (td as ICollection <KeyValuePair <Type, Type> >).Contains(new KeyValuePair <Type, Type>(typeof(ServiceCollection), typeof(ServiceProvider))).ShouldBeTrue(); }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } occupySpace = Lazy.New(() => TraitOrDefault <IOccupySpace>()); if (name != null) { if (!Rules.Info.ContainsKey(name.ToLowerInvariant())) { throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant())); } Info = Rules.Info[name.ToLowerInvariant()]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); } } Move = Lazy.New(() => TraitOrDefault <IMove>()); Size = Lazy.New(() => { var si = Info.Traits.GetOrDefault <SelectableInfo>(); if (si != null && si.Bounds != null) { return(new int2(si.Bounds[0], si.Bounds[1])); } // auto size from render var firstSprite = TraitsImplementing <IRender>().SelectMany(ApplyIRender).FirstOrDefault(); if (firstSprite.Sprite == null) { return(int2.Zero); } return((firstSprite.Sprite.size * firstSprite.Scale).ToInt2()); }); ApplyIRender = x => x.Render(this); ApplyRenderModifier = (m, p) => p.ModifyRender(this, m); Bounds = Cached.New(() => CalculateBounds(false)); ExtendedBounds = Cached.New(() => CalculateBounds(true)); }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } occupySpace = Exts.Lazy(() => TraitOrDefault <IOccupySpace>()); if (name != null) { name = name.ToLowerInvariant(); if (!world.Map.Rules.Actors.ContainsKey(name)) { throw new NotImplementedException("No rules definition for unit " + name); } Info = world.Map.Rules.Actors[name]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); } } facing = Exts.Lazy(() => TraitOrDefault <IFacing>()); health = Exts.Lazy(() => TraitOrDefault <Health>()); effectiveOwner = Exts.Lazy(() => TraitOrDefault <IEffectiveOwner>()); bounds = Exts.Lazy(() => { var si = Info.Traits.GetOrDefault <SelectableInfo>(); var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) : TraitsImplementing <IAutoSelectionSize>().Select(x => x.SelectionSize(this)).FirstOrDefault(); var offset = -size / 2; if (si != null && si.Bounds != null && si.Bounds.Length > 2) { offset += new int2(si.Bounds[2], si.Bounds[3]); } return(new Rectangle(offset.X, offset.Y, size.X, size.Y)); }); renderModifiers = TraitsImplementing <IRenderModifier>().ToArray(); renders = TraitsImplementing <IRender>().ToArray(); disables = TraitsImplementing <IDisable>().ToArray(); }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } if (name != null) { name = name.ToLowerInvariant(); if (!world.Map.Rules.Actors.ContainsKey(name)) { throw new NotImplementedException("No rules definition for unit {0}".F(name)); } Info = world.Map.Rules.Actors[name]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); if (trait is IOccupySpaceInfo) { OccupiesSpace = Trait <IOccupySpace>(); } } } EffectiveOwner = TraitOrDefault <IEffectiveOwner>(); facing = TraitOrDefault <IFacing>(); health = TraitOrDefault <IHealth>(); disables = TraitsImplementing <IDisable>().ToArray(); renders = TraitsImplementing <IRender>().ToArray(); renderModifiers = TraitsImplementing <IRenderModifier>().ToArray(); visibilityModifiers = TraitsImplementing <IVisibilityModifier>().ToArray(); defaultVisibility = Trait <IDefaultVisibility>(); Targetables = TraitsImplementing <ITargetable>().ToArray(); mouseBounds = TraitsImplementing <IMouseBounds>().ToArray(); //Bounds = DetermineBounds(); //SyncHashes = TraitsImplementing<ISync>() // .Select(sync => Pair.New(sync, Sync.GetHashFunction(sync))) // .ToArray() // .Select(pair => new SyncHash(pair.First, pair.Second(pair.First))); SyncHashes = TraitsImplementing <ISync>().Select(sync => new SyncHash(sync)).ToArray(); }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } occupySpace = Lazy.New(() => TraitOrDefault <IOccupySpace>()); if (name != null) { if (!Rules.Info.ContainsKey(name.ToLowerInvariant())) { throw new NotImplementedException("No rules definition for unit {0}".F(name.ToLowerInvariant())); } Info = Rules.Info[name.ToLowerInvariant()]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); } } facing = Lazy.New(() => TraitOrDefault <IFacing>()); health = Lazy.New(() => TraitOrDefault <Health>()); applyIRender = (x, wr) => x.Render(this, wr); applyRenderModifier = (m, p, wr) => p.ModifyRender(this, wr, m); Bounds = Lazy.New(() => { var si = Info.Traits.GetOrDefault <SelectableInfo>(); var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) : TraitsImplementing <IAutoSelectionSize>().Select(x => x.SelectionSize(this)).FirstOrDefault(); var offset = -size / 2; if (si != null && si.Bounds != null && si.Bounds.Length > 2) { offset += new int2(si.Bounds[2], si.Bounds[3]); } return(new Rectangle(offset.X, offset.Y, size.X, size.Y)); }); }
internal Actor(World world, string name, TypeDictionary initDict) { var init = new ActorInitializer(this, initDict); World = world; ActorID = world.NextAID(); if (initDict.Contains <OwnerInit>()) { Owner = init.Get <OwnerInit, Player>(); } if (name != null) { name = name.ToLowerInvariant(); if (!world.Map.Rules.Actors.ContainsKey(name)) { throw new NotImplementedException("No rules definition for unit " + name); } Info = world.Map.Rules.Actors[name]; foreach (var trait in Info.TraitsInConstructOrder()) { AddTrait(trait.Create(init)); // Some traits rely on properties provided by IOccupySpace in their initialization, // so we must ready it now, we cannot wait until all traits have finished construction. if (trait is IOccupySpaceInfo) { OccupiesSpace = Trait <IOccupySpace>(); } } } Bounds = DetermineBounds(); VisualBounds = DetermineVisualBounds(); EffectiveOwner = TraitOrDefault <IEffectiveOwner>(); facing = TraitOrDefault <IFacing>(); health = TraitOrDefault <IHealth>(); renderModifiers = TraitsImplementing <IRenderModifier>().ToArray(); renders = TraitsImplementing <IRender>().ToArray(); disables = TraitsImplementing <IDisable>().ToArray(); visibilityModifiers = TraitsImplementing <IVisibilityModifier>().ToArray(); defaultVisibility = Trait <IDefaultVisibility>(); }
public ActorReference(string type, Dictionary <string, MiniYaml> inits) { Type = type; initDict = Exts.Lazy(() => { var dict = new TypeDictionary(); foreach (var i in inits) { var init = LoadInit(i.Key, i.Value); if (init is ISingleInstanceInit && dict.Contains(init.GetType())) { throw new InvalidDataException("Duplicate initializer '{0}'".F(init.GetType().Name)); } dict.Add(init); } return(dict); }); }
public bool Contains <T>() where T : IActorInit { return(Dict.Contains <T>()); }
// Don't add the new actor to the world before all RemovedFromWorld callbacks have run void INotifyRemovedFromWorld.RemovedFromWorld(Actor self) { if (attackingPlayer == null) { return; } var defeated = self.Owner.WinState == WinState.Lost; if (defeated && !Info.SpawnAfterDefeat) { return; } var td = new TypeDictionary { new ParentActorInit(self), new LocationInit(self.Location + Info.Offset), new CenterPositionInit(self.CenterPosition), new FactionInit(faction) }; if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised) { td.Add(new EffectiveOwnerInit(self.EffectiveOwner.Owner)); } else if (Info.EffectiveOwnerFromOwner) { td.Add(new EffectiveOwnerInit(self.Owner)); } if (Info.OwnerType == OwnerType.Victim) { // Fall back to InternalOwner if the Victim was defeated, // but only if InternalOwner is defined if (!defeated || string.IsNullOrEmpty(Info.InternalOwner)) { td.Add(new OwnerInit(self.Owner)); } else { td.Add(new OwnerInit(self.World.Players.First(p => p.InternalName == Info.InternalOwner))); if (!td.Contains <EffectiveOwnerInit>()) { td.Add(new EffectiveOwnerInit(self.Owner)); } } } else if (Info.OwnerType == OwnerType.Killer) { td.Add(new OwnerInit(attackingPlayer)); } else { td.Add(new OwnerInit(self.World.Players.First(p => p.InternalName == Info.InternalOwner))); } if (Info.SkipMakeAnimations) { td.Add(new SkipMakeAnimsInit()); } foreach (var modifier in self.TraitsImplementing <IDeathActorInitModifier>()) { modifier.ModifyDeathActorInit(self, td); } var huskActor = self.TraitsImplementing <IHuskModifier>() .Select(ihm => ihm.HuskActor(self)) .FirstOrDefault(a => a != null); self.World.AddFrameEndTask(w => w.CreateActor(huskActor ?? Info.Actor, td)); }
public bool Contains <T>() where T : IGlobalModData { return(modules.Contains <T>()); }
public bool AlreadyContains <T>() where T : GameState { return(m_StateDictionary.Contains <T>()); }
void IActorPreviewInitModifier.ModifyActorPreviewInit(Actor self, TypeDictionary inits) { if (!inits.Contains<FactionInit>()) inits.Add(new FactionInit(faction)); }
public bool HasTraitInfo <T>() where T : ITraitInfoInterface { return(traits.Contains <T>()); }