Convenient Z-Levels (#421)

* clear ores and herbals frmo generation

* remake simple zlevels system

* GetMapOffset

* woohoo

* autolink between zlevels

* 5am

* somwthing sommetinh work

* Update CP14StationZLevelsSystem.cs

* fix biomespawner portal deletion

* some docs

* Revert "clear ores and herbals frmo generation"

This reverts commit 658d15a602.
This commit is contained in:
Ed
2024-08-25 19:53:15 +05:00
committed by GitHub
parent ea9c6ee7bf
commit 79515d9303
14 changed files with 264 additions and 71 deletions

View File

@@ -7,6 +7,7 @@
using Content.Server._CP14.BiomeSpawner.EntitySystems;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Whitelist;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.BiomeSpawner.Components;
@@ -19,4 +20,10 @@ public sealed partial class CP14BiomeSpawnerComponent : Component
{
[DataField]
public ProtoId<BiomeTemplatePrototype> Biome = "Grasslands";
/// <summary>
/// entities that we don't remove.
/// </summary>
[DataField(required: true)]
public EntityWhitelist DeleteBlacklist = new();
}

View File

@@ -10,6 +10,7 @@ using Content.Server._CP14.BiomeSpawner.Components;
using Content.Server._CP14.RoundSeed;
using Content.Server.Decals;
using Content.Server.Parallax;
using Content.Shared.Whitelist;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
@@ -26,6 +27,7 @@ public sealed class CP14BiomeSpawnerSystem : EntitySystem
[Dependency] private readonly DecalSystem _decals = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly CP14RoundSeedSystem _roundSeed = default!;
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
public override void Initialize()
{
@@ -79,11 +81,12 @@ public sealed class CP14BiomeSpawnerSystem : EntitySystem
}
// Remove entities
var oldEntities = _lookup.GetEntitiesInRange(spawnerTransform.Coordinates, 0.48f);
var oldEntities = _lookup.GetEntitiesInRange(spawnerTransform.Coordinates, 0.48f, LookupFlags.Uncontained);
// TODO: Replace this shit with GetEntitiesInBox2
foreach (var entToRemove in oldEntities.Concat(new[] { ent.Owner })) // Do not remove self
{
QueueDel(entToRemove);
if (!_whitelist.IsValid(ent.Comp.DeleteBlacklist, entToRemove))
QueueDel(entToRemove);
}
if (_biome.TryGetEntity(vec, biome.Layers, tile.Value, seed, map, out var entityProto))

View File

@@ -1,16 +0,0 @@
using Robust.Shared.Utility;
namespace Content.Server._CP14.StationDungeonMap;
/// <summary>
/// Loads additional maps from the list at the start of the round.
/// </summary>
[RegisterComponent, Access(typeof(CP14StationAdditionalMapSystem))]
public sealed partial class CP14StationAdditionalMapComponent : Component
{
/// <summary>
/// A map paths to load on a new map.
/// </summary>
[DataField]
public List<ResPath> MapPaths = new();
}

View File

@@ -1,46 +0,0 @@
using Content.Server.Parallax;
using Content.Server.Station.Components;
using Content.Server.Station.Events;
using Content.Server.Station.Systems;
using Content.Shared.Teleportation.Systems;
using Robust.Server.GameObjects;
using Robust.Server.Maps;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.StationDungeonMap;
public sealed partial class CP14StationAdditionalMapSystem : EntitySystem
{
[Dependency] private readonly BiomeSystem _biome = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14StationAdditionalMapComponent, StationPostInitEvent>(OnStationPostInit);
}
private void OnStationPostInit(Entity<CP14StationAdditionalMapComponent> addMap, ref StationPostInitEvent args)
{
if (!TryComp(addMap, out StationDataComponent? dataComp))
return;
foreach (var path in addMap.Comp.MapPaths)
{
var mapUid = _map.CreateMap(out var mapId);
Log.Info($"Created map {mapId} for StationAdditionalMap system");
var options = new MapLoadOptions { LoadMap = true };
if (!_mapLoader.TryLoad(mapId, path.ToString(), out var roots, options))
{
Log.Error($"Failed to load map from {path}!");
Del(mapUid);
return;
}
}
}
}

View File

@@ -0,0 +1,28 @@
using Content.Server._CP14.StationDungeonMap.EntitySystems;
using Robust.Shared.Map;
using Robust.Shared.Utility;
namespace Content.Server._CP14.StationDungeonMap.Components;
/// <summary>
/// Initializes the z-level system by creating a series of linked maps
/// </summary>
[RegisterComponent, Access(typeof(CP14StationZLevelsSystem))]
public sealed partial class CP14StationZLevelsComponent : Component
{
[DataField(required: true)]
public int DefaultMapLevel = 0;
[DataField(required: true)]
public Dictionary<int, CP14ZLevelEntry> Levels = new();
public bool Initialized = false;
public Dictionary<MapId, int> LevelEntities = new();
}
[DataRecord, Serializable]
public sealed class CP14ZLevelEntry
{
public ResPath? Path { get; set; } = null;
}

