/// </summary>
private async Task PostGen(
OreDunGen gen,
- Dungeon dungeon,
+ List<Dungeon> dungeons,
+ HashSet<Vector2i> reservedTiles,
Random random)
{
- // Doesn't use dungeon data because layers and we don't need top-down support at the moment.
-
- var emptyTiles = false;
- var replaceEntities = new Dictionary<Vector2i, EntityUid>();
- var availableTiles = new List<Vector2i>();
-
- foreach (var node in dungeon.AllTiles)
+ foreach (var dungeon in dungeons)
{
- // Empty tile, skip if relevant.
- if (!emptyTiles && (!_maps.TryGetTile(_grid, node, out var tile) || tile.IsEmpty))
- continue;
-
- // Check if it's a valid spawn, if so then use it.
- var enumerator = _maps.GetAnchoredEntitiesEnumerator(_gridUid, _grid, node);
- var found = false;
-
- // We use existing entities as a mark to spawn in place
- // OR
- // We check for any existing entities to see if we can spawn there.
- while (enumerator.MoveNext(out var uid))
+ var emptyTiles = false;
+ var replaceEntities = new Dictionary<Vector2i, EntityUid>();
+ var availableTiles = new List<Vector2i>();
+
+ foreach (var node in dungeon.AllTiles)
{
- // We can't replace so just stop here.
- if (gen.Replacement == null)
- break;
+ if (reservedTiles.Contains(node))
+ continue;
- var prototype = _entManager.GetComponent<MetaDataComponent>(uid.Value).EntityPrototype;
+ // Empty tile, skip if relevant.
+ if (!emptyTiles && (!_maps.TryGetTile(_grid, node, out var tile) || tile.IsEmpty))
+ continue;
- if (prototype?.ID == gen.Replacement)
- {
- replaceEntities[node] = uid.Value;
- found = true;
- break;
- }
- }
+ // Check if it's a valid spawn, if so then use it.
+ var enumerator = _maps.GetAnchoredEntitiesEnumerator(_gridUid, _grid, node);
+ var found = false;
- if (!found)
- continue;
+ // We use existing entities as a mark to spawn in place
+ // OR
+ // We check for any existing entities to see if we can spawn there.
+ while (enumerator.MoveNext(out var uid))
+ {
+ // We can't replace so just stop here.
+ if (gen.Replacement == null)
+ break;
- // Add it to valid nodes.
- availableTiles.Add(node);
+ var prototype = _entManager.GetComponent<MetaDataComponent>(uid.Value).EntityPrototype;
- await SuspendDungeon();
+ if (prototype?.ID == gen.Replacement)
+ {
+ replaceEntities[node] = uid.Value;
+ found = true;
+ break;
+ }
+ }
- if (!ValidateResume())
- return;
- }
+ if (!found)
+ continue;
- var remapping = new Dictionary<EntProtoId, EntProtoId>();
+ // Add it to valid nodes.
+ availableTiles.Add(node);
- // TODO: Move this to engine
- if (_prototype.TryIndex(gen.Entity, out var proto) &&
- proto.Components.TryGetComponent("EntityRemap", out var comps))
- {
- var remappingComp = (EntityRemapComponent) comps;
- remapping = remappingComp.Mask;
- }
+ await SuspendDungeon();
- var frontier = new ValueList<Vector2i>(32);
+ if (!ValidateResume())
+ return;
+ }
- // Iterate the group counts and pathfind out each group.
- for (var i = 0; i < gen.Count; i++)
- {
- await SuspendDungeon();
+ var remapping = new Dictionary<EntProtoId, EntProtoId>();
- if (!ValidateResume())
- return;
+ // TODO: Move this to engine
+ if (_prototype.TryIndex(gen.Entity, out var proto) &&
+ proto.Components.TryGetComponent("EntityRemap", out var comps))
+ {
+ var remappingComp = (EntityRemapComponent) comps;
+ remapping = remappingComp.Mask;
+ }
- var groupSize = random.Next(gen.MinGroupSize, gen.MaxGroupSize + 1);
+ var frontier = new ValueList<Vector2i>(32);
- // While we have remaining tiles keep iterating
- while (groupSize > 0 && availableTiles.Count > 0)
+ // Iterate the group counts and pathfind out each group.
+ for (var i = 0; i < gen.Count; i++)
{
- var startNode = random.PickAndTake(availableTiles);
- frontier.Clear();
- frontier.Add(startNode);
+ await SuspendDungeon();
+
+ if (!ValidateResume())
+ return;
+
+ var groupSize = random.Next(gen.MinGroupSize, gen.MaxGroupSize + 1);
- // This essentially may lead to a vein being split in multiple areas but the count matters more than position.
- while (frontier.Count > 0 && groupSize > 0)
+ // While we have remaining tiles keep iterating
+ while (groupSize > 0 && availableTiles.Count > 0)
{
- // Need to pick a random index so we don't just get straight lines of ores.
- var frontierIndex = random.Next(frontier.Count);
- var node = frontier[frontierIndex];
- frontier.RemoveSwap(frontierIndex);
- availableTiles.Remove(node);
-
- // Add neighbors if they're valid, worst case we add no more and pick another random seed tile.
- for (var x = -1; x <= 1; x++)
+ var startNode = random.PickAndTake(availableTiles);
+ frontier.Clear();
+ frontier.Add(startNode);
+
+ // This essentially may lead to a vein being split in multiple areas but the count matters more than position.
+ while (frontier.Count > 0 && groupSize > 0)
{
- for (var y = -1; y <= 1; y++)
+ // Need to pick a random index so we don't just get straight lines of ores.
+ var frontierIndex = random.Next(frontier.Count);
+ var node = frontier[frontierIndex];
+ frontier.RemoveSwap(frontierIndex);
+ availableTiles.Remove(node);
+
+ // Add neighbors if they're valid, worst case we add no more and pick another random seed tile.
+ for (var x = -1; x <= 1; x++)
{
- var neighbor = new Vector2i(node.X + x, node.Y + y);
+ for (var y = -1; y <= 1; y++)
+ {
+ var neighbor = new Vector2i(node.X + x, node.Y + y);
- if (frontier.Contains(neighbor) || !availableTiles.Contains(neighbor))
- continue;
+ if (frontier.Contains(neighbor) || !availableTiles.Contains(neighbor))
+ continue;
- frontier.Add(neighbor);
+ frontier.Add(neighbor);
+ }
}
- }
- var prototype = gen.Entity;
-
- if (replaceEntities.TryGetValue(node, out var existingEnt))
- {
- var existingProto = _entManager.GetComponent<MetaDataComponent>(existingEnt).EntityPrototype;
- _entManager.DeleteEntity(existingEnt);
+ var prototype = gen.Entity;
- if (existingProto != null && remapping.TryGetValue(existingProto.ID, out var remapped))
+ if (replaceEntities.TryGetValue(node, out var existingEnt))
{
- prototype = remapped;
+ var existingProto = _entManager.GetComponent<MetaDataComponent>(existingEnt).EntityPrototype;
+ _entManager.DeleteEntity(existingEnt);
+
+ if (existingProto != null && remapping.TryGetValue(existingProto.ID, out var remapped))
+ {
+ prototype = remapped;
+ }
}
- }
- // Tile valid salad so add it.
- _entManager.SpawnAtPosition(prototype, _maps.GridTileToLocal(_gridUid, _grid, node));
+ // Tile valid salad so add it.
+ _entManager.SpawnAtPosition(prototype, _maps.GridTileToLocal(_gridUid, _grid, node));
- groupSize--;
+ groupSize--;
+ }
}
- }
- if (groupSize > 0)
- {
- _sawmill.Warning($"Found remaining group size for ore veins of {gen.Replacement ?? "null"}!");
+ if (groupSize > 0)
+ {
+ _sawmill.Warning($"Found remaining group size for ore veins of {gen.Replacement ?? "null"}!");
+ }
}
}
}
foreach (var layer in layers)
{
+ var dungCount = dungeons.Count;
await RunLayer(dungeons, position, layer, reservedTiles, seed, random);
if (config.ReserveTiles)
{
- // Remove any dungeons passed in so we don't interfere with them
- // This is kinda goofy but okay for now.
- if (existing != null)
- {
- for (var j = 0; j < dungeons.Count; j++)
- {
- var dung = dungeons[j];
-
- if (existing.Contains(dung))
- {
- dungeons.RemoveSwap(j);
- }
- }
- }
-
- foreach (var dungeon in dungeons)
+ // Reserve tiles on any new dungeons.
+ for (var d = dungCount; d < dungeons.Count; d++)
{
+ var dungeon = dungeons[d];
reservedTiles.UnionWith(dungeon.AllTiles);
}
}
npcSystem.WakeNPC(npc.Owner, npc.Comp);
}
+ _sawmill.Info($"Finished generating dungeon {_gen} with seed {_seed}");
return dungeons;
}
await PostGen(mob, dungeons[^1], random);
break;
case EntityTableDunGen entityTable:
- await PostGen(entityTable, dungeons[^1], random);
+ await PostGen(entityTable, dungeons, reservedTiles, random);
break;
case NoiseDistanceDunGen distance:
dungeons.Add(await GenerateNoiseDistanceDunGen(position, distance, reservedTiles, seed, random));
dungeons.Add(await GenerateNoiseDunGen(position, noise, reservedTiles, seed, random));
break;
case OreDunGen ore:
- await PostGen(ore, dungeons[^1], random);
+ await PostGen(ore, dungeons, reservedTiles, random);
break;
case PrefabDunGen prefab:
dungeons.Add(await GeneratePrefabDunGen(position, prefab, reservedTiles, random));