/// <summary> /// Call if this entity is relevant for the pathfinder /// </summary> /// <param name="entity"></param> /// TODO: These 2 methods currently don't account for a bunch of changes (e.g. airlock unpowered, wrenching, etc.) /// TODO: Could probably optimise this slightly more. public void AddEntity(IEntity entity, IPhysicsComponent physicsComponent) { // If we're a door if (entity.HasComponent <AirlockComponent>() || entity.HasComponent <ServerDoorComponent>()) { // If we need access to traverse this then add to readers, otherwise no point adding it (except for maybe tile costs in future) // TODO: Check for powered I think (also need an event for when it's depowered // AccessReader calls this whenever opening / closing but it can seem to get called multiple times // Which may or may not be intended? if (entity.TryGetComponent(out AccessReader accessReader) && !_accessReaders.ContainsKey(entity)) { _accessReaders.Add(entity, accessReader); ParentChunk.Dirty(); } return; } DebugTools.Assert((PathfindingSystem.TrackedCollisionLayers & physicsComponent.CollisionLayer) != 0); if (!physicsComponent.Anchored) { _physicsLayers.Add(entity, physicsComponent.CollisionLayer); } else { _blockedCollidables.Add(entity, physicsComponent.CollisionLayer); GenerateMask(); ParentChunk.Dirty(); } }
/// <summary> /// Returns information about given voxel face which is then used in meshing algorithm /// </summary> /// <param name="x">Chunk segment relative block X coordinate.</param> /// <param name="y">Chunk segment relative block Y coordinate.</param> /// <param name="z">Chunk segment relative block Z coordinate.</param> /// <param name="side">Face side we want to get, is one of constants in the beginning of this file</param> /// <returns>Face data about the block</returns> /// <remarks> /// Currently returns only block data since face data are not yet implemented /// X, Y, Z are in the range of -1 to 16 (chunk +- 1 block from neighbor) /// </remarks> private Block GetVoxelFace(int x, int y, int z, int side) { var xValid = x >= 0 && x < VoxelWorld.Configuration.ChunkSegmentSize; var yValid = y >= 0 && y < VoxelWorld.Configuration.ChunkSegmentSize; var zValid = z >= 0 && z < VoxelWorld.Configuration.ChunkSegmentSize; // Current segment if (xValid && yValid && zValid) { return(Blocks[x, y, z]); } // Get world absolute Y coordinate var absY = VoxelWorld.Configuration.ChunkSegmentSize * _segmentIndex + y; // Current chunk (this is faster then performing chunk lookup) if (!yValid && xValid && zValid) { return(ParentChunk.GetBlock(x, absY, z)); } // Perform world-wide block lookup var absX = VoxelWorld.Configuration.ChunkSegmentSize * ParentChunk.WorldPosition.X + x; var absZ = VoxelWorld.Configuration.ChunkSegmentSize * ParentChunk.WorldPosition.Y + z; return(ParentChunk.World.GetBlock(absX, absY, absZ)); }
/// <summary> /// Starts the generation of a <see cref="TagHelperChunk"/>. /// </summary> /// <param name="target"> /// The <see cref="Block"/> responsible for this <see cref="TagHelperChunkGenerator"/>. /// </param> /// <param name="context">A <see cref="ChunkGeneratorContext"/> instance that contains information about /// the current chunk generation process.</param> public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context) { var tagHelperBlock = target as TagHelperBlock; Debug.Assert( tagHelperBlock != null, $"A {nameof(TagHelperChunkGenerator)} must only be used with {nameof(TagHelperBlock)}s."); var attributes = new List <TagHelperAttributeTracker>(); // We need to create a chunk generator to create chunks for each of the attributes. var chunkGenerator = context.Host.CreateChunkGenerator( context.ClassName, context.RootNamespace, context.SourceFile); foreach (var attribute in tagHelperBlock.Attributes) { ParentChunk attributeChunkValue = null; if (attribute.Value != null) { // Populates the chunk tree with chunks associated with attributes attribute.Value.Accept(chunkGenerator); var chunks = chunkGenerator.Context.ChunkTreeBuilder.Root.Children; var first = chunks.FirstOrDefault(); attributeChunkValue = new ParentChunk { Association = first?.Association, Children = chunks, Start = first == null ? SourceLocation.Zero : first.Start }; } var attributeChunk = new TagHelperAttributeTracker( attribute.Name, attributeChunkValue, attribute.ValueStyle); attributes.Add(attributeChunk); // Reset the chunk tree builder so we can build a new one for the next attribute chunkGenerator.Context.ChunkTreeBuilder = new ChunkTreeBuilder(); } var unprefixedTagName = tagHelperBlock.TagName.Substring(_tagHelperDescriptors.First().Prefix.Length); context.ChunkTreeBuilder.StartParentChunk( new TagHelperChunk( unprefixedTagName, tagHelperBlock.TagMode, attributes, _tagHelperDescriptors), target, topLevel: false); }
/// <summary> /// Starts the generation of a <see cref="TagHelperChunk"/>. /// </summary> /// <param name="target"> /// The <see cref="Block"/> responsible for this <see cref="TagHelperChunkGenerator"/>. /// </param> /// <param name="context">A <see cref="ChunkGeneratorContext"/> instance that contains information about /// the current chunk generation process.</param> public override void GenerateStartParentChunk(Block target, ChunkGeneratorContext context) { var tagHelperBlock = target as TagHelperBlock; Debug.Assert( tagHelperBlock != null, $"A {nameof(TagHelperChunkGenerator)} must only be used with {nameof(TagHelperBlock)}s."); var attributes = new List<KeyValuePair<string, Chunk>>(); // We need to create a chunk generator to create chunks for each of the attributes. var chunkGenerator = context.Host.CreateChunkGenerator( context.ClassName, context.RootNamespace, context.SourceFile); foreach (var attribute in tagHelperBlock.Attributes) { ParentChunk attributeChunkValue = null; if (attribute.Value != null) { // Populates the chunk tree with chunks associated with attributes attribute.Value.Accept(chunkGenerator); var chunks = chunkGenerator.Context.ChunkTreeBuilder.ChunkTree.Chunks; var first = chunks.FirstOrDefault(); attributeChunkValue = new ParentChunk { Association = first?.Association, Children = chunks, Start = first == null ? SourceLocation.Zero : first.Start }; } attributes.Add(new KeyValuePair<string, Chunk>(attribute.Key, attributeChunkValue)); // Reset the chunk tree builder so we can build a new one for the next attribute chunkGenerator.Context.ChunkTreeBuilder = new ChunkTreeBuilder(); } var unprefixedTagName = tagHelperBlock.TagName.Substring(_tagHelperDescriptors.First().Prefix.Length); context.ChunkTreeBuilder.StartParentChunk( new TagHelperChunk( unprefixedTagName, tagHelperBlock.TagMode, attributes, _tagHelperDescriptors), target, topLevel: false); }
/// <summary> /// Writes code for the given <paramref name="chunk"/>. /// </summary> /// <param name="chunk">The <see cref="ParentChunk"/> to render.</param> /// <remarks> /// Tracks code mappings for all children while writing. /// </remarks> protected override void Visit(ParentChunk chunk) { // Line mappings are captured in RenderCode(), not this method. _firstChild = true; Accept(chunk.Children); if (_firstChild) { // Attribute value was empty. Context.ErrorSink.OnError( chunk.Association.Start, RazorResources.TagHelpers_AttributeExpressionRequired, chunk.Association.Length); } }
/// <summary> /// Return our neighboring nodes (even across chunks) /// </summary> /// <returns></returns> public IEnumerable <PathfindingNode> GetNeighbors() { List <PathfindingChunk> neighborChunks = null; if (ParentChunk.OnEdge(this)) { neighborChunks = ParentChunk.RelevantChunks(this).ToList(); } for (var x = -1; x <= 1; x++) { for (var y = -1; y <= 1; y++) { if (x == 0 && y == 0) { continue; } var indices = new Vector2i(TileRef.X + x, TileRef.Y + y); if (ParentChunk.InBounds(indices)) { var(relativeX, relativeY) = (indices.X - ParentChunk.Indices.X, indices.Y - ParentChunk.Indices.Y); yield return(ParentChunk.Nodes[relativeX, relativeY]); } else { DebugTools.AssertNotNull(neighborChunks); // Get the relevant chunk and then get the node on it foreach (var neighbor in neighborChunks) { // A lot of edge transitions are going to have a single neighboring chunk // (given > 1 only affects corners) // So we can just check the count to see if it's inbound if (neighborChunks.Count > 0 && !neighbor.InBounds(indices)) { continue; } var(relativeX, relativeY) = (indices.X - neighbor.Indices.X, indices.Y - neighbor.Indices.Y); yield return(neighbor.Nodes[relativeX, relativeY]); break; } } } } }
public bool FindSuccessNode() { if (SuccessNode == null) { ActionNodeState successState = null; if (ParentChunk.GetNode(State.SuccessActionNodeName, false, out successState)) { SuccessNode = successState.actionNode; if (SuccessNode == null) { //Debug.Log ("Couldn't find success node in " + name + " but it doesn't matter, still returning true"); return(false); } } } return(true); }
public override bool OnPlayerEnter() { if (mDimmingLanterns) { return(false); } if (LanternsToDim.Count == 0) { WorldItem lanternWorldItem = null; for (int i = 0; i < State.LanternsToDim.Count; i++) { MobileReference mr = State.LanternsToDim[i]; if (WIGroups.FindChildItem(mr.GroupPath, mr.FileName, out lanternWorldItem)) { LanternsToDim.Add(lanternWorldItem); } } if (State.LanternsToDim.Count == 0) { return(false); } } if (GuardInterventionTrigger == null) { WorldTriggerState wts = null; if (ParentChunk.GetTriggerState(State.GuardInterventionTriggerName, out wts)) { GuardInterventionTrigger = wts.trigger as TriggerGuardIntervention; } else { return(false); } } mDimmingLanterns = true; mStartTime = WorldClock.AdjustedRealTime; StartCoroutine(DimLanternsOverTime()); return(true); }
/// <summary> /// Remove the entity from this node. /// Will check each category and remove it from the applicable one /// </summary> /// <param name="entity"></param> public void RemoveEntity(IEntity entity) { // There's no guarantee that the entity isn't deleted // 90% of updates are probably entities moving around // Entity can't be under multiple categories so just checking each once is fine. if (_physicsLayers.ContainsKey(entity)) { _physicsLayers.Remove(entity); } else if (_accessReaders.ContainsKey(entity)) { _accessReaders.Remove(entity); ParentChunk.Dirty(); } else if (_blockedCollidables.ContainsKey(entity)) { _blockedCollidables.Remove(entity); GenerateMask(); ParentChunk.Dirty(); } }
public bool FindGuardNode() { if (GuardNode == null) { ActionNodeState guardNodeState = null; if (ParentChunk.GetNode(State.GuardActionNodeName, false, out guardNodeState)) { guardNodeState.OccupantIsDead = State.GuardIsDead; GuardNode = guardNodeState.actionNode; if (GuardNode == null) { //Debug.Log ("Couldn't get guard node from action node state, quitting in " + name); return(false); } } else { //Debug.Log ("Couldn't get guard node from parent chunk, quitting in " + name); return(false); } } return(true); }
public override bool OnPlayerEnter() { if (AvailableSpawnNodes.Count == 0) { ParentChunk.GetNodes(State.AvailableSpawnNodes, true, AvailableSpawnNodes); } //now get the node we want to spawn at if (AvailableSpawnNodes.Count == 0) { Debug.Log("NO SPAWN NODES AVAILBLE in " + name); return(false); } if (mSpawningOverTime) { return(false); } else { mSpawningOverTime = true; StartCoroutine(SpawnOverTime()); return(true); } }
public void UpdateTile(TileRef newTile) { TileRef = newTile; ParentChunk.Dirty(); }
public PathfindingNode GetNeighbor(Direction direction) { var chunkXOffset = TileRef.X - ParentChunk.Indices.X; var chunkYOffset = TileRef.Y - ParentChunk.Indices.Y; Vector2i neighborVector2i; switch (direction) { case Direction.East: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset + 1, chunkYOffset]); } neighborVector2i = new Vector2i(TileRef.X + 1, TileRef.Y); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); case Direction.NorthEast: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset + 1, chunkYOffset + 1]); } neighborVector2i = new Vector2i(TileRef.X + 1, TileRef.Y + 1); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); case Direction.North: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset, chunkYOffset + 1]); } neighborVector2i = new Vector2i(TileRef.X, TileRef.Y + 1); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); case Direction.NorthWest: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset - 1, chunkYOffset + 1]); } neighborVector2i = new Vector2i(TileRef.X - 1, TileRef.Y + 1); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); case Direction.West: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset - 1, chunkYOffset]); } neighborVector2i = new Vector2i(TileRef.X - 1, TileRef.Y); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); case Direction.SouthWest: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset - 1, chunkYOffset - 1]); } neighborVector2i = new Vector2i(TileRef.X - 1, TileRef.Y - 1); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); case Direction.South: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset, chunkYOffset - 1]); } neighborVector2i = new Vector2i(TileRef.X, TileRef.Y - 1); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); case Direction.SouthEast: if (!ParentChunk.OnEdge(this)) { return(ParentChunk.Nodes[chunkXOffset + 1, chunkYOffset - 1]); } neighborVector2i = new Vector2i(TileRef.X + 1, TileRef.Y - 1); foreach (var neighbor in ParentChunk.GetNeighbors()) { if (neighbor.InBounds(neighborVector2i)) { return(neighbor.Nodes[neighborVector2i.X - neighbor.Indices.X, neighborVector2i.Y - neighbor.Indices.Y]); } } return(null); default: throw new ArgumentOutOfRangeException(nameof(direction), direction, null); } }
protected virtual void Visit(ParentChunk chunk) { Accept(chunk.Children); }
protected abstract void Visit(ParentChunk chunk);
protected IEnumerator DimLanternsOverTime() { Debug.Log("Dimming lanterns!"); GUI.GUIManager.PostIntrospection(State.IntrospectionBeforeStarting, true); double waitUntil = WorldClock.AdjustedRealTime + State.InitialDelay; while (WorldClock.AdjustedRealTime < waitUntil) { yield return(null); } GuardInterventionTrigger.SuspendGuard(); //GuardInterventionTrigger.gameObject.SetActive (false); for (int i = 0; i < LanternsToDim.Count; i++) { LanternDimmer ld = LanternsToDim[i].Get <LanternDimmer>(); ld.StartDimming(); waitUntil = WorldClock.AdjustedRealTime + 0.5f; } if (State.UseReactivationTrigger) { WorldTriggerState reactivationTriggerState = null; if (ParentChunk.GetTriggerState(State.ReactivationTriggerName, out reactivationTriggerState)) { int numTimesTriggeredOnStart = reactivationTriggerState.NumTimesTriggered; while (reactivationTriggerState.NumTimesTriggered == numTimesTriggeredOnStart) { //wait until it's been triggered again waitUntil = WorldClock.AdjustedRealTime + 0.5f; while (WorldClock.AdjustedRealTime < waitUntil) { yield return(null); } } } } else { while (WorldClock.AdjustedRealTime < mStartTime + State.RTDimDuration) { yield return(null); } } for (int i = 0; i < LanternsToDim.Count; i++) { LanternDimmer ld = LanternsToDim[i].Get <LanternDimmer>(); ld.StopDimming(); waitUntil = WorldClock.AdjustedRealTime + 0.5f; while (WorldClock.AdjustedRealTime < waitUntil) { yield return(null); } } //GuardInterventionTrigger.gameObject.SetActive (true); GuardInterventionTrigger.ResumeGuard(false); mDimmingLanterns = false; yield break; }
protected override void Visit(ParentChunk chunk) { Accept(chunk.Children); }
protected override void Visit(ParentChunk chunk) { }