View File

@@ -0,0 +1,23 @@
using Content.Server._CP14.StationDungeonMap.EntitySystems;
using Robust.Shared.Prototypes;
namespace Content.Server._CP14.StationDungeonMap.Components;
/// <summary>
/// automatically creates a linked portal at a different relative z-level, and then the component is removed
/// </summary>
[RegisterComponent, Access(typeof(CP14StationZLevelsSystem))]
public sealed partial class CP14ZLevelAutoPortalComponent : Component
{
/// <summary>
/// relative neighboring layer. Ideally, -1 is the neighboring bottom layer, +1 is the neighboring top layer
/// </summary>
[DataField(required: true)]
public int ZLevelOffset = 0;
/// <summary>
/// prototype of the portal being created on the other side
/// </summary>
[DataField(required: true)]
public EntProtoId OtherSideProto = default!;
}

View File

@@ -0,0 +1,147 @@
using Content.Server._CP14.StationDungeonMap.Components;
using Content.Server.GameTicking.Events;
using Content.Server.Station.Components;
using Content.Server.Station.Events;
using Content.Server.Station.Systems;
using Content.Shared.Maps;
using Content.Shared.Station.Components;
using Content.Shared.Teleportation.Systems;
using Robust.Server.GameObjects;
using Robust.Server.Maps;
using Robust.Shared.Map;
using Robust.Shared.Random;
namespace Content.Server._CP14.StationDungeonMap.EntitySystems;
public sealed partial class CP14StationZLevelsSystem : EntitySystem
{
[Dependency] private readonly MapSystem _map = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly SharedMapSystem _maps = default!;
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CP14ZLevelAutoPortalComponent, MapInitEvent>(OnPortalMapInit);
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
SubscribeLocalEvent<CP14StationZLevelsComponent, StationPostInitEvent>(OnStationPostInit);
}
private void OnRoundStart(RoundStartingEvent ev)
{
var query = EntityQueryEnumerator<CP14ZLevelAutoPortalComponent>();
while (query.MoveNext(out var uid, out var portal))
{
InitPortal((uid, portal));
}
}
private void OnStationPostInit(Entity<CP14StationZLevelsComponent> ent, ref StationPostInitEvent args)
{
if (ent.Comp.Initialized)
return;
if (!TryComp(ent, out StationDataComponent? dataComp))
{
Log.Error($"Failed to init CP14StationZLevelsSystem: no StationData");
return;
}
var defaultMap = _station.GetLargestGrid(dataComp);
if (defaultMap is null)
{
Log.Error($"Failed to init CP14StationZLevelsSystem: defaultMap is null");
return;
}
ent.Comp.LevelEntities.Add(Transform(defaultMap.Value).MapID, ent.Comp.DefaultMapLevel);
ent.Comp.Initialized = true;
foreach (var (map, level) in ent.Comp.Levels)
{
if (ent.Comp.LevelEntities.ContainsValue(map))
{
Log.Error($"Key duplication for CP14StationZLevelsSystem at level {map}!");
continue;
}
var path = level.Path.ToString();
if (path is null)
{
Log.Error($"path {path} for CP14StationZLevelsSystem at level {map} don't exist!");
continue;
}
var mapUid = _map.CreateMap(out var mapId);
var member = EnsureComp<StationMemberComponent>(mapUid);
member.Station = ent;
Log.Info($"Created map {mapId} for CP14StationZLevelsSystem at level {map}");
var options = new MapLoadOptions { LoadMap = true };
if (!_mapLoader.TryLoad(mapId, path, out var grids, options))
{
Log.Error($"Failed to load map for CP14StationZLevelsSystem at level {map}!");
Del(mapUid);
continue;
}
ent.Comp.LevelEntities.Add(mapId, map);
}
}
private void OnPortalMapInit(Entity<CP14ZLevelAutoPortalComponent> autoPortal, ref MapInitEvent args)
{
InitPortal(autoPortal);
}
private void InitPortal(Entity<CP14ZLevelAutoPortalComponent> autoPortal)
{
var mapId = Transform(autoPortal).MapUid;
if (mapId is null)
return;
var offsetMap = GetMapOffset(mapId.Value, autoPortal.Comp.ZLevelOffset);
if (offsetMap is null)
return;
var currentWorldPos = _transform.GetWorldPosition(autoPortal);
var targetMapPos = new MapCoordinates(currentWorldPos, offsetMap.Value);
var otherSidePortal = Spawn(autoPortal.Comp.OtherSideProto, targetMapPos);
if (_linkedEntity.TryLink(autoPortal, otherSidePortal, true))
RemComp<CP14ZLevelAutoPortalComponent>(autoPortal);
}
public MapId? GetMapOffset(EntityUid mapUid, int offset)
{
var query = EntityQueryEnumerator<CP14StationZLevelsComponent, StationDataComponent>();
while (query.MoveNext(out var uid, out var zLevel, out _))
{
if (!zLevel.LevelEntities.TryGetValue(Transform(mapUid).MapID, out var currentLevel))
continue;
var targetLevel = currentLevel + offset;
if (!zLevel.LevelEntities.ContainsValue(targetLevel))
continue;
foreach (var (key, value) in zLevel.LevelEntities)
{
if (value == targetLevel && _map.MapExists(key))
return key;
}
}
return null;
}
}

View File

@@ -25,7 +25,6 @@ entities:
name: Map Entity
- type: Transform
- type: Map
mapPaused: True
- type: PhysicsMap
- type: GridTree
- type: MovedGrids

View File

@@ -14,6 +14,11 @@
drawdepth: BelowFloor
sprite: _CP14/Markers/biome.rsi
- type: CP14BiomeSpawner
deleteBlacklist:
components:
- Portal
- MindContainer
- CP14WorldBounding
- type: PlacementReplacement
key: CP14BiomeSpawner

View File

@@ -1,6 +1,7 @@
- type: entity
id: CP14DungeonEntrance
name: dungeon entrance
noSpawn: true
description: The dark depths of the underworld are calling you.
placement:
mode: SnapgridCenter
@@ -31,12 +32,12 @@
- type: Portal
canTeleportToOtherMaps: true
randomTeleport: false
- type: CP14AutoLink
- type: entity
parent: CP14DungeonEntrance
id: CP14DungeonExit
name: dungeon exit
noSpawn: true
description: A way out of the dark underworld into the overworld.
components:
- type: Sprite
@@ -50,4 +51,19 @@
radius: 3
energy: 1
netsync: false
- type: CP14AutoLink
- type: entity
parent: CP14DungeonEntrance
id: CP14DungeonEntranceAutoLink
components:
- type: CP14ZLevelAutoPortal
zLevelOffset: -1 # Go into deep
otherSideProto: CP14DungeonExit
- type: entity
parent: CP14DungeonExit
id: CP14DungeonExitAutoLink
components:
- type: CP14ZLevelAutoPortal
zLevelOffset: 1 # Go onto surface
otherSideProto: CP14DungeonEntrance

View File

@@ -24,9 +24,11 @@
AlchemyTest:
stationProto: StandardStationArena
components:
- type: CP14StationAdditionalMap
mapPaths:
- /Maps/_CP14/alchemy_test_layer2.yml
- type: CP14StationZLevels
defaultMapLevel: 0
levels:
1:
path: /Maps/_CP14/alchemy_test_layer2.yml
- type: StationNameSetup
mapNameTemplate: "Alchemy test"
- type: StationJobs
@@ -78,4 +80,11 @@
CP14GuardCommander: [1, 1]
CP14HouseKeeper: [1, 1]
- type: CP14StationExpeditionTarget
shuttlePath: /Maps/_CP14/Shuttles/test-ship.yml
shuttlePath: /Maps/_CP14/Shuttles/test-ship.yml
- type: CP14StationZLevels
defaultMapLevel: 0
levels:
-1:
path: /Maps/_CP14/alchemy_test_layer2.yml
-2:
path: /Maps/_CP14/battle_royale.yml

View File

@@ -27,3 +27,8 @@
- type: StationJobs
availableJobs:
CP14Adventurer: [ -1, -1 ]
- type: CP14StationZLevels
defaultMapLevel: 0
levels:
-1:
path: /Maps/_CP14/alchemy_test_layer2.yml

View File

@@ -0,0 +1,9 @@
- type: biomeMarkerLayer
id: CP14OreGold
entityMask:
CP14WallStone: CP14PlantPumpkinDeath
maxCount: 30
minGroupSize: 10
maxGroupSize: 15
radius: 4

View File

@@ -37,6 +37,10 @@ CP14WallStoneSilverOre: CP14WallStoneGoldOre
CP14PloughedGround: CP14SeedbedWooden
CP14SeedbedDefault: CP14SeedbedWooden
# 2024-08-24
CP14DungeonEntrance: CP14DungeonEntranceAutoLink
CP14DungeonExit: CP14DungeonExitAutoLink
# <---> CrystallPunk migration zone end